From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/Devices/Graphics/.scm-settings | 88 + src/VBox/Devices/Graphics/BIOS/BUGS | 3 + src/VBox/Devices/Graphics/BIOS/COPYING | 504 + src/VBox/Devices/Graphics/BIOS/ChangeLog | 1212 ++ src/VBox/Devices/Graphics/BIOS/Makefile.kmk | 201 + src/VBox/Devices/Graphics/BIOS/README | 214 + .../Graphics/BIOS/VBoxVgaBiosAlternative286.asm | 9250 +++++++++ .../Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum | 1 + .../Graphics/BIOS/VBoxVgaBiosAlternative386.asm | 8704 +++++++++ .../Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum | 1 + .../Graphics/BIOS/VBoxVgaBiosAlternative8086.asm | 9408 ++++++++++ .../BIOS/VBoxVgaBiosAlternative8086.md5sum | 1 + src/VBox/Devices/Graphics/BIOS/inlines.h | 180 + src/VBox/Devices/Graphics/BIOS/makefile | 48 + src/VBox/Devices/Graphics/BIOS/ose_logo.bmp | Bin 0 -> 630 bytes src/VBox/Devices/Graphics/BIOS/tests/testbios.c | 353 + src/VBox/Devices/Graphics/BIOS/vbe.c | 816 + src/VBox/Devices/Graphics/BIOS/vbe.h | 117 + src/VBox/Devices/Graphics/BIOS/vbe_display_api.txt | 237 + src/VBox/Devices/Graphics/BIOS/vberom.asm | 951 + src/VBox/Devices/Graphics/BIOS/vbetables-gen.c | 245 + src/VBox/Devices/Graphics/BIOS/vgabios.c | 2805 +++ src/VBox/Devices/Graphics/BIOS/vgabios.h | 68 + src/VBox/Devices/Graphics/BIOS/vgadefs.h | 78 + src/VBox/Devices/Graphics/BIOS/vgadefs.inc | 58 + src/VBox/Devices/Graphics/BIOS/vgafonts.h | 878 + src/VBox/Devices/Graphics/BIOS/vgarom.asm | 1102 ++ src/VBox/Devices/Graphics/BIOS/vgatables.h | 625 + src/VBox/Devices/Graphics/DevVGA-SVGA-cmd.cpp | 7650 ++++++++ src/VBox/Devices/Graphics/DevVGA-SVGA-internal.h | 306 + src/VBox/Devices/Graphics/DevVGA-SVGA.cpp | 7149 +++++++ src/VBox/Devices/Graphics/DevVGA-SVGA.h | 674 + src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.h | 67 + src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m | 947 + .../Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp | 10277 ++++++++++ .../Graphics/DevVGA-SVGA3d-dx-savedstate.cpp | 464 + .../Devices/Graphics/DevVGA-SVGA3d-dx-shader.cpp | 3056 +++ .../Devices/Graphics/DevVGA-SVGA3d-dx-shader.h | 88 + src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx.cpp | 3256 ++++ src/VBox/Devices/Graphics/DevVGA-SVGA3d-glHlp.cpp | 768 + src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.cpp | 428 + src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.h | 443 + src/VBox/Devices/Graphics/DevVGA-SVGA3d-hlp.cpp | 466 + src/VBox/Devices/Graphics/DevVGA-SVGA3d-info.cpp | 1935 ++ src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h | 1446 ++ src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp | 7967 ++++++++ .../Devices/Graphics/DevVGA-SVGA3d-savedstate.cpp | 1290 ++ src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp | 1740 ++ .../Devices/Graphics/DevVGA-SVGA3d-win-d3d9.cpp | 1247 ++ src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp | 6453 +++++++ src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp | 1913 ++ src/VBox/Devices/Graphics/DevVGA-SVGA3d.h | 686 + src/VBox/Devices/Graphics/DevVGA.cpp | 7504 ++++++++ src/VBox/Devices/Graphics/DevVGA.h | 796 + src/VBox/Devices/Graphics/DevVGAModes.h | 45 + src/VBox/Devices/Graphics/DevVGASavedState.h | 89 + src/VBox/Devices/Graphics/DevVGATmpl.h | 582 + src/VBox/Devices/Graphics/DevVGA_VBVA.cpp | 2884 +++ src/VBox/Devices/Graphics/DevVGA_VDMA.cpp | 373 + src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp | 1702 ++ src/VBox/Devices/Graphics/HGSMI/HGSMIHost.h | 122 + src/VBox/Devices/Graphics/HGSMI/Makefile.kup | 0 src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.cpp | 61 + src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.h | 40 + src/VBox/Devices/Graphics/Makefile.kup | 0 src/VBox/Devices/Graphics/VBoxSVGA3D.def | 49 + src/VBox/Devices/Graphics/VBoxSVGA3DObjC.def | 39 + src/VBox/Devices/Graphics/shaderlib/Makefile.kup | 0 src/VBox/Devices/Graphics/shaderlib/directx.c | 2672 +++ src/VBox/Devices/Graphics/shaderlib/glsl_shader.c | 5608 ++++++ .../Graphics/shaderlib/libWineStub/Makefile.kup | 0 .../Devices/Graphics/shaderlib/libWineStub/debug.c | 534 + .../shaderlib/libWineStub/include/config.h | 1282 ++ .../Graphics/shaderlib/libWineStub/include/d3d8.h | 1154 ++ .../Graphics/shaderlib/libWineStub/include/d3d9.h | 2047 ++ .../shaderlib/libWineStub/include/wine/debug.h | 381 + .../shaderlib/libWineStub/include/wine/guiddef.h | 131 + .../shaderlib/libWineStub/include/wine/initguid.h | 35 + .../shaderlib/libWineStub/include/wine/list.h | 246 + .../shaderlib/libWineStub/include/wine/port.h | 491 + .../shaderlib/libWineStub/include/wine/rbtree.h | 357 + .../shaderlib/libWineStub/include/wine/unicode.h | 355 + .../shaderlib/libWineStub/include/wine/wined3d.h | 9725 ++++++++++ src/VBox/Devices/Graphics/shaderlib/shader.c | 2523 +++ src/VBox/Devices/Graphics/shaderlib/shader_sm1.c | 707 + src/VBox/Devices/Graphics/shaderlib/shader_sm4.c | 444 + src/VBox/Devices/Graphics/shaderlib/shaderapi.c | 804 + src/VBox/Devices/Graphics/shaderlib/shaderlib.h | 110 + src/VBox/Devices/Graphics/shaderlib/stateblock.c | 99 + src/VBox/Devices/Graphics/shaderlib/utils.c | 158 + src/VBox/Devices/Graphics/shaderlib/vboxext.h | 177 + .../Graphics/shaderlib/wine/include/Makefile.in | 669 + .../Graphics/shaderlib/wine/include/accctrl.h | 460 + .../Graphics/shaderlib/wine/include/access.idl | 88 + .../Graphics/shaderlib/wine/include/aclapi.h | 92 + .../Graphics/shaderlib/wine/include/aclui.h | 247 + .../Graphics/shaderlib/wine/include/activaut.idl | 38 + .../Graphics/shaderlib/wine/include/activdbg.idl | 590 + .../Graphics/shaderlib/wine/include/activscp.idl | 558 + .../Graphics/shaderlib/wine/include/adshlp.h | 45 + .../Graphics/shaderlib/wine/include/advpub.h | 290 + .../Graphics/shaderlib/wine/include/af_irda.h | 110 + .../Graphics/shaderlib/wine/include/amaudio.h | 56 + .../Graphics/shaderlib/wine/include/amstream.idl | 327 + .../Graphics/shaderlib/wine/include/amvideo.idl | 250 + .../Graphics/shaderlib/wine/include/appcompatapi.h | 41 + .../Graphics/shaderlib/wine/include/appmgmt.h | 63 + .../Graphics/shaderlib/wine/include/asptlb.idl | 142 + .../Graphics/shaderlib/wine/include/asynot.idl | 68 + .../Graphics/shaderlib/wine/include/asysta.idl | 60 + .../Graphics/shaderlib/wine/include/atlbase.h | 275 + .../Graphics/shaderlib/wine/include/atliface.idl | 96 + .../Graphics/shaderlib/wine/include/atlwin.h | 62 + .../Graphics/shaderlib/wine/include/audevcod.h | 53 + .../shaderlib/wine/include/audioclient.idl | 336 + .../shaderlib/wine/include/audiopolicy.idl | 249 + .../shaderlib/wine/include/audiosessiontypes.h | 57 + .../Graphics/shaderlib/wine/include/austream.idl | 117 + .../Graphics/shaderlib/wine/include/aviriff.h | 333 + .../Devices/Graphics/shaderlib/wine/include/avrt.h | 83 + .../Graphics/shaderlib/wine/include/axcore.idl | 666 + .../Graphics/shaderlib/wine/include/axextend.idl | 1074 ++ .../Graphics/shaderlib/wine/include/basetsd.h | 333 + .../Graphics/shaderlib/wine/include/basetyps.h | 92 + .../Graphics/shaderlib/wine/include/bcrypt.h | 59 + .../Graphics/shaderlib/wine/include/binres.idl | 58 + .../Graphics/shaderlib/wine/include/bits.idl | 426 + .../Graphics/shaderlib/wine/include/bits1_5.idl | 97 + .../Graphics/shaderlib/wine/include/bitsmsg.h | 90 + .../Graphics/shaderlib/wine/include/cderr.h | 80 + .../Graphics/shaderlib/wine/include/cfgmgr32.h | 214 + .../Graphics/shaderlib/wine/include/cguid.h | 118 + .../Graphics/shaderlib/wine/include/chprst.idl | 52 + .../Graphics/shaderlib/wine/include/cierror.h | 53 + .../Graphics/shaderlib/wine/include/clusapi.h | 66 + .../Graphics/shaderlib/wine/include/cmdbas.idl | 71 + .../Graphics/shaderlib/wine/include/cmdtxt.idl | 53 + .../Graphics/shaderlib/wine/include/comcat.idl | 241 + .../Graphics/shaderlib/wine/include/commctrl.h | 5183 ++++++ .../Graphics/shaderlib/wine/include/commctrl.rh | 220 + .../Graphics/shaderlib/wine/include/commdlg.h | 851 + .../shaderlib/wine/include/commoncontrols.idl | 223 + .../Graphics/shaderlib/wine/include/compobj.h | 34 + .../Graphics/shaderlib/wine/include/config.h | 1273 ++ .../Graphics/shaderlib/wine/include/config.h.in | 1412 ++ .../Graphics/shaderlib/wine/include/config_linux.h | 1275 ++ .../Graphics/shaderlib/wine/include/control.idl | 257 + .../Graphics/shaderlib/wine/include/cor.idl | 117 + .../Graphics/shaderlib/wine/include/cordebug.idl | 1050 ++ .../Graphics/shaderlib/wine/include/corerror.h | 139 + .../Graphics/shaderlib/wine/include/corhdr.h | 139 + .../Devices/Graphics/shaderlib/wine/include/cpl.h | 98 + .../Graphics/shaderlib/wine/include/crtrow.idl | 60 + .../Graphics/shaderlib/wine/include/cryptdlg.h | 323 + .../Graphics/shaderlib/wine/include/cryptuiapi.h | 447 + .../Graphics/shaderlib/wine/include/ctfutb.idl | 82 + .../Graphics/shaderlib/wine/include/ctxtcall.idl | 58 + .../Graphics/shaderlib/wine/include/custcntl.h | 137 + .../Graphics/shaderlib/wine/include/cvconst.h | 719 + .../Devices/Graphics/shaderlib/wine/include/d3d.h | 1577 ++ .../Graphics/shaderlib/wine/include/d3d10.idl | 1611 ++ .../Graphics/shaderlib/wine/include/d3d10_1.idl | 135 + .../shaderlib/wine/include/d3d10_1shader.h | 61 + .../Graphics/shaderlib/wine/include/d3d10effect.h | 866 + .../Graphics/shaderlib/wine/include/d3d10misc.h | 57 + .../Graphics/shaderlib/wine/include/d3d10shader.h | 242 + .../Graphics/shaderlib/wine/include/d3d11.idl | 2010 ++ .../shaderlib/wine/include/d3d11sdklayers.idl | 1268 ++ .../Graphics/shaderlib/wine/include/d3d11shader.h | 217 + .../Devices/Graphics/shaderlib/wine/include/d3d8.h | 1162 ++ .../Graphics/shaderlib/wine/include/d3d8caps.h | 295 + .../Graphics/shaderlib/wine/include/d3d8types.h | 1222 ++ .../Devices/Graphics/shaderlib/wine/include/d3d9.h | 2134 +++ .../Graphics/shaderlib/wine/include/d3d9caps.h | 404 + .../Graphics/shaderlib/wine/include/d3d9types.h | 1595 ++ .../Graphics/shaderlib/wine/include/d3dcaps.h | 442 + .../Graphics/shaderlib/wine/include/d3dcommon.idl | 648 + .../Graphics/shaderlib/wine/include/d3dcompiler.h | 132 + .../Graphics/shaderlib/wine/include/d3dhal.h | 529 + .../Graphics/shaderlib/wine/include/d3drm.h | 533 + .../Graphics/shaderlib/wine/include/d3drmdef.h | 475 + .../Graphics/shaderlib/wine/include/d3drmobj.h | 4711 +++++ .../Graphics/shaderlib/wine/include/d3drmwin.h | 112 + .../Graphics/shaderlib/wine/include/d3dtypes.h | 1368 ++ .../Graphics/shaderlib/wine/include/d3dvec.inl | 152 + .../Graphics/shaderlib/wine/include/d3dx9.h | 65 + .../Graphics/shaderlib/wine/include/d3dx9anim.h | 417 + .../Graphics/shaderlib/wine/include/d3dx9core.h | 514 + .../Graphics/shaderlib/wine/include/d3dx9effect.h | 441 + .../Graphics/shaderlib/wine/include/d3dx9math.h | 483 + .../Graphics/shaderlib/wine/include/d3dx9math.inl | 1307 ++ .../Graphics/shaderlib/wine/include/d3dx9mesh.h | 1066 ++ .../Graphics/shaderlib/wine/include/d3dx9shader.h | 381 + .../Graphics/shaderlib/wine/include/d3dx9shape.h | 55 + .../Graphics/shaderlib/wine/include/d3dx9tex.h | 358 + .../Graphics/shaderlib/wine/include/d3dx9xof.h | 195 + .../Graphics/shaderlib/wine/include/dbccmd.idl | 45 + .../Graphics/shaderlib/wine/include/dbcses.idl | 45 + .../Graphics/shaderlib/wine/include/dbdsad.idl | 84 + .../Graphics/shaderlib/wine/include/dbghelp.h | 1543 ++ .../Graphics/shaderlib/wine/include/dbinit.idl | 38 + .../Graphics/shaderlib/wine/include/dbprop.idl | 75 + .../Graphics/shaderlib/wine/include/dbs.idl | 740 + .../Devices/Graphics/shaderlib/wine/include/dbt.h | 160 + .../Graphics/shaderlib/wine/include/dciddi.h | 92 + .../Graphics/shaderlib/wine/include/dciman.h | 47 + .../Graphics/shaderlib/wine/include/dcommon.h | 38 + .../Devices/Graphics/shaderlib/wine/include/dde.h | 88 + .../Devices/Graphics/shaderlib/wine/include/dde.rh | 41 + .../Graphics/shaderlib/wine/include/ddeml.h | 392 + .../Graphics/shaderlib/wine/include/ddk/compstui.h | 80 + .../Graphics/shaderlib/wine/include/ddk/hidsdi.h | 44 + .../Graphics/shaderlib/wine/include/ddk/imm.h | 182 + .../Graphics/shaderlib/wine/include/ddk/mountmgr.h | 151 + .../Graphics/shaderlib/wine/include/ddk/ntddcdvd.h | 207 + .../Graphics/shaderlib/wine/include/ddk/ntddk.h | 155 + .../Graphics/shaderlib/wine/include/ddk/ntddser.h | 407 + .../Graphics/shaderlib/wine/include/ddk/ntddtape.h | 59 + .../Graphics/shaderlib/wine/include/ddk/usb.h | 415 + .../Graphics/shaderlib/wine/include/ddk/usb100.h | 127 + .../Graphics/shaderlib/wine/include/ddk/usb200.h | 33 + .../Graphics/shaderlib/wine/include/ddk/usbdlib.h | 46 + .../Graphics/shaderlib/wine/include/ddk/usbioctl.h | 34 + .../Graphics/shaderlib/wine/include/ddk/usbiodef.h | 35 + .../Graphics/shaderlib/wine/include/ddk/wdm.h | 1361 ++ .../Graphics/shaderlib/wine/include/ddk/winddiui.h | 59 + .../Graphics/shaderlib/wine/include/ddk/winsplp.h | 436 + .../Graphics/shaderlib/wine/include/ddraw.h | 2740 +++ .../Graphics/shaderlib/wine/include/ddrawgdi.h | 45 + .../Graphics/shaderlib/wine/include/ddrawi.h | 1079 ++ .../Graphics/shaderlib/wine/include/ddstream.idl | 97 + .../shaderlib/wine/include/delayloadhandler.h | 64 + .../Graphics/shaderlib/wine/include/devenum.idl | 46 + .../Graphics/shaderlib/wine/include/devguid.h | 115 + .../shaderlib/wine/include/devicetopology.idl | 745 + .../Graphics/shaderlib/wine/include/devpkey.h | 71 + .../Graphics/shaderlib/wine/include/devpropdef.h | 114 + .../Graphics/shaderlib/wine/include/difxapi.h | 79 + .../Graphics/shaderlib/wine/include/digitalv.h | 875 + .../Graphics/shaderlib/wine/include/dimm.idl | 599 + .../Graphics/shaderlib/wine/include/dinput.h | 2511 +++ .../Graphics/shaderlib/wine/include/dinputd.h | 254 + .../Graphics/shaderlib/wine/include/dispdib.h | 53 + .../Graphics/shaderlib/wine/include/dispex.idl | 214 + .../Devices/Graphics/shaderlib/wine/include/dlgs.h | 233 + .../Devices/Graphics/shaderlib/wine/include/dls1.h | 212 + .../Devices/Graphics/shaderlib/wine/include/dls2.h | 116 + .../Graphics/shaderlib/wine/include/dmdls.h | 219 + .../Graphics/shaderlib/wine/include/dmerror.h | 173 + .../Graphics/shaderlib/wine/include/dmksctrl.h | 119 + .../Devices/Graphics/shaderlib/wine/include/dmo.h | 43 + .../Graphics/shaderlib/wine/include/dmoreg.h | 87 + .../Graphics/shaderlib/wine/include/dmort.h | 38 + .../Graphics/shaderlib/wine/include/dmplugin.h | 308 + .../Graphics/shaderlib/wine/include/dmusbuff.h | 61 + .../Graphics/shaderlib/wine/include/dmusicc.h | 775 + .../Graphics/shaderlib/wine/include/dmusicf.h | 918 + .../Graphics/shaderlib/wine/include/dmusici.h | 1743 ++ .../Graphics/shaderlib/wine/include/dmusics.h | 246 + .../Graphics/shaderlib/wine/include/docobj.idl | 420 + .../shaderlib/wine/include/docobjectservice.idl | 76 + .../shaderlib/wine/include/downloadmgr.idl | 52 + .../Graphics/shaderlib/wine/include/dpaddr.h | 367 + .../Graphics/shaderlib/wine/include/dplay.h | 1282 ++ .../Graphics/shaderlib/wine/include/dplay8.h | 1010 + .../Graphics/shaderlib/wine/include/dplobby.h | 518 + .../Graphics/shaderlib/wine/include/dplobby8.h | 268 + .../Graphics/shaderlib/wine/include/dpnathlp.h | 201 + .../Graphics/shaderlib/wine/include/dsconf.h | 176 + .../Graphics/shaderlib/wine/include/dsgetdc.h | 112 + .../Graphics/shaderlib/wine/include/dshow.h | 69 + .../Graphics/shaderlib/wine/include/dsound.h | 1211 ++ .../Graphics/shaderlib/wine/include/dsrole.h | 101 + .../Graphics/shaderlib/wine/include/dvdmedia.h | 63 + .../Graphics/shaderlib/wine/include/dwmapi.h | 137 + .../Graphics/shaderlib/wine/include/dwrite.idl | 1420 ++ .../Graphics/shaderlib/wine/include/dwrite_1.idl | 833 + .../Graphics/shaderlib/wine/include/dxdiag.h | 164 + .../Graphics/shaderlib/wine/include/dxerr8.h | 61 + .../Graphics/shaderlib/wine/include/dxerr9.h | 61 + .../Graphics/shaderlib/wine/include/dxfile.h | 308 + .../Graphics/shaderlib/wine/include/dxgi.idl | 465 + .../Graphics/shaderlib/wine/include/dxgiformat.h | 153 + .../Graphics/shaderlib/wine/include/dxgitype.h | 93 + .../Graphics/shaderlib/wine/include/dyngraph.idl | 159 + .../shaderlib/wine/include/endpointvolume.idl | 157 + .../Graphics/shaderlib/wine/include/errorrep.h | 52 + .../Graphics/shaderlib/wine/include/errors.h | 54 + .../Graphics/shaderlib/wine/include/errrec.idl | 87 + .../Graphics/shaderlib/wine/include/evcode.h | 103 + .../Graphics/shaderlib/wine/include/evntprov.h | 80 + .../Graphics/shaderlib/wine/include/evntrace.h | 251 + .../Graphics/shaderlib/wine/include/excpt.h | 60 + .../Graphics/shaderlib/wine/include/exdisp.idl | 1055 ++ .../Graphics/shaderlib/wine/include/exdispid.h | 181 + .../Devices/Graphics/shaderlib/wine/include/fci.h | 272 + .../Devices/Graphics/shaderlib/wine/include/fdi.h | 310 + .../Graphics/shaderlib/wine/include/fileapi.h | 50 + .../Graphics/shaderlib/wine/include/fltdefs.h | 142 + .../Graphics/shaderlib/wine/include/fusion.idl | 365 + .../Graphics/shaderlib/wine/include/gameux.idl | 210 + .../Graphics/shaderlib/wine/include/gdiplus.h | 74 + .../Graphics/shaderlib/wine/include/gdipluscolor.h | 60 + .../shaderlib/wine/include/gdipluscolormatrix.h | 69 + .../Graphics/shaderlib/wine/include/gdiplusenums.h | 767 + .../Graphics/shaderlib/wine/include/gdiplusflat.h | 753 + .../shaderlib/wine/include/gdiplusgpstubs.h | 108 + .../shaderlib/wine/include/gdiplusimaging.h | 462 + .../Graphics/shaderlib/wine/include/gdiplusinit.h | 78 + .../Graphics/shaderlib/wine/include/gdiplusmem.h | 44 + .../shaderlib/wine/include/gdiplusmetaheader.h | 176 + .../shaderlib/wine/include/gdipluspixelformats.h | 114 + .../Graphics/shaderlib/wine/include/gdiplustypes.h | 285 + .../Graphics/shaderlib/wine/include/guiddef.h | 169 + .../Graphics/shaderlib/wine/include/hlguids.h | 40 + .../Graphics/shaderlib/wine/include/hlink.idl | 450 + .../Graphics/shaderlib/wine/include/htiface.idl | 137 + .../Graphics/shaderlib/wine/include/htiframe.idl | 143 + .../Graphics/shaderlib/wine/include/htmlhelp.h | 461 + .../Devices/Graphics/shaderlib/wine/include/http.h | 75 + .../shaderlib/wine/include/httprequest.idl | 201 + .../shaderlib/wine/include/httprequestid.h | 51 + .../shaderlib/wine/include/i_cryptasn1tls.h | 50 + .../Graphics/shaderlib/wine/include/iads.idl | 788 + .../Graphics/shaderlib/wine/include/icftypes.idl | 78 + .../Devices/Graphics/shaderlib/wine/include/icm.h | 445 + .../Graphics/shaderlib/wine/include/icmpapi.h | 62 + .../Graphics/shaderlib/wine/include/idispids.h | 42 + .../Graphics/shaderlib/wine/include/iextag.idl | 129 + .../Graphics/shaderlib/wine/include/ifdef.h | 239 + .../Graphics/shaderlib/wine/include/ifmib.h | 80 + .../Graphics/shaderlib/wine/include/imagehlp.h | 1409 ++ .../Devices/Graphics/shaderlib/wine/include/imm.h | 587 + .../Graphics/shaderlib/wine/include/imnact.idl | 308 + .../Graphics/shaderlib/wine/include/imnxport.idl | 1123 ++ .../Graphics/shaderlib/wine/include/in6addr.h | 61 + .../Graphics/shaderlib/wine/include/inaddr.h | 69 + .../Graphics/shaderlib/wine/include/indexsrv.idl | 133 + .../Graphics/shaderlib/wine/include/initguid.h | 35 + .../Graphics/shaderlib/wine/include/inputscope.idl | 93 + .../Graphics/shaderlib/wine/include/intshcut.h | 123 + .../Graphics/shaderlib/wine/include/ipexport.h | 128 + .../Graphics/shaderlib/wine/include/iphlpapi.h | 171 + .../Graphics/shaderlib/wine/include/ipifcons.h | 254 + .../Graphics/shaderlib/wine/include/ipmib.h | 254 + .../Graphics/shaderlib/wine/include/iprtrmib.h | 58 + .../Graphics/shaderlib/wine/include/iptypes.h | 269 + .../Graphics/shaderlib/wine/include/isguids.h | 37 + .../Graphics/shaderlib/wine/include/knownfolders.h | 151 + .../Devices/Graphics/shaderlib/wine/include/ks.h | 75 + .../Graphics/shaderlib/wine/include/ksguid.h | 29 + .../Graphics/shaderlib/wine/include/ksmedia.h | 153 + .../Devices/Graphics/shaderlib/wine/include/lm.h | 55 + .../Graphics/shaderlib/wine/include/lmaccess.h | 487 + .../Graphics/shaderlib/wine/include/lmapibuf.h | 49 + .../Devices/Graphics/shaderlib/wine/include/lmat.h | 44 + .../Graphics/shaderlib/wine/include/lmbrowsr.h | 56 + .../Graphics/shaderlib/wine/include/lmcons.h | 79 + .../Graphics/shaderlib/wine/include/lmerr.h | 327 + .../Graphics/shaderlib/wine/include/lmjoin.h | 52 + .../Graphics/shaderlib/wine/include/lmmsg.h | 61 + .../Graphics/shaderlib/wine/include/lmserver.h | 91 + .../Graphics/shaderlib/wine/include/lmshare.h | 71 + .../Graphics/shaderlib/wine/include/lmstats.h | 107 + .../Graphics/shaderlib/wine/include/lmuse.h | 93 + .../Graphics/shaderlib/wine/include/lmuseflg.h | 35 + .../Graphics/shaderlib/wine/include/lmwksta.h | 102 + .../Graphics/shaderlib/wine/include/loadperf.h | 51 + .../Graphics/shaderlib/wine/include/lzexpand.h | 64 + .../Devices/Graphics/shaderlib/wine/include/mapi.h | 254 + .../Graphics/shaderlib/wine/include/mapicode.h | 123 + .../Graphics/shaderlib/wine/include/mapidefs.h | 1332 ++ .../Graphics/shaderlib/wine/include/mapiform.h | 56 + .../Graphics/shaderlib/wine/include/mapiguid.h | 90 + .../Graphics/shaderlib/wine/include/mapitags.h | 824 + .../Graphics/shaderlib/wine/include/mapiutil.h | 286 + .../Graphics/shaderlib/wine/include/mapival.h | 130 + .../Graphics/shaderlib/wine/include/mapix.h | 196 + .../Graphics/shaderlib/wine/include/mciavi.h | 52 + .../Devices/Graphics/shaderlib/wine/include/mcx.h | 69 + .../Graphics/shaderlib/wine/include/mediaerr.h | 38 + .../Graphics/shaderlib/wine/include/mediaobj.idl | 78 + .../Graphics/shaderlib/wine/include/metahost.idl | 215 + .../Graphics/shaderlib/wine/include/midles.h | 142 + .../Graphics/shaderlib/wine/include/mimeinfo.idl | 45 + .../Graphics/shaderlib/wine/include/mimeole.idl | 1346 ++ .../Graphics/shaderlib/wine/include/minmax.h | 40 + .../Graphics/shaderlib/wine/include/mlang.idl | 766 + .../Graphics/shaderlib/wine/include/mmc.idl | 67 + .../Graphics/shaderlib/wine/include/mmddk.h | 480 + .../shaderlib/wine/include/mmdeviceapi.idl | 259 + .../Graphics/shaderlib/wine/include/mmreg.h | 508 + .../Graphics/shaderlib/wine/include/mmstream.idl | 193 + .../Graphics/shaderlib/wine/include/mmsystem.h | 2531 +++ .../Graphics/shaderlib/wine/include/mprapi.h | 55 + .../Graphics/shaderlib/wine/include/mprerror.h | 74 + .../Graphics/shaderlib/wine/include/msacm.h | 801 + .../Graphics/shaderlib/wine/include/msacmdlg.h | 45 + .../Graphics/shaderlib/wine/include/msacmdrv.h | 168 + .../Graphics/shaderlib/wine/include/mscat.h | 143 + .../Graphics/shaderlib/wine/include/mscoree.idl | 249 + .../Graphics/shaderlib/wine/include/msctf.idl | 1533 ++ .../Graphics/shaderlib/wine/include/msdadc.idl | 101 + .../Graphics/shaderlib/wine/include/msdaguid.h | 36 + .../Graphics/shaderlib/wine/include/msdasc.idl | 147 + .../Graphics/shaderlib/wine/include/mshtmcid.h | 434 + .../Graphics/shaderlib/wine/include/mshtmdid.h | 3105 ++++ .../Graphics/shaderlib/wine/include/mshtmhst.idl | 311 + .../Graphics/shaderlib/wine/include/mshtml.idl | 18564 +++++++++++++++++++ .../Devices/Graphics/shaderlib/wine/include/msi.h | 719 + .../Graphics/shaderlib/wine/include/msidefs.h | 290 + .../Graphics/shaderlib/wine/include/msident.idl | 103 + .../Graphics/shaderlib/wine/include/msinkaut.idl | 1018 + .../Graphics/shaderlib/wine/include/msiquery.h | 335 + .../Graphics/shaderlib/wine/include/mssip.h | 189 + .../Graphics/shaderlib/wine/include/mstask.idl | 402 + .../Graphics/shaderlib/wine/include/mstcpip.h | 78 + .../shaderlib/wine/include/msvcrt/assert.h | 46 + .../Graphics/shaderlib/wine/include/msvcrt/conio.h | 63 + .../shaderlib/wine/include/msvcrt/crtdbg.h | 140 + .../shaderlib/wine/include/msvcrt/crtdefs.h | 248 + .../Graphics/shaderlib/wine/include/msvcrt/ctype.h | 85 + .../shaderlib/wine/include/msvcrt/direct.h | 59 + .../shaderlib/wine/include/msvcrt/dirent.h | 1 + .../Graphics/shaderlib/wine/include/msvcrt/dos.h | 50 + .../Graphics/shaderlib/wine/include/msvcrt/eh.h | 58 + .../Graphics/shaderlib/wine/include/msvcrt/errno.h | 87 + .../Graphics/shaderlib/wine/include/msvcrt/fcntl.h | 50 + .../Graphics/shaderlib/wine/include/msvcrt/float.h | 158 + .../Graphics/shaderlib/wine/include/msvcrt/io.h | 184 + .../shaderlib/wine/include/msvcrt/limits.h | 49 + .../shaderlib/wine/include/msvcrt/locale.h | 90 + .../shaderlib/wine/include/msvcrt/malloc.h | 99 + .../Graphics/shaderlib/wine/include/msvcrt/math.h | 174 + .../shaderlib/wine/include/msvcrt/mbctype.h | 90 + .../shaderlib/wine/include/msvcrt/mbstring.h | 132 + .../shaderlib/wine/include/msvcrt/memory.h | 37 + .../shaderlib/wine/include/msvcrt/process.h | 126 + .../shaderlib/wine/include/msvcrt/search.h | 52 + .../shaderlib/wine/include/msvcrt/setjmp.h | 140 + .../Graphics/shaderlib/wine/include/msvcrt/share.h | 42 + .../shaderlib/wine/include/msvcrt/signal.h | 63 + .../shaderlib/wine/include/msvcrt/stddef.h | 60 + .../Graphics/shaderlib/wine/include/msvcrt/stdio.h | 272 + .../shaderlib/wine/include/msvcrt/stdlib.h | 301 + .../shaderlib/wine/include/msvcrt/string.h | 156 + .../shaderlib/wine/include/msvcrt/sys/locking.h | 42 + .../shaderlib/wine/include/msvcrt/sys/stat.h | 201 + .../shaderlib/wine/include/msvcrt/sys/timeb.h | 86 + .../shaderlib/wine/include/msvcrt/sys/types.h | 82 + .../shaderlib/wine/include/msvcrt/sys/unistd.h | 1 + .../shaderlib/wine/include/msvcrt/sys/utime.h | 88 + .../Graphics/shaderlib/wine/include/msvcrt/time.h | 162 + .../shaderlib/wine/include/msvcrt/unistd.h | 2 + .../Graphics/shaderlib/wine/include/msvcrt/wchar.h | 478 + .../shaderlib/wine/include/msvcrt/wctype.h | 92 + .../Graphics/shaderlib/wine/include/mswsock.h | 197 + .../Graphics/shaderlib/wine/include/msxml.h | 1773 ++ .../Graphics/shaderlib/wine/include/msxml.idl | 366 + .../Graphics/shaderlib/wine/include/msxml2.idl | 3576 ++++ .../Graphics/shaderlib/wine/include/msxml2did.h | 563 + .../Graphics/shaderlib/wine/include/msxml6.idl | 3431 ++++ .../Graphics/shaderlib/wine/include/msxml6did.h | 33 + .../Graphics/shaderlib/wine/include/msxmldid.h | 76 + .../Devices/Graphics/shaderlib/wine/include/nb30.h | 231 + .../Graphics/shaderlib/wine/include/ndrtypes.h | 190 + .../Graphics/shaderlib/wine/include/netcon.idl | 421 + .../Graphics/shaderlib/wine/include/netfw.idl | 479 + .../Graphics/shaderlib/wine/include/nldef.h | 89 + .../Graphics/shaderlib/wine/include/npapi.h | 229 + .../Graphics/shaderlib/wine/include/nspapi.h | 214 + .../Graphics/shaderlib/wine/include/ntddcdrm.h | 194 + .../Graphics/shaderlib/wine/include/ntddndis.h | 181 + .../Graphics/shaderlib/wine/include/ntddscsi.h | 133 + .../Graphics/shaderlib/wine/include/ntddstor.h | 288 + .../Graphics/shaderlib/wine/include/ntdsapi.h | 66 + .../Graphics/shaderlib/wine/include/ntquery.h | 92 + .../Graphics/shaderlib/wine/include/ntsecapi.h | 403 + .../Graphics/shaderlib/wine/include/ntsecpkg.h | 480 + .../Graphics/shaderlib/wine/include/ntstatus.h | 1229 ++ .../Graphics/shaderlib/wine/include/oaidl.h | 5205 ++++++ .../Graphics/shaderlib/wine/include/oaidl.idl | 1651 ++ .../Graphics/shaderlib/wine/include/objbase.h | 511 + .../shaderlib/wine/include/objectarray.idl | 56 + .../Graphics/shaderlib/wine/include/objidl.h | 10438 +++++++++++ .../Graphics/shaderlib/wine/include/objidl.idl | 2531 +++ .../Graphics/shaderlib/wine/include/objsafe.idl | 54 + .../Graphics/shaderlib/wine/include/objsel.h | 169 + .../Graphics/shaderlib/wine/include/ocidl.idl | 1343 ++ .../Graphics/shaderlib/wine/include/ocmm.idl | 83 + .../Graphics/shaderlib/wine/include/odbcinst.h | 141 + .../Devices/Graphics/shaderlib/wine/include/ole2.h | 179 + .../Graphics/shaderlib/wine/include/ole2ver.h | 53 + .../Graphics/shaderlib/wine/include/oleacc.idl | 305 + .../Graphics/shaderlib/wine/include/oleauto.h | 772 + .../Graphics/shaderlib/wine/include/olectl.h | 458 + .../Graphics/shaderlib/wine/include/oledb.idl | 85 + .../Graphics/shaderlib/wine/include/oledberr.h | 83 + .../Graphics/shaderlib/wine/include/oledlg.h | 988 + .../Graphics/shaderlib/wine/include/oleidl.h | 3645 ++++ .../Graphics/shaderlib/wine/include/oleidl.idl | 967 + .../Graphics/shaderlib/wine/include/opnrst.idl | 56 + .../Graphics/shaderlib/wine/include/optary.idl | 74 + .../Graphics/shaderlib/wine/include/patchapi.h | 61 + .../Devices/Graphics/shaderlib/wine/include/pdh.h | 255 + .../Graphics/shaderlib/wine/include/pdhmsg.h | 120 + .../Graphics/shaderlib/wine/include/perhist.idl | 47 + .../Graphics/shaderlib/wine/include/pktdef.h | 257 + .../Graphics/shaderlib/wine/include/poppack.h | 272 + .../Graphics/shaderlib/wine/include/powrprof.h | 153 + .../Graphics/shaderlib/wine/include/profinfo.h | 56 + .../Graphics/shaderlib/wine/include/propidl.h | 1027 + .../Graphics/shaderlib/wine/include/propidl.idl | 464 + .../Graphics/shaderlib/wine/include/propkey.h | 55 + .../Graphics/shaderlib/wine/include/propkeydef.h | 82 + .../Graphics/shaderlib/wine/include/propsys.idl | 832 + .../Graphics/shaderlib/wine/include/propvarutil.h | 127 + .../Graphics/shaderlib/wine/include/prsht.h | 547 + .../Graphics/shaderlib/wine/include/psapi.h | 128 + .../Graphics/shaderlib/wine/include/pshpack1.h | 121 + .../Graphics/shaderlib/wine/include/pshpack2.h | 121 + .../Graphics/shaderlib/wine/include/pshpack4.h | 121 + .../Graphics/shaderlib/wine/include/pshpack8.h | 121 + .../Graphics/shaderlib/wine/include/pstore.idl | 285 + .../Graphics/shaderlib/wine/include/qedit.idl | 187 + .../Devices/Graphics/shaderlib/wine/include/ras.h | 526 + .../Graphics/shaderlib/wine/include/rasdlg.h | 41 + .../Graphics/shaderlib/wine/include/raserror.h | 38 + .../Graphics/shaderlib/wine/include/reason.h | 84 + .../Graphics/shaderlib/wine/include/regstr.h | 42 + .../shaderlib/wine/include/restartmanager.h | 67 + .../Graphics/shaderlib/wine/include/richedit.h | 1088 ++ .../Graphics/shaderlib/wine/include/richole.idl | 142 + .../Graphics/shaderlib/wine/include/rmxfguid.h | 139 + .../Graphics/shaderlib/wine/include/rmxftmpl.x | 277 + .../Graphics/shaderlib/wine/include/row.idl | 51 + .../Graphics/shaderlib/wine/include/rowchg.idl | 39 + .../Graphics/shaderlib/wine/include/rowpos.idl | 86 + .../Graphics/shaderlib/wine/include/rowpsc.idl | 45 + .../Devices/Graphics/shaderlib/wine/include/rpc.h | 93 + .../Graphics/shaderlib/wine/include/rpcasync.h | 211 + .../Graphics/shaderlib/wine/include/rpcdce.h | 635 + .../Graphics/shaderlib/wine/include/rpcdcep.h | 241 + .../Graphics/shaderlib/wine/include/rpcndr.h | 786 + .../Graphics/shaderlib/wine/include/rpcnterr.h | 53 + .../Graphics/shaderlib/wine/include/rpcproxy.h | 394 + .../Graphics/shaderlib/wine/include/rpcsal.h | 175 + .../Graphics/shaderlib/wine/include/rstbas.idl | 60 + .../Graphics/shaderlib/wine/include/rstinf.idl | 67 + .../Graphics/shaderlib/wine/include/rstloc.idl | 76 + .../Graphics/shaderlib/wine/include/rstnot.idl | 83 + .../Graphics/shaderlib/wine/include/rtutils.h | 58 + .../Graphics/shaderlib/wine/include/scarderr.h | 105 + .../Graphics/shaderlib/wine/include/schannel.h | 249 + .../Graphics/shaderlib/wine/include/schemadef.h | 54 + .../Graphics/shaderlib/wine/include/schnlsp.h | 33 + .../Devices/Graphics/shaderlib/wine/include/sddl.h | 130 + .../Graphics/shaderlib/wine/include/secext.h | 67 + .../Graphics/shaderlib/wine/include/security.h | 35 + .../Graphics/shaderlib/wine/include/sensapi.h | 56 + .../Graphics/shaderlib/wine/include/sensevts.idl | 136 + .../Graphics/shaderlib/wine/include/servprov.h | 114 + .../Graphics/shaderlib/wine/include/servprov.idl | 55 + .../Graphics/shaderlib/wine/include/sesprp.idl | 60 + .../Graphics/shaderlib/wine/include/setupapi.h | 1873 ++ .../Devices/Graphics/shaderlib/wine/include/sfc.h | 55 + .../shaderlib/wine/include/shdeprecated.idl | 613 + .../Graphics/shaderlib/wine/include/shdispid.h | 39 + .../Graphics/shaderlib/wine/include/shellapi.h | 670 + .../Graphics/shaderlib/wine/include/shldisp.idl | 573 + .../Graphics/shaderlib/wine/include/shlguid.h | 248 + .../Graphics/shaderlib/wine/include/shlobj.h | 1775 ++ .../Graphics/shaderlib/wine/include/shlwapi.h | 1135 ++ .../Graphics/shaderlib/wine/include/shobjidl.idl | 3408 ++++ .../Graphics/shaderlib/wine/include/shtypes.idl | 171 + .../Graphics/shaderlib/wine/include/sipbase.h | 33 + .../Graphics/shaderlib/wine/include/slerror.h | 35 + .../Graphics/shaderlib/wine/include/slpublic.h | 49 + .../Devices/Graphics/shaderlib/wine/include/snmp.h | 304 + .../Graphics/shaderlib/wine/include/softpub.h | 254 + .../Devices/Graphics/shaderlib/wine/include/sql.h | 755 + .../Graphics/shaderlib/wine/include/sqlext.h | 1682 ++ .../Graphics/shaderlib/wine/include/sqltypes.h | 258 + .../Graphics/shaderlib/wine/include/srcrst.idl | 62 + .../shaderlib/wine/include/srrestoreptapi.h | 67 + .../Devices/Graphics/shaderlib/wine/include/sspi.h | 842 + .../Graphics/shaderlib/wine/include/stamp-h.in | 1 + .../Graphics/shaderlib/wine/include/stdole2.idl | 440 + .../Devices/Graphics/shaderlib/wine/include/sti.h | 190 + .../Graphics/shaderlib/wine/include/storage.h | 35 + .../Graphics/shaderlib/wine/include/strmif.idl | 40 + .../Graphics/shaderlib/wine/include/strsafe.h | 42 + .../wine/include/structuredquerycondition.idl | 61 + .../Graphics/shaderlib/wine/include/svrapi.h | 55 + .../Graphics/shaderlib/wine/include/t2embapi.h | 85 + .../Devices/Graphics/shaderlib/wine/include/tapi.h | 1077 ++ .../Graphics/shaderlib/wine/include/tchar.h | 277 + .../Graphics/shaderlib/wine/include/tcpmib.h | 202 + .../Graphics/shaderlib/wine/include/textserv.h | 378 + .../Graphics/shaderlib/wine/include/textstor.idl | 320 + .../Graphics/shaderlib/wine/include/tlhelp32.h | 193 + .../Graphics/shaderlib/wine/include/tlogstg.idl | 61 + .../Graphics/shaderlib/wine/include/tmschema.h | 1279 ++ .../Graphics/shaderlib/wine/include/tom.idl | 444 + .../Graphics/shaderlib/wine/include/traffic.h | 57 + .../Graphics/shaderlib/wine/include/transact.idl | 235 + .../Graphics/shaderlib/wine/include/twain.h | 1849 ++ .../Graphics/shaderlib/wine/include/txcoord.idl | 190 + .../Graphics/shaderlib/wine/include/txdtc.idl | 524 + .../Graphics/shaderlib/wine/include/udpmib.h | 95 + .../Graphics/shaderlib/wine/include/uiautomation.h | 30 + .../shaderlib/wine/include/uiautomationclient.idl | 158 + .../shaderlib/wine/include/uiautomationcore.idl | 100 + .../shaderlib/wine/include/uiautomationcoreapi.h | 58 + .../Graphics/shaderlib/wine/include/unknwn.h | 221 + .../Graphics/shaderlib/wine/include/unknwn.idl | 89 + .../Graphics/shaderlib/wine/include/urlhist.idl | 155 + .../Graphics/shaderlib/wine/include/urlmon.h | 5449 ++++++ .../Graphics/shaderlib/wine/include/urlmon.idl | 2172 +++ .../Graphics/shaderlib/wine/include/userenv.h | 116 + .../Graphics/shaderlib/wine/include/usp10.h | 304 + .../Graphics/shaderlib/wine/include/uuids.h | 289 + .../Graphics/shaderlib/wine/include/uxtheme.h | 217 + .../Graphics/shaderlib/wine/include/vdmdbg.h | 49 + .../Devices/Graphics/shaderlib/wine/include/ver.h | 37 + .../Graphics/shaderlib/wine/include/verrsrc.h | 182 + .../Devices/Graphics/shaderlib/wine/include/vfw.h | 1953 ++ .../Graphics/shaderlib/wine/include/vfwmsgs.h | 175 + .../Graphics/shaderlib/wine/include/vmr9.idl | 533 + .../Graphics/shaderlib/wine/include/vmrender.idl | 490 + .../Graphics/shaderlib/wine/include/vsstyle.h | 1748 ++ .../Graphics/shaderlib/wine/include/vssym32.h | 687 + .../Graphics/shaderlib/wine/include/wbemcli.idl | 671 + .../Graphics/shaderlib/wine/include/wbemdisp.idl | 1130 ++ .../Graphics/shaderlib/wine/include/wbemprov.idl | 37 + .../Graphics/shaderlib/wine/include/werapi.h | 199 + .../Graphics/shaderlib/wine/include/wfext.h | 42 + .../Devices/Graphics/shaderlib/wine/include/wia.h | 36 + .../Graphics/shaderlib/wine/include/wia_lh.idl | 137 + .../Graphics/shaderlib/wine/include/wia_xp.idl | 137 + .../Graphics/shaderlib/wine/include/winbase.h | 2825 +++ .../Graphics/shaderlib/wine/include/wincodec.idl | 1041 ++ .../shaderlib/wine/include/wincodecsdk.idl | 330 + .../Graphics/shaderlib/wine/include/wincon.h | 416 + .../Graphics/shaderlib/wine/include/wincred.h | 303 + .../Graphics/shaderlib/wine/include/wincrypt.h | 4589 +++++ .../Graphics/shaderlib/wine/include/windef.h | 425 + .../Graphics/shaderlib/wine/include/windns.h | 666 + .../Graphics/shaderlib/wine/include/windows.h | 116 + .../Graphics/shaderlib/wine/include/windowsx.h | 1448 ++ .../shaderlib/wine/include/wine/dcetypes.idl | 97 + .../Graphics/shaderlib/wine/include/wine/debug.h | 297 + .../Graphics/shaderlib/wine/include/wine/dplaysp.h | 375 + .../Graphics/shaderlib/wine/include/wine/epm.idl | 131 + .../shaderlib/wine/include/wine/exception.h | 282 + .../shaderlib/wine/include/wine/gdi_driver.h | 291 + .../Graphics/shaderlib/wine/include/wine/irot.idl | 106 + .../Graphics/shaderlib/wine/include/wine/itss.idl | 104 + .../Graphics/shaderlib/wine/include/wine/library.h | 208 + .../Graphics/shaderlib/wine/include/wine/list.h | 243 + .../shaderlib/wine/include/wine/mmsystem16.h | 822 + .../Graphics/shaderlib/wine/include/wine/mscvpdb.h | 2197 +++ .../Graphics/shaderlib/wine/include/wine/port.h | 484 + .../Graphics/shaderlib/wine/include/wine/rbtree.h | 351 + .../Graphics/shaderlib/wine/include/wine/rpcfc.h | 205 + .../Graphics/shaderlib/wine/include/wine/server.h | 151 + .../shaderlib/wine/include/wine/server_protocol.h | 5828 ++++++ .../shaderlib/wine/include/wine/strmbase.h | 669 + .../shaderlib/wine/include/wine/svcctl.idl | 380 + .../Graphics/shaderlib/wine/include/wine/test.h | 654 + .../Graphics/shaderlib/wine/include/wine/unicode.h | 320 + .../Graphics/shaderlib/wine/include/wine/wgl.h | 5081 +++++ .../shaderlib/wine/include/wine/wgl_driver.h | 2862 +++ .../Graphics/shaderlib/wine/include/wine/wglext.h | 943 + .../Graphics/shaderlib/wine/include/wine/winaspi.h | 152 + .../shaderlib/wine/include/wine/winbase16.h | 572 + .../shaderlib/wine/include/wine/windef16.h | 178 + .../shaderlib/wine/include/wine/wine_common_ver.rc | 129 + .../Graphics/shaderlib/wine/include/wine/wined3d.h | 9726 ++++++++++ .../shaderlib/wine/include/wine/winedxgi.idl | 79 + .../shaderlib/wine/include/wine/wingdi16.h | 629 + .../shaderlib/wine/include/wine/winnet16.h | 297 + .../shaderlib/wine/include/wine/winuser16.h | 966 + .../Graphics/shaderlib/wine/include/wine/wpp.h | 71 + .../Graphics/shaderlib/wine/include/winerror.h | 2952 +++ .../Graphics/shaderlib/wine/include/winevt.h | 141 + .../Graphics/shaderlib/wine/include/wingdi.h | 3809 ++++ .../Graphics/shaderlib/wine/include/winhttp.h | 593 + .../Graphics/shaderlib/wine/include/wininet.h | 1739 ++ .../Graphics/shaderlib/wine/include/winineti.h | 143 + .../Graphics/shaderlib/wine/include/winioctl.h | 480 + .../Graphics/shaderlib/wine/include/winldap.h | 653 + .../Graphics/shaderlib/wine/include/winnetwk.h | 416 + .../Graphics/shaderlib/wine/include/winnls.h | 896 + .../Graphics/shaderlib/wine/include/winnls32.h | 43 + .../Graphics/shaderlib/wine/include/winnt.h | 5525 ++++++ .../Graphics/shaderlib/wine/include/winnt.rh | 459 + .../Graphics/shaderlib/wine/include/winperf.h | 79 + .../Graphics/shaderlib/wine/include/winreg.h | 195 + .../Graphics/shaderlib/wine/include/winresrc.h | 54 + .../Graphics/shaderlib/wine/include/winsafer.h | 89 + .../Graphics/shaderlib/wine/include/winscard.h | 164 + .../Graphics/shaderlib/wine/include/winsmcrd.h | 46 + .../Graphics/shaderlib/wine/include/winsnmp.h | 64 + .../Graphics/shaderlib/wine/include/winsock.h | 1057 ++ .../Graphics/shaderlib/wine/include/winsock2.h | 768 + .../Graphics/shaderlib/wine/include/winspool.h | 1822 ++ .../Graphics/shaderlib/wine/include/winsvc.h | 425 + .../Graphics/shaderlib/wine/include/winsxs.idl | 207 + .../Graphics/shaderlib/wine/include/wintab.h | 797 + .../Graphics/shaderlib/wine/include/wintabx.h | 139 + .../Graphics/shaderlib/wine/include/winternl.h | 2708 +++ .../Graphics/shaderlib/wine/include/wintrust.h | 633 + .../Graphics/shaderlib/wine/include/winuser.h | 4043 ++++ .../Graphics/shaderlib/wine/include/winuser.rh | 1351 ++ .../Graphics/shaderlib/wine/include/winver.h | 74 + .../Graphics/shaderlib/wine/include/wmistr.h | 69 + .../Graphics/shaderlib/wine/include/wmiutils.idl | 245 + .../Graphics/shaderlib/wine/include/wmsbuffer.idl | 52 + .../Graphics/shaderlib/wine/include/wmsdkidl.idl | 395 + .../Graphics/shaderlib/wine/include/wnaspi32.h | 250 + .../Graphics/shaderlib/wine/include/wownt32.h | 167 + .../Graphics/shaderlib/wine/include/wpcapi.idl | 116 + .../Graphics/shaderlib/wine/include/ws2def.h | 122 + .../Graphics/shaderlib/wine/include/ws2ipdef.h | 293 + .../Graphics/shaderlib/wine/include/ws2spi.h | 63 + .../Graphics/shaderlib/wine/include/ws2tcpip.h | 217 + .../Graphics/shaderlib/wine/include/wshisotp.h | 39 + .../Graphics/shaderlib/wine/include/wsipx.h | 53 + .../Graphics/shaderlib/wine/include/wsnwlink.h | 58 + .../Graphics/shaderlib/wine/include/wtsapi32.h | 187 + .../Graphics/shaderlib/wine/include/wtypes.h | 767 + .../Graphics/shaderlib/wine/include/wtypes.idl | 848 + .../Graphics/shaderlib/wine/include/wuapi.idl | 1359 ++ .../Devices/Graphics/shaderlib/wine/include/xcmc.h | 359 + .../Graphics/shaderlib/wine/include/xinput.h | 248 + .../Graphics/shaderlib/wine/include/xmldom.h | 29 + .../Graphics/shaderlib/wine/include/xmldom.idl | 847 + .../Graphics/shaderlib/wine/include/xmldomdid.h | 214 + .../Graphics/shaderlib/wine/include/xmldso.idl | 77 + .../Graphics/shaderlib/wine/include/xmldsodid.h | 39 + .../Graphics/shaderlib/wine/include/xmllite.idl | 304 + .../Graphics/shaderlib/wine/include/zmouse.h | 55 + src/VBox/Devices/Graphics/shaderlib/wined3d_gl.h | 4576 +++++ .../Devices/Graphics/shaderlib/wined3d_private.h | 3479 ++++ src/VBox/Devices/Graphics/shaderlib/winoverride.h | 46 + src/VBox/Devices/Graphics/shaders/Makefile.kmk | 50 + .../Devices/Graphics/shaders/d3d11blitter.hlsl | 75 + .../Graphics/shaders/d3d11blitter.hlsl.ps.h | 169 + .../Graphics/shaders/d3d11blitter.hlsl.vs.h | 249 + src/VBox/Devices/Graphics/svgadump/Makefile.kup | 0 src/VBox/Devices/Graphics/svgadump/svga_dump.c | 2815 +++ src/VBox/Devices/Graphics/svgadump/svga_dump.h | 39 + src/VBox/Devices/Graphics/testcase/dump-vmwgfx.c | 639 + src/VBox/Devices/Graphics/vmsvga_glext/glext.h | 12905 +++++++++++++ src/VBox/Devices/Graphics/vmsvga_glext/glxext.h | 957 + .../Devices/Graphics/vmsvga_glext/khrplatform.h | 314 + src/VBox/Devices/Graphics/vmsvga_glext/wglext.h | 848 + .../Graphics/vmsvga_include/VGPU10ShaderTokens.h | 819 + .../Devices/Graphics/vmsvga_include/includeCheck.h | 0 .../Devices/Graphics/vmsvga_include/svga3d_caps.h | 111 + .../Devices/Graphics/vmsvga_include/svga3d_cmd.h | 2279 +++ .../Graphics/vmsvga_include/svga3d_devcaps.h | 510 + .../Devices/Graphics/vmsvga_include/svga3d_dx.h | 2077 +++ .../Graphics/vmsvga_include/svga3d_limits.h | 130 + .../Devices/Graphics/vmsvga_include/svga3d_reg.h | 51 + .../Graphics/vmsvga_include/svga3d_shaderdefs.h | 518 + .../Graphics/vmsvga_include/svga3d_surfacedefs.h | 1687 ++ .../Devices/Graphics/vmsvga_include/svga3d_types.h | 2000 ++ .../Devices/Graphics/vmsvga_include/svga_escape.h | 90 + .../Devices/Graphics/vmsvga_include/svga_overlay.h | 200 + .../Devices/Graphics/vmsvga_include/svga_reg.h | 2264 +++ .../Devices/Graphics/vmsvga_include/svga_types.h | 55 + .../Graphics/vmsvga_include/vmsvga_headers_begin.h | 35 + .../Graphics/vmsvga_include/vmsvga_headers_end.h | 35 + .../Graphics/vmsvga_include/vmware_pack_begin.h | 0 .../Graphics/vmsvga_include/vmware_pack_end.h | 0 777 files changed, 514665 insertions(+) create mode 100644 src/VBox/Devices/Graphics/.scm-settings create mode 100644 src/VBox/Devices/Graphics/BIOS/BUGS create mode 100644 src/VBox/Devices/Graphics/BIOS/COPYING create mode 100644 src/VBox/Devices/Graphics/BIOS/ChangeLog create mode 100644 src/VBox/Devices/Graphics/BIOS/Makefile.kmk create mode 100644 src/VBox/Devices/Graphics/BIOS/README create mode 100644 src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm create mode 100644 src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum create mode 100644 src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm create mode 100644 src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum create mode 100644 src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm create mode 100644 src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum create mode 100644 src/VBox/Devices/Graphics/BIOS/inlines.h create mode 100644 src/VBox/Devices/Graphics/BIOS/makefile create mode 100644 src/VBox/Devices/Graphics/BIOS/ose_logo.bmp create mode 100644 src/VBox/Devices/Graphics/BIOS/tests/testbios.c create mode 100644 src/VBox/Devices/Graphics/BIOS/vbe.c create mode 100644 src/VBox/Devices/Graphics/BIOS/vbe.h create mode 100644 src/VBox/Devices/Graphics/BIOS/vbe_display_api.txt create mode 100644 src/VBox/Devices/Graphics/BIOS/vberom.asm create mode 100644 src/VBox/Devices/Graphics/BIOS/vbetables-gen.c create mode 100644 src/VBox/Devices/Graphics/BIOS/vgabios.c create mode 100644 src/VBox/Devices/Graphics/BIOS/vgabios.h create mode 100644 src/VBox/Devices/Graphics/BIOS/vgadefs.h create mode 100644 src/VBox/Devices/Graphics/BIOS/vgadefs.inc create mode 100644 src/VBox/Devices/Graphics/BIOS/vgafonts.h create mode 100644 src/VBox/Devices/Graphics/BIOS/vgarom.asm create mode 100644 src/VBox/Devices/Graphics/BIOS/vgatables.h create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA-cmd.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA-internal.h create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA.h create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.h create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-savedstate.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-shader.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-shader.h create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-glHlp.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.h create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-hlp.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-info.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-savedstate.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-win-d3d9.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA-SVGA3d.h create mode 100644 src/VBox/Devices/Graphics/DevVGA.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA.h create mode 100644 src/VBox/Devices/Graphics/DevVGAModes.h create mode 100644 src/VBox/Devices/Graphics/DevVGASavedState.h create mode 100644 src/VBox/Devices/Graphics/DevVGATmpl.h create mode 100644 src/VBox/Devices/Graphics/DevVGA_VBVA.cpp create mode 100644 src/VBox/Devices/Graphics/DevVGA_VDMA.cpp create mode 100644 src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp create mode 100644 src/VBox/Devices/Graphics/HGSMI/HGSMIHost.h create mode 100644 src/VBox/Devices/Graphics/HGSMI/Makefile.kup create mode 100644 src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.cpp create mode 100644 src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.h create mode 100644 src/VBox/Devices/Graphics/Makefile.kup create mode 100644 src/VBox/Devices/Graphics/VBoxSVGA3D.def create mode 100644 src/VBox/Devices/Graphics/VBoxSVGA3DObjC.def create mode 100644 src/VBox/Devices/Graphics/shaderlib/Makefile.kup create mode 100644 src/VBox/Devices/Graphics/shaderlib/directx.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/glsl_shader.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/Makefile.kup create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/debug.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/config.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/d3d8.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/d3d9.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/wine/debug.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/wine/guiddef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/wine/initguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/wine/list.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/wine/port.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/wine/rbtree.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/wine/unicode.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/libWineStub/include/wine/wined3d.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/shader.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/shader_sm1.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/shader_sm4.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/shaderapi.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/shaderlib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/stateblock.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/utils.c create mode 100644 src/VBox/Devices/Graphics/shaderlib/vboxext.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/Makefile.in create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/accctrl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/access.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/aclapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/aclui.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/activaut.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/activdbg.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/activscp.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/adshlp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/advpub.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/af_irda.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/amaudio.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/amstream.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/amvideo.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/appcompatapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/appmgmt.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/asptlb.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/asynot.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/asysta.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/atlbase.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/atliface.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/atlwin.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/audevcod.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/audioclient.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/audiopolicy.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/audiosessiontypes.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/austream.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/aviriff.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/avrt.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/axcore.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/axextend.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/basetsd.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/basetyps.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/bcrypt.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/binres.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/bits.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/bits1_5.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/bitsmsg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cderr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cfgmgr32.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/chprst.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cierror.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/clusapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cmdbas.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cmdtxt.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/comcat.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/commctrl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/commctrl.rh create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/commdlg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/commoncontrols.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/compobj.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/config.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/config.h.in create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/config_linux.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/control.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cor.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cordebug.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/corerror.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/corhdr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cpl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/crtrow.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cryptdlg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cryptuiapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ctfutb.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ctxtcall.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/custcntl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/cvconst.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d10.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d10_1.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d10_1shader.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d10effect.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d10misc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d10shader.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d11.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d11sdklayers.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d11shader.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d8.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d8caps.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d8types.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d9.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d9caps.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3d9types.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dcaps.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dcommon.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dcompiler.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dhal.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3drm.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3drmdef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3drmobj.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3drmwin.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dtypes.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dvec.inl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9anim.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9core.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9effect.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9math.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9math.inl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9mesh.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9shader.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9shape.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9tex.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/d3dx9xof.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dbccmd.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dbcses.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dbdsad.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dbghelp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dbinit.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dbprop.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dbs.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dbt.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dciddi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dciman.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dcommon.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dde.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dde.rh create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddeml.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/compstui.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/hidsdi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/imm.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/mountmgr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/ntddcdvd.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/ntddk.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/ntddser.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/ntddtape.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/usb.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/usb100.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/usb200.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/usbdlib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/usbioctl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/usbiodef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/wdm.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/winddiui.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddk/winsplp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddraw.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddrawgdi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddrawi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ddstream.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/delayloadhandler.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/devenum.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/devguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/devicetopology.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/devpkey.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/devpropdef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/difxapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/digitalv.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dimm.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dinput.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dinputd.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dispdib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dispex.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dlgs.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dls1.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dls2.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmdls.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmerror.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmksctrl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmo.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmoreg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmort.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmplugin.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmusbuff.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmusicc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmusicf.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmusici.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dmusics.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/docobj.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/docobjectservice.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/downloadmgr.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dpaddr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dplay.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dplay8.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dplobby.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dplobby8.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dpnathlp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dsconf.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dsgetdc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dshow.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dsound.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dsrole.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dvdmedia.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dwmapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dwrite.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dwrite_1.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dxdiag.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dxerr8.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dxerr9.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dxfile.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dxgi.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dxgiformat.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dxgitype.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/dyngraph.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/endpointvolume.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/errorrep.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/errors.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/errrec.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/evcode.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/evntprov.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/evntrace.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/excpt.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/exdisp.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/exdispid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/fci.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/fdi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/fileapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/fltdefs.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/fusion.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gameux.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplus.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdipluscolor.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdipluscolormatrix.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplusenums.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplusflat.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplusgpstubs.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplusimaging.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplusinit.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplusmem.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplusmetaheader.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdipluspixelformats.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/gdiplustypes.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/guiddef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/hlguids.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/hlink.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/htiface.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/htiframe.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/htmlhelp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/http.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/httprequest.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/httprequestid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/i_cryptasn1tls.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/iads.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/icftypes.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/icm.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/icmpapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/idispids.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/iextag.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ifdef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ifmib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/imagehlp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/imm.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/imnact.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/imnxport.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/in6addr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/inaddr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/indexsrv.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/initguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/inputscope.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/intshcut.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ipexport.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/iphlpapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ipifcons.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ipmib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/iprtrmib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/iptypes.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/isguids.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/knownfolders.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ks.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ksguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ksmedia.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lm.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmaccess.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmapibuf.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmat.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmbrowsr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmcons.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmerr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmjoin.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmmsg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmserver.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmshare.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmstats.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmuse.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmuseflg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lmwksta.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/loadperf.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/lzexpand.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapicode.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapidefs.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapiform.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapiguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapitags.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapiutil.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapival.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mapix.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mciavi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mcx.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mediaerr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mediaobj.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/metahost.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/midles.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mimeinfo.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mimeole.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/minmax.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mlang.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mmc.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mmddk.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mmdeviceapi.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mmreg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mmstream.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mmsystem.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mprapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mprerror.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msacm.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msacmdlg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msacmdrv.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mscat.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mscoree.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msctf.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msdadc.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msdaguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msdasc.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mshtmcid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mshtmdid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mshtmhst.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mshtml.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msidefs.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msident.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msinkaut.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msiquery.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mssip.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mstask.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mstcpip.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/assert.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/conio.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/crtdbg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/crtdefs.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/ctype.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/direct.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/dirent.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/dos.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/eh.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/errno.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/fcntl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/float.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/io.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/limits.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/locale.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/malloc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/math.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/mbctype.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/mbstring.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/memory.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/process.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/search.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/setjmp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/share.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/signal.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/stddef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/stdio.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/stdlib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/string.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/sys/locking.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/sys/stat.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/sys/timeb.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/sys/types.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/sys/unistd.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/sys/utime.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/time.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/unistd.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/wchar.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msvcrt/wctype.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/mswsock.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msxml.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msxml.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msxml2.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msxml2did.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msxml6.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msxml6did.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/msxmldid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/nb30.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ndrtypes.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/netcon.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/netfw.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/nldef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/npapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/nspapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntddcdrm.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntddndis.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntddscsi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntddstor.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntdsapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntquery.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntsecapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntsecpkg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ntstatus.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oaidl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oaidl.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/objbase.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/objectarray.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/objidl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/objidl.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/objsafe.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/objsel.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ocidl.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ocmm.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/odbcinst.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ole2.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ole2ver.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oleacc.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oleauto.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/olectl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oledb.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oledberr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oledlg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oleidl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/oleidl.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/opnrst.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/optary.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/patchapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/pdh.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/pdhmsg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/perhist.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/pktdef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/poppack.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/powrprof.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/profinfo.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/propidl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/propidl.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/propkey.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/propkeydef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/propsys.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/propvarutil.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/prsht.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/psapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/pshpack1.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/pshpack2.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/pshpack4.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/pshpack8.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/pstore.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/qedit.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ras.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rasdlg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/raserror.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/reason.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/regstr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/restartmanager.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/richedit.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/richole.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rmxfguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rmxftmpl.x create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/row.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rowchg.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rowpos.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rowpsc.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rpc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rpcasync.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rpcdce.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rpcdcep.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rpcndr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rpcnterr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rpcproxy.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rpcsal.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rstbas.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rstinf.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rstloc.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rstnot.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/rtutils.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/scarderr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/schannel.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/schemadef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/schnlsp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sddl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/secext.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/security.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sensapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sensevts.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/servprov.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/servprov.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sesprp.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/setupapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sfc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shdeprecated.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shdispid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shellapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shldisp.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shlguid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shlobj.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shlwapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shobjidl.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/shtypes.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sipbase.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/slerror.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/slpublic.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/snmp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/softpub.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sql.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sqlext.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sqltypes.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/srcrst.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/srrestoreptapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sspi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/stamp-h.in create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/stdole2.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/sti.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/storage.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/strmif.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/strsafe.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/structuredquerycondition.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/svrapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/t2embapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/tapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/tchar.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/tcpmib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/textserv.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/textstor.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/tlhelp32.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/tlogstg.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/tmschema.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/tom.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/traffic.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/transact.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/twain.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/txcoord.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/txdtc.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/udpmib.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/uiautomation.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/uiautomationclient.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/uiautomationcore.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/uiautomationcoreapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/unknwn.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/unknwn.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/urlhist.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/urlmon.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/urlmon.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/userenv.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/usp10.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/uuids.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/uxtheme.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/vdmdbg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ver.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/verrsrc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/vfw.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/vfwmsgs.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/vmr9.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/vmrender.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/vsstyle.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/vssym32.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wbemcli.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wbemdisp.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wbemprov.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/werapi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wfext.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wia.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wia_lh.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wia_xp.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winbase.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wincodec.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wincodecsdk.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wincon.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wincred.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wincrypt.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/windef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/windns.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/windows.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/windowsx.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/dcetypes.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/debug.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/dplaysp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/epm.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/exception.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/gdi_driver.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/irot.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/itss.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/library.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/list.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/mmsystem16.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/mscvpdb.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/port.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/rbtree.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/rpcfc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/server.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/server_protocol.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/strmbase.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/svcctl.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/test.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/unicode.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/wgl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/wgl_driver.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/wglext.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/winaspi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/winbase16.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/windef16.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/wine_common_ver.rc create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/wined3d.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/winedxgi.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/wingdi16.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/winnet16.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/winuser16.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wine/wpp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winerror.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winevt.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wingdi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winhttp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wininet.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winineti.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winioctl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winldap.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winnetwk.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winnls.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winnls32.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winnt.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winnt.rh create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winperf.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winreg.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winresrc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winsafer.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winscard.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winsmcrd.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winsnmp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winsock.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winsock2.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winspool.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winsvc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winsxs.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wintab.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wintabx.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winternl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wintrust.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winuser.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winuser.rh create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/winver.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wmistr.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wmiutils.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wmsbuffer.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wmsdkidl.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wnaspi32.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wownt32.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wpcapi.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ws2def.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ws2ipdef.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ws2spi.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/ws2tcpip.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wshisotp.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wsipx.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wsnwlink.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wtsapi32.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wtypes.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wtypes.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/wuapi.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/xcmc.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/xinput.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/xmldom.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/xmldom.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/xmldomdid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/xmldso.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/xmldsodid.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/xmllite.idl create mode 100644 src/VBox/Devices/Graphics/shaderlib/wine/include/zmouse.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wined3d_gl.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/wined3d_private.h create mode 100644 src/VBox/Devices/Graphics/shaderlib/winoverride.h create mode 100644 src/VBox/Devices/Graphics/shaders/Makefile.kmk create mode 100644 src/VBox/Devices/Graphics/shaders/d3d11blitter.hlsl create mode 100644 src/VBox/Devices/Graphics/shaders/d3d11blitter.hlsl.ps.h create mode 100644 src/VBox/Devices/Graphics/shaders/d3d11blitter.hlsl.vs.h create mode 100644 src/VBox/Devices/Graphics/svgadump/Makefile.kup create mode 100644 src/VBox/Devices/Graphics/svgadump/svga_dump.c create mode 100644 src/VBox/Devices/Graphics/svgadump/svga_dump.h create mode 100644 src/VBox/Devices/Graphics/testcase/dump-vmwgfx.c create mode 100644 src/VBox/Devices/Graphics/vmsvga_glext/glext.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_glext/glxext.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_glext/khrplatform.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_glext/wglext.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/VGPU10ShaderTokens.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/includeCheck.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_caps.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_cmd.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_devcaps.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_dx.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_limits.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_reg.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_shaderdefs.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_surfacedefs.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga3d_types.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga_escape.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga_overlay.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga_reg.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/svga_types.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/vmsvga_headers_begin.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/vmsvga_headers_end.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/vmware_pack_begin.h create mode 100644 src/VBox/Devices/Graphics/vmsvga_include/vmware_pack_end.h (limited to 'src/VBox/Devices/Graphics') diff --git a/src/VBox/Devices/Graphics/.scm-settings b/src/VBox/Devices/Graphics/.scm-settings new file mode 100644 index 00000000..b0390afd --- /dev/null +++ b/src/VBox/Devices/Graphics/.scm-settings @@ -0,0 +1,88 @@ +# $Id: .scm-settings $ +## @file +# Source code massager settings for graphics. +# + +# +# Copyright (C) 2017-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + + +/BIOS/vbe.c: --external-copyright --lgpl-disclaimer +/BIOS/vbe.h: --external-copyright --lgpl-disclaimer +/BIOS/vberom.asm: --external-copyright --lgpl-disclaimer +/BIOS/vbetables-gen.c: --external-copyright +/BIOS/vgabios.c: --external-copyright --lgpl-disclaimer +/BIOS/vgabios.h: --external-copyright +/BIOS/vgadefs.h: --external-copyright +/BIOS/vgadefs.inc: --external-copyright +/BIOS/vgafonts.h: --external-copyright +/BIOS/vgarom.asm: --external-copyright --lgpl-disclaimer +/BIOS/vgatables.h: --external-copyright +/BIOS/tests/testbios.c: --external-copyright + +--filter-out-files /BIOS/BUGS +--filter-out-files /BIOS/ChangeLog +--filter-out-files /BIOS/makefile +--filter-out-files /BIOS/Notes +--filter-out-files /BIOS/README +--filter-out-files /BIOS/TODO +--filter-out-files /BIOS/vbe_display_api.txt +--filter-out-files /BIOS/VBoxVgaBiosAlternative*.asm +--filter-out-files /BIOS/VBoxVgaBiosAlternative*.md5sum + + +/shaderlib/*: --external-copyright --lgpl-disclaimer --no-convert-tabs --no-fix-todos --no-strip-trailing-blanks +/shaderlib/wine/include/*.idl: --treat-as .h --no-fix-header-guards +/shaderlib/wine/include/*.rh: --treat-as .h --no-fix-header-guards +/shaderlib/wine/include/*.h.in: --treat-as .h --no-fix-header-guards +/shaderlib/wine/include/*-h.in: --treat-as .h --no-fix-header-guards +/shaderlib/wine/include/*.inl: --treat-as .h --no-fix-header-guards +/shaderlib/wine/include/*.x: --treat-as .h --no-fix-header-guards +/shaderlib/wine/include/Makefile.in: --treat-as Makefile +/shaderlib/wine/include/*.h: --no-fix-header-guards +/shaderlib/libWineStub/include/*.h: --no-fix-header-guards +/shaderlib/libWineStub/include/wine/*.h: --no-fix-header-guards +/shaderlib/wine/vbox/libWineStub/include/*.h: --no-fix-header-guards +/shaderlib/wine/vbox/libWineStub/include/wine/*.h: --no-fix-header-guards + +/shaderlib/shaderapi.c: --no-external-copyright --no-lgpl-disclaimer --convert-tabs --fix-todos --strip-trailing-blanks +/shaderlib/shaderlib.h: --no-external-copyright --no-lgpl-disclaimer --convert-tabs --fix-todos --strip-trailing-blanks +/shaderlib/utils.c: --no-external-copyright --no-lgpl-disclaimer --convert-tabs --fix-todos --strip-trailing-blanks +/shaderlib/vboxext.h: --no-external-copyright --no-lgpl-disclaimer --convert-tabs --fix-todos --strip-trailing-blanks +/shaderlib/wine/vbox/VBoxDbgGl.c: --no-external-copyright --no-lgpl-disclaimer --convert-tabs --fix-todos --strip-trailing-blanks +/shaderlib/wine/vbox/VBoxDbgGl.h: --no-external-copyright --no-lgpl-disclaimer --convert-tabs --fix-todos --strip-trailing-blanks +/shaderlib/wine/vbox/VBoxWineEx.h: --no-external-copyright --no-lgpl-disclaimer --convert-tabs --fix-todos --strip-trailing-blanks +/shaderlib/winoverride.h: --no-external-copyright --no-lgpl-disclaimer --convert-tabs --fix-todos --strip-trailing-blanks + +/shaders/*.h: --external-copyright --no-fix-header-guards --dont-set-svn-keywords --no-strip-trailing-blanks +/shaders/*.hlsl: --treat-as .cpp + +--filter-out-dirs "/svgadump/." + +/vmsvga_glext/*.h: --external-copyright --no-convert-tabs --no-strip-trailing-blanks +/vmsvga_include/includeCheck.h: --external-copyright --no-fix-header-guards +/vmsvga_include/svga*.h: --external-copyright --no-fix-header-guards --no-convert-tabs --no-strip-trailing-blanks --dont-set-svn-keywords --no-page-restrictions +/vmsvga_include/vmware*.h: --external-copyright --no-fix-header-guards --no-convert-tabs --no-strip-trailing-blanks --dont-set-svn-keywords +/vmsvga_include/VGPU*.h: --external-copyright --no-fix-header-guards --no-convert-tabs --no-strip-trailing-blanks --dont-set-svn-keywords +/vmsvga_include/vmsvga*.h: --no-fix-header-guards + +/DevVGATmpl.h: --no-fix-header-guards diff --git a/src/VBox/Devices/Graphics/BIOS/BUGS b/src/VBox/Devices/Graphics/BIOS/BUGS new file mode 100644 index 00000000..25f88aa0 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/BUGS @@ -0,0 +1,3 @@ +Not all the functions have been implemented yet. + +Please report any bugs to diff --git a/src/VBox/Devices/Graphics/BIOS/COPYING b/src/VBox/Devices/Graphics/BIOS/COPYING new file mode 100644 index 00000000..223ede7d --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/VBox/Devices/Graphics/BIOS/ChangeLog b/src/VBox/Devices/Graphics/BIOS/ChangeLog new file mode 100644 index 00000000..4b88fab1 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/ChangeLog @@ -0,0 +1,1212 @@ +2006-08-19 09:39 vruppert + + * vbe.c (1.58): + + - improved VGA compatible setup for VBE modes (disable CGA and Hercules + compatible memory layout) + +2006-08-18 20:39 vruppert + + * vbe.c (1.57): + + - improved VGA compatible setup for >=8bpp VBE modes (CRTC doubleword mode and + GRDC shift register setting added) + - now using symbolic name for CRTC address register + +2006-08-15 20:42 vruppert + + * vbe.c (1.56), vbetables-gen.c (1.4): + + - init 4bpp VBE modes by a temporary switch to VGA mode 0x6A + - all 4bpp VBE modes now enabled + +2006-08-14 20:24 vruppert + + * vbe.c (1.55): + + - VGA compatible setup for VBE modes improved (Bochs hack can be removed now) + +2006-08-12 07:51 vruppert + + * .cvsignore (1.1): + + - .cvsignore added for auto-generated file + +2006-08-12 07:47 vruppert + + * vbe.c (1.54), vbe.h (1.27), vbe_display_api.txt (1.13), vbetables-gen.c (1.3): + + - cleaned up VBE memory size definitions (removed duplicate defines, main + definition now in vbetables-gen.c) + +2006-08-09 21:28 vruppert + + * vbetables.h (1.30): + + - removed auto-generated file + +2006-08-09 21:26 vruppert + + * vbe.c (1.53), vbe.h (1.26), vbe_display_api.txt (1.12), vbetables-gen.c (1.2), + vbetables.h (1.29): + + - VBE video memory increased to 8 MB + - VBE dispi ID changed to B0C4 + - documentation update + +2006-07-11 08:03 vruppert + + * Makefile (1.18), vbetables-gen.c (1.1), vbetables.h (1.28): + + - generate vbetables.h dynamicly + * initial patch from the qemu project by Fabrice Bellard + * only add modes that fit in video memory (still 4 MB) + * several other fixes (e.g. 4 bpp specific stuff, number of pages) + +2006-07-10 07:47 vruppert + + * vgabios.c (1.66): + + - biosfn_scroll(): check variable 'i' for underflowing when scrolling downwards + to avoid screen corruption + +2006-07-10 07:47 vruppert + + * vbe.c (1.52): + + - VBE set bank functions failure handling added + - VBE get/set logical scan line length fixes for the 4bpp mode + +2006-07-08 13:27 vruppert + + * vbe.c (1.51), vbetables.h (1.27): + + - added special case for the 4 bpp when setting VBE display start + - VBE mode table fixes + +2006-07-07 13:30 vruppert + + * clext.c (1.12): + + - bank pointer must be set to 0 after a mode set + +2006-06-21 16:58 vruppert + + * vbe.c (1.50), vbetables.h (1.26): + + - improved VBE display capabilities check (X resulution checked now) + - removed obsolete defines (LFB always available, always generate dynamic list) + - CR/LF to LF fixes + +2006-06-18 15:22 vruppert + + * clext.c (1.11), vbe.c (1.49), vbe.h (1.25), vbetables.h (1.25), vgabios.c + (1.65): + + - applied patch from the qemu project (Fabrice Bellard) + * Cirrus SVGA now supports the "no clear" bit when switching to Cirrus or + VESA mode + * Bochs VBE protected mode interface improved + * save/restore video state support for Bochs VBE and standard VGA added + * Bochs VBE prepared for more modi + +2006-03-25 10:19 vruppert + + * clext.c (1.10), vgabios.c (1.64), vgatables.h (1.10): + + - applied patch from Fabrice Bellard + * added minimal support for the video parameter table (VPT) + * added Cirrus SVGA mode 0x7b (1600x1200x8) + +2005-12-26 19:50 vruppert + + * vbe.c (1.48), vgabios.c (1.63): + + - Bochs VBE protected mode interface added (based on a patch by malc@pulsesoft.com) + +2005-12-26 19:50 vruppert + + * biossums.c (1.3): + + - biossums utility now supports VGABIOS sizes up to 64 kBytes + +2005-09-21 18:45 vruppert + + * vgatables.h (1.9): + + - mode 0x11: all color planes must be enabled in this 2-color VGA mode + +2005-08-30 18:41 vruppert + + * biossums.c (1.2): + + - missing license text added in biossums.c + +2005-07-02 18:39 vruppert + + * vgabios.c (1.62): + + - BIOS configuration word usually reports initial mode 80x25 color text + - vgabios function 0x0e (write teletype): linefeed (0x0a) only increments the + cursor row value + +2005-05-24 16:50 vruppert + + * vbe.c (1.47), vgabios.c (1.61): + + - output to the vgabios info port can be disabled now. It is still enabled by + default and always possible in debug mode. (based on a patch from Alex Beregszaszi) + +2005-05-20 16:06 vruppert + + * vbe.c (1.46), vgabios.c (1.60): + + - fixed return value for the default case in the VBE section (non-debug mode) + - removed unused macros HALT and PANIC_PORT + +2005-03-07 20:39 vruppert + + * README (1.9): + + - updates for 0.5a release + +2005-03-06 13:06 vruppert + + * Makefile (1.17): + + - vgabios files with cirrus support added to release target + +2005-03-06 12:24 vruppert + + * Makefile (1.16): + + - cross compilation support added (patch from Alex Beregszaszi) + +2005-03-05 13:03 vruppert + + * BUGS (1.3), README (1.8), TODO (1.11): + + - documentation updates + +2004-12-04 15:26 vruppert + + * VGABIOS-lgpl-latest.bin (1.61), VGABIOS-lgpl-latest.cirrus.bin + (1.13), VGABIOS-lgpl-latest.cirrus.debug.bin (1.13), + VGABIOS-lgpl-latest.debug.bin (1.61), clext.c (1.9): + + - Cirrus extension: support for 1280x1024x15 and 1280x1024x16 modes added (patch + from Fabrice Bellard) + +2004-08-08 16:53 vruppert + + * VGABIOS-lgpl-latest.bin (1.60), VGABIOS-lgpl-latest.cirrus.bin (1.12), + VGABIOS-lgpl-latest.cirrus.debug.bin (1.12), + VGABIOS-lgpl-latest.debug.bin (1.60), clext.c (1.8): + + - use single bank mode for VBE + - enable 16k granularity for VBE only + +2004-07-30 19:33 vruppert + + * VGABIOS-lgpl-latest.bin (1.59), VGABIOS-lgpl-latest.cirrus.bin (1.11), + VGABIOS-lgpl-latest.cirrus.debug.bin (1.11), + VGABIOS-lgpl-latest.debug.bin (1.59), clext.c (1.7): + + - cirrus init: set standard vga mode and reset bitblt + +2004-07-22 18:38 vruppert + + * VGABIOS-lgpl-latest.bin (1.58), VGABIOS-lgpl-latest.cirrus.bin (1.10), + VGABIOS-lgpl-latest.cirrus.debug.bin (1.10), + VGABIOS-lgpl-latest.debug.bin (1.58), clext.c (1.6), vbe.c (1.45), + vbetables.h (1.24): + + - cirrus extension: tables for mode 1280x1024x8 added + - vbe: dispi_set_xres() and dispi_set_virt_width() now modify vga compatible + registers + - vbe: mode list entry for mode 800x600x4 fixed + +2004-07-18 20:23 vruppert + + * VGABIOS-lgpl-latest.bin (1.57), VGABIOS-lgpl-latest.cirrus.bin (1.9), + VGABIOS-lgpl-latest.cirrus.debug.bin (1.9), + VGABIOS-lgpl-latest.debug.bin (1.57), vgabios.c (1.59), vgatables.h (1.8): + + - disable CRTC write protection before setting new values + - CRTC line for mode 0x6a fixed + +2004-07-07 16:08 vruppert + + * Makefile (1.15), VGABIOS-lgpl-latest.bin (1.56), + VGABIOS-lgpl-latest.cirrus.bin (1.8), VGABIOS-lgpl-latest.cirrus.debug.bin (1.8), + VGABIOS-lgpl-latest.debug.bin (1.56), biossums.c (1.1), clext.c (1.5): + + - biossums utility for the Bochs BIOS adapted for the LGPL'd VGABIOS + - VESA3 PMINFO checksum calculated in the source + - 24 bpp mode entries fixed (patch from Fabrice Bellard) + +2004-06-25 18:28 vruppert + + * VGABIOS-lgpl-latest.cirrus.bin (1.7), VGABIOS-lgpl-latest.cirrus.debug.bin (1.7), + clext.c (1.4): + + - 4MB memory probe added (patch from Fabrice Bellard) + +2004-06-25 17:31 vruppert + + * VGABIOS-lgpl-latest.bin (1.55), VGABIOS-lgpl-latest.cirrus.bin (1.6), + VGABIOS-lgpl-latest.cirrus.debug.bin (1.6), + VGABIOS-lgpl-latest.debug.bin (1.55), clext.c (1.3): + + - fixed value of sequencer reset register in cirrus mode table + - fixed possible overflow error if cirrus start address is >256k + +2004-06-23 21:11 vruppert + + * VGABIOS-lgpl-latest.bin (1.54), VGABIOS-lgpl-latest.cirrus.bin (1.5), + VGABIOS-lgpl-latest.cirrus.debug.bin (1.5), + VGABIOS-lgpl-latest.debug.bin (1.54), clext.c (1.2): + + - applied new patch for the cirrus extension from suzu + * enable VESA LFB support if a Cirrus PCI adapter is detected + * prepared VBE3 protected mode info block (test case required) + - added VBE functions 4F06h and 4F07h + - some bugfixes + +2004-06-17 18:57 vruppert + + * Makefile (1.14), VGABIOS-lgpl-latest.bin (1.53), + VGABIOS-lgpl-latest.cirrus.bin (1.2), VGABIOS-lgpl-latest.cirrus.debug.bin (1.2), + VGABIOS-lgpl-latest.debug.bin (1.53): + + - fixed makefile targets for the binaries with cirrus extension + +2004-06-16 21:11 vruppert + + * Makefile (1.13), VGABIOS-lgpl-latest.bin (1.52), + VGABIOS-lgpl-latest.cirrus.bin (1.1), VGABIOS-lgpl-latest.cirrus.debug.bin (1.1), + VGABIOS-lgpl-latest.debug.bin (1.52), clext.c (1.1), vgabios.c (1.58): + + - applied suzu's cirrus extension patch. Cirrus SVGA detection, most of the + cirrus-specific modes and some basic VBE features are present now. + +2004-05-31 21:15 vruppert + + * VGABIOS-lgpl-latest.bin (1.51), VGABIOS-lgpl-latest.debug.bin (1.51), + vgabios.c (1.57): + + - write character in planar graphics modes: sequencer map mask must be 0x0f and + bit operation must be 'replace' if bit 7 of attribute is clear + - read/write pixel in planar graphics modes: bit mask setup simplified + +2004-05-11 18:08 vruppert + + * VGABIOS-lgpl-latest.bin (1.50), VGABIOS-lgpl-latest.debug.bin (1.50), + vgabios.c (1.56): + + - biosfn_select_vert_res rewritten in assembler + - scroll text in planar graphics modes: attribute for blank line fixed + - write character in planar graphics modes: graphics controller values fixed + +2004-05-09 20:32 vruppert + + * VGABIOS-lgpl-latest.bin (1.49), VGABIOS-lgpl-latest.debug.bin (1.49), + vbe.c (1.44), vbe.h (1.24), vgabios.c (1.55): + + - VBE init code and some dispi ioport functions rewritten in assembler + - text scroll functions for CGA graphics modes added + - scroll text in graphics modes: attribute for blank line fixed + +2004-05-08 16:06 vruppert + + * BUGS (1.2), README (1.7), TODO (1.10), VGABIOS-lgpl-latest.bin (1.48), + VGABIOS-lgpl-latest.debug.bin (1.48), vbe.c (1.43), vbe.h (1.23), + vbe_display_api.txt (1.11), vgabios.c (1.54): + + - VBE internal functions dispi_set_enable and dispi_set_bank now called both from C + and asm code + - VBE function 0x03 rewritten in assembler + - VBE function 0x08 cleaned up + - text output and scroll functions for graphics modes rewritten using case + structures + - documentation and comments updated + +2004-05-06 21:18 vruppert + + * VGABIOS-lgpl-latest.bin (1.47), VGABIOS-lgpl-latest.debug.bin (1.47), + vbe.c (1.42), vbe.h (1.22), vgabios.c (1.53): + + - VBE functions 0x05, 0x06, 0x07 and some dispi ioport functions rewritten in + assembler + - VBE functions 0x06 and 0x07: get functions now supported, 15 bpp bug fixed + +2004-05-05 19:24 vruppert + + * VGABIOS-lgpl-latest.bin (1.46), VGABIOS-lgpl-latest.debug.bin (1.46), + vbe.c (1.41), vbe.h (1.21), vbe_display_api.txt (1.10), vgabios.c (1.52): + + - 8 bit DAC capability flag set + - vbe_biosfn_set_get_dac_palette_format implemented + - VBE api description updated + - C definitions from header files now used assembler code + +2004-05-02 17:27 vruppert + + * VGABIOS-lgpl-latest.bin (1.45), VGABIOS-lgpl-latest.debug.bin (1.45), + vgabios.c (1.51): + + - text scroll functions for PLANAR1/PLANAR4 graphics modes added + - function biosfn_get_ega_info rewritten in assembler + - read/write graphics pixel functions rewritten using a case structure + +2004-05-01 16:03 vruppert + + * VGABIOS-lgpl-latest.bin (1.44), VGABIOS-lgpl-latest.debug.bin (1.44), + vgabios.c (1.50): + + - biosfn_enable_cursor_emulation rewritten in assembler + - remap of the cursor shape depends on modeset control bit 0 + - text output in PLANAR4 modes now supports attribute bit 7 (XOR with background) + +2004-04-25 20:13 vruppert + + * VGABIOS-lgpl-latest.bin (1.43), VGABIOS-lgpl-latest.debug.bin (1.43), + vgabios.c (1.49), vgatables.h (1.7): + + - table entries for vga mode 0x0f fixed (PLANAR2 exists on EGA only) + - function release_font_access now supports the monochrome text mode + - PLANAR1 modes now supported in text output functions and read/write pixel + - function AH=0x12/BL=0x32 rewritten in assembler + +2004-04-25 08:45 vruppert + + * VGABIOS-lgpl-latest.bin (1.42), VGABIOS-lgpl-latest.debug.bin (1.42), + vgabios.c (1.48): + + - block address calculation in font functions fixed + - functions AX=0x1103, AH=0x12/BL=0x31 and AH=0x12/BL=0x33 rewritten in assembler + +2004-04-24 09:59 vruppert + + * VGABIOS-lgpl-latest.bin (1.41), VGABIOS-lgpl-latest.debug.bin (1.41), + vgabios.c (1.47): + + - read/write graphics pixel for PLANAR4 modes added + - CGA specific functions (group AH = 0x0B) implemented + +2004-04-23 14:34 vruppert + + * VGABIOS-lgpl-latest.bin (1.40), VGABIOS-lgpl-latest.debug.bin (1.40), + vgabios.c (1.46): + + - remaining palette and dac read/write functions (except gray scale summing) + rewritten in assembler + +2004-04-18 13:43 vruppert + + * VGABIOS-lgpl-latest.bin (1.39), VGABIOS-lgpl-latest.debug.bin (1.39), + vgabios.c (1.45): + + - some palette and dac read/write functions rewritten in assembler + - main int10 debug message now works with assembler functions, too + +2004-04-18 09:15 japj + + * vbe.c (1.40): + + updated my email address + put vgabios url in the bios copyright string + (instead of my old email address) + +2004-04-17 07:18 vruppert + + * VGABIOS-lgpl-latest.bin (1.38), VGABIOS-lgpl-latest.debug.bin (1.38), + vgabios.c (1.44): + + - biosfn_set_video_mode: don't load DAC registers if default palette loading is + disabled. Perform gray scale summing if enabled. + - biosfn_perform_gray_scale_summing: switch between DAC read and write mode is + required to make this function work. Maximum DAC value always set to 0x3f. + +2004-04-08 17:50 vruppert + + * VGABIOS-lgpl-latest.bin (1.37), VGABIOS-lgpl-latest.debug.bin (1.37), + vgabios.c (1.43): + + - write character function for the LINEAR8 mode + - get_font_access() and release_font_access() rewritten in assembler + - fixed wrong variable name in the init code + +2004-04-06 19:31 vruppert + + * VGABIOS-lgpl-latest.bin (1.36), VGABIOS-lgpl-latest.debug.bin (1.36), + vgabios.c (1.42): + + - init functions rewitten in assembler + - function biosfn_set_display_code rewritten in assembler + +2004-04-05 19:40 vruppert + + * VGABIOS-lgpl-latest.bin (1.35), VGABIOS-lgpl-latest.debug.bin (1.35), + vgabios.c (1.41): + + - functions biosfn_get_video_mode() and biosfn_read_display_code() rewritten + in assembler + +2004-04-04 18:20 vruppert + + * VGABIOS-lgpl-latest.bin (1.34), VGABIOS-lgpl-latest.debug.bin (1.34), + vgabios.c (1.40): + + - write character function for CGA modes added + - read/write graphics pixel for CGA and LINEAR8 modes added + +2004-02-23 21:08 vruppert + + * VGABIOS-lgpl-latest.bin (1.33), VGABIOS-lgpl-latest.debug.bin (1.33), + vbe.c (1.39): + + - dispi_get_max_bpp(): restore the original value of the vbe enable register + +2004-02-22 14:17 vruppert + + * README (1.6), vbe.c (1.38), vbe.h (1.20), vbe_display_api.txt (1.9), + VGABIOS-lgpl-latest.bin (1.32), VGABIOS-lgpl-latest.debug.bin (1.32): + + - new function dispi_get_max_bpp() returns the bpp capabilities of the Bochs gui + - create the mode list depending on the supported bpp capability + - unused stuff removed + - documentation updated + +2004-02-21 18:20 vruppert + + * vbe.c (1.37), vbe.h (1.19), vbetables.h (1.23), + VGABIOS-lgpl-latest.bin (1.31), VGABIOS-lgpl-latest.debug.bin (1.31): + + - dynamicly genarated vbe mode_info list works now + +2003-11-17 21:04 vruppert + + * vbe.c (1.36), vbetables.h (1.22), vgabios.c (1.39), vgatables.h (1.6), + VGABIOS-lgpl-latest.bin (1.30), VGABIOS-lgpl-latest.debug.bin (1.30): + + - new VBE presence flag stored at unused BDA address 0xB9 + - VBE init code rewritten + - added BIOS TTY flag for VBE mode 0x0102 (TODO: scrolling) + - vgabios_init_func: load and activate text font already done by set_video_mode + - function biosfn_get_all_palette_reg() fixed + +2003-11-06 00:26 cbothamy + + * README (1.5): + + - add changes for 0.4c release + +2003-11-06 00:22 cbothamy + + * VGABIOS-lgpl-latest.bin (1.29), VGABIOS-lgpl-latest.debug.bin + (1.29): + + - compile vgabios.c rev1.38 + +2003-11-06 00:21 cbothamy + + * vgabios.c (1.38): + + - activate char table after loading it when setting a text video + mode + +2003-11-06 00:19 cbothamy + + * Makefile (1.12): + + - when making a release, remove unwanted files first, and exclude + CVS from the tarball + +2003-11-04 22:50 cbothamy + + * ChangeLog (1.20, v0_4b): + + - update ChangeLog for 0.4b release + +2003-11-04 22:49 cbothamy + + * README (1.4, v0_4b): + + - update Changes for 0.4b release + +2003-11-04 20:26 vruppert + + * vgabios.c (1.37), VGABIOS-lgpl-latest.bin (1.28), + VGABIOS-lgpl-latest.debug.bin (1.28) (utags: v0_4b): + + - biosfn_get_font_info(): character height must be returned in CX + +2003-11-03 21:57 vruppert + + * vbe.c (1.35, v0_4b), vgabios.c (1.36), VGABIOS-lgpl-latest.bin + (1.27), VGABIOS-lgpl-latest.debug.bin (1.27): + + - the 'noclearmem' flag is not stored in the 'current video mode' + register (0040h:0049h) - VBE also stores the 'noclear' flag in + the 'video control' register (0040h:0087h) + +2003-10-05 10:06 vruppert + + * vbe.h (1.18, v0_4b), vbe_display_api.txt (1.8, v0_4b), + VGABIOS-lgpl-latest.bin (1.26), VGABIOS-lgpl-latest.debug.bin + (1.26): + + - changed VBE i/o registers to 0x01CE/CF (suggestion from Daniel + Gimpelevich) + +2003-08-18 18:38 vruppert + + * VGABIOS-lgpl-latest.bin (1.25), VGABIOS-lgpl-latest.debug.bin + (1.25), vgabios.c (1.35): + + - wrong offsets to the character tables (INT 0x1F/0x43) fixed + (underscore added) - functions accessing the CRT controller + optimized using a local variable 'crtc_addr' + +2003-08-17 15:46 cbothamy + + * ChangeLog (1.19, v0_4a): + + - ChangeLog is now automatically generated by running "cvs2cl -r + -t -P -S" - update ChangeLog for 0.4a release + +2003-08-17 15:44 cbothamy + + * README (1.3, v0_4a): + + - added the old ChangeLog in the HOSTORY section of the README + file - update History for 0.4a release, with a summary of Changes + +2003-08-17 15:24 cbothamy + + * Makefile (1.11, v0_4b, v0_4a): + + - fix Makefile for "release" target + +2003-08-16 01:49 cbothamy + + * Makefile (1.10), README (1.2), VGABIOS-lgpl-latest.bin (1.24, + v0_4a), VGABIOS-lgpl-latest.debug.bin (1.24, v0_4a), vgabios.c + (1.34, v0_4a): + + - update the Makefile for releases - remove references to old + plex86 website - update the Makefile so it build + VGABIOS-lgpl-latest.bin and VGABIOS-lgpl-latest.debug.bin + +2003-08-07 18:17 vruppert + + * VGABIOS-lgpl-latest.bin (1.23), VGABIOS-lgpl-latest.debug.bin + (1.23): + + - current VBE mode now stored in BDA (unused address 0xBA) + +2003-08-07 17:54 vruppert + + * vbe.c (1.34), vgatables.h (1.5, v0_4b) (utags: v0_4a): + + - current VBE mode now stored in BDA (unused address 0xBA) + +2003-07-20 18:05 vruppert + + * vgabios.c (1.33), VGABIOS-lgpl-latest.bin (1.22), + VGABIOS-lgpl-latest.debug.bin (1.22): + + - fixed a few functions accessing the attribute controller + +2003-07-19 09:33 vruppert + + * vgabios.c (1.32), VGABIOS-lgpl-latest.bin (1.21), + VGABIOS-lgpl-latest.debug.bin (1.21): + + - re-enable video after programming the attribute controller - + biosfn_set_all_palette_reg(): number of palette registers fixed + +2003-07-16 22:32 vruppert + + * ChangeLog (1.18), vbe.c (1.33), vbe.h (1.17, v0_4a), + vbe_display_api.txt (1.7, v0_4a), vgabios.c (1.31), + VGABIOS-lgpl-latest.bin (1.20), VGABIOS-lgpl-latest.debug.bin + (1.20): + + - LFB flag now stored in the register VBE_DISPI_INDEX_ENABLE - + release date in Changelog fixed - release date of VBE BIOS 0.6 + was the same as VGA BIOS 0.3b - year changed in copyright + messages + +2003-07-15 12:40 vruppert + + * VGABIOS-lgpl-latest.bin (1.19), VGABIOS-lgpl-latest.debug.bin + (1.19): + + - new function dispi_get_bpp() - function + vbe_biosfn_set_get_logical_scan_line_length() fixed for >8bpp - + number of image pages of all VBE modes fixed + +2003-07-15 12:35 vruppert + + * vbe.c (1.32), vbetables.h (1.21, v0_4b, v0_4a): + + - new function dispi_get_bpp() - function + vbe_biosfn_set_get_logical_scan_line_length() fixed for >8bpp - + number of image pages of all VBE modes fixed + +2003-07-14 19:45 vruppert + + * vbe_display_api.txt (1.6): + + - description of VBE_DISPI_ interface 0xb0c2 added + +2003-07-10 19:07 vruppert + + * vbe.c (1.31), vbetables.h (1.20), VGABIOS-lgpl-latest.bin (1.18), + VGABIOS-lgpl-latest.debug.bin (1.18): + + - 15 bpp VBE modes added - "Bochs own" mode 0x142 (640x480x32bpp) + added + +2003-07-01 19:00 vruppert + + * vbe.c (1.30), vbe.h (1.16), vbetables.h (1.19), + VGABIOS-lgpl-latest.bin (1.17), VGABIOS-lgpl-latest.debug.bin + (1.17): + + - VBE preserve display memory feature implemented - VBE mode + entries 0x117 and 0x118 added + +2003-06-30 21:27 vruppert + + * vbe.c (1.29), vbe.h (1.15), vbetables.h (1.18), + VGABIOS-lgpl-latest.bin (1.16), VGABIOS-lgpl-latest.debug.bin + (1.16): + + - VBE mode info blocks of modes with >8bpp enabled - VBE modes + with 24 bpp: bytes per scanline fixed - vbe_biosfn_set_mode() now + supports >8bpp - VBE will be enabled with new VBE_DISPI_ID2 + (0xB0C2) + +2003-06-29 12:53 vruppert + + * vbetables.h (1.17), VGABIOS-lgpl-latest.bin (1.15), + VGABIOS-lgpl-latest.debug.bin (1.15): + + - duplicate lines with VBE_MODE_ATTRIBUTE_GRAPHICS_MODE removed - + VBE mode info items of currently unsupported modes fixed + +2003-06-15 21:19 vruppert + + * vgabios.c (1.30), VGABIOS-lgpl-latest.bin (1.14), + VGABIOS-lgpl-latest.debug.bin (1.14): + + - function write_gfx_char() rewritten + +2003-04-26 09:27 vruppert + + * VGABIOS-lgpl-latest.debug.bin (1.13): + + - added missing VBE function dispi_get_bank() - added missing + return codes for VBE function 4F05h - memory size is always + reported in VBE function 4F00h - fixed scan line length for VBE + mode 0102h - fixed function set_active_page() for graphics modes + - fixed the page sizes of some VGA modes + +2003-04-26 09:22 vruppert + + * vbe.c (1.28), vbetables.h (1.16), vgabios.c (1.29), vgatables.h + (1.4), VGABIOS-lgpl-latest.bin (1.13): + + - added missing VBE function dispi_get_bank() - added missing + return codes for VBE function 4F05h - memory size is always + reported in VBE function 4F00h - fixed scan line length for VBE + mode 0102h - fixed function set_active_page() for graphics modes + - fixed the page sizes of some VGA modes + +2003-04-20 09:51 vruppert + + * vgabios.c (1.28), vgatables.h (1.3), VGABIOS-lgpl-latest.bin + (1.12), VGABIOS-lgpl-latest.debug.bin (1.12): + + - function write_gfx_char() now supports different font sizes - + some entries of the static functionality table fixed + +2003-04-18 09:23 vruppert + + * vbe.c (1.27), vbe.h (1.14), vbetables.h (1.15): + + - applied patch #1331 * new function dispi_set_bank_farcall() + * VBE mode info item WinFuncPtr points to the new function if the + flag VBE_WINDOW_ATTRIBUTE_RELOCATABLE is set * flag + VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE added + +2003-02-11 20:17 vruppert + + * VGABIOS-lgpl-latest.bin (1.11), VGABIOS-lgpl-latest.debug.bin + (1.11), vbe.c (1.26), vbetables.h (1.14): + + - VBE mode search rewritten * improved function + mode_info_find_mode() is now used by the VBE functions 0x4F01 + and 0x4F02 * removed all mode list entries with the LFB bit + set. LFB detection is now present in the function + mode_info_find_mode() + +2003-02-09 20:59 vruppert + + * VGABIOS-lgpl-latest.bin (1.10), VGABIOS-lgpl-latest.debug.bin + (1.10), vgabios.c (1.27): + + - function write_gfx_char(): memory address now calculated in + this function; background color is always black - function + biosfn_write_char_attr(): the count parameter is now used in + graphics modes too - function biosfn_write_char_only() works + the same way as function biosfn_write_char_attr() in graphics + mode - copying charmap data optimized using memcpyb() + +2003-02-09 11:36 vruppert + + * VGABIOS-lgpl-latest.bin (1.9), VGABIOS-lgpl-latest.debug.bin + (1.9): + + - VESA mode 0x102 added (uses existing SVGA mode 0x6a) - all VESA + modes with the LFB flag set removed from the list (Linux doesn't + like mode numbers > 0x07ff) + +2003-02-09 11:02 vruppert + + * vbe.c (1.25), vbe.h (1.13), vbetables.h (1.13): + + - VESA mode 0x102 added (uses existing SVGA mode 0x6a) - all VESA + modes with the LFB flag set removed from the list (Linux doesn't + like mode numbers > 0x07ff) + +2003-02-08 13:04 vruppert + + * vbe.c (1.24), vgabios.c (1.26): + + - vbe_biosfn_return_current_mode() now returns the active + standard VGA mode TODO: return VESA mode if enabled - + biosfn_set_video_mode() now clears the screen in CGA mode + correctly - write character functions are now working in all + PLANAR4 graphics modes - added stubs for unimplemented features + in graphics modes + +2003-02-04 22:19 vruppert + + * VGABIOS-lgpl-latest.bin (1.8), VGABIOS-lgpl-latest.debug.bin + (1.8): + + - set video mode: clear vga memory in graphics mode - set video + mode: load default font in text mode - write character + implemented for graphics mode 0x12 + +2003-02-04 22:06 vruppert + + * vgabios.c (1.25): + + - set video mode: clear vga memory in graphics mode - set video + mode: load default font in text mode - write character + implemented for graphics mode 0x12 + +2003-01-21 19:30 vruppert + + * vgabios.c (1.24): + + - remap the cursor size if the char height is > 8 and the new + values are < 8 + +2003-01-20 18:24 cbothamy + + * Makefile (1.9): + + - fix so make -j2 does not overwrite temp files + +2003-01-19 12:35 vruppert + + * vgabios.c (1.23): + + - function set_scan_lines() recalculates the number of rows and + the page size - new values for char height, text rows and page + size are stored in the BIOS data segment - asm helper function + idiv_u added + +2003-01-15 18:49 cbothamy + + * VGABIOS-lgpl-latest.bin (1.7), VGABIOS-lgpl-latest.debug.bin + (1.7): + + - compile vgabios rev 1.22 + +2003-01-15 18:49 cbothamy + + * vgabios.c (1.22): + + - fix bug found by ams : a 8bits index value was compared to + 0x100 in some cases in biosfn_set_all_dac_reg, + biosfn_read_all_dac_reg, biosfn_perform_gray_scale_summing + +2003-01-15 17:34 cbothamy + + * Makefile (1.8): + + - fix symbol table file names, discovered by ams + +2003-01-04 21:20 vruppert + + * VGABIOS-lgpl-latest.bin (1.6), VGABIOS-lgpl-latest.debug.bin + (1.6), vgabios.c (1.21): + + - biosfn_set_video_mode(): reset attribute controller flip-flop + before setting up the controller's registers (bug found with + amidiag) + +2003-01-04 09:50 vruppert + + * vbe.c (1.23): + + - VBE function 0x00 returns VBE 1.x compatible information if no + VBE signature is present + +2003-01-01 12:44 vruppert + + * VGABIOS-lgpl-latest.bin (1.5), VGABIOS-lgpl-latest.debug.bin + (1.5): + + - SVGA mode 0x6A (800x600x4) added to the list of graphics modes + +2002-12-31 18:07 vruppert + + * vgatables.h (1.2): + + - SVGA mode 0x6A (800x600x4) added to the list of graphics modes + +2002-11-23 10:38 cbothamy + + * ChangeLog (1.17, v0_3b): + + - fix changelog for 0.3b release + +2002-10-20 17:12 vruppert + + * VGABIOS-lgpl-latest.bin (1.4), VGABIOS-lgpl-latest.debug.bin + (1.4), vgabios.c (1.20) (utags: v0_3b): + + - new function set_scan_lines() for the font size change (patch + from Hartmut Birr) - cursor shape start and end must be updated + in set_scan_lines() - set_scan_lines() is called by the functions + 0x1110, 0x1111, 0x1112 and 0x1114 after copying the font data + +2002-10-04 08:20 vruppert + + * VGABIOS-lgpl-latest.bin (1.3), VGABIOS-lgpl-latest.debug.bin + (1.3), vgabios.c (1.19): + + - biosfn_set_single_dac_reg(): the red value is stored in DH + +2002-09-19 19:05 cbothamy + + * VGABIOS-lgpl-latest.bin (1.2), VGABIOS-lgpl-latest.debug.bin + (1.2): + + - updated with latest changes + +2002-09-19 19:03 cbothamy + + * ChangeLog (1.16), Makefile (1.7, v0_3b), vbe.c (1.22, v0_3b), + vgabios.c (1.18), vgabios.h (1.3, v0_4b, v0_4a, v0_3b): + + - updated the Makefile - removed display of copyrights. - + changed the Copyright string to "LGPL VGABios developers" + +2002-09-08 21:14 vruppert + + * vgabios.c (1.17): + + - set the cursor shape depending on the current font height - + clear BL before calling int 0x10 function 0x1103 in + vgabios_init_func + +2002-08-23 22:58 cbothamy + + * vbe.c (1.21), vbetables.h (1.12, v0_3b): + + - added lfb-mode numbers (patch from mathis) + +2002-07-21 21:57 japj + + * vbe.c (1.20), vgabios.c (1.16): + + gcc2/3 preprocessing fix + +2002-05-18 16:55 cbothamy + + * vgabios.c (1.15): + + - include patch from Volker that adds some text font functions + +2002-05-01 23:13 japj + + * VGABIOS-lgpl-latest.bin (1.1), VGABIOS-lgpl-latest.debug.bin + (1.1): + + adding latest bin & debug bin of the vgabios + +2002-04-29 14:50 japj + + * ChangeLog (1.15), vbe.c (1.19), vbe.h (1.12, v0_3b), vbetables.h + (1.11), vgabios.c (1.14): + + - applying hw scrolling/multibuffering patch + +2002-04-25 21:59 japj + + * Makefile (1.6), vbe.c (1.18), vgabios.c (1.13): + + - reverting #asm/##asm & endasm patch (does not work with with + cygwin) + +2002-04-19 19:38 japj + + * Makefile (1.5), vbe.c (1.17), vgabios.c (1.12): + + - fixing preprocessing of vgabios with latest gcc (from Mandrake + 8.2) + +2002-04-08 23:44 japj + + * ChangeLog (1.14), vbe_display_api.txt (1.5, v0_3b): + + - preparing docs for new DISPI interface (for hardware scrolling) + +2002-04-03 19:06 japj + + * ChangeLog (1.13), TODO (1.9, v0_4b, v0_4a, v0_3b), vbe.c (1.16): + + - defaulting LFB on + updated changelog & todo + +2002-04-03 00:38 cbothamy + + * vbe.c (1.15), vgabios.c (1.11): + + - changed the logging ports to 0x500 -> 0x502 + +2002-03-14 17:54 japj + + * vbe.c (1.14): + + - vbetables.h is dependant upon some defines (VBE_HAVE_LFB), so + put the include *after* the define + +2002-03-13 21:47 japj + + * ChangeLog (1.12), TODO (1.8), vbe.c (1.13), vbetables.h (1.10), + vgabios.c (1.10): + + - made LFB dependant upon define - not implement vbe functions + return failure - updated todo & docs for things after bochs 1.4 + +2002-03-13 19:46 japj + + * vbe.h (1.11), vbe_display_api.txt (1.4): + + - added max video memory + documented what is in the 0xb0c0 + interface + +2002-03-12 02:33 cbothamy + + * ChangeLog (1.11), Makefile (1.4): + + - updated for 0.3a. Merged vgabios.bin and vbebios.bin + +2002-03-10 21:36 japj + + * ChangeLog (1.10), vbetables.h (1.9): + + - added LFB modes for testing with vbe-lfb patch in Bochs + +2002-03-10 17:42 japj + + * vbe.c (1.12, v0_3a): + + - show people when they do NOT have VBE support available + +2002-03-10 17:36 japj + + * TODO (1.7, v0_3a), vbe.c (1.11), vbe.h (1.10, v0_3a), vgabios.c + (1.9, v0_3a): + + - cleanup of vbe internal functions (set 8bpp mode is now + dependant on ModeInfo content instead of hardcoded functions) + +2002-03-10 17:20 cbothamy + + * ChangeLog (1.9, v0_3a), TODO (1.6): + + - updated for 0.3a + +2002-03-10 17:19 cbothamy + + * vbe.c (1.10), vbe.h (1.9): + + - added vbe_has_vbe_display function that detects an attached vbe + display + +2002-03-10 17:12 cbothamy + + * vgabios.c (1.8): + + - vbe calls are done only if a vbe display is detected + +2002-03-10 11:25 japj + + * vbe.h (1.8), vbe_display_api.txt (1.3, v0_3a): + + - preparing for LFB support + +2002-03-09 14:25 japj + + * vgabios.c (1.7): + + - fixing initial cursor shape to _ instead of - + +2002-03-08 23:08 japj + + * ChangeLog (1.8), TODO (1.5), vbe.c (1.9), vbe.h (1.7), vgabios.c + (1.6): + + - updating vbe code to new API + +2002-03-08 21:48 japj + + * vbe.c (1.8), vbe.h (1.6), vbetables.h (1.8, v0_3a): + + - updating vbe code with #defines from API + +2002-03-08 21:31 japj + + * vbe_display_api.txt (1.2): + + - adding some text about how banks work + +2002-03-08 21:09 japj + + * ChangeLog (1.7), vbe_display_api.txt (1.1): + + - adding vbe_display_api documentation + +2002-03-07 21:36 japj + + * ChangeLog (1.6), vbe.c (1.7), vbetables.h (1.7): + + - added 1024x768xbpp support - some more cleanups/comments + +2002-03-06 21:55 japj + + * ChangeLog (1.5), TODO (1.4), vbe.c (1.6), vbetables.h (1.6), + vgabios.c (1.5): + + - updated changelog with new modi - added 640x480x8 (Mandrake + Installer can use this!) - added pre VBE2 compatible 'detection' + - fixed problem when normal vga set mode wouldn't disable vbe + mode + +2002-03-06 20:59 japj + + * TODO (1.3), vbe.c (1.5), vbe.h (1.5), vbetables.h (1.5), + vgabios.c (1.4): + + - adding 640x400x8 and 800x600x8 vbe support (this depends + HEAVILY on my bochs vga code patch - japj) + +2002-03-06 18:00 japj + + * vbe.c (1.4), vbe.h (1.4), vbetables.h (1.4): + + - implemented banked & lfb support for 320x200x8bpp (some fixes + for vbetest program not displaying anything) + +2002-03-05 20:25 japj + + * Makefile (1.3, v0_3a): + + for vbe debug bios: - print debugging information in assembly + output - print source code in assembly output + +2002-03-01 19:39 japj + + * ChangeLog (1.4), TODO (1.2), vbe.c (1.3), vbe.h (1.3), + vbetables.h (1.3): + + - added vbe support for 320x200x8 using the standard vgamode + (0x13) + +2002-02-19 00:29 japj + + * ChangeLog (1.3): + + - updating ChangeLog with lfbprof + +2002-02-18 23:26 japj + + * tests/lfbprof/: lfbprof.c (1.2), lfbprof.h (1.2) (utags: v0_3a, + v0_3b, v0_4a, v0_4b): + + - fixed unsigned short for mode list (-1 != 0xffff otherwise) - + fixed LfbMapRealPointer macro mask problem (some modes were + skipped) - added some extra 'debugging' printf's + +2002-02-18 23:07 japj + + * tests/lfbprof/: Makefile (1.1, v0_4b, v0_4a, v0_3b, v0_3a), + lfbprof.c (1.1), lfbprof.h (1.1): + + - Adding lfbprof testprogram (for vbe testing purposes) It + needs to be compiled with the Watcom C Compiler + +2002-02-18 18:48 japj + + * vbe.c (1.2), vbe.h (1.2): + + - cosmetic updates to vbe.c/h + added bunch of FIXMEs for work + that needs to be done + +2002-02-18 18:34 japj + + * vbetables.h (1.2): + + - cosmetic updates in vbetables.h + +2002-02-18 18:32 japj + + * ChangeLog (1.2): + + updated changelog with merge of vbebios 0.2 + +2002-02-18 18:07 japj + + * vgabios.c (1.3): + + - small cosmetic cleanup in vgabios vbe code + added FIXMEs + +2002-02-18 17:55 japj + + * Makefile (1.2), dataseghack (1.2, v0_4b, v0_4a, v0_3b, v0_3a), + vbe.c (1.1), vbe.h (1.1), vbetables.h (1.1), vgabios.c (1.2), + vgabios.h (1.2, v0_3a): + + - merging with vbebios 0.2 release + +2002-02-18 11:31 cbothamy + + * BUGS (1.1, v0_4b, v0_4a, v0_3b, v0_3a), COPYING (1.1, v0_4b, + v0_4a, v0_3b, v0_3a), ChangeLog (1.1), Makefile (1.1), Notes + (1.1, v0_4b, v0_4a, v0_3b, v0_3a), README (1.1, v0_3b, v0_3a), + TODO (1.1), dataseghack (1.1), vgabios.c (1.1), vgabios.h (1.1), + vgafonts.h (1.1, v0_4b, v0_4a, v0_3b, v0_3a), vgatables.h (1.1, + v0_3b, v0_3a), tests/testbios.c (1.1, v0_4b, v0_4a, v0_3b, + v0_3a): + + - initial import + diff --git a/src/VBox/Devices/Graphics/BIOS/Makefile.kmk b/src/VBox/Devices/Graphics/BIOS/Makefile.kmk new file mode 100644 index 00000000..3c7e504c --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/Makefile.kmk @@ -0,0 +1,201 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-Makefile for the New VGA BIOS ROM. +# + +# +# Copyright (C) 2012-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + +SUB_DEPTH = ../../../../.. +include $(KBUILD_PATH)/subheader.kmk + + +ifdef VBOX_WITH_OPEN_WATCOM + + # + # VBoxVgaBios - The VGA BIOS. + # + MISCBINS += VBoxVgaBios386 + VBoxVgaBios386_TEMPLATE = VBoxBios + VBoxVgaBios386_ASFLAGS = -0 + VBoxVgaBios386_CFLAGS = -3 + VBoxVgaBios386_DEFS = VBE VBOX_BIOS_CPU=80386 + VBoxVgaBios386_INCS = $(VBOX_GRAPHICS_INCS) + VBoxVgaBios386_SOURCES = \ + vgarom.asm \ + vberom.asm \ + vgabios.c \ + vbe.c + VBoxVgaBios386_LDFLAGS = \ + output raw offset=0xC0000 \ + order \ + clname CODE \ + segment VGAROM segaddr=0xC000 \ + segment _TEXT segaddr=0xC000 offset=0x9F0 \ + segment VBE32 segaddr=0xC000 offset=0x4640 \ + clname DATA \ + segment _DATA segaddr=0xC000 offset=0x4780 + + MISCBINS += VBoxVgaBios286 + VBoxVgaBios286_EXTENDS = VBoxVgaBios386 + VBoxVgaBios286_CFLAGS = -2 + VBoxVgaBios286_DEFS = $(filter-out VBOX_BIOS_CPU=80386,$(VBoxVgaBios386_DEFS)) VBOX_BIOS_CPU=80286 + + MISCBINS += VBoxVgaBios8086 + VBoxVgaBios8086_EXTENDS = VBoxVgaBios386 + VBoxVgaBios8086_CFLAGS = -0 + VBoxVgaBios8086_DEFS = $(filter-out VBOX_BIOS_CPU=80386,$(VBoxVgaBios386_DEFS)) VBOX_BIOS_CPU=8086 + + # + # Updates the alternative source file. + # + define def_VBoxVgaBiosUpdateAltSource + $$(PATH_SUB_CURRENT)/VBoxVgaBiosAlternative$(1).asm +| $$(PATH_SUB_CURRENT)/VBoxVgaBiosAlternative$(1).md5sum: \ + $$$$(VBoxVgaBios$(1)_1_TARGET) \ + $$(VBOX_MAKE_ALTERNATIVE_SOURCE) \ + $$(VBOX_VBOXCMP) + if1of ($$(KBUILD_TYPE), release) + $$(VBOX_MAKE_ALTERNATIVE_SOURCE) \ + --bios-image $$< \ + --bios-map $$(basename $$<).map \ + --bios-sym $$(basename $$<).sym \ + --bios-type vga \ + --output $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).asm + $$(QUIET)$$(TOOL_YASM_AS) -f bin \ + -o $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).bin \ + -l $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).lst \ + $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).asm + $$(VBOX_VBOXCMP) $$< $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).bin + $$(CP) --changed -- $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).asm $$(PATH_ROOT)/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative$(1).asm + $$(REDIRECT) -C $$(dir $$(VBoxVgaBios$(1)_1_TARGET)) -- \ + $$(MD5SUM_EXT) -bo $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).md5sum $$(notdir $$(VBoxVgaBios$(1)_1_TARGET)) + $$(CP) --changed -- $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).md5sum $$(PATH_ROOT)/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative$(1).md5sum + $$(RM) -f -- $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).asm \ + $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).bin \ + $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).lst \ + $$(VBoxVgaBios$(1)_0_OUTDIR)/VBoxVgaBiosAlternative$(1).md5sum + else + $$(QUIET)$$(ECHO) "Fatal error: Can only update VBoxVgaBiosAlternative$(1).asm/md5sum with a release build." + $$(QUIET)exit 1 + endif + endef + + $(evalcall2 def_VBoxVgaBiosUpdateAltSource,386) + $(evalcall2 def_VBoxVgaBiosUpdateAltSource,286) + $(evalcall2 def_VBoxVgaBiosUpdateAltSource,8086) + + update-vgabios-source: \ + $(PATH_SUB_CURRENT)/VBoxVgaBiosAlternative386.asm \ + $(PATH_SUB_CURRENT)/VBoxVgaBiosAlternative286.asm \ + $(PATH_SUB_CURRENT)/VBoxVgaBiosAlternative8086.asm + +endif # VBOX_WITH_OPEN_WATCOM + + +# +# The library containing the VGA BIOS image. +# +LIBRARIES += VgaBiosBin +VgaBiosBin_TEMPLATE = VBoxR3Dll +VgaBiosBin_DEFS = IN_VBOXDD2 +VgaBiosBin_SOURCES = +VgaBiosBin_DEPS = $(VgaBiosBin_0_OUTDIR)/vbetables.h +VgaBiosBin_CLEAN = $(VgaBiosBin_0_OUTDIR)/vbetables.h + +define def_VBoxVgaBiosBin + VgaBiosBin_SOURCES += $$(VgaBiosBin_0_OUTDIR)/VgaBiosBin$(1).c + VgaBiosBin_CLEAN += $$(VgaBiosBin_0_OUTDIR)/VgaBiosBin$(1).c + ifdef VBOX_WITH_OPEN_WATCOM + $$$$(VgaBiosBin_0_OUTDIR)/VgaBiosBin$(1).c: $$$$(VBoxVgaBios$(1)_1_TARGET) $$(VBOX_BIN2C) | $$$$(dir $$$$@) + $$(call MSG_TOOL,bin2c,VgaBiosBin,$$<,$$@) + $$(QUIET)$$(VBOX_BIN2C) -min 32 -max 36 -mask 0x0fff -ascii -export VgaBiosBinary$(1) $$< $$@ + else + VgaBiosBin_CLEAN += $$(VgaBiosBin_0_OUTDIR)/VBoxVgaBios$(1).rom + + $$$$(VgaBiosBin_0_OUTDIR)/VgaBiosBin$(1).c + $$$$(VgaBiosBin_0_OUTDIR)/VBoxVgaBios$(1).rom: \ + $$(PATH_SUB_CURRENT)/VBoxVgaBiosAlternative$(1).asm \ + $$(PATH_SUB_CURRENT)/VBoxVgaBiosAlternative$(1).md5sum \ + $$(VBOX_BIN2C) | $$$$(dir $$$$@) + $$(call MSG_TOOL,bin2c,VgaBiosBin,$$<,$$@) + $$(QUIET)$$(TOOL_YASM_AS) -f bin -o $$(VgaBiosBin_0_OUTDIR)/VBoxVgaBios$(1).rom $$< + $$(QUIET)$$(REDIRECT) -C $$(VgaBiosBin_0_OUTDIR) -- \ + $$(MD5SUM_EXT) -c $$(basename $$<).md5sum + $$(QUIET)$$(VBOX_BIN2C) -min 32 -max 36 -mask 0x0fff -ascii -export VgaBiosBinary$(1) $$(VgaBiosBin_0_OUTDIR)/VBoxVgaBios$(1).rom $$@ + $$(QUIET)$$(RM) -f -- $$$$(VgaBiosBin_0_OUTDIR)/VBoxVgaBios$(1).rom + endif +endef +$(evalcall2 def_VBoxVgaBiosBin,386) +$(evalcall2 def_VBoxVgaBiosBin,286) +$(evalcall2 def_VBoxVgaBiosBin,8086) + + +# Rule for making the vbetables.h that DevVGA uses. +$$(VgaBiosBin_0_OUTDIR)/vbetables.h: $(MAKEFILE_CURRENT) $$(vbetables-gen_1_TARGET) | $$(dir $$@) + $(QUIET)$(REDIRECT) -wo $@ -- $(vbetables-gen_1_TARGET) + + +# +# The VBE tables. +# +BLDPROGS += vbetables-gen +vbetables-gen_TEMPLATE = VBoxBldProg +vbetables-gen_SOURCES = vbetables-gen.c +vbetables-gen_CLEAN = $(vbetables-gen) + + +# +# The VGA BIOS Logo. +# +LIBRARIES += VgaDefBiosLogo +VgaDefBiosLogo_TEMPLATE = VBoxR3Dll +VgaDefBiosLogo_INCS = $(VBOX_PATH_DEVICES_SRC) +VgaDefBiosLogo_SOURCES = $(VgaDefBiosLogo_0_OUTDIR)/VgaDefBiosLogo.c +VgaDefBiosLogo_CLEAN = $(VgaDefBiosLogo_0_OUTDIR)/VgaDefBiosLogo.c +ifndef VBOX_OSE + VgaDefBiosLogo_SOURCES += $(VgaDefBiosLogo_0_OUTDIR)/VgaDefBiosLogoNY.c + VgaDefBiosLogo_CLEAN += $(VgaDefBiosLogo_0_OUTDIR)/VgaDefBiosLogoNY.c +endif + +# Rule for making the bios logo. +$$(VgaDefBiosLogo_0_OUTDIR)/VgaDefBiosLogo.c: $(VBOX_BRAND_BIOS_LOGO) $(VBOX_BIN2C) | $$(dir $$@) + $(call MSG_TOOL,bin2c,VgaDefBiosLogo,$<,$@) + $(QUIET)$(VBOX_BIN2C) VgaDefBiosLogo $< $@ + +# Rule for making the bios logo. +$$(VgaDefBiosLogo_0_OUTDIR)/VgaDefBiosLogoNY.c: $(PATH_ROOT)/src/VBox/Devices/Graphics/BIOS/puel_logo_ny.bmp $(VBOX_BIN2C) | $$(dir $$@) + $(call MSG_TOOL,bin2c,VgaDefBiosLogoNY,$<,$@) + $(QUIET)$(VBOX_BIN2C) VgaDefBiosLogoNY $< $@ + + +ifdef VBOX_WITH_OPEN_WATCOM + # + # Install the symbol file for the BIOS. + # + INSTALLS += VBoxVgaBiosSym + VBoxVgaBiosSym_TEMPLATE = VBoxDbgSyms + VBoxVgaBiosSym_SOURCES = \ + $(basename $(VBoxVgaBios386_1_TARGET)).sym \ + $(basename $(VBoxVgaBios286_1_TARGET)).sym \ + $(basename $(VBoxVgaBios8086_1_TARGET)).sym +endif + +include $(FILE_KBUILD_SUB_FOOTER) diff --git a/src/VBox/Devices/Graphics/BIOS/README b/src/VBox/Devices/Graphics/BIOS/README new file mode 100644 index 00000000..3b585e66 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/README @@ -0,0 +1,214 @@ +Plex86/Bochs VGABios +-------------------- + +The goal of this project is to have a LGPL'd Video Bios in plex86, +Bochs and qemu. +This VGA Bios is very specific to the emulated VGA card. +It is NOT meant to drive a physical vga card. + + +Cirrus SVGA extension +--------------------- + +The Cirrus SVGA extension is designed for the Cirrus emulation in Bochs and +qemu. The initial patch for the Cirrus extension has been written by Makoto +Suzuki (suzu). + + +Install +------- +To compile the VGA Bios you will need : +- gcc +- bcc +- as86 +- ld86 + +Untar the archive, and type make. You should get a "VGABIOS-lgpl-latest.bin" +file. Alternatively, you can use the binary file "VGABIOS-lgpl-latest.bin", +i have compiled for you. + +Edit your plex86/bochs conf file, and modify the load-rom command in the +VGA BIOS section, to point to the new vgabios image file. + + +Debugging +--------- +You can get a very basic debugging system: messages printed by the vgabios. +You have to register the "unmapped" device driver in plex86 or bochs, and make +sure it grabs port 0xfff0. + +Comment the #undef DEBUG at the beginning of vgabios.c. +You can then use the "printf" function in the bios. + + +Testing +------- +Look at the "testvga.c" file in the archive. This is a minimal Turbo C 2.0 +source file that calls a few int10 functions. Feel free to modify it to suit +your needs. + + +Copyright and License +--------------------- +This program has been written by Christophe Bothamy +It is protected by the GNU Lesser Public License, which you should +have received a copy of along with this package. + + +Reverse Engineering +------------------- +The VGA Bios has been written without reverse-engineering any existing Bios. + + +Acknowledgment +-------------- +The source code contains code ripped from rombios.c of plex86, written +by Kevin Lawton + +The source code contains fonts from fntcol16.zip (c) by Joseph Gil avalable at : +ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip +These fonts are public domain + +The source code is based on information taken from : +- Kevin Lawton's vga card emulation for bochs/plex86 +- Ralf Brown's interrupts list avalaible at + http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html +- Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/ +- Michael Abrash's Graphics Programming Black Book +- Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" + edited by sybex +- DOSEMU 1.0.1 source code for several tables values and formulas + + +Feedback +-------- +Please report any bugs, comments, patches for this VGA Bios to info@vruppert.de +You can find the latest release at : http://www.nongnu.org/vgabios/ +For any information on bochs, visit the website http://bochs.sourceforge.net/ +For any information on qemu, visit the website http://fabrice.bellard.free.fr/qemu/ + + +History +------- +vgabios-0.6a : Aug 19 2006 + - Volker + . added minimal support for the video parameter table (VPT) + . Cirrus SVGA now supports the "no clear" bit in Cirrus and VESA mode + . Bochs VBE protected mode interface improved + . save/restore video state support for Bochs VBE and standard VGA added + . generate vbetables.h dynamicly + . VBE video memory increased to 8 MB (VBE dispi ID changed to B0C4) + . lots of 4bpp VBE fixes (all 4bpp VBE modes now enabled) + . VGA compatible setup for VBE modes added + +vgabios-0.5d : Dec 29 2005 + - Volker + . Bochs VBE protected mode interface added (based on a patch by malc@pulsesoft.com) + . biossums utility now supports VGABIOS sizes up to 64 kBytes + . VGA mode 0x11: all color planes must be enabled in this 2-color VGA mode + +vgabios-0.5c : Jul 07 2005 + - Volker + . BIOS configuration word usually reports initial mode 80x25 color text + . vgabios function 0x0e (write teletype): linefeed (0x0a) only increments the + cursor row value + +vgabios-0.5b : May 24 2005 + - Volker + . fixed return value for the default case in the VBE section (non-debug mode) + . removed unused stuff + +vgabios-0.5a : Mar 07 2005 + - Volker + . Cirrus SVGA extension (initial patches from Makoto Suzuki, improvements + from Fabrice Bellard) + . vgabios image size is now exactly 32k with a checksum + . a lot of vgabios and vbe functions rewritten in assembler + . dynamicly generated VBE mode info list + . write character function for CGA and LINEAR8 modes + . read/write graphics pixel for some graphics modes + . text scroll feature for some graphics modes + . VBE 8-bit DAC support + +vgabios-0.4c : Nov 06 2003 + - Christophe + . fix font problem on initial screen of NT4 Loader + +vgabios-0.4b : Nov 04 2003 + - Volker + . fix offset of character tables + . optimizations of CRT controller accesses + . VBE i/o registers changed to 0x01CE/CF + (suggestion from Daniel Gimpelevich) + . "noclear" flag stored in BIOS area + . fix character height returned by get_font_info function + +vgabios-0.4a : Aug 17 2003 + - Volker + . VBE mode search rewritten (VBE modes with LFB bit removed) + . many bugfixes and optimizations + . write character function implemented for graphics modes + . support for 15bpp, 16bpp, 24bpp and 32bpp VBE modes added + . SVGA mode 0x6A added + . VBE modes 0x102, 0x117, 0x118 and 0x142 (Bochs specific) + +vgabios-0.3b : Nov 23 2002 + - Christophe + . added lfb-mode numbers (patch from mathis) + . updated the Makefile + . removed display of copyrights. + . changed the Copyright string to "LGPL VGABios developers" + - Volker + . set the cursor shape depending on the current font height + . clear BL before calling int 0x10 function 0x1103 in vgabios_init_func + . added some text font functions + - Jeroen + . Forced to new DISPI (0xb0c1) interface (requires latest bochs vbe code) + . Added multibuffering support + . Added new DISPI interface for: virt width, height, x offset, y offset + . Added LFB modes (to be used with the vbe-lfb patch in bochs) + see VBE_HAVE_LFB in vbe.c (currently default enabled) + . updated TODO & docs for changes after bochs 1.4 + +vgabios-0.3a : Mar 10 2002 + - Christophe + . Fixed bug in function ah=13 + - Jeroen + . updated vbebios implementation to new api + . added vbe_display_api documentation + . added 640x400x8, 640x480x8, 800x600x8, 1024x768 + (>640x480 needs a special bochs patch atm) + . added 320x200x8 vbe support (uses the standard 320x200x8 vga mode to + display, this allows for testing & having something on screen as well, + at least until bochs host side display is up & running) + . adding lfbprof (vbe) testprogram (+some small fixes to it) + . merging with vbebios 0.2 + +vgabios-0.2b : Nov 19 2001 + - Christophe + . Fixed bug in function ah=13 + +vgabios-0.2a : Nov 09 2001 + - Christophe + . Included bugfix from techt@pikeonline.net about grayscale summing + . Added the "IBM" string at org 0x1e as Bart Oldeman suggested + . Fixed DS and ES that where inverted in the int10 parameters list! + . The following have been implemented : + - function ax=1a00, ax=1a01, ah=1b + - function ax=1130 + . Added debug messages for unimplemented/unknown functions + Must be compiled with DEBUG defined. The output is trapped + by the unknown-ioport driver of plex/bochs (port 0xfff0 is used) + +vgabios-0.1a : May 8 2001 + - Christophe + . First release. The work has been focused only on text mode. + . The following have been implemented : + - inits + - int 10 handler + - functions ah=00, ah=01, ah=02, ah=03, ah=05, ah=06, ah=07, ah=08 + ah=09, ah=0a, ah=0e, ah=0f, ax=1000, ax=1001, ax=1002, ax=1003 + ax=1007, ax=1008, ax=1009, ax=1010, ax=1012, ax=1013, ax=1015 + ax=1017, ax=1018, ax=1019, ax=101a, ax=101b, ah=12 bl=10, + ah=12 bl=30, ah=12 bl=31, ah=12 bl=32, ah=12 bl=33, ah=12 bl=34 + ah=13 diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm new file mode 100644 index 00000000..d805833f --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm @@ -0,0 +1,9250 @@ +; $Id: VBoxVgaBiosAlternative286.asm $ +;; @file +; Auto Generated source file. Do not edit. +; + +; +; Source file: vgarom.asm +; +; ============================================================================================ +; +; Copyright (C) 2001,2002 the LGPL VGABios developers Team +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this library; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; ============================================================================================ +; +; This VGA Bios is specific to the plex86/bochs Emulated VGA card. +; You can NOT drive any physical vga card with it. +; +; ============================================================================================ +; + +; +; Source file: vberom.asm +; +; ============================================================================================ +; +; Copyright (C) 2002 Jeroen Janssen +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this library; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; ============================================================================================ +; +; This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +; You can NOT drive any physical vga card with it. +; +; ============================================================================================ +; +; This VBE Bios is based on information taken from : +; - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +; +; ============================================================================================ + +; +; Source file: vgabios.c +; +; // ============================================================================================ +; +; vgabios.c +; +; // ============================================================================================ +; // +; // Copyright (C) 2001,2002 the LGPL VGABios developers Team +; // +; // This library is free software; you can redistribute it and/or +; // modify it under the terms of the GNU Lesser General Public +; // License as published by the Free Software Foundation; either +; // version 2 of the License, or (at your option) any later version. +; // +; // This library is distributed in the hope that it will be useful, +; // but WITHOUT ANY WARRANTY; without even the implied warranty of +; // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; // Lesser General Public License for more details. +; // +; // You should have received a copy of the GNU Lesser General Public +; // License along with this library; if not, write to the Free Software +; // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; // +; // ============================================================================================ +; // +; // This VGA Bios is specific to the plex86/bochs Emulated VGA card. +; // You can NOT drive any physical vga card with it. +; // +; // ============================================================================================ +; // +; // This file contains code ripped from : +; // - rombios.c of plex86 +; // +; // This VGA Bios contains fonts from : +; // - fntcol16.zip (c) by Joseph Gil avalable at : +; // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip +; // These fonts are public domain +; // +; // This VGA Bios is based on information taken from : +; // - Kevin Lawton's vga card emulation for bochs/plex86 +; // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html +; // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/ +; // - Michael Abrash's Graphics Programming Black Book +; // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex +; // - DOSEMU 1.0.1 source code for several tables values and formulas +; // +; // Thanks for patches, comments and ideas to : +; // - techt@pikeonline.net +; // +; // ============================================================================================ + +; +; Source file: vbe.c +; +; // ============================================================================================ +; // +; // Copyright (C) 2002 Jeroen Janssen +; // +; // This library is free software; you can redistribute it and/or +; // modify it under the terms of the GNU Lesser General Public +; // License as published by the Free Software Foundation; either +; // version 2 of the License, or (at your option) any later version. +; // +; // This library is distributed in the hope that it will be useful, +; // but WITHOUT ANY WARRANTY; without even the implied warranty of +; // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; // Lesser General Public License for more details. +; // +; // You should have received a copy of the GNU Lesser General Public +; // License along with this library; if not, write to the Free Software +; // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; // +; // ============================================================================================ +; // +; // This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +; // You can NOT drive any physical vga card with it. +; // +; // ============================================================================================ +; // +; // This VBE Bios is based on information taken from : +; // - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +; // +; // ============================================================================================ + +; +; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice +; other than GPL or LGPL is available it will apply instead, Oracle elects to use only +; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where +; a choice of LGPL license versions is made available with the language indicating +; that LGPLv2 or any later version may be used, or where a choice of which version +; of the LGPL is applied is otherwise unspecified. +; + + + + + +section VGAROM progbits vstart=0x0 align=1 ; size=0x8fa class=CODE group=AUTO + ; disGetNextSymbol 0xc0000 LB 0x8fa -> off=0x28 cb=0000000000000548 uValue=00000000000c0028 'vgabios_int10_handler' + db 055h, 0aah, 040h, 0ebh, 01dh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 049h, 042h + db 04dh, 000h, 00eh, 01fh, 0fch, 0e9h, 03dh, 00ah +vgabios_int10_handler: ; 0xc0028 LB 0x548 + pushfw ; 9c ; 0xc0028 vgarom.asm:91 + cmp ah, 00fh ; 80 fc 0f ; 0xc0029 vgarom.asm:104 + jne short 00034h ; 75 06 ; 0xc002c vgarom.asm:105 + call 0017dh ; e8 4c 01 ; 0xc002e vgarom.asm:106 + jmp near 000edh ; e9 b9 00 ; 0xc0031 vgarom.asm:107 + cmp ah, 01ah ; 80 fc 1a ; 0xc0034 vgarom.asm:109 + jne short 0003fh ; 75 06 ; 0xc0037 vgarom.asm:110 + call 00532h ; e8 f6 04 ; 0xc0039 vgarom.asm:111 + jmp near 000edh ; e9 ae 00 ; 0xc003c vgarom.asm:112 + cmp ah, 00bh ; 80 fc 0b ; 0xc003f vgarom.asm:114 + jne short 0004ah ; 75 06 ; 0xc0042 vgarom.asm:115 + call 000efh ; e8 a8 00 ; 0xc0044 vgarom.asm:116 + jmp near 000edh ; e9 a3 00 ; 0xc0047 vgarom.asm:117 + cmp ax, 01103h ; 3d 03 11 ; 0xc004a vgarom.asm:119 + jne short 00055h ; 75 06 ; 0xc004d vgarom.asm:120 + call 00429h ; e8 d7 03 ; 0xc004f vgarom.asm:121 + jmp near 000edh ; e9 98 00 ; 0xc0052 vgarom.asm:122 + cmp ah, 012h ; 80 fc 12 ; 0xc0055 vgarom.asm:124 + jne short 00097h ; 75 3d ; 0xc0058 vgarom.asm:125 + cmp bl, 010h ; 80 fb 10 ; 0xc005a vgarom.asm:126 + jne short 00065h ; 75 06 ; 0xc005d vgarom.asm:127 + call 00436h ; e8 d4 03 ; 0xc005f vgarom.asm:128 + jmp near 000edh ; e9 88 00 ; 0xc0062 vgarom.asm:129 + cmp bl, 030h ; 80 fb 30 ; 0xc0065 vgarom.asm:131 + jne short 0006fh ; 75 05 ; 0xc0068 vgarom.asm:132 + call 00459h ; e8 ec 03 ; 0xc006a vgarom.asm:133 + jmp short 000edh ; eb 7e ; 0xc006d vgarom.asm:134 + cmp bl, 031h ; 80 fb 31 ; 0xc006f vgarom.asm:136 + jne short 00079h ; 75 05 ; 0xc0072 vgarom.asm:137 + call 004ach ; e8 35 04 ; 0xc0074 vgarom.asm:138 + jmp short 000edh ; eb 74 ; 0xc0077 vgarom.asm:139 + cmp bl, 032h ; 80 fb 32 ; 0xc0079 vgarom.asm:141 + jne short 00083h ; 75 05 ; 0xc007c vgarom.asm:142 + call 004ceh ; e8 4d 04 ; 0xc007e vgarom.asm:143 + jmp short 000edh ; eb 6a ; 0xc0081 vgarom.asm:144 + cmp bl, 033h ; 80 fb 33 ; 0xc0083 vgarom.asm:146 + jne short 0008dh ; 75 05 ; 0xc0086 vgarom.asm:147 + call 004ech ; e8 61 04 ; 0xc0088 vgarom.asm:148 + jmp short 000edh ; eb 60 ; 0xc008b vgarom.asm:149 + cmp bl, 034h ; 80 fb 34 ; 0xc008d vgarom.asm:151 + jne short 000e1h ; 75 4f ; 0xc0090 vgarom.asm:152 + call 00510h ; e8 7b 04 ; 0xc0092 vgarom.asm:153 + jmp short 000edh ; eb 56 ; 0xc0095 vgarom.asm:154 + cmp ax, 0101bh ; 3d 1b 10 ; 0xc0097 vgarom.asm:156 + je short 000e1h ; 74 45 ; 0xc009a vgarom.asm:157 + cmp ah, 010h ; 80 fc 10 ; 0xc009c vgarom.asm:158 + jne short 000a6h ; 75 05 ; 0xc009f vgarom.asm:162 + call 001a4h ; e8 00 01 ; 0xc00a1 vgarom.asm:164 + jmp short 000edh ; eb 47 ; 0xc00a4 vgarom.asm:165 + cmp ah, 04fh ; 80 fc 4f ; 0xc00a6 vgarom.asm:168 + jne short 000e1h ; 75 36 ; 0xc00a9 vgarom.asm:169 + cmp AL, strict byte 003h ; 3c 03 ; 0xc00ab vgarom.asm:170 + jne short 000b4h ; 75 05 ; 0xc00ad vgarom.asm:171 + call 007d2h ; e8 20 07 ; 0xc00af vgarom.asm:172 + jmp short 000edh ; eb 39 ; 0xc00b2 vgarom.asm:173 + cmp AL, strict byte 005h ; 3c 05 ; 0xc00b4 vgarom.asm:175 + jne short 000bdh ; 75 05 ; 0xc00b6 vgarom.asm:176 + call 007f7h ; e8 3c 07 ; 0xc00b8 vgarom.asm:177 + jmp short 000edh ; eb 30 ; 0xc00bb vgarom.asm:178 + cmp AL, strict byte 007h ; 3c 07 ; 0xc00bd vgarom.asm:180 + jne short 000c6h ; 75 05 ; 0xc00bf vgarom.asm:181 + call 00824h ; e8 60 07 ; 0xc00c1 vgarom.asm:182 + jmp short 000edh ; eb 27 ; 0xc00c4 vgarom.asm:183 + cmp AL, strict byte 008h ; 3c 08 ; 0xc00c6 vgarom.asm:185 + jne short 000cfh ; 75 05 ; 0xc00c8 vgarom.asm:186 + call 00858h ; e8 8b 07 ; 0xc00ca vgarom.asm:187 + jmp short 000edh ; eb 1e ; 0xc00cd vgarom.asm:188 + cmp AL, strict byte 009h ; 3c 09 ; 0xc00cf vgarom.asm:190 + jne short 000d8h ; 75 05 ; 0xc00d1 vgarom.asm:191 + call 0088fh ; e8 b9 07 ; 0xc00d3 vgarom.asm:192 + jmp short 000edh ; eb 15 ; 0xc00d6 vgarom.asm:193 + cmp AL, strict byte 00ah ; 3c 0a ; 0xc00d8 vgarom.asm:195 + jne short 000e1h ; 75 05 ; 0xc00da vgarom.asm:196 + call 008e6h ; e8 07 08 ; 0xc00dc vgarom.asm:197 + jmp short 000edh ; eb 0c ; 0xc00df vgarom.asm:198 + push ES ; 06 ; 0xc00e1 vgarom.asm:202 + push DS ; 1e ; 0xc00e2 vgarom.asm:203 + pushaw ; 60 ; 0xc00e3 vgarom.asm:107 + push CS ; 0e ; 0xc00e4 vgarom.asm:207 + pop DS ; 1f ; 0xc00e5 vgarom.asm:208 + cld ; fc ; 0xc00e6 vgarom.asm:209 + call 038d9h ; e8 ef 37 ; 0xc00e7 vgarom.asm:210 + popaw ; 61 ; 0xc00ea vgarom.asm:124 + pop DS ; 1f ; 0xc00eb vgarom.asm:213 + pop ES ; 07 ; 0xc00ec vgarom.asm:214 + popfw ; 9d ; 0xc00ed vgarom.asm:216 + iret ; cf ; 0xc00ee vgarom.asm:217 + cmp bh, 000h ; 80 ff 00 ; 0xc00ef vgarom.asm:222 + je short 000fah ; 74 06 ; 0xc00f2 vgarom.asm:223 + cmp bh, 001h ; 80 ff 01 ; 0xc00f4 vgarom.asm:224 + je short 0014bh ; 74 52 ; 0xc00f7 vgarom.asm:225 + retn ; c3 ; 0xc00f9 vgarom.asm:229 + push ax ; 50 ; 0xc00fa vgarom.asm:231 + push bx ; 53 ; 0xc00fb vgarom.asm:232 + push cx ; 51 ; 0xc00fc vgarom.asm:233 + push dx ; 52 ; 0xc00fd vgarom.asm:234 + push DS ; 1e ; 0xc00fe vgarom.asm:235 + mov dx, strict word 00040h ; ba 40 00 ; 0xc00ff vgarom.asm:236 + mov ds, dx ; 8e da ; 0xc0102 vgarom.asm:237 + mov dx, 003dah ; ba da 03 ; 0xc0104 vgarom.asm:238 + in AL, DX ; ec ; 0xc0107 vgarom.asm:239 + cmp byte [word 00049h], 003h ; 80 3e 49 00 03 ; 0xc0108 vgarom.asm:240 + jbe short 0013eh ; 76 2f ; 0xc010d vgarom.asm:241 + mov dx, 003c0h ; ba c0 03 ; 0xc010f vgarom.asm:242 + mov AL, strict byte 000h ; b0 00 ; 0xc0112 vgarom.asm:243 + out DX, AL ; ee ; 0xc0114 vgarom.asm:244 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0115 vgarom.asm:245 + and AL, strict byte 00fh ; 24 0f ; 0xc0117 vgarom.asm:246 + test AL, strict byte 008h ; a8 08 ; 0xc0119 vgarom.asm:247 + je short 0011fh ; 74 02 ; 0xc011b vgarom.asm:248 + add AL, strict byte 008h ; 04 08 ; 0xc011d vgarom.asm:249 + out DX, AL ; ee ; 0xc011f vgarom.asm:251 + mov CL, strict byte 001h ; b1 01 ; 0xc0120 vgarom.asm:252 + and bl, 010h ; 80 e3 10 ; 0xc0122 vgarom.asm:253 + mov dx, 003c0h ; ba c0 03 ; 0xc0125 vgarom.asm:255 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc0128 vgarom.asm:256 + out DX, AL ; ee ; 0xc012a vgarom.asm:257 + mov dx, 003c1h ; ba c1 03 ; 0xc012b vgarom.asm:258 + in AL, DX ; ec ; 0xc012e vgarom.asm:259 + and AL, strict byte 0efh ; 24 ef ; 0xc012f vgarom.asm:260 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc0131 vgarom.asm:261 + mov dx, 003c0h ; ba c0 03 ; 0xc0133 vgarom.asm:262 + out DX, AL ; ee ; 0xc0136 vgarom.asm:263 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc0137 vgarom.asm:264 + cmp cl, 004h ; 80 f9 04 ; 0xc0139 vgarom.asm:265 + jne short 00125h ; 75 e7 ; 0xc013c vgarom.asm:266 + mov AL, strict byte 020h ; b0 20 ; 0xc013e vgarom.asm:268 + out DX, AL ; ee ; 0xc0140 vgarom.asm:269 + mov dx, 003dah ; ba da 03 ; 0xc0141 vgarom.asm:271 + in AL, DX ; ec ; 0xc0144 vgarom.asm:272 + pop DS ; 1f ; 0xc0145 vgarom.asm:274 + pop dx ; 5a ; 0xc0146 vgarom.asm:275 + pop cx ; 59 ; 0xc0147 vgarom.asm:276 + pop bx ; 5b ; 0xc0148 vgarom.asm:277 + pop ax ; 58 ; 0xc0149 vgarom.asm:278 + retn ; c3 ; 0xc014a vgarom.asm:279 + push ax ; 50 ; 0xc014b vgarom.asm:281 + push bx ; 53 ; 0xc014c vgarom.asm:282 + push cx ; 51 ; 0xc014d vgarom.asm:283 + push dx ; 52 ; 0xc014e vgarom.asm:284 + mov dx, 003dah ; ba da 03 ; 0xc014f vgarom.asm:285 + in AL, DX ; ec ; 0xc0152 vgarom.asm:286 + mov CL, strict byte 001h ; b1 01 ; 0xc0153 vgarom.asm:287 + and bl, 001h ; 80 e3 01 ; 0xc0155 vgarom.asm:288 + mov dx, 003c0h ; ba c0 03 ; 0xc0158 vgarom.asm:290 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc015b vgarom.asm:291 + out DX, AL ; ee ; 0xc015d vgarom.asm:292 + mov dx, 003c1h ; ba c1 03 ; 0xc015e vgarom.asm:293 + in AL, DX ; ec ; 0xc0161 vgarom.asm:294 + and AL, strict byte 0feh ; 24 fe ; 0xc0162 vgarom.asm:295 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc0164 vgarom.asm:296 + mov dx, 003c0h ; ba c0 03 ; 0xc0166 vgarom.asm:297 + out DX, AL ; ee ; 0xc0169 vgarom.asm:298 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc016a vgarom.asm:299 + cmp cl, 004h ; 80 f9 04 ; 0xc016c vgarom.asm:300 + jne short 00158h ; 75 e7 ; 0xc016f vgarom.asm:301 + mov AL, strict byte 020h ; b0 20 ; 0xc0171 vgarom.asm:302 + out DX, AL ; ee ; 0xc0173 vgarom.asm:303 + mov dx, 003dah ; ba da 03 ; 0xc0174 vgarom.asm:305 + in AL, DX ; ec ; 0xc0177 vgarom.asm:306 + pop dx ; 5a ; 0xc0178 vgarom.asm:308 + pop cx ; 59 ; 0xc0179 vgarom.asm:309 + pop bx ; 5b ; 0xc017a vgarom.asm:310 + pop ax ; 58 ; 0xc017b vgarom.asm:311 + retn ; c3 ; 0xc017c vgarom.asm:312 + push DS ; 1e ; 0xc017d vgarom.asm:317 + mov ax, strict word 00040h ; b8 40 00 ; 0xc017e vgarom.asm:318 + mov ds, ax ; 8e d8 ; 0xc0181 vgarom.asm:319 + push bx ; 53 ; 0xc0183 vgarom.asm:320 + mov bx, strict word 00062h ; bb 62 00 ; 0xc0184 vgarom.asm:321 + mov al, byte [bx] ; 8a 07 ; 0xc0187 vgarom.asm:322 + pop bx ; 5b ; 0xc0189 vgarom.asm:323 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc018a vgarom.asm:324 + push bx ; 53 ; 0xc018c vgarom.asm:325 + mov bx, 00087h ; bb 87 00 ; 0xc018d vgarom.asm:326 + mov ah, byte [bx] ; 8a 27 ; 0xc0190 vgarom.asm:327 + and ah, 080h ; 80 e4 80 ; 0xc0192 vgarom.asm:328 + mov bx, strict word 00049h ; bb 49 00 ; 0xc0195 vgarom.asm:329 + mov al, byte [bx] ; 8a 07 ; 0xc0198 vgarom.asm:330 + db 00ah, 0c4h + ; or al, ah ; 0a c4 ; 0xc019a vgarom.asm:331 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc019c vgarom.asm:332 + mov ah, byte [bx] ; 8a 27 ; 0xc019f vgarom.asm:333 + pop bx ; 5b ; 0xc01a1 vgarom.asm:334 + pop DS ; 1f ; 0xc01a2 vgarom.asm:335 + retn ; c3 ; 0xc01a3 vgarom.asm:336 + cmp AL, strict byte 000h ; 3c 00 ; 0xc01a4 vgarom.asm:341 + jne short 001aah ; 75 02 ; 0xc01a6 vgarom.asm:342 + jmp short 0020bh ; eb 61 ; 0xc01a8 vgarom.asm:343 + cmp AL, strict byte 001h ; 3c 01 ; 0xc01aa vgarom.asm:345 + jne short 001b0h ; 75 02 ; 0xc01ac vgarom.asm:346 + jmp short 00229h ; eb 79 ; 0xc01ae vgarom.asm:347 + cmp AL, strict byte 002h ; 3c 02 ; 0xc01b0 vgarom.asm:349 + jne short 001b6h ; 75 02 ; 0xc01b2 vgarom.asm:350 + jmp short 00231h ; eb 7b ; 0xc01b4 vgarom.asm:351 + cmp AL, strict byte 003h ; 3c 03 ; 0xc01b6 vgarom.asm:353 + jne short 001bdh ; 75 03 ; 0xc01b8 vgarom.asm:354 + jmp near 00262h ; e9 a5 00 ; 0xc01ba vgarom.asm:355 + cmp AL, strict byte 007h ; 3c 07 ; 0xc01bd vgarom.asm:357 + jne short 001c4h ; 75 03 ; 0xc01bf vgarom.asm:358 + jmp near 0028ch ; e9 c8 00 ; 0xc01c1 vgarom.asm:359 + cmp AL, strict byte 008h ; 3c 08 ; 0xc01c4 vgarom.asm:361 + jne short 001cbh ; 75 03 ; 0xc01c6 vgarom.asm:362 + jmp near 002b4h ; e9 e9 00 ; 0xc01c8 vgarom.asm:363 + cmp AL, strict byte 009h ; 3c 09 ; 0xc01cb vgarom.asm:365 + jne short 001d2h ; 75 03 ; 0xc01cd vgarom.asm:366 + jmp near 002c2h ; e9 f0 00 ; 0xc01cf vgarom.asm:367 + cmp AL, strict byte 010h ; 3c 10 ; 0xc01d2 vgarom.asm:369 + jne short 001d9h ; 75 03 ; 0xc01d4 vgarom.asm:370 + jmp near 00307h ; e9 2e 01 ; 0xc01d6 vgarom.asm:371 + cmp AL, strict byte 012h ; 3c 12 ; 0xc01d9 vgarom.asm:373 + jne short 001e0h ; 75 03 ; 0xc01db vgarom.asm:374 + jmp near 00320h ; e9 40 01 ; 0xc01dd vgarom.asm:375 + cmp AL, strict byte 013h ; 3c 13 ; 0xc01e0 vgarom.asm:377 + jne short 001e7h ; 75 03 ; 0xc01e2 vgarom.asm:378 + jmp near 00348h ; e9 61 01 ; 0xc01e4 vgarom.asm:379 + cmp AL, strict byte 015h ; 3c 15 ; 0xc01e7 vgarom.asm:381 + jne short 001eeh ; 75 03 ; 0xc01e9 vgarom.asm:382 + jmp near 0038fh ; e9 a1 01 ; 0xc01eb vgarom.asm:383 + cmp AL, strict byte 017h ; 3c 17 ; 0xc01ee vgarom.asm:385 + jne short 001f5h ; 75 03 ; 0xc01f0 vgarom.asm:386 + jmp near 003aah ; e9 b5 01 ; 0xc01f2 vgarom.asm:387 + cmp AL, strict byte 018h ; 3c 18 ; 0xc01f5 vgarom.asm:389 + jne short 001fch ; 75 03 ; 0xc01f7 vgarom.asm:390 + jmp near 003d2h ; e9 d6 01 ; 0xc01f9 vgarom.asm:391 + cmp AL, strict byte 019h ; 3c 19 ; 0xc01fc vgarom.asm:393 + jne short 00203h ; 75 03 ; 0xc01fe vgarom.asm:394 + jmp near 003ddh ; e9 da 01 ; 0xc0200 vgarom.asm:395 + cmp AL, strict byte 01ah ; 3c 1a ; 0xc0203 vgarom.asm:397 + jne short 0020ah ; 75 03 ; 0xc0205 vgarom.asm:398 + jmp near 003e8h ; e9 de 01 ; 0xc0207 vgarom.asm:399 + retn ; c3 ; 0xc020a vgarom.asm:404 + cmp bl, 014h ; 80 fb 14 ; 0xc020b vgarom.asm:407 + jnbe short 00228h ; 77 18 ; 0xc020e vgarom.asm:408 + push ax ; 50 ; 0xc0210 vgarom.asm:409 + push dx ; 52 ; 0xc0211 vgarom.asm:410 + mov dx, 003dah ; ba da 03 ; 0xc0212 vgarom.asm:411 + in AL, DX ; ec ; 0xc0215 vgarom.asm:412 + mov dx, 003c0h ; ba c0 03 ; 0xc0216 vgarom.asm:413 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0219 vgarom.asm:414 + out DX, AL ; ee ; 0xc021b vgarom.asm:415 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc021c vgarom.asm:416 + out DX, AL ; ee ; 0xc021e vgarom.asm:417 + mov AL, strict byte 020h ; b0 20 ; 0xc021f vgarom.asm:418 + out DX, AL ; ee ; 0xc0221 vgarom.asm:419 + mov dx, 003dah ; ba da 03 ; 0xc0222 vgarom.asm:421 + in AL, DX ; ec ; 0xc0225 vgarom.asm:422 + pop dx ; 5a ; 0xc0226 vgarom.asm:424 + pop ax ; 58 ; 0xc0227 vgarom.asm:425 + retn ; c3 ; 0xc0228 vgarom.asm:427 + push bx ; 53 ; 0xc0229 vgarom.asm:432 + mov BL, strict byte 011h ; b3 11 ; 0xc022a vgarom.asm:433 + call 0020bh ; e8 dc ff ; 0xc022c vgarom.asm:434 + pop bx ; 5b ; 0xc022f vgarom.asm:435 + retn ; c3 ; 0xc0230 vgarom.asm:436 + push ax ; 50 ; 0xc0231 vgarom.asm:441 + push bx ; 53 ; 0xc0232 vgarom.asm:442 + push cx ; 51 ; 0xc0233 vgarom.asm:443 + push dx ; 52 ; 0xc0234 vgarom.asm:444 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc0235 vgarom.asm:445 + mov dx, 003dah ; ba da 03 ; 0xc0237 vgarom.asm:446 + in AL, DX ; ec ; 0xc023a vgarom.asm:447 + mov CL, strict byte 000h ; b1 00 ; 0xc023b vgarom.asm:448 + mov dx, 003c0h ; ba c0 03 ; 0xc023d vgarom.asm:449 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc0240 vgarom.asm:451 + out DX, AL ; ee ; 0xc0242 vgarom.asm:452 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0243 vgarom.asm:453 + out DX, AL ; ee ; 0xc0246 vgarom.asm:454 + inc bx ; 43 ; 0xc0247 vgarom.asm:455 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc0248 vgarom.asm:456 + cmp cl, 010h ; 80 f9 10 ; 0xc024a vgarom.asm:457 + jne short 00240h ; 75 f1 ; 0xc024d vgarom.asm:458 + mov AL, strict byte 011h ; b0 11 ; 0xc024f vgarom.asm:459 + out DX, AL ; ee ; 0xc0251 vgarom.asm:460 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0252 vgarom.asm:461 + out DX, AL ; ee ; 0xc0255 vgarom.asm:462 + mov AL, strict byte 020h ; b0 20 ; 0xc0256 vgarom.asm:463 + out DX, AL ; ee ; 0xc0258 vgarom.asm:464 + mov dx, 003dah ; ba da 03 ; 0xc0259 vgarom.asm:466 + in AL, DX ; ec ; 0xc025c vgarom.asm:467 + pop dx ; 5a ; 0xc025d vgarom.asm:469 + pop cx ; 59 ; 0xc025e vgarom.asm:470 + pop bx ; 5b ; 0xc025f vgarom.asm:471 + pop ax ; 58 ; 0xc0260 vgarom.asm:472 + retn ; c3 ; 0xc0261 vgarom.asm:473 + push ax ; 50 ; 0xc0262 vgarom.asm:478 + push bx ; 53 ; 0xc0263 vgarom.asm:479 + push dx ; 52 ; 0xc0264 vgarom.asm:480 + mov dx, 003dah ; ba da 03 ; 0xc0265 vgarom.asm:481 + in AL, DX ; ec ; 0xc0268 vgarom.asm:482 + mov dx, 003c0h ; ba c0 03 ; 0xc0269 vgarom.asm:483 + mov AL, strict byte 010h ; b0 10 ; 0xc026c vgarom.asm:484 + out DX, AL ; ee ; 0xc026e vgarom.asm:485 + mov dx, 003c1h ; ba c1 03 ; 0xc026f vgarom.asm:486 + in AL, DX ; ec ; 0xc0272 vgarom.asm:487 + and AL, strict byte 0f7h ; 24 f7 ; 0xc0273 vgarom.asm:488 + and bl, 001h ; 80 e3 01 ; 0xc0275 vgarom.asm:489 + sal bl, 003h ; c0 e3 03 ; 0xc0278 vgarom.asm:491 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc027b vgarom.asm:497 + mov dx, 003c0h ; ba c0 03 ; 0xc027d vgarom.asm:498 + out DX, AL ; ee ; 0xc0280 vgarom.asm:499 + mov AL, strict byte 020h ; b0 20 ; 0xc0281 vgarom.asm:500 + out DX, AL ; ee ; 0xc0283 vgarom.asm:501 + mov dx, 003dah ; ba da 03 ; 0xc0284 vgarom.asm:503 + in AL, DX ; ec ; 0xc0287 vgarom.asm:504 + pop dx ; 5a ; 0xc0288 vgarom.asm:506 + pop bx ; 5b ; 0xc0289 vgarom.asm:507 + pop ax ; 58 ; 0xc028a vgarom.asm:508 + retn ; c3 ; 0xc028b vgarom.asm:509 + cmp bl, 014h ; 80 fb 14 ; 0xc028c vgarom.asm:514 + jnbe short 002b3h ; 77 22 ; 0xc028f vgarom.asm:515 + push ax ; 50 ; 0xc0291 vgarom.asm:516 + push dx ; 52 ; 0xc0292 vgarom.asm:517 + mov dx, 003dah ; ba da 03 ; 0xc0293 vgarom.asm:518 + in AL, DX ; ec ; 0xc0296 vgarom.asm:519 + mov dx, 003c0h ; ba c0 03 ; 0xc0297 vgarom.asm:520 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc029a vgarom.asm:521 + out DX, AL ; ee ; 0xc029c vgarom.asm:522 + mov dx, 003c1h ; ba c1 03 ; 0xc029d vgarom.asm:523 + in AL, DX ; ec ; 0xc02a0 vgarom.asm:524 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc02a1 vgarom.asm:525 + mov dx, 003dah ; ba da 03 ; 0xc02a3 vgarom.asm:526 + in AL, DX ; ec ; 0xc02a6 vgarom.asm:527 + mov dx, 003c0h ; ba c0 03 ; 0xc02a7 vgarom.asm:528 + mov AL, strict byte 020h ; b0 20 ; 0xc02aa vgarom.asm:529 + out DX, AL ; ee ; 0xc02ac vgarom.asm:530 + mov dx, 003dah ; ba da 03 ; 0xc02ad vgarom.asm:532 + in AL, DX ; ec ; 0xc02b0 vgarom.asm:533 + pop dx ; 5a ; 0xc02b1 vgarom.asm:535 + pop ax ; 58 ; 0xc02b2 vgarom.asm:536 + retn ; c3 ; 0xc02b3 vgarom.asm:538 + push ax ; 50 ; 0xc02b4 vgarom.asm:543 + push bx ; 53 ; 0xc02b5 vgarom.asm:544 + mov BL, strict byte 011h ; b3 11 ; 0xc02b6 vgarom.asm:545 + call 0028ch ; e8 d1 ff ; 0xc02b8 vgarom.asm:546 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc02bb vgarom.asm:547 + pop bx ; 5b ; 0xc02bd vgarom.asm:548 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc02be vgarom.asm:549 + pop ax ; 58 ; 0xc02c0 vgarom.asm:550 + retn ; c3 ; 0xc02c1 vgarom.asm:551 + push ax ; 50 ; 0xc02c2 vgarom.asm:556 + push bx ; 53 ; 0xc02c3 vgarom.asm:557 + push cx ; 51 ; 0xc02c4 vgarom.asm:558 + push dx ; 52 ; 0xc02c5 vgarom.asm:559 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc02c6 vgarom.asm:560 + mov CL, strict byte 000h ; b1 00 ; 0xc02c8 vgarom.asm:561 + mov dx, 003dah ; ba da 03 ; 0xc02ca vgarom.asm:563 + in AL, DX ; ec ; 0xc02cd vgarom.asm:564 + mov dx, 003c0h ; ba c0 03 ; 0xc02ce vgarom.asm:565 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc02d1 vgarom.asm:566 + out DX, AL ; ee ; 0xc02d3 vgarom.asm:567 + mov dx, 003c1h ; ba c1 03 ; 0xc02d4 vgarom.asm:568 + in AL, DX ; ec ; 0xc02d7 vgarom.asm:569 + mov byte [es:bx], al ; 26 88 07 ; 0xc02d8 vgarom.asm:570 + inc bx ; 43 ; 0xc02db vgarom.asm:571 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc02dc vgarom.asm:572 + cmp cl, 010h ; 80 f9 10 ; 0xc02de vgarom.asm:573 + jne short 002cah ; 75 e7 ; 0xc02e1 vgarom.asm:574 + mov dx, 003dah ; ba da 03 ; 0xc02e3 vgarom.asm:575 + in AL, DX ; ec ; 0xc02e6 vgarom.asm:576 + mov dx, 003c0h ; ba c0 03 ; 0xc02e7 vgarom.asm:577 + mov AL, strict byte 011h ; b0 11 ; 0xc02ea vgarom.asm:578 + out DX, AL ; ee ; 0xc02ec vgarom.asm:579 + mov dx, 003c1h ; ba c1 03 ; 0xc02ed vgarom.asm:580 + in AL, DX ; ec ; 0xc02f0 vgarom.asm:581 + mov byte [es:bx], al ; 26 88 07 ; 0xc02f1 vgarom.asm:582 + mov dx, 003dah ; ba da 03 ; 0xc02f4 vgarom.asm:583 + in AL, DX ; ec ; 0xc02f7 vgarom.asm:584 + mov dx, 003c0h ; ba c0 03 ; 0xc02f8 vgarom.asm:585 + mov AL, strict byte 020h ; b0 20 ; 0xc02fb vgarom.asm:586 + out DX, AL ; ee ; 0xc02fd vgarom.asm:587 + mov dx, 003dah ; ba da 03 ; 0xc02fe vgarom.asm:589 + in AL, DX ; ec ; 0xc0301 vgarom.asm:590 + pop dx ; 5a ; 0xc0302 vgarom.asm:592 + pop cx ; 59 ; 0xc0303 vgarom.asm:593 + pop bx ; 5b ; 0xc0304 vgarom.asm:594 + pop ax ; 58 ; 0xc0305 vgarom.asm:595 + retn ; c3 ; 0xc0306 vgarom.asm:596 + push ax ; 50 ; 0xc0307 vgarom.asm:601 + push dx ; 52 ; 0xc0308 vgarom.asm:602 + mov dx, 003c8h ; ba c8 03 ; 0xc0309 vgarom.asm:603 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc030c vgarom.asm:604 + out DX, AL ; ee ; 0xc030e vgarom.asm:605 + mov dx, 003c9h ; ba c9 03 ; 0xc030f vgarom.asm:606 + pop ax ; 58 ; 0xc0312 vgarom.asm:607 + push ax ; 50 ; 0xc0313 vgarom.asm:608 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc0314 vgarom.asm:609 + out DX, AL ; ee ; 0xc0316 vgarom.asm:610 + db 08ah, 0c5h + ; mov al, ch ; 8a c5 ; 0xc0317 vgarom.asm:611 + out DX, AL ; ee ; 0xc0319 vgarom.asm:612 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc031a vgarom.asm:613 + out DX, AL ; ee ; 0xc031c vgarom.asm:614 + pop dx ; 5a ; 0xc031d vgarom.asm:615 + pop ax ; 58 ; 0xc031e vgarom.asm:616 + retn ; c3 ; 0xc031f vgarom.asm:617 + push ax ; 50 ; 0xc0320 vgarom.asm:622 + push bx ; 53 ; 0xc0321 vgarom.asm:623 + push cx ; 51 ; 0xc0322 vgarom.asm:624 + push dx ; 52 ; 0xc0323 vgarom.asm:625 + mov dx, 003c8h ; ba c8 03 ; 0xc0324 vgarom.asm:626 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0327 vgarom.asm:627 + out DX, AL ; ee ; 0xc0329 vgarom.asm:628 + pop dx ; 5a ; 0xc032a vgarom.asm:629 + push dx ; 52 ; 0xc032b vgarom.asm:630 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc032c vgarom.asm:631 + mov dx, 003c9h ; ba c9 03 ; 0xc032e vgarom.asm:632 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0331 vgarom.asm:634 + out DX, AL ; ee ; 0xc0334 vgarom.asm:635 + inc bx ; 43 ; 0xc0335 vgarom.asm:636 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0336 vgarom.asm:637 + out DX, AL ; ee ; 0xc0339 vgarom.asm:638 + inc bx ; 43 ; 0xc033a vgarom.asm:639 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc033b vgarom.asm:640 + out DX, AL ; ee ; 0xc033e vgarom.asm:641 + inc bx ; 43 ; 0xc033f vgarom.asm:642 + dec cx ; 49 ; 0xc0340 vgarom.asm:643 + jne short 00331h ; 75 ee ; 0xc0341 vgarom.asm:644 + pop dx ; 5a ; 0xc0343 vgarom.asm:645 + pop cx ; 59 ; 0xc0344 vgarom.asm:646 + pop bx ; 5b ; 0xc0345 vgarom.asm:647 + pop ax ; 58 ; 0xc0346 vgarom.asm:648 + retn ; c3 ; 0xc0347 vgarom.asm:649 + push ax ; 50 ; 0xc0348 vgarom.asm:654 + push bx ; 53 ; 0xc0349 vgarom.asm:655 + push dx ; 52 ; 0xc034a vgarom.asm:656 + mov dx, 003dah ; ba da 03 ; 0xc034b vgarom.asm:657 + in AL, DX ; ec ; 0xc034e vgarom.asm:658 + mov dx, 003c0h ; ba c0 03 ; 0xc034f vgarom.asm:659 + mov AL, strict byte 010h ; b0 10 ; 0xc0352 vgarom.asm:660 + out DX, AL ; ee ; 0xc0354 vgarom.asm:661 + mov dx, 003c1h ; ba c1 03 ; 0xc0355 vgarom.asm:662 + in AL, DX ; ec ; 0xc0358 vgarom.asm:663 + and bl, 001h ; 80 e3 01 ; 0xc0359 vgarom.asm:664 + jne short 0036bh ; 75 0d ; 0xc035c vgarom.asm:665 + and AL, strict byte 07fh ; 24 7f ; 0xc035e vgarom.asm:666 + sal bh, 007h ; c0 e7 07 ; 0xc0360 vgarom.asm:668 + db 00ah, 0c7h + ; or al, bh ; 0a c7 ; 0xc0363 vgarom.asm:678 + mov dx, 003c0h ; ba c0 03 ; 0xc0365 vgarom.asm:679 + out DX, AL ; ee ; 0xc0368 vgarom.asm:680 + jmp short 00384h ; eb 19 ; 0xc0369 vgarom.asm:681 + push ax ; 50 ; 0xc036b vgarom.asm:683 + mov dx, 003dah ; ba da 03 ; 0xc036c vgarom.asm:684 + in AL, DX ; ec ; 0xc036f vgarom.asm:685 + mov dx, 003c0h ; ba c0 03 ; 0xc0370 vgarom.asm:686 + mov AL, strict byte 014h ; b0 14 ; 0xc0373 vgarom.asm:687 + out DX, AL ; ee ; 0xc0375 vgarom.asm:688 + pop ax ; 58 ; 0xc0376 vgarom.asm:689 + and AL, strict byte 080h ; 24 80 ; 0xc0377 vgarom.asm:690 + jne short 0037eh ; 75 03 ; 0xc0379 vgarom.asm:691 + sal bh, 002h ; c0 e7 02 ; 0xc037b vgarom.asm:693 + and bh, 00fh ; 80 e7 0f ; 0xc037e vgarom.asm:699 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc0381 vgarom.asm:700 + out DX, AL ; ee ; 0xc0383 vgarom.asm:701 + mov AL, strict byte 020h ; b0 20 ; 0xc0384 vgarom.asm:703 + out DX, AL ; ee ; 0xc0386 vgarom.asm:704 + mov dx, 003dah ; ba da 03 ; 0xc0387 vgarom.asm:706 + in AL, DX ; ec ; 0xc038a vgarom.asm:707 + pop dx ; 5a ; 0xc038b vgarom.asm:709 + pop bx ; 5b ; 0xc038c vgarom.asm:710 + pop ax ; 58 ; 0xc038d vgarom.asm:711 + retn ; c3 ; 0xc038e vgarom.asm:712 + push ax ; 50 ; 0xc038f vgarom.asm:717 + push dx ; 52 ; 0xc0390 vgarom.asm:718 + mov dx, 003c7h ; ba c7 03 ; 0xc0391 vgarom.asm:719 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0394 vgarom.asm:720 + out DX, AL ; ee ; 0xc0396 vgarom.asm:721 + pop ax ; 58 ; 0xc0397 vgarom.asm:722 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc0398 vgarom.asm:723 + mov dx, 003c9h ; ba c9 03 ; 0xc039a vgarom.asm:724 + in AL, DX ; ec ; 0xc039d vgarom.asm:725 + xchg al, ah ; 86 e0 ; 0xc039e vgarom.asm:726 + push ax ; 50 ; 0xc03a0 vgarom.asm:727 + in AL, DX ; ec ; 0xc03a1 vgarom.asm:728 + db 08ah, 0e8h + ; mov ch, al ; 8a e8 ; 0xc03a2 vgarom.asm:729 + in AL, DX ; ec ; 0xc03a4 vgarom.asm:730 + db 08ah, 0c8h + ; mov cl, al ; 8a c8 ; 0xc03a5 vgarom.asm:731 + pop dx ; 5a ; 0xc03a7 vgarom.asm:732 + pop ax ; 58 ; 0xc03a8 vgarom.asm:733 + retn ; c3 ; 0xc03a9 vgarom.asm:734 + push ax ; 50 ; 0xc03aa vgarom.asm:739 + push bx ; 53 ; 0xc03ab vgarom.asm:740 + push cx ; 51 ; 0xc03ac vgarom.asm:741 + push dx ; 52 ; 0xc03ad vgarom.asm:742 + mov dx, 003c7h ; ba c7 03 ; 0xc03ae vgarom.asm:743 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc03b1 vgarom.asm:744 + out DX, AL ; ee ; 0xc03b3 vgarom.asm:745 + pop dx ; 5a ; 0xc03b4 vgarom.asm:746 + push dx ; 52 ; 0xc03b5 vgarom.asm:747 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc03b6 vgarom.asm:748 + mov dx, 003c9h ; ba c9 03 ; 0xc03b8 vgarom.asm:749 + in AL, DX ; ec ; 0xc03bb vgarom.asm:751 + mov byte [es:bx], al ; 26 88 07 ; 0xc03bc vgarom.asm:752 + inc bx ; 43 ; 0xc03bf vgarom.asm:753 + in AL, DX ; ec ; 0xc03c0 vgarom.asm:754 + mov byte [es:bx], al ; 26 88 07 ; 0xc03c1 vgarom.asm:755 + inc bx ; 43 ; 0xc03c4 vgarom.asm:756 + in AL, DX ; ec ; 0xc03c5 vgarom.asm:757 + mov byte [es:bx], al ; 26 88 07 ; 0xc03c6 vgarom.asm:758 + inc bx ; 43 ; 0xc03c9 vgarom.asm:759 + dec cx ; 49 ; 0xc03ca vgarom.asm:760 + jne short 003bbh ; 75 ee ; 0xc03cb vgarom.asm:761 + pop dx ; 5a ; 0xc03cd vgarom.asm:762 + pop cx ; 59 ; 0xc03ce vgarom.asm:763 + pop bx ; 5b ; 0xc03cf vgarom.asm:764 + pop ax ; 58 ; 0xc03d0 vgarom.asm:765 + retn ; c3 ; 0xc03d1 vgarom.asm:766 + push ax ; 50 ; 0xc03d2 vgarom.asm:771 + push dx ; 52 ; 0xc03d3 vgarom.asm:772 + mov dx, 003c6h ; ba c6 03 ; 0xc03d4 vgarom.asm:773 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc03d7 vgarom.asm:774 + out DX, AL ; ee ; 0xc03d9 vgarom.asm:775 + pop dx ; 5a ; 0xc03da vgarom.asm:776 + pop ax ; 58 ; 0xc03db vgarom.asm:777 + retn ; c3 ; 0xc03dc vgarom.asm:778 + push ax ; 50 ; 0xc03dd vgarom.asm:783 + push dx ; 52 ; 0xc03de vgarom.asm:784 + mov dx, 003c6h ; ba c6 03 ; 0xc03df vgarom.asm:785 + in AL, DX ; ec ; 0xc03e2 vgarom.asm:786 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc03e3 vgarom.asm:787 + pop dx ; 5a ; 0xc03e5 vgarom.asm:788 + pop ax ; 58 ; 0xc03e6 vgarom.asm:789 + retn ; c3 ; 0xc03e7 vgarom.asm:790 + push ax ; 50 ; 0xc03e8 vgarom.asm:795 + push dx ; 52 ; 0xc03e9 vgarom.asm:796 + mov dx, 003dah ; ba da 03 ; 0xc03ea vgarom.asm:797 + in AL, DX ; ec ; 0xc03ed vgarom.asm:798 + mov dx, 003c0h ; ba c0 03 ; 0xc03ee vgarom.asm:799 + mov AL, strict byte 010h ; b0 10 ; 0xc03f1 vgarom.asm:800 + out DX, AL ; ee ; 0xc03f3 vgarom.asm:801 + mov dx, 003c1h ; ba c1 03 ; 0xc03f4 vgarom.asm:802 + in AL, DX ; ec ; 0xc03f7 vgarom.asm:803 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc03f8 vgarom.asm:804 + shr bl, 007h ; c0 eb 07 ; 0xc03fa vgarom.asm:806 + mov dx, 003dah ; ba da 03 ; 0xc03fd vgarom.asm:816 + in AL, DX ; ec ; 0xc0400 vgarom.asm:817 + mov dx, 003c0h ; ba c0 03 ; 0xc0401 vgarom.asm:818 + mov AL, strict byte 014h ; b0 14 ; 0xc0404 vgarom.asm:819 + out DX, AL ; ee ; 0xc0406 vgarom.asm:820 + mov dx, 003c1h ; ba c1 03 ; 0xc0407 vgarom.asm:821 + in AL, DX ; ec ; 0xc040a vgarom.asm:822 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc040b vgarom.asm:823 + and bh, 00fh ; 80 e7 0f ; 0xc040d vgarom.asm:824 + test bl, 001h ; f6 c3 01 ; 0xc0410 vgarom.asm:825 + jne short 00418h ; 75 03 ; 0xc0413 vgarom.asm:826 + shr bh, 002h ; c0 ef 02 ; 0xc0415 vgarom.asm:828 + mov dx, 003dah ; ba da 03 ; 0xc0418 vgarom.asm:834 + in AL, DX ; ec ; 0xc041b vgarom.asm:835 + mov dx, 003c0h ; ba c0 03 ; 0xc041c vgarom.asm:836 + mov AL, strict byte 020h ; b0 20 ; 0xc041f vgarom.asm:837 + out DX, AL ; ee ; 0xc0421 vgarom.asm:838 + mov dx, 003dah ; ba da 03 ; 0xc0422 vgarom.asm:840 + in AL, DX ; ec ; 0xc0425 vgarom.asm:841 + pop dx ; 5a ; 0xc0426 vgarom.asm:843 + pop ax ; 58 ; 0xc0427 vgarom.asm:844 + retn ; c3 ; 0xc0428 vgarom.asm:845 + push ax ; 50 ; 0xc0429 vgarom.asm:850 + push dx ; 52 ; 0xc042a vgarom.asm:851 + mov dx, 003c4h ; ba c4 03 ; 0xc042b vgarom.asm:852 + db 08ah, 0e3h + ; mov ah, bl ; 8a e3 ; 0xc042e vgarom.asm:853 + mov AL, strict byte 003h ; b0 03 ; 0xc0430 vgarom.asm:854 + out DX, ax ; ef ; 0xc0432 vgarom.asm:855 + pop dx ; 5a ; 0xc0433 vgarom.asm:856 + pop ax ; 58 ; 0xc0434 vgarom.asm:857 + retn ; c3 ; 0xc0435 vgarom.asm:858 + push DS ; 1e ; 0xc0436 vgarom.asm:863 + push ax ; 50 ; 0xc0437 vgarom.asm:864 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0438 vgarom.asm:865 + mov ds, ax ; 8e d8 ; 0xc043b vgarom.asm:866 + db 032h, 0edh + ; xor ch, ch ; 32 ed ; 0xc043d vgarom.asm:867 + mov bx, 00088h ; bb 88 00 ; 0xc043f vgarom.asm:868 + mov cl, byte [bx] ; 8a 0f ; 0xc0442 vgarom.asm:869 + and cl, 00fh ; 80 e1 0f ; 0xc0444 vgarom.asm:870 + mov bx, strict word 00063h ; bb 63 00 ; 0xc0447 vgarom.asm:871 + mov ax, word [bx] ; 8b 07 ; 0xc044a vgarom.asm:872 + mov bx, strict word 00003h ; bb 03 00 ; 0xc044c vgarom.asm:873 + cmp ax, 003b4h ; 3d b4 03 ; 0xc044f vgarom.asm:874 + jne short 00456h ; 75 02 ; 0xc0452 vgarom.asm:875 + mov BH, strict byte 001h ; b7 01 ; 0xc0454 vgarom.asm:876 + pop ax ; 58 ; 0xc0456 vgarom.asm:878 + pop DS ; 1f ; 0xc0457 vgarom.asm:879 + retn ; c3 ; 0xc0458 vgarom.asm:880 + push DS ; 1e ; 0xc0459 vgarom.asm:888 + push bx ; 53 ; 0xc045a vgarom.asm:889 + push dx ; 52 ; 0xc045b vgarom.asm:890 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc045c vgarom.asm:891 + mov ax, strict word 00040h ; b8 40 00 ; 0xc045e vgarom.asm:892 + mov ds, ax ; 8e d8 ; 0xc0461 vgarom.asm:893 + mov bx, 00089h ; bb 89 00 ; 0xc0463 vgarom.asm:894 + mov al, byte [bx] ; 8a 07 ; 0xc0466 vgarom.asm:895 + mov bx, 00088h ; bb 88 00 ; 0xc0468 vgarom.asm:896 + mov ah, byte [bx] ; 8a 27 ; 0xc046b vgarom.asm:897 + cmp dl, 001h ; 80 fa 01 ; 0xc046d vgarom.asm:898 + je short 00487h ; 74 15 ; 0xc0470 vgarom.asm:899 + jc short 00491h ; 72 1d ; 0xc0472 vgarom.asm:900 + cmp dl, 002h ; 80 fa 02 ; 0xc0474 vgarom.asm:901 + je short 0047bh ; 74 02 ; 0xc0477 vgarom.asm:902 + jmp short 004a5h ; eb 2a ; 0xc0479 vgarom.asm:912 + and AL, strict byte 07fh ; 24 7f ; 0xc047b vgarom.asm:918 + or AL, strict byte 010h ; 0c 10 ; 0xc047d vgarom.asm:919 + and ah, 0f0h ; 80 e4 f0 ; 0xc047f vgarom.asm:920 + or ah, 009h ; 80 cc 09 ; 0xc0482 vgarom.asm:921 + jne short 0049bh ; 75 14 ; 0xc0485 vgarom.asm:922 + and AL, strict byte 06fh ; 24 6f ; 0xc0487 vgarom.asm:928 + and ah, 0f0h ; 80 e4 f0 ; 0xc0489 vgarom.asm:929 + or ah, 009h ; 80 cc 09 ; 0xc048c vgarom.asm:930 + jne short 0049bh ; 75 0a ; 0xc048f vgarom.asm:931 + and AL, strict byte 0efh ; 24 ef ; 0xc0491 vgarom.asm:937 + or AL, strict byte 080h ; 0c 80 ; 0xc0493 vgarom.asm:938 + and ah, 0f0h ; 80 e4 f0 ; 0xc0495 vgarom.asm:939 + or ah, 008h ; 80 cc 08 ; 0xc0498 vgarom.asm:940 + mov bx, 00089h ; bb 89 00 ; 0xc049b vgarom.asm:942 + mov byte [bx], al ; 88 07 ; 0xc049e vgarom.asm:943 + mov bx, 00088h ; bb 88 00 ; 0xc04a0 vgarom.asm:944 + mov byte [bx], ah ; 88 27 ; 0xc04a3 vgarom.asm:945 + mov ax, 01212h ; b8 12 12 ; 0xc04a5 vgarom.asm:947 + pop dx ; 5a ; 0xc04a8 vgarom.asm:948 + pop bx ; 5b ; 0xc04a9 vgarom.asm:949 + pop DS ; 1f ; 0xc04aa vgarom.asm:950 + retn ; c3 ; 0xc04ab vgarom.asm:951 + push DS ; 1e ; 0xc04ac vgarom.asm:960 + push bx ; 53 ; 0xc04ad vgarom.asm:961 + push dx ; 52 ; 0xc04ae vgarom.asm:962 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc04af vgarom.asm:963 + and dl, 001h ; 80 e2 01 ; 0xc04b1 vgarom.asm:964 + sal dl, 003h ; c0 e2 03 ; 0xc04b4 vgarom.asm:966 + mov ax, strict word 00040h ; b8 40 00 ; 0xc04b7 vgarom.asm:972 + mov ds, ax ; 8e d8 ; 0xc04ba vgarom.asm:973 + mov bx, 00089h ; bb 89 00 ; 0xc04bc vgarom.asm:974 + mov al, byte [bx] ; 8a 07 ; 0xc04bf vgarom.asm:975 + and AL, strict byte 0f7h ; 24 f7 ; 0xc04c1 vgarom.asm:976 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc04c3 vgarom.asm:977 + mov byte [bx], al ; 88 07 ; 0xc04c5 vgarom.asm:978 + mov ax, 01212h ; b8 12 12 ; 0xc04c7 vgarom.asm:979 + pop dx ; 5a ; 0xc04ca vgarom.asm:980 + pop bx ; 5b ; 0xc04cb vgarom.asm:981 + pop DS ; 1f ; 0xc04cc vgarom.asm:982 + retn ; c3 ; 0xc04cd vgarom.asm:983 + push bx ; 53 ; 0xc04ce vgarom.asm:987 + push dx ; 52 ; 0xc04cf vgarom.asm:988 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc04d0 vgarom.asm:989 + and bl, 001h ; 80 e3 01 ; 0xc04d2 vgarom.asm:990 + xor bl, 001h ; 80 f3 01 ; 0xc04d5 vgarom.asm:991 + sal bl, 1 ; d0 e3 ; 0xc04d8 vgarom.asm:992 + mov dx, 003cch ; ba cc 03 ; 0xc04da vgarom.asm:993 + in AL, DX ; ec ; 0xc04dd vgarom.asm:994 + and AL, strict byte 0fdh ; 24 fd ; 0xc04de vgarom.asm:995 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc04e0 vgarom.asm:996 + mov dx, 003c2h ; ba c2 03 ; 0xc04e2 vgarom.asm:997 + out DX, AL ; ee ; 0xc04e5 vgarom.asm:998 + mov ax, 01212h ; b8 12 12 ; 0xc04e6 vgarom.asm:999 + pop dx ; 5a ; 0xc04e9 vgarom.asm:1000 + pop bx ; 5b ; 0xc04ea vgarom.asm:1001 + retn ; c3 ; 0xc04eb vgarom.asm:1002 + push DS ; 1e ; 0xc04ec vgarom.asm:1006 + push bx ; 53 ; 0xc04ed vgarom.asm:1007 + push dx ; 52 ; 0xc04ee vgarom.asm:1008 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc04ef vgarom.asm:1009 + and dl, 001h ; 80 e2 01 ; 0xc04f1 vgarom.asm:1010 + xor dl, 001h ; 80 f2 01 ; 0xc04f4 vgarom.asm:1011 + sal dl, 1 ; d0 e2 ; 0xc04f7 vgarom.asm:1012 + mov ax, strict word 00040h ; b8 40 00 ; 0xc04f9 vgarom.asm:1013 + mov ds, ax ; 8e d8 ; 0xc04fc vgarom.asm:1014 + mov bx, 00089h ; bb 89 00 ; 0xc04fe vgarom.asm:1015 + mov al, byte [bx] ; 8a 07 ; 0xc0501 vgarom.asm:1016 + and AL, strict byte 0fdh ; 24 fd ; 0xc0503 vgarom.asm:1017 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc0505 vgarom.asm:1018 + mov byte [bx], al ; 88 07 ; 0xc0507 vgarom.asm:1019 + mov ax, 01212h ; b8 12 12 ; 0xc0509 vgarom.asm:1020 + pop dx ; 5a ; 0xc050c vgarom.asm:1021 + pop bx ; 5b ; 0xc050d vgarom.asm:1022 + pop DS ; 1f ; 0xc050e vgarom.asm:1023 + retn ; c3 ; 0xc050f vgarom.asm:1024 + push DS ; 1e ; 0xc0510 vgarom.asm:1028 + push bx ; 53 ; 0xc0511 vgarom.asm:1029 + push dx ; 52 ; 0xc0512 vgarom.asm:1030 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc0513 vgarom.asm:1031 + and dl, 001h ; 80 e2 01 ; 0xc0515 vgarom.asm:1032 + xor dl, 001h ; 80 f2 01 ; 0xc0518 vgarom.asm:1033 + mov ax, strict word 00040h ; b8 40 00 ; 0xc051b vgarom.asm:1034 + mov ds, ax ; 8e d8 ; 0xc051e vgarom.asm:1035 + mov bx, 00089h ; bb 89 00 ; 0xc0520 vgarom.asm:1036 + mov al, byte [bx] ; 8a 07 ; 0xc0523 vgarom.asm:1037 + and AL, strict byte 0feh ; 24 fe ; 0xc0525 vgarom.asm:1038 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc0527 vgarom.asm:1039 + mov byte [bx], al ; 88 07 ; 0xc0529 vgarom.asm:1040 + mov ax, 01212h ; b8 12 12 ; 0xc052b vgarom.asm:1041 + pop dx ; 5a ; 0xc052e vgarom.asm:1042 + pop bx ; 5b ; 0xc052f vgarom.asm:1043 + pop DS ; 1f ; 0xc0530 vgarom.asm:1044 + retn ; c3 ; 0xc0531 vgarom.asm:1045 + cmp AL, strict byte 000h ; 3c 00 ; 0xc0532 vgarom.asm:1050 + je short 0053bh ; 74 05 ; 0xc0534 vgarom.asm:1051 + cmp AL, strict byte 001h ; 3c 01 ; 0xc0536 vgarom.asm:1052 + je short 00550h ; 74 16 ; 0xc0538 vgarom.asm:1053 + retn ; c3 ; 0xc053a vgarom.asm:1057 + push DS ; 1e ; 0xc053b vgarom.asm:1059 + push ax ; 50 ; 0xc053c vgarom.asm:1060 + mov ax, strict word 00040h ; b8 40 00 ; 0xc053d vgarom.asm:1061 + mov ds, ax ; 8e d8 ; 0xc0540 vgarom.asm:1062 + mov bx, 0008ah ; bb 8a 00 ; 0xc0542 vgarom.asm:1063 + mov al, byte [bx] ; 8a 07 ; 0xc0545 vgarom.asm:1064 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc0547 vgarom.asm:1065 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc0549 vgarom.asm:1066 + pop ax ; 58 ; 0xc054b vgarom.asm:1067 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc054c vgarom.asm:1068 + pop DS ; 1f ; 0xc054e vgarom.asm:1069 + retn ; c3 ; 0xc054f vgarom.asm:1070 + push DS ; 1e ; 0xc0550 vgarom.asm:1072 + push ax ; 50 ; 0xc0551 vgarom.asm:1073 + push bx ; 53 ; 0xc0552 vgarom.asm:1074 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0553 vgarom.asm:1075 + mov ds, ax ; 8e d8 ; 0xc0556 vgarom.asm:1076 + db 08bh, 0c3h + ; mov ax, bx ; 8b c3 ; 0xc0558 vgarom.asm:1077 + mov bx, 0008ah ; bb 8a 00 ; 0xc055a vgarom.asm:1078 + mov byte [bx], al ; 88 07 ; 0xc055d vgarom.asm:1079 + pop bx ; 5b ; 0xc055f vgarom.asm:1089 + pop ax ; 58 ; 0xc0560 vgarom.asm:1090 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc0561 vgarom.asm:1091 + pop DS ; 1f ; 0xc0563 vgarom.asm:1092 + retn ; c3 ; 0xc0564 vgarom.asm:1093 + times 0xb db 0 + ; disGetNextSymbol 0xc0570 LB 0x38a -> off=0x0 cb=0000000000000007 uValue=00000000000c0570 'do_out_dx_ax' +do_out_dx_ax: ; 0xc0570 LB 0x7 + xchg ah, al ; 86 c4 ; 0xc0570 vberom.asm:69 + out DX, AL ; ee ; 0xc0572 vberom.asm:70 + xchg ah, al ; 86 c4 ; 0xc0573 vberom.asm:71 + out DX, AL ; ee ; 0xc0575 vberom.asm:72 + retn ; c3 ; 0xc0576 vberom.asm:73 + ; disGetNextSymbol 0xc0577 LB 0x383 -> off=0x0 cb=0000000000000040 uValue=00000000000c0577 'do_in_ax_dx' +do_in_ax_dx: ; 0xc0577 LB 0x40 + in AL, DX ; ec ; 0xc0577 vberom.asm:76 + xchg ah, al ; 86 c4 ; 0xc0578 vberom.asm:77 + in AL, DX ; ec ; 0xc057a vberom.asm:78 + retn ; c3 ; 0xc057b vberom.asm:79 + push ax ; 50 ; 0xc057c vberom.asm:90 + push dx ; 52 ; 0xc057d vberom.asm:91 + mov dx, 003dah ; ba da 03 ; 0xc057e vberom.asm:92 + in AL, DX ; ec ; 0xc0581 vberom.asm:94 + test AL, strict byte 008h ; a8 08 ; 0xc0582 vberom.asm:95 + je short 00581h ; 74 fb ; 0xc0584 vberom.asm:96 + pop dx ; 5a ; 0xc0586 vberom.asm:97 + pop ax ; 58 ; 0xc0587 vberom.asm:98 + retn ; c3 ; 0xc0588 vberom.asm:99 + push ax ; 50 ; 0xc0589 vberom.asm:102 + push dx ; 52 ; 0xc058a vberom.asm:103 + mov dx, 003dah ; ba da 03 ; 0xc058b vberom.asm:104 + in AL, DX ; ec ; 0xc058e vberom.asm:106 + test AL, strict byte 008h ; a8 08 ; 0xc058f vberom.asm:107 + jne short 0058eh ; 75 fb ; 0xc0591 vberom.asm:108 + pop dx ; 5a ; 0xc0593 vberom.asm:109 + pop ax ; 58 ; 0xc0594 vberom.asm:110 + retn ; c3 ; 0xc0595 vberom.asm:111 + push dx ; 52 ; 0xc0596 vberom.asm:116 + mov dx, 001ceh ; ba ce 01 ; 0xc0597 vberom.asm:117 + mov ax, strict word 00003h ; b8 03 00 ; 0xc059a vberom.asm:118 + call 00570h ; e8 d0 ff ; 0xc059d vberom.asm:119 + mov dx, 001cfh ; ba cf 01 ; 0xc05a0 vberom.asm:120 + call 00577h ; e8 d1 ff ; 0xc05a3 vberom.asm:121 + cmp AL, strict byte 004h ; 3c 04 ; 0xc05a6 vberom.asm:122 + jbe short 005b5h ; 76 0b ; 0xc05a8 vberom.asm:123 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc05aa vberom.asm:124 + shr ah, 003h ; c0 ec 03 ; 0xc05ac vberom.asm:126 + test AL, strict byte 007h ; a8 07 ; 0xc05af vberom.asm:132 + je short 005b5h ; 74 02 ; 0xc05b1 vberom.asm:133 + db 0feh, 0c4h + ; inc ah ; fe c4 ; 0xc05b3 vberom.asm:134 + pop dx ; 5a ; 0xc05b5 vberom.asm:136 + retn ; c3 ; 0xc05b6 vberom.asm:137 + ; disGetNextSymbol 0xc05b7 LB 0x343 -> off=0x0 cb=0000000000000026 uValue=00000000000c05b7 '_dispi_get_max_bpp' +_dispi_get_max_bpp: ; 0xc05b7 LB 0x26 + push dx ; 52 ; 0xc05b7 vberom.asm:142 + push bx ; 53 ; 0xc05b8 vberom.asm:143 + call 005f1h ; e8 35 00 ; 0xc05b9 vberom.asm:144 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc05bc vberom.asm:145 + or ax, strict byte 00002h ; 83 c8 02 ; 0xc05be vberom.asm:146 + call 005ddh ; e8 19 00 ; 0xc05c1 vberom.asm:147 + mov dx, 001ceh ; ba ce 01 ; 0xc05c4 vberom.asm:148 + mov ax, strict word 00003h ; b8 03 00 ; 0xc05c7 vberom.asm:149 + call 00570h ; e8 a3 ff ; 0xc05ca vberom.asm:150 + mov dx, 001cfh ; ba cf 01 ; 0xc05cd vberom.asm:151 + call 00577h ; e8 a4 ff ; 0xc05d0 vberom.asm:152 + push ax ; 50 ; 0xc05d3 vberom.asm:153 + db 08bh, 0c3h + ; mov ax, bx ; 8b c3 ; 0xc05d4 vberom.asm:154 + call 005ddh ; e8 04 00 ; 0xc05d6 vberom.asm:155 + pop ax ; 58 ; 0xc05d9 vberom.asm:156 + pop bx ; 5b ; 0xc05da vberom.asm:157 + pop dx ; 5a ; 0xc05db vberom.asm:158 + retn ; c3 ; 0xc05dc vberom.asm:159 + ; disGetNextSymbol 0xc05dd LB 0x31d -> off=0x0 cb=0000000000000026 uValue=00000000000c05dd 'dispi_set_enable_' +dispi_set_enable_: ; 0xc05dd LB 0x26 + push dx ; 52 ; 0xc05dd vberom.asm:162 + push ax ; 50 ; 0xc05de vberom.asm:163 + mov dx, 001ceh ; ba ce 01 ; 0xc05df vberom.asm:164 + mov ax, strict word 00004h ; b8 04 00 ; 0xc05e2 vberom.asm:165 + call 00570h ; e8 88 ff ; 0xc05e5 vberom.asm:166 + pop ax ; 58 ; 0xc05e8 vberom.asm:167 + mov dx, 001cfh ; ba cf 01 ; 0xc05e9 vberom.asm:168 + call 00570h ; e8 81 ff ; 0xc05ec vberom.asm:169 + pop dx ; 5a ; 0xc05ef vberom.asm:170 + retn ; c3 ; 0xc05f0 vberom.asm:171 + push dx ; 52 ; 0xc05f1 vberom.asm:174 + mov dx, 001ceh ; ba ce 01 ; 0xc05f2 vberom.asm:175 + mov ax, strict word 00004h ; b8 04 00 ; 0xc05f5 vberom.asm:176 + call 00570h ; e8 75 ff ; 0xc05f8 vberom.asm:177 + mov dx, 001cfh ; ba cf 01 ; 0xc05fb vberom.asm:178 + call 00577h ; e8 76 ff ; 0xc05fe vberom.asm:179 + pop dx ; 5a ; 0xc0601 vberom.asm:180 + retn ; c3 ; 0xc0602 vberom.asm:181 + ; disGetNextSymbol 0xc0603 LB 0x2f7 -> off=0x0 cb=0000000000000026 uValue=00000000000c0603 'dispi_set_bank_' +dispi_set_bank_: ; 0xc0603 LB 0x26 + push dx ; 52 ; 0xc0603 vberom.asm:184 + push ax ; 50 ; 0xc0604 vberom.asm:185 + mov dx, 001ceh ; ba ce 01 ; 0xc0605 vberom.asm:186 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0608 vberom.asm:187 + call 00570h ; e8 62 ff ; 0xc060b vberom.asm:188 + pop ax ; 58 ; 0xc060e vberom.asm:189 + mov dx, 001cfh ; ba cf 01 ; 0xc060f vberom.asm:190 + call 00570h ; e8 5b ff ; 0xc0612 vberom.asm:191 + pop dx ; 5a ; 0xc0615 vberom.asm:192 + retn ; c3 ; 0xc0616 vberom.asm:193 + push dx ; 52 ; 0xc0617 vberom.asm:196 + mov dx, 001ceh ; ba ce 01 ; 0xc0618 vberom.asm:197 + mov ax, strict word 00005h ; b8 05 00 ; 0xc061b vberom.asm:198 + call 00570h ; e8 4f ff ; 0xc061e vberom.asm:199 + mov dx, 001cfh ; ba cf 01 ; 0xc0621 vberom.asm:200 + call 00577h ; e8 50 ff ; 0xc0624 vberom.asm:201 + pop dx ; 5a ; 0xc0627 vberom.asm:202 + retn ; c3 ; 0xc0628 vberom.asm:203 + ; disGetNextSymbol 0xc0629 LB 0x2d1 -> off=0x0 cb=00000000000000a9 uValue=00000000000c0629 '_dispi_set_bank_farcall' +_dispi_set_bank_farcall: ; 0xc0629 LB 0xa9 + cmp bx, 00100h ; 81 fb 00 01 ; 0xc0629 vberom.asm:206 + je short 00653h ; 74 24 ; 0xc062d vberom.asm:207 + db 00bh, 0dbh + ; or bx, bx ; 0b db ; 0xc062f vberom.asm:208 + jne short 00665h ; 75 32 ; 0xc0631 vberom.asm:209 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc0633 vberom.asm:210 + push dx ; 52 ; 0xc0635 vberom.asm:211 + push ax ; 50 ; 0xc0636 vberom.asm:212 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0637 vberom.asm:213 + mov dx, 001ceh ; ba ce 01 ; 0xc063a vberom.asm:214 + call 00570h ; e8 30 ff ; 0xc063d vberom.asm:215 + pop ax ; 58 ; 0xc0640 vberom.asm:216 + mov dx, 001cfh ; ba cf 01 ; 0xc0641 vberom.asm:217 + call 00570h ; e8 29 ff ; 0xc0644 vberom.asm:218 + call 00577h ; e8 2d ff ; 0xc0647 vberom.asm:219 + pop dx ; 5a ; 0xc064a vberom.asm:220 + db 03bh, 0d0h + ; cmp dx, ax ; 3b d0 ; 0xc064b vberom.asm:221 + jne short 00665h ; 75 16 ; 0xc064d vberom.asm:222 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc064f vberom.asm:223 + retf ; cb ; 0xc0652 vberom.asm:224 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0653 vberom.asm:226 + mov dx, 001ceh ; ba ce 01 ; 0xc0656 vberom.asm:227 + call 00570h ; e8 14 ff ; 0xc0659 vberom.asm:228 + mov dx, 001cfh ; ba cf 01 ; 0xc065c vberom.asm:229 + call 00577h ; e8 15 ff ; 0xc065f vberom.asm:230 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc0662 vberom.asm:231 + retf ; cb ; 0xc0664 vberom.asm:232 + mov ax, 0014fh ; b8 4f 01 ; 0xc0665 vberom.asm:234 + retf ; cb ; 0xc0668 vberom.asm:235 + push dx ; 52 ; 0xc0669 vberom.asm:238 + push ax ; 50 ; 0xc066a vberom.asm:239 + mov dx, 001ceh ; ba ce 01 ; 0xc066b vberom.asm:240 + mov ax, strict word 00008h ; b8 08 00 ; 0xc066e vberom.asm:241 + call 00570h ; e8 fc fe ; 0xc0671 vberom.asm:242 + pop ax ; 58 ; 0xc0674 vberom.asm:243 + mov dx, 001cfh ; ba cf 01 ; 0xc0675 vberom.asm:244 + call 00570h ; e8 f5 fe ; 0xc0678 vberom.asm:245 + pop dx ; 5a ; 0xc067b vberom.asm:246 + retn ; c3 ; 0xc067c vberom.asm:247 + push dx ; 52 ; 0xc067d vberom.asm:250 + mov dx, 001ceh ; ba ce 01 ; 0xc067e vberom.asm:251 + mov ax, strict word 00008h ; b8 08 00 ; 0xc0681 vberom.asm:252 + call 00570h ; e8 e9 fe ; 0xc0684 vberom.asm:253 + mov dx, 001cfh ; ba cf 01 ; 0xc0687 vberom.asm:254 + call 00577h ; e8 ea fe ; 0xc068a vberom.asm:255 + pop dx ; 5a ; 0xc068d vberom.asm:256 + retn ; c3 ; 0xc068e vberom.asm:257 + push dx ; 52 ; 0xc068f vberom.asm:260 + push ax ; 50 ; 0xc0690 vberom.asm:261 + mov dx, 001ceh ; ba ce 01 ; 0xc0691 vberom.asm:262 + mov ax, strict word 00009h ; b8 09 00 ; 0xc0694 vberom.asm:263 + call 00570h ; e8 d6 fe ; 0xc0697 vberom.asm:264 + pop ax ; 58 ; 0xc069a vberom.asm:265 + mov dx, 001cfh ; ba cf 01 ; 0xc069b vberom.asm:266 + call 00570h ; e8 cf fe ; 0xc069e vberom.asm:267 + pop dx ; 5a ; 0xc06a1 vberom.asm:268 + retn ; c3 ; 0xc06a2 vberom.asm:269 + push dx ; 52 ; 0xc06a3 vberom.asm:272 + mov dx, 001ceh ; ba ce 01 ; 0xc06a4 vberom.asm:273 + mov ax, strict word 00009h ; b8 09 00 ; 0xc06a7 vberom.asm:274 + call 00570h ; e8 c3 fe ; 0xc06aa vberom.asm:275 + mov dx, 001cfh ; ba cf 01 ; 0xc06ad vberom.asm:276 + call 00577h ; e8 c4 fe ; 0xc06b0 vberom.asm:277 + pop dx ; 5a ; 0xc06b3 vberom.asm:278 + retn ; c3 ; 0xc06b4 vberom.asm:279 + push ax ; 50 ; 0xc06b5 vberom.asm:282 + push bx ; 53 ; 0xc06b6 vberom.asm:283 + push dx ; 52 ; 0xc06b7 vberom.asm:284 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc06b8 vberom.asm:285 + call 00596h ; e8 d9 fe ; 0xc06ba vberom.asm:286 + cmp AL, strict byte 004h ; 3c 04 ; 0xc06bd vberom.asm:287 + jnbe short 006c3h ; 77 02 ; 0xc06bf vberom.asm:288 + shr bx, 1 ; d1 eb ; 0xc06c1 vberom.asm:289 + shr bx, 003h ; c1 eb 03 ; 0xc06c3 vberom.asm:292 + mov dx, 003d4h ; ba d4 03 ; 0xc06c6 vberom.asm:298 + db 08ah, 0e3h + ; mov ah, bl ; 8a e3 ; 0xc06c9 vberom.asm:299 + mov AL, strict byte 013h ; b0 13 ; 0xc06cb vberom.asm:300 + out DX, ax ; ef ; 0xc06cd vberom.asm:301 + pop dx ; 5a ; 0xc06ce vberom.asm:302 + pop bx ; 5b ; 0xc06cf vberom.asm:303 + pop ax ; 58 ; 0xc06d0 vberom.asm:304 + retn ; c3 ; 0xc06d1 vberom.asm:305 + ; disGetNextSymbol 0xc06d2 LB 0x228 -> off=0x0 cb=00000000000000ed uValue=00000000000c06d2 '_vga_compat_setup' +_vga_compat_setup: ; 0xc06d2 LB 0xed + push ax ; 50 ; 0xc06d2 vberom.asm:308 + push dx ; 52 ; 0xc06d3 vberom.asm:309 + mov dx, 001ceh ; ba ce 01 ; 0xc06d4 vberom.asm:312 + mov ax, strict word 00001h ; b8 01 00 ; 0xc06d7 vberom.asm:313 + call 00570h ; e8 93 fe ; 0xc06da vberom.asm:314 + mov dx, 001cfh ; ba cf 01 ; 0xc06dd vberom.asm:315 + call 00577h ; e8 94 fe ; 0xc06e0 vberom.asm:316 + push ax ; 50 ; 0xc06e3 vberom.asm:317 + mov dx, 003d4h ; ba d4 03 ; 0xc06e4 vberom.asm:318 + mov ax, strict word 00011h ; b8 11 00 ; 0xc06e7 vberom.asm:319 + out DX, ax ; ef ; 0xc06ea vberom.asm:320 + pop ax ; 58 ; 0xc06eb vberom.asm:321 + push ax ; 50 ; 0xc06ec vberom.asm:322 + shr ax, 003h ; c1 e8 03 ; 0xc06ed vberom.asm:324 + dec ax ; 48 ; 0xc06f0 vberom.asm:330 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc06f1 vberom.asm:331 + mov AL, strict byte 001h ; b0 01 ; 0xc06f3 vberom.asm:332 + out DX, ax ; ef ; 0xc06f5 vberom.asm:333 + pop ax ; 58 ; 0xc06f6 vberom.asm:334 + call 006b5h ; e8 bb ff ; 0xc06f7 vberom.asm:335 + mov dx, 001ceh ; ba ce 01 ; 0xc06fa vberom.asm:338 + mov ax, strict word 00002h ; b8 02 00 ; 0xc06fd vberom.asm:339 + call 00570h ; e8 6d fe ; 0xc0700 vberom.asm:340 + mov dx, 001cfh ; ba cf 01 ; 0xc0703 vberom.asm:341 + call 00577h ; e8 6e fe ; 0xc0706 vberom.asm:342 + dec ax ; 48 ; 0xc0709 vberom.asm:343 + push ax ; 50 ; 0xc070a vberom.asm:344 + mov dx, 003d4h ; ba d4 03 ; 0xc070b vberom.asm:345 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc070e vberom.asm:346 + mov AL, strict byte 012h ; b0 12 ; 0xc0710 vberom.asm:347 + out DX, ax ; ef ; 0xc0712 vberom.asm:348 + pop ax ; 58 ; 0xc0713 vberom.asm:349 + mov AL, strict byte 007h ; b0 07 ; 0xc0714 vberom.asm:350 + out DX, AL ; ee ; 0xc0716 vberom.asm:351 + inc dx ; 42 ; 0xc0717 vberom.asm:352 + in AL, DX ; ec ; 0xc0718 vberom.asm:353 + and AL, strict byte 0bdh ; 24 bd ; 0xc0719 vberom.asm:354 + test ah, 001h ; f6 c4 01 ; 0xc071b vberom.asm:355 + je short 00722h ; 74 02 ; 0xc071e vberom.asm:356 + or AL, strict byte 002h ; 0c 02 ; 0xc0720 vberom.asm:357 + test ah, 002h ; f6 c4 02 ; 0xc0722 vberom.asm:359 + je short 00729h ; 74 02 ; 0xc0725 vberom.asm:360 + or AL, strict byte 040h ; 0c 40 ; 0xc0727 vberom.asm:361 + out DX, AL ; ee ; 0xc0729 vberom.asm:363 + mov dx, 003d4h ; ba d4 03 ; 0xc072a vberom.asm:366 + mov ax, strict word 00009h ; b8 09 00 ; 0xc072d vberom.asm:367 + out DX, AL ; ee ; 0xc0730 vberom.asm:368 + mov dx, 003d5h ; ba d5 03 ; 0xc0731 vberom.asm:369 + in AL, DX ; ec ; 0xc0734 vberom.asm:370 + and AL, strict byte 060h ; 24 60 ; 0xc0735 vberom.asm:371 + out DX, AL ; ee ; 0xc0737 vberom.asm:372 + mov dx, 003d4h ; ba d4 03 ; 0xc0738 vberom.asm:373 + mov AL, strict byte 017h ; b0 17 ; 0xc073b vberom.asm:374 + out DX, AL ; ee ; 0xc073d vberom.asm:375 + mov dx, 003d5h ; ba d5 03 ; 0xc073e vberom.asm:376 + in AL, DX ; ec ; 0xc0741 vberom.asm:377 + or AL, strict byte 003h ; 0c 03 ; 0xc0742 vberom.asm:378 + out DX, AL ; ee ; 0xc0744 vberom.asm:379 + mov dx, 003dah ; ba da 03 ; 0xc0745 vberom.asm:380 + in AL, DX ; ec ; 0xc0748 vberom.asm:381 + mov dx, 003c0h ; ba c0 03 ; 0xc0749 vberom.asm:382 + mov AL, strict byte 010h ; b0 10 ; 0xc074c vberom.asm:383 + out DX, AL ; ee ; 0xc074e vberom.asm:384 + mov dx, 003c1h ; ba c1 03 ; 0xc074f vberom.asm:385 + in AL, DX ; ec ; 0xc0752 vberom.asm:386 + or AL, strict byte 001h ; 0c 01 ; 0xc0753 vberom.asm:387 + mov dx, 003c0h ; ba c0 03 ; 0xc0755 vberom.asm:388 + out DX, AL ; ee ; 0xc0758 vberom.asm:389 + mov AL, strict byte 020h ; b0 20 ; 0xc0759 vberom.asm:390 + out DX, AL ; ee ; 0xc075b vberom.asm:391 + mov dx, 003ceh ; ba ce 03 ; 0xc075c vberom.asm:392 + mov ax, 00506h ; b8 06 05 ; 0xc075f vberom.asm:393 + out DX, ax ; ef ; 0xc0762 vberom.asm:394 + mov dx, 003c4h ; ba c4 03 ; 0xc0763 vberom.asm:395 + mov ax, 00f02h ; b8 02 0f ; 0xc0766 vberom.asm:396 + out DX, ax ; ef ; 0xc0769 vberom.asm:397 + mov dx, 001ceh ; ba ce 01 ; 0xc076a vberom.asm:400 + mov ax, strict word 00003h ; b8 03 00 ; 0xc076d vberom.asm:401 + call 00570h ; e8 fd fd ; 0xc0770 vberom.asm:402 + mov dx, 001cfh ; ba cf 01 ; 0xc0773 vberom.asm:403 + call 00577h ; e8 fe fd ; 0xc0776 vberom.asm:404 + cmp AL, strict byte 008h ; 3c 08 ; 0xc0779 vberom.asm:405 + jc short 007bdh ; 72 40 ; 0xc077b vberom.asm:406 + mov dx, 003d4h ; ba d4 03 ; 0xc077d vberom.asm:407 + mov AL, strict byte 014h ; b0 14 ; 0xc0780 vberom.asm:408 + out DX, AL ; ee ; 0xc0782 vberom.asm:409 + mov dx, 003d5h ; ba d5 03 ; 0xc0783 vberom.asm:410 + in AL, DX ; ec ; 0xc0786 vberom.asm:411 + or AL, strict byte 040h ; 0c 40 ; 0xc0787 vberom.asm:412 + out DX, AL ; ee ; 0xc0789 vberom.asm:413 + mov dx, 003dah ; ba da 03 ; 0xc078a vberom.asm:414 + in AL, DX ; ec ; 0xc078d vberom.asm:415 + mov dx, 003c0h ; ba c0 03 ; 0xc078e vberom.asm:416 + mov AL, strict byte 010h ; b0 10 ; 0xc0791 vberom.asm:417 + out DX, AL ; ee ; 0xc0793 vberom.asm:418 + mov dx, 003c1h ; ba c1 03 ; 0xc0794 vberom.asm:419 + in AL, DX ; ec ; 0xc0797 vberom.asm:420 + or AL, strict byte 040h ; 0c 40 ; 0xc0798 vberom.asm:421 + mov dx, 003c0h ; ba c0 03 ; 0xc079a vberom.asm:422 + out DX, AL ; ee ; 0xc079d vberom.asm:423 + mov AL, strict byte 020h ; b0 20 ; 0xc079e vberom.asm:424 + out DX, AL ; ee ; 0xc07a0 vberom.asm:425 + mov dx, 003c4h ; ba c4 03 ; 0xc07a1 vberom.asm:426 + mov AL, strict byte 004h ; b0 04 ; 0xc07a4 vberom.asm:427 + out DX, AL ; ee ; 0xc07a6 vberom.asm:428 + mov dx, 003c5h ; ba c5 03 ; 0xc07a7 vberom.asm:429 + in AL, DX ; ec ; 0xc07aa vberom.asm:430 + or AL, strict byte 008h ; 0c 08 ; 0xc07ab vberom.asm:431 + out DX, AL ; ee ; 0xc07ad vberom.asm:432 + mov dx, 003ceh ; ba ce 03 ; 0xc07ae vberom.asm:433 + mov AL, strict byte 005h ; b0 05 ; 0xc07b1 vberom.asm:434 + out DX, AL ; ee ; 0xc07b3 vberom.asm:435 + mov dx, 003cfh ; ba cf 03 ; 0xc07b4 vberom.asm:436 + in AL, DX ; ec ; 0xc07b7 vberom.asm:437 + and AL, strict byte 09fh ; 24 9f ; 0xc07b8 vberom.asm:438 + or AL, strict byte 040h ; 0c 40 ; 0xc07ba vberom.asm:439 + out DX, AL ; ee ; 0xc07bc vberom.asm:440 + pop dx ; 5a ; 0xc07bd vberom.asm:443 + pop ax ; 58 ; 0xc07be vberom.asm:444 + ; disGetNextSymbol 0xc07bf LB 0x13b -> off=0x0 cb=0000000000000013 uValue=00000000000c07bf '_vbe_has_vbe_display' +_vbe_has_vbe_display: ; 0xc07bf LB 0x13 + push DS ; 1e ; 0xc07bf vberom.asm:450 + push bx ; 53 ; 0xc07c0 vberom.asm:451 + mov ax, strict word 00040h ; b8 40 00 ; 0xc07c1 vberom.asm:452 + mov ds, ax ; 8e d8 ; 0xc07c4 vberom.asm:453 + mov bx, 000b9h ; bb b9 00 ; 0xc07c6 vberom.asm:454 + mov al, byte [bx] ; 8a 07 ; 0xc07c9 vberom.asm:455 + and AL, strict byte 001h ; 24 01 ; 0xc07cb vberom.asm:456 + db 032h, 0e4h + ; xor ah, ah ; 32 e4 ; 0xc07cd vberom.asm:457 + pop bx ; 5b ; 0xc07cf vberom.asm:458 + pop DS ; 1f ; 0xc07d0 vberom.asm:459 + retn ; c3 ; 0xc07d1 vberom.asm:460 + ; disGetNextSymbol 0xc07d2 LB 0x128 -> off=0x0 cb=0000000000000025 uValue=00000000000c07d2 'vbe_biosfn_return_current_mode' +vbe_biosfn_return_current_mode: ; 0xc07d2 LB 0x25 + push DS ; 1e ; 0xc07d2 vberom.asm:473 + mov ax, strict word 00040h ; b8 40 00 ; 0xc07d3 vberom.asm:474 + mov ds, ax ; 8e d8 ; 0xc07d6 vberom.asm:475 + call 005f1h ; e8 16 fe ; 0xc07d8 vberom.asm:476 + and ax, strict byte 00001h ; 83 e0 01 ; 0xc07db vberom.asm:477 + je short 007e9h ; 74 09 ; 0xc07de vberom.asm:478 + mov bx, 000bah ; bb ba 00 ; 0xc07e0 vberom.asm:479 + mov ax, word [bx] ; 8b 07 ; 0xc07e3 vberom.asm:480 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc07e5 vberom.asm:481 + jne short 007f2h ; 75 09 ; 0xc07e7 vberom.asm:482 + mov bx, strict word 00049h ; bb 49 00 ; 0xc07e9 vberom.asm:484 + mov al, byte [bx] ; 8a 07 ; 0xc07ec vberom.asm:485 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc07ee vberom.asm:486 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc07f0 vberom.asm:487 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc07f2 vberom.asm:489 + pop DS ; 1f ; 0xc07f5 vberom.asm:490 + retn ; c3 ; 0xc07f6 vberom.asm:491 + ; disGetNextSymbol 0xc07f7 LB 0x103 -> off=0x0 cb=000000000000002d uValue=00000000000c07f7 'vbe_biosfn_display_window_control' +vbe_biosfn_display_window_control: ; 0xc07f7 LB 0x2d + cmp bl, 000h ; 80 fb 00 ; 0xc07f7 vberom.asm:515 + jne short 00820h ; 75 24 ; 0xc07fa vberom.asm:516 + cmp bh, 001h ; 80 ff 01 ; 0xc07fc vberom.asm:517 + je short 00817h ; 74 16 ; 0xc07ff vberom.asm:518 + jc short 00807h ; 72 04 ; 0xc0801 vberom.asm:519 + mov ax, 00100h ; b8 00 01 ; 0xc0803 vberom.asm:520 + retn ; c3 ; 0xc0806 vberom.asm:521 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc0807 vberom.asm:523 + call 00603h ; e8 f7 fd ; 0xc0809 vberom.asm:524 + call 00617h ; e8 08 fe ; 0xc080c vberom.asm:525 + db 03bh, 0c2h + ; cmp ax, dx ; 3b c2 ; 0xc080f vberom.asm:526 + jne short 00820h ; 75 0d ; 0xc0811 vberom.asm:527 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0813 vberom.asm:528 + retn ; c3 ; 0xc0816 vberom.asm:529 + call 00617h ; e8 fd fd ; 0xc0817 vberom.asm:531 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc081a vberom.asm:532 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc081c vberom.asm:533 + retn ; c3 ; 0xc081f vberom.asm:534 + mov ax, 0014fh ; b8 4f 01 ; 0xc0820 vberom.asm:536 + retn ; c3 ; 0xc0823 vberom.asm:537 + ; disGetNextSymbol 0xc0824 LB 0xd6 -> off=0x0 cb=0000000000000034 uValue=00000000000c0824 'vbe_biosfn_set_get_display_start' +vbe_biosfn_set_get_display_start: ; 0xc0824 LB 0x34 + cmp bl, 080h ; 80 fb 80 ; 0xc0824 vberom.asm:577 + je short 00834h ; 74 0b ; 0xc0827 vberom.asm:578 + cmp bl, 001h ; 80 fb 01 ; 0xc0829 vberom.asm:579 + je short 00848h ; 74 1a ; 0xc082c vberom.asm:580 + jc short 0083ah ; 72 0a ; 0xc082e vberom.asm:581 + mov ax, 00100h ; b8 00 01 ; 0xc0830 vberom.asm:582 + retn ; c3 ; 0xc0833 vberom.asm:583 + call 00589h ; e8 52 fd ; 0xc0834 vberom.asm:585 + call 0057ch ; e8 42 fd ; 0xc0837 vberom.asm:586 + db 08bh, 0c1h + ; mov ax, cx ; 8b c1 ; 0xc083a vberom.asm:588 + call 00669h ; e8 2a fe ; 0xc083c vberom.asm:589 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc083f vberom.asm:590 + call 0068fh ; e8 4b fe ; 0xc0841 vberom.asm:591 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0844 vberom.asm:592 + retn ; c3 ; 0xc0847 vberom.asm:593 + call 0067dh ; e8 32 fe ; 0xc0848 vberom.asm:595 + db 08bh, 0c8h + ; mov cx, ax ; 8b c8 ; 0xc084b vberom.asm:596 + call 006a3h ; e8 53 fe ; 0xc084d vberom.asm:597 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc0850 vberom.asm:598 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc0852 vberom.asm:599 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0854 vberom.asm:600 + retn ; c3 ; 0xc0857 vberom.asm:601 + ; disGetNextSymbol 0xc0858 LB 0xa2 -> off=0x0 cb=0000000000000037 uValue=00000000000c0858 'vbe_biosfn_set_get_dac_palette_format' +vbe_biosfn_set_get_dac_palette_format: ; 0xc0858 LB 0x37 + cmp bl, 001h ; 80 fb 01 ; 0xc0858 vberom.asm:616 + je short 0087bh ; 74 1e ; 0xc085b vberom.asm:617 + jc short 00863h ; 72 04 ; 0xc085d vberom.asm:618 + mov ax, 00100h ; b8 00 01 ; 0xc085f vberom.asm:619 + retn ; c3 ; 0xc0862 vberom.asm:620 + call 005f1h ; e8 8b fd ; 0xc0863 vberom.asm:622 + cmp bh, 006h ; 80 ff 06 ; 0xc0866 vberom.asm:623 + je short 00875h ; 74 0a ; 0xc0869 vberom.asm:624 + cmp bh, 008h ; 80 ff 08 ; 0xc086b vberom.asm:625 + jne short 0088bh ; 75 1b ; 0xc086e vberom.asm:626 + or ax, strict byte 00020h ; 83 c8 20 ; 0xc0870 vberom.asm:627 + jne short 00878h ; 75 03 ; 0xc0873 vberom.asm:628 + and ax, strict byte 0ffdfh ; 83 e0 df ; 0xc0875 vberom.asm:630 + call 005ddh ; e8 62 fd ; 0xc0878 vberom.asm:632 + mov BH, strict byte 006h ; b7 06 ; 0xc087b vberom.asm:634 + call 005f1h ; e8 71 fd ; 0xc087d vberom.asm:635 + and ax, strict byte 00020h ; 83 e0 20 ; 0xc0880 vberom.asm:636 + je short 00887h ; 74 02 ; 0xc0883 vberom.asm:637 + mov BH, strict byte 008h ; b7 08 ; 0xc0885 vberom.asm:638 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0887 vberom.asm:640 + retn ; c3 ; 0xc088a vberom.asm:641 + mov ax, 0014fh ; b8 4f 01 ; 0xc088b vberom.asm:643 + retn ; c3 ; 0xc088e vberom.asm:644 + ; disGetNextSymbol 0xc088f LB 0x6b -> off=0x0 cb=0000000000000057 uValue=00000000000c088f 'vbe_biosfn_set_get_palette_data' +vbe_biosfn_set_get_palette_data: ; 0xc088f LB 0x57 + test bl, bl ; 84 db ; 0xc088f vberom.asm:683 + je short 008a2h ; 74 0f ; 0xc0891 vberom.asm:684 + cmp bl, 001h ; 80 fb 01 ; 0xc0893 vberom.asm:685 + je short 008c2h ; 74 2a ; 0xc0896 vberom.asm:686 + cmp bl, 003h ; 80 fb 03 ; 0xc0898 vberom.asm:687 + jbe short 008e2h ; 76 45 ; 0xc089b vberom.asm:688 + cmp bl, 080h ; 80 fb 80 ; 0xc089d vberom.asm:689 + jne short 008deh ; 75 3c ; 0xc08a0 vberom.asm:690 + pushaw ; 60 ; 0xc08a2 vberom.asm:143 + push DS ; 1e ; 0xc08a3 vberom.asm:696 + push ES ; 06 ; 0xc08a4 vberom.asm:697 + pop DS ; 1f ; 0xc08a5 vberom.asm:698 + db 08ah, 0c2h + ; mov al, dl ; 8a c2 ; 0xc08a6 vberom.asm:699 + mov dx, 003c8h ; ba c8 03 ; 0xc08a8 vberom.asm:700 + out DX, AL ; ee ; 0xc08ab vberom.asm:701 + inc dx ; 42 ; 0xc08ac vberom.asm:702 + db 08bh, 0f7h + ; mov si, di ; 8b f7 ; 0xc08ad vberom.asm:703 + lodsw ; ad ; 0xc08af vberom.asm:714 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc08b0 vberom.asm:715 + lodsw ; ad ; 0xc08b2 vberom.asm:716 + out DX, AL ; ee ; 0xc08b3 vberom.asm:717 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc08b4 vberom.asm:718 + out DX, AL ; ee ; 0xc08b6 vberom.asm:719 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc08b7 vberom.asm:720 + out DX, AL ; ee ; 0xc08b9 vberom.asm:721 + loop 008afh ; e2 f3 ; 0xc08ba vberom.asm:723 + pop DS ; 1f ; 0xc08bc vberom.asm:724 + popaw ; 61 ; 0xc08bd vberom.asm:162 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc08be vberom.asm:727 + retn ; c3 ; 0xc08c1 vberom.asm:728 + pushaw ; 60 ; 0xc08c2 vberom.asm:143 + db 08ah, 0c2h + ; mov al, dl ; 8a c2 ; 0xc08c3 vberom.asm:732 + mov dx, 003c7h ; ba c7 03 ; 0xc08c5 vberom.asm:733 + out DX, AL ; ee ; 0xc08c8 vberom.asm:734 + add dl, 002h ; 80 c2 02 ; 0xc08c9 vberom.asm:735 + db 033h, 0dbh + ; xor bx, bx ; 33 db ; 0xc08cc vberom.asm:746 + in AL, DX ; ec ; 0xc08ce vberom.asm:748 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc08cf vberom.asm:749 + in AL, DX ; ec ; 0xc08d1 vberom.asm:750 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc08d2 vberom.asm:751 + in AL, DX ; ec ; 0xc08d4 vberom.asm:752 + stosw ; ab ; 0xc08d5 vberom.asm:753 + db 08bh, 0c3h + ; mov ax, bx ; 8b c3 ; 0xc08d6 vberom.asm:754 + stosw ; ab ; 0xc08d8 vberom.asm:755 + loop 008ceh ; e2 f3 ; 0xc08d9 vberom.asm:757 + popaw ; 61 ; 0xc08db vberom.asm:162 + jmp short 008beh ; eb e0 ; 0xc08dc vberom.asm:759 + mov ax, 0014fh ; b8 4f 01 ; 0xc08de vberom.asm:762 + retn ; c3 ; 0xc08e1 vberom.asm:763 + mov ax, 0024fh ; b8 4f 02 ; 0xc08e2 vberom.asm:765 + retn ; c3 ; 0xc08e5 vberom.asm:766 + ; disGetNextSymbol 0xc08e6 LB 0x14 -> off=0x0 cb=0000000000000014 uValue=00000000000c08e6 'vbe_biosfn_return_protected_mode_interface' +vbe_biosfn_return_protected_mode_interface: ; 0xc08e6 LB 0x14 + test bl, bl ; 84 db ; 0xc08e6 vberom.asm:780 + jne short 008f6h ; 75 0c ; 0xc08e8 vberom.asm:781 + push CS ; 0e ; 0xc08ea vberom.asm:782 + pop ES ; 07 ; 0xc08eb vberom.asm:783 + mov di, 04640h ; bf 40 46 ; 0xc08ec vberom.asm:784 + mov cx, 00115h ; b9 15 01 ; 0xc08ef vberom.asm:785 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc08f2 vberom.asm:786 + retn ; c3 ; 0xc08f5 vberom.asm:787 + mov ax, 0014fh ; b8 4f 01 ; 0xc08f6 vberom.asm:789 + retn ; c3 ; 0xc08f9 vberom.asm:790 + + ; Padding 0xf6 bytes at 0xc08fa + times 246 db 0 + +section _TEXT progbits vstart=0x9f0 align=1 ; size=0x3b42 class=CODE group=AUTO + ; disGetNextSymbol 0xc09f0 LB 0x3b42 -> off=0x0 cb=000000000000001b uValue=00000000000c09f0 'set_int_vector' +set_int_vector: ; 0xc09f0 LB 0x1b + push dx ; 52 ; 0xc09f0 vgabios.c:87 + push bp ; 55 ; 0xc09f1 + mov bp, sp ; 89 e5 ; 0xc09f2 + mov dx, bx ; 89 da ; 0xc09f4 + mov bl, al ; 88 c3 ; 0xc09f6 vgabios.c:91 + xor bh, bh ; 30 ff ; 0xc09f8 + sal bx, 002h ; c1 e3 02 ; 0xc09fa + xor ax, ax ; 31 c0 ; 0xc09fd + mov es, ax ; 8e c0 ; 0xc09ff + mov word [es:bx], dx ; 26 89 17 ; 0xc0a01 + mov word [es:bx+002h], cx ; 26 89 4f 02 ; 0xc0a04 + pop bp ; 5d ; 0xc0a08 vgabios.c:92 + pop dx ; 5a ; 0xc0a09 + retn ; c3 ; 0xc0a0a + ; disGetNextSymbol 0xc0a0b LB 0x3b27 -> off=0x0 cb=000000000000001c uValue=00000000000c0a0b 'init_vga_card' +init_vga_card: ; 0xc0a0b LB 0x1c + push bp ; 55 ; 0xc0a0b vgabios.c:143 + mov bp, sp ; 89 e5 ; 0xc0a0c + push dx ; 52 ; 0xc0a0e + mov AL, strict byte 0c3h ; b0 c3 ; 0xc0a0f vgabios.c:146 + mov dx, 003c2h ; ba c2 03 ; 0xc0a11 + out DX, AL ; ee ; 0xc0a14 + mov AL, strict byte 004h ; b0 04 ; 0xc0a15 vgabios.c:149 + mov dx, 003c4h ; ba c4 03 ; 0xc0a17 + out DX, AL ; ee ; 0xc0a1a + mov AL, strict byte 002h ; b0 02 ; 0xc0a1b vgabios.c:150 + mov dx, 003c5h ; ba c5 03 ; 0xc0a1d + out DX, AL ; ee ; 0xc0a20 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc0a21 vgabios.c:155 + pop dx ; 5a ; 0xc0a24 + pop bp ; 5d ; 0xc0a25 + retn ; c3 ; 0xc0a26 + ; disGetNextSymbol 0xc0a27 LB 0x3b0b -> off=0x0 cb=000000000000003e uValue=00000000000c0a27 'init_bios_area' +init_bios_area: ; 0xc0a27 LB 0x3e + push bx ; 53 ; 0xc0a27 vgabios.c:221 + push bp ; 55 ; 0xc0a28 + mov bp, sp ; 89 e5 ; 0xc0a29 + xor bx, bx ; 31 db ; 0xc0a2b vgabios.c:225 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0a2d + mov es, ax ; 8e c0 ; 0xc0a30 + mov al, byte [es:bx+010h] ; 26 8a 47 10 ; 0xc0a32 vgabios.c:228 + and AL, strict byte 0cfh ; 24 cf ; 0xc0a36 + or AL, strict byte 020h ; 0c 20 ; 0xc0a38 + mov byte [es:bx+010h], al ; 26 88 47 10 ; 0xc0a3a + mov byte [es:bx+00085h], 010h ; 26 c6 87 85 00 10 ; 0xc0a3e vgabios.c:232 + mov word [es:bx+00087h], 0f960h ; 26 c7 87 87 00 60 f9 ; 0xc0a44 vgabios.c:234 + mov byte [es:bx+00089h], 051h ; 26 c6 87 89 00 51 ; 0xc0a4b vgabios.c:238 + mov byte [es:bx+065h], 009h ; 26 c6 47 65 09 ; 0xc0a51 vgabios.c:240 + mov word [es:bx+000a8h], 05551h ; 26 c7 87 a8 00 51 55 ; 0xc0a56 vgabios.c:242 + mov [es:bx+000aah], ds ; 26 8c 9f aa 00 ; 0xc0a5d + pop bp ; 5d ; 0xc0a62 vgabios.c:243 + pop bx ; 5b ; 0xc0a63 + retn ; c3 ; 0xc0a64 + ; disGetNextSymbol 0xc0a65 LB 0x3acd -> off=0x0 cb=0000000000000031 uValue=00000000000c0a65 'vgabios_init_func' +vgabios_init_func: ; 0xc0a65 LB 0x31 + inc bp ; 45 ; 0xc0a65 vgabios.c:250 + push bp ; 55 ; 0xc0a66 + mov bp, sp ; 89 e5 ; 0xc0a67 + call 00a0bh ; e8 9f ff ; 0xc0a69 vgabios.c:252 + call 00a27h ; e8 b8 ff ; 0xc0a6c vgabios.c:253 + call 03each ; e8 3a 34 ; 0xc0a6f vgabios.c:255 + mov bx, strict word 00028h ; bb 28 00 ; 0xc0a72 vgabios.c:257 + mov cx, 0c000h ; b9 00 c0 ; 0xc0a75 + mov ax, strict word 00010h ; b8 10 00 ; 0xc0a78 + call 009f0h ; e8 72 ff ; 0xc0a7b + mov bx, strict word 00028h ; bb 28 00 ; 0xc0a7e vgabios.c:258 + mov cx, 0c000h ; b9 00 c0 ; 0xc0a81 + mov ax, strict word 0006dh ; b8 6d 00 ; 0xc0a84 + call 009f0h ; e8 66 ff ; 0xc0a87 + mov ax, strict word 00003h ; b8 03 00 ; 0xc0a8a vgabios.c:284 + db 032h, 0e4h + ; xor ah, ah ; 32 e4 ; 0xc0a8d + int 010h ; cd 10 ; 0xc0a8f + mov sp, bp ; 89 ec ; 0xc0a91 vgabios.c:287 + pop bp ; 5d ; 0xc0a93 + dec bp ; 4d ; 0xc0a94 + retf ; cb ; 0xc0a95 + ; disGetNextSymbol 0xc0a96 LB 0x3a9c -> off=0x0 cb=0000000000000040 uValue=00000000000c0a96 'vga_get_cursor_pos' +vga_get_cursor_pos: ; 0xc0a96 LB 0x40 + push si ; 56 ; 0xc0a96 vgabios.c:356 + push di ; 57 ; 0xc0a97 + push bp ; 55 ; 0xc0a98 + mov bp, sp ; 89 e5 ; 0xc0a99 + mov si, dx ; 89 d6 ; 0xc0a9b + cmp AL, strict byte 007h ; 3c 07 ; 0xc0a9d vgabios.c:358 + jbe short 00aafh ; 76 0e ; 0xc0a9f + push SS ; 16 ; 0xc0aa1 vgabios.c:359 + pop ES ; 07 ; 0xc0aa2 + mov word [es:si], strict word 00000h ; 26 c7 04 00 00 ; 0xc0aa3 + mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xc0aa8 vgabios.c:360 + jmp short 00ad2h ; eb 23 ; 0xc0aad vgabios.c:361 + mov di, strict word 00060h ; bf 60 00 ; 0xc0aaf vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc0ab2 + mov es, dx ; 8e c2 ; 0xc0ab5 + mov di, word [es:di] ; 26 8b 3d ; 0xc0ab7 + push SS ; 16 ; 0xc0aba vgabios.c:58 + pop ES ; 07 ; 0xc0abb + mov word [es:si], di ; 26 89 3c ; 0xc0abc + xor ah, ah ; 30 e4 ; 0xc0abf vgabios.c:364 + mov si, ax ; 89 c6 ; 0xc0ac1 + add si, ax ; 01 c6 ; 0xc0ac3 + add si, strict byte 00050h ; 83 c6 50 ; 0xc0ac5 + mov es, dx ; 8e c2 ; 0xc0ac8 vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc0aca + push SS ; 16 ; 0xc0acd vgabios.c:58 + pop ES ; 07 ; 0xc0ace + mov word [es:bx], ax ; 26 89 07 ; 0xc0acf + pop bp ; 5d ; 0xc0ad2 vgabios.c:366 + pop di ; 5f ; 0xc0ad3 + pop si ; 5e ; 0xc0ad4 + retn ; c3 ; 0xc0ad5 + ; disGetNextSymbol 0xc0ad6 LB 0x3a5c -> off=0x0 cb=000000000000005e uValue=00000000000c0ad6 'vga_find_glyph' +vga_find_glyph: ; 0xc0ad6 LB 0x5e + push bp ; 55 ; 0xc0ad6 vgabios.c:369 + mov bp, sp ; 89 e5 ; 0xc0ad7 + push si ; 56 ; 0xc0ad9 + push di ; 57 ; 0xc0ada + push ax ; 50 ; 0xc0adb + push ax ; 50 ; 0xc0adc + push dx ; 52 ; 0xc0add + push bx ; 53 ; 0xc0ade + mov bl, cl ; 88 cb ; 0xc0adf + mov word [bp-006h], strict word 00000h ; c7 46 fa 00 00 ; 0xc0ae1 vgabios.c:371 + dec word [bp+004h] ; ff 4e 04 ; 0xc0ae6 vgabios.c:373 + cmp word [bp+004h], strict byte 0ffffh ; 83 7e 04 ff ; 0xc0ae9 + je short 00b28h ; 74 39 ; 0xc0aed + mov cl, byte [bp+006h] ; 8a 4e 06 ; 0xc0aef vgabios.c:374 + xor ch, ch ; 30 ed ; 0xc0af2 + mov dx, ss ; 8c d2 ; 0xc0af4 + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc0af6 + mov di, word [bp-008h] ; 8b 7e f8 ; 0xc0af9 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc0afc + push DS ; 1e ; 0xc0aff + mov ds, dx ; 8e da ; 0xc0b00 + rep cmpsb ; f3 a6 ; 0xc0b02 + pop DS ; 1f ; 0xc0b04 + mov ax, strict word 00000h ; b8 00 00 ; 0xc0b05 + je short 00b0ch ; 74 02 ; 0xc0b08 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc0b0a + test ax, ax ; 85 c0 ; 0xc0b0c + jne short 00b1ch ; 75 0c ; 0xc0b0e + mov al, bl ; 88 d8 ; 0xc0b10 vgabios.c:375 + xor ah, ah ; 30 e4 ; 0xc0b12 + or ah, 080h ; 80 cc 80 ; 0xc0b14 + mov word [bp-006h], ax ; 89 46 fa ; 0xc0b17 + jmp short 00b28h ; eb 0c ; 0xc0b1a vgabios.c:376 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc0b1c vgabios.c:378 + xor ah, ah ; 30 e4 ; 0xc0b1f + add word [bp-008h], ax ; 01 46 f8 ; 0xc0b21 + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc0b24 vgabios.c:379 + jmp short 00ae6h ; eb be ; 0xc0b26 vgabios.c:380 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc0b28 vgabios.c:382 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0b2b + pop di ; 5f ; 0xc0b2e + pop si ; 5e ; 0xc0b2f + pop bp ; 5d ; 0xc0b30 + retn 00004h ; c2 04 00 ; 0xc0b31 + ; disGetNextSymbol 0xc0b34 LB 0x39fe -> off=0x0 cb=0000000000000046 uValue=00000000000c0b34 'vga_read_glyph_planar' +vga_read_glyph_planar: ; 0xc0b34 LB 0x46 + push bp ; 55 ; 0xc0b34 vgabios.c:384 + mov bp, sp ; 89 e5 ; 0xc0b35 + push si ; 56 ; 0xc0b37 + push di ; 57 ; 0xc0b38 + push ax ; 50 ; 0xc0b39 + push ax ; 50 ; 0xc0b3a + mov si, ax ; 89 c6 ; 0xc0b3b + mov word [bp-006h], dx ; 89 56 fa ; 0xc0b3d + mov word [bp-008h], bx ; 89 5e f8 ; 0xc0b40 + mov bx, cx ; 89 cb ; 0xc0b43 + mov ax, 00805h ; b8 05 08 ; 0xc0b45 vgabios.c:391 + mov dx, 003ceh ; ba ce 03 ; 0xc0b48 + out DX, ax ; ef ; 0xc0b4b + dec byte [bp+004h] ; fe 4e 04 ; 0xc0b4c vgabios.c:393 + cmp byte [bp+004h], 0ffh ; 80 7e 04 ff ; 0xc0b4f + je short 00b6ah ; 74 15 ; 0xc0b53 + mov es, [bp-006h] ; 8e 46 fa ; 0xc0b55 vgabios.c:394 + mov al, byte [es:si] ; 26 8a 04 ; 0xc0b58 + not al ; f6 d0 ; 0xc0b5b + mov di, bx ; 89 df ; 0xc0b5d + inc bx ; 43 ; 0xc0b5f + push SS ; 16 ; 0xc0b60 + pop ES ; 07 ; 0xc0b61 + mov byte [es:di], al ; 26 88 05 ; 0xc0b62 + add si, word [bp-008h] ; 03 76 f8 ; 0xc0b65 vgabios.c:395 + jmp short 00b4ch ; eb e2 ; 0xc0b68 vgabios.c:396 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0b6a vgabios.c:399 + mov dx, 003ceh ; ba ce 03 ; 0xc0b6d + out DX, ax ; ef ; 0xc0b70 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0b71 vgabios.c:400 + pop di ; 5f ; 0xc0b74 + pop si ; 5e ; 0xc0b75 + pop bp ; 5d ; 0xc0b76 + retn 00002h ; c2 02 00 ; 0xc0b77 + ; disGetNextSymbol 0xc0b7a LB 0x39b8 -> off=0x0 cb=000000000000002f uValue=00000000000c0b7a 'vga_char_ofs_planar' +vga_char_ofs_planar: ; 0xc0b7a LB 0x2f + push si ; 56 ; 0xc0b7a vgabios.c:402 + push bp ; 55 ; 0xc0b7b + mov bp, sp ; 89 e5 ; 0xc0b7c + mov ch, al ; 88 c5 ; 0xc0b7e + mov al, dl ; 88 d0 ; 0xc0b80 + xor ah, ah ; 30 e4 ; 0xc0b82 vgabios.c:406 + mul bx ; f7 e3 ; 0xc0b84 + mov bl, byte [bp+006h] ; 8a 5e 06 ; 0xc0b86 + xor bh, bh ; 30 ff ; 0xc0b89 + mul bx ; f7 e3 ; 0xc0b8b + mov bl, ch ; 88 eb ; 0xc0b8d + add bx, ax ; 01 c3 ; 0xc0b8f + mov si, strict word 0004ch ; be 4c 00 ; 0xc0b91 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0b94 + mov es, ax ; 8e c0 ; 0xc0b97 + mov si, word [es:si] ; 26 8b 34 ; 0xc0b99 + mov al, cl ; 88 c8 ; 0xc0b9c vgabios.c:58 + xor ah, ah ; 30 e4 ; 0xc0b9e + mul si ; f7 e6 ; 0xc0ba0 + add ax, bx ; 01 d8 ; 0xc0ba2 + pop bp ; 5d ; 0xc0ba4 vgabios.c:410 + pop si ; 5e ; 0xc0ba5 + retn 00002h ; c2 02 00 ; 0xc0ba6 + ; disGetNextSymbol 0xc0ba9 LB 0x3989 -> off=0x0 cb=0000000000000040 uValue=00000000000c0ba9 'vga_read_char_planar' +vga_read_char_planar: ; 0xc0ba9 LB 0x40 + push bp ; 55 ; 0xc0ba9 vgabios.c:412 + mov bp, sp ; 89 e5 ; 0xc0baa + push cx ; 51 ; 0xc0bac + sub sp, strict byte 00012h ; 83 ec 12 ; 0xc0bad + mov byte [bp-004h], bl ; 88 5e fc ; 0xc0bb0 vgabios.c:416 + mov byte [bp-003h], 000h ; c6 46 fd 00 ; 0xc0bb3 + push word [bp-004h] ; ff 76 fc ; 0xc0bb7 + lea cx, [bp-014h] ; 8d 4e ec ; 0xc0bba + mov bx, ax ; 89 c3 ; 0xc0bbd + mov ax, dx ; 89 d0 ; 0xc0bbf + mov dx, 0a000h ; ba 00 a0 ; 0xc0bc1 + call 00b34h ; e8 6d ff ; 0xc0bc4 + push word [bp-004h] ; ff 76 fc ; 0xc0bc7 vgabios.c:419 + push 00100h ; 68 00 01 ; 0xc0bca + mov bx, 0010ch ; bb 0c 01 ; 0xc0bcd vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0bd0 + mov es, ax ; 8e c0 ; 0xc0bd2 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0bd4 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0bd7 + xor cx, cx ; 31 c9 ; 0xc0bdb vgabios.c:68 + lea bx, [bp-014h] ; 8d 5e ec ; 0xc0bdd + call 00ad6h ; e8 f3 fe ; 0xc0be0 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc0be3 vgabios.c:420 + pop cx ; 59 ; 0xc0be6 + pop bp ; 5d ; 0xc0be7 + retn ; c3 ; 0xc0be8 + ; disGetNextSymbol 0xc0be9 LB 0x3949 -> off=0x0 cb=0000000000000024 uValue=00000000000c0be9 'vga_char_ofs_linear' +vga_char_ofs_linear: ; 0xc0be9 LB 0x24 + enter 00002h, 000h ; c8 02 00 00 ; 0xc0be9 vgabios.c:422 + mov byte [bp-002h], al ; 88 46 fe ; 0xc0bed + mov al, dl ; 88 d0 ; 0xc0bf0 vgabios.c:426 + xor ah, ah ; 30 e4 ; 0xc0bf2 + mul bx ; f7 e3 ; 0xc0bf4 + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc0bf6 + xor dh, dh ; 30 f6 ; 0xc0bf9 + mul dx ; f7 e2 ; 0xc0bfb + mov dx, ax ; 89 c2 ; 0xc0bfd + mov al, byte [bp-002h] ; 8a 46 fe ; 0xc0bff + xor ah, ah ; 30 e4 ; 0xc0c02 + add ax, dx ; 01 d0 ; 0xc0c04 + sal ax, 003h ; c1 e0 03 ; 0xc0c06 vgabios.c:427 + leave ; c9 ; 0xc0c09 vgabios.c:429 + retn 00002h ; c2 02 00 ; 0xc0c0a + ; disGetNextSymbol 0xc0c0d LB 0x3925 -> off=0x0 cb=000000000000004b uValue=00000000000c0c0d 'vga_read_glyph_linear' +vga_read_glyph_linear: ; 0xc0c0d LB 0x4b + push si ; 56 ; 0xc0c0d vgabios.c:431 + push di ; 57 ; 0xc0c0e + enter 00004h, 000h ; c8 04 00 00 ; 0xc0c0f + mov si, ax ; 89 c6 ; 0xc0c13 + mov word [bp-002h], dx ; 89 56 fe ; 0xc0c15 + mov word [bp-004h], bx ; 89 5e fc ; 0xc0c18 + mov bx, cx ; 89 cb ; 0xc0c1b + dec byte [bp+008h] ; fe 4e 08 ; 0xc0c1d vgabios.c:437 + cmp byte [bp+008h], 0ffh ; 80 7e 08 ff ; 0xc0c20 + je short 00c52h ; 74 2c ; 0xc0c24 + xor dh, dh ; 30 f6 ; 0xc0c26 vgabios.c:438 + mov DL, strict byte 080h ; b2 80 ; 0xc0c28 vgabios.c:439 + xor ax, ax ; 31 c0 ; 0xc0c2a vgabios.c:440 + jmp short 00c33h ; eb 05 ; 0xc0c2c + cmp ax, strict word 00008h ; 3d 08 00 ; 0xc0c2e + jnl short 00c47h ; 7d 14 ; 0xc0c31 + mov es, [bp-002h] ; 8e 46 fe ; 0xc0c33 vgabios.c:441 + mov di, si ; 89 f7 ; 0xc0c36 + add di, ax ; 01 c7 ; 0xc0c38 + cmp byte [es:di], 000h ; 26 80 3d 00 ; 0xc0c3a + je short 00c42h ; 74 02 ; 0xc0c3e + or dh, dl ; 08 d6 ; 0xc0c40 vgabios.c:442 + shr dl, 1 ; d0 ea ; 0xc0c42 vgabios.c:443 + inc ax ; 40 ; 0xc0c44 vgabios.c:444 + jmp short 00c2eh ; eb e7 ; 0xc0c45 + mov di, bx ; 89 df ; 0xc0c47 vgabios.c:445 + inc bx ; 43 ; 0xc0c49 + mov byte [ss:di], dh ; 36 88 35 ; 0xc0c4a + add si, word [bp-004h] ; 03 76 fc ; 0xc0c4d vgabios.c:446 + jmp short 00c1dh ; eb cb ; 0xc0c50 vgabios.c:447 + leave ; c9 ; 0xc0c52 vgabios.c:448 + pop di ; 5f ; 0xc0c53 + pop si ; 5e ; 0xc0c54 + retn 00002h ; c2 02 00 ; 0xc0c55 + ; disGetNextSymbol 0xc0c58 LB 0x38da -> off=0x0 cb=0000000000000045 uValue=00000000000c0c58 'vga_read_char_linear' +vga_read_char_linear: ; 0xc0c58 LB 0x45 + push bp ; 55 ; 0xc0c58 vgabios.c:450 + mov bp, sp ; 89 e5 ; 0xc0c59 + push cx ; 51 ; 0xc0c5b + sub sp, strict byte 00012h ; 83 ec 12 ; 0xc0c5c + mov cx, ax ; 89 c1 ; 0xc0c5f + mov ax, dx ; 89 d0 ; 0xc0c61 + mov byte [bp-004h], bl ; 88 5e fc ; 0xc0c63 vgabios.c:454 + mov byte [bp-003h], 000h ; c6 46 fd 00 ; 0xc0c66 + push word [bp-004h] ; ff 76 fc ; 0xc0c6a + mov bx, cx ; 89 cb ; 0xc0c6d + sal bx, 003h ; c1 e3 03 ; 0xc0c6f + lea cx, [bp-014h] ; 8d 4e ec ; 0xc0c72 + mov dx, 0a000h ; ba 00 a0 ; 0xc0c75 + call 00c0dh ; e8 92 ff ; 0xc0c78 + push word [bp-004h] ; ff 76 fc ; 0xc0c7b vgabios.c:457 + push 00100h ; 68 00 01 ; 0xc0c7e + mov bx, 0010ch ; bb 0c 01 ; 0xc0c81 vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0c84 + mov es, ax ; 8e c0 ; 0xc0c86 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0c88 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0c8b + xor cx, cx ; 31 c9 ; 0xc0c8f vgabios.c:68 + lea bx, [bp-014h] ; 8d 5e ec ; 0xc0c91 + call 00ad6h ; e8 3f fe ; 0xc0c94 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc0c97 vgabios.c:458 + pop cx ; 59 ; 0xc0c9a + pop bp ; 5d ; 0xc0c9b + retn ; c3 ; 0xc0c9c + ; disGetNextSymbol 0xc0c9d LB 0x3895 -> off=0x0 cb=0000000000000035 uValue=00000000000c0c9d 'vga_read_2bpp_char' +vga_read_2bpp_char: ; 0xc0c9d LB 0x35 + push bp ; 55 ; 0xc0c9d vgabios.c:460 + mov bp, sp ; 89 e5 ; 0xc0c9e + push bx ; 53 ; 0xc0ca0 + push cx ; 51 ; 0xc0ca1 + mov bx, ax ; 89 c3 ; 0xc0ca2 + mov es, dx ; 8e c2 ; 0xc0ca4 + mov cx, 0c000h ; b9 00 c0 ; 0xc0ca6 vgabios.c:466 + mov DH, strict byte 080h ; b6 80 ; 0xc0ca9 vgabios.c:467 + xor dl, dl ; 30 d2 ; 0xc0cab vgabios.c:468 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0cad vgabios.c:469 + xchg ah, al ; 86 c4 ; 0xc0cb0 + xor bx, bx ; 31 db ; 0xc0cb2 vgabios.c:471 + jmp short 00cbbh ; eb 05 ; 0xc0cb4 + cmp bx, strict byte 00008h ; 83 fb 08 ; 0xc0cb6 + jnl short 00cc9h ; 7d 0e ; 0xc0cb9 + test ax, cx ; 85 c8 ; 0xc0cbb vgabios.c:472 + je short 00cc1h ; 74 02 ; 0xc0cbd + or dl, dh ; 08 f2 ; 0xc0cbf vgabios.c:473 + shr dh, 1 ; d0 ee ; 0xc0cc1 vgabios.c:474 + shr cx, 002h ; c1 e9 02 ; 0xc0cc3 vgabios.c:475 + inc bx ; 43 ; 0xc0cc6 vgabios.c:476 + jmp short 00cb6h ; eb ed ; 0xc0cc7 + mov al, dl ; 88 d0 ; 0xc0cc9 vgabios.c:478 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0ccb + pop cx ; 59 ; 0xc0cce + pop bx ; 5b ; 0xc0ccf + pop bp ; 5d ; 0xc0cd0 + retn ; c3 ; 0xc0cd1 + ; disGetNextSymbol 0xc0cd2 LB 0x3860 -> off=0x0 cb=0000000000000084 uValue=00000000000c0cd2 'vga_read_glyph_cga' +vga_read_glyph_cga: ; 0xc0cd2 LB 0x84 + push bp ; 55 ; 0xc0cd2 vgabios.c:480 + mov bp, sp ; 89 e5 ; 0xc0cd3 + push cx ; 51 ; 0xc0cd5 + push si ; 56 ; 0xc0cd6 + push di ; 57 ; 0xc0cd7 + push ax ; 50 ; 0xc0cd8 + mov si, dx ; 89 d6 ; 0xc0cd9 + cmp bl, 006h ; 80 fb 06 ; 0xc0cdb vgabios.c:488 + je short 00d1ah ; 74 3a ; 0xc0cde + mov bx, ax ; 89 c3 ; 0xc0ce0 vgabios.c:490 + add bx, ax ; 01 c3 ; 0xc0ce2 + mov word [bp-008h], 0b800h ; c7 46 f8 00 b8 ; 0xc0ce4 + xor cx, cx ; 31 c9 ; 0xc0ce9 vgabios.c:492 + jmp short 00cf2h ; eb 05 ; 0xc0ceb + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc0ced + jnl short 00d4eh ; 7d 5c ; 0xc0cf0 + mov ax, bx ; 89 d8 ; 0xc0cf2 vgabios.c:493 + mov dx, word [bp-008h] ; 8b 56 f8 ; 0xc0cf4 + call 00c9dh ; e8 a3 ff ; 0xc0cf7 + mov di, si ; 89 f7 ; 0xc0cfa + inc si ; 46 ; 0xc0cfc + push SS ; 16 ; 0xc0cfd + pop ES ; 07 ; 0xc0cfe + mov byte [es:di], al ; 26 88 05 ; 0xc0cff + lea ax, [bx+02000h] ; 8d 87 00 20 ; 0xc0d02 vgabios.c:494 + mov dx, word [bp-008h] ; 8b 56 f8 ; 0xc0d06 + call 00c9dh ; e8 91 ff ; 0xc0d09 + mov di, si ; 89 f7 ; 0xc0d0c + inc si ; 46 ; 0xc0d0e + push SS ; 16 ; 0xc0d0f + pop ES ; 07 ; 0xc0d10 + mov byte [es:di], al ; 26 88 05 ; 0xc0d11 + add bx, strict byte 00050h ; 83 c3 50 ; 0xc0d14 vgabios.c:495 + inc cx ; 41 ; 0xc0d17 vgabios.c:496 + jmp short 00cedh ; eb d3 ; 0xc0d18 + mov bx, ax ; 89 c3 ; 0xc0d1a vgabios.c:498 + mov word [bp-008h], 0b800h ; c7 46 f8 00 b8 ; 0xc0d1c + xor cx, cx ; 31 c9 ; 0xc0d21 vgabios.c:499 + jmp short 00d2ah ; eb 05 ; 0xc0d23 + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc0d25 + jnl short 00d4eh ; 7d 24 ; 0xc0d28 + mov di, si ; 89 f7 ; 0xc0d2a vgabios.c:500 + inc si ; 46 ; 0xc0d2c + mov es, [bp-008h] ; 8e 46 f8 ; 0xc0d2d + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0d30 + push SS ; 16 ; 0xc0d33 + pop ES ; 07 ; 0xc0d34 + mov byte [es:di], al ; 26 88 05 ; 0xc0d35 + mov di, si ; 89 f7 ; 0xc0d38 vgabios.c:501 + inc si ; 46 ; 0xc0d3a + mov es, [bp-008h] ; 8e 46 f8 ; 0xc0d3b + mov al, byte [es:bx+02000h] ; 26 8a 87 00 20 ; 0xc0d3e + push SS ; 16 ; 0xc0d43 + pop ES ; 07 ; 0xc0d44 + mov byte [es:di], al ; 26 88 05 ; 0xc0d45 + add bx, strict byte 00050h ; 83 c3 50 ; 0xc0d48 vgabios.c:502 + inc cx ; 41 ; 0xc0d4b vgabios.c:503 + jmp short 00d25h ; eb d7 ; 0xc0d4c + lea sp, [bp-006h] ; 8d 66 fa ; 0xc0d4e vgabios.c:505 + pop di ; 5f ; 0xc0d51 + pop si ; 5e ; 0xc0d52 + pop cx ; 59 ; 0xc0d53 + pop bp ; 5d ; 0xc0d54 + retn ; c3 ; 0xc0d55 + ; disGetNextSymbol 0xc0d56 LB 0x37dc -> off=0x0 cb=000000000000001a uValue=00000000000c0d56 'vga_char_ofs_cga' +vga_char_ofs_cga: ; 0xc0d56 LB 0x1a + push cx ; 51 ; 0xc0d56 vgabios.c:507 + push bp ; 55 ; 0xc0d57 + mov bp, sp ; 89 e5 ; 0xc0d58 + mov cl, al ; 88 c1 ; 0xc0d5a + mov al, dl ; 88 d0 ; 0xc0d5c + xor ah, ah ; 30 e4 ; 0xc0d5e vgabios.c:512 + mul bx ; f7 e3 ; 0xc0d60 + mov bx, ax ; 89 c3 ; 0xc0d62 + sal bx, 002h ; c1 e3 02 ; 0xc0d64 + mov al, cl ; 88 c8 ; 0xc0d67 + xor ah, ah ; 30 e4 ; 0xc0d69 + add ax, bx ; 01 d8 ; 0xc0d6b + pop bp ; 5d ; 0xc0d6d vgabios.c:513 + pop cx ; 59 ; 0xc0d6e + retn ; c3 ; 0xc0d6f + ; disGetNextSymbol 0xc0d70 LB 0x37c2 -> off=0x0 cb=0000000000000066 uValue=00000000000c0d70 'vga_read_char_cga' +vga_read_char_cga: ; 0xc0d70 LB 0x66 + push bp ; 55 ; 0xc0d70 vgabios.c:515 + mov bp, sp ; 89 e5 ; 0xc0d71 + push bx ; 53 ; 0xc0d73 + push cx ; 51 ; 0xc0d74 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc0d75 + mov bl, dl ; 88 d3 ; 0xc0d78 vgabios.c:521 + xor bh, bh ; 30 ff ; 0xc0d7a + lea dx, [bp-00eh] ; 8d 56 f2 ; 0xc0d7c + call 00cd2h ; e8 50 ff ; 0xc0d7f + push strict byte 00008h ; 6a 08 ; 0xc0d82 vgabios.c:524 + push 00080h ; 68 80 00 ; 0xc0d84 + mov bx, 0010ch ; bb 0c 01 ; 0xc0d87 vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0d8a + mov es, ax ; 8e c0 ; 0xc0d8c + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0d8e + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0d91 + xor cx, cx ; 31 c9 ; 0xc0d95 vgabios.c:68 + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc0d97 + call 00ad6h ; e8 39 fd ; 0xc0d9a + mov word [bp-006h], ax ; 89 46 fa ; 0xc0d9d + test ah, 080h ; f6 c4 80 ; 0xc0da0 vgabios.c:526 + jne short 00dcch ; 75 27 ; 0xc0da3 + mov bx, strict word 0007ch ; bb 7c 00 ; 0xc0da5 vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0da8 + mov es, ax ; 8e c0 ; 0xc0daa + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0dac + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0daf + test dx, dx ; 85 d2 ; 0xc0db3 vgabios.c:530 + jne short 00dbbh ; 75 04 ; 0xc0db5 + test ax, ax ; 85 c0 ; 0xc0db7 + je short 00dcch ; 74 11 ; 0xc0db9 + push strict byte 00008h ; 6a 08 ; 0xc0dbb vgabios.c:531 + push 00080h ; 68 80 00 ; 0xc0dbd + mov cx, 00080h ; b9 80 00 ; 0xc0dc0 + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc0dc3 + call 00ad6h ; e8 0d fd ; 0xc0dc6 + mov word [bp-006h], ax ; 89 46 fa ; 0xc0dc9 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc0dcc vgabios.c:534 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0dcf + pop cx ; 59 ; 0xc0dd2 + pop bx ; 5b ; 0xc0dd3 + pop bp ; 5d ; 0xc0dd4 + retn ; c3 ; 0xc0dd5 + ; disGetNextSymbol 0xc0dd6 LB 0x375c -> off=0x0 cb=0000000000000130 uValue=00000000000c0dd6 'vga_read_char_attr' +vga_read_char_attr: ; 0xc0dd6 LB 0x130 + push bp ; 55 ; 0xc0dd6 vgabios.c:536 + mov bp, sp ; 89 e5 ; 0xc0dd7 + push bx ; 53 ; 0xc0dd9 + push cx ; 51 ; 0xc0dda + push si ; 56 ; 0xc0ddb + push di ; 57 ; 0xc0ddc + sub sp, strict byte 00014h ; 83 ec 14 ; 0xc0ddd + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc0de0 + mov si, dx ; 89 d6 ; 0xc0de3 + mov bx, strict word 00049h ; bb 49 00 ; 0xc0de5 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0de8 + mov es, ax ; 8e c0 ; 0xc0deb + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0ded + mov byte [bp-010h], al ; 88 46 f0 ; 0xc0df0 vgabios.c:48 + xor ah, ah ; 30 e4 ; 0xc0df3 vgabios.c:544 + call 03819h ; e8 21 2a ; 0xc0df5 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc0df8 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc0dfb vgabios.c:545 + jne short 00e02h ; 75 03 ; 0xc0dfd + jmp near 00efdh ; e9 fb 00 ; 0xc0dff + mov cl, byte [bp-00eh] ; 8a 4e f2 ; 0xc0e02 vgabios.c:549 + xor ch, ch ; 30 ed ; 0xc0e05 + lea bx, [bp-01ch] ; 8d 5e e4 ; 0xc0e07 + lea dx, [bp-01ah] ; 8d 56 e6 ; 0xc0e0a + mov ax, cx ; 89 c8 ; 0xc0e0d + call 00a96h ; e8 84 fc ; 0xc0e0f + mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xc0e12 vgabios.c:550 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc0e15 + mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xc0e18 vgabios.c:551 + xor al, al ; 30 c0 ; 0xc0e1b + shr ax, 008h ; c1 e8 08 ; 0xc0e1d + mov word [bp-016h], ax ; 89 46 ea ; 0xc0e20 + mov dl, byte [bp-016h] ; 8a 56 ea ; 0xc0e23 + mov bx, 00084h ; bb 84 00 ; 0xc0e26 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0e29 + mov es, ax ; 8e c0 ; 0xc0e2c + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0e2e + xor ah, ah ; 30 e4 ; 0xc0e31 vgabios.c:48 + inc ax ; 40 ; 0xc0e33 + mov word [bp-014h], ax ; 89 46 ec ; 0xc0e34 + mov di, strict word 0004ah ; bf 4a 00 ; 0xc0e37 vgabios.c:57 + mov di, word [es:di] ; 26 8b 3d ; 0xc0e3a + mov word [bp-018h], di ; 89 7e e8 ; 0xc0e3d vgabios.c:58 + mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xc0e40 vgabios.c:557 + xor bh, bh ; 30 ff ; 0xc0e43 + sal bx, 003h ; c1 e3 03 ; 0xc0e45 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc0e48 + jne short 00e7fh ; 75 30 ; 0xc0e4d + mov ax, di ; 89 f8 ; 0xc0e4f vgabios.c:559 + mul word [bp-014h] ; f7 66 ec ; 0xc0e51 + add ax, ax ; 01 c0 ; 0xc0e54 + or AL, strict byte 0ffh ; 0c ff ; 0xc0e56 + inc ax ; 40 ; 0xc0e58 + mul cx ; f7 e1 ; 0xc0e59 + mov cx, ax ; 89 c1 ; 0xc0e5b + mov al, byte [bp-016h] ; 8a 46 ea ; 0xc0e5d + xor ah, ah ; 30 e4 ; 0xc0e60 + mul di ; f7 e7 ; 0xc0e62 + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc0e64 + xor dh, dh ; 30 f6 ; 0xc0e67 + mov di, ax ; 89 c7 ; 0xc0e69 + add di, dx ; 01 d7 ; 0xc0e6b + add di, di ; 01 ff ; 0xc0e6d + add di, cx ; 01 cf ; 0xc0e6f + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc0e71 vgabios.c:55 + mov ax, word [es:di] ; 26 8b 05 ; 0xc0e75 + push SS ; 16 ; 0xc0e78 vgabios.c:58 + pop ES ; 07 ; 0xc0e79 + mov word [es:si], ax ; 26 89 04 ; 0xc0e7a + jmp short 00dffh ; eb 80 ; 0xc0e7d vgabios.c:561 + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc0e7f vgabios.c:562 + cmp bl, 005h ; 80 fb 05 ; 0xc0e83 + je short 00ed6h ; 74 4e ; 0xc0e86 + cmp bl, 002h ; 80 fb 02 ; 0xc0e88 + jc short 00efdh ; 72 70 ; 0xc0e8b + jbe short 00e96h ; 76 07 ; 0xc0e8d + cmp bl, 004h ; 80 fb 04 ; 0xc0e8f + jbe short 00eafh ; 76 1b ; 0xc0e92 + jmp short 00efdh ; eb 67 ; 0xc0e94 + xor dh, dh ; 30 f6 ; 0xc0e96 vgabios.c:565 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc0e98 + xor ah, ah ; 30 e4 ; 0xc0e9b + mov bx, word [bp-018h] ; 8b 5e e8 ; 0xc0e9d + call 00d56h ; e8 b3 fe ; 0xc0ea0 + mov dl, byte [bp-010h] ; 8a 56 f0 ; 0xc0ea3 vgabios.c:566 + xor dh, dh ; 30 f6 ; 0xc0ea6 + call 00d70h ; e8 c5 fe ; 0xc0ea8 + xor ah, ah ; 30 e4 ; 0xc0eab + jmp short 00e78h ; eb c9 ; 0xc0ead + mov bx, 00085h ; bb 85 00 ; 0xc0eaf vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0eb2 + mov byte [bp-012h], al ; 88 46 ee ; 0xc0eb5 vgabios.c:571 + mov byte [bp-011h], ch ; 88 6e ef ; 0xc0eb8 + push word [bp-012h] ; ff 76 ee ; 0xc0ebb + xor dh, dh ; 30 f6 ; 0xc0ebe + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc0ec0 + xor ah, ah ; 30 e4 ; 0xc0ec3 + mov bx, di ; 89 fb ; 0xc0ec5 + call 00b7ah ; e8 b0 fc ; 0xc0ec7 + mov bx, word [bp-012h] ; 8b 5e ee ; 0xc0eca vgabios.c:572 + mov dx, ax ; 89 c2 ; 0xc0ecd + mov ax, di ; 89 f8 ; 0xc0ecf + call 00ba9h ; e8 d5 fc ; 0xc0ed1 + jmp short 00eabh ; eb d5 ; 0xc0ed4 + mov bx, 00085h ; bb 85 00 ; 0xc0ed6 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0ed9 + mov byte [bp-012h], al ; 88 46 ee ; 0xc0edc vgabios.c:576 + mov byte [bp-011h], ch ; 88 6e ef ; 0xc0edf + push word [bp-012h] ; ff 76 ee ; 0xc0ee2 + xor dh, dh ; 30 f6 ; 0xc0ee5 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc0ee7 + xor ah, ah ; 30 e4 ; 0xc0eea + mov bx, di ; 89 fb ; 0xc0eec + call 00be9h ; e8 f8 fc ; 0xc0eee + mov bx, word [bp-012h] ; 8b 5e ee ; 0xc0ef1 vgabios.c:577 + mov dx, ax ; 89 c2 ; 0xc0ef4 + mov ax, di ; 89 f8 ; 0xc0ef6 + call 00c58h ; e8 5d fd ; 0xc0ef8 + jmp short 00eabh ; eb ae ; 0xc0efb + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc0efd vgabios.c:586 + pop di ; 5f ; 0xc0f00 + pop si ; 5e ; 0xc0f01 + pop cx ; 59 ; 0xc0f02 + pop bx ; 5b ; 0xc0f03 + pop bp ; 5d ; 0xc0f04 + retn ; c3 ; 0xc0f05 + ; disGetNextSymbol 0xc0f06 LB 0x362c -> off=0x10 cb=0000000000000083 uValue=00000000000c0f16 'vga_get_font_info' + db 02dh, 00fh, 072h, 00fh, 077h, 00fh, 07eh, 00fh, 083h, 00fh, 088h, 00fh, 08dh, 00fh, 092h, 00fh +vga_get_font_info: ; 0xc0f16 LB 0x83 + push si ; 56 ; 0xc0f16 vgabios.c:588 + push di ; 57 ; 0xc0f17 + push bp ; 55 ; 0xc0f18 + mov bp, sp ; 89 e5 ; 0xc0f19 + mov si, dx ; 89 d6 ; 0xc0f1b + mov di, bx ; 89 df ; 0xc0f1d + cmp ax, strict word 00007h ; 3d 07 00 ; 0xc0f1f vgabios.c:593 + jnbe short 00f6ch ; 77 48 ; 0xc0f22 + mov bx, ax ; 89 c3 ; 0xc0f24 + add bx, ax ; 01 c3 ; 0xc0f26 + jmp word [cs:bx+00f06h] ; 2e ff a7 06 0f ; 0xc0f28 + mov bx, strict word 0007ch ; bb 7c 00 ; 0xc0f2d vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0f30 + mov es, ax ; 8e c0 ; 0xc0f32 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc0f34 + mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xc0f37 + push SS ; 16 ; 0xc0f3b vgabios.c:596 + pop ES ; 07 ; 0xc0f3c + mov word [es:di], dx ; 26 89 15 ; 0xc0f3d + mov word [es:si], ax ; 26 89 04 ; 0xc0f40 + mov bx, 00085h ; bb 85 00 ; 0xc0f43 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0f46 + mov es, ax ; 8e c0 ; 0xc0f49 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0f4b + xor ah, ah ; 30 e4 ; 0xc0f4e + push SS ; 16 ; 0xc0f50 + pop ES ; 07 ; 0xc0f51 + mov bx, cx ; 89 cb ; 0xc0f52 + mov word [es:bx], ax ; 26 89 07 ; 0xc0f54 + mov bx, 00084h ; bb 84 00 ; 0xc0f57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0f5a + mov es, ax ; 8e c0 ; 0xc0f5d + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0f5f + xor ah, ah ; 30 e4 ; 0xc0f62 + push SS ; 16 ; 0xc0f64 + pop ES ; 07 ; 0xc0f65 + mov bx, word [bp+008h] ; 8b 5e 08 ; 0xc0f66 + mov word [es:bx], ax ; 26 89 07 ; 0xc0f69 + pop bp ; 5d ; 0xc0f6c + pop di ; 5f ; 0xc0f6d + pop si ; 5e ; 0xc0f6e + retn 00002h ; c2 02 00 ; 0xc0f6f + mov bx, 0010ch ; bb 0c 01 ; 0xc0f72 vgabios.c:67 + jmp short 00f30h ; eb b9 ; 0xc0f75 + mov dx, 05d6dh ; ba 6d 5d ; 0xc0f77 vgabios.c:601 + mov ax, ds ; 8c d8 ; 0xc0f7a + jmp short 00f3bh ; eb bd ; 0xc0f7c vgabios.c:602 + mov dx, 0556dh ; ba 6d 55 ; 0xc0f7e vgabios.c:604 + jmp short 00f7ah ; eb f7 ; 0xc0f81 + mov dx, 0596dh ; ba 6d 59 ; 0xc0f83 vgabios.c:607 + jmp short 00f7ah ; eb f2 ; 0xc0f86 + mov dx, 07b6dh ; ba 6d 7b ; 0xc0f88 vgabios.c:610 + jmp short 00f7ah ; eb ed ; 0xc0f8b + mov dx, 06b6dh ; ba 6d 6b ; 0xc0f8d vgabios.c:613 + jmp short 00f7ah ; eb e8 ; 0xc0f90 + mov dx, 07c9ah ; ba 9a 7c ; 0xc0f92 vgabios.c:616 + jmp short 00f7ah ; eb e3 ; 0xc0f95 + jmp short 00f6ch ; eb d3 ; 0xc0f97 vgabios.c:622 + ; disGetNextSymbol 0xc0f99 LB 0x3599 -> off=0x0 cb=0000000000000166 uValue=00000000000c0f99 'vga_read_pixel' +vga_read_pixel: ; 0xc0f99 LB 0x166 + push bp ; 55 ; 0xc0f99 vgabios.c:635 + mov bp, sp ; 89 e5 ; 0xc0f9a + push si ; 56 ; 0xc0f9c + push di ; 57 ; 0xc0f9d + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc0f9e + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc0fa1 + mov si, dx ; 89 d6 ; 0xc0fa4 + mov dx, bx ; 89 da ; 0xc0fa6 + mov word [bp-00ch], cx ; 89 4e f4 ; 0xc0fa8 + mov bx, strict word 00049h ; bb 49 00 ; 0xc0fab vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0fae + mov es, ax ; 8e c0 ; 0xc0fb1 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0fb3 + xor ah, ah ; 30 e4 ; 0xc0fb6 vgabios.c:642 + call 03819h ; e8 5e 28 ; 0xc0fb8 + mov ah, al ; 88 c4 ; 0xc0fbb + cmp AL, strict byte 0ffh ; 3c ff ; 0xc0fbd vgabios.c:643 + je short 00fcfh ; 74 0e ; 0xc0fbf + mov bl, al ; 88 c3 ; 0xc0fc1 vgabios.c:645 + xor bh, bh ; 30 ff ; 0xc0fc3 + sal bx, 003h ; c1 e3 03 ; 0xc0fc5 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc0fc8 + jne short 00fd2h ; 75 03 ; 0xc0fcd + jmp near 010f8h ; e9 26 01 ; 0xc0fcf vgabios.c:646 + mov ch, byte [bx+047b1h] ; 8a af b1 47 ; 0xc0fd2 vgabios.c:649 + cmp ch, 003h ; 80 fd 03 ; 0xc0fd6 + jc short 00feah ; 72 0f ; 0xc0fd9 + jbe short 00ff2h ; 76 15 ; 0xc0fdb + cmp ch, 005h ; 80 fd 05 ; 0xc0fdd + je short 01029h ; 74 47 ; 0xc0fe0 + cmp ch, 004h ; 80 fd 04 ; 0xc0fe2 + je short 00ff2h ; 74 0b ; 0xc0fe5 + jmp near 010eeh ; e9 04 01 ; 0xc0fe7 + cmp ch, 002h ; 80 fd 02 ; 0xc0fea + je short 01060h ; 74 71 ; 0xc0fed + jmp near 010eeh ; e9 fc 00 ; 0xc0fef + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc0ff2 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0ff5 + mov es, ax ; 8e c0 ; 0xc0ff8 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc0ffa + mov ax, dx ; 89 d0 ; 0xc0ffd vgabios.c:58 + mul bx ; f7 e3 ; 0xc0fff + mov bx, si ; 89 f3 ; 0xc1001 + shr bx, 003h ; c1 eb 03 ; 0xc1003 + add bx, ax ; 01 c3 ; 0xc1006 + mov di, strict word 0004ch ; bf 4c 00 ; 0xc1008 vgabios.c:57 + mov ax, word [es:di] ; 26 8b 05 ; 0xc100b + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc100e vgabios.c:58 + xor dh, dh ; 30 f6 ; 0xc1011 + mul dx ; f7 e2 ; 0xc1013 + add bx, ax ; 01 c3 ; 0xc1015 + mov cx, si ; 89 f1 ; 0xc1017 vgabios.c:654 + and cx, strict byte 00007h ; 83 e1 07 ; 0xc1019 + mov ax, 00080h ; b8 80 00 ; 0xc101c + sar ax, CL ; d3 f8 ; 0xc101f + mov byte [bp-008h], al ; 88 46 f8 ; 0xc1021 + mov byte [bp-006h], ch ; 88 6e fa ; 0xc1024 vgabios.c:656 + jmp short 01032h ; eb 09 ; 0xc1027 + jmp near 010ceh ; e9 a2 00 ; 0xc1029 + cmp byte [bp-006h], 004h ; 80 7e fa 04 ; 0xc102c + jnc short 0105dh ; 73 2b ; 0xc1030 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1032 vgabios.c:657 + xor ah, ah ; 30 e4 ; 0xc1035 + sal ax, 008h ; c1 e0 08 ; 0xc1037 + or AL, strict byte 004h ; 0c 04 ; 0xc103a + mov dx, 003ceh ; ba ce 03 ; 0xc103c + out DX, ax ; ef ; 0xc103f + mov ax, 0a000h ; b8 00 a0 ; 0xc1040 vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc1043 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1045 + and al, byte [bp-008h] ; 22 46 f8 ; 0xc1048 vgabios.c:48 + test al, al ; 84 c0 ; 0xc104b vgabios.c:659 + jbe short 01058h ; 76 09 ; 0xc104d + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc104f vgabios.c:660 + mov AL, strict byte 001h ; b0 01 ; 0xc1052 + sal al, CL ; d2 e0 ; 0xc1054 + or ch, al ; 08 c5 ; 0xc1056 + inc byte [bp-006h] ; fe 46 fa ; 0xc1058 vgabios.c:661 + jmp short 0102ch ; eb cf ; 0xc105b + jmp near 010f0h ; e9 90 00 ; 0xc105d + mov cl, byte [bx+047b2h] ; 8a 8f b2 47 ; 0xc1060 vgabios.c:664 + xor ch, ch ; 30 ed ; 0xc1064 + mov bx, strict word 00004h ; bb 04 00 ; 0xc1066 + sub bx, cx ; 29 cb ; 0xc1069 + mov cx, bx ; 89 d9 ; 0xc106b + mov bx, si ; 89 f3 ; 0xc106d + shr bx, CL ; d3 eb ; 0xc106f + mov cx, bx ; 89 d9 ; 0xc1071 + mov bx, dx ; 89 d3 ; 0xc1073 + shr bx, 1 ; d1 eb ; 0xc1075 + imul bx, bx, strict byte 00050h ; 6b db 50 ; 0xc1077 + add bx, cx ; 01 cb ; 0xc107a + test dl, 001h ; f6 c2 01 ; 0xc107c vgabios.c:665 + je short 01084h ; 74 03 ; 0xc107f + add bh, 020h ; 80 c7 20 ; 0xc1081 vgabios.c:666 + mov dx, 0b800h ; ba 00 b8 ; 0xc1084 vgabios.c:47 + mov es, dx ; 8e c2 ; 0xc1087 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1089 + mov bl, ah ; 88 e3 ; 0xc108c vgabios.c:668 + xor bh, bh ; 30 ff ; 0xc108e + sal bx, 003h ; c1 e3 03 ; 0xc1090 + cmp byte [bx+047b2h], 002h ; 80 bf b2 47 02 ; 0xc1093 + jne short 010b5h ; 75 1b ; 0xc1098 + mov cx, si ; 89 f1 ; 0xc109a vgabios.c:669 + xor ch, ch ; 30 ed ; 0xc109c + and cl, 003h ; 80 e1 03 ; 0xc109e + mov dx, strict word 00003h ; ba 03 00 ; 0xc10a1 + sub dx, cx ; 29 ca ; 0xc10a4 + mov cx, dx ; 89 d1 ; 0xc10a6 + add cx, dx ; 01 d1 ; 0xc10a8 + xor ah, ah ; 30 e4 ; 0xc10aa + sar ax, CL ; d3 f8 ; 0xc10ac + mov ch, al ; 88 c5 ; 0xc10ae + and ch, 003h ; 80 e5 03 ; 0xc10b0 + jmp short 010f0h ; eb 3b ; 0xc10b3 vgabios.c:670 + mov cx, si ; 89 f1 ; 0xc10b5 vgabios.c:671 + xor ch, ch ; 30 ed ; 0xc10b7 + and cl, 007h ; 80 e1 07 ; 0xc10b9 + mov dx, strict word 00007h ; ba 07 00 ; 0xc10bc + sub dx, cx ; 29 ca ; 0xc10bf + mov cx, dx ; 89 d1 ; 0xc10c1 + xor ah, ah ; 30 e4 ; 0xc10c3 + sar ax, CL ; d3 f8 ; 0xc10c5 + mov ch, al ; 88 c5 ; 0xc10c7 + and ch, 001h ; 80 e5 01 ; 0xc10c9 + jmp short 010f0h ; eb 22 ; 0xc10cc vgabios.c:672 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc10ce vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc10d1 + mov es, ax ; 8e c0 ; 0xc10d4 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc10d6 + sal bx, 003h ; c1 e3 03 ; 0xc10d9 vgabios.c:58 + mov ax, dx ; 89 d0 ; 0xc10dc + mul bx ; f7 e3 ; 0xc10de + mov bx, si ; 89 f3 ; 0xc10e0 + add bx, ax ; 01 c3 ; 0xc10e2 + mov ax, 0a000h ; b8 00 a0 ; 0xc10e4 vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc10e7 + mov ch, byte [es:bx] ; 26 8a 2f ; 0xc10e9 + jmp short 010f0h ; eb 02 ; 0xc10ec vgabios.c:676 + xor ch, ch ; 30 ed ; 0xc10ee vgabios.c:681 + push SS ; 16 ; 0xc10f0 vgabios.c:683 + pop ES ; 07 ; 0xc10f1 + mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xc10f2 + mov byte [es:bx], ch ; 26 88 2f ; 0xc10f5 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc10f8 vgabios.c:684 + pop di ; 5f ; 0xc10fb + pop si ; 5e ; 0xc10fc + pop bp ; 5d ; 0xc10fd + retn ; c3 ; 0xc10fe + ; disGetNextSymbol 0xc10ff LB 0x3433 -> off=0x0 cb=000000000000008d uValue=00000000000c10ff 'biosfn_perform_gray_scale_summing' +biosfn_perform_gray_scale_summing: ; 0xc10ff LB 0x8d + push bp ; 55 ; 0xc10ff vgabios.c:689 + mov bp, sp ; 89 e5 ; 0xc1100 + push bx ; 53 ; 0xc1102 + push cx ; 51 ; 0xc1103 + push si ; 56 ; 0xc1104 + push di ; 57 ; 0xc1105 + push ax ; 50 ; 0xc1106 + push ax ; 50 ; 0xc1107 + mov bx, ax ; 89 c3 ; 0xc1108 + mov di, dx ; 89 d7 ; 0xc110a + mov dx, 003dah ; ba da 03 ; 0xc110c vgabios.c:694 + in AL, DX ; ec ; 0xc110f + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1110 + xor al, al ; 30 c0 ; 0xc1112 vgabios.c:695 + mov dx, 003c0h ; ba c0 03 ; 0xc1114 + out DX, AL ; ee ; 0xc1117 + xor si, si ; 31 f6 ; 0xc1118 vgabios.c:697 + cmp si, di ; 39 fe ; 0xc111a + jnc short 01171h ; 73 53 ; 0xc111c + mov al, bl ; 88 d8 ; 0xc111e vgabios.c:700 + mov dx, 003c7h ; ba c7 03 ; 0xc1120 + out DX, AL ; ee ; 0xc1123 + mov dx, 003c9h ; ba c9 03 ; 0xc1124 vgabios.c:702 + in AL, DX ; ec ; 0xc1127 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1128 + mov cx, ax ; 89 c1 ; 0xc112a + in AL, DX ; ec ; 0xc112c vgabios.c:703 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc112d + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc112f + in AL, DX ; ec ; 0xc1132 vgabios.c:704 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1133 + xor ch, ch ; 30 ed ; 0xc1135 vgabios.c:707 + imul cx, cx, strict byte 0004dh ; 6b c9 4d ; 0xc1137 + mov word [bp-00ah], cx ; 89 4e f6 ; 0xc113a + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc113d + xor ch, ch ; 30 ed ; 0xc1140 + imul cx, cx, 00097h ; 69 c9 97 00 ; 0xc1142 + add cx, word [bp-00ah] ; 03 4e f6 ; 0xc1146 + xor ah, ah ; 30 e4 ; 0xc1149 + imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xc114b + add cx, ax ; 01 c1 ; 0xc114e + add cx, 00080h ; 81 c1 80 00 ; 0xc1150 + sar cx, 008h ; c1 f9 08 ; 0xc1154 + cmp cx, strict byte 0003fh ; 83 f9 3f ; 0xc1157 vgabios.c:709 + jbe short 0115fh ; 76 03 ; 0xc115a + mov cx, strict word 0003fh ; b9 3f 00 ; 0xc115c + mov al, bl ; 88 d8 ; 0xc115f vgabios.c:712 + mov dx, 003c8h ; ba c8 03 ; 0xc1161 + out DX, AL ; ee ; 0xc1164 + mov al, cl ; 88 c8 ; 0xc1165 vgabios.c:714 + mov dx, 003c9h ; ba c9 03 ; 0xc1167 + out DX, AL ; ee ; 0xc116a + out DX, AL ; ee ; 0xc116b vgabios.c:715 + out DX, AL ; ee ; 0xc116c vgabios.c:716 + inc bx ; 43 ; 0xc116d vgabios.c:717 + inc si ; 46 ; 0xc116e vgabios.c:718 + jmp short 0111ah ; eb a9 ; 0xc116f + mov dx, 003dah ; ba da 03 ; 0xc1171 vgabios.c:719 + in AL, DX ; ec ; 0xc1174 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1175 + mov AL, strict byte 020h ; b0 20 ; 0xc1177 vgabios.c:720 + mov dx, 003c0h ; ba c0 03 ; 0xc1179 + out DX, AL ; ee ; 0xc117c + mov dx, 003dah ; ba da 03 ; 0xc117d vgabios.c:722 + in AL, DX ; ec ; 0xc1180 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1181 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc1183 vgabios.c:724 + pop di ; 5f ; 0xc1186 + pop si ; 5e ; 0xc1187 + pop cx ; 59 ; 0xc1188 + pop bx ; 5b ; 0xc1189 + pop bp ; 5d ; 0xc118a + retn ; c3 ; 0xc118b + ; disGetNextSymbol 0xc118c LB 0x33a6 -> off=0x0 cb=0000000000000107 uValue=00000000000c118c 'biosfn_set_cursor_shape' +biosfn_set_cursor_shape: ; 0xc118c LB 0x107 + push bp ; 55 ; 0xc118c vgabios.c:727 + mov bp, sp ; 89 e5 ; 0xc118d + push bx ; 53 ; 0xc118f + push cx ; 51 ; 0xc1190 + push si ; 56 ; 0xc1191 + push ax ; 50 ; 0xc1192 + push ax ; 50 ; 0xc1193 + mov bl, al ; 88 c3 ; 0xc1194 + mov ah, dl ; 88 d4 ; 0xc1196 + mov dl, al ; 88 c2 ; 0xc1198 vgabios.c:733 + xor dh, dh ; 30 f6 ; 0xc119a + mov cx, dx ; 89 d1 ; 0xc119c + sal cx, 008h ; c1 e1 08 ; 0xc119e + mov dl, ah ; 88 e2 ; 0xc11a1 + add dx, cx ; 01 ca ; 0xc11a3 + mov si, strict word 00060h ; be 60 00 ; 0xc11a5 vgabios.c:62 + mov cx, strict word 00040h ; b9 40 00 ; 0xc11a8 + mov es, cx ; 8e c1 ; 0xc11ab + mov word [es:si], dx ; 26 89 14 ; 0xc11ad + mov si, 00087h ; be 87 00 ; 0xc11b0 vgabios.c:47 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc11b3 + test dl, 008h ; f6 c2 08 ; 0xc11b6 vgabios.c:48 + jne short 011f8h ; 75 3d ; 0xc11b9 + mov dl, al ; 88 c2 ; 0xc11bb vgabios.c:739 + and dl, 060h ; 80 e2 60 ; 0xc11bd + cmp dl, 020h ; 80 fa 20 ; 0xc11c0 + jne short 011cbh ; 75 06 ; 0xc11c3 + mov BL, strict byte 01eh ; b3 1e ; 0xc11c5 vgabios.c:741 + xor ah, ah ; 30 e4 ; 0xc11c7 vgabios.c:742 + jmp short 011f8h ; eb 2d ; 0xc11c9 vgabios.c:743 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc11cb vgabios.c:47 + test dl, 001h ; f6 c2 01 ; 0xc11ce vgabios.c:48 + jne short 0122dh ; 75 5a ; 0xc11d1 + cmp bl, 020h ; 80 fb 20 ; 0xc11d3 + jnc short 0122dh ; 73 55 ; 0xc11d6 + cmp ah, 020h ; 80 fc 20 ; 0xc11d8 + jnc short 0122dh ; 73 50 ; 0xc11db + mov si, 00085h ; be 85 00 ; 0xc11dd vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc11e0 + mov es, dx ; 8e c2 ; 0xc11e3 + mov cx, word [es:si] ; 26 8b 0c ; 0xc11e5 + mov dx, cx ; 89 ca ; 0xc11e8 vgabios.c:58 + cmp ah, bl ; 38 dc ; 0xc11ea vgabios.c:754 + jnc short 011fah ; 73 0c ; 0xc11ec + test ah, ah ; 84 e4 ; 0xc11ee vgabios.c:756 + je short 0122dh ; 74 3b ; 0xc11f0 + xor bl, bl ; 30 db ; 0xc11f2 vgabios.c:757 + mov ah, cl ; 88 cc ; 0xc11f4 vgabios.c:758 + db 0feh, 0cch + ; dec ah ; fe cc ; 0xc11f6 + jmp short 0122dh ; eb 33 ; 0xc11f8 vgabios.c:760 + mov byte [bp-008h], ah ; 88 66 f8 ; 0xc11fa vgabios.c:761 + xor al, al ; 30 c0 ; 0xc11fd + mov byte [bp-007h], al ; 88 46 f9 ; 0xc11ff + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc1202 + mov byte [bp-009h], al ; 88 46 f7 ; 0xc1205 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc1208 + or si, word [bp-00ah] ; 0b 76 f6 ; 0xc120b + cmp si, cx ; 39 ce ; 0xc120e + jnc short 0122fh ; 73 1d ; 0xc1210 + mov byte [bp-00ah], ah ; 88 66 f6 ; 0xc1212 + mov byte [bp-009h], al ; 88 46 f7 ; 0xc1215 + mov si, cx ; 89 ce ; 0xc1218 + dec si ; 4e ; 0xc121a + cmp si, word [bp-00ah] ; 3b 76 f6 ; 0xc121b + je short 01269h ; 74 49 ; 0xc121e + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc1220 + mov byte [bp-007h], al ; 88 46 f9 ; 0xc1223 + dec cx ; 49 ; 0xc1226 + dec cx ; 49 ; 0xc1227 + cmp cx, word [bp-008h] ; 3b 4e f8 ; 0xc1228 + jne short 0122fh ; 75 02 ; 0xc122b + jmp short 01269h ; eb 3a ; 0xc122d + cmp ah, 003h ; 80 fc 03 ; 0xc122f vgabios.c:763 + jbe short 01269h ; 76 35 ; 0xc1232 + mov cl, bl ; 88 d9 ; 0xc1234 vgabios.c:764 + xor ch, ch ; 30 ed ; 0xc1236 + mov byte [bp-00ah], ah ; 88 66 f6 ; 0xc1238 + mov byte [bp-009h], ch ; 88 6e f7 ; 0xc123b + mov si, cx ; 89 ce ; 0xc123e + inc si ; 46 ; 0xc1240 + inc si ; 46 ; 0xc1241 + mov cl, dl ; 88 d1 ; 0xc1242 + db 0feh, 0c9h + ; dec cl ; fe c9 ; 0xc1244 + cmp si, word [bp-00ah] ; 3b 76 f6 ; 0xc1246 + jl short 0125eh ; 7c 13 ; 0xc1249 + sub bl, ah ; 28 e3 ; 0xc124b vgabios.c:766 + add bl, dl ; 00 d3 ; 0xc124d + db 0feh, 0cbh + ; dec bl ; fe cb ; 0xc124f + mov ah, cl ; 88 cc ; 0xc1251 vgabios.c:767 + cmp dx, strict byte 0000eh ; 83 fa 0e ; 0xc1253 vgabios.c:768 + jc short 01269h ; 72 11 ; 0xc1256 + db 0feh, 0cch + ; dec ah ; fe cc ; 0xc1258 vgabios.c:770 + db 0feh, 0cbh + ; dec bl ; fe cb ; 0xc125a vgabios.c:771 + jmp short 01269h ; eb 0b ; 0xc125c vgabios.c:773 + cmp bl, 002h ; 80 fb 02 ; 0xc125e + jbe short 01267h ; 76 04 ; 0xc1261 + shr dx, 1 ; d1 ea ; 0xc1263 vgabios.c:775 + mov bl, dl ; 88 d3 ; 0xc1265 + mov ah, cl ; 88 cc ; 0xc1267 vgabios.c:779 + mov si, strict word 00063h ; be 63 00 ; 0xc1269 vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc126c + mov es, dx ; 8e c2 ; 0xc126f + mov cx, word [es:si] ; 26 8b 0c ; 0xc1271 + mov AL, strict byte 00ah ; b0 0a ; 0xc1274 vgabios.c:790 + mov dx, cx ; 89 ca ; 0xc1276 + out DX, AL ; ee ; 0xc1278 + mov si, cx ; 89 ce ; 0xc1279 vgabios.c:791 + inc si ; 46 ; 0xc127b + mov al, bl ; 88 d8 ; 0xc127c + mov dx, si ; 89 f2 ; 0xc127e + out DX, AL ; ee ; 0xc1280 + mov AL, strict byte 00bh ; b0 0b ; 0xc1281 vgabios.c:792 + mov dx, cx ; 89 ca ; 0xc1283 + out DX, AL ; ee ; 0xc1285 + mov al, ah ; 88 e0 ; 0xc1286 vgabios.c:793 + mov dx, si ; 89 f2 ; 0xc1288 + out DX, AL ; ee ; 0xc128a + lea sp, [bp-006h] ; 8d 66 fa ; 0xc128b vgabios.c:794 + pop si ; 5e ; 0xc128e + pop cx ; 59 ; 0xc128f + pop bx ; 5b ; 0xc1290 + pop bp ; 5d ; 0xc1291 + retn ; c3 ; 0xc1292 + ; disGetNextSymbol 0xc1293 LB 0x329f -> off=0x0 cb=000000000000008f uValue=00000000000c1293 'biosfn_set_cursor_pos' +biosfn_set_cursor_pos: ; 0xc1293 LB 0x8f + push bp ; 55 ; 0xc1293 vgabios.c:797 + mov bp, sp ; 89 e5 ; 0xc1294 + push bx ; 53 ; 0xc1296 + push cx ; 51 ; 0xc1297 + push si ; 56 ; 0xc1298 + push di ; 57 ; 0xc1299 + push ax ; 50 ; 0xc129a + mov bl, al ; 88 c3 ; 0xc129b + mov cx, dx ; 89 d1 ; 0xc129d + cmp AL, strict byte 007h ; 3c 07 ; 0xc129f vgabios.c:803 + jnbe short 01319h ; 77 76 ; 0xc12a1 + xor ah, ah ; 30 e4 ; 0xc12a3 vgabios.c:806 + mov si, ax ; 89 c6 ; 0xc12a5 + add si, ax ; 01 c6 ; 0xc12a7 + add si, strict byte 00050h ; 83 c6 50 ; 0xc12a9 + mov ax, strict word 00040h ; b8 40 00 ; 0xc12ac vgabios.c:62 + mov es, ax ; 8e c0 ; 0xc12af + mov word [es:si], dx ; 26 89 14 ; 0xc12b1 + mov si, strict word 00062h ; be 62 00 ; 0xc12b4 vgabios.c:47 + mov al, byte [es:si] ; 26 8a 04 ; 0xc12b7 + cmp bl, al ; 38 c3 ; 0xc12ba vgabios.c:810 + jne short 01319h ; 75 5b ; 0xc12bc + mov di, strict word 0004ah ; bf 4a 00 ; 0xc12be vgabios.c:57 + mov di, word [es:di] ; 26 8b 3d ; 0xc12c1 + mov si, 00084h ; be 84 00 ; 0xc12c4 vgabios.c:47 + mov al, byte [es:si] ; 26 8a 04 ; 0xc12c7 + xor ah, ah ; 30 e4 ; 0xc12ca vgabios.c:48 + mov si, ax ; 89 c6 ; 0xc12cc + inc si ; 46 ; 0xc12ce + mov ax, dx ; 89 d0 ; 0xc12cf vgabios.c:816 + xor al, dl ; 30 d0 ; 0xc12d1 + shr ax, 008h ; c1 e8 08 ; 0xc12d3 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc12d6 + mov ax, di ; 89 f8 ; 0xc12d9 vgabios.c:819 + mul si ; f7 e6 ; 0xc12db + or AL, strict byte 0ffh ; 0c ff ; 0xc12dd + xor bh, bh ; 30 ff ; 0xc12df + inc ax ; 40 ; 0xc12e1 + mul bx ; f7 e3 ; 0xc12e2 + mov bl, cl ; 88 cb ; 0xc12e4 + mov si, bx ; 89 de ; 0xc12e6 + add si, ax ; 01 c6 ; 0xc12e8 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc12ea + xor ah, ah ; 30 e4 ; 0xc12ed + mul di ; f7 e7 ; 0xc12ef + add si, ax ; 01 c6 ; 0xc12f1 + mov bx, strict word 00063h ; bb 63 00 ; 0xc12f3 vgabios.c:57 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc12f6 + mov AL, strict byte 00eh ; b0 0e ; 0xc12f9 vgabios.c:823 + mov dx, bx ; 89 da ; 0xc12fb + out DX, AL ; ee ; 0xc12fd + mov ax, si ; 89 f0 ; 0xc12fe vgabios.c:824 + xor al, al ; 30 c0 ; 0xc1300 + shr ax, 008h ; c1 e8 08 ; 0xc1302 + lea cx, [bx+001h] ; 8d 4f 01 ; 0xc1305 + mov dx, cx ; 89 ca ; 0xc1308 + out DX, AL ; ee ; 0xc130a + mov AL, strict byte 00fh ; b0 0f ; 0xc130b vgabios.c:825 + mov dx, bx ; 89 da ; 0xc130d + out DX, AL ; ee ; 0xc130f + and si, 000ffh ; 81 e6 ff 00 ; 0xc1310 vgabios.c:826 + mov ax, si ; 89 f0 ; 0xc1314 + mov dx, cx ; 89 ca ; 0xc1316 + out DX, AL ; ee ; 0xc1318 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc1319 vgabios.c:828 + pop di ; 5f ; 0xc131c + pop si ; 5e ; 0xc131d + pop cx ; 59 ; 0xc131e + pop bx ; 5b ; 0xc131f + pop bp ; 5d ; 0xc1320 + retn ; c3 ; 0xc1321 + ; disGetNextSymbol 0xc1322 LB 0x3210 -> off=0x0 cb=00000000000000d8 uValue=00000000000c1322 'biosfn_set_active_page' +biosfn_set_active_page: ; 0xc1322 LB 0xd8 + push bp ; 55 ; 0xc1322 vgabios.c:831 + mov bp, sp ; 89 e5 ; 0xc1323 + push bx ; 53 ; 0xc1325 + push cx ; 51 ; 0xc1326 + push dx ; 52 ; 0xc1327 + push si ; 56 ; 0xc1328 + push di ; 57 ; 0xc1329 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc132a + mov cl, al ; 88 c1 ; 0xc132d + cmp AL, strict byte 007h ; 3c 07 ; 0xc132f vgabios.c:837 + jnbe short 01349h ; 77 16 ; 0xc1331 + mov bx, strict word 00049h ; bb 49 00 ; 0xc1333 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1336 + mov es, ax ; 8e c0 ; 0xc1339 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc133b + xor ah, ah ; 30 e4 ; 0xc133e vgabios.c:841 + call 03819h ; e8 d6 24 ; 0xc1340 + mov ch, al ; 88 c5 ; 0xc1343 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc1345 vgabios.c:842 + jne short 0134ch ; 75 03 ; 0xc1347 + jmp near 013f0h ; e9 a4 00 ; 0xc1349 + mov al, cl ; 88 c8 ; 0xc134c vgabios.c:845 + xor ah, ah ; 30 e4 ; 0xc134e + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc1350 + lea dx, [bp-010h] ; 8d 56 f0 ; 0xc1353 + call 00a96h ; e8 3d f7 ; 0xc1356 + mov bl, ch ; 88 eb ; 0xc1359 vgabios.c:847 + xor bh, bh ; 30 ff ; 0xc135b + mov si, bx ; 89 de ; 0xc135d + sal si, 003h ; c1 e6 03 ; 0xc135f + cmp byte [si+047b0h], 000h ; 80 bc b0 47 00 ; 0xc1362 + jne short 013a8h ; 75 3f ; 0xc1367 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1369 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc136c + mov es, ax ; 8e c0 ; 0xc136f + mov dx, word [es:bx] ; 26 8b 17 ; 0xc1371 + mov bx, 00084h ; bb 84 00 ; 0xc1374 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1377 + xor ah, ah ; 30 e4 ; 0xc137a vgabios.c:48 + mov bx, ax ; 89 c3 ; 0xc137c + inc bx ; 43 ; 0xc137e + mov ax, dx ; 89 d0 ; 0xc137f vgabios.c:854 + mul bx ; f7 e3 ; 0xc1381 + mov di, ax ; 89 c7 ; 0xc1383 + add ax, ax ; 01 c0 ; 0xc1385 + or AL, strict byte 0ffh ; 0c ff ; 0xc1387 + mov byte [bp-00ch], cl ; 88 4e f4 ; 0xc1389 + mov byte [bp-00bh], 000h ; c6 46 f5 00 ; 0xc138c + inc ax ; 40 ; 0xc1390 + mul word [bp-00ch] ; f7 66 f4 ; 0xc1391 + mov bx, ax ; 89 c3 ; 0xc1394 + mov si, strict word 0004eh ; be 4e 00 ; 0xc1396 vgabios.c:62 + mov word [es:si], ax ; 26 89 04 ; 0xc1399 + or di, 000ffh ; 81 cf ff 00 ; 0xc139c vgabios.c:858 + lea ax, [di+001h] ; 8d 45 01 ; 0xc13a0 + mul word [bp-00ch] ; f7 66 f4 ; 0xc13a3 + jmp short 013b7h ; eb 0f ; 0xc13a6 vgabios.c:860 + mov bl, byte [bx+0482fh] ; 8a 9f 2f 48 ; 0xc13a8 vgabios.c:862 + sal bx, 006h ; c1 e3 06 ; 0xc13ac + mov al, cl ; 88 c8 ; 0xc13af + xor ah, ah ; 30 e4 ; 0xc13b1 + mul word [bx+04846h] ; f7 a7 46 48 ; 0xc13b3 + mov bx, ax ; 89 c3 ; 0xc13b7 + mov si, strict word 00063h ; be 63 00 ; 0xc13b9 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc13bc + mov es, ax ; 8e c0 ; 0xc13bf + mov si, word [es:si] ; 26 8b 34 ; 0xc13c1 + mov AL, strict byte 00ch ; b0 0c ; 0xc13c4 vgabios.c:867 + mov dx, si ; 89 f2 ; 0xc13c6 + out DX, AL ; ee ; 0xc13c8 + mov ax, bx ; 89 d8 ; 0xc13c9 vgabios.c:868 + xor al, bl ; 30 d8 ; 0xc13cb + shr ax, 008h ; c1 e8 08 ; 0xc13cd + lea di, [si+001h] ; 8d 7c 01 ; 0xc13d0 + mov dx, di ; 89 fa ; 0xc13d3 + out DX, AL ; ee ; 0xc13d5 + mov AL, strict byte 00dh ; b0 0d ; 0xc13d6 vgabios.c:869 + mov dx, si ; 89 f2 ; 0xc13d8 + out DX, AL ; ee ; 0xc13da + xor bh, bh ; 30 ff ; 0xc13db vgabios.c:870 + mov ax, bx ; 89 d8 ; 0xc13dd + mov dx, di ; 89 fa ; 0xc13df + out DX, AL ; ee ; 0xc13e1 + mov bx, strict word 00062h ; bb 62 00 ; 0xc13e2 vgabios.c:52 + mov byte [es:bx], cl ; 26 88 0f ; 0xc13e5 + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc13e8 vgabios.c:880 + mov al, cl ; 88 c8 ; 0xc13eb + call 01293h ; e8 a3 fe ; 0xc13ed + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc13f0 vgabios.c:881 + pop di ; 5f ; 0xc13f3 + pop si ; 5e ; 0xc13f4 + pop dx ; 5a ; 0xc13f5 + pop cx ; 59 ; 0xc13f6 + pop bx ; 5b ; 0xc13f7 + pop bp ; 5d ; 0xc13f8 + retn ; c3 ; 0xc13f9 + ; disGetNextSymbol 0xc13fa LB 0x3138 -> off=0x0 cb=0000000000000045 uValue=00000000000c13fa 'find_vpti' +find_vpti: ; 0xc13fa LB 0x45 + push bx ; 53 ; 0xc13fa vgabios.c:916 + push si ; 56 ; 0xc13fb + push bp ; 55 ; 0xc13fc + mov bp, sp ; 89 e5 ; 0xc13fd + mov bl, al ; 88 c3 ; 0xc13ff vgabios.c:921 + xor bh, bh ; 30 ff ; 0xc1401 + mov si, bx ; 89 de ; 0xc1403 + sal si, 003h ; c1 e6 03 ; 0xc1405 + cmp byte [si+047b0h], 000h ; 80 bc b0 47 00 ; 0xc1408 + jne short 01435h ; 75 26 ; 0xc140d + mov si, 00089h ; be 89 00 ; 0xc140f vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1412 + mov es, ax ; 8e c0 ; 0xc1415 + mov al, byte [es:si] ; 26 8a 04 ; 0xc1417 + test AL, strict byte 010h ; a8 10 ; 0xc141a vgabios.c:923 + je short 01424h ; 74 06 ; 0xc141c + mov al, byte [bx+07df6h] ; 8a 87 f6 7d ; 0xc141e vgabios.c:924 + jmp short 01432h ; eb 0e ; 0xc1422 vgabios.c:925 + test AL, strict byte 080h ; a8 80 ; 0xc1424 + je short 0142eh ; 74 06 ; 0xc1426 + mov al, byte [bx+07de6h] ; 8a 87 e6 7d ; 0xc1428 vgabios.c:926 + jmp short 01432h ; eb 04 ; 0xc142c vgabios.c:927 + mov al, byte [bx+07deeh] ; 8a 87 ee 7d ; 0xc142e vgabios.c:928 + cbw ; 98 ; 0xc1432 + jmp short 0143bh ; eb 06 ; 0xc1433 vgabios.c:929 + mov al, byte [bx+0482fh] ; 8a 87 2f 48 ; 0xc1435 vgabios.c:930 + xor ah, ah ; 30 e4 ; 0xc1439 + pop bp ; 5d ; 0xc143b vgabios.c:933 + pop si ; 5e ; 0xc143c + pop bx ; 5b ; 0xc143d + retn ; c3 ; 0xc143e + ; disGetNextSymbol 0xc143f LB 0x30f3 -> off=0x0 cb=00000000000004d5 uValue=00000000000c143f 'biosfn_set_video_mode' +biosfn_set_video_mode: ; 0xc143f LB 0x4d5 + push bp ; 55 ; 0xc143f vgabios.c:938 + mov bp, sp ; 89 e5 ; 0xc1440 + push bx ; 53 ; 0xc1442 + push cx ; 51 ; 0xc1443 + push dx ; 52 ; 0xc1444 + push si ; 56 ; 0xc1445 + push di ; 57 ; 0xc1446 + sub sp, strict byte 00018h ; 83 ec 18 ; 0xc1447 + mov byte [bp-010h], al ; 88 46 f0 ; 0xc144a + and AL, strict byte 080h ; 24 80 ; 0xc144d vgabios.c:942 + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc144f + call 007bfh ; e8 6a f3 ; 0xc1452 vgabios.c:952 + test ax, ax ; 85 c0 ; 0xc1455 + je short 01465h ; 74 0c ; 0xc1457 + mov AL, strict byte 007h ; b0 07 ; 0xc1459 vgabios.c:954 + mov dx, 003c4h ; ba c4 03 ; 0xc145b + out DX, AL ; ee ; 0xc145e + xor al, al ; 30 c0 ; 0xc145f vgabios.c:955 + mov dx, 003c5h ; ba c5 03 ; 0xc1461 + out DX, AL ; ee ; 0xc1464 + and byte [bp-010h], 07fh ; 80 66 f0 7f ; 0xc1465 vgabios.c:960 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc1469 vgabios.c:966 + xor ah, ah ; 30 e4 ; 0xc146c + call 03819h ; e8 a8 23 ; 0xc146e + mov cl, al ; 88 c1 ; 0xc1471 + mov byte [bp-012h], al ; 88 46 ee ; 0xc1473 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc1476 vgabios.c:972 + je short 014e5h ; 74 6b ; 0xc1478 + mov bx, 000a8h ; bb a8 00 ; 0xc147a vgabios.c:67 + mov ax, strict word 00040h ; b8 40 00 ; 0xc147d + mov es, ax ; 8e c0 ; 0xc1480 + mov di, word [es:bx] ; 26 8b 3f ; 0xc1482 + mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xc1485 + mov bx, di ; 89 fb ; 0xc1489 vgabios.c:68 + mov word [bp-018h], ax ; 89 46 e8 ; 0xc148b + xor ch, ch ; 30 ed ; 0xc148e vgabios.c:978 + mov ax, cx ; 89 c8 ; 0xc1490 + call 013fah ; e8 65 ff ; 0xc1492 + mov es, [bp-018h] ; 8e 46 e8 ; 0xc1495 vgabios.c:979 + mov si, word [es:di] ; 26 8b 35 ; 0xc1498 + mov dx, word [es:di+002h] ; 26 8b 55 02 ; 0xc149b + mov word [bp-01eh], dx ; 89 56 e2 ; 0xc149f + xor ah, ah ; 30 e4 ; 0xc14a2 vgabios.c:980 + sal ax, 006h ; c1 e0 06 ; 0xc14a4 + add si, ax ; 01 c6 ; 0xc14a7 + mov di, 00089h ; bf 89 00 ; 0xc14a9 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc14ac + mov es, ax ; 8e c0 ; 0xc14af + mov al, byte [es:di] ; 26 8a 05 ; 0xc14b1 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc14b4 vgabios.c:48 + test AL, strict byte 008h ; a8 08 ; 0xc14b7 vgabios.c:997 + jne short 01501h ; 75 46 ; 0xc14b9 + mov di, cx ; 89 cf ; 0xc14bb vgabios.c:999 + sal di, 003h ; c1 e7 03 ; 0xc14bd + mov al, byte [di+047b5h] ; 8a 85 b5 47 ; 0xc14c0 + mov dx, 003c6h ; ba c6 03 ; 0xc14c4 + out DX, AL ; ee ; 0xc14c7 + xor al, al ; 30 c0 ; 0xc14c8 vgabios.c:1002 + mov dx, 003c8h ; ba c8 03 ; 0xc14ca + out DX, AL ; ee ; 0xc14cd + mov cl, byte [di+047b6h] ; 8a 8d b6 47 ; 0xc14ce vgabios.c:1005 + cmp cl, 001h ; 80 f9 01 ; 0xc14d2 + jc short 014e8h ; 72 11 ; 0xc14d5 + jbe short 014f3h ; 76 1a ; 0xc14d7 + cmp cl, 003h ; 80 f9 03 ; 0xc14d9 + je short 01504h ; 74 26 ; 0xc14dc + cmp cl, 002h ; 80 f9 02 ; 0xc14de + je short 014fah ; 74 17 ; 0xc14e1 + jmp short 01509h ; eb 24 ; 0xc14e3 + jmp near 0190ah ; e9 22 04 ; 0xc14e5 + test cl, cl ; 84 c9 ; 0xc14e8 + jne short 01509h ; 75 1d ; 0xc14ea + mov word [bp-014h], 04fc3h ; c7 46 ec c3 4f ; 0xc14ec vgabios.c:1007 + jmp short 01509h ; eb 16 ; 0xc14f1 vgabios.c:1008 + mov word [bp-014h], 05083h ; c7 46 ec 83 50 ; 0xc14f3 vgabios.c:1010 + jmp short 01509h ; eb 0f ; 0xc14f8 vgabios.c:1011 + mov word [bp-014h], 05143h ; c7 46 ec 43 51 ; 0xc14fa vgabios.c:1013 + jmp short 01509h ; eb 08 ; 0xc14ff vgabios.c:1014 + jmp near 01578h ; e9 74 00 ; 0xc1501 + mov word [bp-014h], 05203h ; c7 46 ec 03 52 ; 0xc1504 vgabios.c:1016 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc1509 vgabios.c:1020 + xor ah, ah ; 30 e4 ; 0xc150c + mov di, ax ; 89 c7 ; 0xc150e + sal di, 003h ; c1 e7 03 ; 0xc1510 + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc1513 + jne short 01529h ; 75 0f ; 0xc1518 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc151a vgabios.c:1022 + cmp byte [es:si+002h], 008h ; 26 80 7c 02 08 ; 0xc151d + jne short 01529h ; 75 05 ; 0xc1522 + mov word [bp-014h], 05083h ; c7 46 ec 83 50 ; 0xc1524 vgabios.c:1023 + xor cx, cx ; 31 c9 ; 0xc1529 vgabios.c:1026 + jmp short 0153ch ; eb 0f ; 0xc152b + xor al, al ; 30 c0 ; 0xc152d vgabios.c:1033 + mov dx, 003c9h ; ba c9 03 ; 0xc152f + out DX, AL ; ee ; 0xc1532 + out DX, AL ; ee ; 0xc1533 vgabios.c:1034 + out DX, AL ; ee ; 0xc1534 vgabios.c:1035 + inc cx ; 41 ; 0xc1535 vgabios.c:1037 + cmp cx, 00100h ; 81 f9 00 01 ; 0xc1536 + jnc short 0156ah ; 73 2e ; 0xc153a + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc153c + xor ah, ah ; 30 e4 ; 0xc153f + mov di, ax ; 89 c7 ; 0xc1541 + sal di, 003h ; c1 e7 03 ; 0xc1543 + mov al, byte [di+047b6h] ; 8a 85 b6 47 ; 0xc1546 + mov di, ax ; 89 c7 ; 0xc154a + mov al, byte [di+0483fh] ; 8a 85 3f 48 ; 0xc154c + cmp cx, ax ; 39 c1 ; 0xc1550 + jnbe short 0152dh ; 77 d9 ; 0xc1552 + imul di, cx, strict byte 00003h ; 6b f9 03 ; 0xc1554 + add di, word [bp-014h] ; 03 7e ec ; 0xc1557 + mov al, byte [di] ; 8a 05 ; 0xc155a + mov dx, 003c9h ; ba c9 03 ; 0xc155c + out DX, AL ; ee ; 0xc155f + mov al, byte [di+001h] ; 8a 45 01 ; 0xc1560 + out DX, AL ; ee ; 0xc1563 + mov al, byte [di+002h] ; 8a 45 02 ; 0xc1564 + out DX, AL ; ee ; 0xc1567 + jmp short 01535h ; eb cb ; 0xc1568 + test byte [bp-00ch], 002h ; f6 46 f4 02 ; 0xc156a vgabios.c:1038 + je short 01578h ; 74 08 ; 0xc156e + mov dx, 00100h ; ba 00 01 ; 0xc1570 vgabios.c:1040 + xor ax, ax ; 31 c0 ; 0xc1573 + call 010ffh ; e8 87 fb ; 0xc1575 + mov dx, 003dah ; ba da 03 ; 0xc1578 vgabios.c:1045 + in AL, DX ; ec ; 0xc157b + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc157c + xor cx, cx ; 31 c9 ; 0xc157e vgabios.c:1048 + jmp short 01587h ; eb 05 ; 0xc1580 + cmp cx, strict byte 00013h ; 83 f9 13 ; 0xc1582 + jnbe short 0159ch ; 77 15 ; 0xc1585 + mov al, cl ; 88 c8 ; 0xc1587 vgabios.c:1049 + mov dx, 003c0h ; ba c0 03 ; 0xc1589 + out DX, AL ; ee ; 0xc158c + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc158d vgabios.c:1050 + mov di, si ; 89 f7 ; 0xc1590 + add di, cx ; 01 cf ; 0xc1592 + mov al, byte [es:di+023h] ; 26 8a 45 23 ; 0xc1594 + out DX, AL ; ee ; 0xc1598 + inc cx ; 41 ; 0xc1599 vgabios.c:1051 + jmp short 01582h ; eb e6 ; 0xc159a + mov AL, strict byte 014h ; b0 14 ; 0xc159c vgabios.c:1052 + mov dx, 003c0h ; ba c0 03 ; 0xc159e + out DX, AL ; ee ; 0xc15a1 + xor al, al ; 30 c0 ; 0xc15a2 vgabios.c:1053 + out DX, AL ; ee ; 0xc15a4 + mov es, [bp-018h] ; 8e 46 e8 ; 0xc15a5 vgabios.c:1056 + mov dx, word [es:bx+004h] ; 26 8b 57 04 ; 0xc15a8 + mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xc15ac + test ax, ax ; 85 c0 ; 0xc15b0 + jne short 015b8h ; 75 04 ; 0xc15b2 + test dx, dx ; 85 d2 ; 0xc15b4 + je short 015f5h ; 74 3d ; 0xc15b6 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc15b8 vgabios.c:1060 + xor cx, cx ; 31 c9 ; 0xc15bb vgabios.c:1061 + jmp short 015c4h ; eb 05 ; 0xc15bd + cmp cx, strict byte 00010h ; 83 f9 10 ; 0xc15bf + jnc short 015e5h ; 73 21 ; 0xc15c2 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc15c4 vgabios.c:1062 + mov di, si ; 89 f7 ; 0xc15c7 + add di, cx ; 01 cf ; 0xc15c9 + mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xc15cb + mov word [bp-020h], ax ; 89 46 e0 ; 0xc15ce + mov ax, dx ; 89 d0 ; 0xc15d1 + add ax, cx ; 01 c8 ; 0xc15d3 + mov word [bp-022h], ax ; 89 46 de ; 0xc15d5 + mov al, byte [es:di+023h] ; 26 8a 45 23 ; 0xc15d8 + les di, [bp-022h] ; c4 7e de ; 0xc15dc + mov byte [es:di], al ; 26 88 05 ; 0xc15df + inc cx ; 41 ; 0xc15e2 + jmp short 015bfh ; eb da ; 0xc15e3 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc15e5 vgabios.c:1063 + mov al, byte [es:si+034h] ; 26 8a 44 34 ; 0xc15e8 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc15ec + mov di, dx ; 89 d7 ; 0xc15ef + mov byte [es:di+010h], al ; 26 88 45 10 ; 0xc15f1 + xor al, al ; 30 c0 ; 0xc15f5 vgabios.c:1067 + mov dx, 003c4h ; ba c4 03 ; 0xc15f7 + out DX, AL ; ee ; 0xc15fa + mov AL, strict byte 003h ; b0 03 ; 0xc15fb vgabios.c:1068 + mov dx, 003c5h ; ba c5 03 ; 0xc15fd + out DX, AL ; ee ; 0xc1600 + mov cx, strict word 00001h ; b9 01 00 ; 0xc1601 vgabios.c:1069 + jmp short 0160bh ; eb 05 ; 0xc1604 + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc1606 + jnbe short 01623h ; 77 18 ; 0xc1609 + mov al, cl ; 88 c8 ; 0xc160b vgabios.c:1070 + mov dx, 003c4h ; ba c4 03 ; 0xc160d + out DX, AL ; ee ; 0xc1610 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc1611 vgabios.c:1071 + mov di, si ; 89 f7 ; 0xc1614 + add di, cx ; 01 cf ; 0xc1616 + mov al, byte [es:di+004h] ; 26 8a 45 04 ; 0xc1618 + mov dx, 003c5h ; ba c5 03 ; 0xc161c + out DX, AL ; ee ; 0xc161f + inc cx ; 41 ; 0xc1620 vgabios.c:1072 + jmp short 01606h ; eb e3 ; 0xc1621 + xor cx, cx ; 31 c9 ; 0xc1623 vgabios.c:1075 + jmp short 0162ch ; eb 05 ; 0xc1625 + cmp cx, strict byte 00008h ; 83 f9 08 ; 0xc1627 + jnbe short 01644h ; 77 18 ; 0xc162a + mov al, cl ; 88 c8 ; 0xc162c vgabios.c:1076 + mov dx, 003ceh ; ba ce 03 ; 0xc162e + out DX, AL ; ee ; 0xc1631 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc1632 vgabios.c:1077 + mov di, si ; 89 f7 ; 0xc1635 + add di, cx ; 01 cf ; 0xc1637 + mov al, byte [es:di+037h] ; 26 8a 45 37 ; 0xc1639 + mov dx, 003cfh ; ba cf 03 ; 0xc163d + out DX, AL ; ee ; 0xc1640 + inc cx ; 41 ; 0xc1641 vgabios.c:1078 + jmp short 01627h ; eb e3 ; 0xc1642 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc1644 vgabios.c:1081 + xor ah, ah ; 30 e4 ; 0xc1647 + mov di, ax ; 89 c7 ; 0xc1649 + sal di, 003h ; c1 e7 03 ; 0xc164b + cmp byte [di+047b1h], 001h ; 80 bd b1 47 01 ; 0xc164e + jne short 0165ah ; 75 05 ; 0xc1653 + mov cx, 003b4h ; b9 b4 03 ; 0xc1655 + jmp short 0165dh ; eb 03 ; 0xc1658 + mov cx, 003d4h ; b9 d4 03 ; 0xc165a + mov word [bp-016h], cx ; 89 4e ea ; 0xc165d + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc1660 vgabios.c:1084 + mov al, byte [es:si+009h] ; 26 8a 44 09 ; 0xc1663 + mov dx, 003c2h ; ba c2 03 ; 0xc1667 + out DX, AL ; ee ; 0xc166a + mov ax, strict word 00011h ; b8 11 00 ; 0xc166b vgabios.c:1087 + mov dx, cx ; 89 ca ; 0xc166e + out DX, ax ; ef ; 0xc1670 + xor cx, cx ; 31 c9 ; 0xc1671 vgabios.c:1089 + jmp short 0167ah ; eb 05 ; 0xc1673 + cmp cx, strict byte 00018h ; 83 f9 18 ; 0xc1675 + jnbe short 01690h ; 77 16 ; 0xc1678 + mov al, cl ; 88 c8 ; 0xc167a vgabios.c:1090 + mov dx, word [bp-016h] ; 8b 56 ea ; 0xc167c + out DX, AL ; ee ; 0xc167f + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc1680 vgabios.c:1091 + mov di, si ; 89 f7 ; 0xc1683 + add di, cx ; 01 cf ; 0xc1685 + inc dx ; 42 ; 0xc1687 + mov al, byte [es:di+00ah] ; 26 8a 45 0a ; 0xc1688 + out DX, AL ; ee ; 0xc168c + inc cx ; 41 ; 0xc168d vgabios.c:1092 + jmp short 01675h ; eb e5 ; 0xc168e + mov AL, strict byte 020h ; b0 20 ; 0xc1690 vgabios.c:1095 + mov dx, 003c0h ; ba c0 03 ; 0xc1692 + out DX, AL ; ee ; 0xc1695 + mov dx, word [bp-016h] ; 8b 56 ea ; 0xc1696 vgabios.c:1096 + add dx, strict byte 00006h ; 83 c2 06 ; 0xc1699 + in AL, DX ; ec ; 0xc169c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc169d + cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xc169f vgabios.c:1098 + jne short 01704h ; 75 5f ; 0xc16a3 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc16a5 vgabios.c:1100 + xor ah, ah ; 30 e4 ; 0xc16a8 + mov di, ax ; 89 c7 ; 0xc16aa + sal di, 003h ; c1 e7 03 ; 0xc16ac + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc16af + jne short 016c8h ; 75 12 ; 0xc16b4 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc16b6 vgabios.c:1102 + mov cx, 04000h ; b9 00 40 ; 0xc16ba + mov ax, 00720h ; b8 20 07 ; 0xc16bd + xor di, di ; 31 ff ; 0xc16c0 + jcxz 016c6h ; e3 02 ; 0xc16c2 + rep stosw ; f3 ab ; 0xc16c4 + jmp short 01704h ; eb 3c ; 0xc16c6 vgabios.c:1104 + cmp byte [bp-010h], 00dh ; 80 7e f0 0d ; 0xc16c8 vgabios.c:1106 + jnc short 016dfh ; 73 11 ; 0xc16cc + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc16ce vgabios.c:1108 + mov cx, 04000h ; b9 00 40 ; 0xc16d2 + xor al, al ; 30 c0 ; 0xc16d5 + xor di, di ; 31 ff ; 0xc16d7 + jcxz 016ddh ; e3 02 ; 0xc16d9 + rep stosw ; f3 ab ; 0xc16db + jmp short 01704h ; eb 25 ; 0xc16dd vgabios.c:1110 + mov AL, strict byte 002h ; b0 02 ; 0xc16df vgabios.c:1112 + mov dx, 003c4h ; ba c4 03 ; 0xc16e1 + out DX, AL ; ee ; 0xc16e4 + mov dx, 003c5h ; ba c5 03 ; 0xc16e5 vgabios.c:1113 + in AL, DX ; ec ; 0xc16e8 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc16e9 + mov word [bp-020h], ax ; 89 46 e0 ; 0xc16eb + mov AL, strict byte 00fh ; b0 0f ; 0xc16ee vgabios.c:1114 + out DX, AL ; ee ; 0xc16f0 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc16f1 vgabios.c:1115 + mov cx, 08000h ; b9 00 80 ; 0xc16f5 + xor ax, ax ; 31 c0 ; 0xc16f8 + xor di, di ; 31 ff ; 0xc16fa + jcxz 01700h ; e3 02 ; 0xc16fc + rep stosw ; f3 ab ; 0xc16fe + mov al, byte [bp-020h] ; 8a 46 e0 ; 0xc1700 vgabios.c:1116 + out DX, AL ; ee ; 0xc1703 + mov di, strict word 00049h ; bf 49 00 ; 0xc1704 vgabios.c:52 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1707 + mov es, ax ; 8e c0 ; 0xc170a + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc170c + mov byte [es:di], al ; 26 88 05 ; 0xc170f + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc1712 vgabios.c:1123 + mov al, byte [es:si] ; 26 8a 04 ; 0xc1715 + xor ah, ah ; 30 e4 ; 0xc1718 + mov di, strict word 0004ah ; bf 4a 00 ; 0xc171a vgabios.c:62 + mov dx, strict word 00040h ; ba 40 00 ; 0xc171d + mov es, dx ; 8e c2 ; 0xc1720 + mov word [es:di], ax ; 26 89 05 ; 0xc1722 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc1725 vgabios.c:60 + mov ax, word [es:si+003h] ; 26 8b 44 03 ; 0xc1728 + mov di, strict word 0004ch ; bf 4c 00 ; 0xc172c vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc172f + mov word [es:di], ax ; 26 89 05 ; 0xc1731 + mov di, strict word 00063h ; bf 63 00 ; 0xc1734 vgabios.c:62 + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc1737 + mov word [es:di], ax ; 26 89 05 ; 0xc173a + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc173d vgabios.c:50 + mov al, byte [es:si+001h] ; 26 8a 44 01 ; 0xc1740 + mov di, 00084h ; bf 84 00 ; 0xc1744 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc1747 + mov byte [es:di], al ; 26 88 05 ; 0xc1749 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc174c vgabios.c:1127 + mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xc174f + xor ah, ah ; 30 e4 ; 0xc1753 + mov di, 00085h ; bf 85 00 ; 0xc1755 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc1758 + mov word [es:di], ax ; 26 89 05 ; 0xc175a + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc175d vgabios.c:1128 + or AL, strict byte 060h ; 0c 60 ; 0xc1760 + mov di, 00087h ; bf 87 00 ; 0xc1762 vgabios.c:52 + mov byte [es:di], al ; 26 88 05 ; 0xc1765 + mov di, 00088h ; bf 88 00 ; 0xc1768 vgabios.c:52 + mov byte [es:di], 0f9h ; 26 c6 05 f9 ; 0xc176b + mov di, 0008ah ; bf 8a 00 ; 0xc176f vgabios.c:52 + mov byte [es:di], 008h ; 26 c6 05 08 ; 0xc1772 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc1776 vgabios.c:1134 + cmp AL, strict byte 007h ; 3c 07 ; 0xc1779 + jnbe short 017a2h ; 77 25 ; 0xc177b + mov di, ax ; 89 c7 ; 0xc177d vgabios.c:1136 + mov al, byte [di+07ddeh] ; 8a 85 de 7d ; 0xc177f + mov di, strict word 00065h ; bf 65 00 ; 0xc1783 vgabios.c:52 + mov byte [es:di], al ; 26 88 05 ; 0xc1786 + cmp byte [bp-010h], 006h ; 80 7e f0 06 ; 0xc1789 vgabios.c:1137 + jne short 01794h ; 75 05 ; 0xc178d + mov ax, strict word 0003fh ; b8 3f 00 ; 0xc178f + jmp short 01797h ; eb 03 ; 0xc1792 + mov ax, strict word 00030h ; b8 30 00 ; 0xc1794 + mov di, strict word 00066h ; bf 66 00 ; 0xc1797 vgabios.c:52 + mov dx, strict word 00040h ; ba 40 00 ; 0xc179a + mov es, dx ; 8e c2 ; 0xc179d + mov byte [es:di], al ; 26 88 05 ; 0xc179f + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc17a2 vgabios.c:1141 + xor ah, ah ; 30 e4 ; 0xc17a5 + mov di, ax ; 89 c7 ; 0xc17a7 + sal di, 003h ; c1 e7 03 ; 0xc17a9 + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc17ac + jne short 017bch ; 75 09 ; 0xc17b1 + mov dx, strict word 00007h ; ba 07 00 ; 0xc17b3 vgabios.c:1143 + mov ax, strict word 00006h ; b8 06 00 ; 0xc17b6 + call 0118ch ; e8 d0 f9 ; 0xc17b9 + xor cx, cx ; 31 c9 ; 0xc17bc vgabios.c:1148 + jmp short 017c5h ; eb 05 ; 0xc17be + cmp cx, strict byte 00008h ; 83 f9 08 ; 0xc17c0 + jnc short 017d1h ; 73 0c ; 0xc17c3 + mov al, cl ; 88 c8 ; 0xc17c5 vgabios.c:1149 + xor ah, ah ; 30 e4 ; 0xc17c7 + xor dx, dx ; 31 d2 ; 0xc17c9 + call 01293h ; e8 c5 fa ; 0xc17cb + inc cx ; 41 ; 0xc17ce + jmp short 017c0h ; eb ef ; 0xc17cf + xor ax, ax ; 31 c0 ; 0xc17d1 vgabios.c:1152 + call 01322h ; e8 4c fb ; 0xc17d3 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc17d6 vgabios.c:1155 + xor ah, ah ; 30 e4 ; 0xc17d9 + mov di, ax ; 89 c7 ; 0xc17db + sal di, 003h ; c1 e7 03 ; 0xc17dd + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc17e0 + jne short 01851h ; 75 6a ; 0xc17e5 + mov es, [bp-018h] ; 8e 46 e8 ; 0xc17e7 vgabios.c:1157 + mov di, word [es:bx+008h] ; 26 8b 7f 08 ; 0xc17ea + mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xc17ee + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc17f2 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc17f5 vgabios.c:1159 + mov bl, byte [es:si+002h] ; 26 8a 5c 02 ; 0xc17f8 + cmp bl, 00eh ; 80 fb 0e ; 0xc17fc + je short 01824h ; 74 23 ; 0xc17ff + cmp bl, 008h ; 80 fb 08 ; 0xc1801 + jne short 01854h ; 75 4e ; 0xc1804 + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc1806 vgabios.c:1161 + mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xc1809 + xor ah, ah ; 30 e4 ; 0xc180d + push ax ; 50 ; 0xc180f + push strict byte 00000h ; 6a 00 ; 0xc1810 + push strict byte 00000h ; 6a 00 ; 0xc1812 + mov cx, 00100h ; b9 00 01 ; 0xc1814 + mov bx, 0556dh ; bb 6d 55 ; 0xc1817 + mov dx, 0c000h ; ba 00 c0 ; 0xc181a + xor al, al ; 30 c0 ; 0xc181d + call 02e1ah ; e8 f8 15 ; 0xc181f + jmp short 01879h ; eb 55 ; 0xc1822 vgabios.c:1162 + mov al, bl ; 88 d8 ; 0xc1824 vgabios.c:1164 + xor ah, ah ; 30 e4 ; 0xc1826 + push ax ; 50 ; 0xc1828 + push strict byte 00000h ; 6a 00 ; 0xc1829 + push strict byte 00000h ; 6a 00 ; 0xc182b + mov cx, 00100h ; b9 00 01 ; 0xc182d + mov bx, 05d6dh ; bb 6d 5d ; 0xc1830 + mov dx, 0c000h ; ba 00 c0 ; 0xc1833 + xor al, al ; 30 c0 ; 0xc1836 + call 02e1ah ; e8 df 15 ; 0xc1838 + cmp byte [bp-010h], 007h ; 80 7e f0 07 ; 0xc183b vgabios.c:1165 + jne short 01879h ; 75 38 ; 0xc183f + mov cx, strict word 0000eh ; b9 0e 00 ; 0xc1841 vgabios.c:1166 + xor bx, bx ; 31 db ; 0xc1844 + mov dx, 07b6dh ; ba 6d 7b ; 0xc1846 + mov ax, 0c000h ; b8 00 c0 ; 0xc1849 + call 02da5h ; e8 56 15 ; 0xc184c + jmp short 01879h ; eb 28 ; 0xc184f vgabios.c:1167 + jmp near 018d5h ; e9 81 00 ; 0xc1851 + mov al, bl ; 88 d8 ; 0xc1854 vgabios.c:1169 + xor ah, ah ; 30 e4 ; 0xc1856 + push ax ; 50 ; 0xc1858 + push strict byte 00000h ; 6a 00 ; 0xc1859 + push strict byte 00000h ; 6a 00 ; 0xc185b + mov cx, 00100h ; b9 00 01 ; 0xc185d + mov bx, 06b6dh ; bb 6d 6b ; 0xc1860 + mov dx, 0c000h ; ba 00 c0 ; 0xc1863 + xor al, al ; 30 c0 ; 0xc1866 + call 02e1ah ; e8 af 15 ; 0xc1868 + mov cx, strict word 00010h ; b9 10 00 ; 0xc186b vgabios.c:1170 + xor bx, bx ; 31 db ; 0xc186e + mov dx, 07c9ah ; ba 9a 7c ; 0xc1870 + mov ax, 0c000h ; b8 00 c0 ; 0xc1873 + call 02da5h ; e8 2c 15 ; 0xc1876 + cmp word [bp-01ch], strict byte 00000h ; 83 7e e4 00 ; 0xc1879 vgabios.c:1172 + jne short 01883h ; 75 04 ; 0xc187d + test di, di ; 85 ff ; 0xc187f + je short 018cdh ; 74 4a ; 0xc1881 + xor cx, cx ; 31 c9 ; 0xc1883 vgabios.c:1177 + mov es, [bp-01ch] ; 8e 46 e4 ; 0xc1885 vgabios.c:1179 + mov bx, di ; 89 fb ; 0xc1888 + add bx, cx ; 01 cb ; 0xc188a + mov al, byte [es:bx+00bh] ; 26 8a 47 0b ; 0xc188c + cmp AL, strict byte 0ffh ; 3c ff ; 0xc1890 + je short 0189ch ; 74 08 ; 0xc1892 + cmp al, byte [bp-010h] ; 3a 46 f0 ; 0xc1894 vgabios.c:1181 + je short 0189ch ; 74 03 ; 0xc1897 + inc cx ; 41 ; 0xc1899 vgabios.c:1183 + jmp short 01885h ; eb e9 ; 0xc189a vgabios.c:1184 + mov es, [bp-01ch] ; 8e 46 e4 ; 0xc189c vgabios.c:1186 + mov bx, di ; 89 fb ; 0xc189f + add bx, cx ; 01 cb ; 0xc18a1 + mov al, byte [es:bx+00bh] ; 26 8a 47 0b ; 0xc18a3 + cmp al, byte [bp-010h] ; 3a 46 f0 ; 0xc18a7 + jne short 018cdh ; 75 21 ; 0xc18aa + mov al, byte [es:di] ; 26 8a 05 ; 0xc18ac vgabios.c:1191 + xor ah, ah ; 30 e4 ; 0xc18af + push ax ; 50 ; 0xc18b1 + mov al, byte [es:di+001h] ; 26 8a 45 01 ; 0xc18b2 + push ax ; 50 ; 0xc18b6 + push word [es:di+004h] ; 26 ff 75 04 ; 0xc18b7 + mov cx, word [es:di+002h] ; 26 8b 4d 02 ; 0xc18bb + mov bx, word [es:di+006h] ; 26 8b 5d 06 ; 0xc18bf + mov dx, word [es:di+008h] ; 26 8b 55 08 ; 0xc18c3 + mov ax, strict word 00010h ; b8 10 00 ; 0xc18c7 + call 02e1ah ; e8 4d 15 ; 0xc18ca + xor bl, bl ; 30 db ; 0xc18cd vgabios.c:1195 + mov AL, strict byte 003h ; b0 03 ; 0xc18cf + mov AH, strict byte 011h ; b4 11 ; 0xc18d1 + int 06dh ; cd 6d ; 0xc18d3 + mov bx, 0596dh ; bb 6d 59 ; 0xc18d5 vgabios.c:1199 + mov cx, ds ; 8c d9 ; 0xc18d8 + mov ax, strict word 0001fh ; b8 1f 00 ; 0xc18da + call 009f0h ; e8 10 f1 ; 0xc18dd + mov es, [bp-01eh] ; 8e 46 e2 ; 0xc18e0 vgabios.c:1201 + mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xc18e3 + cmp AL, strict byte 010h ; 3c 10 ; 0xc18e7 + je short 01905h ; 74 1a ; 0xc18e9 + cmp AL, strict byte 00eh ; 3c 0e ; 0xc18eb + je short 01900h ; 74 11 ; 0xc18ed + cmp AL, strict byte 008h ; 3c 08 ; 0xc18ef + jne short 0190ah ; 75 17 ; 0xc18f1 + mov bx, 0556dh ; bb 6d 55 ; 0xc18f3 vgabios.c:1203 + mov cx, ds ; 8c d9 ; 0xc18f6 + mov ax, strict word 00043h ; b8 43 00 ; 0xc18f8 + call 009f0h ; e8 f2 f0 ; 0xc18fb + jmp short 0190ah ; eb 0a ; 0xc18fe vgabios.c:1204 + mov bx, 05d6dh ; bb 6d 5d ; 0xc1900 vgabios.c:1206 + jmp short 018f6h ; eb f1 ; 0xc1903 + mov bx, 06b6dh ; bb 6d 6b ; 0xc1905 vgabios.c:1209 + jmp short 018f6h ; eb ec ; 0xc1908 + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc190a vgabios.c:1212 + pop di ; 5f ; 0xc190d + pop si ; 5e ; 0xc190e + pop dx ; 5a ; 0xc190f + pop cx ; 59 ; 0xc1910 + pop bx ; 5b ; 0xc1911 + pop bp ; 5d ; 0xc1912 + retn ; c3 ; 0xc1913 + ; disGetNextSymbol 0xc1914 LB 0x2c1e -> off=0x0 cb=000000000000008e uValue=00000000000c1914 'vgamem_copy_pl4' +vgamem_copy_pl4: ; 0xc1914 LB 0x8e + push bp ; 55 ; 0xc1914 vgabios.c:1215 + mov bp, sp ; 89 e5 ; 0xc1915 + push si ; 56 ; 0xc1917 + push di ; 57 ; 0xc1918 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc1919 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc191c + mov al, dl ; 88 d0 ; 0xc191f + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc1921 + mov byte [bp-006h], cl ; 88 4e fa ; 0xc1924 + xor ah, ah ; 30 e4 ; 0xc1927 vgabios.c:1221 + mov dl, byte [bp+006h] ; 8a 56 06 ; 0xc1929 + xor dh, dh ; 30 f6 ; 0xc192c + mov cx, dx ; 89 d1 ; 0xc192e + imul dx ; f7 ea ; 0xc1930 + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc1932 + xor dh, dh ; 30 f6 ; 0xc1935 + mov si, dx ; 89 d6 ; 0xc1937 + imul dx ; f7 ea ; 0xc1939 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc193b + xor dh, dh ; 30 f6 ; 0xc193e + mov bx, dx ; 89 d3 ; 0xc1940 + add ax, dx ; 01 d0 ; 0xc1942 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc1944 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1947 vgabios.c:1222 + xor ah, ah ; 30 e4 ; 0xc194a + imul cx ; f7 e9 ; 0xc194c + imul si ; f7 ee ; 0xc194e + add ax, bx ; 01 d8 ; 0xc1950 + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc1952 + mov ax, 00105h ; b8 05 01 ; 0xc1955 vgabios.c:1223 + mov dx, 003ceh ; ba ce 03 ; 0xc1958 + out DX, ax ; ef ; 0xc195b + xor bl, bl ; 30 db ; 0xc195c vgabios.c:1224 + cmp bl, byte [bp+006h] ; 3a 5e 06 ; 0xc195e + jnc short 01992h ; 73 2f ; 0xc1961 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1963 vgabios.c:1226 + xor ah, ah ; 30 e4 ; 0xc1966 + mov cx, ax ; 89 c1 ; 0xc1968 + mov al, bl ; 88 d8 ; 0xc196a + mov dx, ax ; 89 c2 ; 0xc196c + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc196e + mov si, ax ; 89 c6 ; 0xc1971 + mov ax, dx ; 89 d0 ; 0xc1973 + imul si ; f7 ee ; 0xc1975 + mov si, word [bp-00eh] ; 8b 76 f2 ; 0xc1977 + add si, ax ; 01 c6 ; 0xc197a + mov di, word [bp-00ch] ; 8b 7e f4 ; 0xc197c + add di, ax ; 01 c7 ; 0xc197f + mov dx, 0a000h ; ba 00 a0 ; 0xc1981 + mov es, dx ; 8e c2 ; 0xc1984 + jcxz 0198eh ; e3 06 ; 0xc1986 + push DS ; 1e ; 0xc1988 + mov ds, dx ; 8e da ; 0xc1989 + rep movsb ; f3 a4 ; 0xc198b + pop DS ; 1f ; 0xc198d + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc198e vgabios.c:1227 + jmp short 0195eh ; eb cc ; 0xc1990 + mov ax, strict word 00005h ; b8 05 00 ; 0xc1992 vgabios.c:1228 + mov dx, 003ceh ; ba ce 03 ; 0xc1995 + out DX, ax ; ef ; 0xc1998 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1999 vgabios.c:1229 + pop di ; 5f ; 0xc199c + pop si ; 5e ; 0xc199d + pop bp ; 5d ; 0xc199e + retn 00004h ; c2 04 00 ; 0xc199f + ; disGetNextSymbol 0xc19a2 LB 0x2b90 -> off=0x0 cb=000000000000007b uValue=00000000000c19a2 'vgamem_fill_pl4' +vgamem_fill_pl4: ; 0xc19a2 LB 0x7b + push bp ; 55 ; 0xc19a2 vgabios.c:1232 + mov bp, sp ; 89 e5 ; 0xc19a3 + push si ; 56 ; 0xc19a5 + push di ; 57 ; 0xc19a6 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc19a7 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc19aa + mov al, dl ; 88 d0 ; 0xc19ad + mov byte [bp-006h], bl ; 88 5e fa ; 0xc19af + mov bh, cl ; 88 cf ; 0xc19b2 + xor ah, ah ; 30 e4 ; 0xc19b4 vgabios.c:1238 + mov dx, ax ; 89 c2 ; 0xc19b6 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc19b8 + mov cx, ax ; 89 c1 ; 0xc19bb + mov ax, dx ; 89 d0 ; 0xc19bd + imul cx ; f7 e9 ; 0xc19bf + mov dl, bh ; 88 fa ; 0xc19c1 + xor dh, dh ; 30 f6 ; 0xc19c3 + imul dx ; f7 ea ; 0xc19c5 + mov dx, ax ; 89 c2 ; 0xc19c7 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc19c9 + xor ah, ah ; 30 e4 ; 0xc19cc + add dx, ax ; 01 c2 ; 0xc19ce + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc19d0 + mov ax, 00205h ; b8 05 02 ; 0xc19d3 vgabios.c:1239 + mov dx, 003ceh ; ba ce 03 ; 0xc19d6 + out DX, ax ; ef ; 0xc19d9 + xor bl, bl ; 30 db ; 0xc19da vgabios.c:1240 + cmp bl, byte [bp+004h] ; 3a 5e 04 ; 0xc19dc + jnc short 01a0dh ; 73 2c ; 0xc19df + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc19e1 vgabios.c:1242 + xor ch, ch ; 30 ed ; 0xc19e4 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc19e6 + xor ah, ah ; 30 e4 ; 0xc19e9 + mov si, ax ; 89 c6 ; 0xc19eb + mov al, bl ; 88 d8 ; 0xc19ed + mov dx, ax ; 89 c2 ; 0xc19ef + mov al, bh ; 88 f8 ; 0xc19f1 + mov di, ax ; 89 c7 ; 0xc19f3 + mov ax, dx ; 89 d0 ; 0xc19f5 + imul di ; f7 ef ; 0xc19f7 + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc19f9 + add di, ax ; 01 c7 ; 0xc19fc + mov ax, si ; 89 f0 ; 0xc19fe + mov dx, 0a000h ; ba 00 a0 ; 0xc1a00 + mov es, dx ; 8e c2 ; 0xc1a03 + jcxz 01a09h ; e3 02 ; 0xc1a05 + rep stosb ; f3 aa ; 0xc1a07 + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc1a09 vgabios.c:1243 + jmp short 019dch ; eb cf ; 0xc1a0b + mov ax, strict word 00005h ; b8 05 00 ; 0xc1a0d vgabios.c:1244 + mov dx, 003ceh ; ba ce 03 ; 0xc1a10 + out DX, ax ; ef ; 0xc1a13 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1a14 vgabios.c:1245 + pop di ; 5f ; 0xc1a17 + pop si ; 5e ; 0xc1a18 + pop bp ; 5d ; 0xc1a19 + retn 00004h ; c2 04 00 ; 0xc1a1a + ; disGetNextSymbol 0xc1a1d LB 0x2b15 -> off=0x0 cb=00000000000000b6 uValue=00000000000c1a1d 'vgamem_copy_cga' +vgamem_copy_cga: ; 0xc1a1d LB 0xb6 + push bp ; 55 ; 0xc1a1d vgabios.c:1248 + mov bp, sp ; 89 e5 ; 0xc1a1e + push si ; 56 ; 0xc1a20 + push di ; 57 ; 0xc1a21 + sub sp, strict byte 0000eh ; 83 ec 0e ; 0xc1a22 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc1a25 + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc1a28 + mov byte [bp-00ah], cl ; 88 4e f6 ; 0xc1a2b + mov al, dl ; 88 d0 ; 0xc1a2e vgabios.c:1254 + xor ah, ah ; 30 e4 ; 0xc1a30 + mov bx, ax ; 89 c3 ; 0xc1a32 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1a34 + mov si, ax ; 89 c6 ; 0xc1a37 + mov ax, bx ; 89 d8 ; 0xc1a39 + imul si ; f7 ee ; 0xc1a3b + mov bl, byte [bp+004h] ; 8a 5e 04 ; 0xc1a3d + mov di, bx ; 89 df ; 0xc1a40 + imul bx ; f7 eb ; 0xc1a42 + mov dx, ax ; 89 c2 ; 0xc1a44 + sar dx, 1 ; d1 fa ; 0xc1a46 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1a48 + xor ah, ah ; 30 e4 ; 0xc1a4b + mov bx, ax ; 89 c3 ; 0xc1a4d + add dx, ax ; 01 c2 ; 0xc1a4f + mov word [bp-00eh], dx ; 89 56 f2 ; 0xc1a51 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1a54 vgabios.c:1255 + imul si ; f7 ee ; 0xc1a57 + imul di ; f7 ef ; 0xc1a59 + sar ax, 1 ; d1 f8 ; 0xc1a5b + add ax, bx ; 01 d8 ; 0xc1a5d + mov word [bp-010h], ax ; 89 46 f0 ; 0xc1a5f + mov byte [bp-006h], bh ; 88 7e fa ; 0xc1a62 vgabios.c:1256 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1a65 + xor ah, ah ; 30 e4 ; 0xc1a68 + cwd ; 99 ; 0xc1a6a + db 02bh, 0c2h + ; sub ax, dx ; 2b c2 ; 0xc1a6b + sar ax, 1 ; d1 f8 ; 0xc1a6d + mov bx, ax ; 89 c3 ; 0xc1a6f + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1a71 + xor ah, ah ; 30 e4 ; 0xc1a74 + cmp ax, bx ; 39 d8 ; 0xc1a76 + jnl short 01acah ; 7d 50 ; 0xc1a78 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc1a7a vgabios.c:1258 + xor bh, bh ; 30 ff ; 0xc1a7d + mov word [bp-012h], bx ; 89 5e ee ; 0xc1a7f + mov bl, byte [bp+004h] ; 8a 5e 04 ; 0xc1a82 + imul bx ; f7 eb ; 0xc1a85 + mov bx, ax ; 89 c3 ; 0xc1a87 + mov si, word [bp-00eh] ; 8b 76 f2 ; 0xc1a89 + add si, ax ; 01 c6 ; 0xc1a8c + mov di, word [bp-010h] ; 8b 7e f0 ; 0xc1a8e + add di, ax ; 01 c7 ; 0xc1a91 + mov cx, word [bp-012h] ; 8b 4e ee ; 0xc1a93 + mov dx, 0b800h ; ba 00 b8 ; 0xc1a96 + mov es, dx ; 8e c2 ; 0xc1a99 + jcxz 01aa3h ; e3 06 ; 0xc1a9b + push DS ; 1e ; 0xc1a9d + mov ds, dx ; 8e da ; 0xc1a9e + rep movsb ; f3 a4 ; 0xc1aa0 + pop DS ; 1f ; 0xc1aa2 + mov si, word [bp-00eh] ; 8b 76 f2 ; 0xc1aa3 vgabios.c:1259 + add si, 02000h ; 81 c6 00 20 ; 0xc1aa6 + add si, bx ; 01 de ; 0xc1aaa + mov di, word [bp-010h] ; 8b 7e f0 ; 0xc1aac + add di, 02000h ; 81 c7 00 20 ; 0xc1aaf + add di, bx ; 01 df ; 0xc1ab3 + mov cx, word [bp-012h] ; 8b 4e ee ; 0xc1ab5 + mov dx, 0b800h ; ba 00 b8 ; 0xc1ab8 + mov es, dx ; 8e c2 ; 0xc1abb + jcxz 01ac5h ; e3 06 ; 0xc1abd + push DS ; 1e ; 0xc1abf + mov ds, dx ; 8e da ; 0xc1ac0 + rep movsb ; f3 a4 ; 0xc1ac2 + pop DS ; 1f ; 0xc1ac4 + inc byte [bp-006h] ; fe 46 fa ; 0xc1ac5 vgabios.c:1260 + jmp short 01a65h ; eb 9b ; 0xc1ac8 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1aca vgabios.c:1261 + pop di ; 5f ; 0xc1acd + pop si ; 5e ; 0xc1ace + pop bp ; 5d ; 0xc1acf + retn 00004h ; c2 04 00 ; 0xc1ad0 + ; disGetNextSymbol 0xc1ad3 LB 0x2a5f -> off=0x0 cb=0000000000000094 uValue=00000000000c1ad3 'vgamem_fill_cga' +vgamem_fill_cga: ; 0xc1ad3 LB 0x94 + push bp ; 55 ; 0xc1ad3 vgabios.c:1264 + mov bp, sp ; 89 e5 ; 0xc1ad4 + push si ; 56 ; 0xc1ad6 + push di ; 57 ; 0xc1ad7 + sub sp, strict byte 0000ch ; 83 ec 0c ; 0xc1ad8 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc1adb + mov al, dl ; 88 d0 ; 0xc1ade + mov byte [bp-00ch], bl ; 88 5e f4 ; 0xc1ae0 + mov byte [bp-008h], cl ; 88 4e f8 ; 0xc1ae3 + xor ah, ah ; 30 e4 ; 0xc1ae6 vgabios.c:1270 + mov dx, ax ; 89 c2 ; 0xc1ae8 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1aea + mov bx, ax ; 89 c3 ; 0xc1aed + mov ax, dx ; 89 d0 ; 0xc1aef + imul bx ; f7 eb ; 0xc1af1 + mov dl, cl ; 88 ca ; 0xc1af3 + xor dh, dh ; 30 f6 ; 0xc1af5 + imul dx ; f7 ea ; 0xc1af7 + mov dx, ax ; 89 c2 ; 0xc1af9 + sar dx, 1 ; d1 fa ; 0xc1afb + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1afd + xor ah, ah ; 30 e4 ; 0xc1b00 + add dx, ax ; 01 c2 ; 0xc1b02 + mov word [bp-00eh], dx ; 89 56 f2 ; 0xc1b04 + mov byte [bp-006h], ah ; 88 66 fa ; 0xc1b07 vgabios.c:1271 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1b0a + xor ah, ah ; 30 e4 ; 0xc1b0d + cwd ; 99 ; 0xc1b0f + db 02bh, 0c2h + ; sub ax, dx ; 2b c2 ; 0xc1b10 + sar ax, 1 ; d1 f8 ; 0xc1b12 + mov dx, ax ; 89 c2 ; 0xc1b14 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1b16 + xor ah, ah ; 30 e4 ; 0xc1b19 + cmp ax, dx ; 39 d0 ; 0xc1b1b + jnl short 01b5eh ; 7d 3f ; 0xc1b1d + mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xc1b1f vgabios.c:1273 + xor bh, bh ; 30 ff ; 0xc1b22 + mov dl, byte [bp+006h] ; 8a 56 06 ; 0xc1b24 + xor dh, dh ; 30 f6 ; 0xc1b27 + mov si, dx ; 89 d6 ; 0xc1b29 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc1b2b + imul dx ; f7 ea ; 0xc1b2e + mov word [bp-010h], ax ; 89 46 f0 ; 0xc1b30 + mov di, word [bp-00eh] ; 8b 7e f2 ; 0xc1b33 + add di, ax ; 01 c7 ; 0xc1b36 + mov cx, bx ; 89 d9 ; 0xc1b38 + mov ax, si ; 89 f0 ; 0xc1b3a + mov dx, 0b800h ; ba 00 b8 ; 0xc1b3c + mov es, dx ; 8e c2 ; 0xc1b3f + jcxz 01b45h ; e3 02 ; 0xc1b41 + rep stosb ; f3 aa ; 0xc1b43 + mov di, word [bp-00eh] ; 8b 7e f2 ; 0xc1b45 vgabios.c:1274 + add di, 02000h ; 81 c7 00 20 ; 0xc1b48 + add di, word [bp-010h] ; 03 7e f0 ; 0xc1b4c + mov cx, bx ; 89 d9 ; 0xc1b4f + mov ax, si ; 89 f0 ; 0xc1b51 + mov es, dx ; 8e c2 ; 0xc1b53 + jcxz 01b59h ; e3 02 ; 0xc1b55 + rep stosb ; f3 aa ; 0xc1b57 + inc byte [bp-006h] ; fe 46 fa ; 0xc1b59 vgabios.c:1275 + jmp short 01b0ah ; eb ac ; 0xc1b5c + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1b5e vgabios.c:1276 + pop di ; 5f ; 0xc1b61 + pop si ; 5e ; 0xc1b62 + pop bp ; 5d ; 0xc1b63 + retn 00004h ; c2 04 00 ; 0xc1b64 + ; disGetNextSymbol 0xc1b67 LB 0x29cb -> off=0x0 cb=0000000000000081 uValue=00000000000c1b67 'vgamem_copy_linear' +vgamem_copy_linear: ; 0xc1b67 LB 0x81 + push bp ; 55 ; 0xc1b67 vgabios.c:1279 + mov bp, sp ; 89 e5 ; 0xc1b68 + push si ; 56 ; 0xc1b6a + push di ; 57 ; 0xc1b6b + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc1b6c + mov byte [bp-008h], al ; 88 46 f8 ; 0xc1b6f + mov al, dl ; 88 d0 ; 0xc1b72 + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc1b74 + mov bx, cx ; 89 cb ; 0xc1b77 + xor ah, ah ; 30 e4 ; 0xc1b79 vgabios.c:1285 + mov si, ax ; 89 c6 ; 0xc1b7b + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1b7d + mov di, ax ; 89 c7 ; 0xc1b80 + mov ax, si ; 89 f0 ; 0xc1b82 + imul di ; f7 ef ; 0xc1b84 + mul word [bp+004h] ; f7 66 04 ; 0xc1b86 + mov si, ax ; 89 c6 ; 0xc1b89 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1b8b + xor ah, ah ; 30 e4 ; 0xc1b8e + mov cx, ax ; 89 c1 ; 0xc1b90 + add si, ax ; 01 c6 ; 0xc1b92 + sal si, 003h ; c1 e6 03 ; 0xc1b94 + mov word [bp-00ch], si ; 89 76 f4 ; 0xc1b97 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1b9a vgabios.c:1286 + imul di ; f7 ef ; 0xc1b9d + mul word [bp+004h] ; f7 66 04 ; 0xc1b9f + add ax, cx ; 01 c8 ; 0xc1ba2 + sal ax, 003h ; c1 e0 03 ; 0xc1ba4 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc1ba7 + sal bx, 003h ; c1 e3 03 ; 0xc1baa vgabios.c:1287 + sal word [bp+004h], 003h ; c1 66 04 03 ; 0xc1bad vgabios.c:1288 + mov byte [bp-006h], ch ; 88 6e fa ; 0xc1bb1 vgabios.c:1289 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1bb4 + cmp al, byte [bp+006h] ; 3a 46 06 ; 0xc1bb7 + jnc short 01bdfh ; 73 23 ; 0xc1bba + xor ah, ah ; 30 e4 ; 0xc1bbc vgabios.c:1291 + mul word [bp+004h] ; f7 66 04 ; 0xc1bbe + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc1bc1 + add si, ax ; 01 c6 ; 0xc1bc4 + mov di, word [bp-00eh] ; 8b 7e f2 ; 0xc1bc6 + add di, ax ; 01 c7 ; 0xc1bc9 + mov cx, bx ; 89 d9 ; 0xc1bcb + mov dx, 0a000h ; ba 00 a0 ; 0xc1bcd + mov es, dx ; 8e c2 ; 0xc1bd0 + jcxz 01bdah ; e3 06 ; 0xc1bd2 + push DS ; 1e ; 0xc1bd4 + mov ds, dx ; 8e da ; 0xc1bd5 + rep movsb ; f3 a4 ; 0xc1bd7 + pop DS ; 1f ; 0xc1bd9 + inc byte [bp-006h] ; fe 46 fa ; 0xc1bda vgabios.c:1292 + jmp short 01bb4h ; eb d5 ; 0xc1bdd + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1bdf vgabios.c:1293 + pop di ; 5f ; 0xc1be2 + pop si ; 5e ; 0xc1be3 + pop bp ; 5d ; 0xc1be4 + retn 00004h ; c2 04 00 ; 0xc1be5 + ; disGetNextSymbol 0xc1be8 LB 0x294a -> off=0x0 cb=000000000000006d uValue=00000000000c1be8 'vgamem_fill_linear' +vgamem_fill_linear: ; 0xc1be8 LB 0x6d + push bp ; 55 ; 0xc1be8 vgabios.c:1296 + mov bp, sp ; 89 e5 ; 0xc1be9 + push si ; 56 ; 0xc1beb + push di ; 57 ; 0xc1bec + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc1bed + mov byte [bp-006h], al ; 88 46 fa ; 0xc1bf0 + mov al, dl ; 88 d0 ; 0xc1bf3 + mov si, cx ; 89 ce ; 0xc1bf5 + xor ah, ah ; 30 e4 ; 0xc1bf7 vgabios.c:1302 + mov dx, ax ; 89 c2 ; 0xc1bf9 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1bfb + mov di, ax ; 89 c7 ; 0xc1bfe + mov ax, dx ; 89 d0 ; 0xc1c00 + imul di ; f7 ef ; 0xc1c02 + mul cx ; f7 e1 ; 0xc1c04 + mov dx, ax ; 89 c2 ; 0xc1c06 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1c08 + xor ah, ah ; 30 e4 ; 0xc1c0b + add ax, dx ; 01 d0 ; 0xc1c0d + sal ax, 003h ; c1 e0 03 ; 0xc1c0f + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc1c12 + sal bx, 003h ; c1 e3 03 ; 0xc1c15 vgabios.c:1303 + sal si, 003h ; c1 e6 03 ; 0xc1c18 vgabios.c:1304 + mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xc1c1b vgabios.c:1305 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1c1f + cmp al, byte [bp+004h] ; 3a 46 04 ; 0xc1c22 + jnc short 01c4ch ; 73 25 ; 0xc1c25 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1c27 vgabios.c:1307 + xor ah, ah ; 30 e4 ; 0xc1c2a + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc1c2c + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1c2f + mul si ; f7 e6 ; 0xc1c32 + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc1c34 + add di, ax ; 01 c7 ; 0xc1c37 + mov cx, bx ; 89 d9 ; 0xc1c39 + mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xc1c3b + mov dx, 0a000h ; ba 00 a0 ; 0xc1c3e + mov es, dx ; 8e c2 ; 0xc1c41 + jcxz 01c47h ; e3 02 ; 0xc1c43 + rep stosb ; f3 aa ; 0xc1c45 + inc byte [bp-008h] ; fe 46 f8 ; 0xc1c47 vgabios.c:1308 + jmp short 01c1fh ; eb d3 ; 0xc1c4a + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1c4c vgabios.c:1309 + pop di ; 5f ; 0xc1c4f + pop si ; 5e ; 0xc1c50 + pop bp ; 5d ; 0xc1c51 + retn 00004h ; c2 04 00 ; 0xc1c52 + ; disGetNextSymbol 0xc1c55 LB 0x28dd -> off=0x0 cb=0000000000000688 uValue=00000000000c1c55 'biosfn_scroll' +biosfn_scroll: ; 0xc1c55 LB 0x688 + push bp ; 55 ; 0xc1c55 vgabios.c:1312 + mov bp, sp ; 89 e5 ; 0xc1c56 + push si ; 56 ; 0xc1c58 + push di ; 57 ; 0xc1c59 + sub sp, strict byte 0001eh ; 83 ec 1e ; 0xc1c5a + mov byte [bp-006h], al ; 88 46 fa ; 0xc1c5d + mov byte [bp-010h], dl ; 88 56 f0 ; 0xc1c60 + mov byte [bp-00ch], bl ; 88 5e f4 ; 0xc1c63 + mov byte [bp-008h], cl ; 88 4e f8 ; 0xc1c66 + cmp bl, byte [bp+004h] ; 3a 5e 04 ; 0xc1c69 vgabios.c:1321 + jnbe short 01c8ah ; 77 1c ; 0xc1c6c + cmp cl, byte [bp+006h] ; 3a 4e 06 ; 0xc1c6e vgabios.c:1322 + jnbe short 01c8ah ; 77 17 ; 0xc1c71 + mov bx, strict word 00049h ; bb 49 00 ; 0xc1c73 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1c76 + mov es, ax ; 8e c0 ; 0xc1c79 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1c7b + xor ah, ah ; 30 e4 ; 0xc1c7e vgabios.c:1326 + call 03819h ; e8 96 1b ; 0xc1c80 + mov byte [bp-012h], al ; 88 46 ee ; 0xc1c83 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc1c86 vgabios.c:1327 + jne short 01c8dh ; 75 03 ; 0xc1c88 + jmp near 022d4h ; e9 47 06 ; 0xc1c8a + mov bx, 00084h ; bb 84 00 ; 0xc1c8d vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1c90 + mov es, ax ; 8e c0 ; 0xc1c93 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1c95 + xor ah, ah ; 30 e4 ; 0xc1c98 vgabios.c:48 + inc ax ; 40 ; 0xc1c9a + mov word [bp-016h], ax ; 89 46 ea ; 0xc1c9b + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1c9e vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc1ca1 + mov word [bp-01eh], ax ; 89 46 e2 ; 0xc1ca4 vgabios.c:58 + cmp byte [bp+008h], 0ffh ; 80 7e 08 ff ; 0xc1ca7 vgabios.c:1334 + jne short 01cb6h ; 75 09 ; 0xc1cab + mov bx, strict word 00062h ; bb 62 00 ; 0xc1cad vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1cb0 + mov byte [bp+008h], al ; 88 46 08 ; 0xc1cb3 vgabios.c:48 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1cb6 vgabios.c:1337 + xor ah, ah ; 30 e4 ; 0xc1cb9 + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc1cbb + jc short 01cc8h ; 72 08 ; 0xc1cbe + mov al, byte [bp-016h] ; 8a 46 ea ; 0xc1cc0 + db 0feh, 0c8h + ; dec al ; fe c8 ; 0xc1cc3 + mov byte [bp+004h], al ; 88 46 04 ; 0xc1cc5 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1cc8 vgabios.c:1338 + xor ah, ah ; 30 e4 ; 0xc1ccb + cmp ax, word [bp-01eh] ; 3b 46 e2 ; 0xc1ccd + jc short 01cdah ; 72 08 ; 0xc1cd0 + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc1cd2 + db 0feh, 0c8h + ; dec al ; fe c8 ; 0xc1cd5 + mov byte [bp+006h], al ; 88 46 06 ; 0xc1cd7 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1cda vgabios.c:1339 + xor ah, ah ; 30 e4 ; 0xc1cdd + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc1cdf + jbe short 01ce7h ; 76 03 ; 0xc1ce2 + mov byte [bp-006h], ah ; 88 66 fa ; 0xc1ce4 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1ce7 vgabios.c:1340 + sub al, byte [bp-008h] ; 2a 46 f8 ; 0xc1cea + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc1ced + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc1cef + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc1cf2 vgabios.c:1342 + mov byte [bp-01ah], al ; 88 46 e6 ; 0xc1cf5 + mov byte [bp-019h], 000h ; c6 46 e7 00 ; 0xc1cf8 + mov bx, word [bp-01ah] ; 8b 5e e6 ; 0xc1cfc + sal bx, 003h ; c1 e3 03 ; 0xc1cff + mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xc1d02 + dec ax ; 48 ; 0xc1d05 + mov word [bp-022h], ax ; 89 46 de ; 0xc1d06 + mov di, word [bp-016h] ; 8b 7e ea ; 0xc1d09 + dec di ; 4f ; 0xc1d0c + mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xc1d0d + mul word [bp-016h] ; f7 66 ea ; 0xc1d10 + mov cx, ax ; 89 c1 ; 0xc1d13 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc1d15 + jne short 01d65h ; 75 49 ; 0xc1d1a + add ax, ax ; 01 c0 ; 0xc1d1c vgabios.c:1345 + or AL, strict byte 0ffh ; 0c ff ; 0xc1d1e + mov dl, byte [bp+008h] ; 8a 56 08 ; 0xc1d20 + xor dh, dh ; 30 f6 ; 0xc1d23 + inc ax ; 40 ; 0xc1d25 + mul dx ; f7 e2 ; 0xc1d26 + mov word [bp-020h], ax ; 89 46 e0 ; 0xc1d28 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1d2b vgabios.c:1350 + jne short 01d68h ; 75 37 ; 0xc1d2f + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc1d31 + jne short 01d68h ; 75 31 ; 0xc1d35 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1d37 + jne short 01d68h ; 75 2b ; 0xc1d3b + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1d3d + xor ah, ah ; 30 e4 ; 0xc1d40 + cmp ax, di ; 39 f8 ; 0xc1d42 + jne short 01d68h ; 75 22 ; 0xc1d44 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1d46 + cmp ax, word [bp-022h] ; 3b 46 de ; 0xc1d49 + jne short 01d68h ; 75 1a ; 0xc1d4c + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc1d4e vgabios.c:1352 + sal ax, 008h ; c1 e0 08 ; 0xc1d51 + add ax, strict word 00020h ; 05 20 00 ; 0xc1d54 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1d57 + mov di, word [bp-020h] ; 8b 7e e0 ; 0xc1d5b + jcxz 01d62h ; e3 02 ; 0xc1d5e + rep stosw ; f3 ab ; 0xc1d60 + jmp near 022d4h ; e9 6f 05 ; 0xc1d62 vgabios.c:1354 + jmp near 01ed8h ; e9 70 01 ; 0xc1d65 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc1d68 vgabios.c:1356 + jne short 01dceh ; 75 60 ; 0xc1d6c + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1d6e vgabios.c:1357 + xor ah, ah ; 30 e4 ; 0xc1d71 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc1d73 + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc1d76 + xor dh, dh ; 30 f6 ; 0xc1d79 + cmp dx, word [bp-01ch] ; 3b 56 e4 ; 0xc1d7b + jc short 01dd0h ; 72 50 ; 0xc1d7e + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1d80 vgabios.c:1359 + xor ah, ah ; 30 e4 ; 0xc1d83 + add ax, word [bp-01ch] ; 03 46 e4 ; 0xc1d85 + cmp ax, dx ; 39 d0 ; 0xc1d88 + jnbe short 01d92h ; 77 06 ; 0xc1d8a + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1d8c + jne short 01dd3h ; 75 41 ; 0xc1d90 + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc1d92 vgabios.c:1360 + xor ch, ch ; 30 ed ; 0xc1d95 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc1d97 + xor ah, ah ; 30 e4 ; 0xc1d9a + mov si, ax ; 89 c6 ; 0xc1d9c + sal si, 008h ; c1 e6 08 ; 0xc1d9e + add si, strict byte 00020h ; 83 c6 20 ; 0xc1da1 + mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xc1da4 + mul word [bp-01eh] ; f7 66 e2 ; 0xc1da7 + mov dx, ax ; 89 c2 ; 0xc1daa + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1dac + xor ah, ah ; 30 e4 ; 0xc1daf + mov di, ax ; 89 c7 ; 0xc1db1 + add di, dx ; 01 d7 ; 0xc1db3 + add di, di ; 01 ff ; 0xc1db5 + add di, word [bp-020h] ; 03 7e e0 ; 0xc1db7 + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1dba + xor bh, bh ; 30 ff ; 0xc1dbd + sal bx, 003h ; c1 e3 03 ; 0xc1dbf + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1dc2 + mov ax, si ; 89 f0 ; 0xc1dc6 + jcxz 01dcch ; e3 02 ; 0xc1dc8 + rep stosw ; f3 ab ; 0xc1dca + jmp short 01e13h ; eb 45 ; 0xc1dcc vgabios.c:1361 + jmp short 01e19h ; eb 49 ; 0xc1dce + jmp near 022d4h ; e9 01 05 ; 0xc1dd0 + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc1dd3 vgabios.c:1362 + xor ch, ch ; 30 ed ; 0xc1dd6 + mul word [bp-01eh] ; f7 66 e2 ; 0xc1dd8 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc1ddb + mov byte [bp-018h], dl ; 88 56 e8 ; 0xc1dde + mov byte [bp-017h], ch ; 88 6e e9 ; 0xc1de1 + mov si, ax ; 89 c6 ; 0xc1de4 + add si, word [bp-018h] ; 03 76 e8 ; 0xc1de6 + add si, si ; 01 f6 ; 0xc1de9 + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1deb + xor bh, bh ; 30 ff ; 0xc1dee + sal bx, 003h ; c1 e3 03 ; 0xc1df0 + mov bx, word [bx+047b3h] ; 8b 9f b3 47 ; 0xc1df3 + mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xc1df7 + mul word [bp-01eh] ; f7 66 e2 ; 0xc1dfa + add ax, word [bp-018h] ; 03 46 e8 ; 0xc1dfd + add ax, ax ; 01 c0 ; 0xc1e00 + mov di, word [bp-020h] ; 8b 7e e0 ; 0xc1e02 + add di, ax ; 01 c7 ; 0xc1e05 + mov dx, bx ; 89 da ; 0xc1e07 + mov es, bx ; 8e c3 ; 0xc1e09 + jcxz 01e13h ; e3 06 ; 0xc1e0b + push DS ; 1e ; 0xc1e0d + mov ds, dx ; 8e da ; 0xc1e0e + rep movsw ; f3 a5 ; 0xc1e10 + pop DS ; 1f ; 0xc1e12 + inc word [bp-01ch] ; ff 46 e4 ; 0xc1e13 vgabios.c:1363 + jmp near 01d76h ; e9 5d ff ; 0xc1e16 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1e19 vgabios.c:1366 + xor ah, ah ; 30 e4 ; 0xc1e1c + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc1e1e + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1e21 + xor ah, ah ; 30 e4 ; 0xc1e24 + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc1e26 + jnbe short 01dd0h ; 77 a5 ; 0xc1e29 + mov dl, al ; 88 c2 ; 0xc1e2b vgabios.c:1368 + xor dh, dh ; 30 f6 ; 0xc1e2d + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1e2f + add ax, dx ; 01 d0 ; 0xc1e32 + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc1e34 + jnbe short 01e3fh ; 77 06 ; 0xc1e37 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1e39 + jne short 01e7bh ; 75 3c ; 0xc1e3d + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc1e3f vgabios.c:1369 + xor ch, ch ; 30 ed ; 0xc1e42 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc1e44 + xor ah, ah ; 30 e4 ; 0xc1e47 + mov si, ax ; 89 c6 ; 0xc1e49 + sal si, 008h ; c1 e6 08 ; 0xc1e4b + add si, strict byte 00020h ; 83 c6 20 ; 0xc1e4e + mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xc1e51 + mul word [bp-01eh] ; f7 66 e2 ; 0xc1e54 + mov dx, ax ; 89 c2 ; 0xc1e57 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1e59 + xor ah, ah ; 30 e4 ; 0xc1e5c + add ax, dx ; 01 d0 ; 0xc1e5e + add ax, ax ; 01 c0 ; 0xc1e60 + mov di, word [bp-020h] ; 8b 7e e0 ; 0xc1e62 + add di, ax ; 01 c7 ; 0xc1e65 + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1e67 + xor bh, bh ; 30 ff ; 0xc1e6a + sal bx, 003h ; c1 e3 03 ; 0xc1e6c + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1e6f + mov ax, si ; 89 f0 ; 0xc1e73 + jcxz 01e79h ; e3 02 ; 0xc1e75 + rep stosw ; f3 ab ; 0xc1e77 + jmp short 01ec8h ; eb 4d ; 0xc1e79 vgabios.c:1370 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1e7b vgabios.c:1371 + mov byte [bp-018h], al ; 88 46 e8 ; 0xc1e7e + mov byte [bp-017h], dh ; 88 76 e9 ; 0xc1e81 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1e84 + xor ah, ah ; 30 e4 ; 0xc1e87 + mov dx, word [bp-01ch] ; 8b 56 e4 ; 0xc1e89 + sub dx, ax ; 29 c2 ; 0xc1e8c + mov ax, dx ; 89 d0 ; 0xc1e8e + mul word [bp-01eh] ; f7 66 e2 ; 0xc1e90 + mov cl, byte [bp-008h] ; 8a 4e f8 ; 0xc1e93 + xor ch, ch ; 30 ed ; 0xc1e96 + mov si, ax ; 89 c6 ; 0xc1e98 + add si, cx ; 01 ce ; 0xc1e9a + add si, si ; 01 f6 ; 0xc1e9c + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1e9e + xor bh, bh ; 30 ff ; 0xc1ea1 + sal bx, 003h ; c1 e3 03 ; 0xc1ea3 + mov bx, word [bx+047b3h] ; 8b 9f b3 47 ; 0xc1ea6 + mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xc1eaa + mul word [bp-01eh] ; f7 66 e2 ; 0xc1ead + add ax, cx ; 01 c8 ; 0xc1eb0 + add ax, ax ; 01 c0 ; 0xc1eb2 + mov di, word [bp-020h] ; 8b 7e e0 ; 0xc1eb4 + add di, ax ; 01 c7 ; 0xc1eb7 + mov cx, word [bp-018h] ; 8b 4e e8 ; 0xc1eb9 + mov dx, bx ; 89 da ; 0xc1ebc + mov es, bx ; 8e c3 ; 0xc1ebe + jcxz 01ec8h ; e3 06 ; 0xc1ec0 + push DS ; 1e ; 0xc1ec2 + mov ds, dx ; 8e da ; 0xc1ec3 + rep movsw ; f3 a5 ; 0xc1ec5 + pop DS ; 1f ; 0xc1ec7 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1ec8 vgabios.c:1372 + xor ah, ah ; 30 e4 ; 0xc1ecb + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc1ecd + jc short 01f05h ; 72 33 ; 0xc1ed0 + dec word [bp-01ch] ; ff 4e e4 ; 0xc1ed2 vgabios.c:1373 + jmp near 01e21h ; e9 49 ff ; 0xc1ed5 + mov si, word [bp-01ah] ; 8b 76 e6 ; 0xc1ed8 vgabios.c:1379 + mov al, byte [si+0482fh] ; 8a 84 2f 48 ; 0xc1edb + xor ah, ah ; 30 e4 ; 0xc1edf + mov si, ax ; 89 c6 ; 0xc1ee1 + sal si, 006h ; c1 e6 06 ; 0xc1ee3 + mov al, byte [si+04845h] ; 8a 84 45 48 ; 0xc1ee6 + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc1eea + mov al, byte [bx+047b1h] ; 8a 87 b1 47 ; 0xc1eed vgabios.c:1380 + cmp AL, strict byte 003h ; 3c 03 ; 0xc1ef1 + jc short 01f01h ; 72 0c ; 0xc1ef3 + jbe short 01f08h ; 76 11 ; 0xc1ef5 + cmp AL, strict byte 005h ; 3c 05 ; 0xc1ef7 + je short 01f36h ; 74 3b ; 0xc1ef9 + cmp AL, strict byte 004h ; 3c 04 ; 0xc1efb + je short 01f08h ; 74 09 ; 0xc1efd + jmp short 01f05h ; eb 04 ; 0xc1eff + cmp AL, strict byte 002h ; 3c 02 ; 0xc1f01 + je short 01f39h ; 74 34 ; 0xc1f03 + jmp near 022d4h ; e9 cc 03 ; 0xc1f05 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1f08 vgabios.c:1384 + jne short 01f34h ; 75 26 ; 0xc1f0c + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc1f0e + jne short 01f76h ; 75 62 ; 0xc1f12 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1f14 + jne short 01f76h ; 75 5c ; 0xc1f18 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1f1a + xor ah, ah ; 30 e4 ; 0xc1f1d + mov dx, word [bp-016h] ; 8b 56 ea ; 0xc1f1f + dec dx ; 4a ; 0xc1f22 + cmp ax, dx ; 39 d0 ; 0xc1f23 + jne short 01f76h ; 75 4f ; 0xc1f25 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1f27 + xor ah, dh ; 30 f4 ; 0xc1f2a + mov dx, word [bp-01eh] ; 8b 56 e2 ; 0xc1f2c + dec dx ; 4a ; 0xc1f2f + cmp ax, dx ; 39 d0 ; 0xc1f30 + je short 01f3ch ; 74 08 ; 0xc1f32 + jmp short 01f76h ; eb 40 ; 0xc1f34 + jmp near 021ach ; e9 73 02 ; 0xc1f36 + jmp near 02066h ; e9 2a 01 ; 0xc1f39 + mov ax, 00205h ; b8 05 02 ; 0xc1f3c vgabios.c:1386 + mov dx, 003ceh ; ba ce 03 ; 0xc1f3f + out DX, ax ; ef ; 0xc1f42 + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc1f43 vgabios.c:1387 + mul word [bp-01eh] ; f7 66 e2 ; 0xc1f46 + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc1f49 + xor dh, dh ; 30 f6 ; 0xc1f4c + mul dx ; f7 e2 ; 0xc1f4e + mov dl, byte [bp-010h] ; 8a 56 f0 ; 0xc1f50 + xor dh, dh ; 30 f6 ; 0xc1f53 + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1f55 + xor bh, bh ; 30 ff ; 0xc1f58 + sal bx, 003h ; c1 e3 03 ; 0xc1f5a + mov bx, word [bx+047b3h] ; 8b 9f b3 47 ; 0xc1f5d + mov cx, ax ; 89 c1 ; 0xc1f61 + mov ax, dx ; 89 d0 ; 0xc1f63 + xor di, di ; 31 ff ; 0xc1f65 + mov es, bx ; 8e c3 ; 0xc1f67 + jcxz 01f6dh ; e3 02 ; 0xc1f69 + rep stosb ; f3 aa ; 0xc1f6b + mov ax, strict word 00005h ; b8 05 00 ; 0xc1f6d vgabios.c:1388 + mov dx, 003ceh ; ba ce 03 ; 0xc1f70 + out DX, ax ; ef ; 0xc1f73 + jmp short 01f05h ; eb 8f ; 0xc1f74 vgabios.c:1390 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc1f76 vgabios.c:1392 + jne short 01ff1h ; 75 75 ; 0xc1f7a + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1f7c vgabios.c:1393 + xor ah, ah ; 30 e4 ; 0xc1f7f + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc1f81 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1f84 + xor ah, ah ; 30 e4 ; 0xc1f87 + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc1f89 + jc short 01feeh ; 72 60 ; 0xc1f8c + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc1f8e vgabios.c:1395 + xor dh, dh ; 30 f6 ; 0xc1f91 + add dx, word [bp-01ch] ; 03 56 e4 ; 0xc1f93 + cmp dx, ax ; 39 c2 ; 0xc1f96 + jnbe short 01fa0h ; 77 06 ; 0xc1f98 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1f9a + jne short 01fc1h ; 75 21 ; 0xc1f9e + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc1fa0 vgabios.c:1396 + xor ah, ah ; 30 e4 ; 0xc1fa3 + push ax ; 50 ; 0xc1fa5 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc1fa6 + push ax ; 50 ; 0xc1fa9 + mov cl, byte [bp-01eh] ; 8a 4e e2 ; 0xc1faa + xor ch, ch ; 30 ed ; 0xc1fad + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc1faf + xor bh, bh ; 30 ff ; 0xc1fb2 + mov dl, byte [bp-01ch] ; 8a 56 e4 ; 0xc1fb4 + xor dh, dh ; 30 f6 ; 0xc1fb7 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1fb9 + call 019a2h ; e8 e3 f9 ; 0xc1fbc + jmp short 01fe9h ; eb 28 ; 0xc1fbf vgabios.c:1397 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc1fc1 vgabios.c:1398 + push ax ; 50 ; 0xc1fc4 + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc1fc5 + push ax ; 50 ; 0xc1fc8 + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc1fc9 + xor ch, ch ; 30 ed ; 0xc1fcc + mov bl, byte [bp-01ch] ; 8a 5e e4 ; 0xc1fce + xor bh, bh ; 30 ff ; 0xc1fd1 + mov dl, bl ; 88 da ; 0xc1fd3 + add dl, byte [bp-006h] ; 02 56 fa ; 0xc1fd5 + xor dh, dh ; 30 f6 ; 0xc1fd8 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1fda + mov byte [bp-018h], al ; 88 46 e8 ; 0xc1fdd + mov byte [bp-017h], ah ; 88 66 e9 ; 0xc1fe0 + mov ax, word [bp-018h] ; 8b 46 e8 ; 0xc1fe3 + call 01914h ; e8 2b f9 ; 0xc1fe6 + inc word [bp-01ch] ; ff 46 e4 ; 0xc1fe9 vgabios.c:1399 + jmp short 01f84h ; eb 96 ; 0xc1fec + jmp near 022d4h ; e9 e3 02 ; 0xc1fee + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1ff1 vgabios.c:1402 + xor ah, ah ; 30 e4 ; 0xc1ff4 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc1ff6 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1ff9 + xor ah, ah ; 30 e4 ; 0xc1ffc + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc1ffe + jnbe short 01feeh ; 77 eb ; 0xc2001 + mov dl, al ; 88 c2 ; 0xc2003 vgabios.c:1404 + xor dh, dh ; 30 f6 ; 0xc2005 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2007 + add ax, dx ; 01 d0 ; 0xc200a + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc200c + jnbe short 02017h ; 77 06 ; 0xc200f + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc2011 + jne short 02038h ; 75 21 ; 0xc2015 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2017 vgabios.c:1405 + xor ah, ah ; 30 e4 ; 0xc201a + push ax ; 50 ; 0xc201c + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc201d + push ax ; 50 ; 0xc2020 + mov cl, byte [bp-01eh] ; 8a 4e e2 ; 0xc2021 + xor ch, ch ; 30 ed ; 0xc2024 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc2026 + xor bh, bh ; 30 ff ; 0xc2029 + mov dl, byte [bp-01ch] ; 8a 56 e4 ; 0xc202b + xor dh, dh ; 30 f6 ; 0xc202e + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2030 + call 019a2h ; e8 6c f9 ; 0xc2033 + jmp short 02057h ; eb 1f ; 0xc2036 vgabios.c:1406 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2038 vgabios.c:1407 + xor ah, ah ; 30 e4 ; 0xc203b + push ax ; 50 ; 0xc203d + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc203e + push ax ; 50 ; 0xc2041 + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc2042 + xor ch, ch ; 30 ed ; 0xc2045 + mov bl, byte [bp-01ch] ; 8a 5e e4 ; 0xc2047 + xor bh, bh ; 30 ff ; 0xc204a + mov dl, bl ; 88 da ; 0xc204c + sub dl, byte [bp-006h] ; 2a 56 fa ; 0xc204e + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2051 + call 01914h ; e8 bd f8 ; 0xc2054 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc2057 vgabios.c:1408 + xor ah, ah ; 30 e4 ; 0xc205a + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc205c + jc short 020afh ; 72 4e ; 0xc205f + dec word [bp-01ch] ; ff 4e e4 ; 0xc2061 vgabios.c:1409 + jmp short 01ff9h ; eb 93 ; 0xc2064 + mov al, byte [bx+047b2h] ; 8a 87 b2 47 ; 0xc2066 vgabios.c:1414 + mov byte [bp-014h], al ; 88 46 ec ; 0xc206a + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc206d vgabios.c:1415 + jne short 020b2h ; 75 3f ; 0xc2071 + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc2073 + jne short 020b2h ; 75 39 ; 0xc2077 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc2079 + jne short 020b2h ; 75 33 ; 0xc207d + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc207f + cmp ax, di ; 39 f8 ; 0xc2082 + jne short 020b2h ; 75 2c ; 0xc2084 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc2086 + cmp ax, word [bp-022h] ; 3b 46 de ; 0xc2089 + jne short 020b2h ; 75 24 ; 0xc208c + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc208e vgabios.c:1417 + xor dh, dh ; 30 f6 ; 0xc2091 + mov ax, cx ; 89 c8 ; 0xc2093 + mul dx ; f7 e2 ; 0xc2095 + mov dl, byte [bp-014h] ; 8a 56 ec ; 0xc2097 + xor dh, dh ; 30 f6 ; 0xc209a + mul dx ; f7 e2 ; 0xc209c + mov cx, ax ; 89 c1 ; 0xc209e + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc20a0 + xor ah, ah ; 30 e4 ; 0xc20a3 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc20a5 + xor di, di ; 31 ff ; 0xc20a9 + jcxz 020afh ; e3 02 ; 0xc20ab + rep stosb ; f3 aa ; 0xc20ad + jmp near 022d4h ; e9 22 02 ; 0xc20af vgabios.c:1419 + cmp byte [bp-014h], 002h ; 80 7e ec 02 ; 0xc20b2 vgabios.c:1421 + jne short 020c1h ; 75 09 ; 0xc20b6 + sal byte [bp-008h], 1 ; d0 66 f8 ; 0xc20b8 vgabios.c:1423 + sal byte [bp-00ah], 1 ; d0 66 f6 ; 0xc20bb vgabios.c:1424 + sal word [bp-01eh], 1 ; d1 66 e2 ; 0xc20be vgabios.c:1425 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc20c1 vgabios.c:1428 + jne short 02130h ; 75 69 ; 0xc20c5 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc20c7 vgabios.c:1429 + xor ah, ah ; 30 e4 ; 0xc20ca + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc20cc + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc20cf + xor ah, ah ; 30 e4 ; 0xc20d2 + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc20d4 + jc short 020afh ; 72 d6 ; 0xc20d7 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc20d9 vgabios.c:1431 + xor dh, dh ; 30 f6 ; 0xc20dc + add dx, word [bp-01ch] ; 03 56 e4 ; 0xc20de + cmp dx, ax ; 39 c2 ; 0xc20e1 + jnbe short 020ebh ; 77 06 ; 0xc20e3 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc20e5 + jne short 0210ch ; 75 21 ; 0xc20e9 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc20eb vgabios.c:1432 + xor ah, ah ; 30 e4 ; 0xc20ee + push ax ; 50 ; 0xc20f0 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc20f1 + push ax ; 50 ; 0xc20f4 + mov cl, byte [bp-01eh] ; 8a 4e e2 ; 0xc20f5 + xor ch, ch ; 30 ed ; 0xc20f8 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc20fa + xor bh, bh ; 30 ff ; 0xc20fd + mov dl, byte [bp-01ch] ; 8a 56 e4 ; 0xc20ff + xor dh, dh ; 30 f6 ; 0xc2102 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2104 + call 01ad3h ; e8 c9 f9 ; 0xc2107 + jmp short 0212bh ; eb 1f ; 0xc210a vgabios.c:1433 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc210c vgabios.c:1434 + push ax ; 50 ; 0xc210f + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc2110 + push ax ; 50 ; 0xc2113 + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc2114 + xor ch, ch ; 30 ed ; 0xc2117 + mov bl, byte [bp-01ch] ; 8a 5e e4 ; 0xc2119 + xor bh, bh ; 30 ff ; 0xc211c + mov dl, bl ; 88 da ; 0xc211e + add dl, byte [bp-006h] ; 02 56 fa ; 0xc2120 + xor dh, dh ; 30 f6 ; 0xc2123 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2125 + call 01a1dh ; e8 f2 f8 ; 0xc2128 + inc word [bp-01ch] ; ff 46 e4 ; 0xc212b vgabios.c:1435 + jmp short 020cfh ; eb 9f ; 0xc212e + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc2130 vgabios.c:1438 + xor ah, ah ; 30 e4 ; 0xc2133 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc2135 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2138 + xor ah, ah ; 30 e4 ; 0xc213b + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc213d + jnbe short 021aah ; 77 68 ; 0xc2140 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc2142 vgabios.c:1440 + xor dh, dh ; 30 f6 ; 0xc2145 + add ax, dx ; 01 d0 ; 0xc2147 + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc2149 + jnbe short 02152h ; 77 04 ; 0xc214c + test dl, dl ; 84 d2 ; 0xc214e + jne short 0217ch ; 75 2a ; 0xc2150 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2152 vgabios.c:1441 + xor ah, ah ; 30 e4 ; 0xc2155 + push ax ; 50 ; 0xc2157 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2158 + push ax ; 50 ; 0xc215b + mov cl, byte [bp-01eh] ; 8a 4e e2 ; 0xc215c + xor ch, ch ; 30 ed ; 0xc215f + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc2161 + xor bh, bh ; 30 ff ; 0xc2164 + mov dl, byte [bp-01ch] ; 8a 56 e4 ; 0xc2166 + xor dh, dh ; 30 f6 ; 0xc2169 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc216b + mov byte [bp-018h], al ; 88 46 e8 ; 0xc216e + mov byte [bp-017h], ah ; 88 66 e9 ; 0xc2171 + mov ax, word [bp-018h] ; 8b 46 e8 ; 0xc2174 + call 01ad3h ; e8 59 f9 ; 0xc2177 + jmp short 0219bh ; eb 1f ; 0xc217a vgabios.c:1442 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc217c vgabios.c:1443 + xor ah, ah ; 30 e4 ; 0xc217f + push ax ; 50 ; 0xc2181 + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc2182 + push ax ; 50 ; 0xc2185 + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc2186 + xor ch, ch ; 30 ed ; 0xc2189 + mov bl, byte [bp-01ch] ; 8a 5e e4 ; 0xc218b + xor bh, bh ; 30 ff ; 0xc218e + mov dl, bl ; 88 da ; 0xc2190 + sub dl, byte [bp-006h] ; 2a 56 fa ; 0xc2192 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2195 + call 01a1dh ; e8 82 f8 ; 0xc2198 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc219b vgabios.c:1444 + xor ah, ah ; 30 e4 ; 0xc219e + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc21a0 + jc short 021eah ; 72 45 ; 0xc21a3 + dec word [bp-01ch] ; ff 4e e4 ; 0xc21a5 vgabios.c:1445 + jmp short 02138h ; eb 8e ; 0xc21a8 + jmp short 021eah ; eb 3e ; 0xc21aa + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc21ac vgabios.c:1450 + jne short 021edh ; 75 3b ; 0xc21b0 + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc21b2 + jne short 021edh ; 75 35 ; 0xc21b6 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc21b8 + jne short 021edh ; 75 2f ; 0xc21bc + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc21be + cmp ax, di ; 39 f8 ; 0xc21c1 + jne short 021edh ; 75 28 ; 0xc21c3 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc21c5 + cmp ax, word [bp-022h] ; 3b 46 de ; 0xc21c8 + jne short 021edh ; 75 20 ; 0xc21cb + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc21cd vgabios.c:1452 + xor dh, dh ; 30 f6 ; 0xc21d0 + mov ax, cx ; 89 c8 ; 0xc21d2 + mul dx ; f7 e2 ; 0xc21d4 + mov cx, ax ; 89 c1 ; 0xc21d6 + sal cx, 003h ; c1 e1 03 ; 0xc21d8 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc21db + xor ah, ah ; 30 e4 ; 0xc21de + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc21e0 + xor di, di ; 31 ff ; 0xc21e4 + jcxz 021eah ; e3 02 ; 0xc21e6 + rep stosb ; f3 aa ; 0xc21e8 + jmp near 022d4h ; e9 e7 00 ; 0xc21ea vgabios.c:1454 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc21ed vgabios.c:1457 + jne short 02262h ; 75 6f ; 0xc21f1 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc21f3 vgabios.c:1458 + xor ah, ah ; 30 e4 ; 0xc21f6 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc21f8 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc21fb + xor ah, ah ; 30 e4 ; 0xc21fe + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc2200 + jc short 021eah ; 72 e5 ; 0xc2203 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc2205 vgabios.c:1460 + xor dh, dh ; 30 f6 ; 0xc2208 + add dx, word [bp-01ch] ; 03 56 e4 ; 0xc220a + cmp dx, ax ; 39 c2 ; 0xc220d + jnbe short 02217h ; 77 06 ; 0xc220f + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc2211 + jne short 02236h ; 75 1f ; 0xc2215 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2217 vgabios.c:1461 + xor ah, ah ; 30 e4 ; 0xc221a + push ax ; 50 ; 0xc221c + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc221d + push ax ; 50 ; 0xc2220 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc2221 + xor bh, bh ; 30 ff ; 0xc2224 + mov dl, byte [bp-01ch] ; 8a 56 e4 ; 0xc2226 + xor dh, dh ; 30 f6 ; 0xc2229 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc222b + mov cx, word [bp-01eh] ; 8b 4e e2 ; 0xc222e + call 01be8h ; e8 b4 f9 ; 0xc2231 + jmp short 0225dh ; eb 27 ; 0xc2234 vgabios.c:1462 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2236 vgabios.c:1463 + push ax ; 50 ; 0xc2239 + push word [bp-01eh] ; ff 76 e2 ; 0xc223a + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc223d + xor ch, ch ; 30 ed ; 0xc2240 + mov bl, byte [bp-01ch] ; 8a 5e e4 ; 0xc2242 + xor bh, bh ; 30 ff ; 0xc2245 + mov dl, bl ; 88 da ; 0xc2247 + add dl, byte [bp-006h] ; 02 56 fa ; 0xc2249 + xor dh, dh ; 30 f6 ; 0xc224c + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc224e + mov byte [bp-018h], al ; 88 46 e8 ; 0xc2251 + mov byte [bp-017h], ah ; 88 66 e9 ; 0xc2254 + mov ax, word [bp-018h] ; 8b 46 e8 ; 0xc2257 + call 01b67h ; e8 0a f9 ; 0xc225a + inc word [bp-01ch] ; ff 46 e4 ; 0xc225d vgabios.c:1464 + jmp short 021fbh ; eb 99 ; 0xc2260 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc2262 vgabios.c:1467 + xor ah, ah ; 30 e4 ; 0xc2265 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc2267 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc226a + xor ah, ah ; 30 e4 ; 0xc226d + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc226f + jnbe short 022d4h ; 77 60 ; 0xc2272 + mov dl, al ; 88 c2 ; 0xc2274 vgabios.c:1469 + xor dh, dh ; 30 f6 ; 0xc2276 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2278 + add ax, dx ; 01 d0 ; 0xc227b + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc227d + jnbe short 02288h ; 77 06 ; 0xc2280 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc2282 + jne short 022a7h ; 75 1f ; 0xc2286 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2288 vgabios.c:1470 + xor ah, ah ; 30 e4 ; 0xc228b + push ax ; 50 ; 0xc228d + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc228e + push ax ; 50 ; 0xc2291 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc2292 + xor bh, bh ; 30 ff ; 0xc2295 + mov dl, byte [bp-01ch] ; 8a 56 e4 ; 0xc2297 + xor dh, dh ; 30 f6 ; 0xc229a + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc229c + mov cx, word [bp-01eh] ; 8b 4e e2 ; 0xc229f + call 01be8h ; e8 43 f9 ; 0xc22a2 + jmp short 022c5h ; eb 1e ; 0xc22a5 vgabios.c:1471 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc22a7 vgabios.c:1472 + xor ah, ah ; 30 e4 ; 0xc22aa + push ax ; 50 ; 0xc22ac + push word [bp-01eh] ; ff 76 e2 ; 0xc22ad + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc22b0 + xor ch, ch ; 30 ed ; 0xc22b3 + mov bl, byte [bp-01ch] ; 8a 5e e4 ; 0xc22b5 + xor bh, bh ; 30 ff ; 0xc22b8 + mov dl, bl ; 88 da ; 0xc22ba + sub dl, byte [bp-006h] ; 2a 56 fa ; 0xc22bc + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc22bf + call 01b67h ; e8 a2 f8 ; 0xc22c2 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc22c5 vgabios.c:1473 + xor ah, ah ; 30 e4 ; 0xc22c8 + cmp ax, word [bp-01ch] ; 3b 46 e4 ; 0xc22ca + jc short 022d4h ; 72 05 ; 0xc22cd + dec word [bp-01ch] ; ff 4e e4 ; 0xc22cf vgabios.c:1474 + jmp short 0226ah ; eb 96 ; 0xc22d2 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc22d4 vgabios.c:1485 + pop di ; 5f ; 0xc22d7 + pop si ; 5e ; 0xc22d8 + pop bp ; 5d ; 0xc22d9 + retn 00008h ; c2 08 00 ; 0xc22da + ; disGetNextSymbol 0xc22dd LB 0x2255 -> off=0x0 cb=0000000000000111 uValue=00000000000c22dd 'write_gfx_char_pl4' +write_gfx_char_pl4: ; 0xc22dd LB 0x111 + push bp ; 55 ; 0xc22dd vgabios.c:1488 + mov bp, sp ; 89 e5 ; 0xc22de + push si ; 56 ; 0xc22e0 + push di ; 57 ; 0xc22e1 + sub sp, strict byte 0000eh ; 83 ec 0e ; 0xc22e2 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc22e5 + mov byte [bp-008h], dl ; 88 56 f8 ; 0xc22e8 + mov ch, bl ; 88 dd ; 0xc22eb + mov al, cl ; 88 c8 ; 0xc22ed + mov bx, 0010ch ; bb 0c 01 ; 0xc22ef vgabios.c:67 + xor dx, dx ; 31 d2 ; 0xc22f2 + mov es, dx ; 8e c2 ; 0xc22f4 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc22f6 + mov bx, word [es:bx+002h] ; 26 8b 5f 02 ; 0xc22f9 + mov word [bp-012h], dx ; 89 56 ee ; 0xc22fd vgabios.c:68 + mov word [bp-00ch], bx ; 89 5e f4 ; 0xc2300 + xor ah, ah ; 30 e4 ; 0xc2303 vgabios.c:1497 + mov bl, byte [bp+006h] ; 8a 5e 06 ; 0xc2305 + xor bh, bh ; 30 ff ; 0xc2308 + imul bx ; f7 eb ; 0xc230a + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc230c + xor dh, dh ; 30 f6 ; 0xc230f + imul dx ; f7 ea ; 0xc2311 + mov si, ax ; 89 c6 ; 0xc2313 + mov al, ch ; 88 e8 ; 0xc2315 + xor ah, ah ; 30 e4 ; 0xc2317 + add si, ax ; 01 c6 ; 0xc2319 + mov di, strict word 0004ch ; bf 4c 00 ; 0xc231b vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc231e + mov es, ax ; 8e c0 ; 0xc2321 + mov ax, word [es:di] ; 26 8b 05 ; 0xc2323 + mov dl, byte [bp+008h] ; 8a 56 08 ; 0xc2326 vgabios.c:58 + xor dh, dh ; 30 f6 ; 0xc2329 + mul dx ; f7 e2 ; 0xc232b + add si, ax ; 01 c6 ; 0xc232d + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc232f vgabios.c:1499 + xor ah, ah ; 30 e4 ; 0xc2332 + imul bx ; f7 eb ; 0xc2334 + mov word [bp-010h], ax ; 89 46 f0 ; 0xc2336 + mov ax, 00f02h ; b8 02 0f ; 0xc2339 vgabios.c:1500 + mov dx, 003c4h ; ba c4 03 ; 0xc233c + out DX, ax ; ef ; 0xc233f + mov ax, 00205h ; b8 05 02 ; 0xc2340 vgabios.c:1501 + mov dx, 003ceh ; ba ce 03 ; 0xc2343 + out DX, ax ; ef ; 0xc2346 + test byte [bp-008h], 080h ; f6 46 f8 80 ; 0xc2347 vgabios.c:1502 + je short 02353h ; 74 06 ; 0xc234b + mov ax, 01803h ; b8 03 18 ; 0xc234d vgabios.c:1504 + out DX, ax ; ef ; 0xc2350 + jmp short 02357h ; eb 04 ; 0xc2351 vgabios.c:1506 + mov ax, strict word 00003h ; b8 03 00 ; 0xc2353 vgabios.c:1508 + out DX, ax ; ef ; 0xc2356 + xor ch, ch ; 30 ed ; 0xc2357 vgabios.c:1510 + cmp ch, byte [bp+006h] ; 3a 6e 06 ; 0xc2359 + jnc short 023d0h ; 73 72 ; 0xc235c + mov al, ch ; 88 e8 ; 0xc235e vgabios.c:1512 + xor ah, ah ; 30 e4 ; 0xc2360 + mov bl, byte [bp+004h] ; 8a 5e 04 ; 0xc2362 + xor bh, bh ; 30 ff ; 0xc2365 + imul bx ; f7 eb ; 0xc2367 + mov bx, si ; 89 f3 ; 0xc2369 + add bx, ax ; 01 c3 ; 0xc236b + mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xc236d vgabios.c:1513 + jmp short 02385h ; eb 12 ; 0xc2371 + mov ax, 0a000h ; b8 00 a0 ; 0xc2373 vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc2376 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc2378 + inc byte [bp-006h] ; fe 46 fa ; 0xc237c vgabios.c:1526 + cmp byte [bp-006h], 008h ; 80 7e fa 08 ; 0xc237f + jnc short 023d2h ; 73 4d ; 0xc2383 + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc2385 + mov ax, 00080h ; b8 80 00 ; 0xc2388 + sar ax, CL ; d3 f8 ; 0xc238b + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc238d + mov byte [bp-00dh], 000h ; c6 46 f3 00 ; 0xc2390 + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc2394 + sal ax, 008h ; c1 e0 08 ; 0xc2397 + or AL, strict byte 008h ; 0c 08 ; 0xc239a + mov dx, 003ceh ; ba ce 03 ; 0xc239c + out DX, ax ; ef ; 0xc239f + mov dx, bx ; 89 da ; 0xc23a0 + mov ax, 0a000h ; b8 00 a0 ; 0xc23a2 + call 03841h ; e8 99 14 ; 0xc23a5 + mov al, ch ; 88 e8 ; 0xc23a8 + xor ah, ah ; 30 e4 ; 0xc23aa + add ax, word [bp-010h] ; 03 46 f0 ; 0xc23ac + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc23af + mov di, word [bp-012h] ; 8b 7e ee ; 0xc23b2 + add di, ax ; 01 c7 ; 0xc23b5 + mov al, byte [es:di] ; 26 8a 05 ; 0xc23b7 + xor ah, ah ; 30 e4 ; 0xc23ba + test word [bp-00eh], ax ; 85 46 f2 ; 0xc23bc + je short 02373h ; 74 b2 ; 0xc23bf + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc23c1 + and AL, strict byte 00fh ; 24 0f ; 0xc23c4 + mov dx, 0a000h ; ba 00 a0 ; 0xc23c6 + mov es, dx ; 8e c2 ; 0xc23c9 + mov byte [es:bx], al ; 26 88 07 ; 0xc23cb + jmp short 0237ch ; eb ac ; 0xc23ce + jmp short 023d6h ; eb 04 ; 0xc23d0 + db 0feh, 0c5h + ; inc ch ; fe c5 ; 0xc23d2 vgabios.c:1527 + jmp short 02359h ; eb 83 ; 0xc23d4 + mov ax, 0ff08h ; b8 08 ff ; 0xc23d6 vgabios.c:1528 + mov dx, 003ceh ; ba ce 03 ; 0xc23d9 + out DX, ax ; ef ; 0xc23dc + mov ax, strict word 00005h ; b8 05 00 ; 0xc23dd vgabios.c:1529 + out DX, ax ; ef ; 0xc23e0 + mov ax, strict word 00003h ; b8 03 00 ; 0xc23e1 vgabios.c:1530 + out DX, ax ; ef ; 0xc23e4 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc23e5 vgabios.c:1531 + pop di ; 5f ; 0xc23e8 + pop si ; 5e ; 0xc23e9 + pop bp ; 5d ; 0xc23ea + retn 00006h ; c2 06 00 ; 0xc23eb + ; disGetNextSymbol 0xc23ee LB 0x2144 -> off=0x0 cb=0000000000000112 uValue=00000000000c23ee 'write_gfx_char_cga' +write_gfx_char_cga: ; 0xc23ee LB 0x112 + push si ; 56 ; 0xc23ee vgabios.c:1534 + push di ; 57 ; 0xc23ef + enter 0000ch, 000h ; c8 0c 00 00 ; 0xc23f0 + mov bh, al ; 88 c7 ; 0xc23f4 + mov ch, dl ; 88 d5 ; 0xc23f6 + mov al, bl ; 88 d8 ; 0xc23f8 + mov di, 0556dh ; bf 6d 55 ; 0xc23fa vgabios.c:1541 + xor ah, ah ; 30 e4 ; 0xc23fd vgabios.c:1542 + mov dl, byte [bp+00ah] ; 8a 56 0a ; 0xc23ff + xor dh, dh ; 30 f6 ; 0xc2402 + imul dx ; f7 ea ; 0xc2404 + mov dl, cl ; 88 ca ; 0xc2406 + xor dh, dh ; 30 f6 ; 0xc2408 + imul dx, dx, 00140h ; 69 d2 40 01 ; 0xc240a + add ax, dx ; 01 d0 ; 0xc240e + mov word [bp-008h], ax ; 89 46 f8 ; 0xc2410 + mov al, bh ; 88 f8 ; 0xc2413 vgabios.c:1543 + xor ah, ah ; 30 e4 ; 0xc2415 + sal ax, 003h ; c1 e0 03 ; 0xc2417 + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc241a + xor ah, ah ; 30 e4 ; 0xc241d vgabios.c:1544 + jmp near 0243eh ; e9 1c 00 ; 0xc241f + mov dl, ah ; 88 e2 ; 0xc2422 vgabios.c:1559 + xor dh, dh ; 30 f6 ; 0xc2424 + add dx, word [bp-00ch] ; 03 56 f4 ; 0xc2426 + mov si, di ; 89 fe ; 0xc2429 + add si, dx ; 01 d6 ; 0xc242b + mov al, byte [si] ; 8a 04 ; 0xc242d + mov dx, 0b800h ; ba 00 b8 ; 0xc242f vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc2432 + mov byte [es:bx], al ; 26 88 07 ; 0xc2434 + db 0feh, 0c4h + ; inc ah ; fe c4 ; 0xc2437 vgabios.c:1563 + cmp ah, 008h ; 80 fc 08 ; 0xc2439 + jnc short 02495h ; 73 57 ; 0xc243c + mov dl, ah ; 88 e2 ; 0xc243e + xor dh, dh ; 30 f6 ; 0xc2440 + sar dx, 1 ; d1 fa ; 0xc2442 + imul dx, dx, strict byte 00050h ; 6b d2 50 ; 0xc2444 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc2447 + add bx, dx ; 01 d3 ; 0xc244a + test ah, 001h ; f6 c4 01 ; 0xc244c + je short 02454h ; 74 03 ; 0xc244f + add bh, 020h ; 80 c7 20 ; 0xc2451 + mov byte [bp-002h], 080h ; c6 46 fe 80 ; 0xc2454 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc2458 + jne short 0247ah ; 75 1c ; 0xc245c + test ch, 080h ; f6 c5 80 ; 0xc245e + je short 02422h ; 74 bf ; 0xc2461 + mov dx, 0b800h ; ba 00 b8 ; 0xc2463 + mov es, dx ; 8e c2 ; 0xc2466 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2468 + mov dl, ah ; 88 e2 ; 0xc246b + xor dh, dh ; 30 f6 ; 0xc246d + add dx, word [bp-00ch] ; 03 56 f4 ; 0xc246f + mov si, di ; 89 fe ; 0xc2472 + add si, dx ; 01 d6 ; 0xc2474 + xor al, byte [si] ; 32 04 ; 0xc2476 + jmp short 0242fh ; eb b5 ; 0xc2478 + cmp byte [bp-002h], 000h ; 80 7e fe 00 ; 0xc247a vgabios.c:1565 + jbe short 02437h ; 76 b7 ; 0xc247e + test ch, 080h ; f6 c5 80 ; 0xc2480 vgabios.c:1567 + je short 0248fh ; 74 0a ; 0xc2483 + mov dx, 0b800h ; ba 00 b8 ; 0xc2485 vgabios.c:47 + mov es, dx ; 8e c2 ; 0xc2488 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc248a + jmp short 02491h ; eb 02 ; 0xc248d vgabios.c:1571 + xor al, al ; 30 c0 ; 0xc248f vgabios.c:1573 + xor dl, dl ; 30 d2 ; 0xc2491 vgabios.c:1575 + jmp short 0249ch ; eb 07 ; 0xc2493 + jmp short 024fah ; eb 63 ; 0xc2495 + cmp dl, 004h ; 80 fa 04 ; 0xc2497 + jnc short 024efh ; 73 53 ; 0xc249a + mov byte [bp-006h], ah ; 88 66 fa ; 0xc249c vgabios.c:1577 + mov byte [bp-005h], 000h ; c6 46 fb 00 ; 0xc249f + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc24a3 + add si, word [bp-006h] ; 03 76 fa ; 0xc24a6 + add si, di ; 01 fe ; 0xc24a9 + mov dh, byte [si] ; 8a 34 ; 0xc24ab + mov byte [bp-006h], dh ; 88 76 fa ; 0xc24ad + mov byte [bp-005h], 000h ; c6 46 fb 00 ; 0xc24b0 + mov dh, byte [bp-002h] ; 8a 76 fe ; 0xc24b4 + mov byte [bp-00ah], dh ; 88 76 f6 ; 0xc24b7 + mov byte [bp-009h], 000h ; c6 46 f7 00 ; 0xc24ba + mov si, word [bp-006h] ; 8b 76 fa ; 0xc24be + test word [bp-00ah], si ; 85 76 f6 ; 0xc24c1 + je short 024e8h ; 74 22 ; 0xc24c4 + mov DH, strict byte 003h ; b6 03 ; 0xc24c6 vgabios.c:1578 + sub dh, dl ; 28 d6 ; 0xc24c8 + mov cl, ch ; 88 e9 ; 0xc24ca + and cl, 003h ; 80 e1 03 ; 0xc24cc + mov byte [bp-004h], cl ; 88 4e fc ; 0xc24cf + mov cl, dh ; 88 f1 ; 0xc24d2 + add cl, dh ; 00 f1 ; 0xc24d4 + mov dh, byte [bp-004h] ; 8a 76 fc ; 0xc24d6 + sal dh, CL ; d2 e6 ; 0xc24d9 + mov cl, dh ; 88 f1 ; 0xc24db + test ch, 080h ; f6 c5 80 ; 0xc24dd vgabios.c:1579 + je short 024e6h ; 74 04 ; 0xc24e0 + xor al, dh ; 30 f0 ; 0xc24e2 vgabios.c:1581 + jmp short 024e8h ; eb 02 ; 0xc24e4 vgabios.c:1583 + or al, dh ; 08 f0 ; 0xc24e6 vgabios.c:1585 + shr byte [bp-002h], 1 ; d0 6e fe ; 0xc24e8 vgabios.c:1588 + db 0feh, 0c2h + ; inc dl ; fe c2 ; 0xc24eb vgabios.c:1589 + jmp short 02497h ; eb a8 ; 0xc24ed + mov dx, 0b800h ; ba 00 b8 ; 0xc24ef vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc24f2 + mov byte [es:bx], al ; 26 88 07 ; 0xc24f4 + inc bx ; 43 ; 0xc24f7 vgabios.c:1591 + jmp short 0247ah ; eb 80 ; 0xc24f8 vgabios.c:1592 + leave ; c9 ; 0xc24fa vgabios.c:1595 + pop di ; 5f ; 0xc24fb + pop si ; 5e ; 0xc24fc + retn 00004h ; c2 04 00 ; 0xc24fd + ; disGetNextSymbol 0xc2500 LB 0x2032 -> off=0x0 cb=000000000000009b uValue=00000000000c2500 'write_gfx_char_lin' +write_gfx_char_lin: ; 0xc2500 LB 0x9b + push si ; 56 ; 0xc2500 vgabios.c:1598 + push di ; 57 ; 0xc2501 + enter 00008h, 000h ; c8 08 00 00 ; 0xc2502 + mov bh, al ; 88 c7 ; 0xc2506 + mov ch, dl ; 88 d5 ; 0xc2508 + mov al, cl ; 88 c8 ; 0xc250a + mov di, 0556dh ; bf 6d 55 ; 0xc250c vgabios.c:1605 + xor ah, ah ; 30 e4 ; 0xc250f vgabios.c:1606 + mov dl, byte [bp+008h] ; 8a 56 08 ; 0xc2511 + xor dh, dh ; 30 f6 ; 0xc2514 + imul dx ; f7 ea ; 0xc2516 + mov dx, ax ; 89 c2 ; 0xc2518 + sal dx, 006h ; c1 e2 06 ; 0xc251a + mov al, bl ; 88 d8 ; 0xc251d + xor ah, ah ; 30 e4 ; 0xc251f + sal ax, 003h ; c1 e0 03 ; 0xc2521 + add ax, dx ; 01 d0 ; 0xc2524 + mov word [bp-002h], ax ; 89 46 fe ; 0xc2526 + mov al, bh ; 88 f8 ; 0xc2529 vgabios.c:1607 + xor ah, ah ; 30 e4 ; 0xc252b + sal ax, 003h ; c1 e0 03 ; 0xc252d + mov word [bp-006h], ax ; 89 46 fa ; 0xc2530 + xor bl, bl ; 30 db ; 0xc2533 vgabios.c:1608 + jmp short 02579h ; eb 42 ; 0xc2535 + cmp AL, strict byte 008h ; 3c 08 ; 0xc2537 vgabios.c:1612 + jnc short 02572h ; 73 37 ; 0xc2539 + xor bh, bh ; 30 ff ; 0xc253b vgabios.c:1614 + mov dl, bl ; 88 da ; 0xc253d vgabios.c:1615 + xor dh, dh ; 30 f6 ; 0xc253f + add dx, word [bp-006h] ; 03 56 fa ; 0xc2541 + mov si, di ; 89 fe ; 0xc2544 + add si, dx ; 01 d6 ; 0xc2546 + mov dl, byte [si] ; 8a 14 ; 0xc2548 + mov byte [bp-004h], dl ; 88 56 fc ; 0xc254a + mov byte [bp-003h], bh ; 88 7e fd ; 0xc254d + mov dl, ah ; 88 e2 ; 0xc2550 + xor dh, dh ; 30 f6 ; 0xc2552 + test word [bp-004h], dx ; 85 56 fc ; 0xc2554 + je short 0255bh ; 74 02 ; 0xc2557 + mov bh, ch ; 88 ef ; 0xc2559 vgabios.c:1617 + mov dl, al ; 88 c2 ; 0xc255b vgabios.c:1619 + xor dh, dh ; 30 f6 ; 0xc255d + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc255f + add si, dx ; 01 d6 ; 0xc2562 + mov dx, 0a000h ; ba 00 a0 ; 0xc2564 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc2567 + mov byte [es:si], bh ; 26 88 3c ; 0xc2569 + shr ah, 1 ; d0 ec ; 0xc256c vgabios.c:1620 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc256e vgabios.c:1621 + jmp short 02537h ; eb c5 ; 0xc2570 + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc2572 vgabios.c:1622 + cmp bl, 008h ; 80 fb 08 ; 0xc2574 + jnc short 02595h ; 73 1c ; 0xc2577 + mov al, bl ; 88 d8 ; 0xc2579 + xor ah, ah ; 30 e4 ; 0xc257b + mov dl, byte [bp+008h] ; 8a 56 08 ; 0xc257d + xor dh, dh ; 30 f6 ; 0xc2580 + imul dx ; f7 ea ; 0xc2582 + sal ax, 003h ; c1 e0 03 ; 0xc2584 + mov dx, word [bp-002h] ; 8b 56 fe ; 0xc2587 + add dx, ax ; 01 c2 ; 0xc258a + mov word [bp-008h], dx ; 89 56 f8 ; 0xc258c + mov AH, strict byte 080h ; b4 80 ; 0xc258f + xor al, al ; 30 c0 ; 0xc2591 + jmp short 0253bh ; eb a6 ; 0xc2593 + leave ; c9 ; 0xc2595 vgabios.c:1623 + pop di ; 5f ; 0xc2596 + pop si ; 5e ; 0xc2597 + retn 00002h ; c2 02 00 ; 0xc2598 + ; disGetNextSymbol 0xc259b LB 0x1f97 -> off=0x0 cb=0000000000000187 uValue=00000000000c259b 'biosfn_write_char_attr' +biosfn_write_char_attr: ; 0xc259b LB 0x187 + push bp ; 55 ; 0xc259b vgabios.c:1626 + mov bp, sp ; 89 e5 ; 0xc259c + push si ; 56 ; 0xc259e + push di ; 57 ; 0xc259f + sub sp, strict byte 0001ch ; 83 ec 1c ; 0xc25a0 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc25a3 + mov byte [bp-00eh], dl ; 88 56 f2 ; 0xc25a6 + mov byte [bp-006h], bl ; 88 5e fa ; 0xc25a9 + mov si, cx ; 89 ce ; 0xc25ac + mov bx, strict word 00049h ; bb 49 00 ; 0xc25ae vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc25b1 + mov es, ax ; 8e c0 ; 0xc25b4 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc25b6 + xor ah, ah ; 30 e4 ; 0xc25b9 vgabios.c:1634 + call 03819h ; e8 5b 12 ; 0xc25bb + mov cl, al ; 88 c1 ; 0xc25be + mov byte [bp-010h], al ; 88 46 f0 ; 0xc25c0 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc25c3 vgabios.c:1635 + jne short 025cah ; 75 03 ; 0xc25c5 + jmp near 0271bh ; e9 51 01 ; 0xc25c7 + mov al, dl ; 88 d0 ; 0xc25ca vgabios.c:1638 + xor ah, ah ; 30 e4 ; 0xc25cc + lea bx, [bp-01eh] ; 8d 5e e2 ; 0xc25ce + lea dx, [bp-020h] ; 8d 56 e0 ; 0xc25d1 + call 00a96h ; e8 bf e4 ; 0xc25d4 + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc25d7 vgabios.c:1639 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc25da + mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xc25dd + xor al, al ; 30 c0 ; 0xc25e0 + shr ax, 008h ; c1 e8 08 ; 0xc25e2 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc25e5 + mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xc25e8 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc25eb + mov bx, 00084h ; bb 84 00 ; 0xc25ee vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc25f1 + mov es, ax ; 8e c0 ; 0xc25f4 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc25f6 + xor ah, ah ; 30 e4 ; 0xc25f9 vgabios.c:48 + mov dx, ax ; 89 c2 ; 0xc25fb + inc dx ; 42 ; 0xc25fd + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc25fe vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc2601 + mov word [bp-018h], ax ; 89 46 e8 ; 0xc2604 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc2607 vgabios.c:58 + mov bl, cl ; 88 cb ; 0xc260a vgabios.c:1645 + xor bh, bh ; 30 ff ; 0xc260c + mov di, bx ; 89 df ; 0xc260e + sal di, 003h ; c1 e7 03 ; 0xc2610 + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc2613 + jne short 02663h ; 75 49 ; 0xc2618 + mul dx ; f7 e2 ; 0xc261a vgabios.c:1648 + add ax, ax ; 01 c0 ; 0xc261c + or AL, strict byte 0ffh ; 0c ff ; 0xc261e + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc2620 + xor dh, dh ; 30 f6 ; 0xc2623 + inc ax ; 40 ; 0xc2625 + mul dx ; f7 e2 ; 0xc2626 + mov bx, ax ; 89 c3 ; 0xc2628 + mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xc262a + xor ah, ah ; 30 e4 ; 0xc262d + mul word [bp-018h] ; f7 66 e8 ; 0xc262f + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc2632 + xor dh, dh ; 30 f6 ; 0xc2635 + add ax, dx ; 01 d0 ; 0xc2637 + add ax, ax ; 01 c0 ; 0xc2639 + mov dx, bx ; 89 da ; 0xc263b + add dx, ax ; 01 c2 ; 0xc263d + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc263f vgabios.c:1650 + xor ah, ah ; 30 e4 ; 0xc2642 + mov bx, ax ; 89 c3 ; 0xc2644 + sal bx, 008h ; c1 e3 08 ; 0xc2646 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2649 + add bx, ax ; 01 c3 ; 0xc264c + mov word [bp-020h], bx ; 89 5e e0 ; 0xc264e + mov ax, word [bp-020h] ; 8b 46 e0 ; 0xc2651 vgabios.c:1651 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc2654 + mov cx, si ; 89 f1 ; 0xc2658 + mov di, dx ; 89 d7 ; 0xc265a + jcxz 02660h ; e3 02 ; 0xc265c + rep stosw ; f3 ab ; 0xc265e + jmp near 0271bh ; e9 b8 00 ; 0xc2660 vgabios.c:1653 + mov bl, byte [bx+0482fh] ; 8a 9f 2f 48 ; 0xc2663 vgabios.c:1656 + sal bx, 006h ; c1 e3 06 ; 0xc2667 + mov al, byte [bx+04845h] ; 8a 87 45 48 ; 0xc266a + mov byte [bp-012h], al ; 88 46 ee ; 0xc266e + mov al, byte [di+047b2h] ; 8a 85 b2 47 ; 0xc2671 vgabios.c:1657 + mov byte [bp-014h], al ; 88 46 ec ; 0xc2675 + dec si ; 4e ; 0xc2678 vgabios.c:1658 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc2679 + je short 026ceh ; 74 50 ; 0xc267c + mov bl, byte [bp-010h] ; 8a 5e f0 ; 0xc267e vgabios.c:1660 + xor bh, bh ; 30 ff ; 0xc2681 + sal bx, 003h ; c1 e3 03 ; 0xc2683 + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc2686 + cmp bl, 003h ; 80 fb 03 ; 0xc268a + jc short 0269eh ; 72 0f ; 0xc268d + jbe short 026a5h ; 76 14 ; 0xc268f + cmp bl, 005h ; 80 fb 05 ; 0xc2691 + je short 026fah ; 74 64 ; 0xc2694 + cmp bl, 004h ; 80 fb 04 ; 0xc2696 + je short 026a9h ; 74 0e ; 0xc2699 + jmp near 02715h ; e9 77 00 ; 0xc269b + cmp bl, 002h ; 80 fb 02 ; 0xc269e + je short 026d0h ; 74 2d ; 0xc26a1 + jmp short 02715h ; eb 70 ; 0xc26a3 + or byte [bp-006h], 001h ; 80 4e fa 01 ; 0xc26a5 vgabios.c:1663 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc26a9 vgabios.c:1665 + xor ah, ah ; 30 e4 ; 0xc26ac + push ax ; 50 ; 0xc26ae + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc26af + push ax ; 50 ; 0xc26b2 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc26b3 + push ax ; 50 ; 0xc26b6 + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc26b7 + xor ch, ch ; 30 ed ; 0xc26ba + mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xc26bc + xor bh, bh ; 30 ff ; 0xc26bf + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc26c1 + xor dh, dh ; 30 f6 ; 0xc26c4 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc26c6 + call 022ddh ; e8 11 fc ; 0xc26c9 + jmp short 02715h ; eb 47 ; 0xc26cc vgabios.c:1666 + jmp short 0271bh ; eb 4b ; 0xc26ce + mov al, byte [bp-014h] ; 8a 46 ec ; 0xc26d0 vgabios.c:1668 + xor ah, ah ; 30 e4 ; 0xc26d3 + push ax ; 50 ; 0xc26d5 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc26d6 + push ax ; 50 ; 0xc26d9 + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc26da + xor ch, ch ; 30 ed ; 0xc26dd + mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xc26df + xor bh, bh ; 30 ff ; 0xc26e2 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc26e4 + xor dh, dh ; 30 f6 ; 0xc26e7 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc26e9 + mov byte [bp-016h], al ; 88 46 ea ; 0xc26ec + mov byte [bp-015h], ah ; 88 66 eb ; 0xc26ef + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc26f2 + call 023eeh ; e8 f6 fc ; 0xc26f5 + jmp short 02715h ; eb 1b ; 0xc26f8 vgabios.c:1669 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc26fa vgabios.c:1671 + xor ah, ah ; 30 e4 ; 0xc26fd + push ax ; 50 ; 0xc26ff + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc2700 + xor ch, ch ; 30 ed ; 0xc2703 + mov bl, byte [bp-008h] ; 8a 5e f8 ; 0xc2705 + xor bh, bh ; 30 ff ; 0xc2708 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc270a + xor dh, dh ; 30 f6 ; 0xc270d + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc270f + call 02500h ; e8 eb fd ; 0xc2712 + inc byte [bp-008h] ; fe 46 f8 ; 0xc2715 vgabios.c:1678 + jmp near 02678h ; e9 5d ff ; 0xc2718 vgabios.c:1679 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc271b vgabios.c:1681 + pop di ; 5f ; 0xc271e + pop si ; 5e ; 0xc271f + pop bp ; 5d ; 0xc2720 + retn ; c3 ; 0xc2721 + ; disGetNextSymbol 0xc2722 LB 0x1e10 -> off=0x0 cb=0000000000000181 uValue=00000000000c2722 'biosfn_write_char_only' +biosfn_write_char_only: ; 0xc2722 LB 0x181 + push bp ; 55 ; 0xc2722 vgabios.c:1684 + mov bp, sp ; 89 e5 ; 0xc2723 + push si ; 56 ; 0xc2725 + push di ; 57 ; 0xc2726 + sub sp, strict byte 0001ch ; 83 ec 1c ; 0xc2727 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc272a + mov byte [bp-00eh], dl ; 88 56 f2 ; 0xc272d + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc2730 + mov si, cx ; 89 ce ; 0xc2733 + mov bx, strict word 00049h ; bb 49 00 ; 0xc2735 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2738 + mov es, ax ; 8e c0 ; 0xc273b + mov al, byte [es:bx] ; 26 8a 07 ; 0xc273d + xor ah, ah ; 30 e4 ; 0xc2740 vgabios.c:1692 + call 03819h ; e8 d4 10 ; 0xc2742 + mov byte [bp-010h], al ; 88 46 f0 ; 0xc2745 + mov byte [bp-012h], al ; 88 46 ee ; 0xc2748 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc274b vgabios.c:1693 + jne short 02752h ; 75 03 ; 0xc274d + jmp near 0289ch ; e9 4a 01 ; 0xc274f + mov al, dl ; 88 d0 ; 0xc2752 vgabios.c:1696 + xor ah, ah ; 30 e4 ; 0xc2754 + lea bx, [bp-01eh] ; 8d 5e e2 ; 0xc2756 + lea dx, [bp-020h] ; 8d 56 e0 ; 0xc2759 + call 00a96h ; e8 37 e3 ; 0xc275c + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc275f vgabios.c:1697 + mov byte [bp-006h], al ; 88 46 fa ; 0xc2762 + mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xc2765 + xor al, al ; 30 c0 ; 0xc2768 + shr ax, 008h ; c1 e8 08 ; 0xc276a + mov word [bp-018h], ax ; 89 46 e8 ; 0xc276d + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc2770 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc2773 + mov bx, 00084h ; bb 84 00 ; 0xc2776 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2779 + mov es, ax ; 8e c0 ; 0xc277c + mov al, byte [es:bx] ; 26 8a 07 ; 0xc277e + xor ah, ah ; 30 e4 ; 0xc2781 vgabios.c:48 + mov dx, ax ; 89 c2 ; 0xc2783 + inc dx ; 42 ; 0xc2785 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2786 vgabios.c:57 + mov cx, word [es:bx] ; 26 8b 0f ; 0xc2789 + mov word [bp-01ch], cx ; 89 4e e4 ; 0xc278c vgabios.c:58 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc278f vgabios.c:1703 + mov bx, ax ; 89 c3 ; 0xc2792 + sal bx, 003h ; c1 e3 03 ; 0xc2794 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc2797 + jne short 027e0h ; 75 42 ; 0xc279c + mov ax, cx ; 89 c8 ; 0xc279e vgabios.c:1706 + mul dx ; f7 e2 ; 0xc27a0 + add ax, ax ; 01 c0 ; 0xc27a2 + or AL, strict byte 0ffh ; 0c ff ; 0xc27a4 + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc27a6 + xor dh, dh ; 30 f6 ; 0xc27a9 + inc ax ; 40 ; 0xc27ab + mul dx ; f7 e2 ; 0xc27ac + mov bx, ax ; 89 c3 ; 0xc27ae + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc27b0 + xor ah, ah ; 30 e4 ; 0xc27b3 + mul cx ; f7 e1 ; 0xc27b5 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc27b7 + xor dh, dh ; 30 f6 ; 0xc27ba + add ax, dx ; 01 d0 ; 0xc27bc + add ax, ax ; 01 c0 ; 0xc27be + add bx, ax ; 01 c3 ; 0xc27c0 + dec si ; 4e ; 0xc27c2 vgabios.c:1708 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc27c3 + je short 0274fh ; 74 87 ; 0xc27c6 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc27c8 vgabios.c:1709 + xor ah, ah ; 30 e4 ; 0xc27cb + mov di, ax ; 89 c7 ; 0xc27cd + sal di, 003h ; c1 e7 03 ; 0xc27cf + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc27d2 vgabios.c:50 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc27d6 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc27d9 + inc bx ; 43 ; 0xc27dc vgabios.c:1710 + inc bx ; 43 ; 0xc27dd + jmp short 027c2h ; eb e2 ; 0xc27de vgabios.c:1711 + mov di, ax ; 89 c7 ; 0xc27e0 vgabios.c:1716 + mov al, byte [di+0482fh] ; 8a 85 2f 48 ; 0xc27e2 + mov di, ax ; 89 c7 ; 0xc27e6 + sal di, 006h ; c1 e7 06 ; 0xc27e8 + mov al, byte [di+04845h] ; 8a 85 45 48 ; 0xc27eb + mov byte [bp-014h], al ; 88 46 ec ; 0xc27ef + mov al, byte [bx+047b2h] ; 8a 87 b2 47 ; 0xc27f2 vgabios.c:1717 + mov byte [bp-016h], al ; 88 46 ea ; 0xc27f6 + dec si ; 4e ; 0xc27f9 vgabios.c:1718 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc27fa + je short 0284fh ; 74 50 ; 0xc27fd + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc27ff vgabios.c:1720 + xor bh, bh ; 30 ff ; 0xc2802 + sal bx, 003h ; c1 e3 03 ; 0xc2804 + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc2807 + cmp bl, 003h ; 80 fb 03 ; 0xc280b + jc short 0281fh ; 72 0f ; 0xc280e + jbe short 02826h ; 76 14 ; 0xc2810 + cmp bl, 005h ; 80 fb 05 ; 0xc2812 + je short 0287bh ; 74 64 ; 0xc2815 + cmp bl, 004h ; 80 fb 04 ; 0xc2817 + je short 0282ah ; 74 0e ; 0xc281a + jmp near 02896h ; e9 77 00 ; 0xc281c + cmp bl, 002h ; 80 fb 02 ; 0xc281f + je short 02851h ; 74 2d ; 0xc2822 + jmp short 02896h ; eb 70 ; 0xc2824 + or byte [bp-008h], 001h ; 80 4e f8 01 ; 0xc2826 vgabios.c:1723 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc282a vgabios.c:1725 + xor ah, ah ; 30 e4 ; 0xc282d + push ax ; 50 ; 0xc282f + mov al, byte [bp-014h] ; 8a 46 ec ; 0xc2830 + push ax ; 50 ; 0xc2833 + mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xc2834 + push ax ; 50 ; 0xc2837 + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc2838 + xor ch, ch ; 30 ed ; 0xc283b + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc283d + xor bh, bh ; 30 ff ; 0xc2840 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc2842 + xor dh, dh ; 30 f6 ; 0xc2845 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2847 + call 022ddh ; e8 90 fa ; 0xc284a + jmp short 02896h ; eb 47 ; 0xc284d vgabios.c:1726 + jmp short 0289ch ; eb 4b ; 0xc284f + mov al, byte [bp-016h] ; 8a 46 ea ; 0xc2851 vgabios.c:1728 + xor ah, ah ; 30 e4 ; 0xc2854 + push ax ; 50 ; 0xc2856 + mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xc2857 + push ax ; 50 ; 0xc285a + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc285b + xor ch, ch ; 30 ed ; 0xc285e + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc2860 + xor bh, bh ; 30 ff ; 0xc2863 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc2865 + xor dh, dh ; 30 f6 ; 0xc2868 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc286a + mov byte [bp-01ah], al ; 88 46 e6 ; 0xc286d + mov byte [bp-019h], ah ; 88 66 e7 ; 0xc2870 + mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xc2873 + call 023eeh ; e8 75 fb ; 0xc2876 + jmp short 02896h ; eb 1b ; 0xc2879 vgabios.c:1729 + mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xc287b vgabios.c:1731 + xor ah, ah ; 30 e4 ; 0xc287e + push ax ; 50 ; 0xc2880 + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc2881 + xor ch, ch ; 30 ed ; 0xc2884 + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc2886 + xor bh, bh ; 30 ff ; 0xc2889 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc288b + xor dh, dh ; 30 f6 ; 0xc288e + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2890 + call 02500h ; e8 6a fc ; 0xc2893 + inc byte [bp-006h] ; fe 46 fa ; 0xc2896 vgabios.c:1738 + jmp near 027f9h ; e9 5d ff ; 0xc2899 vgabios.c:1739 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc289c vgabios.c:1741 + pop di ; 5f ; 0xc289f + pop si ; 5e ; 0xc28a0 + pop bp ; 5d ; 0xc28a1 + retn ; c3 ; 0xc28a2 + ; disGetNextSymbol 0xc28a3 LB 0x1c8f -> off=0x0 cb=0000000000000173 uValue=00000000000c28a3 'biosfn_write_pixel' +biosfn_write_pixel: ; 0xc28a3 LB 0x173 + push bp ; 55 ; 0xc28a3 vgabios.c:1744 + mov bp, sp ; 89 e5 ; 0xc28a4 + push si ; 56 ; 0xc28a6 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc28a7 + mov byte [bp-006h], al ; 88 46 fa ; 0xc28aa + mov byte [bp-004h], dl ; 88 56 fc ; 0xc28ad + mov word [bp-008h], bx ; 89 5e f8 ; 0xc28b0 + mov dx, cx ; 89 ca ; 0xc28b3 + mov bx, strict word 00049h ; bb 49 00 ; 0xc28b5 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc28b8 + mov es, ax ; 8e c0 ; 0xc28bb + mov al, byte [es:bx] ; 26 8a 07 ; 0xc28bd + xor ah, ah ; 30 e4 ; 0xc28c0 vgabios.c:1751 + call 03819h ; e8 54 0f ; 0xc28c2 + mov cl, al ; 88 c1 ; 0xc28c5 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc28c7 vgabios.c:1752 + je short 028f1h ; 74 26 ; 0xc28c9 + mov bl, al ; 88 c3 ; 0xc28cb vgabios.c:1753 + xor bh, bh ; 30 ff ; 0xc28cd + sal bx, 003h ; c1 e3 03 ; 0xc28cf + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc28d2 + je short 028f1h ; 74 18 ; 0xc28d7 + mov al, byte [bx+047b1h] ; 8a 87 b1 47 ; 0xc28d9 vgabios.c:1755 + cmp AL, strict byte 003h ; 3c 03 ; 0xc28dd + jc short 028edh ; 72 0c ; 0xc28df + jbe short 028f7h ; 76 14 ; 0xc28e1 + cmp AL, strict byte 005h ; 3c 05 ; 0xc28e3 + je short 028f4h ; 74 0d ; 0xc28e5 + cmp AL, strict byte 004h ; 3c 04 ; 0xc28e7 + je short 028f7h ; 74 0c ; 0xc28e9 + jmp short 028f1h ; eb 04 ; 0xc28eb + cmp AL, strict byte 002h ; 3c 02 ; 0xc28ed + je short 02968h ; 74 77 ; 0xc28ef + jmp near 02a10h ; e9 1c 01 ; 0xc28f1 + jmp near 029eeh ; e9 f7 00 ; 0xc28f4 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc28f7 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc28fa + mov es, ax ; 8e c0 ; 0xc28fd + mov bx, word [es:bx] ; 26 8b 1f ; 0xc28ff + mov ax, dx ; 89 d0 ; 0xc2902 vgabios.c:58 + mul bx ; f7 e3 ; 0xc2904 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc2906 + shr bx, 003h ; c1 eb 03 ; 0xc2909 + add bx, ax ; 01 c3 ; 0xc290c + mov si, strict word 0004ch ; be 4c 00 ; 0xc290e vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc2911 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc2914 vgabios.c:58 + xor dh, dh ; 30 f6 ; 0xc2917 + mul dx ; f7 e2 ; 0xc2919 + add bx, ax ; 01 c3 ; 0xc291b + mov cx, word [bp-008h] ; 8b 4e f8 ; 0xc291d vgabios.c:1761 + and cl, 007h ; 80 e1 07 ; 0xc2920 + mov ax, 00080h ; b8 80 00 ; 0xc2923 + sar ax, CL ; d3 f8 ; 0xc2926 + xor ah, ah ; 30 e4 ; 0xc2928 vgabios.c:1762 + sal ax, 008h ; c1 e0 08 ; 0xc292a + or AL, strict byte 008h ; 0c 08 ; 0xc292d + mov dx, 003ceh ; ba ce 03 ; 0xc292f + out DX, ax ; ef ; 0xc2932 + mov ax, 00205h ; b8 05 02 ; 0xc2933 vgabios.c:1763 + out DX, ax ; ef ; 0xc2936 + mov dx, bx ; 89 da ; 0xc2937 vgabios.c:1764 + mov ax, 0a000h ; b8 00 a0 ; 0xc2939 + call 03841h ; e8 02 0f ; 0xc293c + test byte [bp-004h], 080h ; f6 46 fc 80 ; 0xc293f vgabios.c:1765 + je short 0294ch ; 74 07 ; 0xc2943 + mov ax, 01803h ; b8 03 18 ; 0xc2945 vgabios.c:1767 + mov dx, 003ceh ; ba ce 03 ; 0xc2948 + out DX, ax ; ef ; 0xc294b + mov ax, 0a000h ; b8 00 a0 ; 0xc294c vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc294f + mov al, byte [bp-004h] ; 8a 46 fc ; 0xc2951 + mov byte [es:bx], al ; 26 88 07 ; 0xc2954 + mov ax, 0ff08h ; b8 08 ff ; 0xc2957 vgabios.c:1770 + mov dx, 003ceh ; ba ce 03 ; 0xc295a + out DX, ax ; ef ; 0xc295d + mov ax, strict word 00005h ; b8 05 00 ; 0xc295e vgabios.c:1771 + out DX, ax ; ef ; 0xc2961 + mov ax, strict word 00003h ; b8 03 00 ; 0xc2962 vgabios.c:1772 + out DX, ax ; ef ; 0xc2965 + jmp short 028f1h ; eb 89 ; 0xc2966 vgabios.c:1773 + mov ax, dx ; 89 d0 ; 0xc2968 vgabios.c:1775 + shr ax, 1 ; d1 e8 ; 0xc296a + imul ax, ax, strict byte 00050h ; 6b c0 50 ; 0xc296c + cmp byte [bx+047b2h], 002h ; 80 bf b2 47 02 ; 0xc296f + jne short 0297eh ; 75 08 ; 0xc2974 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc2976 vgabios.c:1777 + shr bx, 002h ; c1 eb 02 ; 0xc2979 + jmp short 02984h ; eb 06 ; 0xc297c vgabios.c:1779 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc297e vgabios.c:1781 + shr bx, 003h ; c1 eb 03 ; 0xc2981 + add bx, ax ; 01 c3 ; 0xc2984 + test dl, 001h ; f6 c2 01 ; 0xc2986 vgabios.c:1783 + je short 0298eh ; 74 03 ; 0xc2989 + add bh, 020h ; 80 c7 20 ; 0xc298b + mov ax, 0b800h ; b8 00 b8 ; 0xc298e vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc2991 + mov dl, byte [es:bx] ; 26 8a 17 ; 0xc2993 + mov al, cl ; 88 c8 ; 0xc2996 vgabios.c:1785 + xor ah, ah ; 30 e4 ; 0xc2998 + mov si, ax ; 89 c6 ; 0xc299a + sal si, 003h ; c1 e6 03 ; 0xc299c + cmp byte [si+047b2h], 002h ; 80 bc b2 47 02 ; 0xc299f + jne short 029bfh ; 75 19 ; 0xc29a4 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc29a6 vgabios.c:1787 + and AL, strict byte 003h ; 24 03 ; 0xc29a9 + mov AH, strict byte 003h ; b4 03 ; 0xc29ab + sub ah, al ; 28 c4 ; 0xc29ad + mov cl, ah ; 88 e1 ; 0xc29af + add cl, ah ; 00 e1 ; 0xc29b1 + mov dh, byte [bp-004h] ; 8a 76 fc ; 0xc29b3 + and dh, 003h ; 80 e6 03 ; 0xc29b6 + sal dh, CL ; d2 e6 ; 0xc29b9 + mov AL, strict byte 003h ; b0 03 ; 0xc29bb vgabios.c:1788 + jmp short 029d2h ; eb 13 ; 0xc29bd vgabios.c:1790 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc29bf vgabios.c:1792 + and AL, strict byte 007h ; 24 07 ; 0xc29c2 + mov CL, strict byte 007h ; b1 07 ; 0xc29c4 + sub cl, al ; 28 c1 ; 0xc29c6 + mov dh, byte [bp-004h] ; 8a 76 fc ; 0xc29c8 + and dh, 001h ; 80 e6 01 ; 0xc29cb + sal dh, CL ; d2 e6 ; 0xc29ce + mov AL, strict byte 001h ; b0 01 ; 0xc29d0 vgabios.c:1793 + sal al, CL ; d2 e0 ; 0xc29d2 + test byte [bp-004h], 080h ; f6 46 fc 80 ; 0xc29d4 vgabios.c:1795 + je short 029deh ; 74 04 ; 0xc29d8 + xor dl, dh ; 30 f2 ; 0xc29da vgabios.c:1797 + jmp short 029e4h ; eb 06 ; 0xc29dc vgabios.c:1799 + not al ; f6 d0 ; 0xc29de vgabios.c:1801 + and dl, al ; 20 c2 ; 0xc29e0 + or dl, dh ; 08 f2 ; 0xc29e2 vgabios.c:1802 + mov ax, 0b800h ; b8 00 b8 ; 0xc29e4 vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc29e7 + mov byte [es:bx], dl ; 26 88 17 ; 0xc29e9 + jmp short 02a10h ; eb 22 ; 0xc29ec vgabios.c:1805 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc29ee vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc29f1 + mov es, ax ; 8e c0 ; 0xc29f4 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc29f6 + sal bx, 003h ; c1 e3 03 ; 0xc29f9 vgabios.c:58 + mov ax, dx ; 89 d0 ; 0xc29fc + mul bx ; f7 e3 ; 0xc29fe + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc2a00 + add bx, ax ; 01 c3 ; 0xc2a03 + mov ax, 0a000h ; b8 00 a0 ; 0xc2a05 vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc2a08 + mov al, byte [bp-004h] ; 8a 46 fc ; 0xc2a0a + mov byte [es:bx], al ; 26 88 07 ; 0xc2a0d + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2a10 vgabios.c:1815 + pop si ; 5e ; 0xc2a13 + pop bp ; 5d ; 0xc2a14 + retn ; c3 ; 0xc2a15 + ; disGetNextSymbol 0xc2a16 LB 0x1b1c -> off=0x0 cb=0000000000000258 uValue=00000000000c2a16 'biosfn_write_teletype' +biosfn_write_teletype: ; 0xc2a16 LB 0x258 + push bp ; 55 ; 0xc2a16 vgabios.c:1818 + mov bp, sp ; 89 e5 ; 0xc2a17 + push si ; 56 ; 0xc2a19 + sub sp, strict byte 00014h ; 83 ec 14 ; 0xc2a1a + mov ch, al ; 88 c5 ; 0xc2a1d + mov byte [bp-008h], dl ; 88 56 f8 ; 0xc2a1f + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc2a22 + cmp dl, 0ffh ; 80 fa ff ; 0xc2a25 vgabios.c:1826 + jne short 02a38h ; 75 0e ; 0xc2a28 + mov bx, strict word 00062h ; bb 62 00 ; 0xc2a2a vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2a2d + mov es, ax ; 8e c0 ; 0xc2a30 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2a32 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc2a35 vgabios.c:48 + mov bx, strict word 00049h ; bb 49 00 ; 0xc2a38 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2a3b + mov es, ax ; 8e c0 ; 0xc2a3e + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2a40 + xor ah, ah ; 30 e4 ; 0xc2a43 vgabios.c:1831 + call 03819h ; e8 d1 0d ; 0xc2a45 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc2a48 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc2a4b vgabios.c:1832 + je short 02ab5h ; 74 66 ; 0xc2a4d + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2a4f vgabios.c:1835 + xor ah, ah ; 30 e4 ; 0xc2a52 + lea bx, [bp-014h] ; 8d 5e ec ; 0xc2a54 + lea dx, [bp-016h] ; 8d 56 ea ; 0xc2a57 + call 00a96h ; e8 39 e0 ; 0xc2a5a + mov al, byte [bp-014h] ; 8a 46 ec ; 0xc2a5d vgabios.c:1836 + mov byte [bp-004h], al ; 88 46 fc ; 0xc2a60 + mov ax, word [bp-014h] ; 8b 46 ec ; 0xc2a63 + xor al, al ; 30 c0 ; 0xc2a66 + shr ax, 008h ; c1 e8 08 ; 0xc2a68 + mov byte [bp-006h], al ; 88 46 fa ; 0xc2a6b + mov bx, 00084h ; bb 84 00 ; 0xc2a6e vgabios.c:47 + mov dx, strict word 00040h ; ba 40 00 ; 0xc2a71 + mov es, dx ; 8e c2 ; 0xc2a74 + mov dl, byte [es:bx] ; 26 8a 17 ; 0xc2a76 + xor dh, dh ; 30 f6 ; 0xc2a79 vgabios.c:48 + inc dx ; 42 ; 0xc2a7b + mov word [bp-012h], dx ; 89 56 ee ; 0xc2a7c + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2a7f vgabios.c:57 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc2a82 + mov word [bp-010h], dx ; 89 56 f0 ; 0xc2a85 vgabios.c:58 + cmp ch, 008h ; 80 fd 08 ; 0xc2a88 vgabios.c:1842 + jc short 02a9bh ; 72 0e ; 0xc2a8b + jbe short 02aa3h ; 76 14 ; 0xc2a8d + cmp ch, 00dh ; 80 fd 0d ; 0xc2a8f + je short 02ab8h ; 74 24 ; 0xc2a92 + cmp ch, 00ah ; 80 fd 0a ; 0xc2a94 + je short 02aaeh ; 74 15 ; 0xc2a97 + jmp short 02abfh ; eb 24 ; 0xc2a99 + cmp ch, 007h ; 80 fd 07 ; 0xc2a9b + jne short 02abfh ; 75 1f ; 0xc2a9e + jmp near 02bc5h ; e9 22 01 ; 0xc2aa0 + cmp byte [bp-004h], 000h ; 80 7e fc 00 ; 0xc2aa3 vgabios.c:1849 + jbe short 02abch ; 76 13 ; 0xc2aa7 + dec byte [bp-004h] ; fe 4e fc ; 0xc2aa9 + jmp short 02abch ; eb 0e ; 0xc2aac vgabios.c:1850 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc2aae vgabios.c:1853 + mov byte [bp-006h], al ; 88 46 fa ; 0xc2ab0 + jmp short 02abch ; eb 07 ; 0xc2ab3 vgabios.c:1854 + jmp near 02c68h ; e9 b0 01 ; 0xc2ab5 + mov byte [bp-004h], 000h ; c6 46 fc 00 ; 0xc2ab8 vgabios.c:1857 + jmp near 02bc5h ; e9 06 01 ; 0xc2abc vgabios.c:1858 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2abf vgabios.c:1862 + xor ah, ah ; 30 e4 ; 0xc2ac2 + mov bx, ax ; 89 c3 ; 0xc2ac4 + sal bx, 003h ; c1 e3 03 ; 0xc2ac6 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc2ac9 + jne short 02b12h ; 75 42 ; 0xc2ace + mov ax, word [bp-010h] ; 8b 46 f0 ; 0xc2ad0 vgabios.c:1865 + mul word [bp-012h] ; f7 66 ee ; 0xc2ad3 + add ax, ax ; 01 c0 ; 0xc2ad6 + or AL, strict byte 0ffh ; 0c ff ; 0xc2ad8 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc2ada + xor dh, dh ; 30 f6 ; 0xc2add + inc ax ; 40 ; 0xc2adf + mul dx ; f7 e2 ; 0xc2ae0 + mov si, ax ; 89 c6 ; 0xc2ae2 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2ae4 + xor ah, ah ; 30 e4 ; 0xc2ae7 + mul word [bp-010h] ; f7 66 f0 ; 0xc2ae9 + mov dx, ax ; 89 c2 ; 0xc2aec + mov al, byte [bp-004h] ; 8a 46 fc ; 0xc2aee + xor ah, ah ; 30 e4 ; 0xc2af1 + add ax, dx ; 01 d0 ; 0xc2af3 + add ax, ax ; 01 c0 ; 0xc2af5 + add si, ax ; 01 c6 ; 0xc2af7 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2af9 vgabios.c:50 + mov byte [es:si], ch ; 26 88 2c ; 0xc2afd vgabios.c:52 + cmp cl, 003h ; 80 f9 03 ; 0xc2b00 vgabios.c:1870 + jne short 02b41h ; 75 3c ; 0xc2b03 + inc si ; 46 ; 0xc2b05 vgabios.c:1871 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2b06 vgabios.c:50 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2b0a + mov byte [es:si], al ; 26 88 04 ; 0xc2b0d + jmp short 02b41h ; eb 2f ; 0xc2b10 vgabios.c:1873 + mov si, ax ; 89 c6 ; 0xc2b12 vgabios.c:1876 + mov al, byte [si+0482fh] ; 8a 84 2f 48 ; 0xc2b14 + mov si, ax ; 89 c6 ; 0xc2b18 + sal si, 006h ; c1 e6 06 ; 0xc2b1a + mov dl, byte [si+04845h] ; 8a 94 45 48 ; 0xc2b1d + mov al, byte [bx+047b2h] ; 8a 87 b2 47 ; 0xc2b21 vgabios.c:1877 + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc2b25 vgabios.c:1878 + cmp bl, 003h ; 80 fb 03 ; 0xc2b29 + jc short 02b3ch ; 72 0e ; 0xc2b2c + jbe short 02b43h ; 76 13 ; 0xc2b2e + cmp bl, 005h ; 80 fb 05 ; 0xc2b30 + je short 02b93h ; 74 5e ; 0xc2b33 + cmp bl, 004h ; 80 fb 04 ; 0xc2b35 + je short 02b47h ; 74 0d ; 0xc2b38 + jmp short 02bb2h ; eb 76 ; 0xc2b3a + cmp bl, 002h ; 80 fb 02 ; 0xc2b3c + je short 02b71h ; 74 30 ; 0xc2b3f + jmp short 02bb2h ; eb 6f ; 0xc2b41 + or byte [bp-00ah], 001h ; 80 4e f6 01 ; 0xc2b43 vgabios.c:1881 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2b47 vgabios.c:1883 + xor ah, ah ; 30 e4 ; 0xc2b4a + push ax ; 50 ; 0xc2b4c + mov al, dl ; 88 d0 ; 0xc2b4d + push ax ; 50 ; 0xc2b4f + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2b50 + push ax ; 50 ; 0xc2b53 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2b54 + mov bl, byte [bp-004h] ; 8a 5e fc ; 0xc2b57 + xor bh, bh ; 30 ff ; 0xc2b5a + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc2b5c + xor dh, dh ; 30 f6 ; 0xc2b5f + mov byte [bp-00eh], ch ; 88 6e f2 ; 0xc2b61 + mov byte [bp-00dh], ah ; 88 66 f3 ; 0xc2b64 + mov cx, ax ; 89 c1 ; 0xc2b67 + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc2b69 + call 022ddh ; e8 6e f7 ; 0xc2b6c + jmp short 02bb2h ; eb 41 ; 0xc2b6f vgabios.c:1884 + push ax ; 50 ; 0xc2b71 vgabios.c:1886 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2b72 + push ax ; 50 ; 0xc2b75 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2b76 + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc2b79 + mov byte [bp-00dh], ah ; 88 66 f3 ; 0xc2b7c + mov bl, byte [bp-004h] ; 8a 5e fc ; 0xc2b7f + xor bh, bh ; 30 ff ; 0xc2b82 + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc2b84 + xor dh, dh ; 30 f6 ; 0xc2b87 + mov al, ch ; 88 e8 ; 0xc2b89 + mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xc2b8b + call 023eeh ; e8 5d f8 ; 0xc2b8e + jmp short 02bb2h ; eb 1f ; 0xc2b91 vgabios.c:1887 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2b93 vgabios.c:1889 + push ax ; 50 ; 0xc2b96 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2b97 + mov bl, byte [bp-004h] ; 8a 5e fc ; 0xc2b9a + xor bh, bh ; 30 ff ; 0xc2b9d + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc2b9f + xor dh, dh ; 30 f6 ; 0xc2ba2 + mov byte [bp-00eh], ch ; 88 6e f2 ; 0xc2ba4 + mov byte [bp-00dh], ah ; 88 66 f3 ; 0xc2ba7 + mov cx, ax ; 89 c1 ; 0xc2baa + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc2bac + call 02500h ; e8 4e f9 ; 0xc2baf + inc byte [bp-004h] ; fe 46 fc ; 0xc2bb2 vgabios.c:1897 + mov al, byte [bp-004h] ; 8a 46 fc ; 0xc2bb5 vgabios.c:1899 + xor ah, ah ; 30 e4 ; 0xc2bb8 + cmp ax, word [bp-010h] ; 3b 46 f0 ; 0xc2bba + jne short 02bc5h ; 75 06 ; 0xc2bbd + mov byte [bp-004h], ah ; 88 66 fc ; 0xc2bbf vgabios.c:1900 + inc byte [bp-006h] ; fe 46 fa ; 0xc2bc2 vgabios.c:1901 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2bc5 vgabios.c:1906 + xor ah, ah ; 30 e4 ; 0xc2bc8 + cmp ax, word [bp-012h] ; 3b 46 ee ; 0xc2bca + jne short 02c30h ; 75 61 ; 0xc2bcd + mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xc2bcf vgabios.c:1908 + xor bh, bh ; 30 ff ; 0xc2bd2 + sal bx, 003h ; c1 e3 03 ; 0xc2bd4 + mov ch, byte [bp-012h] ; 8a 6e ee ; 0xc2bd7 + db 0feh, 0cdh + ; dec ch ; fe cd ; 0xc2bda + mov cl, byte [bp-010h] ; 8a 4e f0 ; 0xc2bdc + db 0feh, 0c9h + ; dec cl ; fe c9 ; 0xc2bdf + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc2be1 + jne short 02c32h ; 75 4a ; 0xc2be6 + mov ax, word [bp-010h] ; 8b 46 f0 ; 0xc2be8 vgabios.c:1910 + mul word [bp-012h] ; f7 66 ee ; 0xc2beb + add ax, ax ; 01 c0 ; 0xc2bee + or AL, strict byte 0ffh ; 0c ff ; 0xc2bf0 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc2bf2 + xor dh, dh ; 30 f6 ; 0xc2bf5 + inc ax ; 40 ; 0xc2bf7 + mul dx ; f7 e2 ; 0xc2bf8 + mov si, ax ; 89 c6 ; 0xc2bfa + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2bfc + xor ah, ah ; 30 e4 ; 0xc2bff + dec ax ; 48 ; 0xc2c01 + mul word [bp-010h] ; f7 66 f0 ; 0xc2c02 + mov dx, ax ; 89 c2 ; 0xc2c05 + mov al, byte [bp-004h] ; 8a 46 fc ; 0xc2c07 + xor ah, ah ; 30 e4 ; 0xc2c0a + add ax, dx ; 01 d0 ; 0xc2c0c + add ax, ax ; 01 c0 ; 0xc2c0e + add si, ax ; 01 c6 ; 0xc2c10 + inc si ; 46 ; 0xc2c12 vgabios.c:1911 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2c13 vgabios.c:45 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc2c17 + push strict byte 00001h ; 6a 01 ; 0xc2c1a vgabios.c:1912 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2c1c + xor ah, ah ; 30 e4 ; 0xc2c1f + push ax ; 50 ; 0xc2c21 + mov al, cl ; 88 c8 ; 0xc2c22 + push ax ; 50 ; 0xc2c24 + mov al, ch ; 88 e8 ; 0xc2c25 + push ax ; 50 ; 0xc2c27 + xor dh, dh ; 30 f6 ; 0xc2c28 + xor cx, cx ; 31 c9 ; 0xc2c2a + xor bx, bx ; 31 db ; 0xc2c2c + jmp short 02c44h ; eb 14 ; 0xc2c2e vgabios.c:1914 + jmp short 02c4dh ; eb 1b ; 0xc2c30 + push strict byte 00001h ; 6a 01 ; 0xc2c32 vgabios.c:1916 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2c34 + push ax ; 50 ; 0xc2c37 + mov al, cl ; 88 c8 ; 0xc2c38 + push ax ; 50 ; 0xc2c3a + mov al, ch ; 88 e8 ; 0xc2c3b + push ax ; 50 ; 0xc2c3d + xor cx, cx ; 31 c9 ; 0xc2c3e + xor bx, bx ; 31 db ; 0xc2c40 + xor dx, dx ; 31 d2 ; 0xc2c42 + mov ax, strict word 00001h ; b8 01 00 ; 0xc2c44 + call 01c55h ; e8 0b f0 ; 0xc2c47 + dec byte [bp-006h] ; fe 4e fa ; 0xc2c4a vgabios.c:1918 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2c4d vgabios.c:1922 + xor ah, ah ; 30 e4 ; 0xc2c50 + mov word [bp-014h], ax ; 89 46 ec ; 0xc2c52 + sal word [bp-014h], 008h ; c1 66 ec 08 ; 0xc2c55 + mov al, byte [bp-004h] ; 8a 46 fc ; 0xc2c59 + add word [bp-014h], ax ; 01 46 ec ; 0xc2c5c + mov dx, word [bp-014h] ; 8b 56 ec ; 0xc2c5f vgabios.c:1923 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2c62 + call 01293h ; e8 2b e6 ; 0xc2c65 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2c68 vgabios.c:1924 + pop si ; 5e ; 0xc2c6b + pop bp ; 5d ; 0xc2c6c + retn ; c3 ; 0xc2c6d + ; disGetNextSymbol 0xc2c6e LB 0x18c4 -> off=0x0 cb=0000000000000033 uValue=00000000000c2c6e 'get_font_access' +get_font_access: ; 0xc2c6e LB 0x33 + push bp ; 55 ; 0xc2c6e vgabios.c:1927 + mov bp, sp ; 89 e5 ; 0xc2c6f + push dx ; 52 ; 0xc2c71 + mov ax, strict word 00005h ; b8 05 00 ; 0xc2c72 vgabios.c:1929 + mov dx, 003ceh ; ba ce 03 ; 0xc2c75 + out DX, ax ; ef ; 0xc2c78 + mov AL, strict byte 006h ; b0 06 ; 0xc2c79 vgabios.c:1930 + out DX, AL ; ee ; 0xc2c7b + mov dx, 003cfh ; ba cf 03 ; 0xc2c7c vgabios.c:1931 + in AL, DX ; ec ; 0xc2c7f + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2c80 + and ax, strict word 00001h ; 25 01 00 ; 0xc2c82 + or AL, strict byte 004h ; 0c 04 ; 0xc2c85 + sal ax, 008h ; c1 e0 08 ; 0xc2c87 + or AL, strict byte 006h ; 0c 06 ; 0xc2c8a + mov dx, 003ceh ; ba ce 03 ; 0xc2c8c + out DX, ax ; ef ; 0xc2c8f + mov ax, 00402h ; b8 02 04 ; 0xc2c90 vgabios.c:1932 + mov dx, 003c4h ; ba c4 03 ; 0xc2c93 + out DX, ax ; ef ; 0xc2c96 + mov ax, 00604h ; b8 04 06 ; 0xc2c97 vgabios.c:1933 + out DX, ax ; ef ; 0xc2c9a + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2c9b vgabios.c:1934 + pop dx ; 5a ; 0xc2c9e + pop bp ; 5d ; 0xc2c9f + retn ; c3 ; 0xc2ca0 + ; disGetNextSymbol 0xc2ca1 LB 0x1891 -> off=0x0 cb=0000000000000030 uValue=00000000000c2ca1 'release_font_access' +release_font_access: ; 0xc2ca1 LB 0x30 + push bp ; 55 ; 0xc2ca1 vgabios.c:1936 + mov bp, sp ; 89 e5 ; 0xc2ca2 + push dx ; 52 ; 0xc2ca4 + mov dx, 003cch ; ba cc 03 ; 0xc2ca5 vgabios.c:1938 + in AL, DX ; ec ; 0xc2ca8 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2ca9 + and ax, strict word 00001h ; 25 01 00 ; 0xc2cab + sal ax, 002h ; c1 e0 02 ; 0xc2cae + or AL, strict byte 00ah ; 0c 0a ; 0xc2cb1 + sal ax, 008h ; c1 e0 08 ; 0xc2cb3 + or AL, strict byte 006h ; 0c 06 ; 0xc2cb6 + mov dx, 003ceh ; ba ce 03 ; 0xc2cb8 + out DX, ax ; ef ; 0xc2cbb + mov ax, 01005h ; b8 05 10 ; 0xc2cbc vgabios.c:1939 + out DX, ax ; ef ; 0xc2cbf + mov ax, 00302h ; b8 02 03 ; 0xc2cc0 vgabios.c:1940 + mov dx, 003c4h ; ba c4 03 ; 0xc2cc3 + out DX, ax ; ef ; 0xc2cc6 + mov ax, 00204h ; b8 04 02 ; 0xc2cc7 vgabios.c:1941 + out DX, ax ; ef ; 0xc2cca + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2ccb vgabios.c:1942 + pop dx ; 5a ; 0xc2cce + pop bp ; 5d ; 0xc2ccf + retn ; c3 ; 0xc2cd0 + ; disGetNextSymbol 0xc2cd1 LB 0x1861 -> off=0x0 cb=00000000000000b1 uValue=00000000000c2cd1 'set_scan_lines' +set_scan_lines: ; 0xc2cd1 LB 0xb1 + push bp ; 55 ; 0xc2cd1 vgabios.c:1944 + mov bp, sp ; 89 e5 ; 0xc2cd2 + push bx ; 53 ; 0xc2cd4 + push cx ; 51 ; 0xc2cd5 + push dx ; 52 ; 0xc2cd6 + push si ; 56 ; 0xc2cd7 + push di ; 57 ; 0xc2cd8 + mov bl, al ; 88 c3 ; 0xc2cd9 + mov si, strict word 00063h ; be 63 00 ; 0xc2cdb vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2cde + mov es, ax ; 8e c0 ; 0xc2ce1 + mov si, word [es:si] ; 26 8b 34 ; 0xc2ce3 + mov cx, si ; 89 f1 ; 0xc2ce6 vgabios.c:58 + mov AL, strict byte 009h ; b0 09 ; 0xc2ce8 vgabios.c:1950 + mov dx, si ; 89 f2 ; 0xc2cea + out DX, AL ; ee ; 0xc2cec + lea dx, [si+001h] ; 8d 54 01 ; 0xc2ced vgabios.c:1951 + in AL, DX ; ec ; 0xc2cf0 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2cf1 + mov ah, al ; 88 c4 ; 0xc2cf3 vgabios.c:1952 + and ah, 0e0h ; 80 e4 e0 ; 0xc2cf5 + mov al, bl ; 88 d8 ; 0xc2cf8 + db 0feh, 0c8h + ; dec al ; fe c8 ; 0xc2cfa + or al, ah ; 08 e0 ; 0xc2cfc + out DX, AL ; ee ; 0xc2cfe vgabios.c:1953 + cmp bl, 008h ; 80 fb 08 ; 0xc2cff vgabios.c:1954 + jne short 02d0ch ; 75 08 ; 0xc2d02 + mov dx, strict word 00007h ; ba 07 00 ; 0xc2d04 vgabios.c:1956 + mov ax, strict word 00006h ; b8 06 00 ; 0xc2d07 + jmp short 02d19h ; eb 0d ; 0xc2d0a vgabios.c:1958 + mov dl, bl ; 88 da ; 0xc2d0c vgabios.c:1960 + sub dl, 003h ; 80 ea 03 ; 0xc2d0e + xor dh, dh ; 30 f6 ; 0xc2d11 + mov al, bl ; 88 d8 ; 0xc2d13 + sub AL, strict byte 004h ; 2c 04 ; 0xc2d15 + xor ah, ah ; 30 e4 ; 0xc2d17 + call 0118ch ; e8 70 e4 ; 0xc2d19 + xor bh, bh ; 30 ff ; 0xc2d1c vgabios.c:1962 + mov si, 00085h ; be 85 00 ; 0xc2d1e vgabios.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2d21 + mov es, ax ; 8e c0 ; 0xc2d24 + mov word [es:si], bx ; 26 89 1c ; 0xc2d26 + mov AL, strict byte 012h ; b0 12 ; 0xc2d29 vgabios.c:1963 + mov dx, cx ; 89 ca ; 0xc2d2b + out DX, AL ; ee ; 0xc2d2d + mov si, cx ; 89 ce ; 0xc2d2e vgabios.c:1964 + inc si ; 46 ; 0xc2d30 + mov dx, si ; 89 f2 ; 0xc2d31 + in AL, DX ; ec ; 0xc2d33 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2d34 + mov di, ax ; 89 c7 ; 0xc2d36 + mov AL, strict byte 007h ; b0 07 ; 0xc2d38 vgabios.c:1965 + mov dx, cx ; 89 ca ; 0xc2d3a + out DX, AL ; ee ; 0xc2d3c + mov dx, si ; 89 f2 ; 0xc2d3d vgabios.c:1966 + in AL, DX ; ec ; 0xc2d3f + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2d40 + mov dl, al ; 88 c2 ; 0xc2d42 vgabios.c:1967 + and dl, 002h ; 80 e2 02 ; 0xc2d44 + xor dh, dh ; 30 f6 ; 0xc2d47 + sal dx, 007h ; c1 e2 07 ; 0xc2d49 + and AL, strict byte 040h ; 24 40 ; 0xc2d4c + xor ah, ah ; 30 e4 ; 0xc2d4e + sal ax, 003h ; c1 e0 03 ; 0xc2d50 + add ax, dx ; 01 d0 ; 0xc2d53 + inc ax ; 40 ; 0xc2d55 + add ax, di ; 01 f8 ; 0xc2d56 + xor dx, dx ; 31 d2 ; 0xc2d58 vgabios.c:1968 + div bx ; f7 f3 ; 0xc2d5a + mov dl, al ; 88 c2 ; 0xc2d5c vgabios.c:1969 + db 0feh, 0cah + ; dec dl ; fe ca ; 0xc2d5e + mov si, 00084h ; be 84 00 ; 0xc2d60 vgabios.c:52 + mov byte [es:si], dl ; 26 88 14 ; 0xc2d63 + mov si, strict word 0004ah ; be 4a 00 ; 0xc2d66 vgabios.c:57 + mov dx, word [es:si] ; 26 8b 14 ; 0xc2d69 + xor ah, ah ; 30 e4 ; 0xc2d6c vgabios.c:1971 + mul dx ; f7 e2 ; 0xc2d6e + add ax, ax ; 01 c0 ; 0xc2d70 + mov si, strict word 0004ch ; be 4c 00 ; 0xc2d72 vgabios.c:62 + mov word [es:si], ax ; 26 89 04 ; 0xc2d75 + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc2d78 vgabios.c:1972 + pop di ; 5f ; 0xc2d7b + pop si ; 5e ; 0xc2d7c + pop dx ; 5a ; 0xc2d7d + pop cx ; 59 ; 0xc2d7e + pop bx ; 5b ; 0xc2d7f + pop bp ; 5d ; 0xc2d80 + retn ; c3 ; 0xc2d81 + ; disGetNextSymbol 0xc2d82 LB 0x17b0 -> off=0x0 cb=0000000000000023 uValue=00000000000c2d82 'biosfn_set_font_block' +biosfn_set_font_block: ; 0xc2d82 LB 0x23 + push bp ; 55 ; 0xc2d82 vgabios.c:1974 + mov bp, sp ; 89 e5 ; 0xc2d83 + push bx ; 53 ; 0xc2d85 + push dx ; 52 ; 0xc2d86 + mov bl, al ; 88 c3 ; 0xc2d87 + mov ax, 00100h ; b8 00 01 ; 0xc2d89 vgabios.c:1976 + mov dx, 003c4h ; ba c4 03 ; 0xc2d8c + out DX, ax ; ef ; 0xc2d8f + mov al, bl ; 88 d8 ; 0xc2d90 vgabios.c:1977 + xor ah, ah ; 30 e4 ; 0xc2d92 + sal ax, 008h ; c1 e0 08 ; 0xc2d94 + or AL, strict byte 003h ; 0c 03 ; 0xc2d97 + out DX, ax ; ef ; 0xc2d99 + mov ax, 00300h ; b8 00 03 ; 0xc2d9a vgabios.c:1978 + out DX, ax ; ef ; 0xc2d9d + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2d9e vgabios.c:1979 + pop dx ; 5a ; 0xc2da1 + pop bx ; 5b ; 0xc2da2 + pop bp ; 5d ; 0xc2da3 + retn ; c3 ; 0xc2da4 + ; disGetNextSymbol 0xc2da5 LB 0x178d -> off=0x0 cb=0000000000000075 uValue=00000000000c2da5 'load_text_patch' +load_text_patch: ; 0xc2da5 LB 0x75 + push bp ; 55 ; 0xc2da5 vgabios.c:1981 + mov bp, sp ; 89 e5 ; 0xc2da6 + push si ; 56 ; 0xc2da8 + push di ; 57 ; 0xc2da9 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc2daa + push ax ; 50 ; 0xc2dad + mov byte [bp-006h], cl ; 88 4e fa ; 0xc2dae + call 02c6eh ; e8 ba fe ; 0xc2db1 vgabios.c:1986 + mov al, bl ; 88 d8 ; 0xc2db4 vgabios.c:1988 + and AL, strict byte 003h ; 24 03 ; 0xc2db6 + xor ah, ah ; 30 e4 ; 0xc2db8 + mov cx, ax ; 89 c1 ; 0xc2dba + sal cx, 00eh ; c1 e1 0e ; 0xc2dbc + mov al, bl ; 88 d8 ; 0xc2dbf + and AL, strict byte 004h ; 24 04 ; 0xc2dc1 + sal ax, 00bh ; c1 e0 0b ; 0xc2dc3 + add cx, ax ; 01 c1 ; 0xc2dc6 + mov word [bp-00ah], cx ; 89 4e f6 ; 0xc2dc8 + mov bx, dx ; 89 d3 ; 0xc2dcb vgabios.c:1989 + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc2dcd + mov word [bp-008h], ax ; 89 46 f8 ; 0xc2dd0 + inc dx ; 42 ; 0xc2dd3 vgabios.c:1990 + mov word [bp-00ch], dx ; 89 56 f4 ; 0xc2dd4 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc2dd7 vgabios.c:1991 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2dda + test al, al ; 84 c0 ; 0xc2ddd + je short 02e10h ; 74 2f ; 0xc2ddf + xor ah, ah ; 30 e4 ; 0xc2de1 vgabios.c:1992 + sal ax, 005h ; c1 e0 05 ; 0xc2de3 + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc2de6 + add di, ax ; 01 c7 ; 0xc2de9 + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc2deb vgabios.c:1993 + xor ch, ch ; 30 ed ; 0xc2dee + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc2df0 + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc2df3 + mov ax, 0a000h ; b8 00 a0 ; 0xc2df6 + mov es, ax ; 8e c0 ; 0xc2df9 + jcxz 02e03h ; e3 06 ; 0xc2dfb + push DS ; 1e ; 0xc2dfd + mov ds, dx ; 8e da ; 0xc2dfe + rep movsb ; f3 a4 ; 0xc2e00 + pop DS ; 1f ; 0xc2e02 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2e03 vgabios.c:1994 + xor ah, ah ; 30 e4 ; 0xc2e06 + inc ax ; 40 ; 0xc2e08 + add word [bp-00ch], ax ; 01 46 f4 ; 0xc2e09 + add bx, ax ; 01 c3 ; 0xc2e0c vgabios.c:1995 + jmp short 02dd7h ; eb c7 ; 0xc2e0e vgabios.c:1996 + call 02ca1h ; e8 8e fe ; 0xc2e10 vgabios.c:1998 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2e13 vgabios.c:1999 + pop di ; 5f ; 0xc2e16 + pop si ; 5e ; 0xc2e17 + pop bp ; 5d ; 0xc2e18 + retn ; c3 ; 0xc2e19 + ; disGetNextSymbol 0xc2e1a LB 0x1718 -> off=0x0 cb=000000000000007f uValue=00000000000c2e1a 'biosfn_load_text_user_pat' +biosfn_load_text_user_pat: ; 0xc2e1a LB 0x7f + push bp ; 55 ; 0xc2e1a vgabios.c:2001 + mov bp, sp ; 89 e5 ; 0xc2e1b + push si ; 56 ; 0xc2e1d + push di ; 57 ; 0xc2e1e + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc2e1f + mov byte [bp-006h], al ; 88 46 fa ; 0xc2e22 + mov word [bp-00ch], dx ; 89 56 f4 ; 0xc2e25 + mov word [bp-00ah], bx ; 89 5e f6 ; 0xc2e28 + mov word [bp-00eh], cx ; 89 4e f2 ; 0xc2e2b + call 02c6eh ; e8 3d fe ; 0xc2e2e vgabios.c:2006 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc2e31 vgabios.c:2007 + and AL, strict byte 003h ; 24 03 ; 0xc2e34 + xor ah, ah ; 30 e4 ; 0xc2e36 + mov bx, ax ; 89 c3 ; 0xc2e38 + sal bx, 00eh ; c1 e3 0e ; 0xc2e3a + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc2e3d + and AL, strict byte 004h ; 24 04 ; 0xc2e40 + sal ax, 00bh ; c1 e0 0b ; 0xc2e42 + add bx, ax ; 01 c3 ; 0xc2e45 + mov word [bp-008h], bx ; 89 5e f8 ; 0xc2e47 + xor bx, bx ; 31 db ; 0xc2e4a vgabios.c:2008 + cmp bx, word [bp-00eh] ; 3b 5e f2 ; 0xc2e4c + jnc short 02e7fh ; 73 2e ; 0xc2e4f + mov cl, byte [bp+008h] ; 8a 4e 08 ; 0xc2e51 vgabios.c:2010 + xor ch, ch ; 30 ed ; 0xc2e54 + mov ax, bx ; 89 d8 ; 0xc2e56 + mul cx ; f7 e1 ; 0xc2e58 + mov si, word [bp-00ah] ; 8b 76 f6 ; 0xc2e5a + add si, ax ; 01 c6 ; 0xc2e5d + mov ax, word [bp+004h] ; 8b 46 04 ; 0xc2e5f vgabios.c:2011 + add ax, bx ; 01 d8 ; 0xc2e62 + sal ax, 005h ; c1 e0 05 ; 0xc2e64 + mov di, word [bp-008h] ; 8b 7e f8 ; 0xc2e67 + add di, ax ; 01 c7 ; 0xc2e6a + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc2e6c vgabios.c:2012 + mov ax, 0a000h ; b8 00 a0 ; 0xc2e6f + mov es, ax ; 8e c0 ; 0xc2e72 + jcxz 02e7ch ; e3 06 ; 0xc2e74 + push DS ; 1e ; 0xc2e76 + mov ds, dx ; 8e da ; 0xc2e77 + rep movsb ; f3 a4 ; 0xc2e79 + pop DS ; 1f ; 0xc2e7b + inc bx ; 43 ; 0xc2e7c vgabios.c:2013 + jmp short 02e4ch ; eb cd ; 0xc2e7d + call 02ca1h ; e8 1f fe ; 0xc2e7f vgabios.c:2014 + cmp byte [bp-006h], 010h ; 80 7e fa 10 ; 0xc2e82 vgabios.c:2015 + jc short 02e90h ; 72 08 ; 0xc2e86 + mov al, byte [bp+008h] ; 8a 46 08 ; 0xc2e88 vgabios.c:2017 + xor ah, ah ; 30 e4 ; 0xc2e8b + call 02cd1h ; e8 41 fe ; 0xc2e8d + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2e90 vgabios.c:2019 + pop di ; 5f ; 0xc2e93 + pop si ; 5e ; 0xc2e94 + pop bp ; 5d ; 0xc2e95 + retn 00006h ; c2 06 00 ; 0xc2e96 + ; disGetNextSymbol 0xc2e99 LB 0x1699 -> off=0x0 cb=0000000000000016 uValue=00000000000c2e99 'biosfn_load_gfx_8_8_chars' +biosfn_load_gfx_8_8_chars: ; 0xc2e99 LB 0x16 + push bp ; 55 ; 0xc2e99 vgabios.c:2021 + mov bp, sp ; 89 e5 ; 0xc2e9a + push bx ; 53 ; 0xc2e9c + push cx ; 51 ; 0xc2e9d + mov bx, dx ; 89 d3 ; 0xc2e9e vgabios.c:2023 + mov cx, ax ; 89 c1 ; 0xc2ea0 + mov ax, strict word 0001fh ; b8 1f 00 ; 0xc2ea2 + call 009f0h ; e8 48 db ; 0xc2ea5 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2ea8 vgabios.c:2024 + pop cx ; 59 ; 0xc2eab + pop bx ; 5b ; 0xc2eac + pop bp ; 5d ; 0xc2ead + retn ; c3 ; 0xc2eae + ; disGetNextSymbol 0xc2eaf LB 0x1683 -> off=0x0 cb=000000000000004d uValue=00000000000c2eaf 'set_gfx_font' +set_gfx_font: ; 0xc2eaf LB 0x4d + push bp ; 55 ; 0xc2eaf vgabios.c:2026 + mov bp, sp ; 89 e5 ; 0xc2eb0 + push si ; 56 ; 0xc2eb2 + push di ; 57 ; 0xc2eb3 + mov si, ax ; 89 c6 ; 0xc2eb4 + mov ax, dx ; 89 d0 ; 0xc2eb6 + mov di, bx ; 89 df ; 0xc2eb8 + mov dl, cl ; 88 ca ; 0xc2eba + mov bx, si ; 89 f3 ; 0xc2ebc vgabios.c:2030 + mov cx, ax ; 89 c1 ; 0xc2ebe + mov ax, strict word 00043h ; b8 43 00 ; 0xc2ec0 + call 009f0h ; e8 2a db ; 0xc2ec3 + test dl, dl ; 84 d2 ; 0xc2ec6 vgabios.c:2031 + je short 02edch ; 74 12 ; 0xc2ec8 + cmp dl, 003h ; 80 fa 03 ; 0xc2eca vgabios.c:2032 + jbe short 02ed1h ; 76 02 ; 0xc2ecd + mov DL, strict byte 002h ; b2 02 ; 0xc2ecf vgabios.c:2033 + mov bl, dl ; 88 d3 ; 0xc2ed1 vgabios.c:2034 + xor bh, bh ; 30 ff ; 0xc2ed3 + mov al, byte [bx+07dfeh] ; 8a 87 fe 7d ; 0xc2ed5 + mov byte [bp+004h], al ; 88 46 04 ; 0xc2ed9 + mov bx, 00085h ; bb 85 00 ; 0xc2edc vgabios.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2edf + mov es, ax ; 8e c0 ; 0xc2ee2 + mov word [es:bx], di ; 26 89 3f ; 0xc2ee4 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc2ee7 vgabios.c:2039 + xor ah, ah ; 30 e4 ; 0xc2eea + dec ax ; 48 ; 0xc2eec + mov bx, 00084h ; bb 84 00 ; 0xc2eed vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc2ef0 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2ef3 vgabios.c:2040 + pop di ; 5f ; 0xc2ef6 + pop si ; 5e ; 0xc2ef7 + pop bp ; 5d ; 0xc2ef8 + retn 00002h ; c2 02 00 ; 0xc2ef9 + ; disGetNextSymbol 0xc2efc LB 0x1636 -> off=0x0 cb=000000000000001d uValue=00000000000c2efc 'biosfn_load_gfx_user_chars' +biosfn_load_gfx_user_chars: ; 0xc2efc LB 0x1d + push bp ; 55 ; 0xc2efc vgabios.c:2042 + mov bp, sp ; 89 e5 ; 0xc2efd + push si ; 56 ; 0xc2eff + mov si, ax ; 89 c6 ; 0xc2f00 + mov ax, dx ; 89 d0 ; 0xc2f02 + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc2f04 vgabios.c:2045 + xor dh, dh ; 30 f6 ; 0xc2f07 + push dx ; 52 ; 0xc2f09 + xor ch, ch ; 30 ed ; 0xc2f0a + mov dx, si ; 89 f2 ; 0xc2f0c + call 02eafh ; e8 9e ff ; 0xc2f0e + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2f11 vgabios.c:2046 + pop si ; 5e ; 0xc2f14 + pop bp ; 5d ; 0xc2f15 + retn 00002h ; c2 02 00 ; 0xc2f16 + ; disGetNextSymbol 0xc2f19 LB 0x1619 -> off=0x0 cb=0000000000000022 uValue=00000000000c2f19 'biosfn_load_gfx_8_14_chars' +biosfn_load_gfx_8_14_chars: ; 0xc2f19 LB 0x22 + push bp ; 55 ; 0xc2f19 vgabios.c:2051 + mov bp, sp ; 89 e5 ; 0xc2f1a + push bx ; 53 ; 0xc2f1c + push cx ; 51 ; 0xc2f1d + mov bl, al ; 88 c3 ; 0xc2f1e + mov al, dl ; 88 d0 ; 0xc2f20 + xor ah, ah ; 30 e4 ; 0xc2f22 vgabios.c:2053 + push ax ; 50 ; 0xc2f24 + mov al, bl ; 88 d8 ; 0xc2f25 + mov cx, ax ; 89 c1 ; 0xc2f27 + mov bx, strict word 0000eh ; bb 0e 00 ; 0xc2f29 + mov ax, 05d6dh ; b8 6d 5d ; 0xc2f2c + mov dx, ds ; 8c da ; 0xc2f2f + call 02eafh ; e8 7b ff ; 0xc2f31 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2f34 vgabios.c:2054 + pop cx ; 59 ; 0xc2f37 + pop bx ; 5b ; 0xc2f38 + pop bp ; 5d ; 0xc2f39 + retn ; c3 ; 0xc2f3a + ; disGetNextSymbol 0xc2f3b LB 0x15f7 -> off=0x0 cb=0000000000000022 uValue=00000000000c2f3b 'biosfn_load_gfx_8_8_dd_chars' +biosfn_load_gfx_8_8_dd_chars: ; 0xc2f3b LB 0x22 + push bp ; 55 ; 0xc2f3b vgabios.c:2055 + mov bp, sp ; 89 e5 ; 0xc2f3c + push bx ; 53 ; 0xc2f3e + push cx ; 51 ; 0xc2f3f + mov bl, al ; 88 c3 ; 0xc2f40 + mov al, dl ; 88 d0 ; 0xc2f42 + xor ah, ah ; 30 e4 ; 0xc2f44 vgabios.c:2057 + push ax ; 50 ; 0xc2f46 + mov al, bl ; 88 d8 ; 0xc2f47 + mov cx, ax ; 89 c1 ; 0xc2f49 + mov bx, strict word 00008h ; bb 08 00 ; 0xc2f4b + mov ax, 0556dh ; b8 6d 55 ; 0xc2f4e + mov dx, ds ; 8c da ; 0xc2f51 + call 02eafh ; e8 59 ff ; 0xc2f53 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2f56 vgabios.c:2058 + pop cx ; 59 ; 0xc2f59 + pop bx ; 5b ; 0xc2f5a + pop bp ; 5d ; 0xc2f5b + retn ; c3 ; 0xc2f5c + ; disGetNextSymbol 0xc2f5d LB 0x15d5 -> off=0x0 cb=0000000000000022 uValue=00000000000c2f5d 'biosfn_load_gfx_8_16_chars' +biosfn_load_gfx_8_16_chars: ; 0xc2f5d LB 0x22 + push bp ; 55 ; 0xc2f5d vgabios.c:2059 + mov bp, sp ; 89 e5 ; 0xc2f5e + push bx ; 53 ; 0xc2f60 + push cx ; 51 ; 0xc2f61 + mov bl, al ; 88 c3 ; 0xc2f62 + mov al, dl ; 88 d0 ; 0xc2f64 + xor ah, ah ; 30 e4 ; 0xc2f66 vgabios.c:2061 + push ax ; 50 ; 0xc2f68 + mov al, bl ; 88 d8 ; 0xc2f69 + mov cx, ax ; 89 c1 ; 0xc2f6b + mov bx, strict word 00010h ; bb 10 00 ; 0xc2f6d + mov ax, 06b6dh ; b8 6d 6b ; 0xc2f70 + mov dx, ds ; 8c da ; 0xc2f73 + call 02eafh ; e8 37 ff ; 0xc2f75 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2f78 vgabios.c:2062 + pop cx ; 59 ; 0xc2f7b + pop bx ; 5b ; 0xc2f7c + pop bp ; 5d ; 0xc2f7d + retn ; c3 ; 0xc2f7e + ; disGetNextSymbol 0xc2f7f LB 0x15b3 -> off=0x0 cb=0000000000000005 uValue=00000000000c2f7f 'biosfn_alternate_prtsc' +biosfn_alternate_prtsc: ; 0xc2f7f LB 0x5 + push bp ; 55 ; 0xc2f7f vgabios.c:2064 + mov bp, sp ; 89 e5 ; 0xc2f80 + pop bp ; 5d ; 0xc2f82 vgabios.c:2069 + retn ; c3 ; 0xc2f83 + ; disGetNextSymbol 0xc2f84 LB 0x15ae -> off=0x0 cb=0000000000000032 uValue=00000000000c2f84 'biosfn_set_txt_lines' +biosfn_set_txt_lines: ; 0xc2f84 LB 0x32 + push bx ; 53 ; 0xc2f84 vgabios.c:2071 + push si ; 56 ; 0xc2f85 + push bp ; 55 ; 0xc2f86 + mov bp, sp ; 89 e5 ; 0xc2f87 + mov bl, al ; 88 c3 ; 0xc2f89 + mov si, 00089h ; be 89 00 ; 0xc2f8b vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2f8e + mov es, ax ; 8e c0 ; 0xc2f91 + mov al, byte [es:si] ; 26 8a 04 ; 0xc2f93 + and AL, strict byte 06fh ; 24 6f ; 0xc2f96 vgabios.c:2077 + cmp bl, 002h ; 80 fb 02 ; 0xc2f98 vgabios.c:2079 + je short 02fa5h ; 74 08 ; 0xc2f9b + test bl, bl ; 84 db ; 0xc2f9d + jne short 02fa7h ; 75 06 ; 0xc2f9f + or AL, strict byte 080h ; 0c 80 ; 0xc2fa1 vgabios.c:2082 + jmp short 02fa7h ; eb 02 ; 0xc2fa3 vgabios.c:2083 + or AL, strict byte 010h ; 0c 10 ; 0xc2fa5 vgabios.c:2085 + mov bx, 00089h ; bb 89 00 ; 0xc2fa7 vgabios.c:52 + mov si, strict word 00040h ; be 40 00 ; 0xc2faa + mov es, si ; 8e c6 ; 0xc2fad + mov byte [es:bx], al ; 26 88 07 ; 0xc2faf + pop bp ; 5d ; 0xc2fb2 vgabios.c:2089 + pop si ; 5e ; 0xc2fb3 + pop bx ; 5b ; 0xc2fb4 + retn ; c3 ; 0xc2fb5 + ; disGetNextSymbol 0xc2fb6 LB 0x157c -> off=0x0 cb=0000000000000005 uValue=00000000000c2fb6 'biosfn_switch_video_interface' +biosfn_switch_video_interface: ; 0xc2fb6 LB 0x5 + push bp ; 55 ; 0xc2fb6 vgabios.c:2092 + mov bp, sp ; 89 e5 ; 0xc2fb7 + pop bp ; 5d ; 0xc2fb9 vgabios.c:2097 + retn ; c3 ; 0xc2fba + ; disGetNextSymbol 0xc2fbb LB 0x1577 -> off=0x0 cb=0000000000000005 uValue=00000000000c2fbb 'biosfn_enable_video_refresh_control' +biosfn_enable_video_refresh_control: ; 0xc2fbb LB 0x5 + push bp ; 55 ; 0xc2fbb vgabios.c:2098 + mov bp, sp ; 89 e5 ; 0xc2fbc + pop bp ; 5d ; 0xc2fbe vgabios.c:2103 + retn ; c3 ; 0xc2fbf + ; disGetNextSymbol 0xc2fc0 LB 0x1572 -> off=0x0 cb=000000000000009d uValue=00000000000c2fc0 'biosfn_write_string' +biosfn_write_string: ; 0xc2fc0 LB 0x9d + push bp ; 55 ; 0xc2fc0 vgabios.c:2106 + mov bp, sp ; 89 e5 ; 0xc2fc1 + push si ; 56 ; 0xc2fc3 + push di ; 57 ; 0xc2fc4 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc2fc5 + mov byte [bp-006h], al ; 88 46 fa ; 0xc2fc8 + mov byte [bp-008h], dl ; 88 56 f8 ; 0xc2fcb + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc2fce + mov si, cx ; 89 ce ; 0xc2fd1 + mov di, word [bp+00ah] ; 8b 7e 0a ; 0xc2fd3 + mov al, dl ; 88 d0 ; 0xc2fd6 vgabios.c:2113 + xor ah, ah ; 30 e4 ; 0xc2fd8 + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc2fda + lea dx, [bp-00ch] ; 8d 56 f4 ; 0xc2fdd + call 00a96h ; e8 b3 da ; 0xc2fe0 + cmp byte [bp+004h], 0ffh ; 80 7e 04 ff ; 0xc2fe3 vgabios.c:2116 + jne short 02ffah ; 75 11 ; 0xc2fe7 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2fe9 vgabios.c:2117 + mov byte [bp+006h], al ; 88 46 06 ; 0xc2fec + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc2fef vgabios.c:2118 + xor al, al ; 30 c0 ; 0xc2ff2 + shr ax, 008h ; c1 e8 08 ; 0xc2ff4 + mov byte [bp+004h], al ; 88 46 04 ; 0xc2ff7 + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc2ffa vgabios.c:2121 + xor dh, dh ; 30 f6 ; 0xc2ffd + sal dx, 008h ; c1 e2 08 ; 0xc2fff + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc3002 + xor ah, ah ; 30 e4 ; 0xc3005 + add dx, ax ; 01 c2 ; 0xc3007 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3009 vgabios.c:2122 + call 01293h ; e8 84 e2 ; 0xc300c + dec si ; 4e ; 0xc300f vgabios.c:2124 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc3010 + je short 03043h ; 74 2e ; 0xc3013 + mov bx, di ; 89 fb ; 0xc3015 vgabios.c:2126 + inc di ; 47 ; 0xc3017 + mov es, [bp+008h] ; 8e 46 08 ; 0xc3018 vgabios.c:47 + mov ah, byte [es:bx] ; 26 8a 27 ; 0xc301b + test byte [bp-006h], 002h ; f6 46 fa 02 ; 0xc301e vgabios.c:2127 + je short 0302dh ; 74 09 ; 0xc3022 + mov bx, di ; 89 fb ; 0xc3024 vgabios.c:2128 + inc di ; 47 ; 0xc3026 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3027 vgabios.c:47 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc302a vgabios.c:48 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc302d vgabios.c:2130 + xor bh, bh ; 30 ff ; 0xc3030 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc3032 + xor dh, dh ; 30 f6 ; 0xc3035 + mov al, ah ; 88 e0 ; 0xc3037 + xor ah, ah ; 30 e4 ; 0xc3039 + mov cx, strict word 00003h ; b9 03 00 ; 0xc303b + call 02a16h ; e8 d5 f9 ; 0xc303e + jmp short 0300fh ; eb cc ; 0xc3041 vgabios.c:2131 + test byte [bp-006h], 001h ; f6 46 fa 01 ; 0xc3043 vgabios.c:2134 + jne short 03054h ; 75 0b ; 0xc3047 + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc3049 vgabios.c:2135 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc304c + xor ah, ah ; 30 e4 ; 0xc304f + call 01293h ; e8 3f e2 ; 0xc3051 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3054 vgabios.c:2136 + pop di ; 5f ; 0xc3057 + pop si ; 5e ; 0xc3058 + pop bp ; 5d ; 0xc3059 + retn 00008h ; c2 08 00 ; 0xc305a + ; disGetNextSymbol 0xc305d LB 0x14d5 -> off=0x0 cb=00000000000001ef uValue=00000000000c305d 'biosfn_read_state_info' +biosfn_read_state_info: ; 0xc305d LB 0x1ef + push bp ; 55 ; 0xc305d vgabios.c:2139 + mov bp, sp ; 89 e5 ; 0xc305e + push cx ; 51 ; 0xc3060 + push si ; 56 ; 0xc3061 + push di ; 57 ; 0xc3062 + push ax ; 50 ; 0xc3063 + push ax ; 50 ; 0xc3064 + push dx ; 52 ; 0xc3065 + mov si, strict word 00049h ; be 49 00 ; 0xc3066 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3069 + mov es, ax ; 8e c0 ; 0xc306c + mov al, byte [es:si] ; 26 8a 04 ; 0xc306e + mov byte [bp-008h], al ; 88 46 f8 ; 0xc3071 vgabios.c:48 + mov si, strict word 0004ch ; be 4c 00 ; 0xc3074 vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3077 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc307a vgabios.c:58 + mov ax, ds ; 8c d8 ; 0xc307d vgabios.c:2150 + mov es, dx ; 8e c2 ; 0xc307f vgabios.c:72 + mov word [es:bx], 05503h ; 26 c7 07 03 55 ; 0xc3081 + mov [es:bx+002h], ds ; 26 8c 5f 02 ; 0xc3086 + lea di, [bx+004h] ; 8d 7f 04 ; 0xc308a vgabios.c:2155 + mov cx, strict word 0001eh ; b9 1e 00 ; 0xc308d + mov si, strict word 00049h ; be 49 00 ; 0xc3090 + mov dx, strict word 00040h ; ba 40 00 ; 0xc3093 + jcxz 0309eh ; e3 06 ; 0xc3096 + push DS ; 1e ; 0xc3098 + mov ds, dx ; 8e da ; 0xc3099 + rep movsb ; f3 a4 ; 0xc309b + pop DS ; 1f ; 0xc309d + mov si, 00084h ; be 84 00 ; 0xc309e vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc30a1 + mov es, ax ; 8e c0 ; 0xc30a4 + mov al, byte [es:si] ; 26 8a 04 ; 0xc30a6 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc30a9 vgabios.c:48 + lea si, [bx+022h] ; 8d 77 22 ; 0xc30ab + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc30ae vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc30b1 + lea di, [bx+023h] ; 8d 7f 23 ; 0xc30b4 vgabios.c:2157 + mov cx, strict word 00002h ; b9 02 00 ; 0xc30b7 + mov si, 00085h ; be 85 00 ; 0xc30ba + mov dx, strict word 00040h ; ba 40 00 ; 0xc30bd + jcxz 030c8h ; e3 06 ; 0xc30c0 + push DS ; 1e ; 0xc30c2 + mov ds, dx ; 8e da ; 0xc30c3 + rep movsb ; f3 a4 ; 0xc30c5 + pop DS ; 1f ; 0xc30c7 + mov si, 0008ah ; be 8a 00 ; 0xc30c8 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc30cb + mov es, ax ; 8e c0 ; 0xc30ce + mov al, byte [es:si] ; 26 8a 04 ; 0xc30d0 + lea si, [bx+025h] ; 8d 77 25 ; 0xc30d3 vgabios.c:48 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc30d6 vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc30d9 + lea si, [bx+026h] ; 8d 77 26 ; 0xc30dc vgabios.c:2160 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc30df vgabios.c:52 + lea si, [bx+027h] ; 8d 77 27 ; 0xc30e3 vgabios.c:2161 + mov word [es:si], strict word 00010h ; 26 c7 04 10 00 ; 0xc30e6 vgabios.c:62 + lea si, [bx+029h] ; 8d 77 29 ; 0xc30eb vgabios.c:2162 + mov byte [es:si], 008h ; 26 c6 04 08 ; 0xc30ee vgabios.c:52 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc30f2 vgabios.c:2163 + mov byte [es:si], 002h ; 26 c6 04 02 ; 0xc30f5 vgabios.c:52 + lea si, [bx+02bh] ; 8d 77 2b ; 0xc30f9 vgabios.c:2164 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc30fc vgabios.c:52 + lea si, [bx+02ch] ; 8d 77 2c ; 0xc3100 vgabios.c:2165 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc3103 vgabios.c:52 + lea si, [bx+02dh] ; 8d 77 2d ; 0xc3107 vgabios.c:2166 + mov byte [es:si], 021h ; 26 c6 04 21 ; 0xc310a vgabios.c:52 + lea si, [bx+031h] ; 8d 77 31 ; 0xc310e vgabios.c:2167 + mov byte [es:si], 003h ; 26 c6 04 03 ; 0xc3111 vgabios.c:52 + lea si, [bx+032h] ; 8d 77 32 ; 0xc3115 vgabios.c:2168 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc3118 vgabios.c:52 + mov si, 00089h ; be 89 00 ; 0xc311c vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc311f + mov es, ax ; 8e c0 ; 0xc3122 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3124 + mov dl, al ; 88 c2 ; 0xc3127 vgabios.c:2173 + and dl, 080h ; 80 e2 80 ; 0xc3129 + xor dh, dh ; 30 f6 ; 0xc312c + sar dx, 006h ; c1 fa 06 ; 0xc312e + and AL, strict byte 010h ; 24 10 ; 0xc3131 + xor ah, ah ; 30 e4 ; 0xc3133 + sar ax, 004h ; c1 f8 04 ; 0xc3135 + or ax, dx ; 09 d0 ; 0xc3138 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc313a vgabios.c:2174 + je short 03150h ; 74 11 ; 0xc313d + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc313f + je short 0314ch ; 74 08 ; 0xc3142 + test ax, ax ; 85 c0 ; 0xc3144 + jne short 03150h ; 75 08 ; 0xc3146 + mov AL, strict byte 001h ; b0 01 ; 0xc3148 vgabios.c:2175 + jmp short 03152h ; eb 06 ; 0xc314a + mov AL, strict byte 002h ; b0 02 ; 0xc314c vgabios.c:2176 + jmp short 03152h ; eb 02 ; 0xc314e + xor al, al ; 30 c0 ; 0xc3150 vgabios.c:2178 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc3152 vgabios.c:2180 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc3155 vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc3158 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc315b vgabios.c:2183 + cmp AL, strict byte 00eh ; 3c 0e ; 0xc315e + jc short 03181h ; 72 1f ; 0xc3160 + cmp AL, strict byte 012h ; 3c 12 ; 0xc3162 + jnbe short 03181h ; 77 1b ; 0xc3164 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3166 vgabios.c:2184 + test ax, ax ; 85 c0 ; 0xc3169 + je short 031c3h ; 74 56 ; 0xc316b + mov si, ax ; 89 c6 ; 0xc316d vgabios.c:2185 + shr si, 002h ; c1 ee 02 ; 0xc316f + mov ax, 04000h ; b8 00 40 ; 0xc3172 + xor dx, dx ; 31 d2 ; 0xc3175 + div si ; f7 f6 ; 0xc3177 + lea si, [bx+029h] ; 8d 77 29 ; 0xc3179 + mov byte [es:si], al ; 26 88 04 ; 0xc317c vgabios.c:52 + jmp short 031c3h ; eb 42 ; 0xc317f vgabios.c:2186 + lea si, [bx+029h] ; 8d 77 29 ; 0xc3181 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3184 + cmp AL, strict byte 013h ; 3c 13 ; 0xc3187 + jne short 0319ch ; 75 11 ; 0xc3189 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc318b vgabios.c:52 + mov byte [es:si], 001h ; 26 c6 04 01 ; 0xc318e + lea si, [bx+027h] ; 8d 77 27 ; 0xc3192 vgabios.c:2188 + mov word [es:si], 00100h ; 26 c7 04 00 01 ; 0xc3195 vgabios.c:62 + jmp short 031c3h ; eb 27 ; 0xc319a vgabios.c:2189 + cmp AL, strict byte 004h ; 3c 04 ; 0xc319c + jc short 031c3h ; 72 23 ; 0xc319e + cmp AL, strict byte 006h ; 3c 06 ; 0xc31a0 + jnbe short 031c3h ; 77 1f ; 0xc31a2 + cmp word [bp-00ah], strict byte 00000h ; 83 7e f6 00 ; 0xc31a4 vgabios.c:2191 + je short 031b8h ; 74 0e ; 0xc31a8 + mov ax, 04000h ; b8 00 40 ; 0xc31aa vgabios.c:2192 + xor dx, dx ; 31 d2 ; 0xc31ad + div word [bp-00ah] ; f7 76 f6 ; 0xc31af + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc31b2 vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc31b5 + lea si, [bx+027h] ; 8d 77 27 ; 0xc31b8 vgabios.c:2193 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc31bb vgabios.c:62 + mov word [es:si], strict word 00004h ; 26 c7 04 04 00 ; 0xc31be + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc31c3 vgabios.c:2195 + cmp AL, strict byte 006h ; 3c 06 ; 0xc31c6 + je short 031ceh ; 74 04 ; 0xc31c8 + cmp AL, strict byte 011h ; 3c 11 ; 0xc31ca + jne short 031d9h ; 75 0b ; 0xc31cc + lea si, [bx+027h] ; 8d 77 27 ; 0xc31ce vgabios.c:2196 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc31d1 vgabios.c:62 + mov word [es:si], strict word 00002h ; 26 c7 04 02 00 ; 0xc31d4 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc31d9 vgabios.c:2198 + cmp AL, strict byte 004h ; 3c 04 ; 0xc31dc + jc short 03235h ; 72 55 ; 0xc31de + cmp AL, strict byte 007h ; 3c 07 ; 0xc31e0 + je short 03235h ; 74 51 ; 0xc31e2 + lea si, [bx+02dh] ; 8d 77 2d ; 0xc31e4 vgabios.c:2199 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc31e7 vgabios.c:52 + mov byte [es:si], 001h ; 26 c6 04 01 ; 0xc31ea + mov si, 00084h ; be 84 00 ; 0xc31ee vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc31f1 + mov es, ax ; 8e c0 ; 0xc31f4 + mov al, byte [es:si] ; 26 8a 04 ; 0xc31f6 + xor ah, ah ; 30 e4 ; 0xc31f9 vgabios.c:48 + inc ax ; 40 ; 0xc31fb + mov si, 00085h ; be 85 00 ; 0xc31fc vgabios.c:47 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc31ff + xor dh, dh ; 30 f6 ; 0xc3202 vgabios.c:48 + imul dx ; f7 ea ; 0xc3204 + cmp ax, 0015eh ; 3d 5e 01 ; 0xc3206 vgabios.c:2201 + jc short 03219h ; 72 0e ; 0xc3209 + jbe short 03222h ; 76 15 ; 0xc320b + cmp ax, 001e0h ; 3d e0 01 ; 0xc320d + je short 0322ah ; 74 18 ; 0xc3210 + cmp ax, 00190h ; 3d 90 01 ; 0xc3212 + je short 03226h ; 74 0f ; 0xc3215 + jmp short 0322ah ; eb 11 ; 0xc3217 + cmp ax, 000c8h ; 3d c8 00 ; 0xc3219 + jne short 0322ah ; 75 0c ; 0xc321c + xor al, al ; 30 c0 ; 0xc321e vgabios.c:2202 + jmp short 0322ch ; eb 0a ; 0xc3220 + mov AL, strict byte 001h ; b0 01 ; 0xc3222 vgabios.c:2203 + jmp short 0322ch ; eb 06 ; 0xc3224 + mov AL, strict byte 002h ; b0 02 ; 0xc3226 vgabios.c:2204 + jmp short 0322ch ; eb 02 ; 0xc3228 + mov AL, strict byte 003h ; b0 03 ; 0xc322a vgabios.c:2206 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc322c vgabios.c:2208 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc322f vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc3232 + lea di, [bx+033h] ; 8d 7f 33 ; 0xc3235 vgabios.c:2211 + mov cx, strict word 0000dh ; b9 0d 00 ; 0xc3238 + xor ax, ax ; 31 c0 ; 0xc323b + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc323d + jcxz 03244h ; e3 02 ; 0xc3240 + rep stosb ; f3 aa ; 0xc3242 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc3244 vgabios.c:2212 + pop di ; 5f ; 0xc3247 + pop si ; 5e ; 0xc3248 + pop cx ; 59 ; 0xc3249 + pop bp ; 5d ; 0xc324a + retn ; c3 ; 0xc324b + ; disGetNextSymbol 0xc324c LB 0x12e6 -> off=0x0 cb=0000000000000023 uValue=00000000000c324c 'biosfn_read_video_state_size2' +biosfn_read_video_state_size2: ; 0xc324c LB 0x23 + push dx ; 52 ; 0xc324c vgabios.c:2215 + push bp ; 55 ; 0xc324d + mov bp, sp ; 89 e5 ; 0xc324e + mov dx, ax ; 89 c2 ; 0xc3250 + xor ax, ax ; 31 c0 ; 0xc3252 vgabios.c:2219 + test dl, 001h ; f6 c2 01 ; 0xc3254 vgabios.c:2220 + je short 0325ch ; 74 03 ; 0xc3257 + mov ax, strict word 00046h ; b8 46 00 ; 0xc3259 vgabios.c:2221 + test dl, 002h ; f6 c2 02 ; 0xc325c vgabios.c:2223 + je short 03264h ; 74 03 ; 0xc325f + add ax, strict word 0002ah ; 05 2a 00 ; 0xc3261 vgabios.c:2224 + test dl, 004h ; f6 c2 04 ; 0xc3264 vgabios.c:2226 + je short 0326ch ; 74 03 ; 0xc3267 + add ax, 00304h ; 05 04 03 ; 0xc3269 vgabios.c:2227 + pop bp ; 5d ; 0xc326c vgabios.c:2230 + pop dx ; 5a ; 0xc326d + retn ; c3 ; 0xc326e + ; disGetNextSymbol 0xc326f LB 0x12c3 -> off=0x0 cb=0000000000000018 uValue=00000000000c326f 'vga_get_video_state_size' +vga_get_video_state_size: ; 0xc326f LB 0x18 + push bp ; 55 ; 0xc326f vgabios.c:2232 + mov bp, sp ; 89 e5 ; 0xc3270 + push bx ; 53 ; 0xc3272 + mov bx, dx ; 89 d3 ; 0xc3273 + call 0324ch ; e8 d4 ff ; 0xc3275 vgabios.c:2235 + add ax, strict word 0003fh ; 05 3f 00 ; 0xc3278 + shr ax, 006h ; c1 e8 06 ; 0xc327b + mov word [ss:bx], ax ; 36 89 07 ; 0xc327e + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3281 vgabios.c:2236 + pop bx ; 5b ; 0xc3284 + pop bp ; 5d ; 0xc3285 + retn ; c3 ; 0xc3286 + ; disGetNextSymbol 0xc3287 LB 0x12ab -> off=0x0 cb=00000000000002d8 uValue=00000000000c3287 'biosfn_save_video_state' +biosfn_save_video_state: ; 0xc3287 LB 0x2d8 + push bp ; 55 ; 0xc3287 vgabios.c:2238 + mov bp, sp ; 89 e5 ; 0xc3288 + push cx ; 51 ; 0xc328a + push si ; 56 ; 0xc328b + push di ; 57 ; 0xc328c + push ax ; 50 ; 0xc328d + push ax ; 50 ; 0xc328e + push ax ; 50 ; 0xc328f + mov cx, dx ; 89 d1 ; 0xc3290 + mov si, strict word 00063h ; be 63 00 ; 0xc3292 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3295 + mov es, ax ; 8e c0 ; 0xc3298 + mov di, word [es:si] ; 26 8b 3c ; 0xc329a + mov si, di ; 89 fe ; 0xc329d vgabios.c:58 + test byte [bp-00ch], 001h ; f6 46 f4 01 ; 0xc329f vgabios.c:2243 + je short 0330bh ; 74 66 ; 0xc32a3 + mov dx, 003c4h ; ba c4 03 ; 0xc32a5 vgabios.c:2244 + in AL, DX ; ec ; 0xc32a8 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32a9 + mov es, cx ; 8e c1 ; 0xc32ab vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc32ad + inc bx ; 43 ; 0xc32b0 vgabios.c:2244 + mov dx, di ; 89 fa ; 0xc32b1 + in AL, DX ; ec ; 0xc32b3 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32b4 + mov byte [es:bx], al ; 26 88 07 ; 0xc32b6 vgabios.c:52 + inc bx ; 43 ; 0xc32b9 vgabios.c:2245 + mov dx, 003ceh ; ba ce 03 ; 0xc32ba + in AL, DX ; ec ; 0xc32bd + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32be + mov byte [es:bx], al ; 26 88 07 ; 0xc32c0 vgabios.c:52 + inc bx ; 43 ; 0xc32c3 vgabios.c:2246 + mov dx, 003dah ; ba da 03 ; 0xc32c4 + in AL, DX ; ec ; 0xc32c7 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32c8 + mov dx, 003c0h ; ba c0 03 ; 0xc32ca vgabios.c:2248 + in AL, DX ; ec ; 0xc32cd + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32ce + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc32d0 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc32d3 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc32d6 + inc bx ; 43 ; 0xc32d9 vgabios.c:2249 + mov dx, 003cah ; ba ca 03 ; 0xc32da + in AL, DX ; ec ; 0xc32dd + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32de + mov byte [es:bx], al ; 26 88 07 ; 0xc32e0 vgabios.c:52 + mov ax, strict word 00001h ; b8 01 00 ; 0xc32e3 vgabios.c:2252 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc32e6 + add bx, ax ; 01 c3 ; 0xc32e9 vgabios.c:2250 + jmp short 032f3h ; eb 06 ; 0xc32eb + cmp word [bp-008h], strict byte 00004h ; 83 7e f8 04 ; 0xc32ed + jnbe short 0330eh ; 77 1b ; 0xc32f1 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc32f3 vgabios.c:2253 + mov dx, 003c4h ; ba c4 03 ; 0xc32f6 + out DX, AL ; ee ; 0xc32f9 + mov dx, 003c5h ; ba c5 03 ; 0xc32fa vgabios.c:2254 + in AL, DX ; ec ; 0xc32fd + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32fe + mov es, cx ; 8e c1 ; 0xc3300 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3302 + inc bx ; 43 ; 0xc3305 vgabios.c:2254 + inc word [bp-008h] ; ff 46 f8 ; 0xc3306 vgabios.c:2255 + jmp short 032edh ; eb e2 ; 0xc3309 + jmp near 033bbh ; e9 ad 00 ; 0xc330b + xor al, al ; 30 c0 ; 0xc330e vgabios.c:2256 + mov dx, 003c4h ; ba c4 03 ; 0xc3310 + out DX, AL ; ee ; 0xc3313 + mov dx, 003c5h ; ba c5 03 ; 0xc3314 vgabios.c:2257 + in AL, DX ; ec ; 0xc3317 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3318 + mov es, cx ; 8e c1 ; 0xc331a vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc331c + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc331f vgabios.c:2259 + inc bx ; 43 ; 0xc3324 vgabios.c:2257 + jmp short 0332dh ; eb 06 ; 0xc3325 + cmp word [bp-008h], strict byte 00018h ; 83 7e f8 18 ; 0xc3327 + jnbe short 03344h ; 77 17 ; 0xc332b + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc332d vgabios.c:2260 + mov dx, si ; 89 f2 ; 0xc3330 + out DX, AL ; ee ; 0xc3332 + lea dx, [si+001h] ; 8d 54 01 ; 0xc3333 vgabios.c:2261 + in AL, DX ; ec ; 0xc3336 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3337 + mov es, cx ; 8e c1 ; 0xc3339 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc333b + inc bx ; 43 ; 0xc333e vgabios.c:2261 + inc word [bp-008h] ; ff 46 f8 ; 0xc333f vgabios.c:2262 + jmp short 03327h ; eb e3 ; 0xc3342 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc3344 vgabios.c:2264 + jmp short 03351h ; eb 06 ; 0xc3349 + cmp word [bp-008h], strict byte 00013h ; 83 7e f8 13 ; 0xc334b + jnbe short 03375h ; 77 24 ; 0xc334f + mov dx, 003dah ; ba da 03 ; 0xc3351 vgabios.c:2265 + in AL, DX ; ec ; 0xc3354 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3355 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3357 vgabios.c:2266 + and ax, strict word 00020h ; 25 20 00 ; 0xc335a + or ax, word [bp-008h] ; 0b 46 f8 ; 0xc335d + mov dx, 003c0h ; ba c0 03 ; 0xc3360 + out DX, AL ; ee ; 0xc3363 + mov dx, 003c1h ; ba c1 03 ; 0xc3364 vgabios.c:2267 + in AL, DX ; ec ; 0xc3367 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3368 + mov es, cx ; 8e c1 ; 0xc336a vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc336c + inc bx ; 43 ; 0xc336f vgabios.c:2267 + inc word [bp-008h] ; ff 46 f8 ; 0xc3370 vgabios.c:2268 + jmp short 0334bh ; eb d6 ; 0xc3373 + mov dx, 003dah ; ba da 03 ; 0xc3375 vgabios.c:2269 + in AL, DX ; ec ; 0xc3378 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3379 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc337b vgabios.c:2271 + jmp short 03388h ; eb 06 ; 0xc3380 + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc3382 + jnbe short 033a0h ; 77 18 ; 0xc3386 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3388 vgabios.c:2272 + mov dx, 003ceh ; ba ce 03 ; 0xc338b + out DX, AL ; ee ; 0xc338e + mov dx, 003cfh ; ba cf 03 ; 0xc338f vgabios.c:2273 + in AL, DX ; ec ; 0xc3392 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3393 + mov es, cx ; 8e c1 ; 0xc3395 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3397 + inc bx ; 43 ; 0xc339a vgabios.c:2273 + inc word [bp-008h] ; ff 46 f8 ; 0xc339b vgabios.c:2274 + jmp short 03382h ; eb e2 ; 0xc339e + mov es, cx ; 8e c1 ; 0xc33a0 vgabios.c:62 + mov word [es:bx], si ; 26 89 37 ; 0xc33a2 + inc bx ; 43 ; 0xc33a5 vgabios.c:2276 + inc bx ; 43 ; 0xc33a6 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc33a7 vgabios.c:52 + inc bx ; 43 ; 0xc33ab vgabios.c:2279 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc33ac vgabios.c:52 + inc bx ; 43 ; 0xc33b0 vgabios.c:2280 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc33b1 vgabios.c:52 + inc bx ; 43 ; 0xc33b5 vgabios.c:2281 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc33b6 vgabios.c:52 + inc bx ; 43 ; 0xc33ba vgabios.c:2282 + test byte [bp-00ch], 002h ; f6 46 f4 02 ; 0xc33bb vgabios.c:2284 + jne short 033c4h ; 75 03 ; 0xc33bf + jmp near 03503h ; e9 3f 01 ; 0xc33c1 + mov si, strict word 00049h ; be 49 00 ; 0xc33c4 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc33c7 + mov es, ax ; 8e c0 ; 0xc33ca + mov al, byte [es:si] ; 26 8a 04 ; 0xc33cc + mov es, cx ; 8e c1 ; 0xc33cf vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc33d1 + inc bx ; 43 ; 0xc33d4 vgabios.c:2285 + mov si, strict word 0004ah ; be 4a 00 ; 0xc33d5 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc33d8 + mov es, ax ; 8e c0 ; 0xc33db + mov ax, word [es:si] ; 26 8b 04 ; 0xc33dd + mov es, cx ; 8e c1 ; 0xc33e0 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc33e2 + inc bx ; 43 ; 0xc33e5 vgabios.c:2286 + inc bx ; 43 ; 0xc33e6 + mov si, strict word 0004ch ; be 4c 00 ; 0xc33e7 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc33ea + mov es, ax ; 8e c0 ; 0xc33ed + mov ax, word [es:si] ; 26 8b 04 ; 0xc33ef + mov es, cx ; 8e c1 ; 0xc33f2 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc33f4 + inc bx ; 43 ; 0xc33f7 vgabios.c:2287 + inc bx ; 43 ; 0xc33f8 + mov si, strict word 00063h ; be 63 00 ; 0xc33f9 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc33fc + mov es, ax ; 8e c0 ; 0xc33ff + mov ax, word [es:si] ; 26 8b 04 ; 0xc3401 + mov es, cx ; 8e c1 ; 0xc3404 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3406 + inc bx ; 43 ; 0xc3409 vgabios.c:2288 + inc bx ; 43 ; 0xc340a + mov si, 00084h ; be 84 00 ; 0xc340b vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc340e + mov es, ax ; 8e c0 ; 0xc3411 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3413 + mov es, cx ; 8e c1 ; 0xc3416 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3418 + inc bx ; 43 ; 0xc341b vgabios.c:2289 + mov si, 00085h ; be 85 00 ; 0xc341c vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc341f + mov es, ax ; 8e c0 ; 0xc3422 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3424 + mov es, cx ; 8e c1 ; 0xc3427 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3429 + inc bx ; 43 ; 0xc342c vgabios.c:2290 + inc bx ; 43 ; 0xc342d + mov si, 00087h ; be 87 00 ; 0xc342e vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3431 + mov es, ax ; 8e c0 ; 0xc3434 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3436 + mov es, cx ; 8e c1 ; 0xc3439 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc343b + inc bx ; 43 ; 0xc343e vgabios.c:2291 + mov si, 00088h ; be 88 00 ; 0xc343f vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3442 + mov es, ax ; 8e c0 ; 0xc3445 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3447 + mov es, cx ; 8e c1 ; 0xc344a vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc344c + inc bx ; 43 ; 0xc344f vgabios.c:2292 + mov si, 00089h ; be 89 00 ; 0xc3450 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3453 + mov es, ax ; 8e c0 ; 0xc3456 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3458 + mov es, cx ; 8e c1 ; 0xc345b vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc345d + inc bx ; 43 ; 0xc3460 vgabios.c:2293 + mov si, strict word 00060h ; be 60 00 ; 0xc3461 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3464 + mov es, ax ; 8e c0 ; 0xc3467 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3469 + mov es, cx ; 8e c1 ; 0xc346c vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc346e + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc3471 vgabios.c:2295 + inc bx ; 43 ; 0xc3476 vgabios.c:2294 + inc bx ; 43 ; 0xc3477 + jmp short 03480h ; eb 06 ; 0xc3478 + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc347a + jnc short 0349ch ; 73 1c ; 0xc347e + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc3480 vgabios.c:2296 + add si, si ; 01 f6 ; 0xc3483 + add si, strict byte 00050h ; 83 c6 50 ; 0xc3485 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3488 vgabios.c:57 + mov es, ax ; 8e c0 ; 0xc348b + mov ax, word [es:si] ; 26 8b 04 ; 0xc348d + mov es, cx ; 8e c1 ; 0xc3490 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3492 + inc bx ; 43 ; 0xc3495 vgabios.c:2297 + inc bx ; 43 ; 0xc3496 + inc word [bp-008h] ; ff 46 f8 ; 0xc3497 vgabios.c:2298 + jmp short 0347ah ; eb de ; 0xc349a + mov si, strict word 0004eh ; be 4e 00 ; 0xc349c vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc349f + mov es, ax ; 8e c0 ; 0xc34a2 + mov ax, word [es:si] ; 26 8b 04 ; 0xc34a4 + mov es, cx ; 8e c1 ; 0xc34a7 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc34a9 + inc bx ; 43 ; 0xc34ac vgabios.c:2299 + inc bx ; 43 ; 0xc34ad + mov si, strict word 00062h ; be 62 00 ; 0xc34ae vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc34b1 + mov es, ax ; 8e c0 ; 0xc34b4 + mov al, byte [es:si] ; 26 8a 04 ; 0xc34b6 + mov es, cx ; 8e c1 ; 0xc34b9 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc34bb + inc bx ; 43 ; 0xc34be vgabios.c:2300 + mov si, strict word 0007ch ; be 7c 00 ; 0xc34bf vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc34c2 + mov es, ax ; 8e c0 ; 0xc34c4 + mov ax, word [es:si] ; 26 8b 04 ; 0xc34c6 + mov es, cx ; 8e c1 ; 0xc34c9 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc34cb + inc bx ; 43 ; 0xc34ce vgabios.c:2302 + inc bx ; 43 ; 0xc34cf + mov si, strict word 0007eh ; be 7e 00 ; 0xc34d0 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc34d3 + mov es, ax ; 8e c0 ; 0xc34d5 + mov ax, word [es:si] ; 26 8b 04 ; 0xc34d7 + mov es, cx ; 8e c1 ; 0xc34da vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc34dc + inc bx ; 43 ; 0xc34df vgabios.c:2303 + inc bx ; 43 ; 0xc34e0 + mov si, 0010ch ; be 0c 01 ; 0xc34e1 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc34e4 + mov es, ax ; 8e c0 ; 0xc34e6 + mov ax, word [es:si] ; 26 8b 04 ; 0xc34e8 + mov es, cx ; 8e c1 ; 0xc34eb vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc34ed + inc bx ; 43 ; 0xc34f0 vgabios.c:2304 + inc bx ; 43 ; 0xc34f1 + mov si, 0010eh ; be 0e 01 ; 0xc34f2 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc34f5 + mov es, ax ; 8e c0 ; 0xc34f7 + mov ax, word [es:si] ; 26 8b 04 ; 0xc34f9 + mov es, cx ; 8e c1 ; 0xc34fc vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc34fe + inc bx ; 43 ; 0xc3501 vgabios.c:2305 + inc bx ; 43 ; 0xc3502 + test byte [bp-00ch], 004h ; f6 46 f4 04 ; 0xc3503 vgabios.c:2307 + je short 03555h ; 74 4c ; 0xc3507 + mov dx, 003c7h ; ba c7 03 ; 0xc3509 vgabios.c:2309 + in AL, DX ; ec ; 0xc350c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc350d + mov es, cx ; 8e c1 ; 0xc350f vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3511 + inc bx ; 43 ; 0xc3514 vgabios.c:2309 + mov dx, 003c8h ; ba c8 03 ; 0xc3515 + in AL, DX ; ec ; 0xc3518 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3519 + mov byte [es:bx], al ; 26 88 07 ; 0xc351b vgabios.c:52 + inc bx ; 43 ; 0xc351e vgabios.c:2310 + mov dx, 003c6h ; ba c6 03 ; 0xc351f + in AL, DX ; ec ; 0xc3522 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3523 + mov byte [es:bx], al ; 26 88 07 ; 0xc3525 vgabios.c:52 + inc bx ; 43 ; 0xc3528 vgabios.c:2311 + xor al, al ; 30 c0 ; 0xc3529 + mov dx, 003c8h ; ba c8 03 ; 0xc352b + out DX, AL ; ee ; 0xc352e + xor ah, ah ; 30 e4 ; 0xc352f vgabios.c:2314 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc3531 + jmp short 0353dh ; eb 07 ; 0xc3534 + cmp word [bp-008h], 00300h ; 81 7e f8 00 03 ; 0xc3536 + jnc short 0354eh ; 73 11 ; 0xc353b + mov dx, 003c9h ; ba c9 03 ; 0xc353d vgabios.c:2315 + in AL, DX ; ec ; 0xc3540 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3541 + mov es, cx ; 8e c1 ; 0xc3543 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3545 + inc bx ; 43 ; 0xc3548 vgabios.c:2315 + inc word [bp-008h] ; ff 46 f8 ; 0xc3549 vgabios.c:2316 + jmp short 03536h ; eb e8 ; 0xc354c + mov es, cx ; 8e c1 ; 0xc354e vgabios.c:52 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc3550 + inc bx ; 43 ; 0xc3554 vgabios.c:2317 + mov ax, bx ; 89 d8 ; 0xc3555 vgabios.c:2320 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc3557 + pop di ; 5f ; 0xc355a + pop si ; 5e ; 0xc355b + pop cx ; 59 ; 0xc355c + pop bp ; 5d ; 0xc355d + retn ; c3 ; 0xc355e + ; disGetNextSymbol 0xc355f LB 0xfd3 -> off=0x0 cb=00000000000002ba uValue=00000000000c355f 'biosfn_restore_video_state' +biosfn_restore_video_state: ; 0xc355f LB 0x2ba + push bp ; 55 ; 0xc355f vgabios.c:2322 + mov bp, sp ; 89 e5 ; 0xc3560 + push cx ; 51 ; 0xc3562 + push si ; 56 ; 0xc3563 + push di ; 57 ; 0xc3564 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc3565 + push ax ; 50 ; 0xc3568 + mov cx, dx ; 89 d1 ; 0xc3569 + test byte [bp-010h], 001h ; f6 46 f0 01 ; 0xc356b vgabios.c:2326 + je short 035e5h ; 74 74 ; 0xc356f + mov dx, 003dah ; ba da 03 ; 0xc3571 vgabios.c:2328 + in AL, DX ; ec ; 0xc3574 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3575 + lea si, [bx+040h] ; 8d 77 40 ; 0xc3577 vgabios.c:2330 + mov es, cx ; 8e c1 ; 0xc357a vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc357c + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc357f vgabios.c:58 + mov si, bx ; 89 de ; 0xc3582 vgabios.c:2331 + mov word [bp-008h], strict word 00001h ; c7 46 f8 01 00 ; 0xc3584 vgabios.c:2334 + add bx, strict byte 00005h ; 83 c3 05 ; 0xc3589 vgabios.c:2332 + jmp short 03594h ; eb 06 ; 0xc358c + cmp word [bp-008h], strict byte 00004h ; 83 7e f8 04 ; 0xc358e + jnbe short 035aah ; 77 16 ; 0xc3592 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3594 vgabios.c:2335 + mov dx, 003c4h ; ba c4 03 ; 0xc3597 + out DX, AL ; ee ; 0xc359a + mov es, cx ; 8e c1 ; 0xc359b vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc359d + mov dx, 003c5h ; ba c5 03 ; 0xc35a0 vgabios.c:48 + out DX, AL ; ee ; 0xc35a3 + inc bx ; 43 ; 0xc35a4 vgabios.c:2336 + inc word [bp-008h] ; ff 46 f8 ; 0xc35a5 vgabios.c:2337 + jmp short 0358eh ; eb e4 ; 0xc35a8 + xor al, al ; 30 c0 ; 0xc35aa vgabios.c:2338 + mov dx, 003c4h ; ba c4 03 ; 0xc35ac + out DX, AL ; ee ; 0xc35af + mov es, cx ; 8e c1 ; 0xc35b0 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc35b2 + mov dx, 003c5h ; ba c5 03 ; 0xc35b5 vgabios.c:48 + out DX, AL ; ee ; 0xc35b8 + inc bx ; 43 ; 0xc35b9 vgabios.c:2339 + mov dx, 003cch ; ba cc 03 ; 0xc35ba + in AL, DX ; ec ; 0xc35bd + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc35be + and AL, strict byte 0feh ; 24 fe ; 0xc35c0 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc35c2 + cmp word [bp-00ch], 003d4h ; 81 7e f4 d4 03 ; 0xc35c5 vgabios.c:2343 + jne short 035d0h ; 75 04 ; 0xc35ca + or byte [bp-00eh], 001h ; 80 4e f2 01 ; 0xc35cc vgabios.c:2344 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc35d0 vgabios.c:2345 + mov dx, 003c2h ; ba c2 03 ; 0xc35d3 + out DX, AL ; ee ; 0xc35d6 + mov ax, strict word 00011h ; b8 11 00 ; 0xc35d7 vgabios.c:2348 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc35da + out DX, ax ; ef ; 0xc35dd + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc35de vgabios.c:2350 + jmp short 035eeh ; eb 09 ; 0xc35e3 + jmp near 036a8h ; e9 c0 00 ; 0xc35e5 + cmp word [bp-008h], strict byte 00018h ; 83 7e f8 18 ; 0xc35e8 + jnbe short 03608h ; 77 1a ; 0xc35ec + cmp word [bp-008h], strict byte 00011h ; 83 7e f8 11 ; 0xc35ee vgabios.c:2351 + je short 03602h ; 74 0e ; 0xc35f2 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc35f4 vgabios.c:2352 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc35f7 + out DX, AL ; ee ; 0xc35fa + mov es, cx ; 8e c1 ; 0xc35fb vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc35fd + inc dx ; 42 ; 0xc3600 vgabios.c:48 + out DX, AL ; ee ; 0xc3601 + inc bx ; 43 ; 0xc3602 vgabios.c:2355 + inc word [bp-008h] ; ff 46 f8 ; 0xc3603 vgabios.c:2356 + jmp short 035e8h ; eb e0 ; 0xc3606 + mov AL, strict byte 011h ; b0 11 ; 0xc3608 vgabios.c:2358 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc360a + out DX, AL ; ee ; 0xc360d + lea di, [word bx-00007h] ; 8d bf f9 ff ; 0xc360e vgabios.c:2359 + mov es, cx ; 8e c1 ; 0xc3612 vgabios.c:47 + mov al, byte [es:di] ; 26 8a 05 ; 0xc3614 + inc dx ; 42 ; 0xc3617 vgabios.c:48 + out DX, AL ; ee ; 0xc3618 + lea di, [si+003h] ; 8d 7c 03 ; 0xc3619 vgabios.c:2362 + mov dl, byte [es:di] ; 26 8a 15 ; 0xc361c vgabios.c:47 + xor dh, dh ; 30 f6 ; 0xc361f vgabios.c:48 + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc3621 + mov dx, 003dah ; ba da 03 ; 0xc3624 vgabios.c:2363 + in AL, DX ; ec ; 0xc3627 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3628 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc362a vgabios.c:2364 + jmp short 03637h ; eb 06 ; 0xc362f + cmp word [bp-008h], strict byte 00013h ; 83 7e f8 13 ; 0xc3631 + jnbe short 03650h ; 77 19 ; 0xc3635 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3637 vgabios.c:2365 + and ax, strict word 00020h ; 25 20 00 ; 0xc363a + or ax, word [bp-008h] ; 0b 46 f8 ; 0xc363d + mov dx, 003c0h ; ba c0 03 ; 0xc3640 + out DX, AL ; ee ; 0xc3643 + mov es, cx ; 8e c1 ; 0xc3644 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3646 + out DX, AL ; ee ; 0xc3649 vgabios.c:48 + inc bx ; 43 ; 0xc364a vgabios.c:2366 + inc word [bp-008h] ; ff 46 f8 ; 0xc364b vgabios.c:2367 + jmp short 03631h ; eb e1 ; 0xc364e + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc3650 vgabios.c:2368 + mov dx, 003c0h ; ba c0 03 ; 0xc3653 + out DX, AL ; ee ; 0xc3656 + mov dx, 003dah ; ba da 03 ; 0xc3657 vgabios.c:2369 + in AL, DX ; ec ; 0xc365a + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc365b + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc365d vgabios.c:2371 + jmp short 0366ah ; eb 06 ; 0xc3662 + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc3664 + jnbe short 03680h ; 77 16 ; 0xc3668 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc366a vgabios.c:2372 + mov dx, 003ceh ; ba ce 03 ; 0xc366d + out DX, AL ; ee ; 0xc3670 + mov es, cx ; 8e c1 ; 0xc3671 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3673 + mov dx, 003cfh ; ba cf 03 ; 0xc3676 vgabios.c:48 + out DX, AL ; ee ; 0xc3679 + inc bx ; 43 ; 0xc367a vgabios.c:2373 + inc word [bp-008h] ; ff 46 f8 ; 0xc367b vgabios.c:2374 + jmp short 03664h ; eb e4 ; 0xc367e + add bx, strict byte 00006h ; 83 c3 06 ; 0xc3680 vgabios.c:2375 + mov es, cx ; 8e c1 ; 0xc3683 vgabios.c:47 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3685 + mov dx, 003c4h ; ba c4 03 ; 0xc3688 vgabios.c:48 + out DX, AL ; ee ; 0xc368b + inc si ; 46 ; 0xc368c vgabios.c:2378 + mov al, byte [es:si] ; 26 8a 04 ; 0xc368d vgabios.c:47 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc3690 vgabios.c:48 + out DX, AL ; ee ; 0xc3693 + inc si ; 46 ; 0xc3694 vgabios.c:2379 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3695 vgabios.c:47 + mov dx, 003ceh ; ba ce 03 ; 0xc3698 vgabios.c:48 + out DX, AL ; ee ; 0xc369b + inc si ; 46 ; 0xc369c vgabios.c:2380 + inc si ; 46 ; 0xc369d + mov al, byte [es:si] ; 26 8a 04 ; 0xc369e vgabios.c:47 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc36a1 vgabios.c:48 + add dx, strict byte 00006h ; 83 c2 06 ; 0xc36a4 + out DX, AL ; ee ; 0xc36a7 + test byte [bp-010h], 002h ; f6 46 f0 02 ; 0xc36a8 vgabios.c:2384 + jne short 036b1h ; 75 03 ; 0xc36ac + jmp near 037cch ; e9 1b 01 ; 0xc36ae + mov es, cx ; 8e c1 ; 0xc36b1 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc36b3 + mov si, strict word 00049h ; be 49 00 ; 0xc36b6 vgabios.c:52 + mov dx, strict word 00040h ; ba 40 00 ; 0xc36b9 + mov es, dx ; 8e c2 ; 0xc36bc + mov byte [es:si], al ; 26 88 04 ; 0xc36be + inc bx ; 43 ; 0xc36c1 vgabios.c:2385 + mov es, cx ; 8e c1 ; 0xc36c2 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc36c4 + mov si, strict word 0004ah ; be 4a 00 ; 0xc36c7 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc36ca + mov word [es:si], ax ; 26 89 04 ; 0xc36cc + inc bx ; 43 ; 0xc36cf vgabios.c:2386 + inc bx ; 43 ; 0xc36d0 + mov es, cx ; 8e c1 ; 0xc36d1 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc36d3 + mov si, strict word 0004ch ; be 4c 00 ; 0xc36d6 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc36d9 + mov word [es:si], ax ; 26 89 04 ; 0xc36db + inc bx ; 43 ; 0xc36de vgabios.c:2387 + inc bx ; 43 ; 0xc36df + mov es, cx ; 8e c1 ; 0xc36e0 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc36e2 + mov si, strict word 00063h ; be 63 00 ; 0xc36e5 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc36e8 + mov word [es:si], ax ; 26 89 04 ; 0xc36ea + inc bx ; 43 ; 0xc36ed vgabios.c:2388 + inc bx ; 43 ; 0xc36ee + mov es, cx ; 8e c1 ; 0xc36ef vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc36f1 + mov si, 00084h ; be 84 00 ; 0xc36f4 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc36f7 + mov byte [es:si], al ; 26 88 04 ; 0xc36f9 + inc bx ; 43 ; 0xc36fc vgabios.c:2389 + mov es, cx ; 8e c1 ; 0xc36fd vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc36ff + mov si, 00085h ; be 85 00 ; 0xc3702 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3705 + mov word [es:si], ax ; 26 89 04 ; 0xc3707 + inc bx ; 43 ; 0xc370a vgabios.c:2390 + inc bx ; 43 ; 0xc370b + mov es, cx ; 8e c1 ; 0xc370c vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc370e + mov si, 00087h ; be 87 00 ; 0xc3711 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc3714 + mov byte [es:si], al ; 26 88 04 ; 0xc3716 + inc bx ; 43 ; 0xc3719 vgabios.c:2391 + mov es, cx ; 8e c1 ; 0xc371a vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc371c + mov si, 00088h ; be 88 00 ; 0xc371f vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc3722 + mov byte [es:si], al ; 26 88 04 ; 0xc3724 + inc bx ; 43 ; 0xc3727 vgabios.c:2392 + mov es, cx ; 8e c1 ; 0xc3728 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc372a + mov si, 00089h ; be 89 00 ; 0xc372d vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc3730 + mov byte [es:si], al ; 26 88 04 ; 0xc3732 + inc bx ; 43 ; 0xc3735 vgabios.c:2393 + mov es, cx ; 8e c1 ; 0xc3736 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3738 + mov si, strict word 00060h ; be 60 00 ; 0xc373b vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc373e + mov word [es:si], ax ; 26 89 04 ; 0xc3740 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc3743 vgabios.c:2395 + inc bx ; 43 ; 0xc3748 vgabios.c:2394 + inc bx ; 43 ; 0xc3749 + jmp short 03752h ; eb 06 ; 0xc374a + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc374c + jnc short 0376eh ; 73 1c ; 0xc3750 + mov es, cx ; 8e c1 ; 0xc3752 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3754 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc3757 vgabios.c:58 + add si, si ; 01 f6 ; 0xc375a + add si, strict byte 00050h ; 83 c6 50 ; 0xc375c + mov dx, strict word 00040h ; ba 40 00 ; 0xc375f vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3762 + mov word [es:si], ax ; 26 89 04 ; 0xc3764 + inc bx ; 43 ; 0xc3767 vgabios.c:2397 + inc bx ; 43 ; 0xc3768 + inc word [bp-008h] ; ff 46 f8 ; 0xc3769 vgabios.c:2398 + jmp short 0374ch ; eb de ; 0xc376c + mov es, cx ; 8e c1 ; 0xc376e vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3770 + mov si, strict word 0004eh ; be 4e 00 ; 0xc3773 vgabios.c:62 + mov dx, strict word 00040h ; ba 40 00 ; 0xc3776 + mov es, dx ; 8e c2 ; 0xc3779 + mov word [es:si], ax ; 26 89 04 ; 0xc377b + inc bx ; 43 ; 0xc377e vgabios.c:2399 + inc bx ; 43 ; 0xc377f + mov es, cx ; 8e c1 ; 0xc3780 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3782 + mov si, strict word 00062h ; be 62 00 ; 0xc3785 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc3788 + mov byte [es:si], al ; 26 88 04 ; 0xc378a + inc bx ; 43 ; 0xc378d vgabios.c:2400 + mov es, cx ; 8e c1 ; 0xc378e vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3790 + mov si, strict word 0007ch ; be 7c 00 ; 0xc3793 vgabios.c:62 + xor dx, dx ; 31 d2 ; 0xc3796 + mov es, dx ; 8e c2 ; 0xc3798 + mov word [es:si], ax ; 26 89 04 ; 0xc379a + inc bx ; 43 ; 0xc379d vgabios.c:2402 + inc bx ; 43 ; 0xc379e + mov es, cx ; 8e c1 ; 0xc379f vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc37a1 + mov si, strict word 0007eh ; be 7e 00 ; 0xc37a4 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc37a7 + mov word [es:si], ax ; 26 89 04 ; 0xc37a9 + inc bx ; 43 ; 0xc37ac vgabios.c:2403 + inc bx ; 43 ; 0xc37ad + mov es, cx ; 8e c1 ; 0xc37ae vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc37b0 + mov si, 0010ch ; be 0c 01 ; 0xc37b3 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc37b6 + mov word [es:si], ax ; 26 89 04 ; 0xc37b8 + inc bx ; 43 ; 0xc37bb vgabios.c:2404 + inc bx ; 43 ; 0xc37bc + mov es, cx ; 8e c1 ; 0xc37bd vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc37bf + mov si, 0010eh ; be 0e 01 ; 0xc37c2 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc37c5 + mov word [es:si], ax ; 26 89 04 ; 0xc37c7 + inc bx ; 43 ; 0xc37ca vgabios.c:2405 + inc bx ; 43 ; 0xc37cb + test byte [bp-010h], 004h ; f6 46 f0 04 ; 0xc37cc vgabios.c:2407 + je short 0380fh ; 74 3d ; 0xc37d0 + inc bx ; 43 ; 0xc37d2 vgabios.c:2408 + mov es, cx ; 8e c1 ; 0xc37d3 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc37d5 + xor ah, ah ; 30 e4 ; 0xc37d8 vgabios.c:48 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc37da + inc bx ; 43 ; 0xc37dd vgabios.c:2409 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc37de vgabios.c:47 + mov dx, 003c6h ; ba c6 03 ; 0xc37e1 vgabios.c:48 + out DX, AL ; ee ; 0xc37e4 + inc bx ; 43 ; 0xc37e5 vgabios.c:2410 + xor al, al ; 30 c0 ; 0xc37e6 + mov dx, 003c8h ; ba c8 03 ; 0xc37e8 + out DX, AL ; ee ; 0xc37eb + mov word [bp-008h], ax ; 89 46 f8 ; 0xc37ec vgabios.c:2413 + jmp short 037f8h ; eb 07 ; 0xc37ef + cmp word [bp-008h], 00300h ; 81 7e f8 00 03 ; 0xc37f1 + jnc short 03807h ; 73 0f ; 0xc37f6 + mov es, cx ; 8e c1 ; 0xc37f8 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc37fa + mov dx, 003c9h ; ba c9 03 ; 0xc37fd vgabios.c:48 + out DX, AL ; ee ; 0xc3800 + inc bx ; 43 ; 0xc3801 vgabios.c:2414 + inc word [bp-008h] ; ff 46 f8 ; 0xc3802 vgabios.c:2415 + jmp short 037f1h ; eb ea ; 0xc3805 + inc bx ; 43 ; 0xc3807 vgabios.c:2416 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc3808 + mov dx, 003c8h ; ba c8 03 ; 0xc380b + out DX, AL ; ee ; 0xc380e + mov ax, bx ; 89 d8 ; 0xc380f vgabios.c:2420 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc3811 + pop di ; 5f ; 0xc3814 + pop si ; 5e ; 0xc3815 + pop cx ; 59 ; 0xc3816 + pop bp ; 5d ; 0xc3817 + retn ; c3 ; 0xc3818 + ; disGetNextSymbol 0xc3819 LB 0xd19 -> off=0x0 cb=0000000000000028 uValue=00000000000c3819 'find_vga_entry' +find_vga_entry: ; 0xc3819 LB 0x28 + push bx ; 53 ; 0xc3819 vgabios.c:2429 + push dx ; 52 ; 0xc381a + push bp ; 55 ; 0xc381b + mov bp, sp ; 89 e5 ; 0xc381c + mov dl, al ; 88 c2 ; 0xc381e + mov AH, strict byte 0ffh ; b4 ff ; 0xc3820 vgabios.c:2431 + xor al, al ; 30 c0 ; 0xc3822 vgabios.c:2432 + jmp short 0382ch ; eb 06 ; 0xc3824 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc3826 vgabios.c:2433 + cmp AL, strict byte 00fh ; 3c 0f ; 0xc3828 + jnbe short 0383bh ; 77 0f ; 0xc382a + mov bl, al ; 88 c3 ; 0xc382c + xor bh, bh ; 30 ff ; 0xc382e + sal bx, 003h ; c1 e3 03 ; 0xc3830 + cmp dl, byte [bx+047afh] ; 3a 97 af 47 ; 0xc3833 + jne short 03826h ; 75 ed ; 0xc3837 + mov ah, al ; 88 c4 ; 0xc3839 + mov al, ah ; 88 e0 ; 0xc383b vgabios.c:2438 + pop bp ; 5d ; 0xc383d + pop dx ; 5a ; 0xc383e + pop bx ; 5b ; 0xc383f + retn ; c3 ; 0xc3840 + ; disGetNextSymbol 0xc3841 LB 0xcf1 -> off=0x0 cb=000000000000000e uValue=00000000000c3841 'readx_byte' +readx_byte: ; 0xc3841 LB 0xe + push bx ; 53 ; 0xc3841 vgabios.c:2450 + push bp ; 55 ; 0xc3842 + mov bp, sp ; 89 e5 ; 0xc3843 + mov bx, dx ; 89 d3 ; 0xc3845 + mov es, ax ; 8e c0 ; 0xc3847 vgabios.c:2452 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3849 + pop bp ; 5d ; 0xc384c vgabios.c:2453 + pop bx ; 5b ; 0xc384d + retn ; c3 ; 0xc384e + ; disGetNextSymbol 0xc384f LB 0xce3 -> off=0x8a cb=000000000000049f uValue=00000000000c38d9 'int10_func' + db 056h, 04fh, 01ch, 01bh, 013h, 012h, 011h, 010h, 00eh, 00dh, 00ch, 00ah, 009h, 008h, 007h, 006h + db 005h, 004h, 003h, 002h, 001h, 000h, 071h, 03dh, 002h, 039h, 03fh, 039h, 054h, 039h, 064h, 039h + db 077h, 039h, 087h, 039h, 091h, 039h, 0d3h, 039h, 007h, 03ah, 018h, 03ah, 03eh, 03ah, 059h, 03ah + db 078h, 03ah, 095h, 03ah, 0abh, 03ah, 0b7h, 03ah, 0b0h, 03bh, 034h, 03ch, 061h, 03ch, 076h, 03ch + db 0b8h, 03ch, 043h, 03dh, 030h, 024h, 023h, 022h, 021h, 020h, 014h, 012h, 011h, 010h, 004h, 003h + db 002h, 001h, 000h, 071h, 03dh, 0d6h, 03ah, 0f4h, 03ah, 00fh, 03bh, 024h, 03bh, 02fh, 03bh, 0d6h + db 03ah, 0f4h, 03ah, 00fh, 03bh, 02fh, 03bh, 044h, 03bh, 04fh, 03bh, 06ah, 03bh, 079h, 03bh, 088h + db 03bh, 097h, 03bh, 00ah, 009h, 006h, 004h, 002h, 001h, 000h, 035h, 03dh, 0deh, 03ch, 0ech, 03ch + db 0fdh, 03ch, 00dh, 03dh, 022h, 03dh, 035h, 03dh, 035h, 03dh +int10_func: ; 0xc38d9 LB 0x49f + push bp ; 55 ; 0xc38d9 vgabios.c:2531 + mov bp, sp ; 89 e5 ; 0xc38da + push si ; 56 ; 0xc38dc + push di ; 57 ; 0xc38dd + push ax ; 50 ; 0xc38de + mov si, word [bp+004h] ; 8b 76 04 ; 0xc38df + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc38e2 vgabios.c:2536 + shr ax, 008h ; c1 e8 08 ; 0xc38e5 + cmp ax, strict word 00056h ; 3d 56 00 ; 0xc38e8 + jnbe short 03951h ; 77 64 ; 0xc38eb + push CS ; 0e ; 0xc38ed + pop ES ; 07 ; 0xc38ee + mov cx, strict word 00017h ; b9 17 00 ; 0xc38ef + mov di, 0384fh ; bf 4f 38 ; 0xc38f2 + repne scasb ; f2 ae ; 0xc38f5 + sal cx, 1 ; d1 e1 ; 0xc38f7 + mov di, cx ; 89 cf ; 0xc38f9 + mov ax, word [cs:di+03865h] ; 2e 8b 85 65 38 ; 0xc38fb + jmp ax ; ff e0 ; 0xc3900 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3902 vgabios.c:2539 + xor ah, ah ; 30 e4 ; 0xc3905 + call 0143fh ; e8 35 db ; 0xc3907 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc390a vgabios.c:2540 + and ax, strict word 0007fh ; 25 7f 00 ; 0xc390d + cmp ax, strict word 00007h ; 3d 07 00 ; 0xc3910 + je short 0392ah ; 74 15 ; 0xc3913 + cmp ax, strict word 00006h ; 3d 06 00 ; 0xc3915 + je short 03921h ; 74 07 ; 0xc3918 + cmp ax, strict word 00005h ; 3d 05 00 ; 0xc391a + jbe short 0392ah ; 76 0b ; 0xc391d + jmp short 03933h ; eb 12 ; 0xc391f + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3921 vgabios.c:2542 + xor al, al ; 30 c0 ; 0xc3924 + or AL, strict byte 03fh ; 0c 3f ; 0xc3926 + jmp short 0393ah ; eb 10 ; 0xc3928 vgabios.c:2543 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc392a vgabios.c:2551 + xor al, al ; 30 c0 ; 0xc392d + or AL, strict byte 030h ; 0c 30 ; 0xc392f + jmp short 0393ah ; eb 07 ; 0xc3931 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3933 vgabios.c:2554 + xor al, al ; 30 c0 ; 0xc3936 + or AL, strict byte 020h ; 0c 20 ; 0xc3938 + mov word [bp+012h], ax ; 89 46 12 ; 0xc393a + jmp short 03951h ; eb 12 ; 0xc393d vgabios.c:2556 + mov al, byte [bp+010h] ; 8a 46 10 ; 0xc393f vgabios.c:2558 + xor ah, ah ; 30 e4 ; 0xc3942 + mov dx, ax ; 89 c2 ; 0xc3944 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3946 + shr ax, 008h ; c1 e8 08 ; 0xc3949 + xor ah, ah ; 30 e4 ; 0xc394c + call 0118ch ; e8 3b d8 ; 0xc394e + jmp near 03d71h ; e9 1d 04 ; 0xc3951 vgabios.c:2559 + mov dx, word [bp+00eh] ; 8b 56 0e ; 0xc3954 vgabios.c:2561 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3957 + shr ax, 008h ; c1 e8 08 ; 0xc395a + xor ah, ah ; 30 e4 ; 0xc395d + call 01293h ; e8 31 d9 ; 0xc395f + jmp short 03951h ; eb ed ; 0xc3962 vgabios.c:2562 + lea bx, [bp+00eh] ; 8d 5e 0e ; 0xc3964 vgabios.c:2564 + lea dx, [bp+010h] ; 8d 56 10 ; 0xc3967 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc396a + shr ax, 008h ; c1 e8 08 ; 0xc396d + xor ah, ah ; 30 e4 ; 0xc3970 + call 00a96h ; e8 21 d1 ; 0xc3972 + jmp short 03951h ; eb da ; 0xc3975 vgabios.c:2565 + xor ax, ax ; 31 c0 ; 0xc3977 vgabios.c:2571 + mov word [bp+012h], ax ; 89 46 12 ; 0xc3979 + mov word [bp+00ch], ax ; 89 46 0c ; 0xc397c vgabios.c:2572 + mov word [bp+010h], ax ; 89 46 10 ; 0xc397f vgabios.c:2573 + mov word [bp+00eh], ax ; 89 46 0e ; 0xc3982 vgabios.c:2574 + jmp short 03951h ; eb ca ; 0xc3985 vgabios.c:2575 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3987 vgabios.c:2577 + xor ah, ah ; 30 e4 ; 0xc398a + call 01322h ; e8 93 d9 ; 0xc398c + jmp short 03951h ; eb c0 ; 0xc398f vgabios.c:2578 + mov ax, strict word 00001h ; b8 01 00 ; 0xc3991 vgabios.c:2580 + push ax ; 50 ; 0xc3994 + mov ax, 000ffh ; b8 ff 00 ; 0xc3995 + push ax ; 50 ; 0xc3998 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3999 + xor ah, ah ; 30 e4 ; 0xc399c + push ax ; 50 ; 0xc399e + mov ax, word [bp+00eh] ; 8b 46 0e ; 0xc399f + shr ax, 008h ; c1 e8 08 ; 0xc39a2 + xor ah, ah ; 30 e4 ; 0xc39a5 + push ax ; 50 ; 0xc39a7 + mov cl, byte [bp+010h] ; 8a 4e 10 ; 0xc39a8 + xor ch, ch ; 30 ed ; 0xc39ab + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc39ad + shr ax, 008h ; c1 e8 08 ; 0xc39b0 + xor ah, ah ; 30 e4 ; 0xc39b3 + mov bx, ax ; 89 c3 ; 0xc39b5 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc39b7 + shr ax, 008h ; c1 e8 08 ; 0xc39ba + xor ah, ah ; 30 e4 ; 0xc39bd + mov dx, ax ; 89 c2 ; 0xc39bf + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc39c1 + mov byte [bp-006h], al ; 88 46 fa ; 0xc39c4 + mov byte [bp-005h], ch ; 88 6e fb ; 0xc39c7 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc39ca + call 01c55h ; e8 85 e2 ; 0xc39cd + jmp near 03d71h ; e9 9e 03 ; 0xc39d0 vgabios.c:2581 + xor ax, ax ; 31 c0 ; 0xc39d3 vgabios.c:2583 + push ax ; 50 ; 0xc39d5 + mov ax, 000ffh ; b8 ff 00 ; 0xc39d6 + push ax ; 50 ; 0xc39d9 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc39da + xor ah, ah ; 30 e4 ; 0xc39dd + push ax ; 50 ; 0xc39df + mov ax, word [bp+00eh] ; 8b 46 0e ; 0xc39e0 + shr ax, 008h ; c1 e8 08 ; 0xc39e3 + xor ah, ah ; 30 e4 ; 0xc39e6 + push ax ; 50 ; 0xc39e8 + mov al, byte [bp+010h] ; 8a 46 10 ; 0xc39e9 + mov cx, ax ; 89 c1 ; 0xc39ec + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc39ee + shr ax, 008h ; c1 e8 08 ; 0xc39f1 + xor ah, ah ; 30 e4 ; 0xc39f4 + mov bx, ax ; 89 c3 ; 0xc39f6 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc39f8 + shr ax, 008h ; c1 e8 08 ; 0xc39fb + xor ah, ah ; 30 e4 ; 0xc39fe + mov dx, ax ; 89 c2 ; 0xc3a00 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3a02 + jmp short 039cdh ; eb c6 ; 0xc3a05 + lea dx, [bp+012h] ; 8d 56 12 ; 0xc3a07 vgabios.c:2586 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3a0a + shr ax, 008h ; c1 e8 08 ; 0xc3a0d + xor ah, ah ; 30 e4 ; 0xc3a10 + call 00dd6h ; e8 c1 d3 ; 0xc3a12 + jmp near 03d71h ; e9 59 03 ; 0xc3a15 vgabios.c:2587 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3a18 vgabios.c:2589 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3a1b + xor ah, ah ; 30 e4 ; 0xc3a1e + mov bx, ax ; 89 c3 ; 0xc3a20 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3a22 + shr ax, 008h ; c1 e8 08 ; 0xc3a25 + xor ah, ah ; 30 e4 ; 0xc3a28 + mov dx, ax ; 89 c2 ; 0xc3a2a + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3a2c + mov byte [bp-006h], al ; 88 46 fa ; 0xc3a2f + mov byte [bp-005h], bh ; 88 7e fb ; 0xc3a32 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc3a35 + call 0259bh ; e8 60 eb ; 0xc3a38 + jmp near 03d71h ; e9 33 03 ; 0xc3a3b vgabios.c:2590 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3a3e vgabios.c:2592 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3a41 + xor ah, ah ; 30 e4 ; 0xc3a44 + mov bx, ax ; 89 c3 ; 0xc3a46 + mov dx, word [bp+00ch] ; 8b 56 0c ; 0xc3a48 + shr dx, 008h ; c1 ea 08 ; 0xc3a4b + xor dh, dh ; 30 f6 ; 0xc3a4e + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3a50 + call 02722h ; e8 cc ec ; 0xc3a53 + jmp near 03d71h ; e9 18 03 ; 0xc3a56 vgabios.c:2593 + mov cx, word [bp+00eh] ; 8b 4e 0e ; 0xc3a59 vgabios.c:2595 + mov bx, word [bp+010h] ; 8b 5e 10 ; 0xc3a5c + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3a5f + xor ah, ah ; 30 e4 ; 0xc3a62 + mov dx, word [bp+00ch] ; 8b 56 0c ; 0xc3a64 + shr dx, 008h ; c1 ea 08 ; 0xc3a67 + xor dh, dh ; 30 f6 ; 0xc3a6a + mov si, dx ; 89 d6 ; 0xc3a6c + mov dx, ax ; 89 c2 ; 0xc3a6e + mov ax, si ; 89 f0 ; 0xc3a70 + call 028a3h ; e8 2e ee ; 0xc3a72 + jmp near 03d71h ; e9 f9 02 ; 0xc3a75 vgabios.c:2596 + lea cx, [bp+012h] ; 8d 4e 12 ; 0xc3a78 vgabios.c:2598 + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc3a7b + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3a7e + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3a81 + shr ax, 008h ; c1 e8 08 ; 0xc3a84 + mov word [bp-006h], ax ; 89 46 fa ; 0xc3a87 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc3a8a + xor ah, ah ; 30 e4 ; 0xc3a8d + call 00f99h ; e8 07 d5 ; 0xc3a8f + jmp near 03d71h ; e9 dc 02 ; 0xc3a92 vgabios.c:2599 + mov cx, strict word 00002h ; b9 02 00 ; 0xc3a95 vgabios.c:2607 + mov bl, byte [bp+00ch] ; 8a 5e 0c ; 0xc3a98 + xor bh, bh ; 30 ff ; 0xc3a9b + mov dx, 000ffh ; ba ff 00 ; 0xc3a9d + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3aa0 + xor ah, ah ; 30 e4 ; 0xc3aa3 + call 02a16h ; e8 6e ef ; 0xc3aa5 + jmp near 03d71h ; e9 c6 02 ; 0xc3aa8 vgabios.c:2608 + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3aab vgabios.c:2611 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3aae + call 010ffh ; e8 4b d6 ; 0xc3ab1 + jmp near 03d71h ; e9 ba 02 ; 0xc3ab4 vgabios.c:2612 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3ab7 vgabios.c:2614 + xor ah, ah ; 30 e4 ; 0xc3aba + cmp ax, strict word 00030h ; 3d 30 00 ; 0xc3abc + jnbe short 03b2ch ; 77 6b ; 0xc3abf + push CS ; 0e ; 0xc3ac1 + pop ES ; 07 ; 0xc3ac2 + mov cx, strict word 00010h ; b9 10 00 ; 0xc3ac3 + mov di, 03893h ; bf 93 38 ; 0xc3ac6 + repne scasb ; f2 ae ; 0xc3ac9 + sal cx, 1 ; d1 e1 ; 0xc3acb + mov di, cx ; 89 cf ; 0xc3acd + mov ax, word [cs:di+038a2h] ; 2e 8b 85 a2 38 ; 0xc3acf + jmp ax ; ff e0 ; 0xc3ad4 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3ad6 vgabios.c:2618 + shr ax, 008h ; c1 e8 08 ; 0xc3ad9 + xor ah, ah ; 30 e4 ; 0xc3adc + push ax ; 50 ; 0xc3ade + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3adf + push ax ; 50 ; 0xc3ae2 + push word [bp+00eh] ; ff 76 0e ; 0xc3ae3 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3ae6 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3ae9 + mov bx, word [bp+008h] ; 8b 5e 08 ; 0xc3aec + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3aef + jmp short 03b0ah ; eb 16 ; 0xc3af2 + push strict byte 0000eh ; 6a 0e ; 0xc3af4 vgabios.c:2622 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3af6 + xor ah, ah ; 30 e4 ; 0xc3af9 + push ax ; 50 ; 0xc3afb + push strict byte 00000h ; 6a 00 ; 0xc3afc + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3afe + mov cx, 00100h ; b9 00 01 ; 0xc3b01 + mov bx, 05d6dh ; bb 6d 5d ; 0xc3b04 + mov dx, 0c000h ; ba 00 c0 ; 0xc3b07 + call 02e1ah ; e8 0d f3 ; 0xc3b0a + jmp short 03b2ch ; eb 1d ; 0xc3b0d + push strict byte 00008h ; 6a 08 ; 0xc3b0f vgabios.c:2626 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b11 + xor ah, ah ; 30 e4 ; 0xc3b14 + push ax ; 50 ; 0xc3b16 + push strict byte 00000h ; 6a 00 ; 0xc3b17 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3b19 + mov cx, 00100h ; b9 00 01 ; 0xc3b1c + mov bx, 0556dh ; bb 6d 55 ; 0xc3b1f + jmp short 03b07h ; eb e3 ; 0xc3b22 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b24 vgabios.c:2629 + xor ah, ah ; 30 e4 ; 0xc3b27 + call 02d82h ; e8 56 f2 ; 0xc3b29 + jmp near 03d71h ; e9 42 02 ; 0xc3b2c vgabios.c:2630 + push strict byte 00010h ; 6a 10 ; 0xc3b2f vgabios.c:2633 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b31 + xor ah, ah ; 30 e4 ; 0xc3b34 + push ax ; 50 ; 0xc3b36 + push strict byte 00000h ; 6a 00 ; 0xc3b37 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3b39 + mov cx, 00100h ; b9 00 01 ; 0xc3b3c + mov bx, 06b6dh ; bb 6d 6b ; 0xc3b3f + jmp short 03b07h ; eb c3 ; 0xc3b42 + mov dx, word [bp+008h] ; 8b 56 08 ; 0xc3b44 vgabios.c:2636 + mov ax, word [bp+016h] ; 8b 46 16 ; 0xc3b47 + call 02e99h ; e8 4c f3 ; 0xc3b4a + jmp short 03b2ch ; eb dd ; 0xc3b4d vgabios.c:2637 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3b4f vgabios.c:2639 + xor ah, ah ; 30 e4 ; 0xc3b52 + push ax ; 50 ; 0xc3b54 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b55 + mov bx, word [bp+010h] ; 8b 5e 10 ; 0xc3b58 + mov dx, word [bp+008h] ; 8b 56 08 ; 0xc3b5b + mov si, word [bp+016h] ; 8b 76 16 ; 0xc3b5e + mov cx, ax ; 89 c1 ; 0xc3b61 + mov ax, si ; 89 f0 ; 0xc3b63 + call 02efch ; e8 94 f3 ; 0xc3b65 + jmp short 03b2ch ; eb c2 ; 0xc3b68 vgabios.c:2640 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3b6a vgabios.c:2642 + xor ah, ah ; 30 e4 ; 0xc3b6d + mov dx, ax ; 89 c2 ; 0xc3b6f + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b71 + call 02f19h ; e8 a2 f3 ; 0xc3b74 + jmp short 03b2ch ; eb b3 ; 0xc3b77 vgabios.c:2643 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3b79 vgabios.c:2645 + xor ah, ah ; 30 e4 ; 0xc3b7c + mov dx, ax ; 89 c2 ; 0xc3b7e + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b80 + call 02f3bh ; e8 b5 f3 ; 0xc3b83 + jmp short 03b2ch ; eb a4 ; 0xc3b86 vgabios.c:2646 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3b88 vgabios.c:2648 + xor ah, ah ; 30 e4 ; 0xc3b8b + mov dx, ax ; 89 c2 ; 0xc3b8d + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b8f + call 02f5dh ; e8 c8 f3 ; 0xc3b92 + jmp short 03b2ch ; eb 95 ; 0xc3b95 vgabios.c:2649 + lea ax, [bp+00eh] ; 8d 46 0e ; 0xc3b97 vgabios.c:2651 + push ax ; 50 ; 0xc3b9a + lea cx, [bp+010h] ; 8d 4e 10 ; 0xc3b9b + lea bx, [bp+008h] ; 8d 5e 08 ; 0xc3b9e + lea dx, [bp+016h] ; 8d 56 16 ; 0xc3ba1 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3ba4 + shr ax, 008h ; c1 e8 08 ; 0xc3ba7 + call 00f16h ; e8 69 d3 ; 0xc3baa + jmp near 03d71h ; e9 c1 01 ; 0xc3bad vgabios.c:2659 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3bb0 vgabios.c:2661 + xor ah, ah ; 30 e4 ; 0xc3bb3 + cmp ax, strict word 00034h ; 3d 34 00 ; 0xc3bb5 + jc short 03bc9h ; 72 0f ; 0xc3bb8 + jbe short 03bf4h ; 76 38 ; 0xc3bba + cmp ax, strict word 00036h ; 3d 36 00 ; 0xc3bbc + je short 03c1ch ; 74 5b ; 0xc3bbf + cmp ax, strict word 00035h ; 3d 35 00 ; 0xc3bc1 + je short 03c1eh ; 74 58 ; 0xc3bc4 + jmp near 03d71h ; e9 a8 01 ; 0xc3bc6 + cmp ax, strict word 00030h ; 3d 30 00 ; 0xc3bc9 + je short 03bd8h ; 74 0a ; 0xc3bcc + cmp ax, strict word 00020h ; 3d 20 00 ; 0xc3bce + jne short 03c19h ; 75 46 ; 0xc3bd1 + call 02f7fh ; e8 a9 f3 ; 0xc3bd3 vgabios.c:2664 + jmp short 03c19h ; eb 41 ; 0xc3bd6 vgabios.c:2665 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3bd8 vgabios.c:2667 + xor ah, ah ; 30 e4 ; 0xc3bdb + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc3bdd + jnbe short 03c19h ; 77 37 ; 0xc3be0 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3be2 vgabios.c:2668 + call 02f84h ; e8 9c f3 ; 0xc3be5 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3be8 vgabios.c:2669 + xor al, al ; 30 c0 ; 0xc3beb + or AL, strict byte 012h ; 0c 12 ; 0xc3bed + mov word [bp+012h], ax ; 89 46 12 ; 0xc3bef + jmp short 03c19h ; eb 25 ; 0xc3bf2 vgabios.c:2671 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3bf4 vgabios.c:2673 + xor ah, ah ; 30 e4 ; 0xc3bf7 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc3bf9 + jnc short 03c16h ; 73 18 ; 0xc3bfc + mov ax, strict word 00040h ; b8 40 00 ; 0xc3bfe vgabios.c:45 + mov es, ax ; 8e c0 ; 0xc3c01 + mov si, 00087h ; be 87 00 ; 0xc3c03 + mov ah, byte [es:si] ; 26 8a 24 ; 0xc3c06 vgabios.c:47 + and ah, 0feh ; 80 e4 fe ; 0xc3c09 vgabios.c:48 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c0c + or al, ah ; 08 e0 ; 0xc3c0f + mov byte [es:si], al ; 26 88 04 ; 0xc3c11 vgabios.c:52 + jmp short 03be8h ; eb d2 ; 0xc3c14 + mov byte [bp+012h], ah ; 88 66 12 ; 0xc3c16 vgabios.c:2679 + jmp near 03d71h ; e9 55 01 ; 0xc3c19 vgabios.c:2680 + jmp short 03c2ch ; eb 0e ; 0xc3c1c + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c1e vgabios.c:2682 + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc3c21 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3c24 + call 02fb6h ; e8 8c f3 ; 0xc3c27 + jmp short 03be8h ; eb bc ; 0xc3c2a + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c2c vgabios.c:2686 + call 02fbbh ; e8 89 f3 ; 0xc3c2f + jmp short 03be8h ; eb b4 ; 0xc3c32 + push word [bp+008h] ; ff 76 08 ; 0xc3c34 vgabios.c:2696 + push word [bp+016h] ; ff 76 16 ; 0xc3c37 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3c3a + xor ah, ah ; 30 e4 ; 0xc3c3d + push ax ; 50 ; 0xc3c3f + mov ax, word [bp+00eh] ; 8b 46 0e ; 0xc3c40 + shr ax, 008h ; c1 e8 08 ; 0xc3c43 + xor ah, ah ; 30 e4 ; 0xc3c46 + push ax ; 50 ; 0xc3c48 + mov bl, byte [bp+00ch] ; 8a 5e 0c ; 0xc3c49 + xor bh, bh ; 30 ff ; 0xc3c4c + mov dx, word [bp+00ch] ; 8b 56 0c ; 0xc3c4e + shr dx, 008h ; c1 ea 08 ; 0xc3c51 + xor dh, dh ; 30 f6 ; 0xc3c54 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c56 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3c59 + call 02fc0h ; e8 61 f3 ; 0xc3c5c + jmp short 03c19h ; eb b8 ; 0xc3c5f vgabios.c:2697 + mov bx, si ; 89 f3 ; 0xc3c61 vgabios.c:2699 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3c63 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3c66 + call 0305dh ; e8 f1 f3 ; 0xc3c69 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3c6c vgabios.c:2700 + xor al, al ; 30 c0 ; 0xc3c6f + or AL, strict byte 01bh ; 0c 1b ; 0xc3c71 + jmp near 03befh ; e9 79 ff ; 0xc3c73 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3c76 vgabios.c:2703 + xor ah, ah ; 30 e4 ; 0xc3c79 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc3c7b + je short 03ca2h ; 74 22 ; 0xc3c7e + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc3c80 + je short 03c94h ; 74 0f ; 0xc3c83 + test ax, ax ; 85 c0 ; 0xc3c85 + jne short 03caeh ; 75 25 ; 0xc3c87 + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3c89 vgabios.c:2706 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3c8c + call 0326fh ; e8 dd f5 ; 0xc3c8f + jmp short 03caeh ; eb 1a ; 0xc3c92 vgabios.c:2707 + mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xc3c94 vgabios.c:2709 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3c97 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3c9a + call 03287h ; e8 e7 f5 ; 0xc3c9d + jmp short 03caeh ; eb 0c ; 0xc3ca0 vgabios.c:2710 + mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xc3ca2 vgabios.c:2712 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3ca5 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3ca8 + call 0355fh ; e8 b1 f8 ; 0xc3cab + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3cae vgabios.c:2719 + xor al, al ; 30 c0 ; 0xc3cb1 + or AL, strict byte 01ch ; 0c 1c ; 0xc3cb3 + jmp near 03befh ; e9 37 ff ; 0xc3cb5 + call 007bfh ; e8 04 cb ; 0xc3cb8 vgabios.c:2724 + test ax, ax ; 85 c0 ; 0xc3cbb + je short 03d33h ; 74 74 ; 0xc3cbd + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3cbf vgabios.c:2725 + xor ah, ah ; 30 e4 ; 0xc3cc2 + cmp ax, strict word 0000ah ; 3d 0a 00 ; 0xc3cc4 + jnbe short 03d35h ; 77 6c ; 0xc3cc7 + push CS ; 0e ; 0xc3cc9 + pop ES ; 07 ; 0xc3cca + mov cx, strict word 00008h ; b9 08 00 ; 0xc3ccb + mov di, 038c2h ; bf c2 38 ; 0xc3cce + repne scasb ; f2 ae ; 0xc3cd1 + sal cx, 1 ; d1 e1 ; 0xc3cd3 + mov di, cx ; 89 cf ; 0xc3cd5 + mov ax, word [cs:di+038c9h] ; 2e 8b 85 c9 38 ; 0xc3cd7 + jmp ax ; ff e0 ; 0xc3cdc + mov bx, si ; 89 f3 ; 0xc3cde vgabios.c:2728 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3ce0 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3ce3 + call 03f42h ; e8 59 02 ; 0xc3ce6 + jmp near 03d71h ; e9 85 00 ; 0xc3ce9 vgabios.c:2729 + mov cx, si ; 89 f1 ; 0xc3cec vgabios.c:2731 + mov bx, word [bp+016h] ; 8b 5e 16 ; 0xc3cee + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3cf1 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3cf4 + call 0406dh ; e8 73 03 ; 0xc3cf7 + jmp near 03d71h ; e9 74 00 ; 0xc3cfa vgabios.c:2732 + mov cx, si ; 89 f1 ; 0xc3cfd vgabios.c:2734 + mov bx, word [bp+016h] ; 8b 5e 16 ; 0xc3cff + mov dx, word [bp+00ch] ; 8b 56 0c ; 0xc3d02 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d05 + call 0410ch ; e8 01 04 ; 0xc3d08 + jmp short 03d71h ; eb 64 ; 0xc3d0b vgabios.c:2735 + lea ax, [bp+00ch] ; 8d 46 0c ; 0xc3d0d vgabios.c:2737 + push ax ; 50 ; 0xc3d10 + mov cx, word [bp+016h] ; 8b 4e 16 ; 0xc3d11 + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc3d14 + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3d17 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d1a + call 042d5h ; e8 b5 05 ; 0xc3d1d + jmp short 03d71h ; eb 4f ; 0xc3d20 vgabios.c:2738 + lea cx, [bp+00eh] ; 8d 4e 0e ; 0xc3d22 vgabios.c:2740 + lea bx, [bp+010h] ; 8d 5e 10 ; 0xc3d25 + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3d28 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d2b + call 04361h ; e8 30 06 ; 0xc3d2e + jmp short 03d71h ; eb 3e ; 0xc3d31 vgabios.c:2741 + jmp short 03d3ch ; eb 07 ; 0xc3d33 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3d35 vgabios.c:2763 + jmp short 03d71h ; eb 35 ; 0xc3d3a vgabios.c:2766 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3d3c vgabios.c:2768 + jmp short 03d71h ; eb 2e ; 0xc3d41 vgabios.c:2770 + call 007bfh ; e8 79 ca ; 0xc3d43 vgabios.c:2772 + test ax, ax ; 85 c0 ; 0xc3d46 + je short 03d6ch ; 74 22 ; 0xc3d48 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3d4a vgabios.c:2773 + xor ah, ah ; 30 e4 ; 0xc3d4d + cmp ax, strict word 00042h ; 3d 42 00 ; 0xc3d4f + jne short 03d65h ; 75 11 ; 0xc3d52 + lea cx, [bp+00eh] ; 8d 4e 0e ; 0xc3d54 vgabios.c:2776 + lea bx, [bp+010h] ; 8d 5e 10 ; 0xc3d57 + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3d5a + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d5d + call 04440h ; e8 dd 06 ; 0xc3d60 + jmp short 03d71h ; eb 0c ; 0xc3d63 vgabios.c:2777 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3d65 vgabios.c:2779 + jmp short 03d71h ; eb 05 ; 0xc3d6a vgabios.c:2782 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3d6c vgabios.c:2784 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3d71 vgabios.c:2794 + pop di ; 5f ; 0xc3d74 + pop si ; 5e ; 0xc3d75 + pop bp ; 5d ; 0xc3d76 + retn ; c3 ; 0xc3d77 + ; disGetNextSymbol 0xc3d78 LB 0x7ba -> off=0x0 cb=000000000000001f uValue=00000000000c3d78 'dispi_set_xres' +dispi_set_xres: ; 0xc3d78 LB 0x1f + push bp ; 55 ; 0xc3d78 vbe.c:100 + mov bp, sp ; 89 e5 ; 0xc3d79 + push bx ; 53 ; 0xc3d7b + push dx ; 52 ; 0xc3d7c + mov bx, ax ; 89 c3 ; 0xc3d7d + mov ax, strict word 00001h ; b8 01 00 ; 0xc3d7f vbe.c:105 + mov dx, 001ceh ; ba ce 01 ; 0xc3d82 + call 00570h ; e8 e8 c7 ; 0xc3d85 + mov ax, bx ; 89 d8 ; 0xc3d88 vbe.c:106 + mov dx, 001cfh ; ba cf 01 ; 0xc3d8a + call 00570h ; e8 e0 c7 ; 0xc3d8d + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3d90 vbe.c:107 + pop dx ; 5a ; 0xc3d93 + pop bx ; 5b ; 0xc3d94 + pop bp ; 5d ; 0xc3d95 + retn ; c3 ; 0xc3d96 + ; disGetNextSymbol 0xc3d97 LB 0x79b -> off=0x0 cb=000000000000001f uValue=00000000000c3d97 'dispi_set_yres' +dispi_set_yres: ; 0xc3d97 LB 0x1f + push bp ; 55 ; 0xc3d97 vbe.c:109 + mov bp, sp ; 89 e5 ; 0xc3d98 + push bx ; 53 ; 0xc3d9a + push dx ; 52 ; 0xc3d9b + mov bx, ax ; 89 c3 ; 0xc3d9c + mov ax, strict word 00002h ; b8 02 00 ; 0xc3d9e vbe.c:114 + mov dx, 001ceh ; ba ce 01 ; 0xc3da1 + call 00570h ; e8 c9 c7 ; 0xc3da4 + mov ax, bx ; 89 d8 ; 0xc3da7 vbe.c:115 + mov dx, 001cfh ; ba cf 01 ; 0xc3da9 + call 00570h ; e8 c1 c7 ; 0xc3dac + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3daf vbe.c:116 + pop dx ; 5a ; 0xc3db2 + pop bx ; 5b ; 0xc3db3 + pop bp ; 5d ; 0xc3db4 + retn ; c3 ; 0xc3db5 + ; disGetNextSymbol 0xc3db6 LB 0x77c -> off=0x0 cb=0000000000000019 uValue=00000000000c3db6 'dispi_get_yres' +dispi_get_yres: ; 0xc3db6 LB 0x19 + push bp ; 55 ; 0xc3db6 vbe.c:118 + mov bp, sp ; 89 e5 ; 0xc3db7 + push dx ; 52 ; 0xc3db9 + mov ax, strict word 00002h ; b8 02 00 ; 0xc3dba vbe.c:120 + mov dx, 001ceh ; ba ce 01 ; 0xc3dbd + call 00570h ; e8 ad c7 ; 0xc3dc0 + mov dx, 001cfh ; ba cf 01 ; 0xc3dc3 vbe.c:121 + call 00577h ; e8 ae c7 ; 0xc3dc6 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3dc9 vbe.c:122 + pop dx ; 5a ; 0xc3dcc + pop bp ; 5d ; 0xc3dcd + retn ; c3 ; 0xc3dce + ; disGetNextSymbol 0xc3dcf LB 0x763 -> off=0x0 cb=000000000000001f uValue=00000000000c3dcf 'dispi_set_bpp' +dispi_set_bpp: ; 0xc3dcf LB 0x1f + push bp ; 55 ; 0xc3dcf vbe.c:124 + mov bp, sp ; 89 e5 ; 0xc3dd0 + push bx ; 53 ; 0xc3dd2 + push dx ; 52 ; 0xc3dd3 + mov bx, ax ; 89 c3 ; 0xc3dd4 + mov ax, strict word 00003h ; b8 03 00 ; 0xc3dd6 vbe.c:129 + mov dx, 001ceh ; ba ce 01 ; 0xc3dd9 + call 00570h ; e8 91 c7 ; 0xc3ddc + mov ax, bx ; 89 d8 ; 0xc3ddf vbe.c:130 + mov dx, 001cfh ; ba cf 01 ; 0xc3de1 + call 00570h ; e8 89 c7 ; 0xc3de4 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3de7 vbe.c:131 + pop dx ; 5a ; 0xc3dea + pop bx ; 5b ; 0xc3deb + pop bp ; 5d ; 0xc3dec + retn ; c3 ; 0xc3ded + ; disGetNextSymbol 0xc3dee LB 0x744 -> off=0x0 cb=0000000000000019 uValue=00000000000c3dee 'dispi_get_bpp' +dispi_get_bpp: ; 0xc3dee LB 0x19 + push bp ; 55 ; 0xc3dee vbe.c:133 + mov bp, sp ; 89 e5 ; 0xc3def + push dx ; 52 ; 0xc3df1 + mov ax, strict word 00003h ; b8 03 00 ; 0xc3df2 vbe.c:135 + mov dx, 001ceh ; ba ce 01 ; 0xc3df5 + call 00570h ; e8 75 c7 ; 0xc3df8 + mov dx, 001cfh ; ba cf 01 ; 0xc3dfb vbe.c:136 + call 00577h ; e8 76 c7 ; 0xc3dfe + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e01 vbe.c:137 + pop dx ; 5a ; 0xc3e04 + pop bp ; 5d ; 0xc3e05 + retn ; c3 ; 0xc3e06 + ; disGetNextSymbol 0xc3e07 LB 0x72b -> off=0x0 cb=000000000000001f uValue=00000000000c3e07 'dispi_set_virt_width' +dispi_set_virt_width: ; 0xc3e07 LB 0x1f + push bp ; 55 ; 0xc3e07 vbe.c:139 + mov bp, sp ; 89 e5 ; 0xc3e08 + push bx ; 53 ; 0xc3e0a + push dx ; 52 ; 0xc3e0b + mov bx, ax ; 89 c3 ; 0xc3e0c + mov ax, strict word 00006h ; b8 06 00 ; 0xc3e0e vbe.c:144 + mov dx, 001ceh ; ba ce 01 ; 0xc3e11 + call 00570h ; e8 59 c7 ; 0xc3e14 + mov ax, bx ; 89 d8 ; 0xc3e17 vbe.c:145 + mov dx, 001cfh ; ba cf 01 ; 0xc3e19 + call 00570h ; e8 51 c7 ; 0xc3e1c + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3e1f vbe.c:146 + pop dx ; 5a ; 0xc3e22 + pop bx ; 5b ; 0xc3e23 + pop bp ; 5d ; 0xc3e24 + retn ; c3 ; 0xc3e25 + ; disGetNextSymbol 0xc3e26 LB 0x70c -> off=0x0 cb=0000000000000019 uValue=00000000000c3e26 'dispi_get_virt_width' +dispi_get_virt_width: ; 0xc3e26 LB 0x19 + push bp ; 55 ; 0xc3e26 vbe.c:148 + mov bp, sp ; 89 e5 ; 0xc3e27 + push dx ; 52 ; 0xc3e29 + mov ax, strict word 00006h ; b8 06 00 ; 0xc3e2a vbe.c:150 + mov dx, 001ceh ; ba ce 01 ; 0xc3e2d + call 00570h ; e8 3d c7 ; 0xc3e30 + mov dx, 001cfh ; ba cf 01 ; 0xc3e33 vbe.c:151 + call 00577h ; e8 3e c7 ; 0xc3e36 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e39 vbe.c:152 + pop dx ; 5a ; 0xc3e3c + pop bp ; 5d ; 0xc3e3d + retn ; c3 ; 0xc3e3e + ; disGetNextSymbol 0xc3e3f LB 0x6f3 -> off=0x0 cb=0000000000000019 uValue=00000000000c3e3f 'dispi_get_virt_height' +dispi_get_virt_height: ; 0xc3e3f LB 0x19 + push bp ; 55 ; 0xc3e3f vbe.c:154 + mov bp, sp ; 89 e5 ; 0xc3e40 + push dx ; 52 ; 0xc3e42 + mov ax, strict word 00007h ; b8 07 00 ; 0xc3e43 vbe.c:156 + mov dx, 001ceh ; ba ce 01 ; 0xc3e46 + call 00570h ; e8 24 c7 ; 0xc3e49 + mov dx, 001cfh ; ba cf 01 ; 0xc3e4c vbe.c:157 + call 00577h ; e8 25 c7 ; 0xc3e4f + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e52 vbe.c:158 + pop dx ; 5a ; 0xc3e55 + pop bp ; 5d ; 0xc3e56 + retn ; c3 ; 0xc3e57 + ; disGetNextSymbol 0xc3e58 LB 0x6da -> off=0x0 cb=0000000000000012 uValue=00000000000c3e58 'in_word' +in_word: ; 0xc3e58 LB 0x12 + push bp ; 55 ; 0xc3e58 vbe.c:160 + mov bp, sp ; 89 e5 ; 0xc3e59 + push bx ; 53 ; 0xc3e5b + mov bx, ax ; 89 c3 ; 0xc3e5c + mov ax, dx ; 89 d0 ; 0xc3e5e + mov dx, bx ; 89 da ; 0xc3e60 vbe.c:162 + out DX, ax ; ef ; 0xc3e62 + in ax, DX ; ed ; 0xc3e63 vbe.c:163 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e64 vbe.c:164 + pop bx ; 5b ; 0xc3e67 + pop bp ; 5d ; 0xc3e68 + retn ; c3 ; 0xc3e69 + ; disGetNextSymbol 0xc3e6a LB 0x6c8 -> off=0x0 cb=0000000000000014 uValue=00000000000c3e6a 'in_byte' +in_byte: ; 0xc3e6a LB 0x14 + push bp ; 55 ; 0xc3e6a vbe.c:166 + mov bp, sp ; 89 e5 ; 0xc3e6b + push bx ; 53 ; 0xc3e6d + mov bx, ax ; 89 c3 ; 0xc3e6e + mov ax, dx ; 89 d0 ; 0xc3e70 + mov dx, bx ; 89 da ; 0xc3e72 vbe.c:168 + out DX, ax ; ef ; 0xc3e74 + in AL, DX ; ec ; 0xc3e75 vbe.c:169 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3e76 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e78 vbe.c:170 + pop bx ; 5b ; 0xc3e7b + pop bp ; 5d ; 0xc3e7c + retn ; c3 ; 0xc3e7d + ; disGetNextSymbol 0xc3e7e LB 0x6b4 -> off=0x0 cb=0000000000000014 uValue=00000000000c3e7e 'dispi_get_id' +dispi_get_id: ; 0xc3e7e LB 0x14 + push bp ; 55 ; 0xc3e7e vbe.c:173 + mov bp, sp ; 89 e5 ; 0xc3e7f + push dx ; 52 ; 0xc3e81 + xor ax, ax ; 31 c0 ; 0xc3e82 vbe.c:175 + mov dx, 001ceh ; ba ce 01 ; 0xc3e84 + out DX, ax ; ef ; 0xc3e87 + mov dx, 001cfh ; ba cf 01 ; 0xc3e88 vbe.c:176 + in ax, DX ; ed ; 0xc3e8b + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e8c vbe.c:177 + pop dx ; 5a ; 0xc3e8f + pop bp ; 5d ; 0xc3e90 + retn ; c3 ; 0xc3e91 + ; disGetNextSymbol 0xc3e92 LB 0x6a0 -> off=0x0 cb=000000000000001a uValue=00000000000c3e92 'dispi_set_id' +dispi_set_id: ; 0xc3e92 LB 0x1a + push bp ; 55 ; 0xc3e92 vbe.c:179 + mov bp, sp ; 89 e5 ; 0xc3e93 + push bx ; 53 ; 0xc3e95 + push dx ; 52 ; 0xc3e96 + mov bx, ax ; 89 c3 ; 0xc3e97 + xor ax, ax ; 31 c0 ; 0xc3e99 vbe.c:181 + mov dx, 001ceh ; ba ce 01 ; 0xc3e9b + out DX, ax ; ef ; 0xc3e9e + mov ax, bx ; 89 d8 ; 0xc3e9f vbe.c:182 + mov dx, 001cfh ; ba cf 01 ; 0xc3ea1 + out DX, ax ; ef ; 0xc3ea4 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3ea5 vbe.c:183 + pop dx ; 5a ; 0xc3ea8 + pop bx ; 5b ; 0xc3ea9 + pop bp ; 5d ; 0xc3eaa + retn ; c3 ; 0xc3eab + ; disGetNextSymbol 0xc3eac LB 0x686 -> off=0x0 cb=000000000000002a uValue=00000000000c3eac 'vbe_init' +vbe_init: ; 0xc3eac LB 0x2a + push bp ; 55 ; 0xc3eac vbe.c:188 + mov bp, sp ; 89 e5 ; 0xc3ead + push bx ; 53 ; 0xc3eaf + mov ax, 0b0c0h ; b8 c0 b0 ; 0xc3eb0 vbe.c:190 + call 03e92h ; e8 dc ff ; 0xc3eb3 + call 03e7eh ; e8 c5 ff ; 0xc3eb6 vbe.c:191 + cmp ax, 0b0c0h ; 3d c0 b0 ; 0xc3eb9 + jne short 03ed0h ; 75 12 ; 0xc3ebc + mov bx, 000b9h ; bb b9 00 ; 0xc3ebe vbe.c:52 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3ec1 + mov es, ax ; 8e c0 ; 0xc3ec4 + mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xc3ec6 + mov ax, 0b0c4h ; b8 c4 b0 ; 0xc3eca vbe.c:194 + call 03e92h ; e8 c2 ff ; 0xc3ecd + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3ed0 vbe.c:199 + pop bx ; 5b ; 0xc3ed3 + pop bp ; 5d ; 0xc3ed4 + retn ; c3 ; 0xc3ed5 + ; disGetNextSymbol 0xc3ed6 LB 0x65c -> off=0x0 cb=000000000000006c uValue=00000000000c3ed6 'mode_info_find_mode' +mode_info_find_mode: ; 0xc3ed6 LB 0x6c + push bp ; 55 ; 0xc3ed6 vbe.c:202 + mov bp, sp ; 89 e5 ; 0xc3ed7 + push bx ; 53 ; 0xc3ed9 + push cx ; 51 ; 0xc3eda + push si ; 56 ; 0xc3edb + push di ; 57 ; 0xc3edc + mov di, ax ; 89 c7 ; 0xc3edd + mov si, dx ; 89 d6 ; 0xc3edf + xor dx, dx ; 31 d2 ; 0xc3ee1 vbe.c:208 + mov ax, 003b6h ; b8 b6 03 ; 0xc3ee3 + call 03e58h ; e8 6f ff ; 0xc3ee6 + cmp ax, 077cch ; 3d cc 77 ; 0xc3ee9 vbe.c:209 + jne short 03f37h ; 75 49 ; 0xc3eec + test si, si ; 85 f6 ; 0xc3eee vbe.c:213 + je short 03f05h ; 74 13 ; 0xc3ef0 + mov ax, strict word 0000bh ; b8 0b 00 ; 0xc3ef2 vbe.c:220 + mov dx, 001ceh ; ba ce 01 ; 0xc3ef5 + call 00570h ; e8 75 c6 ; 0xc3ef8 + mov dx, 001cfh ; ba cf 01 ; 0xc3efb vbe.c:221 + call 00577h ; e8 76 c6 ; 0xc3efe + test ax, ax ; 85 c0 ; 0xc3f01 vbe.c:222 + je short 03f39h ; 74 34 ; 0xc3f03 + mov bx, strict word 00004h ; bb 04 00 ; 0xc3f05 vbe.c:226 + mov dx, bx ; 89 da ; 0xc3f08 vbe.c:232 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f0a + call 03e58h ; e8 48 ff ; 0xc3f0d + mov cx, ax ; 89 c1 ; 0xc3f10 + cmp cx, strict byte 0ffffh ; 83 f9 ff ; 0xc3f12 vbe.c:233 + je short 03f37h ; 74 20 ; 0xc3f15 + lea dx, [bx+002h] ; 8d 57 02 ; 0xc3f17 vbe.c:235 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f1a + call 03e58h ; e8 38 ff ; 0xc3f1d + lea dx, [bx+044h] ; 8d 57 44 ; 0xc3f20 + cmp cx, di ; 39 f9 ; 0xc3f23 vbe.c:237 + jne short 03f33h ; 75 0c ; 0xc3f25 + test si, si ; 85 f6 ; 0xc3f27 vbe.c:239 + jne short 03f2fh ; 75 04 ; 0xc3f29 + mov ax, bx ; 89 d8 ; 0xc3f2b vbe.c:240 + jmp short 03f39h ; eb 0a ; 0xc3f2d + test AL, strict byte 080h ; a8 80 ; 0xc3f2f vbe.c:241 + jne short 03f2bh ; 75 f8 ; 0xc3f31 + mov bx, dx ; 89 d3 ; 0xc3f33 vbe.c:244 + jmp short 03f0ah ; eb d3 ; 0xc3f35 vbe.c:249 + xor ax, ax ; 31 c0 ; 0xc3f37 vbe.c:252 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc3f39 vbe.c:253 + pop di ; 5f ; 0xc3f3c + pop si ; 5e ; 0xc3f3d + pop cx ; 59 ; 0xc3f3e + pop bx ; 5b ; 0xc3f3f + pop bp ; 5d ; 0xc3f40 + retn ; c3 ; 0xc3f41 + ; disGetNextSymbol 0xc3f42 LB 0x5f0 -> off=0x0 cb=000000000000012b uValue=00000000000c3f42 'vbe_biosfn_return_controller_information' +vbe_biosfn_return_controller_information: ; 0xc3f42 LB 0x12b + push bp ; 55 ; 0xc3f42 vbe.c:284 + mov bp, sp ; 89 e5 ; 0xc3f43 + push cx ; 51 ; 0xc3f45 + push si ; 56 ; 0xc3f46 + push di ; 57 ; 0xc3f47 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc3f48 + mov si, ax ; 89 c6 ; 0xc3f4b + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc3f4d + mov di, bx ; 89 df ; 0xc3f50 + mov word [bp-00ch], strict word 00022h ; c7 46 f4 22 00 ; 0xc3f52 vbe.c:289 + call 005b7h ; e8 5d c6 ; 0xc3f57 vbe.c:292 + mov word [bp-010h], ax ; 89 46 f0 ; 0xc3f5a + mov bx, di ; 89 fb ; 0xc3f5d vbe.c:295 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3f5f + mov word [bp-008h], ax ; 89 46 f8 ; 0xc3f62 + xor dx, dx ; 31 d2 ; 0xc3f65 vbe.c:298 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f67 + call 03e58h ; e8 eb fe ; 0xc3f6a + cmp ax, 077cch ; 3d cc 77 ; 0xc3f6d vbe.c:299 + je short 03f7ch ; 74 0a ; 0xc3f70 + push SS ; 16 ; 0xc3f72 vbe.c:301 + pop ES ; 07 ; 0xc3f73 + mov word [es:si], 00100h ; 26 c7 04 00 01 ; 0xc3f74 + jmp near 04065h ; e9 e9 00 ; 0xc3f79 vbe.c:305 + mov cx, strict word 00004h ; b9 04 00 ; 0xc3f7c vbe.c:307 + mov word [bp-00eh], strict word 00000h ; c7 46 f2 00 00 ; 0xc3f7f vbe.c:314 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc3f84 vbe.c:322 + cmp word [es:bx+002h], 03245h ; 26 81 7f 02 45 32 ; 0xc3f87 + jne short 03f96h ; 75 07 ; 0xc3f8d + cmp word [es:bx], 04256h ; 26 81 3f 56 42 ; 0xc3f8f + je short 03fa5h ; 74 0f ; 0xc3f94 + cmp word [es:bx+002h], 04153h ; 26 81 7f 02 53 41 ; 0xc3f96 + jne short 03faah ; 75 0c ; 0xc3f9c + cmp word [es:bx], 04556h ; 26 81 3f 56 45 ; 0xc3f9e + jne short 03faah ; 75 05 ; 0xc3fa3 + mov word [bp-00eh], strict word 00001h ; c7 46 f2 01 00 ; 0xc3fa5 vbe.c:324 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc3faa vbe.c:332 + mov word [es:bx], 04556h ; 26 c7 07 56 45 ; 0xc3fad + mov word [es:bx+002h], 04153h ; 26 c7 47 02 53 41 ; 0xc3fb2 vbe.c:334 + mov word [es:bx+004h], 00200h ; 26 c7 47 04 00 02 ; 0xc3fb8 vbe.c:338 + mov word [es:bx+006h], 07e02h ; 26 c7 47 06 02 7e ; 0xc3fbe vbe.c:341 + mov [es:bx+008h], ds ; 26 8c 5f 08 ; 0xc3fc4 + mov word [es:bx+00ah], strict word 00001h ; 26 c7 47 0a 01 00 ; 0xc3fc8 vbe.c:344 + mov word [es:bx+00ch], strict word 00000h ; 26 c7 47 0c 00 00 ; 0xc3fce vbe.c:346 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3fd4 vbe.c:350 + mov word [es:bx+010h], ax ; 26 89 47 10 ; 0xc3fd7 + lea ax, [di+022h] ; 8d 45 22 ; 0xc3fdb vbe.c:351 + mov word [es:bx+00eh], ax ; 26 89 47 0e ; 0xc3fde + mov dx, strict word 0ffffh ; ba ff ff ; 0xc3fe2 vbe.c:354 + mov ax, 003b6h ; b8 b6 03 ; 0xc3fe5 + call 03e58h ; e8 6d fe ; 0xc3fe8 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc3feb + mov word [es:bx+012h], ax ; 26 89 47 12 ; 0xc3fee + cmp word [bp-00eh], strict byte 00000h ; 83 7e f2 00 ; 0xc3ff2 vbe.c:356 + je short 0401ch ; 74 24 ; 0xc3ff6 + mov word [es:bx+014h], strict word 00003h ; 26 c7 47 14 03 00 ; 0xc3ff8 vbe.c:359 + mov word [es:bx+016h], 07e17h ; 26 c7 47 16 17 7e ; 0xc3ffe vbe.c:360 + mov [es:bx+018h], ds ; 26 8c 5f 18 ; 0xc4004 + mov word [es:bx+01ah], 07e34h ; 26 c7 47 1a 34 7e ; 0xc4008 vbe.c:361 + mov [es:bx+01ch], ds ; 26 8c 5f 1c ; 0xc400e + mov word [es:bx+01eh], 07e55h ; 26 c7 47 1e 55 7e ; 0xc4012 vbe.c:362 + mov [es:bx+020h], ds ; 26 8c 5f 20 ; 0xc4018 + mov dx, cx ; 89 ca ; 0xc401c vbe.c:369 + add dx, strict byte 0001bh ; 83 c2 1b ; 0xc401e + mov ax, 003b6h ; b8 b6 03 ; 0xc4021 + call 03e6ah ; e8 43 fe ; 0xc4024 + xor ah, ah ; 30 e4 ; 0xc4027 vbe.c:370 + cmp ax, word [bp-010h] ; 3b 46 f0 ; 0xc4029 + jnbe short 04045h ; 77 17 ; 0xc402c + mov dx, cx ; 89 ca ; 0xc402e vbe.c:372 + mov ax, 003b6h ; b8 b6 03 ; 0xc4030 + call 03e58h ; e8 22 fe ; 0xc4033 + mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xc4036 vbe.c:376 + add bx, di ; 01 fb ; 0xc4039 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc403b vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc403e + add word [bp-00ch], strict byte 00002h ; 83 46 f4 02 ; 0xc4041 vbe.c:378 + add cx, strict byte 00044h ; 83 c1 44 ; 0xc4045 vbe.c:380 + mov dx, cx ; 89 ca ; 0xc4048 vbe.c:381 + mov ax, 003b6h ; b8 b6 03 ; 0xc404a + call 03e58h ; e8 08 fe ; 0xc404d + cmp ax, strict word 0ffffh ; 3d ff ff ; 0xc4050 vbe.c:382 + jne short 0401ch ; 75 c7 ; 0xc4053 + add di, word [bp-00ch] ; 03 7e f4 ; 0xc4055 vbe.c:385 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc4058 vbe.c:62 + mov word [es:di], ax ; 26 89 05 ; 0xc405b + push SS ; 16 ; 0xc405e vbe.c:386 + pop ES ; 07 ; 0xc405f + mov word [es:si], strict word 0004fh ; 26 c7 04 4f 00 ; 0xc4060 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc4065 vbe.c:387 + pop di ; 5f ; 0xc4068 + pop si ; 5e ; 0xc4069 + pop cx ; 59 ; 0xc406a + pop bp ; 5d ; 0xc406b + retn ; c3 ; 0xc406c + ; disGetNextSymbol 0xc406d LB 0x4c5 -> off=0x0 cb=000000000000009f uValue=00000000000c406d 'vbe_biosfn_return_mode_information' +vbe_biosfn_return_mode_information: ; 0xc406d LB 0x9f + push bp ; 55 ; 0xc406d vbe.c:399 + mov bp, sp ; 89 e5 ; 0xc406e + push si ; 56 ; 0xc4070 + push di ; 57 ; 0xc4071 + push ax ; 50 ; 0xc4072 + push ax ; 50 ; 0xc4073 + mov ax, dx ; 89 d0 ; 0xc4074 + mov si, bx ; 89 de ; 0xc4076 + mov bx, cx ; 89 cb ; 0xc4078 + test dh, 040h ; f6 c6 40 ; 0xc407a vbe.c:410 + je short 04084h ; 74 05 ; 0xc407d + mov dx, strict word 00001h ; ba 01 00 ; 0xc407f + jmp short 04086h ; eb 02 ; 0xc4082 + xor dx, dx ; 31 d2 ; 0xc4084 + and ah, 001h ; 80 e4 01 ; 0xc4086 vbe.c:411 + call 03ed6h ; e8 4a fe ; 0xc4089 vbe.c:413 + mov word [bp-006h], ax ; 89 46 fa ; 0xc408c + test ax, ax ; 85 c0 ; 0xc408f vbe.c:415 + je short 040fah ; 74 67 ; 0xc4091 + mov cx, 00100h ; b9 00 01 ; 0xc4093 vbe.c:420 + xor ax, ax ; 31 c0 ; 0xc4096 + mov di, bx ; 89 df ; 0xc4098 + mov es, si ; 8e c6 ; 0xc409a + jcxz 040a0h ; e3 02 ; 0xc409c + rep stosb ; f3 aa ; 0xc409e + xor cx, cx ; 31 c9 ; 0xc40a0 vbe.c:421 + jmp short 040a9h ; eb 05 ; 0xc40a2 + cmp cx, strict byte 00042h ; 83 f9 42 ; 0xc40a4 + jnc short 040c2h ; 73 19 ; 0xc40a7 + mov dx, word [bp-006h] ; 8b 56 fa ; 0xc40a9 vbe.c:424 + inc dx ; 42 ; 0xc40ac + inc dx ; 42 ; 0xc40ad + add dx, cx ; 01 ca ; 0xc40ae + mov ax, 003b6h ; b8 b6 03 ; 0xc40b0 + call 03e6ah ; e8 b4 fd ; 0xc40b3 + mov di, bx ; 89 df ; 0xc40b6 vbe.c:425 + add di, cx ; 01 cf ; 0xc40b8 + mov es, si ; 8e c6 ; 0xc40ba vbe.c:52 + mov byte [es:di], al ; 26 88 05 ; 0xc40bc + inc cx ; 41 ; 0xc40bf vbe.c:426 + jmp short 040a4h ; eb e2 ; 0xc40c0 + lea di, [bx+002h] ; 8d 7f 02 ; 0xc40c2 vbe.c:427 + mov es, si ; 8e c6 ; 0xc40c5 vbe.c:47 + mov al, byte [es:di] ; 26 8a 05 ; 0xc40c7 + test AL, strict byte 001h ; a8 01 ; 0xc40ca vbe.c:428 + je short 040deh ; 74 10 ; 0xc40cc + lea di, [bx+00ch] ; 8d 7f 0c ; 0xc40ce vbe.c:429 + mov word [es:di], 00629h ; 26 c7 05 29 06 ; 0xc40d1 vbe.c:62 + lea di, [bx+00eh] ; 8d 7f 0e ; 0xc40d6 vbe.c:431 + mov word [es:di], 0c000h ; 26 c7 05 00 c0 ; 0xc40d9 vbe.c:62 + mov ax, strict word 0000bh ; b8 0b 00 ; 0xc40de vbe.c:434 + mov dx, 001ceh ; ba ce 01 ; 0xc40e1 + call 00570h ; e8 89 c4 ; 0xc40e4 + mov dx, 001cfh ; ba cf 01 ; 0xc40e7 vbe.c:435 + call 00577h ; e8 8a c4 ; 0xc40ea + add bx, strict byte 0002ah ; 83 c3 2a ; 0xc40ed + mov es, si ; 8e c6 ; 0xc40f0 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc40f2 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc40f5 vbe.c:437 + jmp short 040fdh ; eb 03 ; 0xc40f8 vbe.c:438 + mov ax, 00100h ; b8 00 01 ; 0xc40fa vbe.c:442 + push SS ; 16 ; 0xc40fd vbe.c:445 + pop ES ; 07 ; 0xc40fe + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc40ff + mov word [es:bx], ax ; 26 89 07 ; 0xc4102 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc4105 vbe.c:446 + pop di ; 5f ; 0xc4108 + pop si ; 5e ; 0xc4109 + pop bp ; 5d ; 0xc410a + retn ; c3 ; 0xc410b + ; disGetNextSymbol 0xc410c LB 0x426 -> off=0x0 cb=00000000000000e7 uValue=00000000000c410c 'vbe_biosfn_set_mode' +vbe_biosfn_set_mode: ; 0xc410c LB 0xe7 + push bp ; 55 ; 0xc410c vbe.c:458 + mov bp, sp ; 89 e5 ; 0xc410d + push si ; 56 ; 0xc410f + push di ; 57 ; 0xc4110 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc4111 + mov si, ax ; 89 c6 ; 0xc4114 + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc4116 + test byte [bp-009h], 040h ; f6 46 f7 40 ; 0xc4119 vbe.c:466 + je short 04124h ; 74 05 ; 0xc411d + mov ax, strict word 00001h ; b8 01 00 ; 0xc411f + jmp short 04126h ; eb 02 ; 0xc4122 + xor ax, ax ; 31 c0 ; 0xc4124 + mov dx, ax ; 89 c2 ; 0xc4126 + test ax, ax ; 85 c0 ; 0xc4128 vbe.c:467 + je short 0412fh ; 74 03 ; 0xc412a + mov ax, strict word 00040h ; b8 40 00 ; 0xc412c + mov byte [bp-008h], al ; 88 46 f8 ; 0xc412f + test byte [bp-009h], 080h ; f6 46 f7 80 ; 0xc4132 vbe.c:468 + je short 0413dh ; 74 05 ; 0xc4136 + mov ax, 00080h ; b8 80 00 ; 0xc4138 + jmp short 0413fh ; eb 02 ; 0xc413b + xor ax, ax ; 31 c0 ; 0xc413d + mov byte [bp-006h], al ; 88 46 fa ; 0xc413f + and byte [bp-009h], 001h ; 80 66 f7 01 ; 0xc4142 vbe.c:470 + cmp word [bp-00ah], 00100h ; 81 7e f6 00 01 ; 0xc4146 vbe.c:473 + jnc short 04160h ; 73 13 ; 0xc414b + xor ax, ax ; 31 c0 ; 0xc414d vbe.c:477 + call 005ddh ; e8 8b c4 ; 0xc414f + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc4152 vbe.c:481 + xor ah, ah ; 30 e4 ; 0xc4155 + call 0143fh ; e8 e5 d2 ; 0xc4157 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc415a vbe.c:482 + jmp near 041e7h ; e9 87 00 ; 0xc415d vbe.c:483 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc4160 vbe.c:486 + call 03ed6h ; e8 70 fd ; 0xc4163 + mov bx, ax ; 89 c3 ; 0xc4166 + test ax, ax ; 85 c0 ; 0xc4168 vbe.c:488 + je short 041e4h ; 74 78 ; 0xc416a + lea dx, [bx+014h] ; 8d 57 14 ; 0xc416c vbe.c:493 + mov ax, 003b6h ; b8 b6 03 ; 0xc416f + call 03e58h ; e8 e3 fc ; 0xc4172 + mov cx, ax ; 89 c1 ; 0xc4175 + lea dx, [bx+016h] ; 8d 57 16 ; 0xc4177 vbe.c:494 + mov ax, 003b6h ; b8 b6 03 ; 0xc417a + call 03e58h ; e8 d8 fc ; 0xc417d + mov di, ax ; 89 c7 ; 0xc4180 + lea dx, [bx+01bh] ; 8d 57 1b ; 0xc4182 vbe.c:495 + mov ax, 003b6h ; b8 b6 03 ; 0xc4185 + call 03e6ah ; e8 df fc ; 0xc4188 + mov bl, al ; 88 c3 ; 0xc418b + mov dl, al ; 88 c2 ; 0xc418d + xor ax, ax ; 31 c0 ; 0xc418f vbe.c:503 + call 005ddh ; e8 49 c4 ; 0xc4191 + cmp bl, 004h ; 80 fb 04 ; 0xc4194 vbe.c:505 + jne short 0419fh ; 75 06 ; 0xc4197 + mov ax, strict word 0006ah ; b8 6a 00 ; 0xc4199 vbe.c:507 + call 0143fh ; e8 a0 d2 ; 0xc419c + mov al, dl ; 88 d0 ; 0xc419f vbe.c:510 + xor ah, ah ; 30 e4 ; 0xc41a1 + call 03dcfh ; e8 29 fc ; 0xc41a3 + mov ax, cx ; 89 c8 ; 0xc41a6 vbe.c:511 + call 03d78h ; e8 cd fb ; 0xc41a8 + mov ax, di ; 89 f8 ; 0xc41ab vbe.c:512 + call 03d97h ; e8 e7 fb ; 0xc41ad + xor ax, ax ; 31 c0 ; 0xc41b0 vbe.c:513 + call 00603h ; e8 4e c4 ; 0xc41b2 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc41b5 vbe.c:514 + or dl, 001h ; 80 ca 01 ; 0xc41b8 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc41bb + xor ah, ah ; 30 e4 ; 0xc41be + or al, dl ; 08 d0 ; 0xc41c0 + call 005ddh ; e8 18 c4 ; 0xc41c2 + call 006d2h ; e8 0a c5 ; 0xc41c5 vbe.c:515 + mov bx, 000bah ; bb ba 00 ; 0xc41c8 vbe.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc41cb + mov es, ax ; 8e c0 ; 0xc41ce + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc41d0 + mov word [es:bx], ax ; 26 89 07 ; 0xc41d3 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc41d6 vbe.c:518 + or AL, strict byte 060h ; 0c 60 ; 0xc41d9 + mov bx, 00087h ; bb 87 00 ; 0xc41db vbe.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc41de + jmp near 0415ah ; e9 76 ff ; 0xc41e1 + mov ax, 00100h ; b8 00 01 ; 0xc41e4 vbe.c:527 + push SS ; 16 ; 0xc41e7 vbe.c:531 + pop ES ; 07 ; 0xc41e8 + mov word [es:si], ax ; 26 89 04 ; 0xc41e9 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc41ec vbe.c:532 + pop di ; 5f ; 0xc41ef + pop si ; 5e ; 0xc41f0 + pop bp ; 5d ; 0xc41f1 + retn ; c3 ; 0xc41f2 + ; disGetNextSymbol 0xc41f3 LB 0x33f -> off=0x0 cb=0000000000000008 uValue=00000000000c41f3 'vbe_biosfn_read_video_state_size' +vbe_biosfn_read_video_state_size: ; 0xc41f3 LB 0x8 + push bp ; 55 ; 0xc41f3 vbe.c:534 + mov bp, sp ; 89 e5 ; 0xc41f4 + mov ax, strict word 00012h ; b8 12 00 ; 0xc41f6 vbe.c:537 + pop bp ; 5d ; 0xc41f9 + retn ; c3 ; 0xc41fa + ; disGetNextSymbol 0xc41fb LB 0x337 -> off=0x0 cb=000000000000004b uValue=00000000000c41fb 'vbe_biosfn_save_video_state' +vbe_biosfn_save_video_state: ; 0xc41fb LB 0x4b + push bp ; 55 ; 0xc41fb vbe.c:539 + mov bp, sp ; 89 e5 ; 0xc41fc + push bx ; 53 ; 0xc41fe + push cx ; 51 ; 0xc41ff + push si ; 56 ; 0xc4200 + mov si, ax ; 89 c6 ; 0xc4201 + mov bx, dx ; 89 d3 ; 0xc4203 + mov ax, strict word 00004h ; b8 04 00 ; 0xc4205 vbe.c:543 + mov dx, 001ceh ; ba ce 01 ; 0xc4208 + out DX, ax ; ef ; 0xc420b + mov dx, 001cfh ; ba cf 01 ; 0xc420c vbe.c:544 + in ax, DX ; ed ; 0xc420f + mov es, si ; 8e c6 ; 0xc4210 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc4212 + inc bx ; 43 ; 0xc4215 vbe.c:546 + inc bx ; 43 ; 0xc4216 + test AL, strict byte 001h ; a8 01 ; 0xc4217 vbe.c:547 + je short 0423eh ; 74 23 ; 0xc4219 + mov cx, strict word 00001h ; b9 01 00 ; 0xc421b vbe.c:549 + jmp short 04225h ; eb 05 ; 0xc421e + cmp cx, strict byte 00009h ; 83 f9 09 ; 0xc4220 + jnbe short 0423eh ; 77 19 ; 0xc4223 + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc4225 vbe.c:550 + je short 0423bh ; 74 11 ; 0xc4228 + mov ax, cx ; 89 c8 ; 0xc422a vbe.c:551 + mov dx, 001ceh ; ba ce 01 ; 0xc422c + out DX, ax ; ef ; 0xc422f + mov dx, 001cfh ; ba cf 01 ; 0xc4230 vbe.c:552 + in ax, DX ; ed ; 0xc4233 + mov es, si ; 8e c6 ; 0xc4234 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc4236 + inc bx ; 43 ; 0xc4239 vbe.c:553 + inc bx ; 43 ; 0xc423a + inc cx ; 41 ; 0xc423b vbe.c:555 + jmp short 04220h ; eb e2 ; 0xc423c + lea sp, [bp-006h] ; 8d 66 fa ; 0xc423e vbe.c:556 + pop si ; 5e ; 0xc4241 + pop cx ; 59 ; 0xc4242 + pop bx ; 5b ; 0xc4243 + pop bp ; 5d ; 0xc4244 + retn ; c3 ; 0xc4245 + ; disGetNextSymbol 0xc4246 LB 0x2ec -> off=0x0 cb=000000000000008f uValue=00000000000c4246 'vbe_biosfn_restore_video_state' +vbe_biosfn_restore_video_state: ; 0xc4246 LB 0x8f + push bp ; 55 ; 0xc4246 vbe.c:559 + mov bp, sp ; 89 e5 ; 0xc4247 + push bx ; 53 ; 0xc4249 + push cx ; 51 ; 0xc424a + push si ; 56 ; 0xc424b + push ax ; 50 ; 0xc424c + mov cx, ax ; 89 c1 ; 0xc424d + mov bx, dx ; 89 d3 ; 0xc424f + mov es, ax ; 8e c0 ; 0xc4251 vbe.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc4253 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc4256 + inc bx ; 43 ; 0xc4259 vbe.c:564 + inc bx ; 43 ; 0xc425a + test byte [bp-008h], 001h ; f6 46 f8 01 ; 0xc425b vbe.c:566 + jne short 04271h ; 75 10 ; 0xc425f + mov ax, strict word 00004h ; b8 04 00 ; 0xc4261 vbe.c:567 + mov dx, 001ceh ; ba ce 01 ; 0xc4264 + out DX, ax ; ef ; 0xc4267 + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc4268 vbe.c:568 + mov dx, 001cfh ; ba cf 01 ; 0xc426b + out DX, ax ; ef ; 0xc426e + jmp short 042cdh ; eb 5c ; 0xc426f vbe.c:569 + mov ax, strict word 00001h ; b8 01 00 ; 0xc4271 vbe.c:570 + mov dx, 001ceh ; ba ce 01 ; 0xc4274 + out DX, ax ; ef ; 0xc4277 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc4278 vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc427b vbe.c:58 + out DX, ax ; ef ; 0xc427e + inc bx ; 43 ; 0xc427f vbe.c:572 + inc bx ; 43 ; 0xc4280 + mov ax, strict word 00002h ; b8 02 00 ; 0xc4281 + mov dx, 001ceh ; ba ce 01 ; 0xc4284 + out DX, ax ; ef ; 0xc4287 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc4288 vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc428b vbe.c:58 + out DX, ax ; ef ; 0xc428e + inc bx ; 43 ; 0xc428f vbe.c:575 + inc bx ; 43 ; 0xc4290 + mov ax, strict word 00003h ; b8 03 00 ; 0xc4291 + mov dx, 001ceh ; ba ce 01 ; 0xc4294 + out DX, ax ; ef ; 0xc4297 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc4298 vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc429b vbe.c:58 + out DX, ax ; ef ; 0xc429e + inc bx ; 43 ; 0xc429f vbe.c:578 + inc bx ; 43 ; 0xc42a0 + mov ax, strict word 00004h ; b8 04 00 ; 0xc42a1 + mov dx, 001ceh ; ba ce 01 ; 0xc42a4 + out DX, ax ; ef ; 0xc42a7 + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc42a8 vbe.c:580 + mov dx, 001cfh ; ba cf 01 ; 0xc42ab + out DX, ax ; ef ; 0xc42ae + mov si, strict word 00005h ; be 05 00 ; 0xc42af vbe.c:582 + jmp short 042b9h ; eb 05 ; 0xc42b2 + cmp si, strict byte 00009h ; 83 fe 09 ; 0xc42b4 + jnbe short 042cdh ; 77 14 ; 0xc42b7 + mov ax, si ; 89 f0 ; 0xc42b9 vbe.c:583 + mov dx, 001ceh ; ba ce 01 ; 0xc42bb + out DX, ax ; ef ; 0xc42be + mov es, cx ; 8e c1 ; 0xc42bf vbe.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc42c1 + mov dx, 001cfh ; ba cf 01 ; 0xc42c4 vbe.c:58 + out DX, ax ; ef ; 0xc42c7 + inc bx ; 43 ; 0xc42c8 vbe.c:585 + inc bx ; 43 ; 0xc42c9 + inc si ; 46 ; 0xc42ca vbe.c:586 + jmp short 042b4h ; eb e7 ; 0xc42cb + lea sp, [bp-006h] ; 8d 66 fa ; 0xc42cd vbe.c:588 + pop si ; 5e ; 0xc42d0 + pop cx ; 59 ; 0xc42d1 + pop bx ; 5b ; 0xc42d2 + pop bp ; 5d ; 0xc42d3 + retn ; c3 ; 0xc42d4 + ; disGetNextSymbol 0xc42d5 LB 0x25d -> off=0x0 cb=000000000000008c uValue=00000000000c42d5 'vbe_biosfn_save_restore_state' +vbe_biosfn_save_restore_state: ; 0xc42d5 LB 0x8c + push bp ; 55 ; 0xc42d5 vbe.c:604 + mov bp, sp ; 89 e5 ; 0xc42d6 + push si ; 56 ; 0xc42d8 + push di ; 57 ; 0xc42d9 + push ax ; 50 ; 0xc42da + mov si, ax ; 89 c6 ; 0xc42db + mov word [bp-006h], dx ; 89 56 fa ; 0xc42dd + mov ax, bx ; 89 d8 ; 0xc42e0 + mov bx, word [bp+004h] ; 8b 5e 04 ; 0xc42e2 + mov di, strict word 0004fh ; bf 4f 00 ; 0xc42e5 vbe.c:609 + xor ah, ah ; 30 e4 ; 0xc42e8 vbe.c:610 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc42ea + je short 04334h ; 74 45 ; 0xc42ed + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc42ef + je short 04318h ; 74 24 ; 0xc42f2 + test ax, ax ; 85 c0 ; 0xc42f4 + jne short 04350h ; 75 58 ; 0xc42f6 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc42f8 vbe.c:612 + call 0324ch ; e8 4e ef ; 0xc42fb + mov cx, ax ; 89 c1 ; 0xc42fe + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc4300 vbe.c:616 + je short 0430bh ; 74 05 ; 0xc4304 + call 041f3h ; e8 ea fe ; 0xc4306 vbe.c:617 + add ax, cx ; 01 c8 ; 0xc4309 + add ax, strict word 0003fh ; 05 3f 00 ; 0xc430b vbe.c:618 + shr ax, 006h ; c1 e8 06 ; 0xc430e + push SS ; 16 ; 0xc4311 + pop ES ; 07 ; 0xc4312 + mov word [es:bx], ax ; 26 89 07 ; 0xc4313 + jmp short 04353h ; eb 3b ; 0xc4316 vbe.c:619 + push SS ; 16 ; 0xc4318 vbe.c:621 + pop ES ; 07 ; 0xc4319 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc431a + mov dx, cx ; 89 ca ; 0xc431d vbe.c:622 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc431f + call 03287h ; e8 62 ef ; 0xc4322 + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc4325 vbe.c:626 + je short 04353h ; 74 28 ; 0xc4329 + mov dx, ax ; 89 c2 ; 0xc432b vbe.c:627 + mov ax, cx ; 89 c8 ; 0xc432d + call 041fbh ; e8 c9 fe ; 0xc432f + jmp short 04353h ; eb 1f ; 0xc4332 vbe.c:628 + push SS ; 16 ; 0xc4334 vbe.c:630 + pop ES ; 07 ; 0xc4335 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc4336 + mov dx, cx ; 89 ca ; 0xc4339 vbe.c:631 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc433b + call 0355fh ; e8 1e f2 ; 0xc433e + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc4341 vbe.c:635 + je short 04353h ; 74 0c ; 0xc4345 + mov dx, ax ; 89 c2 ; 0xc4347 vbe.c:636 + mov ax, cx ; 89 c8 ; 0xc4349 + call 04246h ; e8 f8 fe ; 0xc434b + jmp short 04353h ; eb 03 ; 0xc434e vbe.c:637 + mov di, 00100h ; bf 00 01 ; 0xc4350 vbe.c:640 + push SS ; 16 ; 0xc4353 vbe.c:643 + pop ES ; 07 ; 0xc4354 + mov word [es:si], di ; 26 89 3c ; 0xc4355 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc4358 vbe.c:644 + pop di ; 5f ; 0xc435b + pop si ; 5e ; 0xc435c + pop bp ; 5d ; 0xc435d + retn 00002h ; c2 02 00 ; 0xc435e + ; disGetNextSymbol 0xc4361 LB 0x1d1 -> off=0x0 cb=00000000000000df uValue=00000000000c4361 'vbe_biosfn_get_set_scanline_length' +vbe_biosfn_get_set_scanline_length: ; 0xc4361 LB 0xdf + push bp ; 55 ; 0xc4361 vbe.c:665 + mov bp, sp ; 89 e5 ; 0xc4362 + push si ; 56 ; 0xc4364 + push di ; 57 ; 0xc4365 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc4366 + push ax ; 50 ; 0xc4369 + mov di, dx ; 89 d7 ; 0xc436a + mov word [bp-008h], bx ; 89 5e f8 ; 0xc436c + mov si, cx ; 89 ce ; 0xc436f + call 03deeh ; e8 7a fa ; 0xc4371 vbe.c:674 + cmp AL, strict byte 00fh ; 3c 0f ; 0xc4374 vbe.c:675 + jne short 0437dh ; 75 05 ; 0xc4376 + mov bx, strict word 00010h ; bb 10 00 ; 0xc4378 + jmp short 04381h ; eb 04 ; 0xc437b + xor ah, ah ; 30 e4 ; 0xc437d + mov bx, ax ; 89 c3 ; 0xc437f + mov byte [bp-006h], bl ; 88 5e fa ; 0xc4381 + call 03e26h ; e8 9f fa ; 0xc4384 vbe.c:676 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc4387 + mov word [bp-00ch], strict word 0004fh ; c7 46 f4 4f 00 ; 0xc438a vbe.c:677 + push SS ; 16 ; 0xc438f vbe.c:678 + pop ES ; 07 ; 0xc4390 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc4391 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc4394 + mov cl, byte [es:di] ; 26 8a 0d ; 0xc4397 vbe.c:679 + cmp cl, 002h ; 80 f9 02 ; 0xc439a vbe.c:683 + je short 043abh ; 74 0c ; 0xc439d + cmp cl, 001h ; 80 f9 01 ; 0xc439f + je short 043d1h ; 74 2d ; 0xc43a2 + test cl, cl ; 84 c9 ; 0xc43a4 + je short 043cch ; 74 24 ; 0xc43a6 + jmp near 04429h ; e9 7e 00 ; 0xc43a8 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc43ab vbe.c:685 + cmp AL, strict byte 004h ; 3c 04 ; 0xc43ae + jne short 043b7h ; 75 05 ; 0xc43b0 + sal bx, 003h ; c1 e3 03 ; 0xc43b2 vbe.c:686 + jmp short 043cch ; eb 15 ; 0xc43b5 vbe.c:687 + xor ah, ah ; 30 e4 ; 0xc43b7 vbe.c:688 + cwd ; 99 ; 0xc43b9 + sal dx, 003h ; c1 e2 03 ; 0xc43ba + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc43bd + sar ax, 003h ; c1 f8 03 ; 0xc43bf + mov cx, ax ; 89 c1 ; 0xc43c2 + mov ax, bx ; 89 d8 ; 0xc43c4 + xor dx, dx ; 31 d2 ; 0xc43c6 + div cx ; f7 f1 ; 0xc43c8 + mov bx, ax ; 89 c3 ; 0xc43ca + mov ax, bx ; 89 d8 ; 0xc43cc vbe.c:691 + call 03e07h ; e8 36 fa ; 0xc43ce + call 03e26h ; e8 52 fa ; 0xc43d1 vbe.c:694 + mov cx, ax ; 89 c1 ; 0xc43d4 + push SS ; 16 ; 0xc43d6 vbe.c:695 + pop ES ; 07 ; 0xc43d7 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc43d8 + mov word [es:bx], ax ; 26 89 07 ; 0xc43db + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc43de vbe.c:696 + cmp AL, strict byte 004h ; 3c 04 ; 0xc43e1 + jne short 043ech ; 75 07 ; 0xc43e3 + mov bx, cx ; 89 cb ; 0xc43e5 vbe.c:697 + shr bx, 003h ; c1 eb 03 ; 0xc43e7 + jmp short 043ffh ; eb 13 ; 0xc43ea vbe.c:698 + xor ah, ah ; 30 e4 ; 0xc43ec vbe.c:699 + cwd ; 99 ; 0xc43ee + sal dx, 003h ; c1 e2 03 ; 0xc43ef + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc43f2 + sar ax, 003h ; c1 f8 03 ; 0xc43f4 + mov bx, ax ; 89 c3 ; 0xc43f7 + mov ax, cx ; 89 c8 ; 0xc43f9 + mul bx ; f7 e3 ; 0xc43fb + mov bx, ax ; 89 c3 ; 0xc43fd + add bx, strict byte 00003h ; 83 c3 03 ; 0xc43ff vbe.c:700 + and bl, 0fch ; 80 e3 fc ; 0xc4402 + push SS ; 16 ; 0xc4405 vbe.c:701 + pop ES ; 07 ; 0xc4406 + mov word [es:di], bx ; 26 89 1d ; 0xc4407 + call 03e3fh ; e8 32 fa ; 0xc440a vbe.c:702 + push SS ; 16 ; 0xc440d + pop ES ; 07 ; 0xc440e + mov word [es:si], ax ; 26 89 04 ; 0xc440f + call 03db6h ; e8 a1 f9 ; 0xc4412 vbe.c:703 + push SS ; 16 ; 0xc4415 + pop ES ; 07 ; 0xc4416 + cmp ax, word [es:si] ; 26 3b 04 ; 0xc4417 + jbe short 0442eh ; 76 12 ; 0xc441a + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc441c vbe.c:704 + call 03e07h ; e8 e5 f9 ; 0xc441f + mov word [bp-00ch], 00200h ; c7 46 f4 00 02 ; 0xc4422 vbe.c:705 + jmp short 0442eh ; eb 05 ; 0xc4427 vbe.c:707 + mov word [bp-00ch], 00100h ; c7 46 f4 00 01 ; 0xc4429 vbe.c:710 + push SS ; 16 ; 0xc442e vbe.c:713 + pop ES ; 07 ; 0xc442f + mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xc4430 + mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xc4433 + mov word [es:bx], ax ; 26 89 07 ; 0xc4436 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc4439 vbe.c:714 + pop di ; 5f ; 0xc443c + pop si ; 5e ; 0xc443d + pop bp ; 5d ; 0xc443e + retn ; c3 ; 0xc443f + ; disGetNextSymbol 0xc4440 LB 0xf2 -> off=0x0 cb=00000000000000f2 uValue=00000000000c4440 'private_biosfn_custom_mode' +private_biosfn_custom_mode: ; 0xc4440 LB 0xf2 + push bp ; 55 ; 0xc4440 vbe.c:740 + mov bp, sp ; 89 e5 ; 0xc4441 + push si ; 56 ; 0xc4443 + push di ; 57 ; 0xc4444 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc4445 + mov di, ax ; 89 c7 ; 0xc4448 + mov si, dx ; 89 d6 ; 0xc444a + mov dx, cx ; 89 ca ; 0xc444c + mov word [bp-00ah], strict word 0004fh ; c7 46 f6 4f 00 ; 0xc444e vbe.c:753 + push SS ; 16 ; 0xc4453 vbe.c:754 + pop ES ; 07 ; 0xc4454 + mov al, byte [es:si] ; 26 8a 04 ; 0xc4455 + test al, al ; 84 c0 ; 0xc4458 vbe.c:755 + jne short 0447eh ; 75 22 ; 0xc445a + push SS ; 16 ; 0xc445c vbe.c:757 + pop ES ; 07 ; 0xc445d + mov cx, word [es:bx] ; 26 8b 0f ; 0xc445e + mov bx, dx ; 89 d3 ; 0xc4461 vbe.c:758 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc4463 + mov ax, word [es:si] ; 26 8b 04 ; 0xc4466 vbe.c:759 + shr ax, 008h ; c1 e8 08 ; 0xc4469 + and ax, strict word 0007fh ; 25 7f 00 ; 0xc446c + mov byte [bp-008h], al ; 88 46 f8 ; 0xc446f + cmp AL, strict byte 008h ; 3c 08 ; 0xc4472 vbe.c:764 + je short 04486h ; 74 10 ; 0xc4474 + cmp AL, strict byte 010h ; 3c 10 ; 0xc4476 + je short 04486h ; 74 0c ; 0xc4478 + cmp AL, strict byte 020h ; 3c 20 ; 0xc447a + je short 04486h ; 74 08 ; 0xc447c + mov word [bp-00ah], 00100h ; c7 46 f6 00 01 ; 0xc447e vbe.c:765 + jmp near 04523h ; e9 9d 00 ; 0xc4483 vbe.c:766 + push SS ; 16 ; 0xc4486 vbe.c:770 + pop ES ; 07 ; 0xc4487 + test byte [es:si+001h], 080h ; 26 f6 44 01 80 ; 0xc4488 + je short 04494h ; 74 05 ; 0xc448d + mov ax, strict word 00040h ; b8 40 00 ; 0xc448f + jmp short 04496h ; eb 02 ; 0xc4492 + xor ax, ax ; 31 c0 ; 0xc4494 + mov byte [bp-006h], al ; 88 46 fa ; 0xc4496 + cmp cx, 00280h ; 81 f9 80 02 ; 0xc4499 vbe.c:773 + jnc short 044a4h ; 73 05 ; 0xc449d + mov cx, 00280h ; b9 80 02 ; 0xc449f vbe.c:774 + jmp short 044adh ; eb 09 ; 0xc44a2 vbe.c:775 + cmp cx, 00a00h ; 81 f9 00 0a ; 0xc44a4 + jbe short 044adh ; 76 03 ; 0xc44a8 + mov cx, 00a00h ; b9 00 0a ; 0xc44aa vbe.c:776 + cmp bx, 001e0h ; 81 fb e0 01 ; 0xc44ad vbe.c:777 + jnc short 044b8h ; 73 05 ; 0xc44b1 + mov bx, 001e0h ; bb e0 01 ; 0xc44b3 vbe.c:778 + jmp short 044c1h ; eb 09 ; 0xc44b6 vbe.c:779 + cmp bx, 00780h ; 81 fb 80 07 ; 0xc44b8 + jbe short 044c1h ; 76 03 ; 0xc44bc + mov bx, 00780h ; bb 80 07 ; 0xc44be vbe.c:780 + mov dx, strict word 0ffffh ; ba ff ff ; 0xc44c1 vbe.c:786 + mov ax, 003b6h ; b8 b6 03 ; 0xc44c4 + call 03e58h ; e8 8e f9 ; 0xc44c7 + mov si, ax ; 89 c6 ; 0xc44ca + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc44cc vbe.c:789 + xor ah, ah ; 30 e4 ; 0xc44cf + cwd ; 99 ; 0xc44d1 + sal dx, 003h ; c1 e2 03 ; 0xc44d2 + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc44d5 + sar ax, 003h ; c1 f8 03 ; 0xc44d7 + mov dx, ax ; 89 c2 ; 0xc44da + mov ax, cx ; 89 c8 ; 0xc44dc + mul dx ; f7 e2 ; 0xc44de + add ax, strict word 00003h ; 05 03 00 ; 0xc44e0 vbe.c:790 + and AL, strict byte 0fch ; 24 fc ; 0xc44e3 + mov dx, bx ; 89 da ; 0xc44e5 vbe.c:792 + mul dx ; f7 e2 ; 0xc44e7 + cmp dx, si ; 39 f2 ; 0xc44e9 vbe.c:794 + jnbe short 044f3h ; 77 06 ; 0xc44eb + jne short 044fah ; 75 0b ; 0xc44ed + test ax, ax ; 85 c0 ; 0xc44ef + jbe short 044fah ; 76 07 ; 0xc44f1 + mov word [bp-00ah], 00200h ; c7 46 f6 00 02 ; 0xc44f3 vbe.c:796 + jmp short 04523h ; eb 29 ; 0xc44f8 vbe.c:797 + xor ax, ax ; 31 c0 ; 0xc44fa vbe.c:801 + call 005ddh ; e8 de c0 ; 0xc44fc + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc44ff vbe.c:802 + xor ah, ah ; 30 e4 ; 0xc4502 + call 03dcfh ; e8 c8 f8 ; 0xc4504 + mov ax, cx ; 89 c8 ; 0xc4507 vbe.c:803 + call 03d78h ; e8 6c f8 ; 0xc4509 + mov ax, bx ; 89 d8 ; 0xc450c vbe.c:804 + call 03d97h ; e8 86 f8 ; 0xc450e + xor ax, ax ; 31 c0 ; 0xc4511 vbe.c:805 + call 00603h ; e8 ed c0 ; 0xc4513 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc4516 vbe.c:806 + or AL, strict byte 001h ; 0c 01 ; 0xc4519 + xor ah, ah ; 30 e4 ; 0xc451b + call 005ddh ; e8 bd c0 ; 0xc451d + call 006d2h ; e8 af c1 ; 0xc4520 vbe.c:807 + push SS ; 16 ; 0xc4523 vbe.c:815 + pop ES ; 07 ; 0xc4524 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc4525 + mov word [es:di], ax ; 26 89 05 ; 0xc4528 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc452b vbe.c:816 + pop di ; 5f ; 0xc452e + pop si ; 5e ; 0xc452f + pop bp ; 5d ; 0xc4530 + retn ; c3 ; 0xc4531 + + ; Padding 0x10e bytes at 0xc4532 + times 270 db 0 + +section VBE32 progbits vstart=0x4640 align=1 ; size=0x115 class=CODE group=AUTO + ; disGetNextSymbol 0xc4640 LB 0x115 -> off=0x0 cb=0000000000000114 uValue=00000000000c0000 'vesa_pm_start' +vesa_pm_start: ; 0xc4640 LB 0x114 + sbb byte [bx+si], al ; 18 00 ; 0xc4640 + dec di ; 4f ; 0xc4642 + add byte [bx+si], dl ; 00 10 ; 0xc4643 + add word [bx+si], cx ; 01 08 ; 0xc4645 + add dh, cl ; 00 ce ; 0xc4647 + add di, cx ; 01 cf ; 0xc4649 + add di, cx ; 01 cf ; 0xc464b + add ax, dx ; 01 d0 ; 0xc464d + add word [bp-048fdh], si ; 01 b6 03 b7 ; 0xc464f + db 003h, 0ffh + ; add di, di ; 03 ff ; 0xc4653 + db 0ffh + db 0ffh + jmp word [bp-07dh] ; ff 66 83 ; 0xc4657 + sti ; fb ; 0xc465a + add byte [si+005h], dh ; 00 74 05 ; 0xc465b + mov eax, strict dword 066c30100h ; 66 b8 00 01 c3 66 ; 0xc465e vberom.asm:825 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc4664 + push edx ; 66 52 ; 0xc4666 vberom.asm:829 + push eax ; 66 50 ; 0xc4668 vberom.asm:830 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc466a vberom.asm:831 + add ax, 06600h ; 05 00 66 ; 0xc4670 + out DX, ax ; ef ; 0xc4673 + pop eax ; 66 58 ; 0xc4674 vberom.asm:834 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc4676 vberom.asm:835 + in eax, DX ; 66 ed ; 0xc467c vberom.asm:837 + pop edx ; 66 5a ; 0xc467e vberom.asm:838 + db 066h, 03bh, 0d0h + ; cmp edx, eax ; 66 3b d0 ; 0xc4680 vberom.asm:839 + jne short 0468ah ; 75 05 ; 0xc4683 vberom.asm:840 + mov eax, strict dword 066c3004fh ; 66 b8 4f 00 c3 66 ; 0xc4685 vberom.asm:841 + mov ax, 0014fh ; b8 4f 01 ; 0xc468b + retn ; c3 ; 0xc468e vberom.asm:845 + cmp bl, 080h ; 80 fb 80 ; 0xc468f vberom.asm:847 + je short 0469eh ; 74 0a ; 0xc4692 vberom.asm:848 + cmp bl, 000h ; 80 fb 00 ; 0xc4694 vberom.asm:849 + je short 046aeh ; 74 15 ; 0xc4697 vberom.asm:850 + mov eax, strict dword 052c30100h ; 66 b8 00 01 c3 52 ; 0xc4699 vberom.asm:851 + mov edx, strict dword 0a8ec03dah ; 66 ba da 03 ec a8 ; 0xc469f vberom.asm:855 + or byte [di-005h], dh ; 08 75 fb ; 0xc46a5 + in AL, DX ; ec ; 0xc46a8 vberom.asm:861 + test AL, strict byte 008h ; a8 08 ; 0xc46a9 vberom.asm:862 + je short 046a8h ; 74 fb ; 0xc46ab vberom.asm:863 + pop dx ; 5a ; 0xc46ad vberom.asm:864 + push ax ; 50 ; 0xc46ae vberom.asm:868 + push cx ; 51 ; 0xc46af vberom.asm:869 + push dx ; 52 ; 0xc46b0 vberom.asm:870 + push si ; 56 ; 0xc46b1 vberom.asm:871 + push di ; 57 ; 0xc46b2 vberom.asm:872 + sal dx, 010h ; c1 e2 10 ; 0xc46b3 vberom.asm:873 + and cx, strict word 0ffffh ; 81 e1 ff ff ; 0xc46b6 vberom.asm:874 + add byte [bx+si], al ; 00 00 ; 0xc46ba + db 00bh, 0cah + ; or cx, dx ; 0b ca ; 0xc46bc vberom.asm:875 + sal cx, 002h ; c1 e1 02 ; 0xc46be vberom.asm:876 + db 08bh, 0c1h + ; mov ax, cx ; 8b c1 ; 0xc46c1 vberom.asm:877 + push ax ; 50 ; 0xc46c3 vberom.asm:878 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc46c4 vberom.asm:879 + push ES ; 06 ; 0xc46ca + add byte [bp-011h], ah ; 00 66 ef ; 0xc46cb + mov edx, strict dword 0ed6601cfh ; 66 ba cf 01 66 ed ; 0xc46ce vberom.asm:882 + db 00fh, 0b7h, 0c8h + ; movzx cx, ax ; 0f b7 c8 ; 0xc46d4 vberom.asm:884 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc46d7 vberom.asm:885 + add ax, word [bx+si] ; 03 00 ; 0xc46dd + out DX, eax ; 66 ef ; 0xc46df vberom.asm:887 + mov edx, strict dword 0ed6601cfh ; 66 ba cf 01 66 ed ; 0xc46e1 vberom.asm:888 + db 00fh, 0b7h, 0f0h + ; movzx si, ax ; 0f b7 f0 ; 0xc46e7 vberom.asm:890 + pop ax ; 58 ; 0xc46ea vberom.asm:891 + cmp si, strict byte 00004h ; 83 fe 04 ; 0xc46eb vberom.asm:893 + je short 04707h ; 74 17 ; 0xc46ee vberom.asm:894 + add si, strict byte 00007h ; 83 c6 07 ; 0xc46f0 vberom.asm:895 + shr si, 003h ; c1 ee 03 ; 0xc46f3 vberom.asm:896 + imul cx, si ; 0f af ce ; 0xc46f6 vberom.asm:897 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc46f9 vberom.asm:898 + div cx ; f7 f1 ; 0xc46fb vberom.asm:899 + db 08bh, 0f8h + ; mov di, ax ; 8b f8 ; 0xc46fd vberom.asm:900 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc46ff vberom.asm:901 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc4701 vberom.asm:902 + div si ; f7 f6 ; 0xc4703 vberom.asm:903 + jmp short 04713h ; eb 0c ; 0xc4705 vberom.asm:904 + shr cx, 1 ; d1 e9 ; 0xc4707 vberom.asm:907 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc4709 vberom.asm:908 + div cx ; f7 f1 ; 0xc470b vberom.asm:909 + db 08bh, 0f8h + ; mov di, ax ; 8b f8 ; 0xc470d vberom.asm:910 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc470f vberom.asm:911 + sal ax, 1 ; d1 e0 ; 0xc4711 vberom.asm:912 + push edx ; 66 52 ; 0xc4713 vberom.asm:915 + push eax ; 66 50 ; 0xc4715 vberom.asm:916 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc4717 vberom.asm:917 + or byte [bx+si], al ; 08 00 ; 0xc471d + out DX, eax ; 66 ef ; 0xc471f vberom.asm:919 + pop eax ; 66 58 ; 0xc4721 vberom.asm:920 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc4723 vberom.asm:921 + pop edx ; 66 5a ; 0xc4729 vberom.asm:923 + db 066h, 08bh, 0c7h + ; mov eax, edi ; 66 8b c7 ; 0xc472b vberom.asm:925 + push edx ; 66 52 ; 0xc472e vberom.asm:926 + push eax ; 66 50 ; 0xc4730 vberom.asm:927 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc4732 vberom.asm:928 + or word [bx+si], ax ; 09 00 ; 0xc4738 + out DX, eax ; 66 ef ; 0xc473a vberom.asm:930 + pop eax ; 66 58 ; 0xc473c vberom.asm:931 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc473e vberom.asm:932 + pop edx ; 66 5a ; 0xc4744 vberom.asm:934 + pop di ; 5f ; 0xc4746 vberom.asm:936 + pop si ; 5e ; 0xc4747 vberom.asm:937 + pop dx ; 5a ; 0xc4748 vberom.asm:938 + pop cx ; 59 ; 0xc4749 vberom.asm:939 + pop ax ; 58 ; 0xc474a vberom.asm:940 + mov eax, strict dword 066c3004fh ; 66 b8 4f 00 c3 66 ; 0xc474b vberom.asm:941 + mov ax, 0014fh ; b8 4f 01 ; 0xc4751 + ; disGetNextSymbol 0xc4754 LB 0x1 -> off=0x0 cb=0000000000000001 uValue=0000000000000114 'vesa_pm_end' +vesa_pm_end: ; 0xc4754 LB 0x1 + retn ; c3 ; 0xc4754 vberom.asm:946 + + ; Padding 0x2b bytes at 0xc4755 + times 43 db 0 + +section _DATA progbits vstart=0x4780 align=1 ; size=0x374d class=DATA group=DGROUP + ; disGetNextSymbol 0xc4780 LB 0x374d -> off=0x0 cb=000000000000002f uValue=00000000000c0000 '_msg_vga_init' +_msg_vga_init: ; 0xc4780 LB 0x2f + db 'Oracle VM VirtualBox Version 7.0.14 VGA BIOS', 00dh, 00ah, 000h + ; disGetNextSymbol 0xc47af LB 0x371e -> off=0x0 cb=0000000000000080 uValue=00000000000c002f 'vga_modes' +vga_modes: ; 0xc47af LB 0x80 + db 000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h + db 002h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 003h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h + db 004h, 001h, 002h, 002h, 000h, 0b8h, 0ffh, 001h, 005h, 001h, 002h, 002h, 000h, 0b8h, 0ffh, 001h + db 006h, 001h, 002h, 001h, 000h, 0b8h, 0ffh, 001h, 007h, 000h, 001h, 004h, 000h, 0b0h, 0ffh, 000h + db 00dh, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 001h, 00eh, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 001h + db 00fh, 001h, 003h, 001h, 000h, 0a0h, 0ffh, 000h, 010h, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + db 011h, 001h, 003h, 001h, 000h, 0a0h, 0ffh, 002h, 012h, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + db 013h, 001h, 005h, 008h, 000h, 0a0h, 0ffh, 003h, 06ah, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + ; disGetNextSymbol 0xc482f LB 0x369e -> off=0x0 cb=0000000000000010 uValue=00000000000c00af 'line_to_vpti' +line_to_vpti: ; 0xc482f LB 0x10 + db 017h, 017h, 018h, 018h, 004h, 005h, 006h, 007h, 00dh, 00eh, 011h, 012h, 01ah, 01bh, 01ch, 01dh + ; disGetNextSymbol 0xc483f LB 0x368e -> off=0x0 cb=0000000000000004 uValue=00000000000c00bf 'dac_regs' +dac_regs: ; 0xc483f LB 0x4 + dd 0ff3f3f3fh + ; disGetNextSymbol 0xc4843 LB 0x368a -> off=0x0 cb=0000000000000780 uValue=00000000000c00c3 'video_param_table' +video_param_table: ; 0xc4843 LB 0x780 + db 028h, 018h, 008h, 000h, 008h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 008h, 000h, 008h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 008h, 000h, 010h, 001h, 003h, 000h, 002h, 063h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 008h, 000h, 010h, 001h, 003h, 000h, 002h, 063h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 008h, 000h, 040h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0a2h, 0ffh, 000h, 013h, 015h, 017h, 002h, 004h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 003h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 00fh, 00fh, 0ffh + db 028h, 018h, 008h, 000h, 040h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0a2h, 0ffh, 000h, 013h, 015h, 017h, 002h, 004h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 003h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 00fh, 00fh, 0ffh + db 050h, 018h, 008h, 000h, 040h, 001h, 001h, 000h, 006h, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 000h, 096h + db 0b9h, 0c2h, 0ffh, 000h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h + db 017h, 017h, 017h, 001h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 00dh, 00fh, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 000h, 003h, 000h, 003h, 0a6h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00dh, 063h + db 0bah, 0a3h, 0ffh, 000h, 008h, 008h, 008h, 008h, 008h, 008h, 008h, 010h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 00eh, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00ah, 000h, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 028h, 018h, 008h, 000h, 020h, 009h, 00fh, 000h, 006h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 018h, 008h, 000h, 040h, 001h, 00fh, 000h, 006h, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 000h, 096h + db 0b9h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 050h, 018h, 00eh, 000h, 080h, 001h, 00fh, 000h, 006h, 0a3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00fh, 063h + db 0bah, 0e3h, 0ffh, 000h, 008h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 008h, 000h, 000h, 000h + db 018h, 000h, 000h, 001h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 018h, 00eh, 000h, 080h, 001h, 00fh, 000h, 006h, 0a3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00fh, 063h + db 0bah, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 028h, 018h, 00eh, 000h, 008h, 009h, 003h, 000h, 002h, 0a3h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 014h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 00eh, 000h, 008h, 009h, 003h, 000h, 002h, 0a3h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 014h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 001h, 003h, 000h, 002h, 0a3h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 001h, 003h, 000h, 002h, 0a3h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 010h, 000h, 008h, 008h, 003h, 000h, 002h, 067h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 00ch, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 00fh, 0ffh + db 050h, 018h, 010h, 000h, 010h, 000h, 003h, 000h, 002h, 067h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 00ch, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 00fh, 0ffh + db 050h, 018h, 010h, 000h, 010h, 000h, 003h, 000h, 002h, 066h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 00fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 008h, 008h, 008h, 008h, 008h, 008h, 008h, 010h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 00eh, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00ah, 00fh, 0ffh + db 050h, 01dh, 010h, 000h, 0a0h, 001h, 00fh, 000h, 006h, 0e3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 00bh, 03eh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 0eah, 08ch, 0dfh, 028h, 000h, 0e7h + db 004h, 0c3h, 0ffh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h + db 03fh, 000h, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 01dh, 010h, 000h, 0a0h, 001h, 00fh, 000h, 006h, 0e3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 00bh, 03eh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 0eah, 08ch, 0dfh, 028h, 000h, 0e7h + db 004h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 028h, 018h, 008h, 000h, 020h, 001h, 00fh, 000h, 00eh, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 041h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 040h, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 008h, 009h, 00ah, 00bh, 00ch + db 00dh, 00eh, 00fh, 041h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 040h, 005h, 00fh, 0ffh + db 064h, 024h, 010h, 000h, 000h, 001h, 00fh, 000h, 006h, 0e3h, 07fh, 063h, 063h, 083h, 06bh, 01bh + db 072h, 0f0h, 000h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 059h, 08dh, 057h, 032h, 000h, 057h + db 073h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + ; disGetNextSymbol 0xc4fc3 LB 0x2f0a -> off=0x0 cb=00000000000000c0 uValue=00000000000c0843 'palette0' +palette0: ; 0xc4fc3 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5083 LB 0x2e4a -> off=0x0 cb=00000000000000c0 uValue=00000000000c0903 'palette1' +palette1: ; 0xc5083 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah + db 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah, 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah + db 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh, 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh + db 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah + db 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah, 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah + db 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh, 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh + db 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5143 LB 0x2d8a -> off=0x0 cb=00000000000000c0 uValue=00000000000c09c3 'palette2' +palette2: ; 0xc5143 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 02ah, 000h, 02ah, 02ah, 02ah, 000h, 000h, 015h, 000h, 000h, 03fh, 000h, 02ah + db 015h, 000h, 02ah, 03fh, 02ah, 000h, 015h, 02ah, 000h, 03fh, 02ah, 02ah, 015h, 02ah, 02ah, 03fh + db 000h, 015h, 000h, 000h, 015h, 02ah, 000h, 03fh, 000h, 000h, 03fh, 02ah, 02ah, 015h, 000h, 02ah + db 015h, 02ah, 02ah, 03fh, 000h, 02ah, 03fh, 02ah, 000h, 015h, 015h, 000h, 015h, 03fh, 000h, 03fh + db 015h, 000h, 03fh, 03fh, 02ah, 015h, 015h, 02ah, 015h, 03fh, 02ah, 03fh, 015h, 02ah, 03fh, 03fh + db 015h, 000h, 000h, 015h, 000h, 02ah, 015h, 02ah, 000h, 015h, 02ah, 02ah, 03fh, 000h, 000h, 03fh + db 000h, 02ah, 03fh, 02ah, 000h, 03fh, 02ah, 02ah, 015h, 000h, 015h, 015h, 000h, 03fh, 015h, 02ah + db 015h, 015h, 02ah, 03fh, 03fh, 000h, 015h, 03fh, 000h, 03fh, 03fh, 02ah, 015h, 03fh, 02ah, 03fh + db 015h, 015h, 000h, 015h, 015h, 02ah, 015h, 03fh, 000h, 015h, 03fh, 02ah, 03fh, 015h, 000h, 03fh + db 015h, 02ah, 03fh, 03fh, 000h, 03fh, 03fh, 02ah, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5203 LB 0x2cca -> off=0x0 cb=0000000000000300 uValue=00000000000c0a83 'palette3' +palette3: ; 0xc5203 LB 0x300 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 005h, 005h, 005h, 008h, 008h, 008h, 00bh, 00bh, 00bh, 00eh, 00eh, 00eh, 011h + db 011h, 011h, 014h, 014h, 014h, 018h, 018h, 018h, 01ch, 01ch, 01ch, 020h, 020h, 020h, 024h, 024h + db 024h, 028h, 028h, 028h, 02dh, 02dh, 02dh, 032h, 032h, 032h, 038h, 038h, 038h, 03fh, 03fh, 03fh + db 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh, 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h, 03fh, 03fh + db 000h, 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh + db 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h, 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 000h + db 000h, 03fh, 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh, 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h + db 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh, 02fh, 01fh + db 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 03fh, 03fh, 01fh, 037h, 03fh, 01fh, 02fh, 03fh, 01fh, 027h + db 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh, 02fh, 01fh, 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 037h + db 03fh, 01fh, 02fh, 03fh, 01fh, 027h, 03fh, 01fh, 01fh, 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh + db 02fh, 01fh, 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 037h, 03fh, 01fh, 02fh, 03fh, 01fh, 027h, 03fh + db 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h, 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh, 03fh, 03fh + db 02dh, 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h + db 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh, 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 02dh + db 02dh, 03fh, 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h, 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh + db 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 000h, 000h, 01ch, 007h, 000h, 01ch, 00eh, 000h + db 01ch, 015h, 000h, 01ch, 01ch, 000h, 01ch, 01ch, 000h, 015h, 01ch, 000h, 00eh, 01ch, 000h, 007h + db 01ch, 000h, 000h, 01ch, 007h, 000h, 01ch, 00eh, 000h, 01ch, 015h, 000h, 01ch, 01ch, 000h, 015h + db 01ch, 000h, 00eh, 01ch, 000h, 007h, 01ch, 000h, 000h, 01ch, 000h, 000h, 01ch, 007h, 000h, 01ch + db 00eh, 000h, 01ch, 015h, 000h, 01ch, 01ch, 000h, 015h, 01ch, 000h, 00eh, 01ch, 000h, 007h, 01ch + db 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h, 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh, 01ch, 01ch + db 00eh, 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h + db 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh, 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 00eh + db 00eh, 01ch, 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h, 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh + db 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch, 018h, 014h + db 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ch, 01ch, 014h, 01ah, 01ch, 014h, 018h, 01ch, 014h, 016h + db 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch, 018h, 014h, 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ah + db 01ch, 014h, 018h, 01ch, 014h, 016h, 01ch, 014h, 014h, 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch + db 018h, 014h, 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ah, 01ch, 014h, 018h, 01ch, 014h, 016h, 01ch + db 000h, 000h, 010h, 004h, 000h, 010h, 008h, 000h, 010h, 00ch, 000h, 010h, 010h, 000h, 010h, 010h + db 000h, 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 000h, 000h, 010h, 004h, 000h, 010h, 008h + db 000h, 010h, 00ch, 000h, 010h, 010h, 000h, 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 000h + db 000h, 010h, 000h, 000h, 010h, 004h, 000h, 010h, 008h, 000h, 010h, 00ch, 000h, 010h, 010h, 000h + db 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 008h, 008h, 010h, 00ah, 008h, 010h, 00ch, 008h + db 010h, 00eh, 008h, 010h, 010h, 008h, 010h, 010h, 008h, 00eh, 010h, 008h, 00ch, 010h, 008h, 00ah + db 010h, 008h, 008h, 010h, 00ah, 008h, 010h, 00ch, 008h, 010h, 00eh, 008h, 010h, 010h, 008h, 00eh + db 010h, 008h, 00ch, 010h, 008h, 00ah, 010h, 008h, 008h, 010h, 008h, 008h, 010h, 00ah, 008h, 010h + db 00ch, 008h, 010h, 00eh, 008h, 010h, 010h, 008h, 00eh, 010h, 008h, 00ch, 010h, 008h, 00ah, 010h + db 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh, 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh, 010h, 010h + db 00bh, 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh + db 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh, 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 00bh + db 00bh, 010h, 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh, 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh + db 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5503 LB 0x29ca -> off=0x0 cb=0000000000000010 uValue=00000000000c0d83 'static_functionality' +static_functionality: ; 0xc5503 LB 0x10 + db 0ffh, 0e0h, 00fh, 000h, 000h, 000h, 000h, 007h, 002h, 008h, 0e7h, 00ch, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5513 LB 0x29ba -> off=0x0 cb=0000000000000024 uValue=00000000000c0d93 '_dcc_table' +_dcc_table: ; 0xc5513 LB 0x24 + db 010h, 001h, 007h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5537 LB 0x2996 -> off=0x0 cb=000000000000001a uValue=00000000000c0db7 '_secondary_save_area' +_secondary_save_area: ; 0xc5537 LB 0x1a + db 01ah, 000h, 013h, 055h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5551 LB 0x297c -> off=0x0 cb=000000000000001c uValue=00000000000c0dd1 '_video_save_pointer_table' +_video_save_pointer_table: ; 0xc5551 LB 0x1c + db 043h, 048h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 037h, 055h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc556d LB 0x2960 -> off=0x0 cb=0000000000000800 uValue=00000000000c0ded 'vgafont8' +vgafont8: ; 0xc556d LB 0x800 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 081h, 0a5h, 081h, 0bdh, 099h, 081h, 07eh + db 07eh, 0ffh, 0dbh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 06ch, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h + db 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 038h, 07ch, 038h, 0feh, 0feh, 07ch, 038h, 07ch + db 010h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 07ch, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h + db 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h + db 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 00fh, 007h, 00fh, 07dh, 0cch, 0cch, 0cch, 078h + db 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 03fh, 033h, 03fh, 030h, 030h, 070h, 0f0h, 0e0h + db 07fh, 063h, 07fh, 063h, 063h, 067h, 0e6h, 0c0h, 099h, 05ah, 03ch, 0e7h, 0e7h, 03ch, 05ah, 099h + db 080h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 080h, 000h, 002h, 00eh, 03eh, 0feh, 03eh, 00eh, 002h, 000h + db 018h, 03ch, 07eh, 018h, 018h, 07eh, 03ch, 018h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 000h + db 07fh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 000h, 03eh, 063h, 038h, 06ch, 06ch, 038h, 0cch, 078h + db 000h, 000h, 000h, 000h, 07eh, 07eh, 07eh, 000h, 018h, 03ch, 07eh, 018h, 07eh, 03ch, 018h, 0ffh + db 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h + db 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h + db 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h + db 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 000h, 000h, 000h, 0ffh, 0ffh, 07eh, 03ch, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 078h, 078h, 030h, 030h, 000h, 030h, 000h + db 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 0feh, 06ch, 06ch, 000h + db 030h, 07ch, 0c0h, 078h, 00ch, 0f8h, 030h, 000h, 000h, 0c6h, 0cch, 018h, 030h, 066h, 0c6h, 000h + db 038h, 06ch, 038h, 076h, 0dch, 0cch, 076h, 000h, 060h, 060h, 0c0h, 000h, 000h, 000h, 000h, 000h + db 018h, 030h, 060h, 060h, 060h, 030h, 018h, 000h, 060h, 030h, 018h, 018h, 018h, 030h, 060h, 000h + db 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 060h, 000h, 000h, 000h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 000h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h + db 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 07ch, 000h, 030h, 070h, 030h, 030h, 030h, 030h, 0fch, 000h + db 078h, 0cch, 00ch, 038h, 060h, 0cch, 0fch, 000h, 078h, 0cch, 00ch, 038h, 00ch, 0cch, 078h, 000h + db 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 01eh, 000h, 0fch, 0c0h, 0f8h, 00ch, 00ch, 0cch, 078h, 000h + db 038h, 060h, 0c0h, 0f8h, 0cch, 0cch, 078h, 000h, 0fch, 0cch, 00ch, 018h, 030h, 030h, 030h, 000h + db 078h, 0cch, 0cch, 078h, 0cch, 0cch, 078h, 000h, 078h, 0cch, 0cch, 07ch, 00ch, 018h, 070h, 000h + db 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 060h + db 018h, 030h, 060h, 0c0h, 060h, 030h, 018h, 000h, 000h, 000h, 0fch, 000h, 000h, 0fch, 000h, 000h + db 060h, 030h, 018h, 00ch, 018h, 030h, 060h, 000h, 078h, 0cch, 00ch, 018h, 030h, 000h, 030h, 000h + db 07ch, 0c6h, 0deh, 0deh, 0deh, 0c0h, 078h, 000h, 030h, 078h, 0cch, 0cch, 0fch, 0cch, 0cch, 000h + db 0fch, 066h, 066h, 07ch, 066h, 066h, 0fch, 000h, 03ch, 066h, 0c0h, 0c0h, 0c0h, 066h, 03ch, 000h + db 0f8h, 06ch, 066h, 066h, 066h, 06ch, 0f8h, 000h, 0feh, 062h, 068h, 078h, 068h, 062h, 0feh, 000h + db 0feh, 062h, 068h, 078h, 068h, 060h, 0f0h, 000h, 03ch, 066h, 0c0h, 0c0h, 0ceh, 066h, 03eh, 000h + db 0cch, 0cch, 0cch, 0fch, 0cch, 0cch, 0cch, 000h, 078h, 030h, 030h, 030h, 030h, 030h, 078h, 000h + db 01eh, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 0e6h, 066h, 06ch, 078h, 06ch, 066h, 0e6h, 000h + db 0f0h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 000h + db 0c6h, 0e6h, 0f6h, 0deh, 0ceh, 0c6h, 0c6h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h + db 0fch, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 078h, 0cch, 0cch, 0cch, 0dch, 078h, 01ch, 000h + db 0fch, 066h, 066h, 07ch, 06ch, 066h, 0e6h, 000h, 078h, 0cch, 0e0h, 070h, 01ch, 0cch, 078h, 000h + db 0fch, 0b4h, 030h, 030h, 030h, 030h, 078h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 0fch, 000h + db 0cch, 0cch, 0cch, 0cch, 0cch, 078h, 030h, 000h, 0c6h, 0c6h, 0c6h, 0d6h, 0feh, 0eeh, 0c6h, 000h + db 0c6h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 030h, 078h, 000h + db 0feh, 0c6h, 08ch, 018h, 032h, 066h, 0feh, 000h, 078h, 060h, 060h, 060h, 060h, 060h, 078h, 000h + db 0c0h, 060h, 030h, 018h, 00ch, 006h, 002h, 000h, 078h, 018h, 018h, 018h, 018h, 018h, 078h, 000h + db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 076h, 000h + db 0e0h, 060h, 060h, 07ch, 066h, 066h, 0dch, 000h, 000h, 000h, 078h, 0cch, 0c0h, 0cch, 078h, 000h + db 01ch, 00ch, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h + db 038h, 06ch, 060h, 0f0h, 060h, 060h, 0f0h, 000h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 0f8h + db 0e0h, 060h, 06ch, 076h, 066h, 066h, 0e6h, 000h, 030h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 00ch, 000h, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 0e0h, 060h, 066h, 06ch, 078h, 06ch, 0e6h, 000h + db 070h, 030h, 030h, 030h, 030h, 030h, 078h, 000h, 000h, 000h, 0cch, 0feh, 0feh, 0d6h, 0c6h, 000h + db 000h, 000h, 0f8h, 0cch, 0cch, 0cch, 0cch, 000h, 000h, 000h, 078h, 0cch, 0cch, 0cch, 078h, 000h + db 000h, 000h, 0dch, 066h, 066h, 07ch, 060h, 0f0h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 01eh + db 000h, 000h, 0dch, 076h, 066h, 060h, 0f0h, 000h, 000h, 000h, 07ch, 0c0h, 078h, 00ch, 0f8h, 000h + db 010h, 030h, 07ch, 030h, 030h, 034h, 018h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 000h, 000h, 000h, 0c6h, 0d6h, 0feh, 0feh, 06ch, 000h + db 000h, 000h, 0c6h, 06ch, 038h, 06ch, 0c6h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 07ch, 00ch, 0f8h + db 000h, 000h, 0fch, 098h, 030h, 064h, 0fch, 000h, 01ch, 030h, 030h, 0e0h, 030h, 030h, 01ch, 000h + db 018h, 018h, 018h, 000h, 018h, 018h, 018h, 000h, 0e0h, 030h, 030h, 01ch, 030h, 030h, 0e0h, 000h + db 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h + db 078h, 0cch, 0c0h, 0cch, 078h, 018h, 00ch, 078h, 000h, 0cch, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 01ch, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h, 07eh, 0c3h, 03ch, 006h, 03eh, 066h, 03fh, 000h + db 0cch, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 0e0h, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h + db 030h, 030h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 000h, 000h, 078h, 0c0h, 0c0h, 078h, 00ch, 038h + db 07eh, 0c3h, 03ch, 066h, 07eh, 060h, 03ch, 000h, 0cch, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h + db 0e0h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h, 0cch, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 07ch, 0c6h, 038h, 018h, 018h, 018h, 03ch, 000h, 0e0h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 0c6h, 038h, 06ch, 0c6h, 0feh, 0c6h, 0c6h, 000h, 030h, 030h, 000h, 078h, 0cch, 0fch, 0cch, 000h + db 01ch, 000h, 0fch, 060h, 078h, 060h, 0fch, 000h, 000h, 000h, 07fh, 00ch, 07fh, 0cch, 07fh, 000h + db 03eh, 06ch, 0cch, 0feh, 0cch, 0cch, 0ceh, 000h, 078h, 0cch, 000h, 078h, 0cch, 0cch, 078h, 000h + db 000h, 0cch, 000h, 078h, 0cch, 0cch, 078h, 000h, 000h, 0e0h, 000h, 078h, 0cch, 0cch, 078h, 000h + db 078h, 0cch, 000h, 0cch, 0cch, 0cch, 07eh, 000h, 000h, 0e0h, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 000h, 0cch, 000h, 0cch, 0cch, 07ch, 00ch, 0f8h, 0c3h, 018h, 03ch, 066h, 066h, 03ch, 018h, 000h + db 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 078h, 000h, 018h, 018h, 07eh, 0c0h, 0c0h, 07eh, 018h, 018h + db 038h, 06ch, 064h, 0f0h, 060h, 0e6h, 0fch, 000h, 0cch, 0cch, 078h, 0fch, 030h, 0fch, 030h, 030h + db 0f8h, 0cch, 0cch, 0fah, 0c6h, 0cfh, 0c6h, 0c7h, 00eh, 01bh, 018h, 03ch, 018h, 018h, 0d8h, 070h + db 01ch, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 038h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 000h, 01ch, 000h, 078h, 0cch, 0cch, 078h, 000h, 000h, 01ch, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 000h, 0f8h, 000h, 0f8h, 0cch, 0cch, 0cch, 000h, 0fch, 000h, 0cch, 0ech, 0fch, 0dch, 0cch, 000h + db 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h + db 030h, 000h, 030h, 060h, 0c0h, 0cch, 078h, 000h, 000h, 000h, 000h, 0fch, 0c0h, 0c0h, 000h, 000h + db 000h, 000h, 000h, 0fch, 00ch, 00ch, 000h, 000h, 0c3h, 0c6h, 0cch, 0deh, 033h, 066h, 0cch, 00fh + db 0c3h, 0c6h, 0cch, 0dbh, 037h, 06fh, 0cfh, 003h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 000h + db 000h, 033h, 066h, 0cch, 066h, 033h, 000h, 000h, 000h, 0cch, 066h, 033h, 066h, 0cch, 000h, 000h + db 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah + db 0dbh, 077h, 0dbh, 0eeh, 0dbh, 077h, 0dbh, 0eeh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h + db 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 0feh, 006h, 0f6h, 036h, 036h, 036h + db 036h, 036h, 0f6h, 006h, 0feh, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h, 000h + db 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h + db 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h + db 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h + db 036h, 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0f7h, 036h, 036h, 036h + db 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h, 000h + db 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 03fh, 000h, 000h, 000h + db 018h, 018h, 01fh, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h + db 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 0c8h, 0dch, 076h, 000h, 000h, 078h, 0cch, 0f8h, 0cch, 0f8h, 0c0h, 0c0h + db 000h, 0fch, 0cch, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 0feh, 06ch, 06ch, 06ch, 06ch, 06ch, 000h + db 0fch, 0cch, 060h, 030h, 060h, 0cch, 0fch, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 070h, 000h + db 000h, 066h, 066h, 066h, 066h, 07ch, 060h, 0c0h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 000h + db 0fch, 030h, 078h, 0cch, 0cch, 078h, 030h, 0fch, 038h, 06ch, 0c6h, 0feh, 0c6h, 06ch, 038h, 000h + db 038h, 06ch, 0c6h, 0c6h, 06ch, 06ch, 0eeh, 000h, 01ch, 030h, 018h, 07ch, 0cch, 0cch, 078h, 000h + db 000h, 000h, 07eh, 0dbh, 0dbh, 07eh, 000h, 000h, 006h, 00ch, 07eh, 0dbh, 0dbh, 07eh, 060h, 0c0h + db 038h, 060h, 0c0h, 0f8h, 0c0h, 060h, 038h, 000h, 078h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 000h + db 000h, 0fch, 000h, 0fch, 000h, 0fch, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 0fch, 000h + db 060h, 030h, 018h, 030h, 060h, 000h, 0fch, 000h, 018h, 030h, 060h, 030h, 018h, 000h, 0fch, 000h + db 00eh, 01bh, 01bh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h, 070h + db 030h, 030h, 000h, 0fch, 000h, 030h, 030h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h + db 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h, 00fh, 00ch, 00ch, 00ch, 0ech, 06ch, 03ch, 01ch + db 078h, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 070h, 018h, 030h, 060h, 078h, 000h, 000h, 000h + db 000h, 000h, 03ch, 03ch, 03ch, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5d6d LB 0x2160 -> off=0x0 cb=0000000000000e00 uValue=00000000000c15ed 'vgafont14' +vgafont14: ; 0xc5d6d LB 0xe00 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 07eh, 081h, 0a5h, 081h, 081h, 0bdh, 099h, 081h, 07eh, 000h, 000h, 000h, 000h, 000h, 07eh, 0ffh + db 0dbh, 0ffh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 06ch, 0feh, 0feh + db 0feh, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 07ch, 0feh, 07ch + db 038h, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 0e7h, 0e7h, 0e7h, 018h, 018h + db 03ch, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 07eh, 018h, 018h, 03ch, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h + db 000h, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh + db 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 01eh, 00eh, 01ah, 032h + db 078h, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 066h, 066h, 03ch, 018h + db 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 03fh, 033h, 03fh, 030h, 030h, 030h, 070h, 0f0h + db 0e0h, 000h, 000h, 000h, 000h, 000h, 07fh, 063h, 07fh, 063h, 063h, 063h, 067h, 0e7h, 0e6h, 0c0h + db 000h, 000h, 000h, 000h, 018h, 018h, 0dbh, 03ch, 0e7h, 03ch, 0dbh, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 080h, 0c0h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 0c0h, 080h, 000h, 000h, 000h, 000h, 000h + db 002h, 006h, 00eh, 03eh, 0feh, 03eh, 00eh, 006h, 002h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch + db 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h + db 066h, 066h, 000h, 066h, 066h, 000h, 000h, 000h, 000h, 000h, 07fh, 0dbh, 0dbh, 0dbh, 07bh, 01bh + db 01bh, 01bh, 01bh, 000h, 000h, 000h, 000h, 07ch, 0c6h, 060h, 038h, 06ch, 0c6h, 0c6h, 06ch, 038h + db 00ch, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 0feh, 000h + db 000h, 000h, 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 07eh, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 060h + db 0feh, 060h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c0h + db 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 028h, 06ch, 0feh, 06ch, 028h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 038h, 07ch, 07ch, 0feh, 0feh, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 07ch, 07ch, 038h, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 03ch, 03ch, 03ch, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 066h, 066h, 066h + db 024h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch + db 06ch, 06ch, 0feh, 06ch, 06ch, 000h, 000h, 000h, 018h, 018h, 07ch, 0c6h, 0c2h, 0c0h, 07ch, 006h + db 086h, 0c6h, 07ch, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 0c2h, 0c6h, 00ch, 018h, 030h, 066h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 038h, 06ch, 06ch, 038h, 076h, 0dch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 030h, 030h, 030h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 018h, 030h, 030h, 030h, 030h, 030h, 018h, 00ch, 000h, 000h, 000h, 000h, 000h + db 030h, 018h, 00ch, 00ch, 00ch, 00ch, 00ch, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h + db 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h + db 000h, 000h, 000h, 000h, 002h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 018h, 038h, 078h, 018h, 018h, 018h, 018h, 018h, 07eh, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h + db 006h, 00ch, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 006h, 006h + db 03ch, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 00ch, 01ch, 03ch, 06ch, 0cch, 0feh + db 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0fch, 006h, 006h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 038h, 060h, 0c0h, 0c0h, 0fch, 0c6h, 0c6h, 0c6h, 07ch, 000h + db 000h, 000h, 000h, 000h, 0feh, 0c6h, 006h, 00ch, 018h, 030h, 030h, 030h, 030h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 07ch, 0c6h, 0c6h, 0c6h, 07eh, 006h, 006h, 00ch, 078h, 000h, 000h, 000h, 000h, 000h, 000h, 018h + db 018h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h + db 000h, 000h, 018h, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 006h, 00ch, 018h, 030h, 060h, 030h + db 018h, 00ch, 006h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 000h, 000h, 07eh, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 060h, 000h + db 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 00ch, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0deh, 0deh, 0deh, 0dch, 0c0h, 07ch, 000h, 000h, 000h, 000h, 000h + db 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h, 0fch, 066h + db 066h, 066h, 07ch, 066h, 066h, 066h, 0fch, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 0c2h, 0c0h + db 0c0h, 0c0h, 0c2h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h, 0f8h, 06ch, 066h, 066h, 066h, 066h + db 066h, 06ch, 0f8h, 000h, 000h, 000h, 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 062h, 066h + db 0feh, 000h, 000h, 000h, 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0deh, 0c6h, 066h, 03ah, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h + db 03ch, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 01eh, 00ch + db 00ch, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h, 000h, 0e6h, 066h, 06ch, 06ch + db 078h, 06ch, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 0f0h, 060h, 060h, 060h, 060h, 060h + db 062h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 0c6h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 000h + db 000h, 000h, 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h, 000h + db 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0deh, 07ch, 00ch, 00eh, 000h, 000h, 000h, 000h, 0fch, 066h + db 066h, 066h, 07ch, 06ch, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 060h + db 038h, 00ch, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 07eh, 07eh, 05ah, 018h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 010h, 000h + db 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0d6h, 0feh, 07ch, 06ch, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 06ch, 038h, 038h, 038h, 06ch, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h + db 066h, 066h, 066h, 066h, 03ch, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 0feh, 0c6h + db 08ch, 018h, 030h, 060h, 0c2h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 03ch, 030h, 030h, 030h + db 030h, 030h, 030h, 030h, 03ch, 000h, 000h, 000h, 000h, 000h, 080h, 0c0h, 0e0h, 070h, 038h, 01ch + db 00eh, 006h, 002h, 000h, 000h, 000h, 000h, 000h, 03ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch + db 03ch, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 0e0h, 060h + db 060h, 078h, 06ch, 066h, 066h, 066h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch + db 0c6h, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 01ch, 00ch, 00ch, 03ch, 06ch, 0cch + db 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 07ch, 00ch, 0cch, 078h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 06ch, 076h, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 006h, 006h + db 000h, 00eh, 006h, 006h, 006h, 006h, 066h, 066h, 03ch, 000h, 000h, 000h, 0e0h, 060h, 060h, 066h + db 06ch, 078h, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ech, 0feh, 0d6h, 0d6h, 0d6h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 000h, 000h + db 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 07ch, 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h, 000h + db 000h, 0dch, 076h, 066h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch + db 0c6h, 070h, 01ch, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 010h, 030h, 030h, 0fch, 030h, 030h + db 030h, 036h, 01ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch + db 076h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 03ch, 018h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0d6h, 0d6h, 0feh, 06ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 0f8h, 000h, 000h, 000h, 000h, 000h + db 000h, 0feh, 0cch, 018h, 030h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h, 00eh, 018h, 018h, 018h + db 070h, 018h, 018h, 018h, 00eh, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 000h, 018h + db 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 070h, 018h, 018h, 018h, 00eh, 018h, 018h, 018h + db 070h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 00ch, 006h, 07ch, 000h, 000h, 000h + db 0cch, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 00ch, 018h, 030h + db 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 000h, 078h + db 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 000h, 078h, 00ch, 07ch + db 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 078h, 00ch, 07ch, 0cch, 0cch + db 076h, 000h, 000h, 000h, 000h, 038h, 06ch, 038h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 060h, 066h, 03ch, 00ch, 006h, 03ch, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 0cch, 0cch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h + db 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 000h, 038h + db 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 018h, 03ch, 066h, 000h, 038h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 038h, 018h, 018h, 018h, 018h + db 03ch, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 000h + db 000h, 000h, 038h, 06ch, 038h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 000h, 000h, 000h + db 018h, 030h, 060h, 000h, 0feh, 066h, 060h, 07ch, 060h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 0cch, 076h, 036h, 07eh, 0d8h, 0d8h, 06eh, 000h, 000h, 000h, 000h, 000h, 03eh, 06ch + db 0cch, 0cch, 0feh, 0cch, 0cch, 0cch, 0ceh, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 000h, 07ch + db 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 000h, 07ch, 0c6h, 0c6h + db 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 030h, 078h, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 060h, 030h, 018h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 078h, 000h, 000h, 0c6h + db 0c6h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 000h + db 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 018h, 018h, 03ch, 066h, 060h + db 060h, 066h, 03ch, 018h, 018h, 000h, 000h, 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h + db 060h, 0e6h, 0fch, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 03ch, 018h, 07eh, 018h, 07eh, 018h + db 018h, 000h, 000h, 000h, 000h, 0f8h, 0cch, 0cch, 0f8h, 0c4h, 0cch, 0deh, 0cch, 0cch, 0c6h, 000h + db 000h, 000h, 000h, 00eh, 01bh, 018h, 018h, 018h, 07eh, 018h, 018h, 018h, 018h, 0d8h, 070h, 000h + db 000h, 018h, 030h, 060h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 00ch + db 018h, 030h, 000h, 038h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 018h, 030h, 060h + db 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 018h, 030h, 060h, 000h, 0cch + db 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 0dch, 066h, 066h + db 066h, 066h, 066h, 000h, 000h, 000h, 076h, 0dch, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h + db 0c6h, 000h, 000h, 000h, 000h, 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 030h, 000h, 030h, 030h, 060h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 006h, 006h, 006h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c6h, 0cch, 0d8h + db 030h, 060h, 0dch, 086h, 00ch, 018h, 03eh, 000h, 000h, 0c0h, 0c0h, 0c6h, 0cch, 0d8h, 030h, 066h + db 0ceh, 09eh, 03eh, 006h, 006h, 000h, 000h, 000h, 018h, 018h, 000h, 018h, 018h, 03ch, 03ch, 03ch + db 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 036h, 06ch, 0d8h, 06ch, 036h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0d8h, 06ch, 036h, 06ch, 0d8h, 000h, 000h, 000h, 000h, 000h + db 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 055h, 0aah + db 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 0ddh, 077h, 0ddh, 077h + db 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h + db 018h, 018h, 018h, 018h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 036h + db 036h, 036h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 036h, 036h + db 036h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 000h, 0feh + db 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0feh + db 000h, 000h, 000h, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h + db 018h, 018h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 030h, 037h + db 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h + db 000h, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 036h + db 036h, 036h, 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h + db 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 0f0h, 0f0h, 0f0h, 0f0h, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh + db 00fh, 00fh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 0d8h, 0d8h, 0dch, 076h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0fch, 0c6h, 0c6h, 0fch, 0c0h, 0c0h, 040h, 000h, 000h, 000h, 0feh, 0c6h + db 0c6h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 06ch + db 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 0feh, 0c6h, 060h, 030h, 018h, 030h + db 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 0d8h + db 070h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0c0h + db 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 07eh, 018h, 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h, 000h + db 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 038h, 06ch + db 0c6h, 0c6h, 0c6h, 06ch, 06ch, 06ch, 0eeh, 000h, 000h, 000h, 000h, 000h, 01eh, 030h, 018h, 00ch + db 03eh, 066h, 066h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 0dbh, 0dbh + db 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 003h, 006h, 07eh, 0dbh, 0dbh, 0f3h, 07eh, 060h + db 0c0h, 000h, 000h, 000h, 000h, 000h, 01ch, 030h, 060h, 060h, 07ch, 060h, 060h, 030h, 01ch, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h + db 000h, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 030h, 018h + db 00ch, 006h, 00ch, 018h, 030h, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 00ch, 018h, 030h, 060h + db 030h, 018h, 00ch, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 00eh, 01bh, 01bh, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h + db 070h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 07eh, 000h, 018h, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 00fh, 00ch, 00ch, 00ch, 00ch + db 00ch, 0ech, 06ch, 03ch, 01ch, 000h, 000h, 000h, 000h, 0d8h, 06ch, 06ch, 06ch, 06ch, 06ch, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 070h, 0d8h, 030h, 060h, 0c8h, 0f8h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc6b6d LB 0x1360 -> off=0x0 cb=0000000000001000 uValue=00000000000c23ed 'vgafont16' +vgafont16: ; 0xc6b6d LB 0x1000 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 081h, 0a5h, 081h, 081h, 0bdh, 099h, 081h, 081h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 0ffh, 0dbh, 0ffh, 0ffh, 0c3h, 0e7h, 0ffh, 0ffh, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 06ch, 0feh, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 03ch, 03ch, 0e7h, 0e7h, 0e7h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 07eh, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 01eh, 00eh, 01ah, 032h, 078h, 0cch, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 03fh, 033h, 03fh, 030h, 030h, 030h, 030h, 070h, 0f0h, 0e0h, 000h, 000h, 000h, 000h + db 000h, 000h, 07fh, 063h, 07fh, 063h, 063h, 063h, 063h, 067h, 0e7h, 0e6h, 0c0h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 018h, 0dbh, 03ch, 0e7h, 03ch, 0dbh, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0feh, 0f8h, 0f0h, 0e0h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 002h, 006h, 00eh, 01eh, 03eh, 0feh, 03eh, 01eh, 00eh, 006h, 002h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 066h, 000h, 000h, 000h, 000h + db 000h, 000h, 07fh, 0dbh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 01bh, 01bh, 000h, 000h, 000h, 000h + db 000h, 07ch, 0c6h, 060h, 038h, 06ch, 0c6h, 0c6h, 06ch, 038h, 00ch, 0c6h, 07ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 0feh, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 028h, 06ch, 0feh, 06ch, 028h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 038h, 07ch, 07ch, 0feh, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 0feh, 07ch, 07ch, 038h, 038h, 010h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 03ch, 03ch, 018h, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 066h, 066h, 066h, 024h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 06ch, 06ch, 0feh, 06ch, 06ch, 000h, 000h, 000h, 000h + db 018h, 018h, 07ch, 0c6h, 0c2h, 0c0h, 07ch, 006h, 006h, 086h, 0c6h, 07ch, 018h, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 0c2h, 0c6h, 00ch, 018h, 030h, 060h, 0c6h, 086h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 06ch, 038h, 076h, 0dch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 030h, 030h, 030h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 018h, 030h, 030h, 030h, 030h, 030h, 030h, 018h, 00ch, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 018h, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 018h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 030h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 002h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0d6h, 0d6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 038h, 078h, 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 006h, 006h, 03ch, 006h, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0fch, 006h, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 060h, 0c0h, 0c0h, 0fch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 006h, 006h, 00ch, 018h, 030h, 030h, 030h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07eh, 006h, 006h, 006h, 00ch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 018h, 018h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 006h, 00ch, 018h, 030h, 060h, 030h, 018h, 00ch, 006h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 000h, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 060h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 060h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 00ch, 018h, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0deh, 0deh, 0deh, 0dch, 0c0h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 066h, 066h, 066h, 066h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0f8h, 06ch, 066h, 066h, 066h, 066h, 066h, 066h, 06ch, 0f8h, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 062h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0deh, 0c6h, 0c6h, 066h, 03ah, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 01eh, 00ch, 00ch, 00ch, 00ch, 00ch, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 0e6h, 066h, 066h, 06ch, 078h, 078h, 06ch, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0f0h, 060h, 060h, 060h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 060h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0deh, 07ch, 00ch, 00eh, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 06ch, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 060h, 038h, 00ch, 006h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 07eh, 05ah, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0d6h, 0d6h, 0feh, 0eeh, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 06ch, 07ch, 038h, 038h, 07ch, 06ch, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 066h, 066h, 03ch, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 086h, 00ch, 018h, 030h, 060h, 0c2h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 030h, 030h, 030h, 030h, 030h, 030h, 030h, 030h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 080h, 0c0h, 0e0h, 070h, 038h, 01ch, 00eh, 006h, 002h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 03ch, 000h, 000h, 000h, 000h + db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 000h + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 078h, 06ch, 066h, 066h, 066h, 066h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c0h, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 01ch, 00ch, 00ch, 03ch, 06ch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 0cch, 0cch, 07ch, 00ch, 0cch, 078h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 06ch, 076h, 066h, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 006h, 006h, 000h, 00eh, 006h, 006h, 006h, 006h, 006h, 006h, 066h, 066h, 03ch, 000h + db 000h, 000h, 0e0h, 060h, 060h, 066h, 06ch, 078h, 078h, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ech, 0feh, 0d6h, 0d6h, 0d6h, 0d6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 0cch, 0cch, 07ch, 00ch, 00ch, 01eh, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 076h, 066h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 060h, 038h, 00ch, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 010h, 030h, 030h, 0fch, 030h, 030h, 030h, 030h, 036h, 01ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 066h, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0d6h, 0d6h, 0d6h, 0feh, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 06ch, 038h, 038h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 0f8h, 000h + db 000h, 000h, 000h, 000h, 000h, 0feh, 0cch, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 00eh, 018h, 018h, 018h, 070h, 018h, 018h, 018h, 018h, 00eh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 070h, 018h, 018h, 018h, 00eh, 018h, 018h, 018h, 018h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 00ch, 006h, 07ch, 000h, 000h + db 000h, 000h, 0cch, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 00ch, 018h, 030h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0cch, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 038h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 03ch, 066h, 060h, 060h, 066h, 03ch, 00ch, 006h, 03ch, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 018h, 03ch, 066h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 0c6h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 038h, 06ch, 038h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 018h, 030h, 060h, 000h, 0feh, 066h, 060h, 07ch, 060h, 060h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0cch, 076h, 036h, 07eh, 0d8h, 0d8h, 06eh, 000h, 000h, 000h, 000h + db 000h, 000h, 03eh, 06ch, 0cch, 0cch, 0feh, 0cch, 0cch, 0cch, 0cch, 0ceh, 000h, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 030h, 078h, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 078h, 000h + db 000h, 0c6h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 0c6h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 018h, 018h, 03ch, 066h, 060h, 060h, 060h, 066h, 03ch, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 060h, 0e6h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 03ch, 018h, 07eh, 018h, 07eh, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 0f8h, 0cch, 0cch, 0f8h, 0c4h, 0cch, 0deh, 0cch, 0cch, 0cch, 0c6h, 000h, 000h, 000h, 000h + db 000h, 00eh, 01bh, 018h, 018h, 018h, 07eh, 018h, 018h, 018h, 018h, 018h, 0d8h, 070h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 00ch, 018h, 030h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 000h, 000h, 000h + db 076h, 0dch, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 030h, 000h, 030h, 030h, 060h, 0c0h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 006h, 006h, 006h, 006h, 000h, 000h, 000h, 000h, 000h + db 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 060h, 0dch, 086h, 00ch, 018h, 03eh, 000h, 000h + db 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 066h, 0ceh, 09eh, 03eh, 006h, 006h, 000h, 000h + db 000h, 000h, 018h, 018h, 000h, 018h, 018h, 018h, 03ch, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 036h, 06ch, 0d8h, 06ch, 036h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0d8h, 06ch, 036h, 06ch, 0d8h, 000h, 000h, 000h, 000h, 000h, 000h + db 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h + db 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah + db 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0feh, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 0d8h, 0d8h, 0d8h, 0dch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 078h, 0cch, 0cch, 0cch, 0d8h, 0cch, 0c6h, 0c6h, 0c6h, 0cch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 0c6h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 06ch, 06ch, 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0feh, 0c6h, 060h, 030h, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 0d8h, 0d8h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0c0h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07eh, 018h, 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 06ch, 06ch, 06ch, 0eeh, 000h, 000h, 000h, 000h + db 000h, 000h, 01eh, 030h, 018h, 00ch, 03eh, 066h, 066h, 066h, 066h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 0dbh, 0dbh, 0dbh, 07eh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 003h, 006h, 07eh, 0dbh, 0dbh, 0f3h, 07eh, 060h, 0c0h, 000h, 000h, 000h, 000h + db 000h, 000h, 01ch, 030h, 060h, 060h, 07ch, 060h, 060h, 060h, 030h, 01ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 000h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 00ch, 018h, 030h, 060h, 030h, 018h, 00ch, 000h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 00eh, 01bh, 01bh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h, 0d8h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 07eh, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 00fh, 00ch, 00ch, 00ch, 00ch, 00ch, 0ech, 06ch, 06ch, 03ch, 01ch, 000h, 000h, 000h, 000h + db 000h, 0d8h, 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 070h, 0d8h, 030h, 060h, 0c8h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7b6d LB 0x360 -> off=0x0 cb=000000000000012d uValue=00000000000c33ed 'vgafont14alt' +vgafont14alt: ; 0xc7b6d LB 0x12d + db 01dh, 000h, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h, 000h, 000h, 000h, 022h + db 000h, 063h, 063h, 063h, 022h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02bh, 000h + db 000h, 000h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 02dh, 000h, 000h + db 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04dh, 000h, 000h, 0c3h + db 0e7h, 0ffh, 0dbh, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 000h, 000h, 000h, 054h, 000h, 000h, 0ffh, 0dbh + db 099h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 056h, 000h, 000h, 0c3h, 0c3h, 0c3h + db 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h, 000h, 000h, 000h, 057h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h + db 0dbh, 0dbh, 0ffh, 066h, 066h, 000h, 000h, 000h, 058h, 000h, 000h, 0c3h, 0c3h, 066h, 03ch, 018h + db 03ch, 066h, 0c3h, 0c3h, 000h, 000h, 000h, 059h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 05ah, 000h, 000h, 0ffh, 0c3h, 086h, 00ch, 018h, 030h, 061h + db 0c3h, 0ffh, 000h, 000h, 000h, 06dh, 000h, 000h, 000h, 000h, 000h, 0e6h, 0ffh, 0dbh, 0dbh, 0dbh + db 0dbh, 000h, 000h, 000h, 076h, 000h, 000h, 000h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 000h, 000h, 000h, 077h, 000h, 000h, 000h, 000h, 000h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh, 066h, 000h + db 000h, 000h, 091h, 000h, 000h, 000h, 000h, 06eh, 03bh, 01bh, 07eh, 0d8h, 0dch, 077h, 000h, 000h + db 000h, 09bh, 000h, 018h, 018h, 07eh, 0c3h, 0c0h, 0c0h, 0c3h, 07eh, 018h, 018h, 000h, 000h, 000h + db 09dh, 000h, 000h, 0c3h, 066h, 03ch, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 000h, 000h, 000h, 09eh + db 000h, 0fch, 066h, 066h, 07ch, 062h, 066h, 06fh, 066h, 066h, 0f3h, 000h, 000h, 000h, 0f1h, 000h + db 000h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 000h, 0ffh, 000h, 000h, 000h, 0f6h, 000h, 000h + db 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7c9a LB 0x233 -> off=0x0 cb=0000000000000144 uValue=00000000000c351a 'vgafont16alt' +vgafont16alt: ; 0xc7c9a LB 0x144 + db 01dh, 000h, 000h, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h, 000h, 000h, 000h + db 000h, 030h, 000h, 000h, 03ch, 066h, 0c3h, 0c3h, 0dbh, 0dbh, 0c3h, 0c3h, 066h, 03ch, 000h, 000h + db 000h, 000h, 04dh, 000h, 000h, 0c3h, 0e7h, 0ffh, 0ffh, 0dbh, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 000h + db 000h, 000h, 000h, 054h, 000h, 000h, 0ffh, 0dbh, 099h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch + db 000h, 000h, 000h, 000h, 056h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 066h, 03ch + db 018h, 000h, 000h, 000h, 000h, 057h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh + db 066h, 066h, 000h, 000h, 000h, 000h, 058h, 000h, 000h, 0c3h, 0c3h, 066h, 03ch, 018h, 018h, 03ch + db 066h, 0c3h, 0c3h, 000h, 000h, 000h, 000h, 059h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 05ah, 000h, 000h, 0ffh, 0c3h, 086h, 00ch, 018h + db 030h, 060h, 0c1h, 0c3h, 0ffh, 000h, 000h, 000h, 000h, 06dh, 000h, 000h, 000h, 000h, 000h, 0e6h + db 0ffh, 0dbh, 0dbh, 0dbh, 0dbh, 0dbh, 000h, 000h, 000h, 000h, 076h, 000h, 000h, 000h, 000h, 000h + db 0c3h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h, 000h, 000h, 000h, 000h, 077h, 000h, 000h, 000h, 000h + db 000h, 0c3h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh, 066h, 000h, 000h, 000h, 000h, 078h, 000h, 000h, 000h + db 000h, 000h, 0c3h, 066h, 03ch, 018h, 03ch, 066h, 0c3h, 000h, 000h, 000h, 000h, 091h, 000h, 000h + db 000h, 000h, 000h, 06eh, 03bh, 01bh, 07eh, 0d8h, 0dch, 077h, 000h, 000h, 000h, 000h, 09bh, 000h + db 018h, 018h, 07eh, 0c3h, 0c0h, 0c0h, 0c0h, 0c3h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 09dh + db 000h, 000h, 0c3h, 066h, 03ch, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 09eh, 000h, 0fch, 066h, 066h, 07ch, 062h, 066h, 06fh, 066h, 066h, 066h, 0f3h, 000h, 000h, 000h + db 000h, 0abh, 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 060h, 0ceh, 09bh, 006h, 00ch, 01fh + db 000h, 000h, 0ach, 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 066h, 0ceh, 096h, 03eh, 006h + db 006h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7dde LB 0xef -> off=0x0 cb=0000000000000008 uValue=00000000000c365e '_cga_msr' +_cga_msr: ; 0xc7dde LB 0x8 + db 02ch, 028h, 02dh, 029h, 02ah, 02eh, 01eh, 029h + ; disGetNextSymbol 0xc7de6 LB 0xe7 -> off=0x0 cb=0000000000000008 uValue=00000000000c3666 'line_to_vpti_200' +line_to_vpti_200: ; 0xc7de6 LB 0x8 + db 000h, 001h, 002h, 003h, 0ffh, 0ffh, 0ffh, 007h + ; disGetNextSymbol 0xc7dee LB 0xdf -> off=0x0 cb=0000000000000008 uValue=00000000000c366e 'line_to_vpti_350' +line_to_vpti_350: ; 0xc7dee LB 0x8 + db 013h, 014h, 015h, 016h, 0ffh, 0ffh, 0ffh, 007h + ; disGetNextSymbol 0xc7df6 LB 0xd7 -> off=0x0 cb=0000000000000008 uValue=00000000000c3676 'line_to_vpti_400' +line_to_vpti_400: ; 0xc7df6 LB 0x8 + db 017h, 017h, 018h, 018h, 0ffh, 0ffh, 0ffh, 019h + ; disGetNextSymbol 0xc7dfe LB 0xcf -> off=0x0 cb=0000000000000004 uValue=00000000000c367e 'row_tbl' +row_tbl: ; 0xc7dfe LB 0x4 + dd 02b190e00h + ; disGetNextSymbol 0xc7e02 LB 0xcb -> off=0x0 cb=0000000000000015 uValue=00000000000c3682 '_vbebios_copyright' +_vbebios_copyright: ; 0xc7e02 LB 0x15 + db 'VirtualBox VESA BIOS', 000h + ; disGetNextSymbol 0xc7e17 LB 0xb6 -> off=0x0 cb=000000000000001d uValue=00000000000c3697 '_vbebios_vendor_name' +_vbebios_vendor_name: ; 0xc7e17 LB 0x1d + db 'Oracle and/or its affiliates', 000h + ; disGetNextSymbol 0xc7e34 LB 0x99 -> off=0x0 cb=0000000000000021 uValue=00000000000c36b4 '_vbebios_product_name' +_vbebios_product_name: ; 0xc7e34 LB 0x21 + db 'Oracle VM VirtualBox VBE Adapter', 000h + ; disGetNextSymbol 0xc7e55 LB 0x78 -> off=0x0 cb=0000000000000024 uValue=00000000000c36d5 '_vbebios_product_revision' +_vbebios_product_revision: ; 0xc7e55 LB 0x24 + db 'Oracle VM VirtualBox Version 7.0.14', 000h + ; disGetNextSymbol 0xc7e79 LB 0x54 -> off=0x0 cb=000000000000002b uValue=00000000000c36f9 '_vbebios_info_string' +_vbebios_info_string: ; 0xc7e79 LB 0x2b + db 'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h + ; disGetNextSymbol 0xc7ea4 LB 0x29 -> off=0x0 cb=0000000000000029 uValue=00000000000c3724 '_no_vbebios_info_string' +_no_vbebios_info_string: ; 0xc7ea4 LB 0x29 + db 'No VirtualBox VBE support available!', 00dh, 00ah, 00dh, 00ah, 000h + + ; Padding 0x1 bytes at 0xc7ecd + db 001h + +section CONST progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP + +section CONST2 progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP + + ; Padding 0x132 bytes at 0xc7ece + db 000h, 000h, 000h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 02fh, 068h, 06fh, 06dh, 065h + db 02fh, 073h, 062h, 075h, 072h, 063h, 068h, 069h, 06ch, 02fh, 076h, 062h, 05fh, 073h, 072h, 063h + db 02fh, 062h, 072h, 061h, 06eh, 063h, 068h, 065h, 073h, 02fh, 056h, 042h, 06fh, 078h, 02dh, 037h + db 02eh, 030h, 02fh, 06fh, 075h, 074h, 02fh, 06ch, 069h, 06eh, 075h, 078h, 02eh, 061h, 06dh, 064h + db 036h, 034h, 02fh, 072h, 065h, 06ch, 065h, 061h, 073h, 065h, 02fh, 06fh, 062h, 06ah, 02fh, 056h + db 042h, 06fh, 078h, 056h, 067h, 061h, 042h, 069h, 06fh, 073h, 032h, 038h, 036h, 02fh, 056h, 042h + db 06fh, 078h, 056h, 067h, 061h, 042h, 069h, 06fh, 073h, 032h, 038h, 036h, 02eh, 073h, 079h, 06dh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 0e2h diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum new file mode 100644 index 00000000..2f608321 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum @@ -0,0 +1 @@ +9431df94586df05b1873d86a27b77eb5 *VBoxVgaBios286.rom diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm new file mode 100644 index 00000000..9b6c7100 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm @@ -0,0 +1,8704 @@ +; $Id: VBoxVgaBiosAlternative386.asm $ +;; @file +; Auto Generated source file. Do not edit. +; + +; +; Source file: vgarom.asm +; +; ============================================================================================ +; +; Copyright (C) 2001,2002 the LGPL VGABios developers Team +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this library; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; ============================================================================================ +; +; This VGA Bios is specific to the plex86/bochs Emulated VGA card. +; You can NOT drive any physical vga card with it. +; +; ============================================================================================ +; + +; +; Source file: vberom.asm +; +; ============================================================================================ +; +; Copyright (C) 2002 Jeroen Janssen +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this library; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; ============================================================================================ +; +; This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +; You can NOT drive any physical vga card with it. +; +; ============================================================================================ +; +; This VBE Bios is based on information taken from : +; - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +; +; ============================================================================================ + +; +; Source file: vgabios.c +; +; // ============================================================================================ +; +; vgabios.c +; +; // ============================================================================================ +; // +; // Copyright (C) 2001,2002 the LGPL VGABios developers Team +; // +; // This library is free software; you can redistribute it and/or +; // modify it under the terms of the GNU Lesser General Public +; // License as published by the Free Software Foundation; either +; // version 2 of the License, or (at your option) any later version. +; // +; // This library is distributed in the hope that it will be useful, +; // but WITHOUT ANY WARRANTY; without even the implied warranty of +; // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; // Lesser General Public License for more details. +; // +; // You should have received a copy of the GNU Lesser General Public +; // License along with this library; if not, write to the Free Software +; // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; // +; // ============================================================================================ +; // +; // This VGA Bios is specific to the plex86/bochs Emulated VGA card. +; // You can NOT drive any physical vga card with it. +; // +; // ============================================================================================ +; // +; // This file contains code ripped from : +; // - rombios.c of plex86 +; // +; // This VGA Bios contains fonts from : +; // - fntcol16.zip (c) by Joseph Gil avalable at : +; // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip +; // These fonts are public domain +; // +; // This VGA Bios is based on information taken from : +; // - Kevin Lawton's vga card emulation for bochs/plex86 +; // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html +; // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/ +; // - Michael Abrash's Graphics Programming Black Book +; // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex +; // - DOSEMU 1.0.1 source code for several tables values and formulas +; // +; // Thanks for patches, comments and ideas to : +; // - techt@pikeonline.net +; // +; // ============================================================================================ + +; +; Source file: vbe.c +; +; // ============================================================================================ +; // +; // Copyright (C) 2002 Jeroen Janssen +; // +; // This library is free software; you can redistribute it and/or +; // modify it under the terms of the GNU Lesser General Public +; // License as published by the Free Software Foundation; either +; // version 2 of the License, or (at your option) any later version. +; // +; // This library is distributed in the hope that it will be useful, +; // but WITHOUT ANY WARRANTY; without even the implied warranty of +; // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; // Lesser General Public License for more details. +; // +; // You should have received a copy of the GNU Lesser General Public +; // License along with this library; if not, write to the Free Software +; // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; // +; // ============================================================================================ +; // +; // This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +; // You can NOT drive any physical vga card with it. +; // +; // ============================================================================================ +; // +; // This VBE Bios is based on information taken from : +; // - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +; // +; // ============================================================================================ + +; +; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice +; other than GPL or LGPL is available it will apply instead, Oracle elects to use only +; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where +; a choice of LGPL license versions is made available with the language indicating +; that LGPLv2 or any later version may be used, or where a choice of which version +; of the LGPL is applied is otherwise unspecified. +; + + + + + +section VGAROM progbits vstart=0x0 align=1 ; size=0x907 class=CODE group=AUTO + ; disGetNextSymbol 0xc0000 LB 0x907 -> off=0x28 cb=0000000000000548 uValue=00000000000c0028 'vgabios_int10_handler' + db 055h, 0aah, 040h, 0ebh, 01dh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 049h, 042h + db 04dh, 000h, 00eh, 01fh, 0fch, 0e9h, 03ch, 00ah +vgabios_int10_handler: ; 0xc0028 LB 0x548 + pushfw ; 9c ; 0xc0028 vgarom.asm:91 + cmp ah, 00fh ; 80 fc 0f ; 0xc0029 vgarom.asm:104 + jne short 00034h ; 75 06 ; 0xc002c vgarom.asm:105 + call 0017dh ; e8 4c 01 ; 0xc002e vgarom.asm:106 + jmp near 000edh ; e9 b9 00 ; 0xc0031 vgarom.asm:107 + cmp ah, 01ah ; 80 fc 1a ; 0xc0034 vgarom.asm:109 + jne short 0003fh ; 75 06 ; 0xc0037 vgarom.asm:110 + call 00532h ; e8 f6 04 ; 0xc0039 vgarom.asm:111 + jmp near 000edh ; e9 ae 00 ; 0xc003c vgarom.asm:112 + cmp ah, 00bh ; 80 fc 0b ; 0xc003f vgarom.asm:114 + jne short 0004ah ; 75 06 ; 0xc0042 vgarom.asm:115 + call 000efh ; e8 a8 00 ; 0xc0044 vgarom.asm:116 + jmp near 000edh ; e9 a3 00 ; 0xc0047 vgarom.asm:117 + cmp ax, 01103h ; 3d 03 11 ; 0xc004a vgarom.asm:119 + jne short 00055h ; 75 06 ; 0xc004d vgarom.asm:120 + call 00429h ; e8 d7 03 ; 0xc004f vgarom.asm:121 + jmp near 000edh ; e9 98 00 ; 0xc0052 vgarom.asm:122 + cmp ah, 012h ; 80 fc 12 ; 0xc0055 vgarom.asm:124 + jne short 00097h ; 75 3d ; 0xc0058 vgarom.asm:125 + cmp bl, 010h ; 80 fb 10 ; 0xc005a vgarom.asm:126 + jne short 00065h ; 75 06 ; 0xc005d vgarom.asm:127 + call 00436h ; e8 d4 03 ; 0xc005f vgarom.asm:128 + jmp near 000edh ; e9 88 00 ; 0xc0062 vgarom.asm:129 + cmp bl, 030h ; 80 fb 30 ; 0xc0065 vgarom.asm:131 + jne short 0006fh ; 75 05 ; 0xc0068 vgarom.asm:132 + call 00459h ; e8 ec 03 ; 0xc006a vgarom.asm:133 + jmp short 000edh ; eb 7e ; 0xc006d vgarom.asm:134 + cmp bl, 031h ; 80 fb 31 ; 0xc006f vgarom.asm:136 + jne short 00079h ; 75 05 ; 0xc0072 vgarom.asm:137 + call 004ach ; e8 35 04 ; 0xc0074 vgarom.asm:138 + jmp short 000edh ; eb 74 ; 0xc0077 vgarom.asm:139 + cmp bl, 032h ; 80 fb 32 ; 0xc0079 vgarom.asm:141 + jne short 00083h ; 75 05 ; 0xc007c vgarom.asm:142 + call 004ceh ; e8 4d 04 ; 0xc007e vgarom.asm:143 + jmp short 000edh ; eb 6a ; 0xc0081 vgarom.asm:144 + cmp bl, 033h ; 80 fb 33 ; 0xc0083 vgarom.asm:146 + jne short 0008dh ; 75 05 ; 0xc0086 vgarom.asm:147 + call 004ech ; e8 61 04 ; 0xc0088 vgarom.asm:148 + jmp short 000edh ; eb 60 ; 0xc008b vgarom.asm:149 + cmp bl, 034h ; 80 fb 34 ; 0xc008d vgarom.asm:151 + jne short 000e1h ; 75 4f ; 0xc0090 vgarom.asm:152 + call 00510h ; e8 7b 04 ; 0xc0092 vgarom.asm:153 + jmp short 000edh ; eb 56 ; 0xc0095 vgarom.asm:154 + cmp ax, 0101bh ; 3d 1b 10 ; 0xc0097 vgarom.asm:156 + je short 000e1h ; 74 45 ; 0xc009a vgarom.asm:157 + cmp ah, 010h ; 80 fc 10 ; 0xc009c vgarom.asm:158 + jne short 000a6h ; 75 05 ; 0xc009f vgarom.asm:162 + call 001a4h ; e8 00 01 ; 0xc00a1 vgarom.asm:164 + jmp short 000edh ; eb 47 ; 0xc00a4 vgarom.asm:165 + cmp ah, 04fh ; 80 fc 4f ; 0xc00a6 vgarom.asm:168 + jne short 000e1h ; 75 36 ; 0xc00a9 vgarom.asm:169 + cmp AL, strict byte 003h ; 3c 03 ; 0xc00ab vgarom.asm:170 + jne short 000b4h ; 75 05 ; 0xc00ad vgarom.asm:171 + call 007d2h ; e8 20 07 ; 0xc00af vgarom.asm:172 + jmp short 000edh ; eb 39 ; 0xc00b2 vgarom.asm:173 + cmp AL, strict byte 005h ; 3c 05 ; 0xc00b4 vgarom.asm:175 + jne short 000bdh ; 75 05 ; 0xc00b6 vgarom.asm:176 + call 007f7h ; e8 3c 07 ; 0xc00b8 vgarom.asm:177 + jmp short 000edh ; eb 30 ; 0xc00bb vgarom.asm:178 + cmp AL, strict byte 007h ; 3c 07 ; 0xc00bd vgarom.asm:180 + jne short 000c6h ; 75 05 ; 0xc00bf vgarom.asm:181 + call 00824h ; e8 60 07 ; 0xc00c1 vgarom.asm:182 + jmp short 000edh ; eb 27 ; 0xc00c4 vgarom.asm:183 + cmp AL, strict byte 008h ; 3c 08 ; 0xc00c6 vgarom.asm:185 + jne short 000cfh ; 75 05 ; 0xc00c8 vgarom.asm:186 + call 00858h ; e8 8b 07 ; 0xc00ca vgarom.asm:187 + jmp short 000edh ; eb 1e ; 0xc00cd vgarom.asm:188 + cmp AL, strict byte 009h ; 3c 09 ; 0xc00cf vgarom.asm:190 + jne short 000d8h ; 75 05 ; 0xc00d1 vgarom.asm:191 + call 0088fh ; e8 b9 07 ; 0xc00d3 vgarom.asm:192 + jmp short 000edh ; eb 15 ; 0xc00d6 vgarom.asm:193 + cmp AL, strict byte 00ah ; 3c 0a ; 0xc00d8 vgarom.asm:195 + jne short 000e1h ; 75 05 ; 0xc00da vgarom.asm:196 + call 008f3h ; e8 14 08 ; 0xc00dc vgarom.asm:197 + jmp short 000edh ; eb 0c ; 0xc00df vgarom.asm:198 + push ES ; 06 ; 0xc00e1 vgarom.asm:202 + push DS ; 1e ; 0xc00e2 vgarom.asm:203 + pushaw ; 60 ; 0xc00e3 vgarom.asm:107 + push CS ; 0e ; 0xc00e4 vgarom.asm:207 + pop DS ; 1f ; 0xc00e5 vgarom.asm:208 + cld ; fc ; 0xc00e6 vgarom.asm:209 + call 036ach ; e8 c2 35 ; 0xc00e7 vgarom.asm:210 + popaw ; 61 ; 0xc00ea vgarom.asm:124 + pop DS ; 1f ; 0xc00eb vgarom.asm:213 + pop ES ; 07 ; 0xc00ec vgarom.asm:214 + popfw ; 9d ; 0xc00ed vgarom.asm:216 + iret ; cf ; 0xc00ee vgarom.asm:217 + cmp bh, 000h ; 80 ff 00 ; 0xc00ef vgarom.asm:222 + je short 000fah ; 74 06 ; 0xc00f2 vgarom.asm:223 + cmp bh, 001h ; 80 ff 01 ; 0xc00f4 vgarom.asm:224 + je short 0014bh ; 74 52 ; 0xc00f7 vgarom.asm:225 + retn ; c3 ; 0xc00f9 vgarom.asm:229 + push ax ; 50 ; 0xc00fa vgarom.asm:231 + push bx ; 53 ; 0xc00fb vgarom.asm:232 + push cx ; 51 ; 0xc00fc vgarom.asm:233 + push dx ; 52 ; 0xc00fd vgarom.asm:234 + push DS ; 1e ; 0xc00fe vgarom.asm:235 + mov dx, strict word 00040h ; ba 40 00 ; 0xc00ff vgarom.asm:236 + mov ds, dx ; 8e da ; 0xc0102 vgarom.asm:237 + mov dx, 003dah ; ba da 03 ; 0xc0104 vgarom.asm:238 + in AL, DX ; ec ; 0xc0107 vgarom.asm:239 + cmp byte [word 00049h], 003h ; 80 3e 49 00 03 ; 0xc0108 vgarom.asm:240 + jbe short 0013eh ; 76 2f ; 0xc010d vgarom.asm:241 + mov dx, 003c0h ; ba c0 03 ; 0xc010f vgarom.asm:242 + mov AL, strict byte 000h ; b0 00 ; 0xc0112 vgarom.asm:243 + out DX, AL ; ee ; 0xc0114 vgarom.asm:244 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0115 vgarom.asm:245 + and AL, strict byte 00fh ; 24 0f ; 0xc0117 vgarom.asm:246 + test AL, strict byte 008h ; a8 08 ; 0xc0119 vgarom.asm:247 + je short 0011fh ; 74 02 ; 0xc011b vgarom.asm:248 + add AL, strict byte 008h ; 04 08 ; 0xc011d vgarom.asm:249 + out DX, AL ; ee ; 0xc011f vgarom.asm:251 + mov CL, strict byte 001h ; b1 01 ; 0xc0120 vgarom.asm:252 + and bl, 010h ; 80 e3 10 ; 0xc0122 vgarom.asm:253 + mov dx, 003c0h ; ba c0 03 ; 0xc0125 vgarom.asm:255 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc0128 vgarom.asm:256 + out DX, AL ; ee ; 0xc012a vgarom.asm:257 + mov dx, 003c1h ; ba c1 03 ; 0xc012b vgarom.asm:258 + in AL, DX ; ec ; 0xc012e vgarom.asm:259 + and AL, strict byte 0efh ; 24 ef ; 0xc012f vgarom.asm:260 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc0131 vgarom.asm:261 + mov dx, 003c0h ; ba c0 03 ; 0xc0133 vgarom.asm:262 + out DX, AL ; ee ; 0xc0136 vgarom.asm:263 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc0137 vgarom.asm:264 + cmp cl, 004h ; 80 f9 04 ; 0xc0139 vgarom.asm:265 + jne short 00125h ; 75 e7 ; 0xc013c vgarom.asm:266 + mov AL, strict byte 020h ; b0 20 ; 0xc013e vgarom.asm:268 + out DX, AL ; ee ; 0xc0140 vgarom.asm:269 + mov dx, 003dah ; ba da 03 ; 0xc0141 vgarom.asm:271 + in AL, DX ; ec ; 0xc0144 vgarom.asm:272 + pop DS ; 1f ; 0xc0145 vgarom.asm:274 + pop dx ; 5a ; 0xc0146 vgarom.asm:275 + pop cx ; 59 ; 0xc0147 vgarom.asm:276 + pop bx ; 5b ; 0xc0148 vgarom.asm:277 + pop ax ; 58 ; 0xc0149 vgarom.asm:278 + retn ; c3 ; 0xc014a vgarom.asm:279 + push ax ; 50 ; 0xc014b vgarom.asm:281 + push bx ; 53 ; 0xc014c vgarom.asm:282 + push cx ; 51 ; 0xc014d vgarom.asm:283 + push dx ; 52 ; 0xc014e vgarom.asm:284 + mov dx, 003dah ; ba da 03 ; 0xc014f vgarom.asm:285 + in AL, DX ; ec ; 0xc0152 vgarom.asm:286 + mov CL, strict byte 001h ; b1 01 ; 0xc0153 vgarom.asm:287 + and bl, 001h ; 80 e3 01 ; 0xc0155 vgarom.asm:288 + mov dx, 003c0h ; ba c0 03 ; 0xc0158 vgarom.asm:290 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc015b vgarom.asm:291 + out DX, AL ; ee ; 0xc015d vgarom.asm:292 + mov dx, 003c1h ; ba c1 03 ; 0xc015e vgarom.asm:293 + in AL, DX ; ec ; 0xc0161 vgarom.asm:294 + and AL, strict byte 0feh ; 24 fe ; 0xc0162 vgarom.asm:295 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc0164 vgarom.asm:296 + mov dx, 003c0h ; ba c0 03 ; 0xc0166 vgarom.asm:297 + out DX, AL ; ee ; 0xc0169 vgarom.asm:298 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc016a vgarom.asm:299 + cmp cl, 004h ; 80 f9 04 ; 0xc016c vgarom.asm:300 + jne short 00158h ; 75 e7 ; 0xc016f vgarom.asm:301 + mov AL, strict byte 020h ; b0 20 ; 0xc0171 vgarom.asm:302 + out DX, AL ; ee ; 0xc0173 vgarom.asm:303 + mov dx, 003dah ; ba da 03 ; 0xc0174 vgarom.asm:305 + in AL, DX ; ec ; 0xc0177 vgarom.asm:306 + pop dx ; 5a ; 0xc0178 vgarom.asm:308 + pop cx ; 59 ; 0xc0179 vgarom.asm:309 + pop bx ; 5b ; 0xc017a vgarom.asm:310 + pop ax ; 58 ; 0xc017b vgarom.asm:311 + retn ; c3 ; 0xc017c vgarom.asm:312 + push DS ; 1e ; 0xc017d vgarom.asm:317 + mov ax, strict word 00040h ; b8 40 00 ; 0xc017e vgarom.asm:318 + mov ds, ax ; 8e d8 ; 0xc0181 vgarom.asm:319 + push bx ; 53 ; 0xc0183 vgarom.asm:320 + mov bx, strict word 00062h ; bb 62 00 ; 0xc0184 vgarom.asm:321 + mov al, byte [bx] ; 8a 07 ; 0xc0187 vgarom.asm:322 + pop bx ; 5b ; 0xc0189 vgarom.asm:323 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc018a vgarom.asm:324 + push bx ; 53 ; 0xc018c vgarom.asm:325 + mov bx, 00087h ; bb 87 00 ; 0xc018d vgarom.asm:326 + mov ah, byte [bx] ; 8a 27 ; 0xc0190 vgarom.asm:327 + and ah, 080h ; 80 e4 80 ; 0xc0192 vgarom.asm:328 + mov bx, strict word 00049h ; bb 49 00 ; 0xc0195 vgarom.asm:329 + mov al, byte [bx] ; 8a 07 ; 0xc0198 vgarom.asm:330 + db 00ah, 0c4h + ; or al, ah ; 0a c4 ; 0xc019a vgarom.asm:331 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc019c vgarom.asm:332 + mov ah, byte [bx] ; 8a 27 ; 0xc019f vgarom.asm:333 + pop bx ; 5b ; 0xc01a1 vgarom.asm:334 + pop DS ; 1f ; 0xc01a2 vgarom.asm:335 + retn ; c3 ; 0xc01a3 vgarom.asm:336 + cmp AL, strict byte 000h ; 3c 00 ; 0xc01a4 vgarom.asm:341 + jne short 001aah ; 75 02 ; 0xc01a6 vgarom.asm:342 + jmp short 0020bh ; eb 61 ; 0xc01a8 vgarom.asm:343 + cmp AL, strict byte 001h ; 3c 01 ; 0xc01aa vgarom.asm:345 + jne short 001b0h ; 75 02 ; 0xc01ac vgarom.asm:346 + jmp short 00229h ; eb 79 ; 0xc01ae vgarom.asm:347 + cmp AL, strict byte 002h ; 3c 02 ; 0xc01b0 vgarom.asm:349 + jne short 001b6h ; 75 02 ; 0xc01b2 vgarom.asm:350 + jmp short 00231h ; eb 7b ; 0xc01b4 vgarom.asm:351 + cmp AL, strict byte 003h ; 3c 03 ; 0xc01b6 vgarom.asm:353 + jne short 001bdh ; 75 03 ; 0xc01b8 vgarom.asm:354 + jmp near 00262h ; e9 a5 00 ; 0xc01ba vgarom.asm:355 + cmp AL, strict byte 007h ; 3c 07 ; 0xc01bd vgarom.asm:357 + jne short 001c4h ; 75 03 ; 0xc01bf vgarom.asm:358 + jmp near 0028ch ; e9 c8 00 ; 0xc01c1 vgarom.asm:359 + cmp AL, strict byte 008h ; 3c 08 ; 0xc01c4 vgarom.asm:361 + jne short 001cbh ; 75 03 ; 0xc01c6 vgarom.asm:362 + jmp near 002b4h ; e9 e9 00 ; 0xc01c8 vgarom.asm:363 + cmp AL, strict byte 009h ; 3c 09 ; 0xc01cb vgarom.asm:365 + jne short 001d2h ; 75 03 ; 0xc01cd vgarom.asm:366 + jmp near 002c2h ; e9 f0 00 ; 0xc01cf vgarom.asm:367 + cmp AL, strict byte 010h ; 3c 10 ; 0xc01d2 vgarom.asm:369 + jne short 001d9h ; 75 03 ; 0xc01d4 vgarom.asm:370 + jmp near 00307h ; e9 2e 01 ; 0xc01d6 vgarom.asm:371 + cmp AL, strict byte 012h ; 3c 12 ; 0xc01d9 vgarom.asm:373 + jne short 001e0h ; 75 03 ; 0xc01db vgarom.asm:374 + jmp near 00320h ; e9 40 01 ; 0xc01dd vgarom.asm:375 + cmp AL, strict byte 013h ; 3c 13 ; 0xc01e0 vgarom.asm:377 + jne short 001e7h ; 75 03 ; 0xc01e2 vgarom.asm:378 + jmp near 00348h ; e9 61 01 ; 0xc01e4 vgarom.asm:379 + cmp AL, strict byte 015h ; 3c 15 ; 0xc01e7 vgarom.asm:381 + jne short 001eeh ; 75 03 ; 0xc01e9 vgarom.asm:382 + jmp near 0038fh ; e9 a1 01 ; 0xc01eb vgarom.asm:383 + cmp AL, strict byte 017h ; 3c 17 ; 0xc01ee vgarom.asm:385 + jne short 001f5h ; 75 03 ; 0xc01f0 vgarom.asm:386 + jmp near 003aah ; e9 b5 01 ; 0xc01f2 vgarom.asm:387 + cmp AL, strict byte 018h ; 3c 18 ; 0xc01f5 vgarom.asm:389 + jne short 001fch ; 75 03 ; 0xc01f7 vgarom.asm:390 + jmp near 003d2h ; e9 d6 01 ; 0xc01f9 vgarom.asm:391 + cmp AL, strict byte 019h ; 3c 19 ; 0xc01fc vgarom.asm:393 + jne short 00203h ; 75 03 ; 0xc01fe vgarom.asm:394 + jmp near 003ddh ; e9 da 01 ; 0xc0200 vgarom.asm:395 + cmp AL, strict byte 01ah ; 3c 1a ; 0xc0203 vgarom.asm:397 + jne short 0020ah ; 75 03 ; 0xc0205 vgarom.asm:398 + jmp near 003e8h ; e9 de 01 ; 0xc0207 vgarom.asm:399 + retn ; c3 ; 0xc020a vgarom.asm:404 + cmp bl, 014h ; 80 fb 14 ; 0xc020b vgarom.asm:407 + jnbe short 00228h ; 77 18 ; 0xc020e vgarom.asm:408 + push ax ; 50 ; 0xc0210 vgarom.asm:409 + push dx ; 52 ; 0xc0211 vgarom.asm:410 + mov dx, 003dah ; ba da 03 ; 0xc0212 vgarom.asm:411 + in AL, DX ; ec ; 0xc0215 vgarom.asm:412 + mov dx, 003c0h ; ba c0 03 ; 0xc0216 vgarom.asm:413 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0219 vgarom.asm:414 + out DX, AL ; ee ; 0xc021b vgarom.asm:415 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc021c vgarom.asm:416 + out DX, AL ; ee ; 0xc021e vgarom.asm:417 + mov AL, strict byte 020h ; b0 20 ; 0xc021f vgarom.asm:418 + out DX, AL ; ee ; 0xc0221 vgarom.asm:419 + mov dx, 003dah ; ba da 03 ; 0xc0222 vgarom.asm:421 + in AL, DX ; ec ; 0xc0225 vgarom.asm:422 + pop dx ; 5a ; 0xc0226 vgarom.asm:424 + pop ax ; 58 ; 0xc0227 vgarom.asm:425 + retn ; c3 ; 0xc0228 vgarom.asm:427 + push bx ; 53 ; 0xc0229 vgarom.asm:432 + mov BL, strict byte 011h ; b3 11 ; 0xc022a vgarom.asm:433 + call 0020bh ; e8 dc ff ; 0xc022c vgarom.asm:434 + pop bx ; 5b ; 0xc022f vgarom.asm:435 + retn ; c3 ; 0xc0230 vgarom.asm:436 + push ax ; 50 ; 0xc0231 vgarom.asm:441 + push bx ; 53 ; 0xc0232 vgarom.asm:442 + push cx ; 51 ; 0xc0233 vgarom.asm:443 + push dx ; 52 ; 0xc0234 vgarom.asm:444 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc0235 vgarom.asm:445 + mov dx, 003dah ; ba da 03 ; 0xc0237 vgarom.asm:446 + in AL, DX ; ec ; 0xc023a vgarom.asm:447 + mov CL, strict byte 000h ; b1 00 ; 0xc023b vgarom.asm:448 + mov dx, 003c0h ; ba c0 03 ; 0xc023d vgarom.asm:449 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc0240 vgarom.asm:451 + out DX, AL ; ee ; 0xc0242 vgarom.asm:452 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0243 vgarom.asm:453 + out DX, AL ; ee ; 0xc0246 vgarom.asm:454 + inc bx ; 43 ; 0xc0247 vgarom.asm:455 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc0248 vgarom.asm:456 + cmp cl, 010h ; 80 f9 10 ; 0xc024a vgarom.asm:457 + jne short 00240h ; 75 f1 ; 0xc024d vgarom.asm:458 + mov AL, strict byte 011h ; b0 11 ; 0xc024f vgarom.asm:459 + out DX, AL ; ee ; 0xc0251 vgarom.asm:460 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0252 vgarom.asm:461 + out DX, AL ; ee ; 0xc0255 vgarom.asm:462 + mov AL, strict byte 020h ; b0 20 ; 0xc0256 vgarom.asm:463 + out DX, AL ; ee ; 0xc0258 vgarom.asm:464 + mov dx, 003dah ; ba da 03 ; 0xc0259 vgarom.asm:466 + in AL, DX ; ec ; 0xc025c vgarom.asm:467 + pop dx ; 5a ; 0xc025d vgarom.asm:469 + pop cx ; 59 ; 0xc025e vgarom.asm:470 + pop bx ; 5b ; 0xc025f vgarom.asm:471 + pop ax ; 58 ; 0xc0260 vgarom.asm:472 + retn ; c3 ; 0xc0261 vgarom.asm:473 + push ax ; 50 ; 0xc0262 vgarom.asm:478 + push bx ; 53 ; 0xc0263 vgarom.asm:479 + push dx ; 52 ; 0xc0264 vgarom.asm:480 + mov dx, 003dah ; ba da 03 ; 0xc0265 vgarom.asm:481 + in AL, DX ; ec ; 0xc0268 vgarom.asm:482 + mov dx, 003c0h ; ba c0 03 ; 0xc0269 vgarom.asm:483 + mov AL, strict byte 010h ; b0 10 ; 0xc026c vgarom.asm:484 + out DX, AL ; ee ; 0xc026e vgarom.asm:485 + mov dx, 003c1h ; ba c1 03 ; 0xc026f vgarom.asm:486 + in AL, DX ; ec ; 0xc0272 vgarom.asm:487 + and AL, strict byte 0f7h ; 24 f7 ; 0xc0273 vgarom.asm:488 + and bl, 001h ; 80 e3 01 ; 0xc0275 vgarom.asm:489 + sal bl, 003h ; c0 e3 03 ; 0xc0278 vgarom.asm:491 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc027b vgarom.asm:497 + mov dx, 003c0h ; ba c0 03 ; 0xc027d vgarom.asm:498 + out DX, AL ; ee ; 0xc0280 vgarom.asm:499 + mov AL, strict byte 020h ; b0 20 ; 0xc0281 vgarom.asm:500 + out DX, AL ; ee ; 0xc0283 vgarom.asm:501 + mov dx, 003dah ; ba da 03 ; 0xc0284 vgarom.asm:503 + in AL, DX ; ec ; 0xc0287 vgarom.asm:504 + pop dx ; 5a ; 0xc0288 vgarom.asm:506 + pop bx ; 5b ; 0xc0289 vgarom.asm:507 + pop ax ; 58 ; 0xc028a vgarom.asm:508 + retn ; c3 ; 0xc028b vgarom.asm:509 + cmp bl, 014h ; 80 fb 14 ; 0xc028c vgarom.asm:514 + jnbe short 002b3h ; 77 22 ; 0xc028f vgarom.asm:515 + push ax ; 50 ; 0xc0291 vgarom.asm:516 + push dx ; 52 ; 0xc0292 vgarom.asm:517 + mov dx, 003dah ; ba da 03 ; 0xc0293 vgarom.asm:518 + in AL, DX ; ec ; 0xc0296 vgarom.asm:519 + mov dx, 003c0h ; ba c0 03 ; 0xc0297 vgarom.asm:520 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc029a vgarom.asm:521 + out DX, AL ; ee ; 0xc029c vgarom.asm:522 + mov dx, 003c1h ; ba c1 03 ; 0xc029d vgarom.asm:523 + in AL, DX ; ec ; 0xc02a0 vgarom.asm:524 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc02a1 vgarom.asm:525 + mov dx, 003dah ; ba da 03 ; 0xc02a3 vgarom.asm:526 + in AL, DX ; ec ; 0xc02a6 vgarom.asm:527 + mov dx, 003c0h ; ba c0 03 ; 0xc02a7 vgarom.asm:528 + mov AL, strict byte 020h ; b0 20 ; 0xc02aa vgarom.asm:529 + out DX, AL ; ee ; 0xc02ac vgarom.asm:530 + mov dx, 003dah ; ba da 03 ; 0xc02ad vgarom.asm:532 + in AL, DX ; ec ; 0xc02b0 vgarom.asm:533 + pop dx ; 5a ; 0xc02b1 vgarom.asm:535 + pop ax ; 58 ; 0xc02b2 vgarom.asm:536 + retn ; c3 ; 0xc02b3 vgarom.asm:538 + push ax ; 50 ; 0xc02b4 vgarom.asm:543 + push bx ; 53 ; 0xc02b5 vgarom.asm:544 + mov BL, strict byte 011h ; b3 11 ; 0xc02b6 vgarom.asm:545 + call 0028ch ; e8 d1 ff ; 0xc02b8 vgarom.asm:546 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc02bb vgarom.asm:547 + pop bx ; 5b ; 0xc02bd vgarom.asm:548 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc02be vgarom.asm:549 + pop ax ; 58 ; 0xc02c0 vgarom.asm:550 + retn ; c3 ; 0xc02c1 vgarom.asm:551 + push ax ; 50 ; 0xc02c2 vgarom.asm:556 + push bx ; 53 ; 0xc02c3 vgarom.asm:557 + push cx ; 51 ; 0xc02c4 vgarom.asm:558 + push dx ; 52 ; 0xc02c5 vgarom.asm:559 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc02c6 vgarom.asm:560 + mov CL, strict byte 000h ; b1 00 ; 0xc02c8 vgarom.asm:561 + mov dx, 003dah ; ba da 03 ; 0xc02ca vgarom.asm:563 + in AL, DX ; ec ; 0xc02cd vgarom.asm:564 + mov dx, 003c0h ; ba c0 03 ; 0xc02ce vgarom.asm:565 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc02d1 vgarom.asm:566 + out DX, AL ; ee ; 0xc02d3 vgarom.asm:567 + mov dx, 003c1h ; ba c1 03 ; 0xc02d4 vgarom.asm:568 + in AL, DX ; ec ; 0xc02d7 vgarom.asm:569 + mov byte [es:bx], al ; 26 88 07 ; 0xc02d8 vgarom.asm:570 + inc bx ; 43 ; 0xc02db vgarom.asm:571 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc02dc vgarom.asm:572 + cmp cl, 010h ; 80 f9 10 ; 0xc02de vgarom.asm:573 + jne short 002cah ; 75 e7 ; 0xc02e1 vgarom.asm:574 + mov dx, 003dah ; ba da 03 ; 0xc02e3 vgarom.asm:575 + in AL, DX ; ec ; 0xc02e6 vgarom.asm:576 + mov dx, 003c0h ; ba c0 03 ; 0xc02e7 vgarom.asm:577 + mov AL, strict byte 011h ; b0 11 ; 0xc02ea vgarom.asm:578 + out DX, AL ; ee ; 0xc02ec vgarom.asm:579 + mov dx, 003c1h ; ba c1 03 ; 0xc02ed vgarom.asm:580 + in AL, DX ; ec ; 0xc02f0 vgarom.asm:581 + mov byte [es:bx], al ; 26 88 07 ; 0xc02f1 vgarom.asm:582 + mov dx, 003dah ; ba da 03 ; 0xc02f4 vgarom.asm:583 + in AL, DX ; ec ; 0xc02f7 vgarom.asm:584 + mov dx, 003c0h ; ba c0 03 ; 0xc02f8 vgarom.asm:585 + mov AL, strict byte 020h ; b0 20 ; 0xc02fb vgarom.asm:586 + out DX, AL ; ee ; 0xc02fd vgarom.asm:587 + mov dx, 003dah ; ba da 03 ; 0xc02fe vgarom.asm:589 + in AL, DX ; ec ; 0xc0301 vgarom.asm:590 + pop dx ; 5a ; 0xc0302 vgarom.asm:592 + pop cx ; 59 ; 0xc0303 vgarom.asm:593 + pop bx ; 5b ; 0xc0304 vgarom.asm:594 + pop ax ; 58 ; 0xc0305 vgarom.asm:595 + retn ; c3 ; 0xc0306 vgarom.asm:596 + push ax ; 50 ; 0xc0307 vgarom.asm:601 + push dx ; 52 ; 0xc0308 vgarom.asm:602 + mov dx, 003c8h ; ba c8 03 ; 0xc0309 vgarom.asm:603 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc030c vgarom.asm:604 + out DX, AL ; ee ; 0xc030e vgarom.asm:605 + mov dx, 003c9h ; ba c9 03 ; 0xc030f vgarom.asm:606 + pop ax ; 58 ; 0xc0312 vgarom.asm:607 + push ax ; 50 ; 0xc0313 vgarom.asm:608 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc0314 vgarom.asm:609 + out DX, AL ; ee ; 0xc0316 vgarom.asm:610 + db 08ah, 0c5h + ; mov al, ch ; 8a c5 ; 0xc0317 vgarom.asm:611 + out DX, AL ; ee ; 0xc0319 vgarom.asm:612 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc031a vgarom.asm:613 + out DX, AL ; ee ; 0xc031c vgarom.asm:614 + pop dx ; 5a ; 0xc031d vgarom.asm:615 + pop ax ; 58 ; 0xc031e vgarom.asm:616 + retn ; c3 ; 0xc031f vgarom.asm:617 + push ax ; 50 ; 0xc0320 vgarom.asm:622 + push bx ; 53 ; 0xc0321 vgarom.asm:623 + push cx ; 51 ; 0xc0322 vgarom.asm:624 + push dx ; 52 ; 0xc0323 vgarom.asm:625 + mov dx, 003c8h ; ba c8 03 ; 0xc0324 vgarom.asm:626 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0327 vgarom.asm:627 + out DX, AL ; ee ; 0xc0329 vgarom.asm:628 + pop dx ; 5a ; 0xc032a vgarom.asm:629 + push dx ; 52 ; 0xc032b vgarom.asm:630 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc032c vgarom.asm:631 + mov dx, 003c9h ; ba c9 03 ; 0xc032e vgarom.asm:632 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0331 vgarom.asm:634 + out DX, AL ; ee ; 0xc0334 vgarom.asm:635 + inc bx ; 43 ; 0xc0335 vgarom.asm:636 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0336 vgarom.asm:637 + out DX, AL ; ee ; 0xc0339 vgarom.asm:638 + inc bx ; 43 ; 0xc033a vgarom.asm:639 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc033b vgarom.asm:640 + out DX, AL ; ee ; 0xc033e vgarom.asm:641 + inc bx ; 43 ; 0xc033f vgarom.asm:642 + dec cx ; 49 ; 0xc0340 vgarom.asm:643 + jne short 00331h ; 75 ee ; 0xc0341 vgarom.asm:644 + pop dx ; 5a ; 0xc0343 vgarom.asm:645 + pop cx ; 59 ; 0xc0344 vgarom.asm:646 + pop bx ; 5b ; 0xc0345 vgarom.asm:647 + pop ax ; 58 ; 0xc0346 vgarom.asm:648 + retn ; c3 ; 0xc0347 vgarom.asm:649 + push ax ; 50 ; 0xc0348 vgarom.asm:654 + push bx ; 53 ; 0xc0349 vgarom.asm:655 + push dx ; 52 ; 0xc034a vgarom.asm:656 + mov dx, 003dah ; ba da 03 ; 0xc034b vgarom.asm:657 + in AL, DX ; ec ; 0xc034e vgarom.asm:658 + mov dx, 003c0h ; ba c0 03 ; 0xc034f vgarom.asm:659 + mov AL, strict byte 010h ; b0 10 ; 0xc0352 vgarom.asm:660 + out DX, AL ; ee ; 0xc0354 vgarom.asm:661 + mov dx, 003c1h ; ba c1 03 ; 0xc0355 vgarom.asm:662 + in AL, DX ; ec ; 0xc0358 vgarom.asm:663 + and bl, 001h ; 80 e3 01 ; 0xc0359 vgarom.asm:664 + jne short 0036bh ; 75 0d ; 0xc035c vgarom.asm:665 + and AL, strict byte 07fh ; 24 7f ; 0xc035e vgarom.asm:666 + sal bh, 007h ; c0 e7 07 ; 0xc0360 vgarom.asm:668 + db 00ah, 0c7h + ; or al, bh ; 0a c7 ; 0xc0363 vgarom.asm:678 + mov dx, 003c0h ; ba c0 03 ; 0xc0365 vgarom.asm:679 + out DX, AL ; ee ; 0xc0368 vgarom.asm:680 + jmp short 00384h ; eb 19 ; 0xc0369 vgarom.asm:681 + push ax ; 50 ; 0xc036b vgarom.asm:683 + mov dx, 003dah ; ba da 03 ; 0xc036c vgarom.asm:684 + in AL, DX ; ec ; 0xc036f vgarom.asm:685 + mov dx, 003c0h ; ba c0 03 ; 0xc0370 vgarom.asm:686 + mov AL, strict byte 014h ; b0 14 ; 0xc0373 vgarom.asm:687 + out DX, AL ; ee ; 0xc0375 vgarom.asm:688 + pop ax ; 58 ; 0xc0376 vgarom.asm:689 + and AL, strict byte 080h ; 24 80 ; 0xc0377 vgarom.asm:690 + jne short 0037eh ; 75 03 ; 0xc0379 vgarom.asm:691 + sal bh, 002h ; c0 e7 02 ; 0xc037b vgarom.asm:693 + and bh, 00fh ; 80 e7 0f ; 0xc037e vgarom.asm:699 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc0381 vgarom.asm:700 + out DX, AL ; ee ; 0xc0383 vgarom.asm:701 + mov AL, strict byte 020h ; b0 20 ; 0xc0384 vgarom.asm:703 + out DX, AL ; ee ; 0xc0386 vgarom.asm:704 + mov dx, 003dah ; ba da 03 ; 0xc0387 vgarom.asm:706 + in AL, DX ; ec ; 0xc038a vgarom.asm:707 + pop dx ; 5a ; 0xc038b vgarom.asm:709 + pop bx ; 5b ; 0xc038c vgarom.asm:710 + pop ax ; 58 ; 0xc038d vgarom.asm:711 + retn ; c3 ; 0xc038e vgarom.asm:712 + push ax ; 50 ; 0xc038f vgarom.asm:717 + push dx ; 52 ; 0xc0390 vgarom.asm:718 + mov dx, 003c7h ; ba c7 03 ; 0xc0391 vgarom.asm:719 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0394 vgarom.asm:720 + out DX, AL ; ee ; 0xc0396 vgarom.asm:721 + pop ax ; 58 ; 0xc0397 vgarom.asm:722 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc0398 vgarom.asm:723 + mov dx, 003c9h ; ba c9 03 ; 0xc039a vgarom.asm:724 + in AL, DX ; ec ; 0xc039d vgarom.asm:725 + xchg al, ah ; 86 e0 ; 0xc039e vgarom.asm:726 + push ax ; 50 ; 0xc03a0 vgarom.asm:727 + in AL, DX ; ec ; 0xc03a1 vgarom.asm:728 + db 08ah, 0e8h + ; mov ch, al ; 8a e8 ; 0xc03a2 vgarom.asm:729 + in AL, DX ; ec ; 0xc03a4 vgarom.asm:730 + db 08ah, 0c8h + ; mov cl, al ; 8a c8 ; 0xc03a5 vgarom.asm:731 + pop dx ; 5a ; 0xc03a7 vgarom.asm:732 + pop ax ; 58 ; 0xc03a8 vgarom.asm:733 + retn ; c3 ; 0xc03a9 vgarom.asm:734 + push ax ; 50 ; 0xc03aa vgarom.asm:739 + push bx ; 53 ; 0xc03ab vgarom.asm:740 + push cx ; 51 ; 0xc03ac vgarom.asm:741 + push dx ; 52 ; 0xc03ad vgarom.asm:742 + mov dx, 003c7h ; ba c7 03 ; 0xc03ae vgarom.asm:743 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc03b1 vgarom.asm:744 + out DX, AL ; ee ; 0xc03b3 vgarom.asm:745 + pop dx ; 5a ; 0xc03b4 vgarom.asm:746 + push dx ; 52 ; 0xc03b5 vgarom.asm:747 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc03b6 vgarom.asm:748 + mov dx, 003c9h ; ba c9 03 ; 0xc03b8 vgarom.asm:749 + in AL, DX ; ec ; 0xc03bb vgarom.asm:751 + mov byte [es:bx], al ; 26 88 07 ; 0xc03bc vgarom.asm:752 + inc bx ; 43 ; 0xc03bf vgarom.asm:753 + in AL, DX ; ec ; 0xc03c0 vgarom.asm:754 + mov byte [es:bx], al ; 26 88 07 ; 0xc03c1 vgarom.asm:755 + inc bx ; 43 ; 0xc03c4 vgarom.asm:756 + in AL, DX ; ec ; 0xc03c5 vgarom.asm:757 + mov byte [es:bx], al ; 26 88 07 ; 0xc03c6 vgarom.asm:758 + inc bx ; 43 ; 0xc03c9 vgarom.asm:759 + dec cx ; 49 ; 0xc03ca vgarom.asm:760 + jne short 003bbh ; 75 ee ; 0xc03cb vgarom.asm:761 + pop dx ; 5a ; 0xc03cd vgarom.asm:762 + pop cx ; 59 ; 0xc03ce vgarom.asm:763 + pop bx ; 5b ; 0xc03cf vgarom.asm:764 + pop ax ; 58 ; 0xc03d0 vgarom.asm:765 + retn ; c3 ; 0xc03d1 vgarom.asm:766 + push ax ; 50 ; 0xc03d2 vgarom.asm:771 + push dx ; 52 ; 0xc03d3 vgarom.asm:772 + mov dx, 003c6h ; ba c6 03 ; 0xc03d4 vgarom.asm:773 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc03d7 vgarom.asm:774 + out DX, AL ; ee ; 0xc03d9 vgarom.asm:775 + pop dx ; 5a ; 0xc03da vgarom.asm:776 + pop ax ; 58 ; 0xc03db vgarom.asm:777 + retn ; c3 ; 0xc03dc vgarom.asm:778 + push ax ; 50 ; 0xc03dd vgarom.asm:783 + push dx ; 52 ; 0xc03de vgarom.asm:784 + mov dx, 003c6h ; ba c6 03 ; 0xc03df vgarom.asm:785 + in AL, DX ; ec ; 0xc03e2 vgarom.asm:786 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc03e3 vgarom.asm:787 + pop dx ; 5a ; 0xc03e5 vgarom.asm:788 + pop ax ; 58 ; 0xc03e6 vgarom.asm:789 + retn ; c3 ; 0xc03e7 vgarom.asm:790 + push ax ; 50 ; 0xc03e8 vgarom.asm:795 + push dx ; 52 ; 0xc03e9 vgarom.asm:796 + mov dx, 003dah ; ba da 03 ; 0xc03ea vgarom.asm:797 + in AL, DX ; ec ; 0xc03ed vgarom.asm:798 + mov dx, 003c0h ; ba c0 03 ; 0xc03ee vgarom.asm:799 + mov AL, strict byte 010h ; b0 10 ; 0xc03f1 vgarom.asm:800 + out DX, AL ; ee ; 0xc03f3 vgarom.asm:801 + mov dx, 003c1h ; ba c1 03 ; 0xc03f4 vgarom.asm:802 + in AL, DX ; ec ; 0xc03f7 vgarom.asm:803 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc03f8 vgarom.asm:804 + shr bl, 007h ; c0 eb 07 ; 0xc03fa vgarom.asm:806 + mov dx, 003dah ; ba da 03 ; 0xc03fd vgarom.asm:816 + in AL, DX ; ec ; 0xc0400 vgarom.asm:817 + mov dx, 003c0h ; ba c0 03 ; 0xc0401 vgarom.asm:818 + mov AL, strict byte 014h ; b0 14 ; 0xc0404 vgarom.asm:819 + out DX, AL ; ee ; 0xc0406 vgarom.asm:820 + mov dx, 003c1h ; ba c1 03 ; 0xc0407 vgarom.asm:821 + in AL, DX ; ec ; 0xc040a vgarom.asm:822 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc040b vgarom.asm:823 + and bh, 00fh ; 80 e7 0f ; 0xc040d vgarom.asm:824 + test bl, 001h ; f6 c3 01 ; 0xc0410 vgarom.asm:825 + jne short 00418h ; 75 03 ; 0xc0413 vgarom.asm:826 + shr bh, 002h ; c0 ef 02 ; 0xc0415 vgarom.asm:828 + mov dx, 003dah ; ba da 03 ; 0xc0418 vgarom.asm:834 + in AL, DX ; ec ; 0xc041b vgarom.asm:835 + mov dx, 003c0h ; ba c0 03 ; 0xc041c vgarom.asm:836 + mov AL, strict byte 020h ; b0 20 ; 0xc041f vgarom.asm:837 + out DX, AL ; ee ; 0xc0421 vgarom.asm:838 + mov dx, 003dah ; ba da 03 ; 0xc0422 vgarom.asm:840 + in AL, DX ; ec ; 0xc0425 vgarom.asm:841 + pop dx ; 5a ; 0xc0426 vgarom.asm:843 + pop ax ; 58 ; 0xc0427 vgarom.asm:844 + retn ; c3 ; 0xc0428 vgarom.asm:845 + push ax ; 50 ; 0xc0429 vgarom.asm:850 + push dx ; 52 ; 0xc042a vgarom.asm:851 + mov dx, 003c4h ; ba c4 03 ; 0xc042b vgarom.asm:852 + db 08ah, 0e3h + ; mov ah, bl ; 8a e3 ; 0xc042e vgarom.asm:853 + mov AL, strict byte 003h ; b0 03 ; 0xc0430 vgarom.asm:854 + out DX, ax ; ef ; 0xc0432 vgarom.asm:855 + pop dx ; 5a ; 0xc0433 vgarom.asm:856 + pop ax ; 58 ; 0xc0434 vgarom.asm:857 + retn ; c3 ; 0xc0435 vgarom.asm:858 + push DS ; 1e ; 0xc0436 vgarom.asm:863 + push ax ; 50 ; 0xc0437 vgarom.asm:864 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0438 vgarom.asm:865 + mov ds, ax ; 8e d8 ; 0xc043b vgarom.asm:866 + db 032h, 0edh + ; xor ch, ch ; 32 ed ; 0xc043d vgarom.asm:867 + mov bx, 00088h ; bb 88 00 ; 0xc043f vgarom.asm:868 + mov cl, byte [bx] ; 8a 0f ; 0xc0442 vgarom.asm:869 + and cl, 00fh ; 80 e1 0f ; 0xc0444 vgarom.asm:870 + mov bx, strict word 00063h ; bb 63 00 ; 0xc0447 vgarom.asm:871 + mov ax, word [bx] ; 8b 07 ; 0xc044a vgarom.asm:872 + mov bx, strict word 00003h ; bb 03 00 ; 0xc044c vgarom.asm:873 + cmp ax, 003b4h ; 3d b4 03 ; 0xc044f vgarom.asm:874 + jne short 00456h ; 75 02 ; 0xc0452 vgarom.asm:875 + mov BH, strict byte 001h ; b7 01 ; 0xc0454 vgarom.asm:876 + pop ax ; 58 ; 0xc0456 vgarom.asm:878 + pop DS ; 1f ; 0xc0457 vgarom.asm:879 + retn ; c3 ; 0xc0458 vgarom.asm:880 + push DS ; 1e ; 0xc0459 vgarom.asm:888 + push bx ; 53 ; 0xc045a vgarom.asm:889 + push dx ; 52 ; 0xc045b vgarom.asm:890 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc045c vgarom.asm:891 + mov ax, strict word 00040h ; b8 40 00 ; 0xc045e vgarom.asm:892 + mov ds, ax ; 8e d8 ; 0xc0461 vgarom.asm:893 + mov bx, 00089h ; bb 89 00 ; 0xc0463 vgarom.asm:894 + mov al, byte [bx] ; 8a 07 ; 0xc0466 vgarom.asm:895 + mov bx, 00088h ; bb 88 00 ; 0xc0468 vgarom.asm:896 + mov ah, byte [bx] ; 8a 27 ; 0xc046b vgarom.asm:897 + cmp dl, 001h ; 80 fa 01 ; 0xc046d vgarom.asm:898 + je short 00487h ; 74 15 ; 0xc0470 vgarom.asm:899 + jc short 00491h ; 72 1d ; 0xc0472 vgarom.asm:900 + cmp dl, 002h ; 80 fa 02 ; 0xc0474 vgarom.asm:901 + je short 0047bh ; 74 02 ; 0xc0477 vgarom.asm:902 + jmp short 004a5h ; eb 2a ; 0xc0479 vgarom.asm:912 + and AL, strict byte 07fh ; 24 7f ; 0xc047b vgarom.asm:918 + or AL, strict byte 010h ; 0c 10 ; 0xc047d vgarom.asm:919 + and ah, 0f0h ; 80 e4 f0 ; 0xc047f vgarom.asm:920 + or ah, 009h ; 80 cc 09 ; 0xc0482 vgarom.asm:921 + jne short 0049bh ; 75 14 ; 0xc0485 vgarom.asm:922 + and AL, strict byte 06fh ; 24 6f ; 0xc0487 vgarom.asm:928 + and ah, 0f0h ; 80 e4 f0 ; 0xc0489 vgarom.asm:929 + or ah, 009h ; 80 cc 09 ; 0xc048c vgarom.asm:930 + jne short 0049bh ; 75 0a ; 0xc048f vgarom.asm:931 + and AL, strict byte 0efh ; 24 ef ; 0xc0491 vgarom.asm:937 + or AL, strict byte 080h ; 0c 80 ; 0xc0493 vgarom.asm:938 + and ah, 0f0h ; 80 e4 f0 ; 0xc0495 vgarom.asm:939 + or ah, 008h ; 80 cc 08 ; 0xc0498 vgarom.asm:940 + mov bx, 00089h ; bb 89 00 ; 0xc049b vgarom.asm:942 + mov byte [bx], al ; 88 07 ; 0xc049e vgarom.asm:943 + mov bx, 00088h ; bb 88 00 ; 0xc04a0 vgarom.asm:944 + mov byte [bx], ah ; 88 27 ; 0xc04a3 vgarom.asm:945 + mov ax, 01212h ; b8 12 12 ; 0xc04a5 vgarom.asm:947 + pop dx ; 5a ; 0xc04a8 vgarom.asm:948 + pop bx ; 5b ; 0xc04a9 vgarom.asm:949 + pop DS ; 1f ; 0xc04aa vgarom.asm:950 + retn ; c3 ; 0xc04ab vgarom.asm:951 + push DS ; 1e ; 0xc04ac vgarom.asm:960 + push bx ; 53 ; 0xc04ad vgarom.asm:961 + push dx ; 52 ; 0xc04ae vgarom.asm:962 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc04af vgarom.asm:963 + and dl, 001h ; 80 e2 01 ; 0xc04b1 vgarom.asm:964 + sal dl, 003h ; c0 e2 03 ; 0xc04b4 vgarom.asm:966 + mov ax, strict word 00040h ; b8 40 00 ; 0xc04b7 vgarom.asm:972 + mov ds, ax ; 8e d8 ; 0xc04ba vgarom.asm:973 + mov bx, 00089h ; bb 89 00 ; 0xc04bc vgarom.asm:974 + mov al, byte [bx] ; 8a 07 ; 0xc04bf vgarom.asm:975 + and AL, strict byte 0f7h ; 24 f7 ; 0xc04c1 vgarom.asm:976 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc04c3 vgarom.asm:977 + mov byte [bx], al ; 88 07 ; 0xc04c5 vgarom.asm:978 + mov ax, 01212h ; b8 12 12 ; 0xc04c7 vgarom.asm:979 + pop dx ; 5a ; 0xc04ca vgarom.asm:980 + pop bx ; 5b ; 0xc04cb vgarom.asm:981 + pop DS ; 1f ; 0xc04cc vgarom.asm:982 + retn ; c3 ; 0xc04cd vgarom.asm:983 + push bx ; 53 ; 0xc04ce vgarom.asm:987 + push dx ; 52 ; 0xc04cf vgarom.asm:988 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc04d0 vgarom.asm:989 + and bl, 001h ; 80 e3 01 ; 0xc04d2 vgarom.asm:990 + xor bl, 001h ; 80 f3 01 ; 0xc04d5 vgarom.asm:991 + sal bl, 1 ; d0 e3 ; 0xc04d8 vgarom.asm:992 + mov dx, 003cch ; ba cc 03 ; 0xc04da vgarom.asm:993 + in AL, DX ; ec ; 0xc04dd vgarom.asm:994 + and AL, strict byte 0fdh ; 24 fd ; 0xc04de vgarom.asm:995 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc04e0 vgarom.asm:996 + mov dx, 003c2h ; ba c2 03 ; 0xc04e2 vgarom.asm:997 + out DX, AL ; ee ; 0xc04e5 vgarom.asm:998 + mov ax, 01212h ; b8 12 12 ; 0xc04e6 vgarom.asm:999 + pop dx ; 5a ; 0xc04e9 vgarom.asm:1000 + pop bx ; 5b ; 0xc04ea vgarom.asm:1001 + retn ; c3 ; 0xc04eb vgarom.asm:1002 + push DS ; 1e ; 0xc04ec vgarom.asm:1006 + push bx ; 53 ; 0xc04ed vgarom.asm:1007 + push dx ; 52 ; 0xc04ee vgarom.asm:1008 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc04ef vgarom.asm:1009 + and dl, 001h ; 80 e2 01 ; 0xc04f1 vgarom.asm:1010 + xor dl, 001h ; 80 f2 01 ; 0xc04f4 vgarom.asm:1011 + sal dl, 1 ; d0 e2 ; 0xc04f7 vgarom.asm:1012 + mov ax, strict word 00040h ; b8 40 00 ; 0xc04f9 vgarom.asm:1013 + mov ds, ax ; 8e d8 ; 0xc04fc vgarom.asm:1014 + mov bx, 00089h ; bb 89 00 ; 0xc04fe vgarom.asm:1015 + mov al, byte [bx] ; 8a 07 ; 0xc0501 vgarom.asm:1016 + and AL, strict byte 0fdh ; 24 fd ; 0xc0503 vgarom.asm:1017 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc0505 vgarom.asm:1018 + mov byte [bx], al ; 88 07 ; 0xc0507 vgarom.asm:1019 + mov ax, 01212h ; b8 12 12 ; 0xc0509 vgarom.asm:1020 + pop dx ; 5a ; 0xc050c vgarom.asm:1021 + pop bx ; 5b ; 0xc050d vgarom.asm:1022 + pop DS ; 1f ; 0xc050e vgarom.asm:1023 + retn ; c3 ; 0xc050f vgarom.asm:1024 + push DS ; 1e ; 0xc0510 vgarom.asm:1028 + push bx ; 53 ; 0xc0511 vgarom.asm:1029 + push dx ; 52 ; 0xc0512 vgarom.asm:1030 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc0513 vgarom.asm:1031 + and dl, 001h ; 80 e2 01 ; 0xc0515 vgarom.asm:1032 + xor dl, 001h ; 80 f2 01 ; 0xc0518 vgarom.asm:1033 + mov ax, strict word 00040h ; b8 40 00 ; 0xc051b vgarom.asm:1034 + mov ds, ax ; 8e d8 ; 0xc051e vgarom.asm:1035 + mov bx, 00089h ; bb 89 00 ; 0xc0520 vgarom.asm:1036 + mov al, byte [bx] ; 8a 07 ; 0xc0523 vgarom.asm:1037 + and AL, strict byte 0feh ; 24 fe ; 0xc0525 vgarom.asm:1038 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc0527 vgarom.asm:1039 + mov byte [bx], al ; 88 07 ; 0xc0529 vgarom.asm:1040 + mov ax, 01212h ; b8 12 12 ; 0xc052b vgarom.asm:1041 + pop dx ; 5a ; 0xc052e vgarom.asm:1042 + pop bx ; 5b ; 0xc052f vgarom.asm:1043 + pop DS ; 1f ; 0xc0530 vgarom.asm:1044 + retn ; c3 ; 0xc0531 vgarom.asm:1045 + cmp AL, strict byte 000h ; 3c 00 ; 0xc0532 vgarom.asm:1050 + je short 0053bh ; 74 05 ; 0xc0534 vgarom.asm:1051 + cmp AL, strict byte 001h ; 3c 01 ; 0xc0536 vgarom.asm:1052 + je short 00550h ; 74 16 ; 0xc0538 vgarom.asm:1053 + retn ; c3 ; 0xc053a vgarom.asm:1057 + push DS ; 1e ; 0xc053b vgarom.asm:1059 + push ax ; 50 ; 0xc053c vgarom.asm:1060 + mov ax, strict word 00040h ; b8 40 00 ; 0xc053d vgarom.asm:1061 + mov ds, ax ; 8e d8 ; 0xc0540 vgarom.asm:1062 + mov bx, 0008ah ; bb 8a 00 ; 0xc0542 vgarom.asm:1063 + mov al, byte [bx] ; 8a 07 ; 0xc0545 vgarom.asm:1064 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc0547 vgarom.asm:1065 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc0549 vgarom.asm:1066 + pop ax ; 58 ; 0xc054b vgarom.asm:1067 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc054c vgarom.asm:1068 + pop DS ; 1f ; 0xc054e vgarom.asm:1069 + retn ; c3 ; 0xc054f vgarom.asm:1070 + push DS ; 1e ; 0xc0550 vgarom.asm:1072 + push ax ; 50 ; 0xc0551 vgarom.asm:1073 + push bx ; 53 ; 0xc0552 vgarom.asm:1074 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0553 vgarom.asm:1075 + mov ds, ax ; 8e d8 ; 0xc0556 vgarom.asm:1076 + db 08bh, 0c3h + ; mov ax, bx ; 8b c3 ; 0xc0558 vgarom.asm:1077 + mov bx, 0008ah ; bb 8a 00 ; 0xc055a vgarom.asm:1078 + mov byte [bx], al ; 88 07 ; 0xc055d vgarom.asm:1079 + pop bx ; 5b ; 0xc055f vgarom.asm:1089 + pop ax ; 58 ; 0xc0560 vgarom.asm:1090 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc0561 vgarom.asm:1091 + pop DS ; 1f ; 0xc0563 vgarom.asm:1092 + retn ; c3 ; 0xc0564 vgarom.asm:1093 + times 0xb db 0 + ; disGetNextSymbol 0xc0570 LB 0x397 -> off=0x0 cb=0000000000000007 uValue=00000000000c0570 'do_out_dx_ax' +do_out_dx_ax: ; 0xc0570 LB 0x7 + xchg ah, al ; 86 c4 ; 0xc0570 vberom.asm:69 + out DX, AL ; ee ; 0xc0572 vberom.asm:70 + xchg ah, al ; 86 c4 ; 0xc0573 vberom.asm:71 + out DX, AL ; ee ; 0xc0575 vberom.asm:72 + retn ; c3 ; 0xc0576 vberom.asm:73 + ; disGetNextSymbol 0xc0577 LB 0x390 -> off=0x0 cb=0000000000000040 uValue=00000000000c0577 'do_in_ax_dx' +do_in_ax_dx: ; 0xc0577 LB 0x40 + in AL, DX ; ec ; 0xc0577 vberom.asm:76 + xchg ah, al ; 86 c4 ; 0xc0578 vberom.asm:77 + in AL, DX ; ec ; 0xc057a vberom.asm:78 + retn ; c3 ; 0xc057b vberom.asm:79 + push ax ; 50 ; 0xc057c vberom.asm:90 + push dx ; 52 ; 0xc057d vberom.asm:91 + mov dx, 003dah ; ba da 03 ; 0xc057e vberom.asm:92 + in AL, DX ; ec ; 0xc0581 vberom.asm:94 + test AL, strict byte 008h ; a8 08 ; 0xc0582 vberom.asm:95 + je short 00581h ; 74 fb ; 0xc0584 vberom.asm:96 + pop dx ; 5a ; 0xc0586 vberom.asm:97 + pop ax ; 58 ; 0xc0587 vberom.asm:98 + retn ; c3 ; 0xc0588 vberom.asm:99 + push ax ; 50 ; 0xc0589 vberom.asm:102 + push dx ; 52 ; 0xc058a vberom.asm:103 + mov dx, 003dah ; ba da 03 ; 0xc058b vberom.asm:104 + in AL, DX ; ec ; 0xc058e vberom.asm:106 + test AL, strict byte 008h ; a8 08 ; 0xc058f vberom.asm:107 + jne short 0058eh ; 75 fb ; 0xc0591 vberom.asm:108 + pop dx ; 5a ; 0xc0593 vberom.asm:109 + pop ax ; 58 ; 0xc0594 vberom.asm:110 + retn ; c3 ; 0xc0595 vberom.asm:111 + push dx ; 52 ; 0xc0596 vberom.asm:116 + mov dx, 001ceh ; ba ce 01 ; 0xc0597 vberom.asm:117 + mov ax, strict word 00003h ; b8 03 00 ; 0xc059a vberom.asm:118 + call 00570h ; e8 d0 ff ; 0xc059d vberom.asm:119 + mov dx, 001cfh ; ba cf 01 ; 0xc05a0 vberom.asm:120 + call 00577h ; e8 d1 ff ; 0xc05a3 vberom.asm:121 + cmp AL, strict byte 004h ; 3c 04 ; 0xc05a6 vberom.asm:122 + jbe short 005b5h ; 76 0b ; 0xc05a8 vberom.asm:123 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc05aa vberom.asm:124 + shr ah, 003h ; c0 ec 03 ; 0xc05ac vberom.asm:126 + test AL, strict byte 007h ; a8 07 ; 0xc05af vberom.asm:132 + je short 005b5h ; 74 02 ; 0xc05b1 vberom.asm:133 + db 0feh, 0c4h + ; inc ah ; fe c4 ; 0xc05b3 vberom.asm:134 + pop dx ; 5a ; 0xc05b5 vberom.asm:136 + retn ; c3 ; 0xc05b6 vberom.asm:137 + ; disGetNextSymbol 0xc05b7 LB 0x350 -> off=0x0 cb=0000000000000026 uValue=00000000000c05b7 '_dispi_get_max_bpp' +_dispi_get_max_bpp: ; 0xc05b7 LB 0x26 + push dx ; 52 ; 0xc05b7 vberom.asm:142 + push bx ; 53 ; 0xc05b8 vberom.asm:143 + call 005f1h ; e8 35 00 ; 0xc05b9 vberom.asm:144 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc05bc vberom.asm:145 + or ax, strict byte 00002h ; 83 c8 02 ; 0xc05be vberom.asm:146 + call 005ddh ; e8 19 00 ; 0xc05c1 vberom.asm:147 + mov dx, 001ceh ; ba ce 01 ; 0xc05c4 vberom.asm:148 + mov ax, strict word 00003h ; b8 03 00 ; 0xc05c7 vberom.asm:149 + call 00570h ; e8 a3 ff ; 0xc05ca vberom.asm:150 + mov dx, 001cfh ; ba cf 01 ; 0xc05cd vberom.asm:151 + call 00577h ; e8 a4 ff ; 0xc05d0 vberom.asm:152 + push ax ; 50 ; 0xc05d3 vberom.asm:153 + db 08bh, 0c3h + ; mov ax, bx ; 8b c3 ; 0xc05d4 vberom.asm:154 + call 005ddh ; e8 04 00 ; 0xc05d6 vberom.asm:155 + pop ax ; 58 ; 0xc05d9 vberom.asm:156 + pop bx ; 5b ; 0xc05da vberom.asm:157 + pop dx ; 5a ; 0xc05db vberom.asm:158 + retn ; c3 ; 0xc05dc vberom.asm:159 + ; disGetNextSymbol 0xc05dd LB 0x32a -> off=0x0 cb=0000000000000026 uValue=00000000000c05dd 'dispi_set_enable_' +dispi_set_enable_: ; 0xc05dd LB 0x26 + push dx ; 52 ; 0xc05dd vberom.asm:162 + push ax ; 50 ; 0xc05de vberom.asm:163 + mov dx, 001ceh ; ba ce 01 ; 0xc05df vberom.asm:164 + mov ax, strict word 00004h ; b8 04 00 ; 0xc05e2 vberom.asm:165 + call 00570h ; e8 88 ff ; 0xc05e5 vberom.asm:166 + pop ax ; 58 ; 0xc05e8 vberom.asm:167 + mov dx, 001cfh ; ba cf 01 ; 0xc05e9 vberom.asm:168 + call 00570h ; e8 81 ff ; 0xc05ec vberom.asm:169 + pop dx ; 5a ; 0xc05ef vberom.asm:170 + retn ; c3 ; 0xc05f0 vberom.asm:171 + push dx ; 52 ; 0xc05f1 vberom.asm:174 + mov dx, 001ceh ; ba ce 01 ; 0xc05f2 vberom.asm:175 + mov ax, strict word 00004h ; b8 04 00 ; 0xc05f5 vberom.asm:176 + call 00570h ; e8 75 ff ; 0xc05f8 vberom.asm:177 + mov dx, 001cfh ; ba cf 01 ; 0xc05fb vberom.asm:178 + call 00577h ; e8 76 ff ; 0xc05fe vberom.asm:179 + pop dx ; 5a ; 0xc0601 vberom.asm:180 + retn ; c3 ; 0xc0602 vberom.asm:181 + ; disGetNextSymbol 0xc0603 LB 0x304 -> off=0x0 cb=0000000000000026 uValue=00000000000c0603 'dispi_set_bank_' +dispi_set_bank_: ; 0xc0603 LB 0x26 + push dx ; 52 ; 0xc0603 vberom.asm:184 + push ax ; 50 ; 0xc0604 vberom.asm:185 + mov dx, 001ceh ; ba ce 01 ; 0xc0605 vberom.asm:186 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0608 vberom.asm:187 + call 00570h ; e8 62 ff ; 0xc060b vberom.asm:188 + pop ax ; 58 ; 0xc060e vberom.asm:189 + mov dx, 001cfh ; ba cf 01 ; 0xc060f vberom.asm:190 + call 00570h ; e8 5b ff ; 0xc0612 vberom.asm:191 + pop dx ; 5a ; 0xc0615 vberom.asm:192 + retn ; c3 ; 0xc0616 vberom.asm:193 + push dx ; 52 ; 0xc0617 vberom.asm:196 + mov dx, 001ceh ; ba ce 01 ; 0xc0618 vberom.asm:197 + mov ax, strict word 00005h ; b8 05 00 ; 0xc061b vberom.asm:198 + call 00570h ; e8 4f ff ; 0xc061e vberom.asm:199 + mov dx, 001cfh ; ba cf 01 ; 0xc0621 vberom.asm:200 + call 00577h ; e8 50 ff ; 0xc0624 vberom.asm:201 + pop dx ; 5a ; 0xc0627 vberom.asm:202 + retn ; c3 ; 0xc0628 vberom.asm:203 + ; disGetNextSymbol 0xc0629 LB 0x2de -> off=0x0 cb=00000000000000a9 uValue=00000000000c0629 '_dispi_set_bank_farcall' +_dispi_set_bank_farcall: ; 0xc0629 LB 0xa9 + cmp bx, 00100h ; 81 fb 00 01 ; 0xc0629 vberom.asm:206 + je short 00653h ; 74 24 ; 0xc062d vberom.asm:207 + db 00bh, 0dbh + ; or bx, bx ; 0b db ; 0xc062f vberom.asm:208 + jne short 00665h ; 75 32 ; 0xc0631 vberom.asm:209 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc0633 vberom.asm:210 + push dx ; 52 ; 0xc0635 vberom.asm:211 + push ax ; 50 ; 0xc0636 vberom.asm:212 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0637 vberom.asm:213 + mov dx, 001ceh ; ba ce 01 ; 0xc063a vberom.asm:214 + call 00570h ; e8 30 ff ; 0xc063d vberom.asm:215 + pop ax ; 58 ; 0xc0640 vberom.asm:216 + mov dx, 001cfh ; ba cf 01 ; 0xc0641 vberom.asm:217 + call 00570h ; e8 29 ff ; 0xc0644 vberom.asm:218 + call 00577h ; e8 2d ff ; 0xc0647 vberom.asm:219 + pop dx ; 5a ; 0xc064a vberom.asm:220 + db 03bh, 0d0h + ; cmp dx, ax ; 3b d0 ; 0xc064b vberom.asm:221 + jne short 00665h ; 75 16 ; 0xc064d vberom.asm:222 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc064f vberom.asm:223 + retf ; cb ; 0xc0652 vberom.asm:224 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0653 vberom.asm:226 + mov dx, 001ceh ; ba ce 01 ; 0xc0656 vberom.asm:227 + call 00570h ; e8 14 ff ; 0xc0659 vberom.asm:228 + mov dx, 001cfh ; ba cf 01 ; 0xc065c vberom.asm:229 + call 00577h ; e8 15 ff ; 0xc065f vberom.asm:230 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc0662 vberom.asm:231 + retf ; cb ; 0xc0664 vberom.asm:232 + mov ax, 0014fh ; b8 4f 01 ; 0xc0665 vberom.asm:234 + retf ; cb ; 0xc0668 vberom.asm:235 + push dx ; 52 ; 0xc0669 vberom.asm:238 + push ax ; 50 ; 0xc066a vberom.asm:239 + mov dx, 001ceh ; ba ce 01 ; 0xc066b vberom.asm:240 + mov ax, strict word 00008h ; b8 08 00 ; 0xc066e vberom.asm:241 + call 00570h ; e8 fc fe ; 0xc0671 vberom.asm:242 + pop ax ; 58 ; 0xc0674 vberom.asm:243 + mov dx, 001cfh ; ba cf 01 ; 0xc0675 vberom.asm:244 + call 00570h ; e8 f5 fe ; 0xc0678 vberom.asm:245 + pop dx ; 5a ; 0xc067b vberom.asm:246 + retn ; c3 ; 0xc067c vberom.asm:247 + push dx ; 52 ; 0xc067d vberom.asm:250 + mov dx, 001ceh ; ba ce 01 ; 0xc067e vberom.asm:251 + mov ax, strict word 00008h ; b8 08 00 ; 0xc0681 vberom.asm:252 + call 00570h ; e8 e9 fe ; 0xc0684 vberom.asm:253 + mov dx, 001cfh ; ba cf 01 ; 0xc0687 vberom.asm:254 + call 00577h ; e8 ea fe ; 0xc068a vberom.asm:255 + pop dx ; 5a ; 0xc068d vberom.asm:256 + retn ; c3 ; 0xc068e vberom.asm:257 + push dx ; 52 ; 0xc068f vberom.asm:260 + push ax ; 50 ; 0xc0690 vberom.asm:261 + mov dx, 001ceh ; ba ce 01 ; 0xc0691 vberom.asm:262 + mov ax, strict word 00009h ; b8 09 00 ; 0xc0694 vberom.asm:263 + call 00570h ; e8 d6 fe ; 0xc0697 vberom.asm:264 + pop ax ; 58 ; 0xc069a vberom.asm:265 + mov dx, 001cfh ; ba cf 01 ; 0xc069b vberom.asm:266 + call 00570h ; e8 cf fe ; 0xc069e vberom.asm:267 + pop dx ; 5a ; 0xc06a1 vberom.asm:268 + retn ; c3 ; 0xc06a2 vberom.asm:269 + push dx ; 52 ; 0xc06a3 vberom.asm:272 + mov dx, 001ceh ; ba ce 01 ; 0xc06a4 vberom.asm:273 + mov ax, strict word 00009h ; b8 09 00 ; 0xc06a7 vberom.asm:274 + call 00570h ; e8 c3 fe ; 0xc06aa vberom.asm:275 + mov dx, 001cfh ; ba cf 01 ; 0xc06ad vberom.asm:276 + call 00577h ; e8 c4 fe ; 0xc06b0 vberom.asm:277 + pop dx ; 5a ; 0xc06b3 vberom.asm:278 + retn ; c3 ; 0xc06b4 vberom.asm:279 + push ax ; 50 ; 0xc06b5 vberom.asm:282 + push bx ; 53 ; 0xc06b6 vberom.asm:283 + push dx ; 52 ; 0xc06b7 vberom.asm:284 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc06b8 vberom.asm:285 + call 00596h ; e8 d9 fe ; 0xc06ba vberom.asm:286 + cmp AL, strict byte 004h ; 3c 04 ; 0xc06bd vberom.asm:287 + jnbe short 006c3h ; 77 02 ; 0xc06bf vberom.asm:288 + shr bx, 1 ; d1 eb ; 0xc06c1 vberom.asm:289 + shr bx, 003h ; c1 eb 03 ; 0xc06c3 vberom.asm:292 + mov dx, 003d4h ; ba d4 03 ; 0xc06c6 vberom.asm:298 + db 08ah, 0e3h + ; mov ah, bl ; 8a e3 ; 0xc06c9 vberom.asm:299 + mov AL, strict byte 013h ; b0 13 ; 0xc06cb vberom.asm:300 + out DX, ax ; ef ; 0xc06cd vberom.asm:301 + pop dx ; 5a ; 0xc06ce vberom.asm:302 + pop bx ; 5b ; 0xc06cf vberom.asm:303 + pop ax ; 58 ; 0xc06d0 vberom.asm:304 + retn ; c3 ; 0xc06d1 vberom.asm:305 + ; disGetNextSymbol 0xc06d2 LB 0x235 -> off=0x0 cb=00000000000000ed uValue=00000000000c06d2 '_vga_compat_setup' +_vga_compat_setup: ; 0xc06d2 LB 0xed + push ax ; 50 ; 0xc06d2 vberom.asm:308 + push dx ; 52 ; 0xc06d3 vberom.asm:309 + mov dx, 001ceh ; ba ce 01 ; 0xc06d4 vberom.asm:312 + mov ax, strict word 00001h ; b8 01 00 ; 0xc06d7 vberom.asm:313 + call 00570h ; e8 93 fe ; 0xc06da vberom.asm:314 + mov dx, 001cfh ; ba cf 01 ; 0xc06dd vberom.asm:315 + call 00577h ; e8 94 fe ; 0xc06e0 vberom.asm:316 + push ax ; 50 ; 0xc06e3 vberom.asm:317 + mov dx, 003d4h ; ba d4 03 ; 0xc06e4 vberom.asm:318 + mov ax, strict word 00011h ; b8 11 00 ; 0xc06e7 vberom.asm:319 + out DX, ax ; ef ; 0xc06ea vberom.asm:320 + pop ax ; 58 ; 0xc06eb vberom.asm:321 + push ax ; 50 ; 0xc06ec vberom.asm:322 + shr ax, 003h ; c1 e8 03 ; 0xc06ed vberom.asm:324 + dec ax ; 48 ; 0xc06f0 vberom.asm:330 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc06f1 vberom.asm:331 + mov AL, strict byte 001h ; b0 01 ; 0xc06f3 vberom.asm:332 + out DX, ax ; ef ; 0xc06f5 vberom.asm:333 + pop ax ; 58 ; 0xc06f6 vberom.asm:334 + call 006b5h ; e8 bb ff ; 0xc06f7 vberom.asm:335 + mov dx, 001ceh ; ba ce 01 ; 0xc06fa vberom.asm:338 + mov ax, strict word 00002h ; b8 02 00 ; 0xc06fd vberom.asm:339 + call 00570h ; e8 6d fe ; 0xc0700 vberom.asm:340 + mov dx, 001cfh ; ba cf 01 ; 0xc0703 vberom.asm:341 + call 00577h ; e8 6e fe ; 0xc0706 vberom.asm:342 + dec ax ; 48 ; 0xc0709 vberom.asm:343 + push ax ; 50 ; 0xc070a vberom.asm:344 + mov dx, 003d4h ; ba d4 03 ; 0xc070b vberom.asm:345 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc070e vberom.asm:346 + mov AL, strict byte 012h ; b0 12 ; 0xc0710 vberom.asm:347 + out DX, ax ; ef ; 0xc0712 vberom.asm:348 + pop ax ; 58 ; 0xc0713 vberom.asm:349 + mov AL, strict byte 007h ; b0 07 ; 0xc0714 vberom.asm:350 + out DX, AL ; ee ; 0xc0716 vberom.asm:351 + inc dx ; 42 ; 0xc0717 vberom.asm:352 + in AL, DX ; ec ; 0xc0718 vberom.asm:353 + and AL, strict byte 0bdh ; 24 bd ; 0xc0719 vberom.asm:354 + test ah, 001h ; f6 c4 01 ; 0xc071b vberom.asm:355 + je short 00722h ; 74 02 ; 0xc071e vberom.asm:356 + or AL, strict byte 002h ; 0c 02 ; 0xc0720 vberom.asm:357 + test ah, 002h ; f6 c4 02 ; 0xc0722 vberom.asm:359 + je short 00729h ; 74 02 ; 0xc0725 vberom.asm:360 + or AL, strict byte 040h ; 0c 40 ; 0xc0727 vberom.asm:361 + out DX, AL ; ee ; 0xc0729 vberom.asm:363 + mov dx, 003d4h ; ba d4 03 ; 0xc072a vberom.asm:366 + mov ax, strict word 00009h ; b8 09 00 ; 0xc072d vberom.asm:367 + out DX, AL ; ee ; 0xc0730 vberom.asm:368 + mov dx, 003d5h ; ba d5 03 ; 0xc0731 vberom.asm:369 + in AL, DX ; ec ; 0xc0734 vberom.asm:370 + and AL, strict byte 060h ; 24 60 ; 0xc0735 vberom.asm:371 + out DX, AL ; ee ; 0xc0737 vberom.asm:372 + mov dx, 003d4h ; ba d4 03 ; 0xc0738 vberom.asm:373 + mov AL, strict byte 017h ; b0 17 ; 0xc073b vberom.asm:374 + out DX, AL ; ee ; 0xc073d vberom.asm:375 + mov dx, 003d5h ; ba d5 03 ; 0xc073e vberom.asm:376 + in AL, DX ; ec ; 0xc0741 vberom.asm:377 + or AL, strict byte 003h ; 0c 03 ; 0xc0742 vberom.asm:378 + out DX, AL ; ee ; 0xc0744 vberom.asm:379 + mov dx, 003dah ; ba da 03 ; 0xc0745 vberom.asm:380 + in AL, DX ; ec ; 0xc0748 vberom.asm:381 + mov dx, 003c0h ; ba c0 03 ; 0xc0749 vberom.asm:382 + mov AL, strict byte 010h ; b0 10 ; 0xc074c vberom.asm:383 + out DX, AL ; ee ; 0xc074e vberom.asm:384 + mov dx, 003c1h ; ba c1 03 ; 0xc074f vberom.asm:385 + in AL, DX ; ec ; 0xc0752 vberom.asm:386 + or AL, strict byte 001h ; 0c 01 ; 0xc0753 vberom.asm:387 + mov dx, 003c0h ; ba c0 03 ; 0xc0755 vberom.asm:388 + out DX, AL ; ee ; 0xc0758 vberom.asm:389 + mov AL, strict byte 020h ; b0 20 ; 0xc0759 vberom.asm:390 + out DX, AL ; ee ; 0xc075b vberom.asm:391 + mov dx, 003ceh ; ba ce 03 ; 0xc075c vberom.asm:392 + mov ax, 00506h ; b8 06 05 ; 0xc075f vberom.asm:393 + out DX, ax ; ef ; 0xc0762 vberom.asm:394 + mov dx, 003c4h ; ba c4 03 ; 0xc0763 vberom.asm:395 + mov ax, 00f02h ; b8 02 0f ; 0xc0766 vberom.asm:396 + out DX, ax ; ef ; 0xc0769 vberom.asm:397 + mov dx, 001ceh ; ba ce 01 ; 0xc076a vberom.asm:400 + mov ax, strict word 00003h ; b8 03 00 ; 0xc076d vberom.asm:401 + call 00570h ; e8 fd fd ; 0xc0770 vberom.asm:402 + mov dx, 001cfh ; ba cf 01 ; 0xc0773 vberom.asm:403 + call 00577h ; e8 fe fd ; 0xc0776 vberom.asm:404 + cmp AL, strict byte 008h ; 3c 08 ; 0xc0779 vberom.asm:405 + jc short 007bdh ; 72 40 ; 0xc077b vberom.asm:406 + mov dx, 003d4h ; ba d4 03 ; 0xc077d vberom.asm:407 + mov AL, strict byte 014h ; b0 14 ; 0xc0780 vberom.asm:408 + out DX, AL ; ee ; 0xc0782 vberom.asm:409 + mov dx, 003d5h ; ba d5 03 ; 0xc0783 vberom.asm:410 + in AL, DX ; ec ; 0xc0786 vberom.asm:411 + or AL, strict byte 040h ; 0c 40 ; 0xc0787 vberom.asm:412 + out DX, AL ; ee ; 0xc0789 vberom.asm:413 + mov dx, 003dah ; ba da 03 ; 0xc078a vberom.asm:414 + in AL, DX ; ec ; 0xc078d vberom.asm:415 + mov dx, 003c0h ; ba c0 03 ; 0xc078e vberom.asm:416 + mov AL, strict byte 010h ; b0 10 ; 0xc0791 vberom.asm:417 + out DX, AL ; ee ; 0xc0793 vberom.asm:418 + mov dx, 003c1h ; ba c1 03 ; 0xc0794 vberom.asm:419 + in AL, DX ; ec ; 0xc0797 vberom.asm:420 + or AL, strict byte 040h ; 0c 40 ; 0xc0798 vberom.asm:421 + mov dx, 003c0h ; ba c0 03 ; 0xc079a vberom.asm:422 + out DX, AL ; ee ; 0xc079d vberom.asm:423 + mov AL, strict byte 020h ; b0 20 ; 0xc079e vberom.asm:424 + out DX, AL ; ee ; 0xc07a0 vberom.asm:425 + mov dx, 003c4h ; ba c4 03 ; 0xc07a1 vberom.asm:426 + mov AL, strict byte 004h ; b0 04 ; 0xc07a4 vberom.asm:427 + out DX, AL ; ee ; 0xc07a6 vberom.asm:428 + mov dx, 003c5h ; ba c5 03 ; 0xc07a7 vberom.asm:429 + in AL, DX ; ec ; 0xc07aa vberom.asm:430 + or AL, strict byte 008h ; 0c 08 ; 0xc07ab vberom.asm:431 + out DX, AL ; ee ; 0xc07ad vberom.asm:432 + mov dx, 003ceh ; ba ce 03 ; 0xc07ae vberom.asm:433 + mov AL, strict byte 005h ; b0 05 ; 0xc07b1 vberom.asm:434 + out DX, AL ; ee ; 0xc07b3 vberom.asm:435 + mov dx, 003cfh ; ba cf 03 ; 0xc07b4 vberom.asm:436 + in AL, DX ; ec ; 0xc07b7 vberom.asm:437 + and AL, strict byte 09fh ; 24 9f ; 0xc07b8 vberom.asm:438 + or AL, strict byte 040h ; 0c 40 ; 0xc07ba vberom.asm:439 + out DX, AL ; ee ; 0xc07bc vberom.asm:440 + pop dx ; 5a ; 0xc07bd vberom.asm:443 + pop ax ; 58 ; 0xc07be vberom.asm:444 + ; disGetNextSymbol 0xc07bf LB 0x148 -> off=0x0 cb=0000000000000013 uValue=00000000000c07bf '_vbe_has_vbe_display' +_vbe_has_vbe_display: ; 0xc07bf LB 0x13 + push DS ; 1e ; 0xc07bf vberom.asm:450 + push bx ; 53 ; 0xc07c0 vberom.asm:451 + mov ax, strict word 00040h ; b8 40 00 ; 0xc07c1 vberom.asm:452 + mov ds, ax ; 8e d8 ; 0xc07c4 vberom.asm:453 + mov bx, 000b9h ; bb b9 00 ; 0xc07c6 vberom.asm:454 + mov al, byte [bx] ; 8a 07 ; 0xc07c9 vberom.asm:455 + and AL, strict byte 001h ; 24 01 ; 0xc07cb vberom.asm:456 + db 032h, 0e4h + ; xor ah, ah ; 32 e4 ; 0xc07cd vberom.asm:457 + pop bx ; 5b ; 0xc07cf vberom.asm:458 + pop DS ; 1f ; 0xc07d0 vberom.asm:459 + retn ; c3 ; 0xc07d1 vberom.asm:460 + ; disGetNextSymbol 0xc07d2 LB 0x135 -> off=0x0 cb=0000000000000025 uValue=00000000000c07d2 'vbe_biosfn_return_current_mode' +vbe_biosfn_return_current_mode: ; 0xc07d2 LB 0x25 + push DS ; 1e ; 0xc07d2 vberom.asm:473 + mov ax, strict word 00040h ; b8 40 00 ; 0xc07d3 vberom.asm:474 + mov ds, ax ; 8e d8 ; 0xc07d6 vberom.asm:475 + call 005f1h ; e8 16 fe ; 0xc07d8 vberom.asm:476 + and ax, strict byte 00001h ; 83 e0 01 ; 0xc07db vberom.asm:477 + je short 007e9h ; 74 09 ; 0xc07de vberom.asm:478 + mov bx, 000bah ; bb ba 00 ; 0xc07e0 vberom.asm:479 + mov ax, word [bx] ; 8b 07 ; 0xc07e3 vberom.asm:480 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc07e5 vberom.asm:481 + jne short 007f2h ; 75 09 ; 0xc07e7 vberom.asm:482 + mov bx, strict word 00049h ; bb 49 00 ; 0xc07e9 vberom.asm:484 + mov al, byte [bx] ; 8a 07 ; 0xc07ec vberom.asm:485 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc07ee vberom.asm:486 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc07f0 vberom.asm:487 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc07f2 vberom.asm:489 + pop DS ; 1f ; 0xc07f5 vberom.asm:490 + retn ; c3 ; 0xc07f6 vberom.asm:491 + ; disGetNextSymbol 0xc07f7 LB 0x110 -> off=0x0 cb=000000000000002d uValue=00000000000c07f7 'vbe_biosfn_display_window_control' +vbe_biosfn_display_window_control: ; 0xc07f7 LB 0x2d + cmp bl, 000h ; 80 fb 00 ; 0xc07f7 vberom.asm:515 + jne short 00820h ; 75 24 ; 0xc07fa vberom.asm:516 + cmp bh, 001h ; 80 ff 01 ; 0xc07fc vberom.asm:517 + je short 00817h ; 74 16 ; 0xc07ff vberom.asm:518 + jc short 00807h ; 72 04 ; 0xc0801 vberom.asm:519 + mov ax, 00100h ; b8 00 01 ; 0xc0803 vberom.asm:520 + retn ; c3 ; 0xc0806 vberom.asm:521 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc0807 vberom.asm:523 + call 00603h ; e8 f7 fd ; 0xc0809 vberom.asm:524 + call 00617h ; e8 08 fe ; 0xc080c vberom.asm:525 + db 03bh, 0c2h + ; cmp ax, dx ; 3b c2 ; 0xc080f vberom.asm:526 + jne short 00820h ; 75 0d ; 0xc0811 vberom.asm:527 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0813 vberom.asm:528 + retn ; c3 ; 0xc0816 vberom.asm:529 + call 00617h ; e8 fd fd ; 0xc0817 vberom.asm:531 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc081a vberom.asm:532 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc081c vberom.asm:533 + retn ; c3 ; 0xc081f vberom.asm:534 + mov ax, 0014fh ; b8 4f 01 ; 0xc0820 vberom.asm:536 + retn ; c3 ; 0xc0823 vberom.asm:537 + ; disGetNextSymbol 0xc0824 LB 0xe3 -> off=0x0 cb=0000000000000034 uValue=00000000000c0824 'vbe_biosfn_set_get_display_start' +vbe_biosfn_set_get_display_start: ; 0xc0824 LB 0x34 + cmp bl, 080h ; 80 fb 80 ; 0xc0824 vberom.asm:577 + je short 00834h ; 74 0b ; 0xc0827 vberom.asm:578 + cmp bl, 001h ; 80 fb 01 ; 0xc0829 vberom.asm:579 + je short 00848h ; 74 1a ; 0xc082c vberom.asm:580 + jc short 0083ah ; 72 0a ; 0xc082e vberom.asm:581 + mov ax, 00100h ; b8 00 01 ; 0xc0830 vberom.asm:582 + retn ; c3 ; 0xc0833 vberom.asm:583 + call 00589h ; e8 52 fd ; 0xc0834 vberom.asm:585 + call 0057ch ; e8 42 fd ; 0xc0837 vberom.asm:586 + db 08bh, 0c1h + ; mov ax, cx ; 8b c1 ; 0xc083a vberom.asm:588 + call 00669h ; e8 2a fe ; 0xc083c vberom.asm:589 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc083f vberom.asm:590 + call 0068fh ; e8 4b fe ; 0xc0841 vberom.asm:591 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0844 vberom.asm:592 + retn ; c3 ; 0xc0847 vberom.asm:593 + call 0067dh ; e8 32 fe ; 0xc0848 vberom.asm:595 + db 08bh, 0c8h + ; mov cx, ax ; 8b c8 ; 0xc084b vberom.asm:596 + call 006a3h ; e8 53 fe ; 0xc084d vberom.asm:597 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc0850 vberom.asm:598 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc0852 vberom.asm:599 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0854 vberom.asm:600 + retn ; c3 ; 0xc0857 vberom.asm:601 + ; disGetNextSymbol 0xc0858 LB 0xaf -> off=0x0 cb=0000000000000037 uValue=00000000000c0858 'vbe_biosfn_set_get_dac_palette_format' +vbe_biosfn_set_get_dac_palette_format: ; 0xc0858 LB 0x37 + cmp bl, 001h ; 80 fb 01 ; 0xc0858 vberom.asm:616 + je short 0087bh ; 74 1e ; 0xc085b vberom.asm:617 + jc short 00863h ; 72 04 ; 0xc085d vberom.asm:618 + mov ax, 00100h ; b8 00 01 ; 0xc085f vberom.asm:619 + retn ; c3 ; 0xc0862 vberom.asm:620 + call 005f1h ; e8 8b fd ; 0xc0863 vberom.asm:622 + cmp bh, 006h ; 80 ff 06 ; 0xc0866 vberom.asm:623 + je short 00875h ; 74 0a ; 0xc0869 vberom.asm:624 + cmp bh, 008h ; 80 ff 08 ; 0xc086b vberom.asm:625 + jne short 0088bh ; 75 1b ; 0xc086e vberom.asm:626 + or ax, strict byte 00020h ; 83 c8 20 ; 0xc0870 vberom.asm:627 + jne short 00878h ; 75 03 ; 0xc0873 vberom.asm:628 + and ax, strict byte 0ffdfh ; 83 e0 df ; 0xc0875 vberom.asm:630 + call 005ddh ; e8 62 fd ; 0xc0878 vberom.asm:632 + mov BH, strict byte 006h ; b7 06 ; 0xc087b vberom.asm:634 + call 005f1h ; e8 71 fd ; 0xc087d vberom.asm:635 + and ax, strict byte 00020h ; 83 e0 20 ; 0xc0880 vberom.asm:636 + je short 00887h ; 74 02 ; 0xc0883 vberom.asm:637 + mov BH, strict byte 008h ; b7 08 ; 0xc0885 vberom.asm:638 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0887 vberom.asm:640 + retn ; c3 ; 0xc088a vberom.asm:641 + mov ax, 0014fh ; b8 4f 01 ; 0xc088b vberom.asm:643 + retn ; c3 ; 0xc088e vberom.asm:644 + ; disGetNextSymbol 0xc088f LB 0x78 -> off=0x0 cb=0000000000000064 uValue=00000000000c088f 'vbe_biosfn_set_get_palette_data' +vbe_biosfn_set_get_palette_data: ; 0xc088f LB 0x64 + test bl, bl ; 84 db ; 0xc088f vberom.asm:683 + je short 008a2h ; 74 0f ; 0xc0891 vberom.asm:684 + cmp bl, 001h ; 80 fb 01 ; 0xc0893 vberom.asm:685 + je short 008cah ; 74 32 ; 0xc0896 vberom.asm:686 + cmp bl, 003h ; 80 fb 03 ; 0xc0898 vberom.asm:687 + jbe short 008efh ; 76 52 ; 0xc089b vberom.asm:688 + cmp bl, 080h ; 80 fb 80 ; 0xc089d vberom.asm:689 + jne short 008ebh ; 75 49 ; 0xc08a0 vberom.asm:690 + pushad ; 66 60 ; 0xc08a2 vberom.asm:141 + push DS ; 1e ; 0xc08a4 vberom.asm:696 + push ES ; 06 ; 0xc08a5 vberom.asm:697 + pop DS ; 1f ; 0xc08a6 vberom.asm:698 + db 08ah, 0c2h + ; mov al, dl ; 8a c2 ; 0xc08a7 vberom.asm:699 + mov dx, 003c8h ; ba c8 03 ; 0xc08a9 vberom.asm:700 + out DX, AL ; ee ; 0xc08ac vberom.asm:701 + inc dx ; 42 ; 0xc08ad vberom.asm:702 + db 08bh, 0f7h + ; mov si, di ; 8b f7 ; 0xc08ae vberom.asm:703 + lodsd ; 66 ad ; 0xc08b0 vberom.asm:706 + ror eax, 010h ; 66 c1 c8 10 ; 0xc08b2 vberom.asm:707 + out DX, AL ; ee ; 0xc08b6 vberom.asm:708 + rol eax, 008h ; 66 c1 c0 08 ; 0xc08b7 vberom.asm:709 + out DX, AL ; ee ; 0xc08bb vberom.asm:710 + rol eax, 008h ; 66 c1 c0 08 ; 0xc08bc vberom.asm:711 + out DX, AL ; ee ; 0xc08c0 vberom.asm:712 + loop 008b0h ; e2 ed ; 0xc08c1 vberom.asm:723 + pop DS ; 1f ; 0xc08c3 vberom.asm:724 + popad ; 66 61 ; 0xc08c4 vberom.asm:160 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc08c6 vberom.asm:727 + retn ; c3 ; 0xc08c9 vberom.asm:728 + pushad ; 66 60 ; 0xc08ca vberom.asm:141 + db 08ah, 0c2h + ; mov al, dl ; 8a c2 ; 0xc08cc vberom.asm:732 + mov dx, 003c7h ; ba c7 03 ; 0xc08ce vberom.asm:733 + out DX, AL ; ee ; 0xc08d1 vberom.asm:734 + add dl, 002h ; 80 c2 02 ; 0xc08d2 vberom.asm:735 + db 066h, 033h, 0c0h + ; xor eax, eax ; 66 33 c0 ; 0xc08d5 vberom.asm:738 + in AL, DX ; ec ; 0xc08d8 vberom.asm:739 + sal eax, 008h ; 66 c1 e0 08 ; 0xc08d9 vberom.asm:740 + in AL, DX ; ec ; 0xc08dd vberom.asm:741 + sal eax, 008h ; 66 c1 e0 08 ; 0xc08de vberom.asm:742 + in AL, DX ; ec ; 0xc08e2 vberom.asm:743 + stosd ; 66 ab ; 0xc08e3 vberom.asm:744 + loop 008d5h ; e2 ee ; 0xc08e5 vberom.asm:757 + popad ; 66 61 ; 0xc08e7 vberom.asm:160 + jmp short 008c6h ; eb db ; 0xc08e9 vberom.asm:759 + mov ax, 0014fh ; b8 4f 01 ; 0xc08eb vberom.asm:762 + retn ; c3 ; 0xc08ee vberom.asm:763 + mov ax, 0024fh ; b8 4f 02 ; 0xc08ef vberom.asm:765 + retn ; c3 ; 0xc08f2 vberom.asm:766 + ; disGetNextSymbol 0xc08f3 LB 0x14 -> off=0x0 cb=0000000000000014 uValue=00000000000c08f3 'vbe_biosfn_return_protected_mode_interface' +vbe_biosfn_return_protected_mode_interface: ; 0xc08f3 LB 0x14 + test bl, bl ; 84 db ; 0xc08f3 vberom.asm:780 + jne short 00903h ; 75 0c ; 0xc08f5 vberom.asm:781 + push CS ; 0e ; 0xc08f7 vberom.asm:782 + pop ES ; 07 ; 0xc08f8 vberom.asm:783 + mov di, 04640h ; bf 40 46 ; 0xc08f9 vberom.asm:784 + mov cx, 00115h ; b9 15 01 ; 0xc08fc vberom.asm:785 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc08ff vberom.asm:786 + retn ; c3 ; 0xc0902 vberom.asm:787 + mov ax, 0014fh ; b8 4f 01 ; 0xc0903 vberom.asm:789 + retn ; c3 ; 0xc0906 vberom.asm:790 + + ; Padding 0xe9 bytes at 0xc0907 + times 233 db 0 + +section _TEXT progbits vstart=0x9f0 align=1 ; size=0x38c9 class=CODE group=AUTO + ; disGetNextSymbol 0xc09f0 LB 0x38c9 -> off=0x0 cb=000000000000001a uValue=00000000000c09f0 'set_int_vector' +set_int_vector: ; 0xc09f0 LB 0x1a + push dx ; 52 ; 0xc09f0 vgabios.c:87 + push bp ; 55 ; 0xc09f1 + mov bp, sp ; 89 e5 ; 0xc09f2 + mov dx, bx ; 89 da ; 0xc09f4 + movzx bx, al ; 0f b6 d8 ; 0xc09f6 vgabios.c:91 + sal bx, 002h ; c1 e3 02 ; 0xc09f9 + xor ax, ax ; 31 c0 ; 0xc09fc + mov es, ax ; 8e c0 ; 0xc09fe + mov word [es:bx], dx ; 26 89 17 ; 0xc0a00 + mov word [es:bx+002h], cx ; 26 89 4f 02 ; 0xc0a03 + pop bp ; 5d ; 0xc0a07 vgabios.c:92 + pop dx ; 5a ; 0xc0a08 + retn ; c3 ; 0xc0a09 + ; disGetNextSymbol 0xc0a0a LB 0x38af -> off=0x0 cb=000000000000001c uValue=00000000000c0a0a 'init_vga_card' +init_vga_card: ; 0xc0a0a LB 0x1c + push bp ; 55 ; 0xc0a0a vgabios.c:143 + mov bp, sp ; 89 e5 ; 0xc0a0b + push dx ; 52 ; 0xc0a0d + mov AL, strict byte 0c3h ; b0 c3 ; 0xc0a0e vgabios.c:146 + mov dx, 003c2h ; ba c2 03 ; 0xc0a10 + out DX, AL ; ee ; 0xc0a13 + mov AL, strict byte 004h ; b0 04 ; 0xc0a14 vgabios.c:149 + mov dx, 003c4h ; ba c4 03 ; 0xc0a16 + out DX, AL ; ee ; 0xc0a19 + mov AL, strict byte 002h ; b0 02 ; 0xc0a1a vgabios.c:150 + mov dx, 003c5h ; ba c5 03 ; 0xc0a1c + out DX, AL ; ee ; 0xc0a1f + lea sp, [bp-002h] ; 8d 66 fe ; 0xc0a20 vgabios.c:155 + pop dx ; 5a ; 0xc0a23 + pop bp ; 5d ; 0xc0a24 + retn ; c3 ; 0xc0a25 + ; disGetNextSymbol 0xc0a26 LB 0x3893 -> off=0x0 cb=000000000000003e uValue=00000000000c0a26 'init_bios_area' +init_bios_area: ; 0xc0a26 LB 0x3e + push bx ; 53 ; 0xc0a26 vgabios.c:221 + push bp ; 55 ; 0xc0a27 + mov bp, sp ; 89 e5 ; 0xc0a28 + xor bx, bx ; 31 db ; 0xc0a2a vgabios.c:225 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0a2c + mov es, ax ; 8e c0 ; 0xc0a2f + mov al, byte [es:bx+010h] ; 26 8a 47 10 ; 0xc0a31 vgabios.c:228 + and AL, strict byte 0cfh ; 24 cf ; 0xc0a35 + or AL, strict byte 020h ; 0c 20 ; 0xc0a37 + mov byte [es:bx+010h], al ; 26 88 47 10 ; 0xc0a39 + mov byte [es:bx+00085h], 010h ; 26 c6 87 85 00 10 ; 0xc0a3d vgabios.c:232 + mov word [es:bx+00087h], 0f960h ; 26 c7 87 87 00 60 f9 ; 0xc0a43 vgabios.c:234 + mov byte [es:bx+00089h], 051h ; 26 c6 87 89 00 51 ; 0xc0a4a vgabios.c:238 + mov byte [es:bx+065h], 009h ; 26 c6 47 65 09 ; 0xc0a50 vgabios.c:240 + mov word [es:bx+000a8h], 05551h ; 26 c7 87 a8 00 51 55 ; 0xc0a55 vgabios.c:242 + mov [es:bx+000aah], ds ; 26 8c 9f aa 00 ; 0xc0a5c + pop bp ; 5d ; 0xc0a61 vgabios.c:243 + pop bx ; 5b ; 0xc0a62 + retn ; c3 ; 0xc0a63 + ; disGetNextSymbol 0xc0a64 LB 0x3855 -> off=0x0 cb=000000000000002f uValue=00000000000c0a64 'vgabios_init_func' +vgabios_init_func: ; 0xc0a64 LB 0x2f + push bp ; 55 ; 0xc0a64 vgabios.c:250 + mov bp, sp ; 89 e5 ; 0xc0a65 + call 00a0ah ; e8 a0 ff ; 0xc0a67 vgabios.c:252 + call 00a26h ; e8 b9 ff ; 0xc0a6a vgabios.c:253 + call 03c5ch ; e8 ec 31 ; 0xc0a6d vgabios.c:255 + mov bx, strict word 00028h ; bb 28 00 ; 0xc0a70 vgabios.c:257 + mov cx, 0c000h ; b9 00 c0 ; 0xc0a73 + mov ax, strict word 00010h ; b8 10 00 ; 0xc0a76 + call 009f0h ; e8 74 ff ; 0xc0a79 + mov bx, strict word 00028h ; bb 28 00 ; 0xc0a7c vgabios.c:258 + mov cx, 0c000h ; b9 00 c0 ; 0xc0a7f + mov ax, strict word 0006dh ; b8 6d 00 ; 0xc0a82 + call 009f0h ; e8 68 ff ; 0xc0a85 + mov ax, strict word 00003h ; b8 03 00 ; 0xc0a88 vgabios.c:284 + db 032h, 0e4h + ; xor ah, ah ; 32 e4 ; 0xc0a8b + int 010h ; cd 10 ; 0xc0a8d + mov sp, bp ; 89 ec ; 0xc0a8f vgabios.c:287 + pop bp ; 5d ; 0xc0a91 + retf ; cb ; 0xc0a92 + ; disGetNextSymbol 0xc0a93 LB 0x3826 -> off=0x0 cb=000000000000003f uValue=00000000000c0a93 'vga_get_cursor_pos' +vga_get_cursor_pos: ; 0xc0a93 LB 0x3f + push si ; 56 ; 0xc0a93 vgabios.c:356 + push di ; 57 ; 0xc0a94 + push bp ; 55 ; 0xc0a95 + mov bp, sp ; 89 e5 ; 0xc0a96 + mov si, dx ; 89 d6 ; 0xc0a98 + cmp AL, strict byte 007h ; 3c 07 ; 0xc0a9a vgabios.c:358 + jbe short 00aach ; 76 0e ; 0xc0a9c + push SS ; 16 ; 0xc0a9e vgabios.c:359 + pop ES ; 07 ; 0xc0a9f + mov word [es:si], strict word 00000h ; 26 c7 04 00 00 ; 0xc0aa0 + mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xc0aa5 vgabios.c:360 + jmp short 00aceh ; eb 22 ; 0xc0aaa vgabios.c:361 + mov di, strict word 00060h ; bf 60 00 ; 0xc0aac vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc0aaf + mov es, dx ; 8e c2 ; 0xc0ab2 + mov di, word [es:di] ; 26 8b 3d ; 0xc0ab4 + push SS ; 16 ; 0xc0ab7 vgabios.c:58 + pop ES ; 07 ; 0xc0ab8 + mov word [es:si], di ; 26 89 3c ; 0xc0ab9 + movzx si, al ; 0f b6 f0 ; 0xc0abc vgabios.c:364 + add si, si ; 01 f6 ; 0xc0abf + add si, strict byte 00050h ; 83 c6 50 ; 0xc0ac1 + mov es, dx ; 8e c2 ; 0xc0ac4 vgabios.c:57 + mov si, word [es:si] ; 26 8b 34 ; 0xc0ac6 + push SS ; 16 ; 0xc0ac9 vgabios.c:58 + pop ES ; 07 ; 0xc0aca + mov word [es:bx], si ; 26 89 37 ; 0xc0acb + pop bp ; 5d ; 0xc0ace vgabios.c:366 + pop di ; 5f ; 0xc0acf + pop si ; 5e ; 0xc0ad0 + retn ; c3 ; 0xc0ad1 + ; disGetNextSymbol 0xc0ad2 LB 0x37e7 -> off=0x0 cb=000000000000005d uValue=00000000000c0ad2 'vga_find_glyph' +vga_find_glyph: ; 0xc0ad2 LB 0x5d + push bp ; 55 ; 0xc0ad2 vgabios.c:369 + mov bp, sp ; 89 e5 ; 0xc0ad3 + push si ; 56 ; 0xc0ad5 + push di ; 57 ; 0xc0ad6 + push ax ; 50 ; 0xc0ad7 + push ax ; 50 ; 0xc0ad8 + push dx ; 52 ; 0xc0ad9 + push bx ; 53 ; 0xc0ada + mov bl, cl ; 88 cb ; 0xc0adb + mov word [bp-006h], strict word 00000h ; c7 46 fa 00 00 ; 0xc0add vgabios.c:371 + dec word [bp+004h] ; ff 4e 04 ; 0xc0ae2 vgabios.c:373 + cmp word [bp+004h], strict byte 0ffffh ; 83 7e 04 ff ; 0xc0ae5 + je short 00b23h ; 74 38 ; 0xc0ae9 + movzx cx, byte [bp+006h] ; 0f b6 4e 06 ; 0xc0aeb vgabios.c:374 + mov dx, ss ; 8c d2 ; 0xc0aef + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc0af1 + mov di, word [bp-008h] ; 8b 7e f8 ; 0xc0af4 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc0af7 + push DS ; 1e ; 0xc0afa + mov ds, dx ; 8e da ; 0xc0afb + rep cmpsb ; f3 a6 ; 0xc0afd + pop DS ; 1f ; 0xc0aff + mov ax, strict word 00000h ; b8 00 00 ; 0xc0b00 + je near 00b09h ; 0f 84 02 00 ; 0xc0b03 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc0b07 + test ax, ax ; 85 c0 ; 0xc0b09 + jne short 00b18h ; 75 0b ; 0xc0b0b + movzx ax, bl ; 0f b6 c3 ; 0xc0b0d vgabios.c:375 + or ah, 080h ; 80 cc 80 ; 0xc0b10 + mov word [bp-006h], ax ; 89 46 fa ; 0xc0b13 + jmp short 00b23h ; eb 0b ; 0xc0b16 vgabios.c:376 + movzx ax, byte [bp+006h] ; 0f b6 46 06 ; 0xc0b18 vgabios.c:378 + add word [bp-008h], ax ; 01 46 f8 ; 0xc0b1c + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc0b1f vgabios.c:379 + jmp short 00ae2h ; eb bf ; 0xc0b21 vgabios.c:380 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc0b23 vgabios.c:382 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0b26 + pop di ; 5f ; 0xc0b29 + pop si ; 5e ; 0xc0b2a + pop bp ; 5d ; 0xc0b2b + retn 00004h ; c2 04 00 ; 0xc0b2c + ; disGetNextSymbol 0xc0b2f LB 0x378a -> off=0x0 cb=0000000000000046 uValue=00000000000c0b2f 'vga_read_glyph_planar' +vga_read_glyph_planar: ; 0xc0b2f LB 0x46 + push bp ; 55 ; 0xc0b2f vgabios.c:384 + mov bp, sp ; 89 e5 ; 0xc0b30 + push si ; 56 ; 0xc0b32 + push di ; 57 ; 0xc0b33 + push ax ; 50 ; 0xc0b34 + push ax ; 50 ; 0xc0b35 + mov si, ax ; 89 c6 ; 0xc0b36 + mov word [bp-006h], dx ; 89 56 fa ; 0xc0b38 + mov word [bp-008h], bx ; 89 5e f8 ; 0xc0b3b + mov bx, cx ; 89 cb ; 0xc0b3e + mov ax, 00805h ; b8 05 08 ; 0xc0b40 vgabios.c:391 + mov dx, 003ceh ; ba ce 03 ; 0xc0b43 + out DX, ax ; ef ; 0xc0b46 + dec byte [bp+004h] ; fe 4e 04 ; 0xc0b47 vgabios.c:393 + cmp byte [bp+004h], 0ffh ; 80 7e 04 ff ; 0xc0b4a + je short 00b65h ; 74 15 ; 0xc0b4e + mov es, [bp-006h] ; 8e 46 fa ; 0xc0b50 vgabios.c:394 + mov al, byte [es:si] ; 26 8a 04 ; 0xc0b53 + not al ; f6 d0 ; 0xc0b56 + mov di, bx ; 89 df ; 0xc0b58 + inc bx ; 43 ; 0xc0b5a + push SS ; 16 ; 0xc0b5b + pop ES ; 07 ; 0xc0b5c + mov byte [es:di], al ; 26 88 05 ; 0xc0b5d + add si, word [bp-008h] ; 03 76 f8 ; 0xc0b60 vgabios.c:395 + jmp short 00b47h ; eb e2 ; 0xc0b63 vgabios.c:396 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0b65 vgabios.c:399 + mov dx, 003ceh ; ba ce 03 ; 0xc0b68 + out DX, ax ; ef ; 0xc0b6b + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0b6c vgabios.c:400 + pop di ; 5f ; 0xc0b6f + pop si ; 5e ; 0xc0b70 + pop bp ; 5d ; 0xc0b71 + retn 00002h ; c2 02 00 ; 0xc0b72 + ; disGetNextSymbol 0xc0b75 LB 0x3744 -> off=0x0 cb=000000000000002a uValue=00000000000c0b75 'vga_char_ofs_planar' +vga_char_ofs_planar: ; 0xc0b75 LB 0x2a + push bp ; 55 ; 0xc0b75 vgabios.c:402 + mov bp, sp ; 89 e5 ; 0xc0b76 + xor dh, dh ; 30 f6 ; 0xc0b78 vgabios.c:406 + imul bx, dx ; 0f af da ; 0xc0b7a + movzx dx, byte [bp+004h] ; 0f b6 56 04 ; 0xc0b7d + imul bx, dx ; 0f af da ; 0xc0b81 + xor ah, ah ; 30 e4 ; 0xc0b84 + add ax, bx ; 01 d8 ; 0xc0b86 + mov bx, strict word 0004ch ; bb 4c 00 ; 0xc0b88 vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc0b8b + mov es, dx ; 8e c2 ; 0xc0b8e + mov dx, word [es:bx] ; 26 8b 17 ; 0xc0b90 + movzx bx, cl ; 0f b6 d9 ; 0xc0b93 vgabios.c:58 + imul dx, bx ; 0f af d3 ; 0xc0b96 + add ax, dx ; 01 d0 ; 0xc0b99 + pop bp ; 5d ; 0xc0b9b vgabios.c:410 + retn 00002h ; c2 02 00 ; 0xc0b9c + ; disGetNextSymbol 0xc0b9f LB 0x371a -> off=0x0 cb=000000000000003e uValue=00000000000c0b9f 'vga_read_char_planar' +vga_read_char_planar: ; 0xc0b9f LB 0x3e + push bp ; 55 ; 0xc0b9f vgabios.c:412 + mov bp, sp ; 89 e5 ; 0xc0ba0 + push cx ; 51 ; 0xc0ba2 + push si ; 56 ; 0xc0ba3 + push di ; 57 ; 0xc0ba4 + sub sp, strict byte 00010h ; 83 ec 10 ; 0xc0ba5 + mov si, ax ; 89 c6 ; 0xc0ba8 + mov ax, dx ; 89 d0 ; 0xc0baa + movzx di, bl ; 0f b6 fb ; 0xc0bac vgabios.c:416 + push di ; 57 ; 0xc0baf + lea cx, [bp-016h] ; 8d 4e ea ; 0xc0bb0 + mov bx, si ; 89 f3 ; 0xc0bb3 + mov dx, 0a000h ; ba 00 a0 ; 0xc0bb5 + call 00b2fh ; e8 74 ff ; 0xc0bb8 + push di ; 57 ; 0xc0bbb vgabios.c:419 + push 00100h ; 68 00 01 ; 0xc0bbc + mov bx, 0010ch ; bb 0c 01 ; 0xc0bbf vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0bc2 + mov es, ax ; 8e c0 ; 0xc0bc4 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0bc6 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0bc9 + xor cx, cx ; 31 c9 ; 0xc0bcd vgabios.c:68 + lea bx, [bp-016h] ; 8d 5e ea ; 0xc0bcf + call 00ad2h ; e8 fd fe ; 0xc0bd2 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc0bd5 vgabios.c:420 + pop di ; 5f ; 0xc0bd8 + pop si ; 5e ; 0xc0bd9 + pop cx ; 59 ; 0xc0bda + pop bp ; 5d ; 0xc0bdb + retn ; c3 ; 0xc0bdc + ; disGetNextSymbol 0xc0bdd LB 0x36dc -> off=0x0 cb=000000000000001a uValue=00000000000c0bdd 'vga_char_ofs_linear' +vga_char_ofs_linear: ; 0xc0bdd LB 0x1a + push bp ; 55 ; 0xc0bdd vgabios.c:422 + mov bp, sp ; 89 e5 ; 0xc0bde + xor dh, dh ; 30 f6 ; 0xc0be0 vgabios.c:426 + imul dx, bx ; 0f af d3 ; 0xc0be2 + movzx bx, byte [bp+004h] ; 0f b6 5e 04 ; 0xc0be5 + imul bx, dx ; 0f af da ; 0xc0be9 + xor ah, ah ; 30 e4 ; 0xc0bec + add ax, bx ; 01 d8 ; 0xc0bee + sal ax, 003h ; c1 e0 03 ; 0xc0bf0 vgabios.c:427 + pop bp ; 5d ; 0xc0bf3 vgabios.c:429 + retn 00002h ; c2 02 00 ; 0xc0bf4 + ; disGetNextSymbol 0xc0bf7 LB 0x36c2 -> off=0x0 cb=000000000000004b uValue=00000000000c0bf7 'vga_read_glyph_linear' +vga_read_glyph_linear: ; 0xc0bf7 LB 0x4b + push si ; 56 ; 0xc0bf7 vgabios.c:431 + push di ; 57 ; 0xc0bf8 + enter 00004h, 000h ; c8 04 00 00 ; 0xc0bf9 + mov si, ax ; 89 c6 ; 0xc0bfd + mov word [bp-002h], dx ; 89 56 fe ; 0xc0bff + mov word [bp-004h], bx ; 89 5e fc ; 0xc0c02 + mov bx, cx ; 89 cb ; 0xc0c05 + dec byte [bp+008h] ; fe 4e 08 ; 0xc0c07 vgabios.c:437 + cmp byte [bp+008h], 0ffh ; 80 7e 08 ff ; 0xc0c0a + je short 00c3ch ; 74 2c ; 0xc0c0e + xor dh, dh ; 30 f6 ; 0xc0c10 vgabios.c:438 + mov DL, strict byte 080h ; b2 80 ; 0xc0c12 vgabios.c:439 + xor ax, ax ; 31 c0 ; 0xc0c14 vgabios.c:440 + jmp short 00c1dh ; eb 05 ; 0xc0c16 + cmp ax, strict word 00008h ; 3d 08 00 ; 0xc0c18 + jnl short 00c31h ; 7d 14 ; 0xc0c1b + mov es, [bp-002h] ; 8e 46 fe ; 0xc0c1d vgabios.c:441 + mov di, si ; 89 f7 ; 0xc0c20 + add di, ax ; 01 c7 ; 0xc0c22 + cmp byte [es:di], 000h ; 26 80 3d 00 ; 0xc0c24 + je short 00c2ch ; 74 02 ; 0xc0c28 + or dh, dl ; 08 d6 ; 0xc0c2a vgabios.c:442 + shr dl, 1 ; d0 ea ; 0xc0c2c vgabios.c:443 + inc ax ; 40 ; 0xc0c2e vgabios.c:444 + jmp short 00c18h ; eb e7 ; 0xc0c2f + mov di, bx ; 89 df ; 0xc0c31 vgabios.c:445 + inc bx ; 43 ; 0xc0c33 + mov byte [ss:di], dh ; 36 88 35 ; 0xc0c34 + add si, word [bp-004h] ; 03 76 fc ; 0xc0c37 vgabios.c:446 + jmp short 00c07h ; eb cb ; 0xc0c3a vgabios.c:447 + leave ; c9 ; 0xc0c3c vgabios.c:448 + pop di ; 5f ; 0xc0c3d + pop si ; 5e ; 0xc0c3e + retn 00002h ; c2 02 00 ; 0xc0c3f + ; disGetNextSymbol 0xc0c42 LB 0x3677 -> off=0x0 cb=000000000000003f uValue=00000000000c0c42 'vga_read_char_linear' +vga_read_char_linear: ; 0xc0c42 LB 0x3f + push bp ; 55 ; 0xc0c42 vgabios.c:450 + mov bp, sp ; 89 e5 ; 0xc0c43 + push cx ; 51 ; 0xc0c45 + push si ; 56 ; 0xc0c46 + sub sp, strict byte 00010h ; 83 ec 10 ; 0xc0c47 + mov cx, ax ; 89 c1 ; 0xc0c4a + mov ax, dx ; 89 d0 ; 0xc0c4c + movzx si, bl ; 0f b6 f3 ; 0xc0c4e vgabios.c:454 + push si ; 56 ; 0xc0c51 + mov bx, cx ; 89 cb ; 0xc0c52 + sal bx, 003h ; c1 e3 03 ; 0xc0c54 + lea cx, [bp-014h] ; 8d 4e ec ; 0xc0c57 + mov dx, 0a000h ; ba 00 a0 ; 0xc0c5a + call 00bf7h ; e8 97 ff ; 0xc0c5d + push si ; 56 ; 0xc0c60 vgabios.c:457 + push 00100h ; 68 00 01 ; 0xc0c61 + mov bx, 0010ch ; bb 0c 01 ; 0xc0c64 vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0c67 + mov es, ax ; 8e c0 ; 0xc0c69 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0c6b + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0c6e + xor cx, cx ; 31 c9 ; 0xc0c72 vgabios.c:68 + lea bx, [bp-014h] ; 8d 5e ec ; 0xc0c74 + call 00ad2h ; e8 58 fe ; 0xc0c77 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0c7a vgabios.c:458 + pop si ; 5e ; 0xc0c7d + pop cx ; 59 ; 0xc0c7e + pop bp ; 5d ; 0xc0c7f + retn ; c3 ; 0xc0c80 + ; disGetNextSymbol 0xc0c81 LB 0x3638 -> off=0x0 cb=0000000000000035 uValue=00000000000c0c81 'vga_read_2bpp_char' +vga_read_2bpp_char: ; 0xc0c81 LB 0x35 + push bp ; 55 ; 0xc0c81 vgabios.c:460 + mov bp, sp ; 89 e5 ; 0xc0c82 + push bx ; 53 ; 0xc0c84 + push cx ; 51 ; 0xc0c85 + mov bx, ax ; 89 c3 ; 0xc0c86 + mov es, dx ; 8e c2 ; 0xc0c88 + mov cx, 0c000h ; b9 00 c0 ; 0xc0c8a vgabios.c:466 + mov DH, strict byte 080h ; b6 80 ; 0xc0c8d vgabios.c:467 + xor dl, dl ; 30 d2 ; 0xc0c8f vgabios.c:468 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0c91 vgabios.c:469 + xchg ah, al ; 86 c4 ; 0xc0c94 + xor bx, bx ; 31 db ; 0xc0c96 vgabios.c:471 + jmp short 00c9fh ; eb 05 ; 0xc0c98 + cmp bx, strict byte 00008h ; 83 fb 08 ; 0xc0c9a + jnl short 00cadh ; 7d 0e ; 0xc0c9d + test ax, cx ; 85 c8 ; 0xc0c9f vgabios.c:472 + je short 00ca5h ; 74 02 ; 0xc0ca1 + or dl, dh ; 08 f2 ; 0xc0ca3 vgabios.c:473 + shr dh, 1 ; d0 ee ; 0xc0ca5 vgabios.c:474 + shr cx, 002h ; c1 e9 02 ; 0xc0ca7 vgabios.c:475 + inc bx ; 43 ; 0xc0caa vgabios.c:476 + jmp short 00c9ah ; eb ed ; 0xc0cab + mov al, dl ; 88 d0 ; 0xc0cad vgabios.c:478 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0caf + pop cx ; 59 ; 0xc0cb2 + pop bx ; 5b ; 0xc0cb3 + pop bp ; 5d ; 0xc0cb4 + retn ; c3 ; 0xc0cb5 + ; disGetNextSymbol 0xc0cb6 LB 0x3603 -> off=0x0 cb=0000000000000084 uValue=00000000000c0cb6 'vga_read_glyph_cga' +vga_read_glyph_cga: ; 0xc0cb6 LB 0x84 + push bp ; 55 ; 0xc0cb6 vgabios.c:480 + mov bp, sp ; 89 e5 ; 0xc0cb7 + push cx ; 51 ; 0xc0cb9 + push si ; 56 ; 0xc0cba + push di ; 57 ; 0xc0cbb + push ax ; 50 ; 0xc0cbc + mov si, dx ; 89 d6 ; 0xc0cbd + cmp bl, 006h ; 80 fb 06 ; 0xc0cbf vgabios.c:488 + je short 00cfeh ; 74 3a ; 0xc0cc2 + mov bx, ax ; 89 c3 ; 0xc0cc4 vgabios.c:490 + add bx, ax ; 01 c3 ; 0xc0cc6 + mov word [bp-008h], 0b800h ; c7 46 f8 00 b8 ; 0xc0cc8 + xor cx, cx ; 31 c9 ; 0xc0ccd vgabios.c:492 + jmp short 00cd6h ; eb 05 ; 0xc0ccf + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc0cd1 + jnl short 00d32h ; 7d 5c ; 0xc0cd4 + mov ax, bx ; 89 d8 ; 0xc0cd6 vgabios.c:493 + mov dx, word [bp-008h] ; 8b 56 f8 ; 0xc0cd8 + call 00c81h ; e8 a3 ff ; 0xc0cdb + mov di, si ; 89 f7 ; 0xc0cde + inc si ; 46 ; 0xc0ce0 + push SS ; 16 ; 0xc0ce1 + pop ES ; 07 ; 0xc0ce2 + mov byte [es:di], al ; 26 88 05 ; 0xc0ce3 + lea ax, [bx+02000h] ; 8d 87 00 20 ; 0xc0ce6 vgabios.c:494 + mov dx, word [bp-008h] ; 8b 56 f8 ; 0xc0cea + call 00c81h ; e8 91 ff ; 0xc0ced + mov di, si ; 89 f7 ; 0xc0cf0 + inc si ; 46 ; 0xc0cf2 + push SS ; 16 ; 0xc0cf3 + pop ES ; 07 ; 0xc0cf4 + mov byte [es:di], al ; 26 88 05 ; 0xc0cf5 + add bx, strict byte 00050h ; 83 c3 50 ; 0xc0cf8 vgabios.c:495 + inc cx ; 41 ; 0xc0cfb vgabios.c:496 + jmp short 00cd1h ; eb d3 ; 0xc0cfc + mov bx, ax ; 89 c3 ; 0xc0cfe vgabios.c:498 + mov word [bp-008h], 0b800h ; c7 46 f8 00 b8 ; 0xc0d00 + xor cx, cx ; 31 c9 ; 0xc0d05 vgabios.c:499 + jmp short 00d0eh ; eb 05 ; 0xc0d07 + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc0d09 + jnl short 00d32h ; 7d 24 ; 0xc0d0c + mov di, si ; 89 f7 ; 0xc0d0e vgabios.c:500 + inc si ; 46 ; 0xc0d10 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc0d11 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0d14 + push SS ; 16 ; 0xc0d17 + pop ES ; 07 ; 0xc0d18 + mov byte [es:di], al ; 26 88 05 ; 0xc0d19 + mov di, si ; 89 f7 ; 0xc0d1c vgabios.c:501 + inc si ; 46 ; 0xc0d1e + mov es, [bp-008h] ; 8e 46 f8 ; 0xc0d1f + mov al, byte [es:bx+02000h] ; 26 8a 87 00 20 ; 0xc0d22 + push SS ; 16 ; 0xc0d27 + pop ES ; 07 ; 0xc0d28 + mov byte [es:di], al ; 26 88 05 ; 0xc0d29 + add bx, strict byte 00050h ; 83 c3 50 ; 0xc0d2c vgabios.c:502 + inc cx ; 41 ; 0xc0d2f vgabios.c:503 + jmp short 00d09h ; eb d7 ; 0xc0d30 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc0d32 vgabios.c:505 + pop di ; 5f ; 0xc0d35 + pop si ; 5e ; 0xc0d36 + pop cx ; 59 ; 0xc0d37 + pop bp ; 5d ; 0xc0d38 + retn ; c3 ; 0xc0d39 + ; disGetNextSymbol 0xc0d3a LB 0x357f -> off=0x0 cb=0000000000000011 uValue=00000000000c0d3a 'vga_char_ofs_cga' +vga_char_ofs_cga: ; 0xc0d3a LB 0x11 + push bp ; 55 ; 0xc0d3a vgabios.c:507 + mov bp, sp ; 89 e5 ; 0xc0d3b + xor dh, dh ; 30 f6 ; 0xc0d3d vgabios.c:512 + imul dx, bx ; 0f af d3 ; 0xc0d3f + sal dx, 002h ; c1 e2 02 ; 0xc0d42 + xor ah, ah ; 30 e4 ; 0xc0d45 + add ax, dx ; 01 d0 ; 0xc0d47 + pop bp ; 5d ; 0xc0d49 vgabios.c:513 + retn ; c3 ; 0xc0d4a + ; disGetNextSymbol 0xc0d4b LB 0x356e -> off=0x0 cb=0000000000000065 uValue=00000000000c0d4b 'vga_read_char_cga' +vga_read_char_cga: ; 0xc0d4b LB 0x65 + push bp ; 55 ; 0xc0d4b vgabios.c:515 + mov bp, sp ; 89 e5 ; 0xc0d4c + push bx ; 53 ; 0xc0d4e + push cx ; 51 ; 0xc0d4f + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc0d50 + movzx bx, dl ; 0f b6 da ; 0xc0d53 vgabios.c:521 + lea dx, [bp-00eh] ; 8d 56 f2 ; 0xc0d56 + call 00cb6h ; e8 5a ff ; 0xc0d59 + push strict byte 00008h ; 6a 08 ; 0xc0d5c vgabios.c:524 + push 00080h ; 68 80 00 ; 0xc0d5e + mov bx, 0010ch ; bb 0c 01 ; 0xc0d61 vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0d64 + mov es, ax ; 8e c0 ; 0xc0d66 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0d68 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0d6b + xor cx, cx ; 31 c9 ; 0xc0d6f vgabios.c:68 + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc0d71 + call 00ad2h ; e8 5b fd ; 0xc0d74 + mov word [bp-006h], ax ; 89 46 fa ; 0xc0d77 + test ah, 080h ; f6 c4 80 ; 0xc0d7a vgabios.c:526 + jne short 00da6h ; 75 27 ; 0xc0d7d + mov bx, strict word 0007ch ; bb 7c 00 ; 0xc0d7f vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0d82 + mov es, ax ; 8e c0 ; 0xc0d84 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0d86 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0d89 + test dx, dx ; 85 d2 ; 0xc0d8d vgabios.c:530 + jne short 00d95h ; 75 04 ; 0xc0d8f + test ax, ax ; 85 c0 ; 0xc0d91 + je short 00da6h ; 74 11 ; 0xc0d93 + push strict byte 00008h ; 6a 08 ; 0xc0d95 vgabios.c:531 + push 00080h ; 68 80 00 ; 0xc0d97 + mov cx, 00080h ; b9 80 00 ; 0xc0d9a + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc0d9d + call 00ad2h ; e8 2f fd ; 0xc0da0 + mov word [bp-006h], ax ; 89 46 fa ; 0xc0da3 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc0da6 vgabios.c:534 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0da9 + pop cx ; 59 ; 0xc0dac + pop bx ; 5b ; 0xc0dad + pop bp ; 5d ; 0xc0dae + retn ; c3 ; 0xc0daf + ; disGetNextSymbol 0xc0db0 LB 0x3509 -> off=0x0 cb=0000000000000127 uValue=00000000000c0db0 'vga_read_char_attr' +vga_read_char_attr: ; 0xc0db0 LB 0x127 + push bp ; 55 ; 0xc0db0 vgabios.c:536 + mov bp, sp ; 89 e5 ; 0xc0db1 + push bx ; 53 ; 0xc0db3 + push cx ; 51 ; 0xc0db4 + push si ; 56 ; 0xc0db5 + push di ; 57 ; 0xc0db6 + sub sp, strict byte 00012h ; 83 ec 12 ; 0xc0db7 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc0dba + mov si, dx ; 89 d6 ; 0xc0dbd + mov bx, strict word 00049h ; bb 49 00 ; 0xc0dbf vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0dc2 + mov es, ax ; 8e c0 ; 0xc0dc5 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0dc7 + mov byte [bp-010h], al ; 88 46 f0 ; 0xc0dca vgabios.c:48 + xor ah, ah ; 30 e4 ; 0xc0dcd vgabios.c:544 + call 035edh ; e8 1b 28 ; 0xc0dcf + mov byte [bp-012h], al ; 88 46 ee ; 0xc0dd2 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc0dd5 vgabios.c:545 + je near 00eceh ; 0f 84 f3 00 ; 0xc0dd7 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc0ddb vgabios.c:549 + lea bx, [bp-018h] ; 8d 5e e8 ; 0xc0ddf + lea dx, [bp-01ah] ; 8d 56 e6 ; 0xc0de2 + mov ax, cx ; 89 c8 ; 0xc0de5 + call 00a93h ; e8 a9 fc ; 0xc0de7 + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc0dea vgabios.c:550 + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc0ded + mov ax, word [bp-018h] ; 8b 46 e8 ; 0xc0df0 vgabios.c:551 + xor al, al ; 30 c0 ; 0xc0df3 + shr ax, 008h ; c1 e8 08 ; 0xc0df5 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc0df8 + mov bx, 00084h ; bb 84 00 ; 0xc0dfb vgabios.c:47 + mov dx, strict word 00040h ; ba 40 00 ; 0xc0dfe + mov es, dx ; 8e c2 ; 0xc0e01 + mov dl, byte [es:bx] ; 26 8a 17 ; 0xc0e03 + xor dh, dh ; 30 f6 ; 0xc0e06 vgabios.c:48 + inc dx ; 42 ; 0xc0e08 + mov di, strict word 0004ah ; bf 4a 00 ; 0xc0e09 vgabios.c:57 + mov di, word [es:di] ; 26 8b 3d ; 0xc0e0c + mov word [bp-014h], di ; 89 7e ec ; 0xc0e0f vgabios.c:58 + movzx bx, byte [bp-012h] ; 0f b6 5e ee ; 0xc0e12 vgabios.c:557 + sal bx, 003h ; c1 e3 03 ; 0xc0e16 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc0e19 + jne short 00e56h ; 75 36 ; 0xc0e1e + imul dx, di ; 0f af d7 ; 0xc0e20 vgabios.c:559 + add dx, dx ; 01 d2 ; 0xc0e23 + or dl, 0ffh ; 80 ca ff ; 0xc0e25 + mov word [bp-016h], dx ; 89 56 ea ; 0xc0e28 + movzx dx, byte [bp-00ah] ; 0f b6 56 f6 ; 0xc0e2b + mov cx, word [bp-016h] ; 8b 4e ea ; 0xc0e2f + inc cx ; 41 ; 0xc0e32 + imul dx, cx ; 0f af d1 ; 0xc0e33 + xor ah, ah ; 30 e4 ; 0xc0e36 + imul di, ax ; 0f af f8 ; 0xc0e38 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc0e3b + add ax, di ; 01 f8 ; 0xc0e3f + add ax, ax ; 01 c0 ; 0xc0e41 + mov di, dx ; 89 d7 ; 0xc0e43 + add di, ax ; 01 c7 ; 0xc0e45 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc0e47 vgabios.c:55 + mov ax, word [es:di] ; 26 8b 05 ; 0xc0e4b + push SS ; 16 ; 0xc0e4e vgabios.c:58 + pop ES ; 07 ; 0xc0e4f + mov word [es:si], ax ; 26 89 04 ; 0xc0e50 + jmp near 00eceh ; e9 78 00 ; 0xc0e53 vgabios.c:561 + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc0e56 vgabios.c:562 + cmp bl, 005h ; 80 fb 05 ; 0xc0e5a + je short 00eaah ; 74 4b ; 0xc0e5d + cmp bl, 002h ; 80 fb 02 ; 0xc0e5f + jc short 00eceh ; 72 6a ; 0xc0e62 + jbe short 00e6dh ; 76 07 ; 0xc0e64 + cmp bl, 004h ; 80 fb 04 ; 0xc0e66 + jbe short 00e86h ; 76 1b ; 0xc0e69 + jmp short 00eceh ; eb 61 ; 0xc0e6b + movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xc0e6d vgabios.c:565 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc0e71 + mov bx, word [bp-014h] ; 8b 5e ec ; 0xc0e75 + call 00d3ah ; e8 bf fe ; 0xc0e78 + movzx dx, byte [bp-010h] ; 0f b6 56 f0 ; 0xc0e7b vgabios.c:566 + call 00d4bh ; e8 c9 fe ; 0xc0e7f + xor ah, ah ; 30 e4 ; 0xc0e82 + jmp short 00e4eh ; eb c8 ; 0xc0e84 + mov bx, 00085h ; bb 85 00 ; 0xc0e86 vgabios.c:57 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc0e89 + xor dh, dh ; 30 f6 ; 0xc0e8c vgabios.c:571 + mov word [bp-016h], dx ; 89 56 ea ; 0xc0e8e + push dx ; 52 ; 0xc0e91 + movzx dx, al ; 0f b6 d0 ; 0xc0e92 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc0e95 + mov bx, di ; 89 fb ; 0xc0e99 + call 00b75h ; e8 d7 fc ; 0xc0e9b + mov bx, word [bp-016h] ; 8b 5e ea ; 0xc0e9e vgabios.c:572 + mov dx, ax ; 89 c2 ; 0xc0ea1 + mov ax, di ; 89 f8 ; 0xc0ea3 + call 00b9fh ; e8 f7 fc ; 0xc0ea5 + jmp short 00e82h ; eb d8 ; 0xc0ea8 + mov bx, 00085h ; bb 85 00 ; 0xc0eaa vgabios.c:57 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc0ead + xor dh, dh ; 30 f6 ; 0xc0eb0 vgabios.c:576 + mov word [bp-016h], dx ; 89 56 ea ; 0xc0eb2 + push dx ; 52 ; 0xc0eb5 + movzx dx, al ; 0f b6 d0 ; 0xc0eb6 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc0eb9 + mov bx, di ; 89 fb ; 0xc0ebd + call 00bddh ; e8 1b fd ; 0xc0ebf + mov bx, word [bp-016h] ; 8b 5e ea ; 0xc0ec2 vgabios.c:577 + mov dx, ax ; 89 c2 ; 0xc0ec5 + mov ax, di ; 89 f8 ; 0xc0ec7 + call 00c42h ; e8 76 fd ; 0xc0ec9 + jmp short 00e82h ; eb b4 ; 0xc0ecc + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc0ece vgabios.c:586 + pop di ; 5f ; 0xc0ed1 + pop si ; 5e ; 0xc0ed2 + pop cx ; 59 ; 0xc0ed3 + pop bx ; 5b ; 0xc0ed4 + pop bp ; 5d ; 0xc0ed5 + retn ; c3 ; 0xc0ed6 + ; disGetNextSymbol 0xc0ed7 LB 0x33e2 -> off=0x10 cb=0000000000000083 uValue=00000000000c0ee7 'vga_get_font_info' + db 0feh, 00eh, 043h, 00fh, 048h, 00fh, 04fh, 00fh, 054h, 00fh, 059h, 00fh, 05eh, 00fh, 063h, 00fh +vga_get_font_info: ; 0xc0ee7 LB 0x83 + push si ; 56 ; 0xc0ee7 vgabios.c:588 + push di ; 57 ; 0xc0ee8 + push bp ; 55 ; 0xc0ee9 + mov bp, sp ; 89 e5 ; 0xc0eea + mov di, dx ; 89 d7 ; 0xc0eec + mov si, bx ; 89 de ; 0xc0eee + cmp ax, strict word 00007h ; 3d 07 00 ; 0xc0ef0 vgabios.c:593 + jnbe short 00f3dh ; 77 48 ; 0xc0ef3 + mov bx, ax ; 89 c3 ; 0xc0ef5 + add bx, ax ; 01 c3 ; 0xc0ef7 + jmp word [cs:bx+00ed7h] ; 2e ff a7 d7 0e ; 0xc0ef9 + mov bx, strict word 0007ch ; bb 7c 00 ; 0xc0efe vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0f01 + mov es, ax ; 8e c0 ; 0xc0f03 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc0f05 + mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xc0f08 + push SS ; 16 ; 0xc0f0c vgabios.c:596 + pop ES ; 07 ; 0xc0f0d + mov word [es:si], dx ; 26 89 14 ; 0xc0f0e + mov word [es:di], ax ; 26 89 05 ; 0xc0f11 + mov bx, 00085h ; bb 85 00 ; 0xc0f14 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0f17 + mov es, ax ; 8e c0 ; 0xc0f1a + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0f1c + xor ah, ah ; 30 e4 ; 0xc0f1f + push SS ; 16 ; 0xc0f21 + pop ES ; 07 ; 0xc0f22 + mov bx, cx ; 89 cb ; 0xc0f23 + mov word [es:bx], ax ; 26 89 07 ; 0xc0f25 + mov bx, 00084h ; bb 84 00 ; 0xc0f28 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0f2b + mov es, ax ; 8e c0 ; 0xc0f2e + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0f30 + xor ah, ah ; 30 e4 ; 0xc0f33 + push SS ; 16 ; 0xc0f35 + pop ES ; 07 ; 0xc0f36 + mov bx, word [bp+008h] ; 8b 5e 08 ; 0xc0f37 + mov word [es:bx], ax ; 26 89 07 ; 0xc0f3a + pop bp ; 5d ; 0xc0f3d + pop di ; 5f ; 0xc0f3e + pop si ; 5e ; 0xc0f3f + retn 00002h ; c2 02 00 ; 0xc0f40 + mov bx, 0010ch ; bb 0c 01 ; 0xc0f43 vgabios.c:67 + jmp short 00f01h ; eb b9 ; 0xc0f46 + mov dx, 05d6dh ; ba 6d 5d ; 0xc0f48 vgabios.c:601 + mov ax, ds ; 8c d8 ; 0xc0f4b + jmp short 00f0ch ; eb bd ; 0xc0f4d vgabios.c:602 + mov dx, 0556dh ; ba 6d 55 ; 0xc0f4f vgabios.c:604 + jmp short 00f4bh ; eb f7 ; 0xc0f52 + mov dx, 0596dh ; ba 6d 59 ; 0xc0f54 vgabios.c:607 + jmp short 00f4bh ; eb f2 ; 0xc0f57 + mov dx, 07b6dh ; ba 6d 7b ; 0xc0f59 vgabios.c:610 + jmp short 00f4bh ; eb ed ; 0xc0f5c + mov dx, 06b6dh ; ba 6d 6b ; 0xc0f5e vgabios.c:613 + jmp short 00f4bh ; eb e8 ; 0xc0f61 + mov dx, 07c9ah ; ba 9a 7c ; 0xc0f63 vgabios.c:616 + jmp short 00f4bh ; eb e3 ; 0xc0f66 + jmp short 00f3dh ; eb d3 ; 0xc0f68 vgabios.c:622 + ; disGetNextSymbol 0xc0f6a LB 0x334f -> off=0x0 cb=0000000000000156 uValue=00000000000c0f6a 'vga_read_pixel' +vga_read_pixel: ; 0xc0f6a LB 0x156 + push bp ; 55 ; 0xc0f6a vgabios.c:635 + mov bp, sp ; 89 e5 ; 0xc0f6b + push si ; 56 ; 0xc0f6d + push di ; 57 ; 0xc0f6e + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc0f6f + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc0f72 + mov word [bp-00ch], bx ; 89 5e f4 ; 0xc0f75 + mov si, cx ; 89 ce ; 0xc0f78 + mov bx, strict word 00049h ; bb 49 00 ; 0xc0f7a vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0f7d + mov es, ax ; 8e c0 ; 0xc0f80 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0f82 + xor ah, ah ; 30 e4 ; 0xc0f85 vgabios.c:642 + call 035edh ; e8 63 26 ; 0xc0f87 + mov ah, al ; 88 c4 ; 0xc0f8a + cmp AL, strict byte 0ffh ; 3c ff ; 0xc0f8c vgabios.c:643 + je near 010b9h ; 0f 84 27 01 ; 0xc0f8e + movzx bx, al ; 0f b6 d8 ; 0xc0f92 vgabios.c:645 + sal bx, 003h ; c1 e3 03 ; 0xc0f95 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc0f98 + je near 010b9h ; 0f 84 18 01 ; 0xc0f9d + mov ch, byte [bx+047b1h] ; 8a af b1 47 ; 0xc0fa1 vgabios.c:649 + cmp ch, 003h ; 80 fd 03 ; 0xc0fa5 + jc short 00fbbh ; 72 11 ; 0xc0fa8 + jbe short 00fc3h ; 76 17 ; 0xc0faa + cmp ch, 005h ; 80 fd 05 ; 0xc0fac + je near 01092h ; 0f 84 df 00 ; 0xc0faf + cmp ch, 004h ; 80 fd 04 ; 0xc0fb3 + je short 00fc3h ; 74 0b ; 0xc0fb6 + jmp near 010b2h ; e9 f7 00 ; 0xc0fb8 + cmp ch, 002h ; 80 fd 02 ; 0xc0fbb + je short 0102eh ; 74 6e ; 0xc0fbe + jmp near 010b2h ; e9 ef 00 ; 0xc0fc0 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc0fc3 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0fc6 + mov es, ax ; 8e c0 ; 0xc0fc9 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0fcb + imul ax, word [bp-00ch] ; 0f af 46 f4 ; 0xc0fce vgabios.c:58 + mov bx, dx ; 89 d3 ; 0xc0fd2 + shr bx, 003h ; c1 eb 03 ; 0xc0fd4 + add bx, ax ; 01 c3 ; 0xc0fd7 + mov di, strict word 0004ch ; bf 4c 00 ; 0xc0fd9 vgabios.c:57 + mov cx, word [es:di] ; 26 8b 0d ; 0xc0fdc + movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xc0fdf vgabios.c:58 + imul ax, cx ; 0f af c1 ; 0xc0fe3 + add bx, ax ; 01 c3 ; 0xc0fe6 + mov cl, dl ; 88 d1 ; 0xc0fe8 vgabios.c:654 + and cl, 007h ; 80 e1 07 ; 0xc0fea + mov ax, 00080h ; b8 80 00 ; 0xc0fed + sar ax, CL ; d3 f8 ; 0xc0ff0 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc0ff2 + xor ch, ch ; 30 ed ; 0xc0ff5 vgabios.c:655 + mov byte [bp-006h], ch ; 88 6e fa ; 0xc0ff7 vgabios.c:656 + jmp short 01004h ; eb 08 ; 0xc0ffa + cmp byte [bp-006h], 004h ; 80 7e fa 04 ; 0xc0ffc + jnc near 010b4h ; 0f 83 b0 00 ; 0xc1000 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc1004 vgabios.c:657 + sal ax, 008h ; c1 e0 08 ; 0xc1008 + or AL, strict byte 004h ; 0c 04 ; 0xc100b + mov dx, 003ceh ; ba ce 03 ; 0xc100d + out DX, ax ; ef ; 0xc1010 + mov ax, 0a000h ; b8 00 a0 ; 0xc1011 vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc1014 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1016 + and al, byte [bp-008h] ; 22 46 f8 ; 0xc1019 vgabios.c:48 + test al, al ; 84 c0 ; 0xc101c vgabios.c:659 + jbe short 01029h ; 76 09 ; 0xc101e + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc1020 vgabios.c:660 + mov AL, strict byte 001h ; b0 01 ; 0xc1023 + sal al, CL ; d2 e0 ; 0xc1025 + or ch, al ; 08 c5 ; 0xc1027 + inc byte [bp-006h] ; fe 46 fa ; 0xc1029 vgabios.c:661 + jmp short 00ffch ; eb ce ; 0xc102c + movzx cx, byte [bx+047b2h] ; 0f b6 8f b2 47 ; 0xc102e vgabios.c:664 + mov bx, strict word 00004h ; bb 04 00 ; 0xc1033 + sub bx, cx ; 29 cb ; 0xc1036 + mov cx, bx ; 89 d9 ; 0xc1038 + mov bx, dx ; 89 d3 ; 0xc103a + shr bx, CL ; d3 eb ; 0xc103c + mov cx, bx ; 89 d9 ; 0xc103e + mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xc1040 + shr bx, 1 ; d1 eb ; 0xc1043 + imul bx, bx, strict byte 00050h ; 6b db 50 ; 0xc1045 + add bx, cx ; 01 cb ; 0xc1048 + test byte [bp-00ch], 001h ; f6 46 f4 01 ; 0xc104a vgabios.c:665 + je short 01053h ; 74 03 ; 0xc104e + add bh, 020h ; 80 c7 20 ; 0xc1050 vgabios.c:666 + mov cx, 0b800h ; b9 00 b8 ; 0xc1053 vgabios.c:47 + mov es, cx ; 8e c1 ; 0xc1056 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1058 + movzx bx, ah ; 0f b6 dc ; 0xc105b vgabios.c:668 + sal bx, 003h ; c1 e3 03 ; 0xc105e + cmp byte [bx+047b2h], 002h ; 80 bf b2 47 02 ; 0xc1061 + jne short 0107dh ; 75 15 ; 0xc1066 + and dx, strict byte 00003h ; 83 e2 03 ; 0xc1068 vgabios.c:669 + mov cx, strict word 00003h ; b9 03 00 ; 0xc106b + sub cx, dx ; 29 d1 ; 0xc106e + add cx, cx ; 01 c9 ; 0xc1070 + xor ah, ah ; 30 e4 ; 0xc1072 + sar ax, CL ; d3 f8 ; 0xc1074 + mov ch, al ; 88 c5 ; 0xc1076 + and ch, 003h ; 80 e5 03 ; 0xc1078 + jmp short 010b4h ; eb 37 ; 0xc107b vgabios.c:670 + xor dh, dh ; 30 f6 ; 0xc107d vgabios.c:671 + and dl, 007h ; 80 e2 07 ; 0xc107f + mov cx, strict word 00007h ; b9 07 00 ; 0xc1082 + sub cx, dx ; 29 d1 ; 0xc1085 + xor ah, ah ; 30 e4 ; 0xc1087 + sar ax, CL ; d3 f8 ; 0xc1089 + mov ch, al ; 88 c5 ; 0xc108b + and ch, 001h ; 80 e5 01 ; 0xc108d + jmp short 010b4h ; eb 22 ; 0xc1090 vgabios.c:672 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1092 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1095 + mov es, ax ; 8e c0 ; 0xc1098 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc109a + sal ax, 003h ; c1 e0 03 ; 0xc109d vgabios.c:58 + mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xc10a0 + imul bx, ax ; 0f af d8 ; 0xc10a3 + add bx, dx ; 01 d3 ; 0xc10a6 + mov ax, 0a000h ; b8 00 a0 ; 0xc10a8 vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc10ab + mov ch, byte [es:bx] ; 26 8a 2f ; 0xc10ad + jmp short 010b4h ; eb 02 ; 0xc10b0 vgabios.c:676 + xor ch, ch ; 30 ed ; 0xc10b2 vgabios.c:681 + push SS ; 16 ; 0xc10b4 vgabios.c:683 + pop ES ; 07 ; 0xc10b5 + mov byte [es:si], ch ; 26 88 2c ; 0xc10b6 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc10b9 vgabios.c:684 + pop di ; 5f ; 0xc10bc + pop si ; 5e ; 0xc10bd + pop bp ; 5d ; 0xc10be + retn ; c3 ; 0xc10bf + ; disGetNextSymbol 0xc10c0 LB 0x31f9 -> off=0x0 cb=000000000000008c uValue=00000000000c10c0 'biosfn_perform_gray_scale_summing' +biosfn_perform_gray_scale_summing: ; 0xc10c0 LB 0x8c + push bp ; 55 ; 0xc10c0 vgabios.c:689 + mov bp, sp ; 89 e5 ; 0xc10c1 + push bx ; 53 ; 0xc10c3 + push cx ; 51 ; 0xc10c4 + push si ; 56 ; 0xc10c5 + push di ; 57 ; 0xc10c6 + push ax ; 50 ; 0xc10c7 + push ax ; 50 ; 0xc10c8 + mov bx, ax ; 89 c3 ; 0xc10c9 + mov di, dx ; 89 d7 ; 0xc10cb + mov dx, 003dah ; ba da 03 ; 0xc10cd vgabios.c:694 + in AL, DX ; ec ; 0xc10d0 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc10d1 + xor al, al ; 30 c0 ; 0xc10d3 vgabios.c:695 + mov dx, 003c0h ; ba c0 03 ; 0xc10d5 + out DX, AL ; ee ; 0xc10d8 + xor si, si ; 31 f6 ; 0xc10d9 vgabios.c:697 + cmp si, di ; 39 fe ; 0xc10db + jnc short 01131h ; 73 52 ; 0xc10dd + mov al, bl ; 88 d8 ; 0xc10df vgabios.c:700 + mov dx, 003c7h ; ba c7 03 ; 0xc10e1 + out DX, AL ; ee ; 0xc10e4 + mov dx, 003c9h ; ba c9 03 ; 0xc10e5 vgabios.c:702 + in AL, DX ; ec ; 0xc10e8 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc10e9 + mov cx, ax ; 89 c1 ; 0xc10eb + in AL, DX ; ec ; 0xc10ed vgabios.c:703 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc10ee + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc10f0 + in AL, DX ; ec ; 0xc10f3 vgabios.c:704 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc10f4 + xor ch, ch ; 30 ed ; 0xc10f6 vgabios.c:707 + imul cx, cx, strict byte 0004dh ; 6b c9 4d ; 0xc10f8 + mov word [bp-00ah], cx ; 89 4e f6 ; 0xc10fb + movzx cx, byte [bp-00ch] ; 0f b6 4e f4 ; 0xc10fe + imul cx, cx, 00097h ; 69 c9 97 00 ; 0xc1102 + add cx, word [bp-00ah] ; 03 4e f6 ; 0xc1106 + xor ah, ah ; 30 e4 ; 0xc1109 + imul ax, ax, strict byte 0001ch ; 6b c0 1c ; 0xc110b + add cx, ax ; 01 c1 ; 0xc110e + add cx, 00080h ; 81 c1 80 00 ; 0xc1110 + sar cx, 008h ; c1 f9 08 ; 0xc1114 + cmp cx, strict byte 0003fh ; 83 f9 3f ; 0xc1117 vgabios.c:709 + jbe short 0111fh ; 76 03 ; 0xc111a + mov cx, strict word 0003fh ; b9 3f 00 ; 0xc111c + mov al, bl ; 88 d8 ; 0xc111f vgabios.c:712 + mov dx, 003c8h ; ba c8 03 ; 0xc1121 + out DX, AL ; ee ; 0xc1124 + mov al, cl ; 88 c8 ; 0xc1125 vgabios.c:714 + mov dx, 003c9h ; ba c9 03 ; 0xc1127 + out DX, AL ; ee ; 0xc112a + out DX, AL ; ee ; 0xc112b vgabios.c:715 + out DX, AL ; ee ; 0xc112c vgabios.c:716 + inc bx ; 43 ; 0xc112d vgabios.c:717 + inc si ; 46 ; 0xc112e vgabios.c:718 + jmp short 010dbh ; eb aa ; 0xc112f + mov dx, 003dah ; ba da 03 ; 0xc1131 vgabios.c:719 + in AL, DX ; ec ; 0xc1134 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1135 + mov AL, strict byte 020h ; b0 20 ; 0xc1137 vgabios.c:720 + mov dx, 003c0h ; ba c0 03 ; 0xc1139 + out DX, AL ; ee ; 0xc113c + mov dx, 003dah ; ba da 03 ; 0xc113d vgabios.c:722 + in AL, DX ; ec ; 0xc1140 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1141 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc1143 vgabios.c:724 + pop di ; 5f ; 0xc1146 + pop si ; 5e ; 0xc1147 + pop cx ; 59 ; 0xc1148 + pop bx ; 5b ; 0xc1149 + pop bp ; 5d ; 0xc114a + retn ; c3 ; 0xc114b + ; disGetNextSymbol 0xc114c LB 0x316d -> off=0x0 cb=00000000000000f6 uValue=00000000000c114c 'biosfn_set_cursor_shape' +biosfn_set_cursor_shape: ; 0xc114c LB 0xf6 + push bp ; 55 ; 0xc114c vgabios.c:727 + mov bp, sp ; 89 e5 ; 0xc114d + push bx ; 53 ; 0xc114f + push cx ; 51 ; 0xc1150 + push si ; 56 ; 0xc1151 + push di ; 57 ; 0xc1152 + push ax ; 50 ; 0xc1153 + mov bl, al ; 88 c3 ; 0xc1154 + mov ah, dl ; 88 d4 ; 0xc1156 + movzx cx, al ; 0f b6 c8 ; 0xc1158 vgabios.c:733 + sal cx, 008h ; c1 e1 08 ; 0xc115b + movzx dx, ah ; 0f b6 d4 ; 0xc115e + add dx, cx ; 01 ca ; 0xc1161 + mov si, strict word 00060h ; be 60 00 ; 0xc1163 vgabios.c:62 + mov cx, strict word 00040h ; b9 40 00 ; 0xc1166 + mov es, cx ; 8e c1 ; 0xc1169 + mov word [es:si], dx ; 26 89 14 ; 0xc116b + mov si, 00087h ; be 87 00 ; 0xc116e vgabios.c:47 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc1171 + test dl, 008h ; f6 c2 08 ; 0xc1174 vgabios.c:48 + jne near 01217h ; 0f 85 9c 00 ; 0xc1177 + mov dl, al ; 88 c2 ; 0xc117b vgabios.c:739 + and dl, 060h ; 80 e2 60 ; 0xc117d + cmp dl, 020h ; 80 fa 20 ; 0xc1180 + jne short 0118ch ; 75 07 ; 0xc1183 + mov BL, strict byte 01eh ; b3 1e ; 0xc1185 vgabios.c:741 + xor ah, ah ; 30 e4 ; 0xc1187 vgabios.c:742 + jmp near 01217h ; e9 8b 00 ; 0xc1189 vgabios.c:743 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc118c vgabios.c:47 + test dl, 001h ; f6 c2 01 ; 0xc118f vgabios.c:48 + jne near 01217h ; 0f 85 81 00 ; 0xc1192 + cmp bl, 020h ; 80 fb 20 ; 0xc1196 + jnc near 01217h ; 0f 83 7a 00 ; 0xc1199 + cmp ah, 020h ; 80 fc 20 ; 0xc119d + jnc near 01217h ; 0f 83 73 00 ; 0xc11a0 + mov si, 00085h ; be 85 00 ; 0xc11a4 vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc11a7 + mov es, dx ; 8e c2 ; 0xc11aa + mov cx, word [es:si] ; 26 8b 0c ; 0xc11ac + mov dx, cx ; 89 ca ; 0xc11af vgabios.c:58 + cmp ah, bl ; 38 dc ; 0xc11b1 vgabios.c:754 + jnc short 011c1h ; 73 0c ; 0xc11b3 + test ah, ah ; 84 e4 ; 0xc11b5 vgabios.c:756 + je short 01217h ; 74 5e ; 0xc11b7 + xor bl, bl ; 30 db ; 0xc11b9 vgabios.c:757 + mov ah, cl ; 88 cc ; 0xc11bb vgabios.c:758 + db 0feh, 0cch + ; dec ah ; fe cc ; 0xc11bd + jmp short 01217h ; eb 56 ; 0xc11bf vgabios.c:760 + movzx si, ah ; 0f b6 f4 ; 0xc11c1 vgabios.c:761 + mov word [bp-00ah], si ; 89 76 f6 ; 0xc11c4 + movzx si, bl ; 0f b6 f3 ; 0xc11c7 + or si, word [bp-00ah] ; 0b 76 f6 ; 0xc11ca + cmp si, cx ; 39 ce ; 0xc11cd + jnc short 011e4h ; 73 13 ; 0xc11cf + movzx di, ah ; 0f b6 fc ; 0xc11d1 + mov si, cx ; 89 ce ; 0xc11d4 + dec si ; 4e ; 0xc11d6 + cmp di, si ; 39 f7 ; 0xc11d7 + je short 01217h ; 74 3c ; 0xc11d9 + movzx si, bl ; 0f b6 f3 ; 0xc11db + dec cx ; 49 ; 0xc11de + dec cx ; 49 ; 0xc11df + cmp si, cx ; 39 ce ; 0xc11e0 + je short 01217h ; 74 33 ; 0xc11e2 + cmp ah, 003h ; 80 fc 03 ; 0xc11e4 vgabios.c:763 + jbe short 01217h ; 76 2e ; 0xc11e7 + movzx si, bl ; 0f b6 f3 ; 0xc11e9 vgabios.c:764 + movzx di, ah ; 0f b6 fc ; 0xc11ec + inc si ; 46 ; 0xc11ef + inc si ; 46 ; 0xc11f0 + mov cl, dl ; 88 d1 ; 0xc11f1 + db 0feh, 0c9h + ; dec cl ; fe c9 ; 0xc11f3 + cmp di, si ; 39 f7 ; 0xc11f5 + jnle short 0120ch ; 7f 13 ; 0xc11f7 + sub bl, ah ; 28 e3 ; 0xc11f9 vgabios.c:766 + add bl, dl ; 00 d3 ; 0xc11fb + db 0feh, 0cbh + ; dec bl ; fe cb ; 0xc11fd + mov ah, cl ; 88 cc ; 0xc11ff vgabios.c:767 + cmp dx, strict byte 0000eh ; 83 fa 0e ; 0xc1201 vgabios.c:768 + jc short 01217h ; 72 11 ; 0xc1204 + db 0feh, 0cch + ; dec ah ; fe cc ; 0xc1206 vgabios.c:770 + db 0feh, 0cbh + ; dec bl ; fe cb ; 0xc1208 vgabios.c:771 + jmp short 01217h ; eb 0b ; 0xc120a vgabios.c:773 + cmp bl, 002h ; 80 fb 02 ; 0xc120c + jbe short 01215h ; 76 04 ; 0xc120f + shr dx, 1 ; d1 ea ; 0xc1211 vgabios.c:775 + mov bl, dl ; 88 d3 ; 0xc1213 + mov ah, cl ; 88 cc ; 0xc1215 vgabios.c:779 + mov si, strict word 00063h ; be 63 00 ; 0xc1217 vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc121a + mov es, dx ; 8e c2 ; 0xc121d + mov cx, word [es:si] ; 26 8b 0c ; 0xc121f + mov AL, strict byte 00ah ; b0 0a ; 0xc1222 vgabios.c:790 + mov dx, cx ; 89 ca ; 0xc1224 + out DX, AL ; ee ; 0xc1226 + mov si, cx ; 89 ce ; 0xc1227 vgabios.c:791 + inc si ; 46 ; 0xc1229 + mov al, bl ; 88 d8 ; 0xc122a + mov dx, si ; 89 f2 ; 0xc122c + out DX, AL ; ee ; 0xc122e + mov AL, strict byte 00bh ; b0 0b ; 0xc122f vgabios.c:792 + mov dx, cx ; 89 ca ; 0xc1231 + out DX, AL ; ee ; 0xc1233 + mov al, ah ; 88 e0 ; 0xc1234 vgabios.c:793 + mov dx, si ; 89 f2 ; 0xc1236 + out DX, AL ; ee ; 0xc1238 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc1239 vgabios.c:794 + pop di ; 5f ; 0xc123c + pop si ; 5e ; 0xc123d + pop cx ; 59 ; 0xc123e + pop bx ; 5b ; 0xc123f + pop bp ; 5d ; 0xc1240 + retn ; c3 ; 0xc1241 + ; disGetNextSymbol 0xc1242 LB 0x3077 -> off=0x0 cb=0000000000000089 uValue=00000000000c1242 'biosfn_set_cursor_pos' +biosfn_set_cursor_pos: ; 0xc1242 LB 0x89 + push bp ; 55 ; 0xc1242 vgabios.c:797 + mov bp, sp ; 89 e5 ; 0xc1243 + push bx ; 53 ; 0xc1245 + push cx ; 51 ; 0xc1246 + push si ; 56 ; 0xc1247 + push ax ; 50 ; 0xc1248 + cmp AL, strict byte 007h ; 3c 07 ; 0xc1249 vgabios.c:803 + jnbe short 012c3h ; 77 76 ; 0xc124b + movzx bx, al ; 0f b6 d8 ; 0xc124d vgabios.c:806 + add bx, bx ; 01 db ; 0xc1250 + add bx, strict byte 00050h ; 83 c3 50 ; 0xc1252 + mov cx, strict word 00040h ; b9 40 00 ; 0xc1255 vgabios.c:62 + mov es, cx ; 8e c1 ; 0xc1258 + mov word [es:bx], dx ; 26 89 17 ; 0xc125a + mov bx, strict word 00062h ; bb 62 00 ; 0xc125d vgabios.c:47 + mov ah, byte [es:bx] ; 26 8a 27 ; 0xc1260 + cmp al, ah ; 38 e0 ; 0xc1263 vgabios.c:810 + jne short 012c3h ; 75 5c ; 0xc1265 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1267 vgabios.c:57 + mov cx, word [es:bx] ; 26 8b 0f ; 0xc126a + mov bx, 00084h ; bb 84 00 ; 0xc126d vgabios.c:47 + mov ah, byte [es:bx] ; 26 8a 27 ; 0xc1270 + movzx bx, ah ; 0f b6 dc ; 0xc1273 vgabios.c:48 + inc bx ; 43 ; 0xc1276 + mov si, dx ; 89 d6 ; 0xc1277 vgabios.c:816 + and si, 0ff00h ; 81 e6 00 ff ; 0xc1279 + shr si, 008h ; c1 ee 08 ; 0xc127d + mov word [bp-008h], si ; 89 76 f8 ; 0xc1280 + imul bx, cx ; 0f af d9 ; 0xc1283 vgabios.c:819 + or bl, 0ffh ; 80 cb ff ; 0xc1286 + xor ah, ah ; 30 e4 ; 0xc1289 + inc bx ; 43 ; 0xc128b + imul ax, bx ; 0f af c3 ; 0xc128c + movzx si, dl ; 0f b6 f2 ; 0xc128f + add si, ax ; 01 c6 ; 0xc1292 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc1294 + imul ax, cx ; 0f af c1 ; 0xc1298 + add si, ax ; 01 c6 ; 0xc129b + mov bx, strict word 00063h ; bb 63 00 ; 0xc129d vgabios.c:57 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc12a0 + mov AL, strict byte 00eh ; b0 0e ; 0xc12a3 vgabios.c:823 + mov dx, bx ; 89 da ; 0xc12a5 + out DX, AL ; ee ; 0xc12a7 + mov ax, si ; 89 f0 ; 0xc12a8 vgabios.c:824 + xor al, al ; 30 c0 ; 0xc12aa + shr ax, 008h ; c1 e8 08 ; 0xc12ac + lea cx, [bx+001h] ; 8d 4f 01 ; 0xc12af + mov dx, cx ; 89 ca ; 0xc12b2 + out DX, AL ; ee ; 0xc12b4 + mov AL, strict byte 00fh ; b0 0f ; 0xc12b5 vgabios.c:825 + mov dx, bx ; 89 da ; 0xc12b7 + out DX, AL ; ee ; 0xc12b9 + and si, 000ffh ; 81 e6 ff 00 ; 0xc12ba vgabios.c:826 + mov ax, si ; 89 f0 ; 0xc12be + mov dx, cx ; 89 ca ; 0xc12c0 + out DX, AL ; ee ; 0xc12c2 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc12c3 vgabios.c:828 + pop si ; 5e ; 0xc12c6 + pop cx ; 59 ; 0xc12c7 + pop bx ; 5b ; 0xc12c8 + pop bp ; 5d ; 0xc12c9 + retn ; c3 ; 0xc12ca + ; disGetNextSymbol 0xc12cb LB 0x2fee -> off=0x0 cb=00000000000000cd uValue=00000000000c12cb 'biosfn_set_active_page' +biosfn_set_active_page: ; 0xc12cb LB 0xcd + push bp ; 55 ; 0xc12cb vgabios.c:831 + mov bp, sp ; 89 e5 ; 0xc12cc + push bx ; 53 ; 0xc12ce + push cx ; 51 ; 0xc12cf + push dx ; 52 ; 0xc12d0 + push si ; 56 ; 0xc12d1 + push di ; 57 ; 0xc12d2 + push ax ; 50 ; 0xc12d3 + push ax ; 50 ; 0xc12d4 + mov cl, al ; 88 c1 ; 0xc12d5 + cmp AL, strict byte 007h ; 3c 07 ; 0xc12d7 vgabios.c:837 + jnbe near 0138eh ; 0f 87 b1 00 ; 0xc12d9 + mov bx, strict word 00049h ; bb 49 00 ; 0xc12dd vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc12e0 + mov es, ax ; 8e c0 ; 0xc12e3 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc12e5 + xor ah, ah ; 30 e4 ; 0xc12e8 vgabios.c:841 + call 035edh ; e8 00 23 ; 0xc12ea + mov ch, al ; 88 c5 ; 0xc12ed + cmp AL, strict byte 0ffh ; 3c ff ; 0xc12ef vgabios.c:842 + je near 0138eh ; 0f 84 99 00 ; 0xc12f1 + movzx ax, cl ; 0f b6 c1 ; 0xc12f5 vgabios.c:845 + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc12f8 + lea dx, [bp-00ch] ; 8d 56 f4 ; 0xc12fb + call 00a93h ; e8 92 f7 ; 0xc12fe + movzx bx, ch ; 0f b6 dd ; 0xc1301 vgabios.c:847 + mov si, bx ; 89 de ; 0xc1304 + sal si, 003h ; c1 e6 03 ; 0xc1306 + cmp byte [si+047b0h], 000h ; 80 bc b0 47 00 ; 0xc1309 + jne short 01344h ; 75 34 ; 0xc130e + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1310 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1313 + mov es, ax ; 8e c0 ; 0xc1316 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc1318 + mov bx, 00084h ; bb 84 00 ; 0xc131b vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc131e + xor ah, ah ; 30 e4 ; 0xc1321 vgabios.c:48 + inc ax ; 40 ; 0xc1323 + imul dx, ax ; 0f af d0 ; 0xc1324 vgabios.c:854 + mov ax, dx ; 89 d0 ; 0xc1327 + add ax, dx ; 01 d0 ; 0xc1329 + or AL, strict byte 0ffh ; 0c ff ; 0xc132b + mov bx, ax ; 89 c3 ; 0xc132d + movzx ax, cl ; 0f b6 c1 ; 0xc132f + inc bx ; 43 ; 0xc1332 + imul bx, ax ; 0f af d8 ; 0xc1333 + mov si, strict word 0004eh ; be 4e 00 ; 0xc1336 vgabios.c:62 + mov word [es:si], bx ; 26 89 1c ; 0xc1339 + or dl, 0ffh ; 80 ca ff ; 0xc133c vgabios.c:858 + mov bx, dx ; 89 d3 ; 0xc133f + inc bx ; 43 ; 0xc1341 + jmp short 01353h ; eb 0f ; 0xc1342 vgabios.c:860 + movzx bx, byte [bx+0482fh] ; 0f b6 9f 2f 48 ; 0xc1344 vgabios.c:862 + sal bx, 006h ; c1 e3 06 ; 0xc1349 + movzx ax, cl ; 0f b6 c1 ; 0xc134c + mov bx, word [bx+04846h] ; 8b 9f 46 48 ; 0xc134f + imul bx, ax ; 0f af d8 ; 0xc1353 + mov si, strict word 00063h ; be 63 00 ; 0xc1356 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1359 + mov es, ax ; 8e c0 ; 0xc135c + mov si, word [es:si] ; 26 8b 34 ; 0xc135e + mov AL, strict byte 00ch ; b0 0c ; 0xc1361 vgabios.c:867 + mov dx, si ; 89 f2 ; 0xc1363 + out DX, AL ; ee ; 0xc1365 + mov ax, bx ; 89 d8 ; 0xc1366 vgabios.c:868 + xor al, bl ; 30 d8 ; 0xc1368 + shr ax, 008h ; c1 e8 08 ; 0xc136a + lea di, [si+001h] ; 8d 7c 01 ; 0xc136d + mov dx, di ; 89 fa ; 0xc1370 + out DX, AL ; ee ; 0xc1372 + mov AL, strict byte 00dh ; b0 0d ; 0xc1373 vgabios.c:869 + mov dx, si ; 89 f2 ; 0xc1375 + out DX, AL ; ee ; 0xc1377 + xor bh, bh ; 30 ff ; 0xc1378 vgabios.c:870 + mov ax, bx ; 89 d8 ; 0xc137a + mov dx, di ; 89 fa ; 0xc137c + out DX, AL ; ee ; 0xc137e + mov bx, strict word 00062h ; bb 62 00 ; 0xc137f vgabios.c:52 + mov byte [es:bx], cl ; 26 88 0f ; 0xc1382 + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc1385 vgabios.c:880 + movzx ax, cl ; 0f b6 c1 ; 0xc1388 + call 01242h ; e8 b4 fe ; 0xc138b + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc138e vgabios.c:881 + pop di ; 5f ; 0xc1391 + pop si ; 5e ; 0xc1392 + pop dx ; 5a ; 0xc1393 + pop cx ; 59 ; 0xc1394 + pop bx ; 5b ; 0xc1395 + pop bp ; 5d ; 0xc1396 + retn ; c3 ; 0xc1397 + ; disGetNextSymbol 0xc1398 LB 0x2f21 -> off=0x0 cb=0000000000000045 uValue=00000000000c1398 'find_vpti' +find_vpti: ; 0xc1398 LB 0x45 + push bx ; 53 ; 0xc1398 vgabios.c:916 + push si ; 56 ; 0xc1399 + push bp ; 55 ; 0xc139a + mov bp, sp ; 89 e5 ; 0xc139b + movzx bx, al ; 0f b6 d8 ; 0xc139d vgabios.c:921 + mov si, bx ; 89 de ; 0xc13a0 + sal si, 003h ; c1 e6 03 ; 0xc13a2 + cmp byte [si+047b0h], 000h ; 80 bc b0 47 00 ; 0xc13a5 + jne short 013d4h ; 75 28 ; 0xc13aa + mov si, 00089h ; be 89 00 ; 0xc13ac vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc13af + mov es, ax ; 8e c0 ; 0xc13b2 + mov al, byte [es:si] ; 26 8a 04 ; 0xc13b4 + test AL, strict byte 010h ; a8 10 ; 0xc13b7 vgabios.c:923 + je short 013c2h ; 74 07 ; 0xc13b9 + movsx ax, byte [bx+07df6h] ; 0f be 87 f6 7d ; 0xc13bb vgabios.c:924 + jmp short 013d9h ; eb 17 ; 0xc13c0 vgabios.c:925 + test AL, strict byte 080h ; a8 80 ; 0xc13c2 + je short 013cdh ; 74 07 ; 0xc13c4 + movsx ax, byte [bx+07de6h] ; 0f be 87 e6 7d ; 0xc13c6 vgabios.c:926 + jmp short 013d9h ; eb 0c ; 0xc13cb vgabios.c:927 + movsx ax, byte [bx+07deeh] ; 0f be 87 ee 7d ; 0xc13cd vgabios.c:928 + jmp short 013d9h ; eb 05 ; 0xc13d2 vgabios.c:929 + movzx ax, byte [bx+0482fh] ; 0f b6 87 2f 48 ; 0xc13d4 vgabios.c:930 + pop bp ; 5d ; 0xc13d9 vgabios.c:933 + pop si ; 5e ; 0xc13da + pop bx ; 5b ; 0xc13db + retn ; c3 ; 0xc13dc + ; disGetNextSymbol 0xc13dd LB 0x2edc -> off=0x0 cb=00000000000004b2 uValue=00000000000c13dd 'biosfn_set_video_mode' +biosfn_set_video_mode: ; 0xc13dd LB 0x4b2 + push bp ; 55 ; 0xc13dd vgabios.c:938 + mov bp, sp ; 89 e5 ; 0xc13de + push bx ; 53 ; 0xc13e0 + push cx ; 51 ; 0xc13e1 + push dx ; 52 ; 0xc13e2 + push si ; 56 ; 0xc13e3 + push di ; 57 ; 0xc13e4 + sub sp, strict byte 00016h ; 83 ec 16 ; 0xc13e5 + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc13e8 + and AL, strict byte 080h ; 24 80 ; 0xc13eb vgabios.c:942 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc13ed + call 007bfh ; e8 cc f3 ; 0xc13f0 vgabios.c:952 + test ax, ax ; 85 c0 ; 0xc13f3 + je short 01403h ; 74 0c ; 0xc13f5 + mov AL, strict byte 007h ; b0 07 ; 0xc13f7 vgabios.c:954 + mov dx, 003c4h ; ba c4 03 ; 0xc13f9 + out DX, AL ; ee ; 0xc13fc + xor al, al ; 30 c0 ; 0xc13fd vgabios.c:955 + mov dx, 003c5h ; ba c5 03 ; 0xc13ff + out DX, AL ; ee ; 0xc1402 + and byte [bp-00eh], 07fh ; 80 66 f2 7f ; 0xc1403 vgabios.c:960 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc1407 vgabios.c:966 + call 035edh ; e8 df 21 ; 0xc140b + mov byte [bp-010h], al ; 88 46 f0 ; 0xc140e + cmp AL, strict byte 0ffh ; 3c ff ; 0xc1411 vgabios.c:972 + je near 01885h ; 0f 84 6e 04 ; 0xc1413 + mov bx, 000a8h ; bb a8 00 ; 0xc1417 vgabios.c:67 + mov dx, strict word 00040h ; ba 40 00 ; 0xc141a + mov es, dx ; 8e c2 ; 0xc141d + mov di, word [es:bx] ; 26 8b 3f ; 0xc141f + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc1422 + mov bx, di ; 89 fb ; 0xc1426 vgabios.c:68 + mov word [bp-014h], dx ; 89 56 ec ; 0xc1428 + movzx cx, al ; 0f b6 c8 ; 0xc142b vgabios.c:978 + mov ax, cx ; 89 c8 ; 0xc142e + call 01398h ; e8 65 ff ; 0xc1430 + mov es, dx ; 8e c2 ; 0xc1433 vgabios.c:979 + mov si, word [es:di] ; 26 8b 35 ; 0xc1435 + mov dx, word [es:di+002h] ; 26 8b 55 02 ; 0xc1438 + mov word [bp-01ah], dx ; 89 56 e6 ; 0xc143c + xor ah, ah ; 30 e4 ; 0xc143f vgabios.c:980 + sal ax, 006h ; c1 e0 06 ; 0xc1441 + add si, ax ; 01 c6 ; 0xc1444 + mov di, 00089h ; bf 89 00 ; 0xc1446 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1449 + mov es, ax ; 8e c0 ; 0xc144c + mov al, byte [es:di] ; 26 8a 05 ; 0xc144e + mov ah, al ; 88 c4 ; 0xc1451 vgabios.c:48 + test AL, strict byte 008h ; a8 08 ; 0xc1453 vgabios.c:997 + jne near 01509h ; 0f 85 b0 00 ; 0xc1455 + mov di, cx ; 89 cf ; 0xc1459 vgabios.c:999 + sal di, 003h ; c1 e7 03 ; 0xc145b + mov al, byte [di+047b5h] ; 8a 85 b5 47 ; 0xc145e + mov dx, 003c6h ; ba c6 03 ; 0xc1462 + out DX, AL ; ee ; 0xc1465 + xor al, al ; 30 c0 ; 0xc1466 vgabios.c:1002 + mov dx, 003c8h ; ba c8 03 ; 0xc1468 + out DX, AL ; ee ; 0xc146b + mov cl, byte [di+047b6h] ; 8a 8d b6 47 ; 0xc146c vgabios.c:1005 + cmp cl, 001h ; 80 f9 01 ; 0xc1470 + jc short 01483h ; 72 0e ; 0xc1473 + jbe short 0148eh ; 76 17 ; 0xc1475 + cmp cl, 003h ; 80 f9 03 ; 0xc1477 + je short 0149ch ; 74 20 ; 0xc147a + cmp cl, 002h ; 80 f9 02 ; 0xc147c + je short 01495h ; 74 14 ; 0xc147f + jmp short 014a1h ; eb 1e ; 0xc1481 + test cl, cl ; 84 c9 ; 0xc1483 + jne short 014a1h ; 75 1a ; 0xc1485 + mov word [bp-016h], 04fc3h ; c7 46 ea c3 4f ; 0xc1487 vgabios.c:1007 + jmp short 014a1h ; eb 13 ; 0xc148c vgabios.c:1008 + mov word [bp-016h], 05083h ; c7 46 ea 83 50 ; 0xc148e vgabios.c:1010 + jmp short 014a1h ; eb 0c ; 0xc1493 vgabios.c:1011 + mov word [bp-016h], 05143h ; c7 46 ea 43 51 ; 0xc1495 vgabios.c:1013 + jmp short 014a1h ; eb 05 ; 0xc149a vgabios.c:1014 + mov word [bp-016h], 05203h ; c7 46 ea 03 52 ; 0xc149c vgabios.c:1016 + movzx di, byte [bp-010h] ; 0f b6 7e f0 ; 0xc14a1 vgabios.c:1020 + sal di, 003h ; c1 e7 03 ; 0xc14a5 + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc14a8 + jne short 014beh ; 75 0f ; 0xc14ad + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc14af vgabios.c:1022 + cmp byte [es:si+002h], 008h ; 26 80 7c 02 08 ; 0xc14b2 + jne short 014beh ; 75 05 ; 0xc14b7 + mov word [bp-016h], 05083h ; c7 46 ea 83 50 ; 0xc14b9 vgabios.c:1023 + xor cx, cx ; 31 c9 ; 0xc14be vgabios.c:1026 + jmp short 014d1h ; eb 0f ; 0xc14c0 + xor al, al ; 30 c0 ; 0xc14c2 vgabios.c:1033 + mov dx, 003c9h ; ba c9 03 ; 0xc14c4 + out DX, AL ; ee ; 0xc14c7 + out DX, AL ; ee ; 0xc14c8 vgabios.c:1034 + out DX, AL ; ee ; 0xc14c9 vgabios.c:1035 + inc cx ; 41 ; 0xc14ca vgabios.c:1037 + cmp cx, 00100h ; 81 f9 00 01 ; 0xc14cb + jnc short 014fch ; 73 2b ; 0xc14cf + movzx di, byte [bp-010h] ; 0f b6 7e f0 ; 0xc14d1 + sal di, 003h ; c1 e7 03 ; 0xc14d5 + movzx di, byte [di+047b6h] ; 0f b6 bd b6 47 ; 0xc14d8 + movzx di, byte [di+0483fh] ; 0f b6 bd 3f 48 ; 0xc14dd + cmp cx, di ; 39 f9 ; 0xc14e2 + jnbe short 014c2h ; 77 dc ; 0xc14e4 + imul di, cx, strict byte 00003h ; 6b f9 03 ; 0xc14e6 + add di, word [bp-016h] ; 03 7e ea ; 0xc14e9 + mov al, byte [di] ; 8a 05 ; 0xc14ec + mov dx, 003c9h ; ba c9 03 ; 0xc14ee + out DX, AL ; ee ; 0xc14f1 + mov al, byte [di+001h] ; 8a 45 01 ; 0xc14f2 + out DX, AL ; ee ; 0xc14f5 + mov al, byte [di+002h] ; 8a 45 02 ; 0xc14f6 + out DX, AL ; ee ; 0xc14f9 + jmp short 014cah ; eb ce ; 0xc14fa + test ah, 002h ; f6 c4 02 ; 0xc14fc vgabios.c:1038 + je short 01509h ; 74 08 ; 0xc14ff + mov dx, 00100h ; ba 00 01 ; 0xc1501 vgabios.c:1040 + xor ax, ax ; 31 c0 ; 0xc1504 + call 010c0h ; e8 b7 fb ; 0xc1506 + mov dx, 003dah ; ba da 03 ; 0xc1509 vgabios.c:1045 + in AL, DX ; ec ; 0xc150c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc150d + xor cx, cx ; 31 c9 ; 0xc150f vgabios.c:1048 + jmp short 01518h ; eb 05 ; 0xc1511 + cmp cx, strict byte 00013h ; 83 f9 13 ; 0xc1513 + jnbe short 0152dh ; 77 15 ; 0xc1516 + mov al, cl ; 88 c8 ; 0xc1518 vgabios.c:1049 + mov dx, 003c0h ; ba c0 03 ; 0xc151a + out DX, AL ; ee ; 0xc151d + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc151e vgabios.c:1050 + mov di, si ; 89 f7 ; 0xc1521 + add di, cx ; 01 cf ; 0xc1523 + mov al, byte [es:di+023h] ; 26 8a 45 23 ; 0xc1525 + out DX, AL ; ee ; 0xc1529 + inc cx ; 41 ; 0xc152a vgabios.c:1051 + jmp short 01513h ; eb e6 ; 0xc152b + mov AL, strict byte 014h ; b0 14 ; 0xc152d vgabios.c:1052 + mov dx, 003c0h ; ba c0 03 ; 0xc152f + out DX, AL ; ee ; 0xc1532 + xor al, al ; 30 c0 ; 0xc1533 vgabios.c:1053 + out DX, AL ; ee ; 0xc1535 + mov es, [bp-014h] ; 8e 46 ec ; 0xc1536 vgabios.c:1056 + mov dx, word [es:bx+004h] ; 26 8b 57 04 ; 0xc1539 + mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xc153d + test ax, ax ; 85 c0 ; 0xc1541 + jne short 01549h ; 75 04 ; 0xc1543 + test dx, dx ; 85 d2 ; 0xc1545 + je short 01589h ; 74 40 ; 0xc1547 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc1549 vgabios.c:1060 + xor cx, cx ; 31 c9 ; 0xc154c vgabios.c:1061 + jmp short 01555h ; eb 05 ; 0xc154e + cmp cx, strict byte 00010h ; 83 f9 10 ; 0xc1550 + jnc short 01579h ; 73 24 ; 0xc1553 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1555 vgabios.c:1062 + mov di, si ; 89 f7 ; 0xc1558 + add di, cx ; 01 cf ; 0xc155a + mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xc155c + mov word [bp-020h], ax ; 89 46 e0 ; 0xc155f + mov ax, dx ; 89 d0 ; 0xc1562 + add ax, cx ; 01 c8 ; 0xc1564 + mov word [bp-01eh], ax ; 89 46 e2 ; 0xc1566 + mov al, byte [es:di+023h] ; 26 8a 45 23 ; 0xc1569 + mov es, [bp-020h] ; 8e 46 e0 ; 0xc156d + mov di, word [bp-01eh] ; 8b 7e e2 ; 0xc1570 + mov byte [es:di], al ; 26 88 05 ; 0xc1573 + inc cx ; 41 ; 0xc1576 + jmp short 01550h ; eb d7 ; 0xc1577 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1579 vgabios.c:1063 + mov al, byte [es:si+034h] ; 26 8a 44 34 ; 0xc157c + mov es, [bp-01ch] ; 8e 46 e4 ; 0xc1580 + mov di, dx ; 89 d7 ; 0xc1583 + mov byte [es:di+010h], al ; 26 88 45 10 ; 0xc1585 + xor al, al ; 30 c0 ; 0xc1589 vgabios.c:1067 + mov dx, 003c4h ; ba c4 03 ; 0xc158b + out DX, AL ; ee ; 0xc158e + mov AL, strict byte 003h ; b0 03 ; 0xc158f vgabios.c:1068 + mov dx, 003c5h ; ba c5 03 ; 0xc1591 + out DX, AL ; ee ; 0xc1594 + mov cx, strict word 00001h ; b9 01 00 ; 0xc1595 vgabios.c:1069 + jmp short 0159fh ; eb 05 ; 0xc1598 + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc159a + jnbe short 015b7h ; 77 18 ; 0xc159d + mov al, cl ; 88 c8 ; 0xc159f vgabios.c:1070 + mov dx, 003c4h ; ba c4 03 ; 0xc15a1 + out DX, AL ; ee ; 0xc15a4 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc15a5 vgabios.c:1071 + mov di, si ; 89 f7 ; 0xc15a8 + add di, cx ; 01 cf ; 0xc15aa + mov al, byte [es:di+004h] ; 26 8a 45 04 ; 0xc15ac + mov dx, 003c5h ; ba c5 03 ; 0xc15b0 + out DX, AL ; ee ; 0xc15b3 + inc cx ; 41 ; 0xc15b4 vgabios.c:1072 + jmp short 0159ah ; eb e3 ; 0xc15b5 + xor cx, cx ; 31 c9 ; 0xc15b7 vgabios.c:1075 + jmp short 015c0h ; eb 05 ; 0xc15b9 + cmp cx, strict byte 00008h ; 83 f9 08 ; 0xc15bb + jnbe short 015d8h ; 77 18 ; 0xc15be + mov al, cl ; 88 c8 ; 0xc15c0 vgabios.c:1076 + mov dx, 003ceh ; ba ce 03 ; 0xc15c2 + out DX, AL ; ee ; 0xc15c5 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc15c6 vgabios.c:1077 + mov di, si ; 89 f7 ; 0xc15c9 + add di, cx ; 01 cf ; 0xc15cb + mov al, byte [es:di+037h] ; 26 8a 45 37 ; 0xc15cd + mov dx, 003cfh ; ba cf 03 ; 0xc15d1 + out DX, AL ; ee ; 0xc15d4 + inc cx ; 41 ; 0xc15d5 vgabios.c:1078 + jmp short 015bbh ; eb e3 ; 0xc15d6 + movzx di, byte [bp-010h] ; 0f b6 7e f0 ; 0xc15d8 vgabios.c:1081 + sal di, 003h ; c1 e7 03 ; 0xc15dc + cmp byte [di+047b1h], 001h ; 80 bd b1 47 01 ; 0xc15df + jne short 015ebh ; 75 05 ; 0xc15e4 + mov cx, 003b4h ; b9 b4 03 ; 0xc15e6 + jmp short 015eeh ; eb 03 ; 0xc15e9 + mov cx, 003d4h ; b9 d4 03 ; 0xc15eb + mov word [bp-018h], cx ; 89 4e e8 ; 0xc15ee + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc15f1 vgabios.c:1084 + mov al, byte [es:si+009h] ; 26 8a 44 09 ; 0xc15f4 + mov dx, 003c2h ; ba c2 03 ; 0xc15f8 + out DX, AL ; ee ; 0xc15fb + mov ax, strict word 00011h ; b8 11 00 ; 0xc15fc vgabios.c:1087 + mov dx, cx ; 89 ca ; 0xc15ff + out DX, ax ; ef ; 0xc1601 + xor cx, cx ; 31 c9 ; 0xc1602 vgabios.c:1089 + jmp short 0160bh ; eb 05 ; 0xc1604 + cmp cx, strict byte 00018h ; 83 f9 18 ; 0xc1606 + jnbe short 01621h ; 77 16 ; 0xc1609 + mov al, cl ; 88 c8 ; 0xc160b vgabios.c:1090 + mov dx, word [bp-018h] ; 8b 56 e8 ; 0xc160d + out DX, AL ; ee ; 0xc1610 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1611 vgabios.c:1091 + mov di, si ; 89 f7 ; 0xc1614 + add di, cx ; 01 cf ; 0xc1616 + inc dx ; 42 ; 0xc1618 + mov al, byte [es:di+00ah] ; 26 8a 45 0a ; 0xc1619 + out DX, AL ; ee ; 0xc161d + inc cx ; 41 ; 0xc161e vgabios.c:1092 + jmp short 01606h ; eb e5 ; 0xc161f + mov AL, strict byte 020h ; b0 20 ; 0xc1621 vgabios.c:1095 + mov dx, 003c0h ; ba c0 03 ; 0xc1623 + out DX, AL ; ee ; 0xc1626 + mov dx, word [bp-018h] ; 8b 56 e8 ; 0xc1627 vgabios.c:1096 + add dx, strict byte 00006h ; 83 c2 06 ; 0xc162a + in AL, DX ; ec ; 0xc162d + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc162e + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc1630 vgabios.c:1098 + jne short 01692h ; 75 5c ; 0xc1634 + movzx di, byte [bp-010h] ; 0f b6 7e f0 ; 0xc1636 vgabios.c:1100 + sal di, 003h ; c1 e7 03 ; 0xc163a + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc163d + jne short 01656h ; 75 12 ; 0xc1642 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc1644 vgabios.c:1102 + mov cx, 04000h ; b9 00 40 ; 0xc1648 + mov ax, 00720h ; b8 20 07 ; 0xc164b + xor di, di ; 31 ff ; 0xc164e + jcxz 01654h ; e3 02 ; 0xc1650 + rep stosw ; f3 ab ; 0xc1652 + jmp short 01692h ; eb 3c ; 0xc1654 vgabios.c:1104 + cmp byte [bp-00eh], 00dh ; 80 7e f2 0d ; 0xc1656 vgabios.c:1106 + jnc short 0166dh ; 73 11 ; 0xc165a + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc165c vgabios.c:1108 + mov cx, 04000h ; b9 00 40 ; 0xc1660 + xor ax, ax ; 31 c0 ; 0xc1663 + xor di, di ; 31 ff ; 0xc1665 + jcxz 0166bh ; e3 02 ; 0xc1667 + rep stosw ; f3 ab ; 0xc1669 + jmp short 01692h ; eb 25 ; 0xc166b vgabios.c:1110 + mov AL, strict byte 002h ; b0 02 ; 0xc166d vgabios.c:1112 + mov dx, 003c4h ; ba c4 03 ; 0xc166f + out DX, AL ; ee ; 0xc1672 + mov dx, 003c5h ; ba c5 03 ; 0xc1673 vgabios.c:1113 + in AL, DX ; ec ; 0xc1676 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1677 + mov word [bp-01eh], ax ; 89 46 e2 ; 0xc1679 + mov AL, strict byte 00fh ; b0 0f ; 0xc167c vgabios.c:1114 + out DX, AL ; ee ; 0xc167e + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc167f vgabios.c:1115 + mov cx, 08000h ; b9 00 80 ; 0xc1683 + xor ax, ax ; 31 c0 ; 0xc1686 + xor di, di ; 31 ff ; 0xc1688 + jcxz 0168eh ; e3 02 ; 0xc168a + rep stosw ; f3 ab ; 0xc168c + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc168e vgabios.c:1116 + out DX, AL ; ee ; 0xc1691 + mov di, strict word 00049h ; bf 49 00 ; 0xc1692 vgabios.c:52 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1695 + mov es, ax ; 8e c0 ; 0xc1698 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc169a + mov byte [es:di], al ; 26 88 05 ; 0xc169d + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc16a0 vgabios.c:1123 + movzx ax, byte [es:si] ; 26 0f b6 04 ; 0xc16a3 + mov di, strict word 0004ah ; bf 4a 00 ; 0xc16a7 vgabios.c:62 + mov dx, strict word 00040h ; ba 40 00 ; 0xc16aa + mov es, dx ; 8e c2 ; 0xc16ad + mov word [es:di], ax ; 26 89 05 ; 0xc16af + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc16b2 vgabios.c:60 + mov ax, word [es:si+003h] ; 26 8b 44 03 ; 0xc16b5 + mov di, strict word 0004ch ; bf 4c 00 ; 0xc16b9 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc16bc + mov word [es:di], ax ; 26 89 05 ; 0xc16be + mov di, strict word 00063h ; bf 63 00 ; 0xc16c1 vgabios.c:62 + mov ax, word [bp-018h] ; 8b 46 e8 ; 0xc16c4 + mov word [es:di], ax ; 26 89 05 ; 0xc16c7 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc16ca vgabios.c:50 + mov al, byte [es:si+001h] ; 26 8a 44 01 ; 0xc16cd + mov di, 00084h ; bf 84 00 ; 0xc16d1 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc16d4 + mov byte [es:di], al ; 26 88 05 ; 0xc16d6 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc16d9 vgabios.c:1127 + movzx ax, byte [es:si+002h] ; 26 0f b6 44 02 ; 0xc16dc + mov di, 00085h ; bf 85 00 ; 0xc16e1 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc16e4 + mov word [es:di], ax ; 26 89 05 ; 0xc16e6 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc16e9 vgabios.c:1128 + or AL, strict byte 060h ; 0c 60 ; 0xc16ec + mov di, 00087h ; bf 87 00 ; 0xc16ee vgabios.c:52 + mov byte [es:di], al ; 26 88 05 ; 0xc16f1 + mov di, 00088h ; bf 88 00 ; 0xc16f4 vgabios.c:52 + mov byte [es:di], 0f9h ; 26 c6 05 f9 ; 0xc16f7 + mov di, 0008ah ; bf 8a 00 ; 0xc16fb vgabios.c:52 + mov byte [es:di], 008h ; 26 c6 05 08 ; 0xc16fe + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc1702 vgabios.c:1134 + cmp AL, strict byte 007h ; 3c 07 ; 0xc1705 + jnbe short 0172fh ; 77 26 ; 0xc1707 + movzx di, al ; 0f b6 f8 ; 0xc1709 vgabios.c:1136 + mov al, byte [di+07ddeh] ; 8a 85 de 7d ; 0xc170c vgabios.c:50 + mov di, strict word 00065h ; bf 65 00 ; 0xc1710 vgabios.c:52 + mov byte [es:di], al ; 26 88 05 ; 0xc1713 + cmp byte [bp-00eh], 006h ; 80 7e f2 06 ; 0xc1716 vgabios.c:1137 + jne short 01721h ; 75 05 ; 0xc171a + mov dx, strict word 0003fh ; ba 3f 00 ; 0xc171c + jmp short 01724h ; eb 03 ; 0xc171f + mov dx, strict word 00030h ; ba 30 00 ; 0xc1721 + mov di, strict word 00066h ; bf 66 00 ; 0xc1724 vgabios.c:52 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1727 + mov es, ax ; 8e c0 ; 0xc172a + mov byte [es:di], dl ; 26 88 15 ; 0xc172c + movzx di, byte [bp-010h] ; 0f b6 7e f0 ; 0xc172f vgabios.c:1141 + sal di, 003h ; c1 e7 03 ; 0xc1733 + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc1736 + jne short 01746h ; 75 09 ; 0xc173b + mov dx, strict word 00007h ; ba 07 00 ; 0xc173d vgabios.c:1143 + mov ax, strict word 00006h ; b8 06 00 ; 0xc1740 + call 0114ch ; e8 06 fa ; 0xc1743 + xor cx, cx ; 31 c9 ; 0xc1746 vgabios.c:1148 + jmp short 0174fh ; eb 05 ; 0xc1748 + cmp cx, strict byte 00008h ; 83 f9 08 ; 0xc174a + jnc short 0175ah ; 73 0b ; 0xc174d + movzx ax, cl ; 0f b6 c1 ; 0xc174f vgabios.c:1149 + xor dx, dx ; 31 d2 ; 0xc1752 + call 01242h ; e8 eb fa ; 0xc1754 + inc cx ; 41 ; 0xc1757 + jmp short 0174ah ; eb f0 ; 0xc1758 + xor ax, ax ; 31 c0 ; 0xc175a vgabios.c:1152 + call 012cbh ; e8 6c fb ; 0xc175c + movzx di, byte [bp-010h] ; 0f b6 7e f0 ; 0xc175f vgabios.c:1155 + sal di, 003h ; c1 e7 03 ; 0xc1763 + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc1766 + jne near 01850h ; 0f 85 e1 00 ; 0xc176b + mov es, [bp-014h] ; 8e 46 ec ; 0xc176f vgabios.c:1157 + mov di, word [es:bx+008h] ; 26 8b 7f 08 ; 0xc1772 + mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xc1776 + mov word [bp-012h], ax ; 89 46 ee ; 0xc177a + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc177d vgabios.c:1159 + mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xc1780 + cmp AL, strict byte 00eh ; 3c 0e ; 0xc1784 + je short 017a8h ; 74 20 ; 0xc1786 + cmp AL, strict byte 008h ; 3c 08 ; 0xc1788 + jne short 017d2h ; 75 46 ; 0xc178a + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc178c vgabios.c:1161 + movzx ax, byte [es:si+002h] ; 26 0f b6 44 02 ; 0xc178f + push ax ; 50 ; 0xc1794 + push dword 000000000h ; 66 6a 00 ; 0xc1795 + mov cx, 00100h ; b9 00 01 ; 0xc1798 + mov bx, 0556dh ; bb 6d 55 ; 0xc179b + mov dx, 0c000h ; ba 00 c0 ; 0xc179e + xor ax, ax ; 31 c0 ; 0xc17a1 + call 02c0ah ; e8 64 14 ; 0xc17a3 + jmp short 017f4h ; eb 4c ; 0xc17a6 vgabios.c:1162 + xor ah, ah ; 30 e4 ; 0xc17a8 vgabios.c:1164 + push ax ; 50 ; 0xc17aa + push dword 000000000h ; 66 6a 00 ; 0xc17ab + mov cx, 00100h ; b9 00 01 ; 0xc17ae + mov bx, 05d6dh ; bb 6d 5d ; 0xc17b1 + mov dx, 0c000h ; ba 00 c0 ; 0xc17b4 + xor al, al ; 30 c0 ; 0xc17b7 + call 02c0ah ; e8 4e 14 ; 0xc17b9 + cmp byte [bp-00eh], 007h ; 80 7e f2 07 ; 0xc17bc vgabios.c:1165 + jne short 017f4h ; 75 32 ; 0xc17c0 + mov cx, strict word 0000eh ; b9 0e 00 ; 0xc17c2 vgabios.c:1166 + xor bx, bx ; 31 db ; 0xc17c5 + mov dx, 07b6dh ; ba 6d 7b ; 0xc17c7 + mov ax, 0c000h ; b8 00 c0 ; 0xc17ca + call 02b95h ; e8 c5 13 ; 0xc17cd + jmp short 017f4h ; eb 22 ; 0xc17d0 vgabios.c:1167 + xor ah, ah ; 30 e4 ; 0xc17d2 vgabios.c:1169 + push ax ; 50 ; 0xc17d4 + push dword 000000000h ; 66 6a 00 ; 0xc17d5 + mov cx, 00100h ; b9 00 01 ; 0xc17d8 + mov bx, 06b6dh ; bb 6d 6b ; 0xc17db + mov dx, 0c000h ; ba 00 c0 ; 0xc17de + xor al, al ; 30 c0 ; 0xc17e1 + call 02c0ah ; e8 24 14 ; 0xc17e3 + mov cx, strict word 00010h ; b9 10 00 ; 0xc17e6 vgabios.c:1170 + xor bx, bx ; 31 db ; 0xc17e9 + mov dx, 07c9ah ; ba 9a 7c ; 0xc17eb + mov ax, 0c000h ; b8 00 c0 ; 0xc17ee + call 02b95h ; e8 a1 13 ; 0xc17f1 + cmp word [bp-012h], strict byte 00000h ; 83 7e ee 00 ; 0xc17f4 vgabios.c:1172 + jne short 017feh ; 75 04 ; 0xc17f8 + test di, di ; 85 ff ; 0xc17fa + je short 01848h ; 74 4a ; 0xc17fc + xor cx, cx ; 31 c9 ; 0xc17fe vgabios.c:1177 + mov es, [bp-012h] ; 8e 46 ee ; 0xc1800 vgabios.c:1179 + mov bx, di ; 89 fb ; 0xc1803 + add bx, cx ; 01 cb ; 0xc1805 + mov al, byte [es:bx+00bh] ; 26 8a 47 0b ; 0xc1807 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc180b + je short 01817h ; 74 08 ; 0xc180d + cmp al, byte [bp-00eh] ; 3a 46 f2 ; 0xc180f vgabios.c:1181 + je short 01817h ; 74 03 ; 0xc1812 + inc cx ; 41 ; 0xc1814 vgabios.c:1183 + jmp short 01800h ; eb e9 ; 0xc1815 vgabios.c:1184 + mov es, [bp-012h] ; 8e 46 ee ; 0xc1817 vgabios.c:1186 + mov bx, di ; 89 fb ; 0xc181a + add bx, cx ; 01 cb ; 0xc181c + mov al, byte [es:bx+00bh] ; 26 8a 47 0b ; 0xc181e + cmp al, byte [bp-00eh] ; 3a 46 f2 ; 0xc1822 + jne short 01848h ; 75 21 ; 0xc1825 + movzx ax, byte [es:di] ; 26 0f b6 05 ; 0xc1827 vgabios.c:1191 + push ax ; 50 ; 0xc182b + movzx ax, byte [es:di+001h] ; 26 0f b6 45 01 ; 0xc182c + push ax ; 50 ; 0xc1831 + push word [es:di+004h] ; 26 ff 75 04 ; 0xc1832 + mov cx, word [es:di+002h] ; 26 8b 4d 02 ; 0xc1836 + mov bx, word [es:di+006h] ; 26 8b 5d 06 ; 0xc183a + mov dx, word [es:di+008h] ; 26 8b 55 08 ; 0xc183e + mov ax, strict word 00010h ; b8 10 00 ; 0xc1842 + call 02c0ah ; e8 c2 13 ; 0xc1845 + xor bl, bl ; 30 db ; 0xc1848 vgabios.c:1195 + mov AL, strict byte 003h ; b0 03 ; 0xc184a + mov AH, strict byte 011h ; b4 11 ; 0xc184c + int 06dh ; cd 6d ; 0xc184e + mov bx, 0596dh ; bb 6d 59 ; 0xc1850 vgabios.c:1199 + mov cx, ds ; 8c d9 ; 0xc1853 + mov ax, strict word 0001fh ; b8 1f 00 ; 0xc1855 + call 009f0h ; e8 95 f1 ; 0xc1858 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc185b vgabios.c:1201 + mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xc185e + cmp AL, strict byte 010h ; 3c 10 ; 0xc1862 + je short 01880h ; 74 1a ; 0xc1864 + cmp AL, strict byte 00eh ; 3c 0e ; 0xc1866 + je short 0187bh ; 74 11 ; 0xc1868 + cmp AL, strict byte 008h ; 3c 08 ; 0xc186a + jne short 01885h ; 75 17 ; 0xc186c + mov bx, 0556dh ; bb 6d 55 ; 0xc186e vgabios.c:1203 + mov cx, ds ; 8c d9 ; 0xc1871 + mov ax, strict word 00043h ; b8 43 00 ; 0xc1873 + call 009f0h ; e8 77 f1 ; 0xc1876 + jmp short 01885h ; eb 0a ; 0xc1879 vgabios.c:1204 + mov bx, 05d6dh ; bb 6d 5d ; 0xc187b vgabios.c:1206 + jmp short 01871h ; eb f1 ; 0xc187e + mov bx, 06b6dh ; bb 6d 6b ; 0xc1880 vgabios.c:1209 + jmp short 01871h ; eb ec ; 0xc1883 + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc1885 vgabios.c:1212 + pop di ; 5f ; 0xc1888 + pop si ; 5e ; 0xc1889 + pop dx ; 5a ; 0xc188a + pop cx ; 59 ; 0xc188b + pop bx ; 5b ; 0xc188c + pop bp ; 5d ; 0xc188d + retn ; c3 ; 0xc188e + ; disGetNextSymbol 0xc188f LB 0x2a2a -> off=0x0 cb=0000000000000075 uValue=00000000000c188f 'vgamem_copy_pl4' +vgamem_copy_pl4: ; 0xc188f LB 0x75 + push bp ; 55 ; 0xc188f vgabios.c:1215 + mov bp, sp ; 89 e5 ; 0xc1890 + push si ; 56 ; 0xc1892 + push di ; 57 ; 0xc1893 + push ax ; 50 ; 0xc1894 + push ax ; 50 ; 0xc1895 + mov bh, cl ; 88 cf ; 0xc1896 + movzx di, dl ; 0f b6 fa ; 0xc1898 vgabios.c:1221 + movzx cx, byte [bp+006h] ; 0f b6 4e 06 ; 0xc189b + imul di, cx ; 0f af f9 ; 0xc189f + movzx si, byte [bp+004h] ; 0f b6 76 04 ; 0xc18a2 + imul di, si ; 0f af fe ; 0xc18a6 + xor ah, ah ; 30 e4 ; 0xc18a9 + add di, ax ; 01 c7 ; 0xc18ab + mov word [bp-008h], di ; 89 7e f8 ; 0xc18ad + movzx di, bl ; 0f b6 fb ; 0xc18b0 vgabios.c:1222 + imul cx, di ; 0f af cf ; 0xc18b3 + imul cx, si ; 0f af ce ; 0xc18b6 + add cx, ax ; 01 c1 ; 0xc18b9 + mov word [bp-006h], cx ; 89 4e fa ; 0xc18bb + mov ax, 00105h ; b8 05 01 ; 0xc18be vgabios.c:1223 + mov dx, 003ceh ; ba ce 03 ; 0xc18c1 + out DX, ax ; ef ; 0xc18c4 + xor bl, bl ; 30 db ; 0xc18c5 vgabios.c:1224 + cmp bl, byte [bp+006h] ; 3a 5e 06 ; 0xc18c7 + jnc short 018f4h ; 73 28 ; 0xc18ca + movzx cx, bh ; 0f b6 cf ; 0xc18cc vgabios.c:1226 + movzx si, bl ; 0f b6 f3 ; 0xc18cf + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc18d2 + imul ax, si ; 0f af c6 ; 0xc18d6 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc18d9 + add si, ax ; 01 c6 ; 0xc18dc + mov di, word [bp-006h] ; 8b 7e fa ; 0xc18de + add di, ax ; 01 c7 ; 0xc18e1 + mov dx, 0a000h ; ba 00 a0 ; 0xc18e3 + mov es, dx ; 8e c2 ; 0xc18e6 + jcxz 018f0h ; e3 06 ; 0xc18e8 + push DS ; 1e ; 0xc18ea + mov ds, dx ; 8e da ; 0xc18eb + rep movsb ; f3 a4 ; 0xc18ed + pop DS ; 1f ; 0xc18ef + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc18f0 vgabios.c:1227 + jmp short 018c7h ; eb d3 ; 0xc18f2 + mov ax, strict word 00005h ; b8 05 00 ; 0xc18f4 vgabios.c:1228 + mov dx, 003ceh ; ba ce 03 ; 0xc18f7 + out DX, ax ; ef ; 0xc18fa + lea sp, [bp-004h] ; 8d 66 fc ; 0xc18fb vgabios.c:1229 + pop di ; 5f ; 0xc18fe + pop si ; 5e ; 0xc18ff + pop bp ; 5d ; 0xc1900 + retn 00004h ; c2 04 00 ; 0xc1901 + ; disGetNextSymbol 0xc1904 LB 0x29b5 -> off=0x0 cb=0000000000000060 uValue=00000000000c1904 'vgamem_fill_pl4' +vgamem_fill_pl4: ; 0xc1904 LB 0x60 + push bp ; 55 ; 0xc1904 vgabios.c:1232 + mov bp, sp ; 89 e5 ; 0xc1905 + push di ; 57 ; 0xc1907 + push ax ; 50 ; 0xc1908 + push ax ; 50 ; 0xc1909 + mov byte [bp-004h], bl ; 88 5e fc ; 0xc190a + mov bh, cl ; 88 cf ; 0xc190d + movzx cx, dl ; 0f b6 ca ; 0xc190f vgabios.c:1238 + movzx dx, byte [bp+004h] ; 0f b6 56 04 ; 0xc1912 + imul cx, dx ; 0f af ca ; 0xc1916 + movzx dx, bh ; 0f b6 d7 ; 0xc1919 + imul dx, cx ; 0f af d1 ; 0xc191c + xor ah, ah ; 30 e4 ; 0xc191f + add dx, ax ; 01 c2 ; 0xc1921 + mov word [bp-006h], dx ; 89 56 fa ; 0xc1923 + mov ax, 00205h ; b8 05 02 ; 0xc1926 vgabios.c:1239 + mov dx, 003ceh ; ba ce 03 ; 0xc1929 + out DX, ax ; ef ; 0xc192c + xor bl, bl ; 30 db ; 0xc192d vgabios.c:1240 + cmp bl, byte [bp+004h] ; 3a 5e 04 ; 0xc192f + jnc short 01955h ; 73 21 ; 0xc1932 + movzx cx, byte [bp-004h] ; 0f b6 4e fc ; 0xc1934 vgabios.c:1242 + movzx ax, byte [bp+006h] ; 0f b6 46 06 ; 0xc1938 + movzx dx, bl ; 0f b6 d3 ; 0xc193c + movzx di, bh ; 0f b6 ff ; 0xc193f + imul di, dx ; 0f af fa ; 0xc1942 + add di, word [bp-006h] ; 03 7e fa ; 0xc1945 + mov dx, 0a000h ; ba 00 a0 ; 0xc1948 + mov es, dx ; 8e c2 ; 0xc194b + jcxz 01951h ; e3 02 ; 0xc194d + rep stosb ; f3 aa ; 0xc194f + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc1951 vgabios.c:1243 + jmp short 0192fh ; eb da ; 0xc1953 + mov ax, strict word 00005h ; b8 05 00 ; 0xc1955 vgabios.c:1244 + mov dx, 003ceh ; ba ce 03 ; 0xc1958 + out DX, ax ; ef ; 0xc195b + lea sp, [bp-002h] ; 8d 66 fe ; 0xc195c vgabios.c:1245 + pop di ; 5f ; 0xc195f + pop bp ; 5d ; 0xc1960 + retn 00004h ; c2 04 00 ; 0xc1961 + ; disGetNextSymbol 0xc1964 LB 0x2955 -> off=0x0 cb=00000000000000a3 uValue=00000000000c1964 'vgamem_copy_cga' +vgamem_copy_cga: ; 0xc1964 LB 0xa3 + push bp ; 55 ; 0xc1964 vgabios.c:1248 + mov bp, sp ; 89 e5 ; 0xc1965 + push si ; 56 ; 0xc1967 + push di ; 57 ; 0xc1968 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc1969 + mov dh, bl ; 88 de ; 0xc196c + mov byte [bp-006h], cl ; 88 4e fa ; 0xc196e + movzx di, dl ; 0f b6 fa ; 0xc1971 vgabios.c:1254 + movzx si, byte [bp+006h] ; 0f b6 76 06 ; 0xc1974 + imul di, si ; 0f af fe ; 0xc1978 + movzx bx, byte [bp+004h] ; 0f b6 5e 04 ; 0xc197b + imul di, bx ; 0f af fb ; 0xc197f + sar di, 1 ; d1 ff ; 0xc1982 + xor ah, ah ; 30 e4 ; 0xc1984 + add di, ax ; 01 c7 ; 0xc1986 + mov word [bp-00ch], di ; 89 7e f4 ; 0xc1988 + movzx dx, dh ; 0f b6 d6 ; 0xc198b vgabios.c:1255 + imul dx, si ; 0f af d6 ; 0xc198e + imul dx, bx ; 0f af d3 ; 0xc1991 + sar dx, 1 ; d1 fa ; 0xc1994 + add dx, ax ; 01 c2 ; 0xc1996 + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc1998 + mov byte [bp-008h], ah ; 88 66 f8 ; 0xc199b vgabios.c:1256 + movzx ax, byte [bp+006h] ; 0f b6 46 06 ; 0xc199e + cwd ; 99 ; 0xc19a2 + db 02bh, 0c2h + ; sub ax, dx ; 2b c2 ; 0xc19a3 + sar ax, 1 ; d1 f8 ; 0xc19a5 + movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xc19a7 + cmp bx, ax ; 39 c3 ; 0xc19ab + jnl short 019feh ; 7d 4f ; 0xc19ad + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc19af vgabios.c:1258 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc19b3 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc19b6 + imul bx, ax ; 0f af d8 ; 0xc19ba + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc19bd + add si, bx ; 01 de ; 0xc19c0 + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc19c2 + add di, bx ; 01 df ; 0xc19c5 + mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xc19c7 + mov dx, 0b800h ; ba 00 b8 ; 0xc19ca + mov es, dx ; 8e c2 ; 0xc19cd + jcxz 019d7h ; e3 06 ; 0xc19cf + push DS ; 1e ; 0xc19d1 + mov ds, dx ; 8e da ; 0xc19d2 + rep movsb ; f3 a4 ; 0xc19d4 + pop DS ; 1f ; 0xc19d6 + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc19d7 vgabios.c:1259 + add si, 02000h ; 81 c6 00 20 ; 0xc19da + add si, bx ; 01 de ; 0xc19de + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc19e0 + add di, 02000h ; 81 c7 00 20 ; 0xc19e3 + add di, bx ; 01 df ; 0xc19e7 + mov cx, word [bp-00eh] ; 8b 4e f2 ; 0xc19e9 + mov dx, 0b800h ; ba 00 b8 ; 0xc19ec + mov es, dx ; 8e c2 ; 0xc19ef + jcxz 019f9h ; e3 06 ; 0xc19f1 + push DS ; 1e ; 0xc19f3 + mov ds, dx ; 8e da ; 0xc19f4 + rep movsb ; f3 a4 ; 0xc19f6 + pop DS ; 1f ; 0xc19f8 + inc byte [bp-008h] ; fe 46 f8 ; 0xc19f9 vgabios.c:1260 + jmp short 0199eh ; eb a0 ; 0xc19fc + lea sp, [bp-004h] ; 8d 66 fc ; 0xc19fe vgabios.c:1261 + pop di ; 5f ; 0xc1a01 + pop si ; 5e ; 0xc1a02 + pop bp ; 5d ; 0xc1a03 + retn 00004h ; c2 04 00 ; 0xc1a04 + ; disGetNextSymbol 0xc1a07 LB 0x28b2 -> off=0x0 cb=0000000000000081 uValue=00000000000c1a07 'vgamem_fill_cga' +vgamem_fill_cga: ; 0xc1a07 LB 0x81 + push bp ; 55 ; 0xc1a07 vgabios.c:1264 + mov bp, sp ; 89 e5 ; 0xc1a08 + push si ; 56 ; 0xc1a0a + push di ; 57 ; 0xc1a0b + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc1a0c + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc1a0f + mov byte [bp-008h], cl ; 88 4e f8 ; 0xc1a12 + movzx bx, dl ; 0f b6 da ; 0xc1a15 vgabios.c:1270 + movzx dx, byte [bp+004h] ; 0f b6 56 04 ; 0xc1a18 + imul bx, dx ; 0f af da ; 0xc1a1c + movzx dx, cl ; 0f b6 d1 ; 0xc1a1f + imul dx, bx ; 0f af d3 ; 0xc1a22 + sar dx, 1 ; d1 fa ; 0xc1a25 + xor ah, ah ; 30 e4 ; 0xc1a27 + add dx, ax ; 01 c2 ; 0xc1a29 + mov word [bp-00ch], dx ; 89 56 f4 ; 0xc1a2b + mov byte [bp-006h], ah ; 88 66 fa ; 0xc1a2e vgabios.c:1271 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1a31 + cwd ; 99 ; 0xc1a35 + db 02bh, 0c2h + ; sub ax, dx ; 2b c2 ; 0xc1a36 + sar ax, 1 ; d1 f8 ; 0xc1a38 + movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xc1a3a + cmp dx, ax ; 39 c2 ; 0xc1a3e + jnl short 01a7fh ; 7d 3d ; 0xc1a40 + movzx si, byte [bp-00ah] ; 0f b6 76 f6 ; 0xc1a42 vgabios.c:1273 + movzx bx, byte [bp+006h] ; 0f b6 5e 06 ; 0xc1a46 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc1a4a + imul dx, ax ; 0f af d0 ; 0xc1a4e + mov word [bp-00eh], dx ; 89 56 f2 ; 0xc1a51 + mov di, word [bp-00ch] ; 8b 7e f4 ; 0xc1a54 + add di, dx ; 01 d7 ; 0xc1a57 + mov cx, si ; 89 f1 ; 0xc1a59 + mov ax, bx ; 89 d8 ; 0xc1a5b + mov dx, 0b800h ; ba 00 b8 ; 0xc1a5d + mov es, dx ; 8e c2 ; 0xc1a60 + jcxz 01a66h ; e3 02 ; 0xc1a62 + rep stosb ; f3 aa ; 0xc1a64 + mov di, word [bp-00ch] ; 8b 7e f4 ; 0xc1a66 vgabios.c:1274 + add di, 02000h ; 81 c7 00 20 ; 0xc1a69 + add di, word [bp-00eh] ; 03 7e f2 ; 0xc1a6d + mov cx, si ; 89 f1 ; 0xc1a70 + mov ax, bx ; 89 d8 ; 0xc1a72 + mov es, dx ; 8e c2 ; 0xc1a74 + jcxz 01a7ah ; e3 02 ; 0xc1a76 + rep stosb ; f3 aa ; 0xc1a78 + inc byte [bp-006h] ; fe 46 fa ; 0xc1a7a vgabios.c:1275 + jmp short 01a31h ; eb b2 ; 0xc1a7d + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1a7f vgabios.c:1276 + pop di ; 5f ; 0xc1a82 + pop si ; 5e ; 0xc1a83 + pop bp ; 5d ; 0xc1a84 + retn 00004h ; c2 04 00 ; 0xc1a85 + ; disGetNextSymbol 0xc1a88 LB 0x2831 -> off=0x0 cb=0000000000000079 uValue=00000000000c1a88 'vgamem_copy_linear' +vgamem_copy_linear: ; 0xc1a88 LB 0x79 + push bp ; 55 ; 0xc1a88 vgabios.c:1279 + mov bp, sp ; 89 e5 ; 0xc1a89 + push si ; 56 ; 0xc1a8b + push di ; 57 ; 0xc1a8c + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc1a8d + mov ah, al ; 88 c4 ; 0xc1a90 + mov al, bl ; 88 d8 ; 0xc1a92 + mov bx, cx ; 89 cb ; 0xc1a94 + xor dh, dh ; 30 f6 ; 0xc1a96 vgabios.c:1285 + movzx di, byte [bp+006h] ; 0f b6 7e 06 ; 0xc1a98 + imul dx, di ; 0f af d7 ; 0xc1a9c + imul dx, word [bp+004h] ; 0f af 56 04 ; 0xc1a9f + movzx si, ah ; 0f b6 f4 ; 0xc1aa3 + add dx, si ; 01 f2 ; 0xc1aa6 + sal dx, 003h ; c1 e2 03 ; 0xc1aa8 + mov word [bp-008h], dx ; 89 56 f8 ; 0xc1aab + xor ah, ah ; 30 e4 ; 0xc1aae vgabios.c:1286 + imul ax, di ; 0f af c7 ; 0xc1ab0 + imul ax, word [bp+004h] ; 0f af 46 04 ; 0xc1ab3 + add si, ax ; 01 c6 ; 0xc1ab7 + sal si, 003h ; c1 e6 03 ; 0xc1ab9 + mov word [bp-00ah], si ; 89 76 f6 ; 0xc1abc + sal bx, 003h ; c1 e3 03 ; 0xc1abf vgabios.c:1287 + sal word [bp+004h], 003h ; c1 66 04 03 ; 0xc1ac2 vgabios.c:1288 + mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xc1ac6 vgabios.c:1289 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1aca + cmp al, byte [bp+006h] ; 3a 46 06 ; 0xc1acd + jnc short 01af8h ; 73 26 ; 0xc1ad0 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc1ad2 vgabios.c:1291 + imul ax, word [bp+004h] ; 0f af 46 04 ; 0xc1ad6 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc1ada + add si, ax ; 01 c6 ; 0xc1add + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc1adf + add di, ax ; 01 c7 ; 0xc1ae2 + mov cx, bx ; 89 d9 ; 0xc1ae4 + mov dx, 0a000h ; ba 00 a0 ; 0xc1ae6 + mov es, dx ; 8e c2 ; 0xc1ae9 + jcxz 01af3h ; e3 06 ; 0xc1aeb + push DS ; 1e ; 0xc1aed + mov ds, dx ; 8e da ; 0xc1aee + rep movsb ; f3 a4 ; 0xc1af0 + pop DS ; 1f ; 0xc1af2 + inc byte [bp-006h] ; fe 46 fa ; 0xc1af3 vgabios.c:1292 + jmp short 01acah ; eb d2 ; 0xc1af6 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1af8 vgabios.c:1293 + pop di ; 5f ; 0xc1afb + pop si ; 5e ; 0xc1afc + pop bp ; 5d ; 0xc1afd + retn 00004h ; c2 04 00 ; 0xc1afe + ; disGetNextSymbol 0xc1b01 LB 0x27b8 -> off=0x0 cb=000000000000005c uValue=00000000000c1b01 'vgamem_fill_linear' +vgamem_fill_linear: ; 0xc1b01 LB 0x5c + push bp ; 55 ; 0xc1b01 vgabios.c:1296 + mov bp, sp ; 89 e5 ; 0xc1b02 + push si ; 56 ; 0xc1b04 + push di ; 57 ; 0xc1b05 + push ax ; 50 ; 0xc1b06 + push ax ; 50 ; 0xc1b07 + mov si, bx ; 89 de ; 0xc1b08 + mov bx, cx ; 89 cb ; 0xc1b0a + xor dh, dh ; 30 f6 ; 0xc1b0c vgabios.c:1302 + movzx di, byte [bp+004h] ; 0f b6 7e 04 ; 0xc1b0e + imul dx, di ; 0f af d7 ; 0xc1b12 + imul dx, cx ; 0f af d1 ; 0xc1b15 + xor ah, ah ; 30 e4 ; 0xc1b18 + add ax, dx ; 01 d0 ; 0xc1b1a + sal ax, 003h ; c1 e0 03 ; 0xc1b1c + mov word [bp-008h], ax ; 89 46 f8 ; 0xc1b1f + sal si, 003h ; c1 e6 03 ; 0xc1b22 vgabios.c:1303 + sal bx, 003h ; c1 e3 03 ; 0xc1b25 vgabios.c:1304 + mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xc1b28 vgabios.c:1305 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1b2c + cmp al, byte [bp+004h] ; 3a 46 04 ; 0xc1b2f + jnc short 01b54h ; 73 20 ; 0xc1b32 + movzx ax, byte [bp+006h] ; 0f b6 46 06 ; 0xc1b34 vgabios.c:1307 + movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xc1b38 + imul dx, bx ; 0f af d3 ; 0xc1b3c + mov di, word [bp-008h] ; 8b 7e f8 ; 0xc1b3f + add di, dx ; 01 d7 ; 0xc1b42 + mov cx, si ; 89 f1 ; 0xc1b44 + mov dx, 0a000h ; ba 00 a0 ; 0xc1b46 + mov es, dx ; 8e c2 ; 0xc1b49 + jcxz 01b4fh ; e3 02 ; 0xc1b4b + rep stosb ; f3 aa ; 0xc1b4d + inc byte [bp-006h] ; fe 46 fa ; 0xc1b4f vgabios.c:1308 + jmp short 01b2ch ; eb d8 ; 0xc1b52 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1b54 vgabios.c:1309 + pop di ; 5f ; 0xc1b57 + pop si ; 5e ; 0xc1b58 + pop bp ; 5d ; 0xc1b59 + retn 00004h ; c2 04 00 ; 0xc1b5a + ; disGetNextSymbol 0xc1b5d LB 0x275c -> off=0x0 cb=0000000000000628 uValue=00000000000c1b5d 'biosfn_scroll' +biosfn_scroll: ; 0xc1b5d LB 0x628 + push bp ; 55 ; 0xc1b5d vgabios.c:1312 + mov bp, sp ; 89 e5 ; 0xc1b5e + push si ; 56 ; 0xc1b60 + push di ; 57 ; 0xc1b61 + sub sp, strict byte 00018h ; 83 ec 18 ; 0xc1b62 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc1b65 + mov byte [bp-012h], dl ; 88 56 ee ; 0xc1b68 + mov byte [bp-00ch], bl ; 88 5e f4 ; 0xc1b6b + mov byte [bp-010h], cl ; 88 4e f0 ; 0xc1b6e + mov dh, byte [bp+006h] ; 8a 76 06 ; 0xc1b71 + cmp bl, byte [bp+004h] ; 3a 5e 04 ; 0xc1b74 vgabios.c:1321 + jnbe near 0217ch ; 0f 87 01 06 ; 0xc1b77 + cmp dh, cl ; 38 ce ; 0xc1b7b vgabios.c:1322 + jc near 0217ch ; 0f 82 fb 05 ; 0xc1b7d + mov bx, strict word 00049h ; bb 49 00 ; 0xc1b81 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1b84 + mov es, ax ; 8e c0 ; 0xc1b87 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1b89 + xor ah, ah ; 30 e4 ; 0xc1b8c vgabios.c:1326 + call 035edh ; e8 5c 1a ; 0xc1b8e + mov byte [bp-006h], al ; 88 46 fa ; 0xc1b91 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc1b94 vgabios.c:1327 + je near 0217ch ; 0f 84 e2 05 ; 0xc1b96 + mov bx, 00084h ; bb 84 00 ; 0xc1b9a vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1b9d + mov es, ax ; 8e c0 ; 0xc1ba0 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1ba2 + movzx cx, al ; 0f b6 c8 ; 0xc1ba5 vgabios.c:48 + inc cx ; 41 ; 0xc1ba8 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1ba9 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc1bac + mov word [bp-014h], ax ; 89 46 ec ; 0xc1baf vgabios.c:58 + cmp byte [bp+008h], 0ffh ; 80 7e 08 ff ; 0xc1bb2 vgabios.c:1334 + jne short 01bc1h ; 75 09 ; 0xc1bb6 + mov bx, strict word 00062h ; bb 62 00 ; 0xc1bb8 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1bbb + mov byte [bp+008h], al ; 88 46 08 ; 0xc1bbe vgabios.c:48 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1bc1 vgabios.c:1337 + cmp ax, cx ; 39 c8 ; 0xc1bc5 + jc short 01bd0h ; 72 07 ; 0xc1bc7 + mov al, cl ; 88 c8 ; 0xc1bc9 + db 0feh, 0c8h + ; dec al ; fe c8 ; 0xc1bcb + mov byte [bp+004h], al ; 88 46 04 ; 0xc1bcd + movzx ax, dh ; 0f b6 c6 ; 0xc1bd0 vgabios.c:1338 + cmp ax, word [bp-014h] ; 3b 46 ec ; 0xc1bd3 + jc short 01bddh ; 72 05 ; 0xc1bd6 + mov dh, byte [bp-014h] ; 8a 76 ec ; 0xc1bd8 + db 0feh, 0ceh + ; dec dh ; fe ce ; 0xc1bdb + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc1bdd vgabios.c:1339 + cmp ax, cx ; 39 c8 ; 0xc1be1 + jbe short 01be9h ; 76 04 ; 0xc1be3 + mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xc1be5 + mov al, dh ; 88 f0 ; 0xc1be9 vgabios.c:1340 + sub al, byte [bp-010h] ; 2a 46 f0 ; 0xc1beb + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc1bee + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc1bf0 + movzx di, byte [bp-006h] ; 0f b6 7e fa ; 0xc1bf3 vgabios.c:1342 + mov bx, di ; 89 fb ; 0xc1bf7 + sal bx, 003h ; c1 e3 03 ; 0xc1bf9 + mov ax, word [bp-014h] ; 8b 46 ec ; 0xc1bfc + dec ax ; 48 ; 0xc1bff + mov word [bp-018h], ax ; 89 46 e8 ; 0xc1c00 + mov ax, cx ; 89 c8 ; 0xc1c03 + dec ax ; 48 ; 0xc1c05 + mov word [bp-016h], ax ; 89 46 ea ; 0xc1c06 + mov ax, word [bp-014h] ; 8b 46 ec ; 0xc1c09 + imul ax, cx ; 0f af c1 ; 0xc1c0c + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc1c0f + jne near 01db3h ; 0f 85 9b 01 ; 0xc1c14 + mov cx, ax ; 89 c1 ; 0xc1c18 vgabios.c:1345 + add cx, ax ; 01 c1 ; 0xc1c1a + or cl, 0ffh ; 80 c9 ff ; 0xc1c1c + movzx si, byte [bp+008h] ; 0f b6 76 08 ; 0xc1c1f + inc cx ; 41 ; 0xc1c23 + imul cx, si ; 0f af ce ; 0xc1c24 + mov word [bp-01ch], cx ; 89 4e e4 ; 0xc1c27 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1c2a vgabios.c:1350 + jne short 01c6bh ; 75 3b ; 0xc1c2e + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc1c30 + jne short 01c6bh ; 75 35 ; 0xc1c34 + cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xc1c36 + jne short 01c6bh ; 75 2f ; 0xc1c3a + movzx cx, byte [bp+004h] ; 0f b6 4e 04 ; 0xc1c3c + cmp cx, word [bp-016h] ; 3b 4e ea ; 0xc1c40 + jne short 01c6bh ; 75 26 ; 0xc1c43 + movzx dx, dh ; 0f b6 d6 ; 0xc1c45 + cmp dx, word [bp-018h] ; 3b 56 e8 ; 0xc1c48 + jne short 01c6bh ; 75 1e ; 0xc1c4b + movzx dx, byte [bp-012h] ; 0f b6 56 ee ; 0xc1c4d vgabios.c:1352 + sal dx, 008h ; c1 e2 08 ; 0xc1c51 + add dx, strict byte 00020h ; 83 c2 20 ; 0xc1c54 + mov bx, word [bx+047b3h] ; 8b 9f b3 47 ; 0xc1c57 + mov cx, ax ; 89 c1 ; 0xc1c5b + mov ax, dx ; 89 d0 ; 0xc1c5d + mov di, word [bp-01ch] ; 8b 7e e4 ; 0xc1c5f + mov es, bx ; 8e c3 ; 0xc1c62 + jcxz 01c68h ; e3 02 ; 0xc1c64 + rep stosw ; f3 ab ; 0xc1c66 + jmp near 0217ch ; e9 11 05 ; 0xc1c68 vgabios.c:1354 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc1c6b vgabios.c:1356 + jne near 01d08h ; 0f 85 95 00 ; 0xc1c6f + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc1c73 vgabios.c:1357 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc1c77 + movzx dx, byte [bp+004h] ; 0f b6 56 04 ; 0xc1c7a + cmp dx, word [bp-01ah] ; 3b 56 e6 ; 0xc1c7e + jc near 0217ch ; 0f 82 f7 04 ; 0xc1c81 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc1c85 vgabios.c:1359 + add ax, word [bp-01ah] ; 03 46 e6 ; 0xc1c89 + cmp ax, dx ; 39 d0 ; 0xc1c8c + jnbe short 01c96h ; 77 06 ; 0xc1c8e + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1c90 + jne short 01cc9h ; 75 33 ; 0xc1c94 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc1c96 vgabios.c:1360 + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc1c9a + sal ax, 008h ; c1 e0 08 ; 0xc1c9e + add ax, strict word 00020h ; 05 20 00 ; 0xc1ca1 + mov bx, word [bp-01ah] ; 8b 5e e6 ; 0xc1ca4 + imul bx, word [bp-014h] ; 0f af 5e ec ; 0xc1ca7 + movzx dx, byte [bp-010h] ; 0f b6 56 f0 ; 0xc1cab + add dx, bx ; 01 da ; 0xc1caf + add dx, dx ; 01 d2 ; 0xc1cb1 + mov di, word [bp-01ch] ; 8b 7e e4 ; 0xc1cb3 + add di, dx ; 01 d7 ; 0xc1cb6 + movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xc1cb8 + sal bx, 003h ; c1 e3 03 ; 0xc1cbc + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1cbf + jcxz 01cc7h ; e3 02 ; 0xc1cc3 + rep stosw ; f3 ab ; 0xc1cc5 + jmp short 01d02h ; eb 39 ; 0xc1cc7 vgabios.c:1361 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc1cc9 vgabios.c:1362 + mov si, ax ; 89 c6 ; 0xc1ccd + imul si, word [bp-014h] ; 0f af 76 ec ; 0xc1ccf + movzx dx, byte [bp-010h] ; 0f b6 56 f0 ; 0xc1cd3 + add si, dx ; 01 d6 ; 0xc1cd7 + add si, si ; 01 f6 ; 0xc1cd9 + movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xc1cdb + sal bx, 003h ; c1 e3 03 ; 0xc1cdf + mov ax, word [bx+047b3h] ; 8b 87 b3 47 ; 0xc1ce2 + mov bx, word [bp-01ah] ; 8b 5e e6 ; 0xc1ce6 + imul bx, word [bp-014h] ; 0f af 5e ec ; 0xc1ce9 + mov di, dx ; 89 d7 ; 0xc1ced + add di, bx ; 01 df ; 0xc1cef + add di, di ; 01 ff ; 0xc1cf1 + add di, word [bp-01ch] ; 03 7e e4 ; 0xc1cf3 + mov dx, ax ; 89 c2 ; 0xc1cf6 + mov es, ax ; 8e c0 ; 0xc1cf8 + jcxz 01d02h ; e3 06 ; 0xc1cfa + push DS ; 1e ; 0xc1cfc + mov ds, dx ; 8e da ; 0xc1cfd + rep movsw ; f3 a5 ; 0xc1cff + pop DS ; 1f ; 0xc1d01 + inc word [bp-01ah] ; ff 46 e6 ; 0xc1d02 vgabios.c:1363 + jmp near 01c7ah ; e9 72 ff ; 0xc1d05 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1d08 vgabios.c:1366 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc1d0c + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc1d0f + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1d13 + jnbe near 0217ch ; 0f 87 62 04 ; 0xc1d16 + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc1d1a vgabios.c:1368 + movzx dx, byte [bp-008h] ; 0f b6 56 f8 ; 0xc1d1e + add ax, dx ; 01 d0 ; 0xc1d22 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1d24 + jnbe short 01d2fh ; 77 06 ; 0xc1d27 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1d29 + jne short 01d62h ; 75 33 ; 0xc1d2d + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc1d2f vgabios.c:1369 + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc1d33 + sal ax, 008h ; c1 e0 08 ; 0xc1d37 + add ax, strict word 00020h ; 05 20 00 ; 0xc1d3a + mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xc1d3d + imul dx, word [bp-014h] ; 0f af 56 ec ; 0xc1d40 + movzx bx, byte [bp-010h] ; 0f b6 5e f0 ; 0xc1d44 + add dx, bx ; 01 da ; 0xc1d48 + add dx, dx ; 01 d2 ; 0xc1d4a + mov di, word [bp-01ch] ; 8b 7e e4 ; 0xc1d4c + add di, dx ; 01 d7 ; 0xc1d4f + movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xc1d51 + sal bx, 003h ; c1 e3 03 ; 0xc1d55 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1d58 + jcxz 01d60h ; e3 02 ; 0xc1d5c + rep stosw ; f3 ab ; 0xc1d5e + jmp short 01da2h ; eb 40 ; 0xc1d60 vgabios.c:1370 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc1d62 vgabios.c:1371 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc1d66 + mov si, word [bp-01ah] ; 8b 76 e6 ; 0xc1d6a + sub si, ax ; 29 c6 ; 0xc1d6d + imul si, word [bp-014h] ; 0f af 76 ec ; 0xc1d6f + movzx dx, byte [bp-010h] ; 0f b6 56 f0 ; 0xc1d73 + add si, dx ; 01 d6 ; 0xc1d77 + add si, si ; 01 f6 ; 0xc1d79 + movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xc1d7b + sal bx, 003h ; c1 e3 03 ; 0xc1d7f + mov ax, word [bx+047b3h] ; 8b 87 b3 47 ; 0xc1d82 + mov bx, word [bp-01ah] ; 8b 5e e6 ; 0xc1d86 + imul bx, word [bp-014h] ; 0f af 5e ec ; 0xc1d89 + add dx, bx ; 01 da ; 0xc1d8d + add dx, dx ; 01 d2 ; 0xc1d8f + mov di, word [bp-01ch] ; 8b 7e e4 ; 0xc1d91 + add di, dx ; 01 d7 ; 0xc1d94 + mov dx, ax ; 89 c2 ; 0xc1d96 + mov es, ax ; 8e c0 ; 0xc1d98 + jcxz 01da2h ; e3 06 ; 0xc1d9a + push DS ; 1e ; 0xc1d9c + mov ds, dx ; 8e da ; 0xc1d9d + rep movsw ; f3 a5 ; 0xc1d9f + pop DS ; 1f ; 0xc1da1 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1da2 vgabios.c:1372 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1da6 + jc near 0217ch ; 0f 82 cf 03 ; 0xc1da9 + dec word [bp-01ah] ; ff 4e e6 ; 0xc1dad vgabios.c:1373 + jmp near 01d0fh ; e9 5c ff ; 0xc1db0 + movzx di, byte [di+0482fh] ; 0f b6 bd 2f 48 ; 0xc1db3 vgabios.c:1379 + sal di, 006h ; c1 e7 06 ; 0xc1db8 + mov dl, byte [di+04845h] ; 8a 95 45 48 ; 0xc1dbb + mov byte [bp-00eh], dl ; 88 56 f2 ; 0xc1dbf + mov dl, byte [bx+047b1h] ; 8a 97 b1 47 ; 0xc1dc2 vgabios.c:1380 + cmp dl, 003h ; 80 fa 03 ; 0xc1dc6 + jc short 01ddch ; 72 11 ; 0xc1dc9 + jbe short 01de6h ; 76 19 ; 0xc1dcb + cmp dl, 005h ; 80 fa 05 ; 0xc1dcd + je near 0205fh ; 0f 84 8b 02 ; 0xc1dd0 + cmp dl, 004h ; 80 fa 04 ; 0xc1dd4 + je short 01de6h ; 74 0d ; 0xc1dd7 + jmp near 0217ch ; e9 a0 03 ; 0xc1dd9 + cmp dl, 002h ; 80 fa 02 ; 0xc1ddc + je near 01f25h ; 0f 84 42 01 ; 0xc1ddf + jmp near 0217ch ; e9 96 03 ; 0xc1de3 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1de6 vgabios.c:1384 + jne short 01e3eh ; 75 52 ; 0xc1dea + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc1dec + jne short 01e3eh ; 75 4c ; 0xc1df0 + cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xc1df2 + jne short 01e3eh ; 75 46 ; 0xc1df6 + movzx bx, byte [bp+004h] ; 0f b6 5e 04 ; 0xc1df8 + mov ax, cx ; 89 c8 ; 0xc1dfc + dec ax ; 48 ; 0xc1dfe + cmp bx, ax ; 39 c3 ; 0xc1dff + jne short 01e3eh ; 75 3b ; 0xc1e01 + movzx ax, dh ; 0f b6 c6 ; 0xc1e03 + mov dx, word [bp-014h] ; 8b 56 ec ; 0xc1e06 + dec dx ; 4a ; 0xc1e09 + cmp ax, dx ; 39 d0 ; 0xc1e0a + jne short 01e3eh ; 75 30 ; 0xc1e0c + mov ax, 00205h ; b8 05 02 ; 0xc1e0e vgabios.c:1386 + mov dx, 003ceh ; ba ce 03 ; 0xc1e11 + out DX, ax ; ef ; 0xc1e14 + mov ax, word [bp-014h] ; 8b 46 ec ; 0xc1e15 vgabios.c:1387 + imul ax, cx ; 0f af c1 ; 0xc1e18 + movzx cx, byte [bp-00eh] ; 0f b6 4e f2 ; 0xc1e1b + imul cx, ax ; 0f af c8 ; 0xc1e1f + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc1e22 + movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xc1e26 + sal bx, 003h ; c1 e3 03 ; 0xc1e2a + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1e2d + xor di, di ; 31 ff ; 0xc1e31 + jcxz 01e37h ; e3 02 ; 0xc1e33 + rep stosb ; f3 aa ; 0xc1e35 + mov ax, strict word 00005h ; b8 05 00 ; 0xc1e37 vgabios.c:1388 + out DX, ax ; ef ; 0xc1e3a + jmp near 0217ch ; e9 3e 03 ; 0xc1e3b vgabios.c:1390 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc1e3e vgabios.c:1392 + jne short 01eadh ; 75 69 ; 0xc1e42 + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc1e44 vgabios.c:1393 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc1e48 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1e4b + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1e4f + jc near 0217ch ; 0f 82 26 03 ; 0xc1e52 + movzx dx, byte [bp-008h] ; 0f b6 56 f8 ; 0xc1e56 vgabios.c:1395 + add dx, word [bp-01ah] ; 03 56 e6 ; 0xc1e5a + cmp dx, ax ; 39 c2 ; 0xc1e5d + jnbe short 01e67h ; 77 06 ; 0xc1e5f + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1e61 + jne short 01e86h ; 75 1f ; 0xc1e65 + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc1e67 vgabios.c:1396 + push ax ; 50 ; 0xc1e6b + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc1e6c + push ax ; 50 ; 0xc1e70 + movzx cx, byte [bp-014h] ; 0f b6 4e ec ; 0xc1e71 + movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xc1e75 + movzx dx, byte [bp-01ah] ; 0f b6 56 e6 ; 0xc1e79 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc1e7d + call 01904h ; e8 80 fa ; 0xc1e81 + jmp short 01ea8h ; eb 22 ; 0xc1e84 vgabios.c:1397 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc1e86 vgabios.c:1398 + push ax ; 50 ; 0xc1e8a + movzx ax, byte [bp-014h] ; 0f b6 46 ec ; 0xc1e8b + push ax ; 50 ; 0xc1e8f + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc1e90 + movzx bx, byte [bp-01ah] ; 0f b6 5e e6 ; 0xc1e94 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc1e98 + add al, byte [bp-008h] ; 02 46 f8 ; 0xc1e9b + movzx dx, al ; 0f b6 d0 ; 0xc1e9e + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc1ea1 + call 0188fh ; e8 e7 f9 ; 0xc1ea5 + inc word [bp-01ah] ; ff 46 e6 ; 0xc1ea8 vgabios.c:1399 + jmp short 01e4bh ; eb 9e ; 0xc1eab + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1ead vgabios.c:1402 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc1eb1 + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc1eb4 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1eb8 + jnbe near 0217ch ; 0f 87 bd 02 ; 0xc1ebb + movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xc1ebf vgabios.c:1404 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc1ec3 + add ax, dx ; 01 d0 ; 0xc1ec7 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1ec9 + jnbe short 01ed4h ; 77 06 ; 0xc1ecc + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1ece + jne short 01ef3h ; 75 1f ; 0xc1ed2 + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc1ed4 vgabios.c:1405 + push ax ; 50 ; 0xc1ed8 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc1ed9 + push ax ; 50 ; 0xc1edd + movzx cx, byte [bp-014h] ; 0f b6 4e ec ; 0xc1ede + movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xc1ee2 + movzx dx, byte [bp-01ah] ; 0f b6 56 e6 ; 0xc1ee6 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc1eea + call 01904h ; e8 13 fa ; 0xc1eee + jmp short 01f15h ; eb 22 ; 0xc1ef1 vgabios.c:1406 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc1ef3 vgabios.c:1407 + push ax ; 50 ; 0xc1ef7 + movzx ax, byte [bp-014h] ; 0f b6 46 ec ; 0xc1ef8 + push ax ; 50 ; 0xc1efc + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc1efd + movzx bx, byte [bp-01ah] ; 0f b6 5e e6 ; 0xc1f01 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc1f05 + sub al, byte [bp-008h] ; 2a 46 f8 ; 0xc1f08 + movzx dx, al ; 0f b6 d0 ; 0xc1f0b + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc1f0e + call 0188fh ; e8 7a f9 ; 0xc1f12 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1f15 vgabios.c:1408 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1f19 + jc near 0217ch ; 0f 82 5c 02 ; 0xc1f1c + dec word [bp-01ah] ; ff 4e e6 ; 0xc1f20 vgabios.c:1409 + jmp short 01eb4h ; eb 8f ; 0xc1f23 + mov dl, byte [bx+047b2h] ; 8a 97 b2 47 ; 0xc1f25 vgabios.c:1414 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1f29 vgabios.c:1415 + jne short 01f6ah ; 75 3b ; 0xc1f2d + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc1f2f + jne short 01f6ah ; 75 35 ; 0xc1f33 + cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xc1f35 + jne short 01f6ah ; 75 2f ; 0xc1f39 + movzx cx, byte [bp+004h] ; 0f b6 4e 04 ; 0xc1f3b + cmp cx, word [bp-016h] ; 3b 4e ea ; 0xc1f3f + jne short 01f6ah ; 75 26 ; 0xc1f42 + movzx cx, dh ; 0f b6 ce ; 0xc1f44 + cmp cx, word [bp-018h] ; 3b 4e e8 ; 0xc1f47 + jne short 01f6ah ; 75 1e ; 0xc1f4a + movzx cx, byte [bp-00eh] ; 0f b6 4e f2 ; 0xc1f4c vgabios.c:1417 + imul ax, cx ; 0f af c1 ; 0xc1f50 + movzx cx, dl ; 0f b6 ca ; 0xc1f53 + imul cx, ax ; 0f af c8 ; 0xc1f56 + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc1f59 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1f5d + xor di, di ; 31 ff ; 0xc1f61 + jcxz 01f67h ; e3 02 ; 0xc1f63 + rep stosb ; f3 aa ; 0xc1f65 + jmp near 0217ch ; e9 12 02 ; 0xc1f67 vgabios.c:1419 + cmp dl, 002h ; 80 fa 02 ; 0xc1f6a vgabios.c:1421 + jne short 01f78h ; 75 09 ; 0xc1f6d + sal byte [bp-010h], 1 ; d0 66 f0 ; 0xc1f6f vgabios.c:1423 + sal byte [bp-00ah], 1 ; d0 66 f6 ; 0xc1f72 vgabios.c:1424 + sal word [bp-014h], 1 ; d1 66 ec ; 0xc1f75 vgabios.c:1425 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc1f78 vgabios.c:1428 + jne short 01fe7h ; 75 69 ; 0xc1f7c + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc1f7e vgabios.c:1429 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc1f82 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1f85 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1f89 + jc near 0217ch ; 0f 82 ec 01 ; 0xc1f8c + movzx dx, byte [bp-008h] ; 0f b6 56 f8 ; 0xc1f90 vgabios.c:1431 + add dx, word [bp-01ah] ; 03 56 e6 ; 0xc1f94 + cmp dx, ax ; 39 c2 ; 0xc1f97 + jnbe short 01fa1h ; 77 06 ; 0xc1f99 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1f9b + jne short 01fc0h ; 75 1f ; 0xc1f9f + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc1fa1 vgabios.c:1432 + push ax ; 50 ; 0xc1fa5 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc1fa6 + push ax ; 50 ; 0xc1faa + movzx cx, byte [bp-014h] ; 0f b6 4e ec ; 0xc1fab + movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xc1faf + movzx dx, byte [bp-01ah] ; 0f b6 56 e6 ; 0xc1fb3 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc1fb7 + call 01a07h ; e8 49 fa ; 0xc1fbb + jmp short 01fe2h ; eb 22 ; 0xc1fbe vgabios.c:1433 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc1fc0 vgabios.c:1434 + push ax ; 50 ; 0xc1fc4 + movzx ax, byte [bp-014h] ; 0f b6 46 ec ; 0xc1fc5 + push ax ; 50 ; 0xc1fc9 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc1fca + movzx bx, byte [bp-01ah] ; 0f b6 5e e6 ; 0xc1fce + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc1fd2 + add al, byte [bp-008h] ; 02 46 f8 ; 0xc1fd5 + movzx dx, al ; 0f b6 d0 ; 0xc1fd8 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc1fdb + call 01964h ; e8 82 f9 ; 0xc1fdf + inc word [bp-01ah] ; ff 46 e6 ; 0xc1fe2 vgabios.c:1435 + jmp short 01f85h ; eb 9e ; 0xc1fe5 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc1fe7 vgabios.c:1438 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc1feb + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc1fee + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc1ff2 + jnbe near 0217ch ; 0f 87 83 01 ; 0xc1ff5 + movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xc1ff9 vgabios.c:1440 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc1ffd + add ax, dx ; 01 d0 ; 0xc2001 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc2003 + jnbe short 0200eh ; 77 06 ; 0xc2006 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc2008 + jne short 0202dh ; 75 1f ; 0xc200c + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc200e vgabios.c:1441 + push ax ; 50 ; 0xc2012 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc2013 + push ax ; 50 ; 0xc2017 + movzx cx, byte [bp-014h] ; 0f b6 4e ec ; 0xc2018 + movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xc201c + movzx dx, byte [bp-01ah] ; 0f b6 56 e6 ; 0xc2020 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc2024 + call 01a07h ; e8 dc f9 ; 0xc2028 + jmp short 0204fh ; eb 22 ; 0xc202b vgabios.c:1442 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc202d vgabios.c:1443 + push ax ; 50 ; 0xc2031 + movzx ax, byte [bp-014h] ; 0f b6 46 ec ; 0xc2032 + push ax ; 50 ; 0xc2036 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc2037 + movzx bx, byte [bp-01ah] ; 0f b6 5e e6 ; 0xc203b + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc203f + sub al, byte [bp-008h] ; 2a 46 f8 ; 0xc2042 + movzx dx, al ; 0f b6 d0 ; 0xc2045 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc2048 + call 01964h ; e8 15 f9 ; 0xc204c + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc204f vgabios.c:1444 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc2053 + jc near 0217ch ; 0f 82 22 01 ; 0xc2056 + dec word [bp-01ah] ; ff 4e e6 ; 0xc205a vgabios.c:1445 + jmp short 01feeh ; eb 8f ; 0xc205d + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc205f vgabios.c:1450 + jne short 0209fh ; 75 3a ; 0xc2063 + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc2065 + jne short 0209fh ; 75 34 ; 0xc2069 + cmp byte [bp-010h], 000h ; 80 7e f0 00 ; 0xc206b + jne short 0209fh ; 75 2e ; 0xc206f + movzx cx, byte [bp+004h] ; 0f b6 4e 04 ; 0xc2071 + cmp cx, word [bp-016h] ; 3b 4e ea ; 0xc2075 + jne short 0209fh ; 75 25 ; 0xc2078 + movzx dx, dh ; 0f b6 d6 ; 0xc207a + cmp dx, word [bp-018h] ; 3b 56 e8 ; 0xc207d + jne short 0209fh ; 75 1d ; 0xc2080 + movzx dx, byte [bp-00eh] ; 0f b6 56 f2 ; 0xc2082 vgabios.c:1452 + mov cx, ax ; 89 c1 ; 0xc2086 + imul cx, dx ; 0f af ca ; 0xc2088 + sal cx, 003h ; c1 e1 03 ; 0xc208b + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc208e + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2092 + xor di, di ; 31 ff ; 0xc2096 + jcxz 0209ch ; e3 02 ; 0xc2098 + rep stosb ; f3 aa ; 0xc209a + jmp near 0217ch ; e9 dd 00 ; 0xc209c vgabios.c:1454 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc209f vgabios.c:1457 + jne short 0210bh ; 75 66 ; 0xc20a3 + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc20a5 vgabios.c:1458 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc20a9 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc20ac + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc20b0 + jc near 0217ch ; 0f 82 c5 00 ; 0xc20b3 + movzx dx, byte [bp-008h] ; 0f b6 56 f8 ; 0xc20b7 vgabios.c:1460 + add dx, word [bp-01ah] ; 03 56 e6 ; 0xc20bb + cmp dx, ax ; 39 c2 ; 0xc20be + jnbe short 020c8h ; 77 06 ; 0xc20c0 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc20c2 + jne short 020e6h ; 75 1e ; 0xc20c6 + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc20c8 vgabios.c:1461 + push ax ; 50 ; 0xc20cc + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc20cd + push ax ; 50 ; 0xc20d1 + movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xc20d2 + movzx dx, byte [bp-01ah] ; 0f b6 56 e6 ; 0xc20d6 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc20da + mov cx, word [bp-014h] ; 8b 4e ec ; 0xc20de + call 01b01h ; e8 1d fa ; 0xc20e1 + jmp short 02106h ; eb 20 ; 0xc20e4 vgabios.c:1462 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc20e6 vgabios.c:1463 + push ax ; 50 ; 0xc20ea + push word [bp-014h] ; ff 76 ec ; 0xc20eb + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc20ee + movzx bx, byte [bp-01ah] ; 0f b6 5e e6 ; 0xc20f2 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc20f6 + add al, byte [bp-008h] ; 02 46 f8 ; 0xc20f9 + movzx dx, al ; 0f b6 d0 ; 0xc20fc + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc20ff + call 01a88h ; e8 82 f9 ; 0xc2103 + inc word [bp-01ah] ; ff 46 e6 ; 0xc2106 vgabios.c:1464 + jmp short 020ach ; eb a1 ; 0xc2109 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc210b vgabios.c:1467 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc210f + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc2112 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc2116 + jnbe short 0217ch ; 77 61 ; 0xc2119 + movzx dx, byte [bp-00ch] ; 0f b6 56 f4 ; 0xc211b vgabios.c:1469 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc211f + add ax, dx ; 01 d0 ; 0xc2123 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc2125 + jnbe short 02130h ; 77 06 ; 0xc2128 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc212a + jne short 0214eh ; 75 1e ; 0xc212e + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc2130 vgabios.c:1470 + push ax ; 50 ; 0xc2134 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc2135 + push ax ; 50 ; 0xc2139 + movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xc213a + movzx dx, byte [bp-01ah] ; 0f b6 56 e6 ; 0xc213e + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc2142 + mov cx, word [bp-014h] ; 8b 4e ec ; 0xc2146 + call 01b01h ; e8 b5 f9 ; 0xc2149 + jmp short 0216eh ; eb 20 ; 0xc214c vgabios.c:1471 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc214e vgabios.c:1472 + push ax ; 50 ; 0xc2152 + push word [bp-014h] ; ff 76 ec ; 0xc2153 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc2156 + movzx bx, byte [bp-01ah] ; 0f b6 5e e6 ; 0xc215a + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc215e + sub al, byte [bp-008h] ; 2a 46 f8 ; 0xc2161 + movzx dx, al ; 0f b6 d0 ; 0xc2164 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc2167 + call 01a88h ; e8 1a f9 ; 0xc216b + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc216e vgabios.c:1473 + cmp ax, word [bp-01ah] ; 3b 46 e6 ; 0xc2172 + jc short 0217ch ; 72 05 ; 0xc2175 + dec word [bp-01ah] ; ff 4e e6 ; 0xc2177 vgabios.c:1474 + jmp short 02112h ; eb 96 ; 0xc217a + lea sp, [bp-004h] ; 8d 66 fc ; 0xc217c vgabios.c:1485 + pop di ; 5f ; 0xc217f + pop si ; 5e ; 0xc2180 + pop bp ; 5d ; 0xc2181 + retn 00008h ; c2 08 00 ; 0xc2182 + ; disGetNextSymbol 0xc2185 LB 0x2134 -> off=0x0 cb=00000000000000ff uValue=00000000000c2185 'write_gfx_char_pl4' +write_gfx_char_pl4: ; 0xc2185 LB 0xff + push bp ; 55 ; 0xc2185 vgabios.c:1488 + mov bp, sp ; 89 e5 ; 0xc2186 + push si ; 56 ; 0xc2188 + push di ; 57 ; 0xc2189 + sub sp, strict byte 0000ch ; 83 ec 0c ; 0xc218a + mov ah, al ; 88 c4 ; 0xc218d + mov byte [bp-008h], dl ; 88 56 f8 ; 0xc218f + mov al, bl ; 88 d8 ; 0xc2192 + mov bx, 0010ch ; bb 0c 01 ; 0xc2194 vgabios.c:67 + xor si, si ; 31 f6 ; 0xc2197 + mov es, si ; 8e c6 ; 0xc2199 + mov si, word [es:bx] ; 26 8b 37 ; 0xc219b + mov bx, word [es:bx+002h] ; 26 8b 5f 02 ; 0xc219e + mov word [bp-00ch], si ; 89 76 f4 ; 0xc21a2 vgabios.c:68 + mov word [bp-00ah], bx ; 89 5e f6 ; 0xc21a5 + movzx bx, cl ; 0f b6 d9 ; 0xc21a8 vgabios.c:1497 + movzx cx, byte [bp+006h] ; 0f b6 4e 06 ; 0xc21ab + imul bx, cx ; 0f af d9 ; 0xc21af + movzx si, byte [bp+004h] ; 0f b6 76 04 ; 0xc21b2 + imul si, bx ; 0f af f3 ; 0xc21b6 + movzx bx, al ; 0f b6 d8 ; 0xc21b9 + add si, bx ; 01 de ; 0xc21bc + mov bx, strict word 0004ch ; bb 4c 00 ; 0xc21be vgabios.c:57 + mov di, strict word 00040h ; bf 40 00 ; 0xc21c1 + mov es, di ; 8e c7 ; 0xc21c4 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc21c6 + movzx di, byte [bp+008h] ; 0f b6 7e 08 ; 0xc21c9 vgabios.c:58 + imul bx, di ; 0f af df ; 0xc21cd + add si, bx ; 01 de ; 0xc21d0 + movzx ax, ah ; 0f b6 c4 ; 0xc21d2 vgabios.c:1499 + imul ax, cx ; 0f af c1 ; 0xc21d5 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc21d8 + mov ax, 00f02h ; b8 02 0f ; 0xc21db vgabios.c:1500 + mov dx, 003c4h ; ba c4 03 ; 0xc21de + out DX, ax ; ef ; 0xc21e1 + mov ax, 00205h ; b8 05 02 ; 0xc21e2 vgabios.c:1501 + mov dx, 003ceh ; ba ce 03 ; 0xc21e5 + out DX, ax ; ef ; 0xc21e8 + test byte [bp-008h], 080h ; f6 46 f8 80 ; 0xc21e9 vgabios.c:1502 + je short 021f5h ; 74 06 ; 0xc21ed + mov ax, 01803h ; b8 03 18 ; 0xc21ef vgabios.c:1504 + out DX, ax ; ef ; 0xc21f2 + jmp short 021f9h ; eb 04 ; 0xc21f3 vgabios.c:1506 + mov ax, strict word 00003h ; b8 03 00 ; 0xc21f5 vgabios.c:1508 + out DX, ax ; ef ; 0xc21f8 + xor ch, ch ; 30 ed ; 0xc21f9 vgabios.c:1510 + cmp ch, byte [bp+006h] ; 3a 6e 06 ; 0xc21fb + jnc short 0226ch ; 73 6c ; 0xc21fe + movzx bx, ch ; 0f b6 dd ; 0xc2200 vgabios.c:1512 + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc2203 + imul bx, ax ; 0f af d8 ; 0xc2207 + add bx, si ; 01 f3 ; 0xc220a + mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xc220c vgabios.c:1513 + jmp short 02224h ; eb 12 ; 0xc2210 + mov ax, 0a000h ; b8 00 a0 ; 0xc2212 vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc2215 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc2217 + inc byte [bp-006h] ; fe 46 fa ; 0xc221b vgabios.c:1526 + cmp byte [bp-006h], 008h ; 80 7e fa 08 ; 0xc221e + jnc short 02268h ; 73 44 ; 0xc2222 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc2224 + mov cl, al ; 88 c1 ; 0xc2228 + mov ax, 00080h ; b8 80 00 ; 0xc222a + sar ax, CL ; d3 f8 ; 0xc222d + xor ah, ah ; 30 e4 ; 0xc222f + mov word [bp-010h], ax ; 89 46 f0 ; 0xc2231 + sal ax, 008h ; c1 e0 08 ; 0xc2234 + or AL, strict byte 008h ; 0c 08 ; 0xc2237 + mov dx, 003ceh ; ba ce 03 ; 0xc2239 + out DX, ax ; ef ; 0xc223c + mov dx, bx ; 89 da ; 0xc223d + mov ax, 0a000h ; b8 00 a0 ; 0xc223f + call 03614h ; e8 cf 13 ; 0xc2242 + movzx ax, ch ; 0f b6 c5 ; 0xc2245 + add ax, word [bp-00eh] ; 03 46 f2 ; 0xc2248 + les di, [bp-00ch] ; c4 7e f4 ; 0xc224b + add di, ax ; 01 c7 ; 0xc224e + movzx ax, byte [es:di] ; 26 0f b6 05 ; 0xc2250 + test word [bp-010h], ax ; 85 46 f0 ; 0xc2254 + je short 02212h ; 74 b9 ; 0xc2257 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2259 + and AL, strict byte 00fh ; 24 0f ; 0xc225c + mov di, 0a000h ; bf 00 a0 ; 0xc225e + mov es, di ; 8e c7 ; 0xc2261 + mov byte [es:bx], al ; 26 88 07 ; 0xc2263 + jmp short 0221bh ; eb b3 ; 0xc2266 + db 0feh, 0c5h + ; inc ch ; fe c5 ; 0xc2268 vgabios.c:1527 + jmp short 021fbh ; eb 8f ; 0xc226a + mov ax, 0ff08h ; b8 08 ff ; 0xc226c vgabios.c:1528 + mov dx, 003ceh ; ba ce 03 ; 0xc226f + out DX, ax ; ef ; 0xc2272 + mov ax, strict word 00005h ; b8 05 00 ; 0xc2273 vgabios.c:1529 + out DX, ax ; ef ; 0xc2276 + mov ax, strict word 00003h ; b8 03 00 ; 0xc2277 vgabios.c:1530 + out DX, ax ; ef ; 0xc227a + lea sp, [bp-004h] ; 8d 66 fc ; 0xc227b vgabios.c:1531 + pop di ; 5f ; 0xc227e + pop si ; 5e ; 0xc227f + pop bp ; 5d ; 0xc2280 + retn 00006h ; c2 06 00 ; 0xc2281 + ; disGetNextSymbol 0xc2284 LB 0x2035 -> off=0x0 cb=00000000000000dd uValue=00000000000c2284 'write_gfx_char_cga' +write_gfx_char_cga: ; 0xc2284 LB 0xdd + push si ; 56 ; 0xc2284 vgabios.c:1534 + push di ; 57 ; 0xc2285 + enter 00006h, 000h ; c8 06 00 00 ; 0xc2286 + mov di, 0556dh ; bf 6d 55 ; 0xc228a vgabios.c:1541 + xor bh, bh ; 30 ff ; 0xc228d vgabios.c:1542 + movzx si, byte [bp+00ah] ; 0f b6 76 0a ; 0xc228f + imul si, bx ; 0f af f3 ; 0xc2293 + movzx bx, cl ; 0f b6 d9 ; 0xc2296 + imul bx, bx, 00140h ; 69 db 40 01 ; 0xc2299 + add si, bx ; 01 de ; 0xc229d + mov word [bp-004h], si ; 89 76 fc ; 0xc229f + xor ah, ah ; 30 e4 ; 0xc22a2 vgabios.c:1543 + sal ax, 003h ; c1 e0 03 ; 0xc22a4 + mov word [bp-006h], ax ; 89 46 fa ; 0xc22a7 + xor ah, ah ; 30 e4 ; 0xc22aa vgabios.c:1544 + jmp near 022cah ; e9 1b 00 ; 0xc22ac + movzx si, ah ; 0f b6 f4 ; 0xc22af vgabios.c:1559 + add si, word [bp-006h] ; 03 76 fa ; 0xc22b2 + add si, di ; 01 fe ; 0xc22b5 + mov al, byte [si] ; 8a 04 ; 0xc22b7 + mov si, 0b800h ; be 00 b8 ; 0xc22b9 vgabios.c:52 + mov es, si ; 8e c6 ; 0xc22bc + mov byte [es:bx], al ; 26 88 07 ; 0xc22be + db 0feh, 0c4h + ; inc ah ; fe c4 ; 0xc22c1 vgabios.c:1563 + cmp ah, 008h ; 80 fc 08 ; 0xc22c3 + jnc near 0235bh ; 0f 83 91 00 ; 0xc22c6 + movzx bx, ah ; 0f b6 dc ; 0xc22ca + sar bx, 1 ; d1 fb ; 0xc22cd + imul bx, bx, strict byte 00050h ; 6b db 50 ; 0xc22cf + add bx, word [bp-004h] ; 03 5e fc ; 0xc22d2 + test ah, 001h ; f6 c4 01 ; 0xc22d5 + je short 022ddh ; 74 03 ; 0xc22d8 + add bh, 020h ; 80 c7 20 ; 0xc22da + mov DH, strict byte 080h ; b6 80 ; 0xc22dd + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc22df + jne short 022fdh ; 75 18 ; 0xc22e3 + test dl, dh ; 84 f2 ; 0xc22e5 + je short 022afh ; 74 c6 ; 0xc22e7 + mov si, 0b800h ; be 00 b8 ; 0xc22e9 + mov es, si ; 8e c6 ; 0xc22ec + mov al, byte [es:bx] ; 26 8a 07 ; 0xc22ee + movzx si, ah ; 0f b6 f4 ; 0xc22f1 + add si, word [bp-006h] ; 03 76 fa ; 0xc22f4 + add si, di ; 01 fe ; 0xc22f7 + xor al, byte [si] ; 32 04 ; 0xc22f9 + jmp short 022b9h ; eb bc ; 0xc22fb + test dh, dh ; 84 f6 ; 0xc22fd vgabios.c:1565 + jbe short 022c1h ; 76 c0 ; 0xc22ff + test dl, 080h ; f6 c2 80 ; 0xc2301 vgabios.c:1567 + je short 02310h ; 74 0a ; 0xc2304 + mov si, 0b800h ; be 00 b8 ; 0xc2306 vgabios.c:47 + mov es, si ; 8e c6 ; 0xc2309 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc230b + jmp short 02312h ; eb 02 ; 0xc230e vgabios.c:1571 + xor al, al ; 30 c0 ; 0xc2310 vgabios.c:1573 + mov byte [bp-002h], 000h ; c6 46 fe 00 ; 0xc2312 vgabios.c:1575 + jmp short 02325h ; eb 0d ; 0xc2316 + or al, ch ; 08 e8 ; 0xc2318 vgabios.c:1585 + shr dh, 1 ; d0 ee ; 0xc231a vgabios.c:1588 + inc byte [bp-002h] ; fe 46 fe ; 0xc231c vgabios.c:1589 + cmp byte [bp-002h], 004h ; 80 7e fe 04 ; 0xc231f + jnc short 02350h ; 73 2b ; 0xc2323 + movzx si, ah ; 0f b6 f4 ; 0xc2325 + add si, word [bp-006h] ; 03 76 fa ; 0xc2328 + add si, di ; 01 fe ; 0xc232b + movzx si, byte [si] ; 0f b6 34 ; 0xc232d + movzx cx, dh ; 0f b6 ce ; 0xc2330 + test si, cx ; 85 ce ; 0xc2333 + je short 0231ah ; 74 e3 ; 0xc2335 + mov CL, strict byte 003h ; b1 03 ; 0xc2337 + sub cl, byte [bp-002h] ; 2a 4e fe ; 0xc2339 + mov ch, dl ; 88 d5 ; 0xc233c + and ch, 003h ; 80 e5 03 ; 0xc233e + add cl, cl ; 00 c9 ; 0xc2341 + sal ch, CL ; d2 e5 ; 0xc2343 + mov cl, ch ; 88 e9 ; 0xc2345 + test dl, 080h ; f6 c2 80 ; 0xc2347 + je short 02318h ; 74 cc ; 0xc234a + xor al, ch ; 30 e8 ; 0xc234c + jmp short 0231ah ; eb ca ; 0xc234e + mov cx, 0b800h ; b9 00 b8 ; 0xc2350 vgabios.c:52 + mov es, cx ; 8e c1 ; 0xc2353 + mov byte [es:bx], al ; 26 88 07 ; 0xc2355 + inc bx ; 43 ; 0xc2358 vgabios.c:1591 + jmp short 022fdh ; eb a2 ; 0xc2359 vgabios.c:1592 + leave ; c9 ; 0xc235b vgabios.c:1595 + pop di ; 5f ; 0xc235c + pop si ; 5e ; 0xc235d + retn 00004h ; c2 04 00 ; 0xc235e + ; disGetNextSymbol 0xc2361 LB 0x1f58 -> off=0x0 cb=0000000000000085 uValue=00000000000c2361 'write_gfx_char_lin' +write_gfx_char_lin: ; 0xc2361 LB 0x85 + push si ; 56 ; 0xc2361 vgabios.c:1598 + push di ; 57 ; 0xc2362 + enter 00006h, 000h ; c8 06 00 00 ; 0xc2363 + mov dh, dl ; 88 d6 ; 0xc2367 + mov word [bp-002h], 0556dh ; c7 46 fe 6d 55 ; 0xc2369 vgabios.c:1605 + movzx si, cl ; 0f b6 f1 ; 0xc236e vgabios.c:1606 + movzx cx, byte [bp+008h] ; 0f b6 4e 08 ; 0xc2371 + imul cx, si ; 0f af ce ; 0xc2375 + sal cx, 006h ; c1 e1 06 ; 0xc2378 + xor bh, bh ; 30 ff ; 0xc237b + sal bx, 003h ; c1 e3 03 ; 0xc237d + add bx, cx ; 01 cb ; 0xc2380 + mov word [bp-004h], bx ; 89 5e fc ; 0xc2382 + xor ah, ah ; 30 e4 ; 0xc2385 vgabios.c:1607 + mov si, ax ; 89 c6 ; 0xc2387 + sal si, 003h ; c1 e6 03 ; 0xc2389 + xor al, al ; 30 c0 ; 0xc238c vgabios.c:1608 + jmp short 023c5h ; eb 35 ; 0xc238e + cmp ah, 008h ; 80 fc 08 ; 0xc2390 vgabios.c:1612 + jnc short 023bfh ; 73 2a ; 0xc2393 + xor cl, cl ; 30 c9 ; 0xc2395 vgabios.c:1614 + movzx bx, al ; 0f b6 d8 ; 0xc2397 vgabios.c:1615 + add bx, si ; 01 f3 ; 0xc239a + add bx, word [bp-002h] ; 03 5e fe ; 0xc239c + movzx bx, byte [bx] ; 0f b6 1f ; 0xc239f + movzx di, dl ; 0f b6 fa ; 0xc23a2 + test bx, di ; 85 fb ; 0xc23a5 + je short 023abh ; 74 02 ; 0xc23a7 + mov cl, dh ; 88 f1 ; 0xc23a9 vgabios.c:1617 + movzx bx, ah ; 0f b6 dc ; 0xc23ab vgabios.c:1619 + add bx, word [bp-006h] ; 03 5e fa ; 0xc23ae + mov di, 0a000h ; bf 00 a0 ; 0xc23b1 vgabios.c:52 + mov es, di ; 8e c7 ; 0xc23b4 + mov byte [es:bx], cl ; 26 88 0f ; 0xc23b6 + shr dl, 1 ; d0 ea ; 0xc23b9 vgabios.c:1620 + db 0feh, 0c4h + ; inc ah ; fe c4 ; 0xc23bb vgabios.c:1621 + jmp short 02390h ; eb d1 ; 0xc23bd + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc23bf vgabios.c:1622 + cmp AL, strict byte 008h ; 3c 08 ; 0xc23c1 + jnc short 023e0h ; 73 1b ; 0xc23c3 + movzx cx, al ; 0f b6 c8 ; 0xc23c5 + movzx bx, byte [bp+008h] ; 0f b6 5e 08 ; 0xc23c8 + imul bx, cx ; 0f af d9 ; 0xc23cc + sal bx, 003h ; c1 e3 03 ; 0xc23cf + mov cx, word [bp-004h] ; 8b 4e fc ; 0xc23d2 + add cx, bx ; 01 d9 ; 0xc23d5 + mov word [bp-006h], cx ; 89 4e fa ; 0xc23d7 + mov DL, strict byte 080h ; b2 80 ; 0xc23da + xor ah, ah ; 30 e4 ; 0xc23dc + jmp short 02395h ; eb b5 ; 0xc23de + leave ; c9 ; 0xc23e0 vgabios.c:1623 + pop di ; 5f ; 0xc23e1 + pop si ; 5e ; 0xc23e2 + retn 00002h ; c2 02 00 ; 0xc23e3 + ; disGetNextSymbol 0xc23e6 LB 0x1ed3 -> off=0x0 cb=0000000000000165 uValue=00000000000c23e6 'biosfn_write_char_attr' +biosfn_write_char_attr: ; 0xc23e6 LB 0x165 + push bp ; 55 ; 0xc23e6 vgabios.c:1626 + mov bp, sp ; 89 e5 ; 0xc23e7 + push si ; 56 ; 0xc23e9 + push di ; 57 ; 0xc23ea + sub sp, strict byte 00018h ; 83 ec 18 ; 0xc23eb + mov byte [bp-008h], al ; 88 46 f8 ; 0xc23ee + mov byte [bp-00eh], dl ; 88 56 f2 ; 0xc23f1 + mov byte [bp-012h], bl ; 88 5e ee ; 0xc23f4 + mov si, cx ; 89 ce ; 0xc23f7 + mov bx, strict word 00049h ; bb 49 00 ; 0xc23f9 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc23fc + mov es, ax ; 8e c0 ; 0xc23ff + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2401 + xor ah, ah ; 30 e4 ; 0xc2404 vgabios.c:1634 + call 035edh ; e8 e4 11 ; 0xc2406 + mov cl, al ; 88 c1 ; 0xc2409 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc240b + cmp AL, strict byte 0ffh ; 3c ff ; 0xc240e vgabios.c:1635 + je near 02544h ; 0f 84 30 01 ; 0xc2410 + movzx ax, dl ; 0f b6 c2 ; 0xc2414 vgabios.c:1638 + lea bx, [bp-01ch] ; 8d 5e e4 ; 0xc2417 + lea dx, [bp-01ah] ; 8d 56 e6 ; 0xc241a + call 00a93h ; e8 73 e6 ; 0xc241d + mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xc2420 vgabios.c:1639 + mov byte [bp-010h], al ; 88 46 f0 ; 0xc2423 + mov dx, word [bp-01ch] ; 8b 56 e4 ; 0xc2426 + xor dl, dl ; 30 d2 ; 0xc2429 + shr dx, 008h ; c1 ea 08 ; 0xc242b + mov byte [bp-014h], dl ; 88 56 ec ; 0xc242e + mov bx, 00084h ; bb 84 00 ; 0xc2431 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2434 + mov es, ax ; 8e c0 ; 0xc2437 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2439 + xor ah, ah ; 30 e4 ; 0xc243c vgabios.c:48 + inc ax ; 40 ; 0xc243e + mov word [bp-018h], ax ; 89 46 e8 ; 0xc243f + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2442 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc2445 + mov word [bp-016h], ax ; 89 46 ea ; 0xc2448 vgabios.c:58 + movzx bx, cl ; 0f b6 d9 ; 0xc244b vgabios.c:1645 + mov di, bx ; 89 df ; 0xc244e + sal di, 003h ; c1 e7 03 ; 0xc2450 + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc2453 + jne short 024a0h ; 75 46 ; 0xc2458 + mov bx, word [bp-018h] ; 8b 5e e8 ; 0xc245a vgabios.c:1648 + imul bx, ax ; 0f af d8 ; 0xc245d + add bx, bx ; 01 db ; 0xc2460 + or bl, 0ffh ; 80 cb ff ; 0xc2462 + movzx cx, byte [bp-00eh] ; 0f b6 4e f2 ; 0xc2465 + inc bx ; 43 ; 0xc2469 + imul bx, cx ; 0f af d9 ; 0xc246a + xor dh, dh ; 30 f6 ; 0xc246d + imul ax, dx ; 0f af c2 ; 0xc246f + movzx dx, byte [bp-010h] ; 0f b6 56 f0 ; 0xc2472 + add ax, dx ; 01 d0 ; 0xc2476 + add ax, ax ; 01 c0 ; 0xc2478 + mov dx, bx ; 89 da ; 0xc247a + add dx, ax ; 01 c2 ; 0xc247c + movzx ax, byte [bp-012h] ; 0f b6 46 ee ; 0xc247e vgabios.c:1650 + sal ax, 008h ; c1 e0 08 ; 0xc2482 + movzx bx, byte [bp-008h] ; 0f b6 5e f8 ; 0xc2485 + add ax, bx ; 01 d8 ; 0xc2489 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc248b + mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xc248e vgabios.c:1651 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc2491 + mov cx, si ; 89 f1 ; 0xc2495 + mov di, dx ; 89 d7 ; 0xc2497 + jcxz 0249dh ; e3 02 ; 0xc2499 + rep stosw ; f3 ab ; 0xc249b + jmp near 02544h ; e9 a4 00 ; 0xc249d vgabios.c:1653 + movzx bx, byte [bx+0482fh] ; 0f b6 9f 2f 48 ; 0xc24a0 vgabios.c:1656 + sal bx, 006h ; c1 e3 06 ; 0xc24a5 + mov al, byte [bx+04845h] ; 8a 87 45 48 ; 0xc24a8 + mov byte [bp-006h], al ; 88 46 fa ; 0xc24ac + mov al, byte [di+047b2h] ; 8a 85 b2 47 ; 0xc24af vgabios.c:1657 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc24b3 + dec si ; 4e ; 0xc24b6 vgabios.c:1658 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc24b7 + je near 02544h ; 0f 84 86 00 ; 0xc24ba + movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xc24be vgabios.c:1660 + sal bx, 003h ; c1 e3 03 ; 0xc24c2 + mov al, byte [bx+047b1h] ; 8a 87 b1 47 ; 0xc24c5 + cmp AL, strict byte 003h ; 3c 03 ; 0xc24c9 + jc short 024d9h ; 72 0c ; 0xc24cb + jbe short 024dfh ; 76 10 ; 0xc24cd + cmp AL, strict byte 005h ; 3c 05 ; 0xc24cf + je short 02526h ; 74 53 ; 0xc24d1 + cmp AL, strict byte 004h ; 3c 04 ; 0xc24d3 + je short 024e3h ; 74 0c ; 0xc24d5 + jmp short 0253eh ; eb 65 ; 0xc24d7 + cmp AL, strict byte 002h ; 3c 02 ; 0xc24d9 + je short 02507h ; 74 2a ; 0xc24db + jmp short 0253eh ; eb 5f ; 0xc24dd + or byte [bp-012h], 001h ; 80 4e ee 01 ; 0xc24df vgabios.c:1663 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc24e3 vgabios.c:1665 + push ax ; 50 ; 0xc24e7 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc24e8 + push ax ; 50 ; 0xc24ec + movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xc24ed + push ax ; 50 ; 0xc24f1 + movzx cx, byte [bp-014h] ; 0f b6 4e ec ; 0xc24f2 + movzx bx, byte [bp-010h] ; 0f b6 5e f0 ; 0xc24f6 + movzx dx, byte [bp-012h] ; 0f b6 56 ee ; 0xc24fa + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc24fe + call 02185h ; e8 80 fc ; 0xc2502 + jmp short 0253eh ; eb 37 ; 0xc2505 vgabios.c:1666 + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc2507 vgabios.c:1668 + push ax ; 50 ; 0xc250b + movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xc250c + push ax ; 50 ; 0xc2510 + movzx cx, byte [bp-014h] ; 0f b6 4e ec ; 0xc2511 + movzx bx, byte [bp-010h] ; 0f b6 5e f0 ; 0xc2515 + movzx dx, byte [bp-012h] ; 0f b6 56 ee ; 0xc2519 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc251d + call 02284h ; e8 60 fd ; 0xc2521 + jmp short 0253eh ; eb 18 ; 0xc2524 vgabios.c:1669 + movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xc2526 vgabios.c:1671 + push ax ; 50 ; 0xc252a + movzx cx, byte [bp-014h] ; 0f b6 4e ec ; 0xc252b + movzx bx, byte [bp-010h] ; 0f b6 5e f0 ; 0xc252f + movzx dx, byte [bp-012h] ; 0f b6 56 ee ; 0xc2533 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc2537 + call 02361h ; e8 23 fe ; 0xc253b + inc byte [bp-010h] ; fe 46 f0 ; 0xc253e vgabios.c:1678 + jmp near 024b6h ; e9 72 ff ; 0xc2541 vgabios.c:1679 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2544 vgabios.c:1681 + pop di ; 5f ; 0xc2547 + pop si ; 5e ; 0xc2548 + pop bp ; 5d ; 0xc2549 + retn ; c3 ; 0xc254a + ; disGetNextSymbol 0xc254b LB 0x1d6e -> off=0x0 cb=0000000000000162 uValue=00000000000c254b 'biosfn_write_char_only' +biosfn_write_char_only: ; 0xc254b LB 0x162 + push bp ; 55 ; 0xc254b vgabios.c:1684 + mov bp, sp ; 89 e5 ; 0xc254c + push si ; 56 ; 0xc254e + push di ; 57 ; 0xc254f + sub sp, strict byte 00016h ; 83 ec 16 ; 0xc2550 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc2553 + mov byte [bp-00eh], dl ; 88 56 f2 ; 0xc2556 + mov byte [bp-006h], bl ; 88 5e fa ; 0xc2559 + mov si, cx ; 89 ce ; 0xc255c + mov bx, strict word 00049h ; bb 49 00 ; 0xc255e vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2561 + mov es, ax ; 8e c0 ; 0xc2564 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2566 + xor ah, ah ; 30 e4 ; 0xc2569 vgabios.c:1692 + call 035edh ; e8 7f 10 ; 0xc256b + mov cl, al ; 88 c1 ; 0xc256e + mov byte [bp-012h], al ; 88 46 ee ; 0xc2570 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc2573 vgabios.c:1693 + je near 026a6h ; 0f 84 2d 01 ; 0xc2575 + movzx ax, dl ; 0f b6 c2 ; 0xc2579 vgabios.c:1696 + lea bx, [bp-01ah] ; 8d 5e e6 ; 0xc257c + lea dx, [bp-018h] ; 8d 56 e8 ; 0xc257f + call 00a93h ; e8 0e e5 ; 0xc2582 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc2585 vgabios.c:1697 + mov byte [bp-010h], al ; 88 46 f0 ; 0xc2588 + mov dx, word [bp-01ah] ; 8b 56 e6 ; 0xc258b + xor dl, dl ; 30 d2 ; 0xc258e + shr dx, 008h ; c1 ea 08 ; 0xc2590 + mov byte [bp-00ah], dl ; 88 56 f6 ; 0xc2593 + mov bx, 00084h ; bb 84 00 ; 0xc2596 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2599 + mov es, ax ; 8e c0 ; 0xc259c + mov al, byte [es:bx] ; 26 8a 07 ; 0xc259e + xor ah, ah ; 30 e4 ; 0xc25a1 vgabios.c:48 + mov di, ax ; 89 c7 ; 0xc25a3 + inc di ; 47 ; 0xc25a5 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc25a6 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc25a9 + mov word [bp-016h], ax ; 89 46 ea ; 0xc25ac vgabios.c:58 + xor ch, ch ; 30 ed ; 0xc25af vgabios.c:1703 + mov bx, cx ; 89 cb ; 0xc25b1 + sal bx, 003h ; c1 e3 03 ; 0xc25b3 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc25b6 + jne short 025fah ; 75 3d ; 0xc25bb + imul di, ax ; 0f af f8 ; 0xc25bd vgabios.c:1706 + add di, di ; 01 ff ; 0xc25c0 + or di, 000ffh ; 81 cf ff 00 ; 0xc25c2 + movzx bx, byte [bp-00eh] ; 0f b6 5e f2 ; 0xc25c6 + inc di ; 47 ; 0xc25ca + imul bx, di ; 0f af df ; 0xc25cb + xor dh, dh ; 30 f6 ; 0xc25ce + imul ax, dx ; 0f af c2 ; 0xc25d0 + movzx dx, byte [bp-010h] ; 0f b6 56 f0 ; 0xc25d3 + add ax, dx ; 01 d0 ; 0xc25d7 + add ax, ax ; 01 c0 ; 0xc25d9 + add bx, ax ; 01 c3 ; 0xc25db + dec si ; 4e ; 0xc25dd vgabios.c:1708 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc25de + je near 026a6h ; 0f 84 c1 00 ; 0xc25e1 + movzx di, byte [bp-012h] ; 0f b6 7e ee ; 0xc25e5 vgabios.c:1709 + sal di, 003h ; c1 e7 03 ; 0xc25e9 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc25ec vgabios.c:50 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc25f0 + mov byte [es:bx], al ; 26 88 07 ; 0xc25f3 + inc bx ; 43 ; 0xc25f6 vgabios.c:1710 + inc bx ; 43 ; 0xc25f7 + jmp short 025ddh ; eb e3 ; 0xc25f8 vgabios.c:1711 + mov di, cx ; 89 cf ; 0xc25fa vgabios.c:1716 + movzx ax, byte [di+0482fh] ; 0f b6 85 2f 48 ; 0xc25fc + mov di, ax ; 89 c7 ; 0xc2601 + sal di, 006h ; c1 e7 06 ; 0xc2603 + mov al, byte [di+04845h] ; 8a 85 45 48 ; 0xc2606 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc260a + mov al, byte [bx+047b2h] ; 8a 87 b2 47 ; 0xc260d vgabios.c:1717 + mov byte [bp-014h], al ; 88 46 ec ; 0xc2611 + dec si ; 4e ; 0xc2614 vgabios.c:1718 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc2615 + je near 026a6h ; 0f 84 8a 00 ; 0xc2618 + movzx bx, byte [bp-012h] ; 0f b6 5e ee ; 0xc261c vgabios.c:1720 + sal bx, 003h ; c1 e3 03 ; 0xc2620 + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc2623 + cmp bl, 003h ; 80 fb 03 ; 0xc2627 + jc short 0263ah ; 72 0e ; 0xc262a + jbe short 02641h ; 76 13 ; 0xc262c + cmp bl, 005h ; 80 fb 05 ; 0xc262e + je short 02688h ; 74 55 ; 0xc2631 + cmp bl, 004h ; 80 fb 04 ; 0xc2633 + je short 02645h ; 74 0d ; 0xc2636 + jmp short 026a0h ; eb 66 ; 0xc2638 + cmp bl, 002h ; 80 fb 02 ; 0xc263a + je short 02669h ; 74 2a ; 0xc263d + jmp short 026a0h ; eb 5f ; 0xc263f + or byte [bp-006h], 001h ; 80 4e fa 01 ; 0xc2641 vgabios.c:1723 + movzx ax, byte [bp-00eh] ; 0f b6 46 f2 ; 0xc2645 vgabios.c:1725 + push ax ; 50 ; 0xc2649 + movzx ax, byte [bp-00ch] ; 0f b6 46 f4 ; 0xc264a + push ax ; 50 ; 0xc264e + movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xc264f + push ax ; 50 ; 0xc2653 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc2654 + movzx bx, byte [bp-010h] ; 0f b6 5e f0 ; 0xc2658 + movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xc265c + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc2660 + call 02185h ; e8 1e fb ; 0xc2664 + jmp short 026a0h ; eb 37 ; 0xc2667 vgabios.c:1726 + movzx ax, byte [bp-014h] ; 0f b6 46 ec ; 0xc2669 vgabios.c:1728 + push ax ; 50 ; 0xc266d + movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xc266e + push ax ; 50 ; 0xc2672 + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc2673 + movzx bx, byte [bp-010h] ; 0f b6 5e f0 ; 0xc2677 + movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xc267b + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc267f + call 02284h ; e8 fe fb ; 0xc2683 + jmp short 026a0h ; eb 18 ; 0xc2686 vgabios.c:1729 + movzx ax, byte [bp-016h] ; 0f b6 46 ea ; 0xc2688 vgabios.c:1731 + push ax ; 50 ; 0xc268c + movzx cx, byte [bp-00ah] ; 0f b6 4e f6 ; 0xc268d + movzx bx, byte [bp-010h] ; 0f b6 5e f0 ; 0xc2691 + movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xc2695 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc2699 + call 02361h ; e8 c1 fc ; 0xc269d + inc byte [bp-010h] ; fe 46 f0 ; 0xc26a0 vgabios.c:1738 + jmp near 02614h ; e9 6e ff ; 0xc26a3 vgabios.c:1739 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc26a6 vgabios.c:1741 + pop di ; 5f ; 0xc26a9 + pop si ; 5e ; 0xc26aa + pop bp ; 5d ; 0xc26ab + retn ; c3 ; 0xc26ac + ; disGetNextSymbol 0xc26ad LB 0x1c0c -> off=0x0 cb=0000000000000165 uValue=00000000000c26ad 'biosfn_write_pixel' +biosfn_write_pixel: ; 0xc26ad LB 0x165 + push bp ; 55 ; 0xc26ad vgabios.c:1744 + mov bp, sp ; 89 e5 ; 0xc26ae + push si ; 56 ; 0xc26b0 + push ax ; 50 ; 0xc26b1 + push ax ; 50 ; 0xc26b2 + mov byte [bp-004h], al ; 88 46 fc ; 0xc26b3 + mov byte [bp-006h], dl ; 88 56 fa ; 0xc26b6 + mov dx, bx ; 89 da ; 0xc26b9 + mov bx, strict word 00049h ; bb 49 00 ; 0xc26bb vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc26be + mov es, ax ; 8e c0 ; 0xc26c1 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc26c3 + xor ah, ah ; 30 e4 ; 0xc26c6 vgabios.c:1751 + call 035edh ; e8 22 0f ; 0xc26c8 + mov ah, al ; 88 c4 ; 0xc26cb + cmp AL, strict byte 0ffh ; 3c ff ; 0xc26cd vgabios.c:1752 + je near 027edh ; 0f 84 1a 01 ; 0xc26cf + movzx bx, al ; 0f b6 d8 ; 0xc26d3 vgabios.c:1753 + sal bx, 003h ; c1 e3 03 ; 0xc26d6 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc26d9 + je near 027edh ; 0f 84 0b 01 ; 0xc26de + mov al, byte [bx+047b1h] ; 8a 87 b1 47 ; 0xc26e2 vgabios.c:1755 + cmp AL, strict byte 003h ; 3c 03 ; 0xc26e6 + jc short 026f9h ; 72 0f ; 0xc26e8 + jbe short 02700h ; 76 14 ; 0xc26ea + cmp AL, strict byte 005h ; 3c 05 ; 0xc26ec + je near 027f3h ; 0f 84 01 01 ; 0xc26ee + cmp AL, strict byte 004h ; 3c 04 ; 0xc26f2 + je short 02700h ; 74 0a ; 0xc26f4 + jmp near 027edh ; e9 f4 00 ; 0xc26f6 + cmp AL, strict byte 002h ; 3c 02 ; 0xc26f9 + je short 0276fh ; 74 72 ; 0xc26fb + jmp near 027edh ; e9 ed 00 ; 0xc26fd + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2700 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2703 + mov es, ax ; 8e c0 ; 0xc2706 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc2708 + imul ax, cx ; 0f af c1 ; 0xc270b vgabios.c:58 + mov bx, dx ; 89 d3 ; 0xc270e + shr bx, 003h ; c1 eb 03 ; 0xc2710 + add bx, ax ; 01 c3 ; 0xc2713 + mov si, strict word 0004ch ; be 4c 00 ; 0xc2715 vgabios.c:57 + mov cx, word [es:si] ; 26 8b 0c ; 0xc2718 + movzx ax, byte [bp-004h] ; 0f b6 46 fc ; 0xc271b vgabios.c:58 + imul ax, cx ; 0f af c1 ; 0xc271f + add bx, ax ; 01 c3 ; 0xc2722 + mov cl, dl ; 88 d1 ; 0xc2724 vgabios.c:1761 + and cl, 007h ; 80 e1 07 ; 0xc2726 + mov ax, 00080h ; b8 80 00 ; 0xc2729 + sar ax, CL ; d3 f8 ; 0xc272c + xor ah, ah ; 30 e4 ; 0xc272e vgabios.c:1762 + sal ax, 008h ; c1 e0 08 ; 0xc2730 + or AL, strict byte 008h ; 0c 08 ; 0xc2733 + mov dx, 003ceh ; ba ce 03 ; 0xc2735 + out DX, ax ; ef ; 0xc2738 + mov ax, 00205h ; b8 05 02 ; 0xc2739 vgabios.c:1763 + out DX, ax ; ef ; 0xc273c + mov dx, bx ; 89 da ; 0xc273d vgabios.c:1764 + mov ax, 0a000h ; b8 00 a0 ; 0xc273f + call 03614h ; e8 cf 0e ; 0xc2742 + test byte [bp-006h], 080h ; f6 46 fa 80 ; 0xc2745 vgabios.c:1765 + je short 02752h ; 74 07 ; 0xc2749 + mov ax, 01803h ; b8 03 18 ; 0xc274b vgabios.c:1767 + mov dx, 003ceh ; ba ce 03 ; 0xc274e + out DX, ax ; ef ; 0xc2751 + mov ax, 0a000h ; b8 00 a0 ; 0xc2752 vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc2755 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2757 + mov byte [es:bx], al ; 26 88 07 ; 0xc275a + mov ax, 0ff08h ; b8 08 ff ; 0xc275d vgabios.c:1770 + mov dx, 003ceh ; ba ce 03 ; 0xc2760 + out DX, ax ; ef ; 0xc2763 + mov ax, strict word 00005h ; b8 05 00 ; 0xc2764 vgabios.c:1771 + out DX, ax ; ef ; 0xc2767 + mov ax, strict word 00003h ; b8 03 00 ; 0xc2768 vgabios.c:1772 + out DX, ax ; ef ; 0xc276b + jmp near 027edh ; e9 7e 00 ; 0xc276c vgabios.c:1773 + mov si, cx ; 89 ce ; 0xc276f vgabios.c:1775 + shr si, 1 ; d1 ee ; 0xc2771 + imul si, si, strict byte 00050h ; 6b f6 50 ; 0xc2773 + cmp al, byte [bx+047b2h] ; 3a 87 b2 47 ; 0xc2776 + jne short 02783h ; 75 07 ; 0xc277a + mov bx, dx ; 89 d3 ; 0xc277c vgabios.c:1777 + shr bx, 002h ; c1 eb 02 ; 0xc277e + jmp short 02788h ; eb 05 ; 0xc2781 vgabios.c:1779 + mov bx, dx ; 89 d3 ; 0xc2783 vgabios.c:1781 + shr bx, 003h ; c1 eb 03 ; 0xc2785 + add bx, si ; 01 f3 ; 0xc2788 + test cl, 001h ; f6 c1 01 ; 0xc278a vgabios.c:1783 + je short 02792h ; 74 03 ; 0xc278d + add bh, 020h ; 80 c7 20 ; 0xc278f + mov cx, 0b800h ; b9 00 b8 ; 0xc2792 vgabios.c:47 + mov es, cx ; 8e c1 ; 0xc2795 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2797 + movzx si, ah ; 0f b6 f4 ; 0xc279a vgabios.c:1785 + sal si, 003h ; c1 e6 03 ; 0xc279d + cmp byte [si+047b2h], 002h ; 80 bc b2 47 02 ; 0xc27a0 + jne short 027beh ; 75 17 ; 0xc27a5 + mov ah, dl ; 88 d4 ; 0xc27a7 vgabios.c:1787 + and ah, 003h ; 80 e4 03 ; 0xc27a9 + mov CL, strict byte 003h ; b1 03 ; 0xc27ac + sub cl, ah ; 28 e1 ; 0xc27ae + add cl, cl ; 00 c9 ; 0xc27b0 + mov dh, byte [bp-006h] ; 8a 76 fa ; 0xc27b2 + and dh, 003h ; 80 e6 03 ; 0xc27b5 + sal dh, CL ; d2 e6 ; 0xc27b8 + mov DL, strict byte 003h ; b2 03 ; 0xc27ba vgabios.c:1788 + jmp short 027d1h ; eb 13 ; 0xc27bc vgabios.c:1790 + mov ah, dl ; 88 d4 ; 0xc27be vgabios.c:1792 + and ah, 007h ; 80 e4 07 ; 0xc27c0 + mov CL, strict byte 007h ; b1 07 ; 0xc27c3 + sub cl, ah ; 28 e1 ; 0xc27c5 + mov dh, byte [bp-006h] ; 8a 76 fa ; 0xc27c7 + and dh, 001h ; 80 e6 01 ; 0xc27ca + sal dh, CL ; d2 e6 ; 0xc27cd + mov DL, strict byte 001h ; b2 01 ; 0xc27cf vgabios.c:1793 + sal dl, CL ; d2 e2 ; 0xc27d1 + test byte [bp-006h], 080h ; f6 46 fa 80 ; 0xc27d3 vgabios.c:1795 + je short 027ddh ; 74 04 ; 0xc27d7 + xor al, dh ; 30 f0 ; 0xc27d9 vgabios.c:1797 + jmp short 027e5h ; eb 08 ; 0xc27db vgabios.c:1799 + mov ah, dl ; 88 d4 ; 0xc27dd vgabios.c:1801 + not ah ; f6 d4 ; 0xc27df + and al, ah ; 20 e0 ; 0xc27e1 + or al, dh ; 08 f0 ; 0xc27e3 vgabios.c:1802 + mov dx, 0b800h ; ba 00 b8 ; 0xc27e5 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc27e8 + mov byte [es:bx], al ; 26 88 07 ; 0xc27ea + lea sp, [bp-002h] ; 8d 66 fe ; 0xc27ed vgabios.c:1805 + pop si ; 5e ; 0xc27f0 + pop bp ; 5d ; 0xc27f1 + retn ; c3 ; 0xc27f2 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc27f3 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc27f6 + mov es, ax ; 8e c0 ; 0xc27f9 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc27fb + sal ax, 003h ; c1 e0 03 ; 0xc27fe vgabios.c:58 + imul ax, cx ; 0f af c1 ; 0xc2801 + mov bx, dx ; 89 d3 ; 0xc2804 + add bx, ax ; 01 c3 ; 0xc2806 + mov ax, 0a000h ; b8 00 a0 ; 0xc2808 vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc280b + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc280d + jmp short 027eah ; eb d8 ; 0xc2810 + ; disGetNextSymbol 0xc2812 LB 0x1aa7 -> off=0x0 cb=000000000000024a uValue=00000000000c2812 'biosfn_write_teletype' +biosfn_write_teletype: ; 0xc2812 LB 0x24a + push bp ; 55 ; 0xc2812 vgabios.c:1818 + mov bp, sp ; 89 e5 ; 0xc2813 + push si ; 56 ; 0xc2815 + sub sp, strict byte 00012h ; 83 ec 12 ; 0xc2816 + mov ch, al ; 88 c5 ; 0xc2819 + mov byte [bp-00ah], dl ; 88 56 f6 ; 0xc281b + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc281e + cmp dl, 0ffh ; 80 fa ff ; 0xc2821 vgabios.c:1826 + jne short 02834h ; 75 0e ; 0xc2824 + mov bx, strict word 00062h ; bb 62 00 ; 0xc2826 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2829 + mov es, ax ; 8e c0 ; 0xc282c + mov al, byte [es:bx] ; 26 8a 07 ; 0xc282e + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc2831 vgabios.c:48 + mov bx, strict word 00049h ; bb 49 00 ; 0xc2834 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2837 + mov es, ax ; 8e c0 ; 0xc283a + mov al, byte [es:bx] ; 26 8a 07 ; 0xc283c + xor ah, ah ; 30 e4 ; 0xc283f vgabios.c:1831 + call 035edh ; e8 a9 0d ; 0xc2841 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc2844 + cmp AL, strict byte 0ffh ; 3c ff ; 0xc2847 vgabios.c:1832 + je near 02a56h ; 0f 84 09 02 ; 0xc2849 + movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xc284d vgabios.c:1835 + lea bx, [bp-012h] ; 8d 5e ee ; 0xc2851 + lea dx, [bp-014h] ; 8d 56 ec ; 0xc2854 + call 00a93h ; e8 39 e2 ; 0xc2857 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc285a vgabios.c:1836 + mov byte [bp-006h], al ; 88 46 fa ; 0xc285d + mov ax, word [bp-012h] ; 8b 46 ee ; 0xc2860 + xor al, al ; 30 c0 ; 0xc2863 + shr ax, 008h ; c1 e8 08 ; 0xc2865 + mov byte [bp-004h], al ; 88 46 fc ; 0xc2868 + mov bx, 00084h ; bb 84 00 ; 0xc286b vgabios.c:47 + mov dx, strict word 00040h ; ba 40 00 ; 0xc286e + mov es, dx ; 8e c2 ; 0xc2871 + mov dl, byte [es:bx] ; 26 8a 17 ; 0xc2873 + xor dh, dh ; 30 f6 ; 0xc2876 vgabios.c:48 + inc dx ; 42 ; 0xc2878 + mov word [bp-00eh], dx ; 89 56 f2 ; 0xc2879 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc287c vgabios.c:57 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc287f + mov word [bp-010h], dx ; 89 56 f0 ; 0xc2882 vgabios.c:58 + cmp ch, 008h ; 80 fd 08 ; 0xc2885 vgabios.c:1842 + jc short 02898h ; 72 0e ; 0xc2888 + jbe short 028a1h ; 76 15 ; 0xc288a + cmp ch, 00dh ; 80 fd 0d ; 0xc288c + je short 028b7h ; 74 26 ; 0xc288f + cmp ch, 00ah ; 80 fd 0a ; 0xc2891 + je short 028afh ; 74 19 ; 0xc2894 + jmp short 028beh ; eb 26 ; 0xc2896 + cmp ch, 007h ; 80 fd 07 ; 0xc2898 + je near 029b2h ; 0f 84 13 01 ; 0xc289b + jmp short 028beh ; eb 1d ; 0xc289f + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc28a1 vgabios.c:1849 + jbe near 029b2h ; 0f 86 09 01 ; 0xc28a5 + dec byte [bp-006h] ; fe 4e fa ; 0xc28a9 + jmp near 029b2h ; e9 03 01 ; 0xc28ac vgabios.c:1850 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc28af vgabios.c:1853 + mov byte [bp-004h], al ; 88 46 fc ; 0xc28b1 + jmp near 029b2h ; e9 fb 00 ; 0xc28b4 vgabios.c:1854 + mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xc28b7 vgabios.c:1857 + jmp near 029b2h ; e9 f4 00 ; 0xc28bb vgabios.c:1858 + movzx si, byte [bp-00ch] ; 0f b6 76 f4 ; 0xc28be vgabios.c:1862 + mov bx, si ; 89 f3 ; 0xc28c2 + sal bx, 003h ; c1 e3 03 ; 0xc28c4 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc28c7 + jne short 02911h ; 75 43 ; 0xc28cc + mov ax, word [bp-010h] ; 8b 46 f0 ; 0xc28ce vgabios.c:1865 + imul ax, word [bp-00eh] ; 0f af 46 f2 ; 0xc28d1 + add ax, ax ; 01 c0 ; 0xc28d5 + or AL, strict byte 0ffh ; 0c ff ; 0xc28d7 + movzx dx, byte [bp-00ah] ; 0f b6 56 f6 ; 0xc28d9 + mov si, ax ; 89 c6 ; 0xc28dd + inc si ; 46 ; 0xc28df + imul si, dx ; 0f af f2 ; 0xc28e0 + movzx ax, byte [bp-004h] ; 0f b6 46 fc ; 0xc28e3 + imul ax, word [bp-010h] ; 0f af 46 f0 ; 0xc28e7 + movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xc28eb + add ax, dx ; 01 d0 ; 0xc28ef + add ax, ax ; 01 c0 ; 0xc28f1 + add si, ax ; 01 c6 ; 0xc28f3 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc28f5 vgabios.c:50 + mov byte [es:si], ch ; 26 88 2c ; 0xc28f9 + cmp cl, 003h ; 80 f9 03 ; 0xc28fc vgabios.c:1870 + jne near 0299fh ; 0f 85 9c 00 ; 0xc28ff + inc si ; 46 ; 0xc2903 vgabios.c:1871 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2904 vgabios.c:50 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2908 + mov byte [es:si], al ; 26 88 04 ; 0xc290b + jmp near 0299fh ; e9 8e 00 ; 0xc290e vgabios.c:1873 + movzx si, byte [si+0482fh] ; 0f b6 b4 2f 48 ; 0xc2911 vgabios.c:1876 + sal si, 006h ; c1 e6 06 ; 0xc2916 + mov ah, byte [si+04845h] ; 8a a4 45 48 ; 0xc2919 + mov dl, byte [bx+047b2h] ; 8a 97 b2 47 ; 0xc291d vgabios.c:1877 + mov al, byte [bx+047b1h] ; 8a 87 b1 47 ; 0xc2921 vgabios.c:1878 + cmp AL, strict byte 003h ; 3c 03 ; 0xc2925 + jc short 02935h ; 72 0c ; 0xc2927 + jbe short 0293bh ; 76 10 ; 0xc2929 + cmp AL, strict byte 005h ; 3c 05 ; 0xc292b + je short 02986h ; 74 57 ; 0xc292d + cmp AL, strict byte 004h ; 3c 04 ; 0xc292f + je short 0293fh ; 74 0c ; 0xc2931 + jmp short 0299fh ; eb 6a ; 0xc2933 + cmp AL, strict byte 002h ; 3c 02 ; 0xc2935 + je short 02965h ; 74 2c ; 0xc2937 + jmp short 0299fh ; eb 64 ; 0xc2939 + or byte [bp-008h], 001h ; 80 4e f8 01 ; 0xc293b vgabios.c:1881 + movzx dx, byte [bp-00ah] ; 0f b6 56 f6 ; 0xc293f vgabios.c:1883 + push dx ; 52 ; 0xc2943 + movzx ax, ah ; 0f b6 c4 ; 0xc2944 + push ax ; 50 ; 0xc2947 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc2948 + push ax ; 50 ; 0xc294c + movzx bx, byte [bp-004h] ; 0f b6 5e fc ; 0xc294d + movzx si, byte [bp-006h] ; 0f b6 76 fa ; 0xc2951 + movzx dx, byte [bp-008h] ; 0f b6 56 f8 ; 0xc2955 + movzx ax, ch ; 0f b6 c5 ; 0xc2959 + mov cx, bx ; 89 d9 ; 0xc295c + mov bx, si ; 89 f3 ; 0xc295e + call 02185h ; e8 22 f8 ; 0xc2960 + jmp short 0299fh ; eb 3a ; 0xc2963 vgabios.c:1884 + movzx ax, dl ; 0f b6 c2 ; 0xc2965 vgabios.c:1886 + push ax ; 50 ; 0xc2968 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc2969 + push ax ; 50 ; 0xc296d + movzx ax, byte [bp-004h] ; 0f b6 46 fc ; 0xc296e + movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xc2972 + movzx dx, byte [bp-008h] ; 0f b6 56 f8 ; 0xc2976 + movzx si, ch ; 0f b6 f5 ; 0xc297a + mov cx, ax ; 89 c1 ; 0xc297d + mov ax, si ; 89 f0 ; 0xc297f + call 02284h ; e8 00 f9 ; 0xc2981 + jmp short 0299fh ; eb 19 ; 0xc2984 vgabios.c:1887 + movzx ax, byte [bp-010h] ; 0f b6 46 f0 ; 0xc2986 vgabios.c:1889 + push ax ; 50 ; 0xc298a + movzx si, byte [bp-004h] ; 0f b6 76 fc ; 0xc298b + movzx bx, byte [bp-006h] ; 0f b6 5e fa ; 0xc298f + movzx dx, byte [bp-008h] ; 0f b6 56 f8 ; 0xc2993 + movzx ax, ch ; 0f b6 c5 ; 0xc2997 + mov cx, si ; 89 f1 ; 0xc299a + call 02361h ; e8 c2 f9 ; 0xc299c + inc byte [bp-006h] ; fe 46 fa ; 0xc299f vgabios.c:1897 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc29a2 vgabios.c:1899 + cmp ax, word [bp-010h] ; 3b 46 f0 ; 0xc29a6 + jne short 029b2h ; 75 07 ; 0xc29a9 + mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xc29ab vgabios.c:1900 + inc byte [bp-004h] ; fe 46 fc ; 0xc29af vgabios.c:1901 + movzx ax, byte [bp-004h] ; 0f b6 46 fc ; 0xc29b2 vgabios.c:1906 + cmp ax, word [bp-00eh] ; 3b 46 f2 ; 0xc29b6 + jne near 02a3ah ; 0f 85 7d 00 ; 0xc29b9 + movzx bx, byte [bp-00ch] ; 0f b6 5e f4 ; 0xc29bd vgabios.c:1908 + sal bx, 003h ; c1 e3 03 ; 0xc29c1 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc29c4 + db 0feh, 0c8h + ; dec al ; fe c8 ; 0xc29c7 + mov ah, byte [bp-010h] ; 8a 66 f0 ; 0xc29c9 + db 0feh, 0cch + ; dec ah ; fe cc ; 0xc29cc + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc29ce + jne short 02a1dh ; 75 48 ; 0xc29d3 + mov dx, word [bp-010h] ; 8b 56 f0 ; 0xc29d5 vgabios.c:1910 + imul dx, word [bp-00eh] ; 0f af 56 f2 ; 0xc29d8 + add dx, dx ; 01 d2 ; 0xc29dc + or dl, 0ffh ; 80 ca ff ; 0xc29de + movzx si, byte [bp-00ah] ; 0f b6 76 f6 ; 0xc29e1 + inc dx ; 42 ; 0xc29e5 + imul si, dx ; 0f af f2 ; 0xc29e6 + movzx dx, byte [bp-004h] ; 0f b6 56 fc ; 0xc29e9 + dec dx ; 4a ; 0xc29ed + mov cx, word [bp-010h] ; 8b 4e f0 ; 0xc29ee + imul cx, dx ; 0f af ca ; 0xc29f1 + movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xc29f4 + add dx, cx ; 01 ca ; 0xc29f8 + add dx, dx ; 01 d2 ; 0xc29fa + add si, dx ; 01 d6 ; 0xc29fc + inc si ; 46 ; 0xc29fe vgabios.c:1911 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc29ff vgabios.c:45 + mov bl, byte [es:si] ; 26 8a 1c ; 0xc2a03 + push strict byte 00001h ; 6a 01 ; 0xc2a06 vgabios.c:1912 + movzx dx, byte [bp-00ah] ; 0f b6 56 f6 ; 0xc2a08 + push dx ; 52 ; 0xc2a0c + movzx dx, ah ; 0f b6 d4 ; 0xc2a0d + push dx ; 52 ; 0xc2a10 + xor ah, ah ; 30 e4 ; 0xc2a11 + push ax ; 50 ; 0xc2a13 + movzx dx, bl ; 0f b6 d3 ; 0xc2a14 + xor cx, cx ; 31 c9 ; 0xc2a17 + xor bx, bx ; 31 db ; 0xc2a19 + jmp short 02a31h ; eb 14 ; 0xc2a1b vgabios.c:1914 + push strict byte 00001h ; 6a 01 ; 0xc2a1d vgabios.c:1916 + movzx dx, byte [bp-00ah] ; 0f b6 56 f6 ; 0xc2a1f + push dx ; 52 ; 0xc2a23 + movzx dx, ah ; 0f b6 d4 ; 0xc2a24 + push dx ; 52 ; 0xc2a27 + xor ah, ah ; 30 e4 ; 0xc2a28 + push ax ; 50 ; 0xc2a2a + xor cx, cx ; 31 c9 ; 0xc2a2b + xor bx, bx ; 31 db ; 0xc2a2d + xor dx, dx ; 31 d2 ; 0xc2a2f + mov ax, strict word 00001h ; b8 01 00 ; 0xc2a31 + call 01b5dh ; e8 26 f1 ; 0xc2a34 + dec byte [bp-004h] ; fe 4e fc ; 0xc2a37 vgabios.c:1918 + movzx ax, byte [bp-004h] ; 0f b6 46 fc ; 0xc2a3a vgabios.c:1922 + mov word [bp-012h], ax ; 89 46 ee ; 0xc2a3e + sal word [bp-012h], 008h ; c1 66 ee 08 ; 0xc2a41 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc2a45 + add word [bp-012h], ax ; 01 46 ee ; 0xc2a49 + mov dx, word [bp-012h] ; 8b 56 ee ; 0xc2a4c vgabios.c:1923 + movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xc2a4f + call 01242h ; e8 ec e7 ; 0xc2a53 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2a56 vgabios.c:1924 + pop si ; 5e ; 0xc2a59 + pop bp ; 5d ; 0xc2a5a + retn ; c3 ; 0xc2a5b + ; disGetNextSymbol 0xc2a5c LB 0x185d -> off=0x0 cb=0000000000000033 uValue=00000000000c2a5c 'get_font_access' +get_font_access: ; 0xc2a5c LB 0x33 + push bp ; 55 ; 0xc2a5c vgabios.c:1927 + mov bp, sp ; 89 e5 ; 0xc2a5d + push dx ; 52 ; 0xc2a5f + mov ax, strict word 00005h ; b8 05 00 ; 0xc2a60 vgabios.c:1929 + mov dx, 003ceh ; ba ce 03 ; 0xc2a63 + out DX, ax ; ef ; 0xc2a66 + mov AL, strict byte 006h ; b0 06 ; 0xc2a67 vgabios.c:1930 + out DX, AL ; ee ; 0xc2a69 + mov dx, 003cfh ; ba cf 03 ; 0xc2a6a vgabios.c:1931 + in AL, DX ; ec ; 0xc2a6d + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2a6e + and ax, strict word 00001h ; 25 01 00 ; 0xc2a70 + or AL, strict byte 004h ; 0c 04 ; 0xc2a73 + sal ax, 008h ; c1 e0 08 ; 0xc2a75 + or AL, strict byte 006h ; 0c 06 ; 0xc2a78 + mov dx, 003ceh ; ba ce 03 ; 0xc2a7a + out DX, ax ; ef ; 0xc2a7d + mov ax, 00402h ; b8 02 04 ; 0xc2a7e vgabios.c:1932 + mov dx, 003c4h ; ba c4 03 ; 0xc2a81 + out DX, ax ; ef ; 0xc2a84 + mov ax, 00604h ; b8 04 06 ; 0xc2a85 vgabios.c:1933 + out DX, ax ; ef ; 0xc2a88 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2a89 vgabios.c:1934 + pop dx ; 5a ; 0xc2a8c + pop bp ; 5d ; 0xc2a8d + retn ; c3 ; 0xc2a8e + ; disGetNextSymbol 0xc2a8f LB 0x182a -> off=0x0 cb=0000000000000030 uValue=00000000000c2a8f 'release_font_access' +release_font_access: ; 0xc2a8f LB 0x30 + push bp ; 55 ; 0xc2a8f vgabios.c:1936 + mov bp, sp ; 89 e5 ; 0xc2a90 + push dx ; 52 ; 0xc2a92 + mov dx, 003cch ; ba cc 03 ; 0xc2a93 vgabios.c:1938 + in AL, DX ; ec ; 0xc2a96 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2a97 + and ax, strict word 00001h ; 25 01 00 ; 0xc2a99 + sal ax, 002h ; c1 e0 02 ; 0xc2a9c + or AL, strict byte 00ah ; 0c 0a ; 0xc2a9f + sal ax, 008h ; c1 e0 08 ; 0xc2aa1 + or AL, strict byte 006h ; 0c 06 ; 0xc2aa4 + mov dx, 003ceh ; ba ce 03 ; 0xc2aa6 + out DX, ax ; ef ; 0xc2aa9 + mov ax, 01005h ; b8 05 10 ; 0xc2aaa vgabios.c:1939 + out DX, ax ; ef ; 0xc2aad + mov ax, 00302h ; b8 02 03 ; 0xc2aae vgabios.c:1940 + mov dx, 003c4h ; ba c4 03 ; 0xc2ab1 + out DX, ax ; ef ; 0xc2ab4 + mov ax, 00204h ; b8 04 02 ; 0xc2ab5 vgabios.c:1941 + out DX, ax ; ef ; 0xc2ab8 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2ab9 vgabios.c:1942 + pop dx ; 5a ; 0xc2abc + pop bp ; 5d ; 0xc2abd + retn ; c3 ; 0xc2abe + ; disGetNextSymbol 0xc2abf LB 0x17fa -> off=0x0 cb=00000000000000b4 uValue=00000000000c2abf 'set_scan_lines' +set_scan_lines: ; 0xc2abf LB 0xb4 + push bp ; 55 ; 0xc2abf vgabios.c:1944 + mov bp, sp ; 89 e5 ; 0xc2ac0 + push bx ; 53 ; 0xc2ac2 + push cx ; 51 ; 0xc2ac3 + push dx ; 52 ; 0xc2ac4 + push si ; 56 ; 0xc2ac5 + push di ; 57 ; 0xc2ac6 + mov bl, al ; 88 c3 ; 0xc2ac7 + mov si, strict word 00063h ; be 63 00 ; 0xc2ac9 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2acc + mov es, ax ; 8e c0 ; 0xc2acf + mov si, word [es:si] ; 26 8b 34 ; 0xc2ad1 + mov cx, si ; 89 f1 ; 0xc2ad4 vgabios.c:58 + mov AL, strict byte 009h ; b0 09 ; 0xc2ad6 vgabios.c:1950 + mov dx, si ; 89 f2 ; 0xc2ad8 + out DX, AL ; ee ; 0xc2ada + lea dx, [si+001h] ; 8d 54 01 ; 0xc2adb vgabios.c:1951 + in AL, DX ; ec ; 0xc2ade + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2adf + mov ah, al ; 88 c4 ; 0xc2ae1 vgabios.c:1952 + and ah, 0e0h ; 80 e4 e0 ; 0xc2ae3 + mov al, bl ; 88 d8 ; 0xc2ae6 + db 0feh, 0c8h + ; dec al ; fe c8 ; 0xc2ae8 + or al, ah ; 08 e0 ; 0xc2aea + out DX, AL ; ee ; 0xc2aec vgabios.c:1953 + cmp bl, 008h ; 80 fb 08 ; 0xc2aed vgabios.c:1954 + jne short 02afah ; 75 08 ; 0xc2af0 + mov dx, strict word 00007h ; ba 07 00 ; 0xc2af2 vgabios.c:1956 + mov ax, strict word 00006h ; b8 06 00 ; 0xc2af5 + jmp short 02b07h ; eb 0d ; 0xc2af8 vgabios.c:1958 + mov al, bl ; 88 d8 ; 0xc2afa vgabios.c:1960 + sub AL, strict byte 003h ; 2c 03 ; 0xc2afc + movzx dx, al ; 0f b6 d0 ; 0xc2afe + mov al, bl ; 88 d8 ; 0xc2b01 + sub AL, strict byte 004h ; 2c 04 ; 0xc2b03 + xor ah, ah ; 30 e4 ; 0xc2b05 + call 0114ch ; e8 42 e6 ; 0xc2b07 + movzx di, bl ; 0f b6 fb ; 0xc2b0a vgabios.c:1962 + mov bx, 00085h ; bb 85 00 ; 0xc2b0d vgabios.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2b10 + mov es, ax ; 8e c0 ; 0xc2b13 + mov word [es:bx], di ; 26 89 3f ; 0xc2b15 + mov AL, strict byte 012h ; b0 12 ; 0xc2b18 vgabios.c:1963 + mov dx, cx ; 89 ca ; 0xc2b1a + out DX, AL ; ee ; 0xc2b1c + mov bx, cx ; 89 cb ; 0xc2b1d vgabios.c:1964 + inc bx ; 43 ; 0xc2b1f + mov dx, bx ; 89 da ; 0xc2b20 + in AL, DX ; ec ; 0xc2b22 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2b23 + mov si, ax ; 89 c6 ; 0xc2b25 + mov AL, strict byte 007h ; b0 07 ; 0xc2b27 vgabios.c:1965 + mov dx, cx ; 89 ca ; 0xc2b29 + out DX, AL ; ee ; 0xc2b2b + mov dx, bx ; 89 da ; 0xc2b2c vgabios.c:1966 + in AL, DX ; ec ; 0xc2b2e + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2b2f + mov ah, al ; 88 c4 ; 0xc2b31 vgabios.c:1967 + and ah, 002h ; 80 e4 02 ; 0xc2b33 + movzx dx, ah ; 0f b6 d4 ; 0xc2b36 + sal dx, 007h ; c1 e2 07 ; 0xc2b39 + and AL, strict byte 040h ; 24 40 ; 0xc2b3c + xor ah, ah ; 30 e4 ; 0xc2b3e + sal ax, 003h ; c1 e0 03 ; 0xc2b40 + add ax, dx ; 01 d0 ; 0xc2b43 + inc ax ; 40 ; 0xc2b45 + add ax, si ; 01 f0 ; 0xc2b46 + xor dx, dx ; 31 d2 ; 0xc2b48 vgabios.c:1968 + div di ; f7 f7 ; 0xc2b4a + mov dl, al ; 88 c2 ; 0xc2b4c vgabios.c:1969 + db 0feh, 0cah + ; dec dl ; fe ca ; 0xc2b4e + mov bx, 00084h ; bb 84 00 ; 0xc2b50 vgabios.c:52 + mov byte [es:bx], dl ; 26 88 17 ; 0xc2b53 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2b56 vgabios.c:57 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc2b59 + xor ah, ah ; 30 e4 ; 0xc2b5c vgabios.c:1971 + imul dx, ax ; 0f af d0 ; 0xc2b5e + add dx, dx ; 01 d2 ; 0xc2b61 + mov bx, strict word 0004ch ; bb 4c 00 ; 0xc2b63 vgabios.c:62 + mov word [es:bx], dx ; 26 89 17 ; 0xc2b66 + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc2b69 vgabios.c:1972 + pop di ; 5f ; 0xc2b6c + pop si ; 5e ; 0xc2b6d + pop dx ; 5a ; 0xc2b6e + pop cx ; 59 ; 0xc2b6f + pop bx ; 5b ; 0xc2b70 + pop bp ; 5d ; 0xc2b71 + retn ; c3 ; 0xc2b72 + ; disGetNextSymbol 0xc2b73 LB 0x1746 -> off=0x0 cb=0000000000000022 uValue=00000000000c2b73 'biosfn_set_font_block' +biosfn_set_font_block: ; 0xc2b73 LB 0x22 + push bp ; 55 ; 0xc2b73 vgabios.c:1974 + mov bp, sp ; 89 e5 ; 0xc2b74 + push bx ; 53 ; 0xc2b76 + push dx ; 52 ; 0xc2b77 + mov bl, al ; 88 c3 ; 0xc2b78 + mov ax, 00100h ; b8 00 01 ; 0xc2b7a vgabios.c:1976 + mov dx, 003c4h ; ba c4 03 ; 0xc2b7d + out DX, ax ; ef ; 0xc2b80 + movzx ax, bl ; 0f b6 c3 ; 0xc2b81 vgabios.c:1977 + sal ax, 008h ; c1 e0 08 ; 0xc2b84 + or AL, strict byte 003h ; 0c 03 ; 0xc2b87 + out DX, ax ; ef ; 0xc2b89 + mov ax, 00300h ; b8 00 03 ; 0xc2b8a vgabios.c:1978 + out DX, ax ; ef ; 0xc2b8d + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2b8e vgabios.c:1979 + pop dx ; 5a ; 0xc2b91 + pop bx ; 5b ; 0xc2b92 + pop bp ; 5d ; 0xc2b93 + retn ; c3 ; 0xc2b94 + ; disGetNextSymbol 0xc2b95 LB 0x1724 -> off=0x0 cb=0000000000000075 uValue=00000000000c2b95 'load_text_patch' +load_text_patch: ; 0xc2b95 LB 0x75 + push bp ; 55 ; 0xc2b95 vgabios.c:1981 + mov bp, sp ; 89 e5 ; 0xc2b96 + push si ; 56 ; 0xc2b98 + push di ; 57 ; 0xc2b99 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc2b9a + push ax ; 50 ; 0xc2b9d + mov byte [bp-006h], cl ; 88 4e fa ; 0xc2b9e + call 02a5ch ; e8 b8 fe ; 0xc2ba1 vgabios.c:1986 + mov al, bl ; 88 d8 ; 0xc2ba4 vgabios.c:1988 + and AL, strict byte 003h ; 24 03 ; 0xc2ba6 + movzx cx, al ; 0f b6 c8 ; 0xc2ba8 + sal cx, 00eh ; c1 e1 0e ; 0xc2bab + mov al, bl ; 88 d8 ; 0xc2bae + and AL, strict byte 004h ; 24 04 ; 0xc2bb0 + xor ah, ah ; 30 e4 ; 0xc2bb2 + sal ax, 00bh ; c1 e0 0b ; 0xc2bb4 + add cx, ax ; 01 c1 ; 0xc2bb7 + mov word [bp-00ch], cx ; 89 4e f4 ; 0xc2bb9 + mov bx, dx ; 89 d3 ; 0xc2bbc vgabios.c:1989 + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc2bbe + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc2bc1 + inc dx ; 42 ; 0xc2bc4 vgabios.c:1990 + mov word [bp-008h], dx ; 89 56 f8 ; 0xc2bc5 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc2bc8 vgabios.c:1991 + cmp byte [es:bx], 000h ; 26 80 3f 00 ; 0xc2bcb + je short 02c00h ; 74 2f ; 0xc2bcf + movzx ax, byte [es:bx] ; 26 0f b6 07 ; 0xc2bd1 vgabios.c:1992 + sal ax, 005h ; c1 e0 05 ; 0xc2bd5 + mov di, word [bp-00ch] ; 8b 7e f4 ; 0xc2bd8 + add di, ax ; 01 c7 ; 0xc2bdb + movzx cx, byte [bp-006h] ; 0f b6 4e fa ; 0xc2bdd vgabios.c:1993 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc2be1 + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc2be4 + mov ax, 0a000h ; b8 00 a0 ; 0xc2be7 + mov es, ax ; 8e c0 ; 0xc2bea + jcxz 02bf4h ; e3 06 ; 0xc2bec + push DS ; 1e ; 0xc2bee + mov ds, dx ; 8e da ; 0xc2bef + rep movsb ; f3 a4 ; 0xc2bf1 + pop DS ; 1f ; 0xc2bf3 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc2bf4 vgabios.c:1994 + inc ax ; 40 ; 0xc2bf8 + add word [bp-008h], ax ; 01 46 f8 ; 0xc2bf9 + add bx, ax ; 01 c3 ; 0xc2bfc vgabios.c:1995 + jmp short 02bc8h ; eb c8 ; 0xc2bfe vgabios.c:1996 + call 02a8fh ; e8 8c fe ; 0xc2c00 vgabios.c:1998 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2c03 vgabios.c:1999 + pop di ; 5f ; 0xc2c06 + pop si ; 5e ; 0xc2c07 + pop bp ; 5d ; 0xc2c08 + retn ; c3 ; 0xc2c09 + ; disGetNextSymbol 0xc2c0a LB 0x16af -> off=0x0 cb=000000000000007c uValue=00000000000c2c0a 'biosfn_load_text_user_pat' +biosfn_load_text_user_pat: ; 0xc2c0a LB 0x7c + push bp ; 55 ; 0xc2c0a vgabios.c:2001 + mov bp, sp ; 89 e5 ; 0xc2c0b + push si ; 56 ; 0xc2c0d + push di ; 57 ; 0xc2c0e + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc2c0f + mov byte [bp-006h], al ; 88 46 fa ; 0xc2c12 + mov word [bp-00ch], dx ; 89 56 f4 ; 0xc2c15 + mov word [bp-008h], bx ; 89 5e f8 ; 0xc2c18 + mov word [bp-00ah], cx ; 89 4e f6 ; 0xc2c1b + call 02a5ch ; e8 3b fe ; 0xc2c1e vgabios.c:2006 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc2c21 vgabios.c:2007 + and AL, strict byte 003h ; 24 03 ; 0xc2c24 + xor ah, ah ; 30 e4 ; 0xc2c26 + mov bx, ax ; 89 c3 ; 0xc2c28 + sal bx, 00eh ; c1 e3 0e ; 0xc2c2a + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc2c2d + and AL, strict byte 004h ; 24 04 ; 0xc2c30 + xor ah, ah ; 30 e4 ; 0xc2c32 + sal ax, 00bh ; c1 e0 0b ; 0xc2c34 + add bx, ax ; 01 c3 ; 0xc2c37 + mov word [bp-00eh], bx ; 89 5e f2 ; 0xc2c39 + xor bx, bx ; 31 db ; 0xc2c3c vgabios.c:2008 + cmp bx, word [bp-00ah] ; 3b 5e f6 ; 0xc2c3e + jnc short 02c6dh ; 73 2a ; 0xc2c41 + movzx cx, byte [bp+008h] ; 0f b6 4e 08 ; 0xc2c43 vgabios.c:2010 + mov si, bx ; 89 de ; 0xc2c47 + imul si, cx ; 0f af f1 ; 0xc2c49 + add si, word [bp-008h] ; 03 76 f8 ; 0xc2c4c + mov di, word [bp+004h] ; 8b 7e 04 ; 0xc2c4f vgabios.c:2011 + add di, bx ; 01 df ; 0xc2c52 + sal di, 005h ; c1 e7 05 ; 0xc2c54 + add di, word [bp-00eh] ; 03 7e f2 ; 0xc2c57 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc2c5a vgabios.c:2012 + mov ax, 0a000h ; b8 00 a0 ; 0xc2c5d + mov es, ax ; 8e c0 ; 0xc2c60 + jcxz 02c6ah ; e3 06 ; 0xc2c62 + push DS ; 1e ; 0xc2c64 + mov ds, dx ; 8e da ; 0xc2c65 + rep movsb ; f3 a4 ; 0xc2c67 + pop DS ; 1f ; 0xc2c69 + inc bx ; 43 ; 0xc2c6a vgabios.c:2013 + jmp short 02c3eh ; eb d1 ; 0xc2c6b + call 02a8fh ; e8 1f fe ; 0xc2c6d vgabios.c:2014 + cmp byte [bp-006h], 010h ; 80 7e fa 10 ; 0xc2c70 vgabios.c:2015 + jc short 02c7dh ; 72 07 ; 0xc2c74 + movzx ax, byte [bp+008h] ; 0f b6 46 08 ; 0xc2c76 vgabios.c:2017 + call 02abfh ; e8 42 fe ; 0xc2c7a + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2c7d vgabios.c:2019 + pop di ; 5f ; 0xc2c80 + pop si ; 5e ; 0xc2c81 + pop bp ; 5d ; 0xc2c82 + retn 00006h ; c2 06 00 ; 0xc2c83 + ; disGetNextSymbol 0xc2c86 LB 0x1633 -> off=0x0 cb=0000000000000016 uValue=00000000000c2c86 'biosfn_load_gfx_8_8_chars' +biosfn_load_gfx_8_8_chars: ; 0xc2c86 LB 0x16 + push bp ; 55 ; 0xc2c86 vgabios.c:2021 + mov bp, sp ; 89 e5 ; 0xc2c87 + push bx ; 53 ; 0xc2c89 + push cx ; 51 ; 0xc2c8a + mov bx, dx ; 89 d3 ; 0xc2c8b vgabios.c:2023 + mov cx, ax ; 89 c1 ; 0xc2c8d + mov ax, strict word 0001fh ; b8 1f 00 ; 0xc2c8f + call 009f0h ; e8 5b dd ; 0xc2c92 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2c95 vgabios.c:2024 + pop cx ; 59 ; 0xc2c98 + pop bx ; 5b ; 0xc2c99 + pop bp ; 5d ; 0xc2c9a + retn ; c3 ; 0xc2c9b + ; disGetNextSymbol 0xc2c9c LB 0x161d -> off=0x0 cb=0000000000000049 uValue=00000000000c2c9c 'set_gfx_font' +set_gfx_font: ; 0xc2c9c LB 0x49 + push bp ; 55 ; 0xc2c9c vgabios.c:2026 + mov bp, sp ; 89 e5 ; 0xc2c9d + push si ; 56 ; 0xc2c9f + push di ; 57 ; 0xc2ca0 + mov si, dx ; 89 d6 ; 0xc2ca1 + mov di, bx ; 89 df ; 0xc2ca3 + mov dl, cl ; 88 ca ; 0xc2ca5 + mov bx, ax ; 89 c3 ; 0xc2ca7 vgabios.c:2030 + mov cx, si ; 89 f1 ; 0xc2ca9 + mov ax, strict word 00043h ; b8 43 00 ; 0xc2cab + call 009f0h ; e8 3f dd ; 0xc2cae + test dl, dl ; 84 d2 ; 0xc2cb1 vgabios.c:2031 + je short 02cc6h ; 74 11 ; 0xc2cb3 + cmp dl, 003h ; 80 fa 03 ; 0xc2cb5 vgabios.c:2032 + jbe short 02cbch ; 76 02 ; 0xc2cb8 + mov DL, strict byte 002h ; b2 02 ; 0xc2cba vgabios.c:2033 + movzx bx, dl ; 0f b6 da ; 0xc2cbc vgabios.c:2034 + mov al, byte [bx+07dfeh] ; 8a 87 fe 7d ; 0xc2cbf + mov byte [bp+004h], al ; 88 46 04 ; 0xc2cc3 + mov bx, 00085h ; bb 85 00 ; 0xc2cc6 vgabios.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2cc9 + mov es, ax ; 8e c0 ; 0xc2ccc + mov word [es:bx], di ; 26 89 3f ; 0xc2cce + movzx ax, byte [bp+004h] ; 0f b6 46 04 ; 0xc2cd1 vgabios.c:2039 + dec ax ; 48 ; 0xc2cd5 + mov bx, 00084h ; bb 84 00 ; 0xc2cd6 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc2cd9 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2cdc vgabios.c:2040 + pop di ; 5f ; 0xc2cdf + pop si ; 5e ; 0xc2ce0 + pop bp ; 5d ; 0xc2ce1 + retn 00002h ; c2 02 00 ; 0xc2ce2 + ; disGetNextSymbol 0xc2ce5 LB 0x15d4 -> off=0x0 cb=000000000000001c uValue=00000000000c2ce5 'biosfn_load_gfx_user_chars' +biosfn_load_gfx_user_chars: ; 0xc2ce5 LB 0x1c + push bp ; 55 ; 0xc2ce5 vgabios.c:2042 + mov bp, sp ; 89 e5 ; 0xc2ce6 + push si ; 56 ; 0xc2ce8 + mov si, ax ; 89 c6 ; 0xc2ce9 + mov ax, dx ; 89 d0 ; 0xc2ceb + movzx dx, byte [bp+004h] ; 0f b6 56 04 ; 0xc2ced vgabios.c:2045 + push dx ; 52 ; 0xc2cf1 + xor ch, ch ; 30 ed ; 0xc2cf2 + mov dx, si ; 89 f2 ; 0xc2cf4 + call 02c9ch ; e8 a3 ff ; 0xc2cf6 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2cf9 vgabios.c:2046 + pop si ; 5e ; 0xc2cfc + pop bp ; 5d ; 0xc2cfd + retn 00002h ; c2 02 00 ; 0xc2cfe + ; disGetNextSymbol 0xc2d01 LB 0x15b8 -> off=0x0 cb=000000000000001e uValue=00000000000c2d01 'biosfn_load_gfx_8_14_chars' +biosfn_load_gfx_8_14_chars: ; 0xc2d01 LB 0x1e + push bp ; 55 ; 0xc2d01 vgabios.c:2051 + mov bp, sp ; 89 e5 ; 0xc2d02 + push bx ; 53 ; 0xc2d04 + push cx ; 51 ; 0xc2d05 + movzx cx, dl ; 0f b6 ca ; 0xc2d06 vgabios.c:2053 + push cx ; 51 ; 0xc2d09 + movzx cx, al ; 0f b6 c8 ; 0xc2d0a + mov bx, strict word 0000eh ; bb 0e 00 ; 0xc2d0d + mov ax, 05d6dh ; b8 6d 5d ; 0xc2d10 + mov dx, ds ; 8c da ; 0xc2d13 + call 02c9ch ; e8 84 ff ; 0xc2d15 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2d18 vgabios.c:2054 + pop cx ; 59 ; 0xc2d1b + pop bx ; 5b ; 0xc2d1c + pop bp ; 5d ; 0xc2d1d + retn ; c3 ; 0xc2d1e + ; disGetNextSymbol 0xc2d1f LB 0x159a -> off=0x0 cb=000000000000001e uValue=00000000000c2d1f 'biosfn_load_gfx_8_8_dd_chars' +biosfn_load_gfx_8_8_dd_chars: ; 0xc2d1f LB 0x1e + push bp ; 55 ; 0xc2d1f vgabios.c:2055 + mov bp, sp ; 89 e5 ; 0xc2d20 + push bx ; 53 ; 0xc2d22 + push cx ; 51 ; 0xc2d23 + movzx cx, dl ; 0f b6 ca ; 0xc2d24 vgabios.c:2057 + push cx ; 51 ; 0xc2d27 + movzx cx, al ; 0f b6 c8 ; 0xc2d28 + mov bx, strict word 00008h ; bb 08 00 ; 0xc2d2b + mov ax, 0556dh ; b8 6d 55 ; 0xc2d2e + mov dx, ds ; 8c da ; 0xc2d31 + call 02c9ch ; e8 66 ff ; 0xc2d33 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2d36 vgabios.c:2058 + pop cx ; 59 ; 0xc2d39 + pop bx ; 5b ; 0xc2d3a + pop bp ; 5d ; 0xc2d3b + retn ; c3 ; 0xc2d3c + ; disGetNextSymbol 0xc2d3d LB 0x157c -> off=0x0 cb=000000000000001e uValue=00000000000c2d3d 'biosfn_load_gfx_8_16_chars' +biosfn_load_gfx_8_16_chars: ; 0xc2d3d LB 0x1e + push bp ; 55 ; 0xc2d3d vgabios.c:2059 + mov bp, sp ; 89 e5 ; 0xc2d3e + push bx ; 53 ; 0xc2d40 + push cx ; 51 ; 0xc2d41 + movzx cx, dl ; 0f b6 ca ; 0xc2d42 vgabios.c:2061 + push cx ; 51 ; 0xc2d45 + movzx cx, al ; 0f b6 c8 ; 0xc2d46 + mov bx, strict word 00010h ; bb 10 00 ; 0xc2d49 + mov ax, 06b6dh ; b8 6d 6b ; 0xc2d4c + mov dx, ds ; 8c da ; 0xc2d4f + call 02c9ch ; e8 48 ff ; 0xc2d51 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2d54 vgabios.c:2062 + pop cx ; 59 ; 0xc2d57 + pop bx ; 5b ; 0xc2d58 + pop bp ; 5d ; 0xc2d59 + retn ; c3 ; 0xc2d5a + ; disGetNextSymbol 0xc2d5b LB 0x155e -> off=0x0 cb=0000000000000005 uValue=00000000000c2d5b 'biosfn_alternate_prtsc' +biosfn_alternate_prtsc: ; 0xc2d5b LB 0x5 + push bp ; 55 ; 0xc2d5b vgabios.c:2064 + mov bp, sp ; 89 e5 ; 0xc2d5c + pop bp ; 5d ; 0xc2d5e vgabios.c:2069 + retn ; c3 ; 0xc2d5f + ; disGetNextSymbol 0xc2d60 LB 0x1559 -> off=0x0 cb=0000000000000032 uValue=00000000000c2d60 'biosfn_set_txt_lines' +biosfn_set_txt_lines: ; 0xc2d60 LB 0x32 + push bx ; 53 ; 0xc2d60 vgabios.c:2071 + push si ; 56 ; 0xc2d61 + push bp ; 55 ; 0xc2d62 + mov bp, sp ; 89 e5 ; 0xc2d63 + mov bl, al ; 88 c3 ; 0xc2d65 + mov si, 00089h ; be 89 00 ; 0xc2d67 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2d6a + mov es, ax ; 8e c0 ; 0xc2d6d + mov al, byte [es:si] ; 26 8a 04 ; 0xc2d6f + and AL, strict byte 06fh ; 24 6f ; 0xc2d72 vgabios.c:2077 + cmp bl, 002h ; 80 fb 02 ; 0xc2d74 vgabios.c:2079 + je short 02d81h ; 74 08 ; 0xc2d77 + test bl, bl ; 84 db ; 0xc2d79 + jne short 02d83h ; 75 06 ; 0xc2d7b + or AL, strict byte 080h ; 0c 80 ; 0xc2d7d vgabios.c:2082 + jmp short 02d83h ; eb 02 ; 0xc2d7f vgabios.c:2083 + or AL, strict byte 010h ; 0c 10 ; 0xc2d81 vgabios.c:2085 + mov bx, 00089h ; bb 89 00 ; 0xc2d83 vgabios.c:52 + mov si, strict word 00040h ; be 40 00 ; 0xc2d86 + mov es, si ; 8e c6 ; 0xc2d89 + mov byte [es:bx], al ; 26 88 07 ; 0xc2d8b + pop bp ; 5d ; 0xc2d8e vgabios.c:2089 + pop si ; 5e ; 0xc2d8f + pop bx ; 5b ; 0xc2d90 + retn ; c3 ; 0xc2d91 + ; disGetNextSymbol 0xc2d92 LB 0x1527 -> off=0x0 cb=0000000000000005 uValue=00000000000c2d92 'biosfn_switch_video_interface' +biosfn_switch_video_interface: ; 0xc2d92 LB 0x5 + push bp ; 55 ; 0xc2d92 vgabios.c:2092 + mov bp, sp ; 89 e5 ; 0xc2d93 + pop bp ; 5d ; 0xc2d95 vgabios.c:2097 + retn ; c3 ; 0xc2d96 + ; disGetNextSymbol 0xc2d97 LB 0x1522 -> off=0x0 cb=0000000000000005 uValue=00000000000c2d97 'biosfn_enable_video_refresh_control' +biosfn_enable_video_refresh_control: ; 0xc2d97 LB 0x5 + push bp ; 55 ; 0xc2d97 vgabios.c:2098 + mov bp, sp ; 89 e5 ; 0xc2d98 + pop bp ; 5d ; 0xc2d9a vgabios.c:2103 + retn ; c3 ; 0xc2d9b + ; disGetNextSymbol 0xc2d9c LB 0x151d -> off=0x0 cb=0000000000000096 uValue=00000000000c2d9c 'biosfn_write_string' +biosfn_write_string: ; 0xc2d9c LB 0x96 + push bp ; 55 ; 0xc2d9c vgabios.c:2106 + mov bp, sp ; 89 e5 ; 0xc2d9d + push si ; 56 ; 0xc2d9f + push di ; 57 ; 0xc2da0 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc2da1 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc2da4 + mov byte [bp-006h], dl ; 88 56 fa ; 0xc2da7 + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc2daa + mov si, cx ; 89 ce ; 0xc2dad + mov di, word [bp+00ah] ; 8b 7e 0a ; 0xc2daf + movzx ax, dl ; 0f b6 c2 ; 0xc2db2 vgabios.c:2113 + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc2db5 + lea dx, [bp-00ch] ; 8d 56 f4 ; 0xc2db8 + call 00a93h ; e8 d5 dc ; 0xc2dbb + cmp byte [bp+004h], 0ffh ; 80 7e 04 ff ; 0xc2dbe vgabios.c:2116 + jne short 02dd5h ; 75 11 ; 0xc2dc2 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2dc4 vgabios.c:2117 + mov byte [bp+006h], al ; 88 46 06 ; 0xc2dc7 + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc2dca vgabios.c:2118 + xor al, al ; 30 c0 ; 0xc2dcd + shr ax, 008h ; c1 e8 08 ; 0xc2dcf + mov byte [bp+004h], al ; 88 46 04 ; 0xc2dd2 + movzx dx, byte [bp+004h] ; 0f b6 56 04 ; 0xc2dd5 vgabios.c:2121 + sal dx, 008h ; c1 e2 08 ; 0xc2dd9 + movzx ax, byte [bp+006h] ; 0f b6 46 06 ; 0xc2ddc + add dx, ax ; 01 c2 ; 0xc2de0 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc2de2 vgabios.c:2122 + call 01242h ; e8 59 e4 ; 0xc2de6 + dec si ; 4e ; 0xc2de9 vgabios.c:2124 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc2dea + je short 02e19h ; 74 2a ; 0xc2ded + mov bx, di ; 89 fb ; 0xc2def vgabios.c:2126 + inc di ; 47 ; 0xc2df1 + mov es, [bp+008h] ; 8e 46 08 ; 0xc2df2 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2df5 + test byte [bp-008h], 002h ; f6 46 f8 02 ; 0xc2df8 vgabios.c:2127 + je short 02e07h ; 74 09 ; 0xc2dfc + mov bx, di ; 89 fb ; 0xc2dfe vgabios.c:2128 + inc di ; 47 ; 0xc2e00 + mov ah, byte [es:bx] ; 26 8a 27 ; 0xc2e01 vgabios.c:47 + mov byte [bp-00ah], ah ; 88 66 f6 ; 0xc2e04 vgabios.c:48 + movzx bx, byte [bp-00ah] ; 0f b6 5e f6 ; 0xc2e07 vgabios.c:2130 + movzx dx, byte [bp-006h] ; 0f b6 56 fa ; 0xc2e0b + xor ah, ah ; 30 e4 ; 0xc2e0f + mov cx, strict word 00003h ; b9 03 00 ; 0xc2e11 + call 02812h ; e8 fb f9 ; 0xc2e14 + jmp short 02de9h ; eb d0 ; 0xc2e17 vgabios.c:2131 + test byte [bp-008h], 001h ; f6 46 f8 01 ; 0xc2e19 vgabios.c:2134 + jne short 02e29h ; 75 0a ; 0xc2e1d + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc2e1f vgabios.c:2135 + movzx ax, byte [bp-006h] ; 0f b6 46 fa ; 0xc2e22 + call 01242h ; e8 19 e4 ; 0xc2e26 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2e29 vgabios.c:2136 + pop di ; 5f ; 0xc2e2c + pop si ; 5e ; 0xc2e2d + pop bp ; 5d ; 0xc2e2e + retn 00008h ; c2 08 00 ; 0xc2e2f + ; disGetNextSymbol 0xc2e32 LB 0x1487 -> off=0x0 cb=00000000000001f2 uValue=00000000000c2e32 'biosfn_read_state_info' +biosfn_read_state_info: ; 0xc2e32 LB 0x1f2 + push bp ; 55 ; 0xc2e32 vgabios.c:2139 + mov bp, sp ; 89 e5 ; 0xc2e33 + push cx ; 51 ; 0xc2e35 + push si ; 56 ; 0xc2e36 + push di ; 57 ; 0xc2e37 + push ax ; 50 ; 0xc2e38 + push ax ; 50 ; 0xc2e39 + push dx ; 52 ; 0xc2e3a + mov si, strict word 00049h ; be 49 00 ; 0xc2e3b vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2e3e + mov es, ax ; 8e c0 ; 0xc2e41 + mov al, byte [es:si] ; 26 8a 04 ; 0xc2e43 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc2e46 vgabios.c:48 + mov si, strict word 0004ch ; be 4c 00 ; 0xc2e49 vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc2e4c + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc2e4f vgabios.c:58 + mov ax, ds ; 8c d8 ; 0xc2e52 vgabios.c:2150 + mov es, dx ; 8e c2 ; 0xc2e54 vgabios.c:72 + mov word [es:bx], 05503h ; 26 c7 07 03 55 ; 0xc2e56 + mov [es:bx+002h], ds ; 26 8c 5f 02 ; 0xc2e5b + lea di, [bx+004h] ; 8d 7f 04 ; 0xc2e5f vgabios.c:2155 + mov cx, strict word 0001eh ; b9 1e 00 ; 0xc2e62 + mov si, strict word 00049h ; be 49 00 ; 0xc2e65 + mov dx, strict word 00040h ; ba 40 00 ; 0xc2e68 + jcxz 02e73h ; e3 06 ; 0xc2e6b + push DS ; 1e ; 0xc2e6d + mov ds, dx ; 8e da ; 0xc2e6e + rep movsb ; f3 a4 ; 0xc2e70 + pop DS ; 1f ; 0xc2e72 + mov si, 00084h ; be 84 00 ; 0xc2e73 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2e76 + mov es, ax ; 8e c0 ; 0xc2e79 + mov al, byte [es:si] ; 26 8a 04 ; 0xc2e7b + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc2e7e vgabios.c:48 + lea si, [bx+022h] ; 8d 77 22 ; 0xc2e80 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc2e83 vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc2e86 + lea di, [bx+023h] ; 8d 7f 23 ; 0xc2e89 vgabios.c:2157 + mov cx, strict word 00002h ; b9 02 00 ; 0xc2e8c + mov si, 00085h ; be 85 00 ; 0xc2e8f + mov dx, strict word 00040h ; ba 40 00 ; 0xc2e92 + jcxz 02e9dh ; e3 06 ; 0xc2e95 + push DS ; 1e ; 0xc2e97 + mov ds, dx ; 8e da ; 0xc2e98 + rep movsb ; f3 a4 ; 0xc2e9a + pop DS ; 1f ; 0xc2e9c + mov si, 0008ah ; be 8a 00 ; 0xc2e9d vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2ea0 + mov es, ax ; 8e c0 ; 0xc2ea3 + mov al, byte [es:si] ; 26 8a 04 ; 0xc2ea5 + lea si, [bx+025h] ; 8d 77 25 ; 0xc2ea8 vgabios.c:48 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc2eab vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc2eae + lea si, [bx+026h] ; 8d 77 26 ; 0xc2eb1 vgabios.c:2160 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc2eb4 vgabios.c:52 + lea si, [bx+027h] ; 8d 77 27 ; 0xc2eb8 vgabios.c:2161 + mov word [es:si], strict word 00010h ; 26 c7 04 10 00 ; 0xc2ebb vgabios.c:62 + lea si, [bx+029h] ; 8d 77 29 ; 0xc2ec0 vgabios.c:2162 + mov byte [es:si], 008h ; 26 c6 04 08 ; 0xc2ec3 vgabios.c:52 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc2ec7 vgabios.c:2163 + mov byte [es:si], 002h ; 26 c6 04 02 ; 0xc2eca vgabios.c:52 + lea si, [bx+02bh] ; 8d 77 2b ; 0xc2ece vgabios.c:2164 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc2ed1 vgabios.c:52 + lea si, [bx+02ch] ; 8d 77 2c ; 0xc2ed5 vgabios.c:2165 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc2ed8 vgabios.c:52 + lea si, [bx+02dh] ; 8d 77 2d ; 0xc2edc vgabios.c:2166 + mov byte [es:si], 021h ; 26 c6 04 21 ; 0xc2edf vgabios.c:52 + lea si, [bx+031h] ; 8d 77 31 ; 0xc2ee3 vgabios.c:2167 + mov byte [es:si], 003h ; 26 c6 04 03 ; 0xc2ee6 vgabios.c:52 + lea si, [bx+032h] ; 8d 77 32 ; 0xc2eea vgabios.c:2168 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc2eed vgabios.c:52 + mov si, 00089h ; be 89 00 ; 0xc2ef1 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2ef4 + mov es, ax ; 8e c0 ; 0xc2ef7 + mov al, byte [es:si] ; 26 8a 04 ; 0xc2ef9 + mov ah, al ; 88 c4 ; 0xc2efc vgabios.c:2173 + and ah, 080h ; 80 e4 80 ; 0xc2efe + movzx si, ah ; 0f b6 f4 ; 0xc2f01 + sar si, 006h ; c1 fe 06 ; 0xc2f04 + and AL, strict byte 010h ; 24 10 ; 0xc2f07 + xor ah, ah ; 30 e4 ; 0xc2f09 + sar ax, 004h ; c1 f8 04 ; 0xc2f0b + or ax, si ; 09 f0 ; 0xc2f0e + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc2f10 vgabios.c:2174 + je short 02f26h ; 74 11 ; 0xc2f13 + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc2f15 + je short 02f22h ; 74 08 ; 0xc2f18 + test ax, ax ; 85 c0 ; 0xc2f1a + jne short 02f26h ; 75 08 ; 0xc2f1c + mov AL, strict byte 001h ; b0 01 ; 0xc2f1e vgabios.c:2175 + jmp short 02f28h ; eb 06 ; 0xc2f20 + mov AL, strict byte 002h ; b0 02 ; 0xc2f22 vgabios.c:2176 + jmp short 02f28h ; eb 02 ; 0xc2f24 + xor al, al ; 30 c0 ; 0xc2f26 vgabios.c:2178 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc2f28 vgabios.c:2180 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc2f2b vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc2f2e + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2f31 vgabios.c:2183 + cmp AL, strict byte 00eh ; 3c 0e ; 0xc2f34 + jc short 02f57h ; 72 1f ; 0xc2f36 + cmp AL, strict byte 012h ; 3c 12 ; 0xc2f38 + jnbe short 02f57h ; 77 1b ; 0xc2f3a + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc2f3c vgabios.c:2184 + test ax, ax ; 85 c0 ; 0xc2f3f + je short 02f99h ; 74 56 ; 0xc2f41 + mov si, ax ; 89 c6 ; 0xc2f43 vgabios.c:2185 + shr si, 002h ; c1 ee 02 ; 0xc2f45 + mov ax, 04000h ; b8 00 40 ; 0xc2f48 + xor dx, dx ; 31 d2 ; 0xc2f4b + div si ; f7 f6 ; 0xc2f4d + lea si, [bx+029h] ; 8d 77 29 ; 0xc2f4f + mov byte [es:si], al ; 26 88 04 ; 0xc2f52 vgabios.c:52 + jmp short 02f99h ; eb 42 ; 0xc2f55 vgabios.c:2186 + lea si, [bx+029h] ; 8d 77 29 ; 0xc2f57 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2f5a + cmp AL, strict byte 013h ; 3c 13 ; 0xc2f5d + jne short 02f72h ; 75 11 ; 0xc2f5f + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc2f61 vgabios.c:52 + mov byte [es:si], 001h ; 26 c6 04 01 ; 0xc2f64 + lea si, [bx+027h] ; 8d 77 27 ; 0xc2f68 vgabios.c:2188 + mov word [es:si], 00100h ; 26 c7 04 00 01 ; 0xc2f6b vgabios.c:62 + jmp short 02f99h ; eb 27 ; 0xc2f70 vgabios.c:2189 + cmp AL, strict byte 004h ; 3c 04 ; 0xc2f72 + jc short 02f99h ; 72 23 ; 0xc2f74 + cmp AL, strict byte 006h ; 3c 06 ; 0xc2f76 + jnbe short 02f99h ; 77 1f ; 0xc2f78 + cmp word [bp-00ah], strict byte 00000h ; 83 7e f6 00 ; 0xc2f7a vgabios.c:2191 + je short 02f8eh ; 74 0e ; 0xc2f7e + mov ax, 04000h ; b8 00 40 ; 0xc2f80 vgabios.c:2192 + xor dx, dx ; 31 d2 ; 0xc2f83 + div word [bp-00ah] ; f7 76 f6 ; 0xc2f85 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc2f88 vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc2f8b + lea si, [bx+027h] ; 8d 77 27 ; 0xc2f8e vgabios.c:2193 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc2f91 vgabios.c:62 + mov word [es:si], strict word 00004h ; 26 c7 04 04 00 ; 0xc2f94 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2f99 vgabios.c:2195 + cmp AL, strict byte 006h ; 3c 06 ; 0xc2f9c + je short 02fa4h ; 74 04 ; 0xc2f9e + cmp AL, strict byte 011h ; 3c 11 ; 0xc2fa0 + jne short 02fafh ; 75 0b ; 0xc2fa2 + lea si, [bx+027h] ; 8d 77 27 ; 0xc2fa4 vgabios.c:2196 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc2fa7 vgabios.c:62 + mov word [es:si], strict word 00002h ; 26 c7 04 02 00 ; 0xc2faa + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2faf vgabios.c:2198 + cmp AL, strict byte 004h ; 3c 04 ; 0xc2fb2 + jc short 0300dh ; 72 57 ; 0xc2fb4 + cmp AL, strict byte 007h ; 3c 07 ; 0xc2fb6 + je short 0300dh ; 74 53 ; 0xc2fb8 + lea si, [bx+02dh] ; 8d 77 2d ; 0xc2fba vgabios.c:2199 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc2fbd vgabios.c:52 + mov byte [es:si], 001h ; 26 c6 04 01 ; 0xc2fc0 + mov si, 00084h ; be 84 00 ; 0xc2fc4 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2fc7 + mov es, ax ; 8e c0 ; 0xc2fca + mov al, byte [es:si] ; 26 8a 04 ; 0xc2fcc + movzx di, al ; 0f b6 f8 ; 0xc2fcf vgabios.c:48 + inc di ; 47 ; 0xc2fd2 + mov si, 00085h ; be 85 00 ; 0xc2fd3 vgabios.c:47 + mov al, byte [es:si] ; 26 8a 04 ; 0xc2fd6 + xor ah, ah ; 30 e4 ; 0xc2fd9 vgabios.c:48 + imul ax, di ; 0f af c7 ; 0xc2fdb + cmp ax, 0015eh ; 3d 5e 01 ; 0xc2fde vgabios.c:2201 + jc short 02ff1h ; 72 0e ; 0xc2fe1 + jbe short 02ffah ; 76 15 ; 0xc2fe3 + cmp ax, 001e0h ; 3d e0 01 ; 0xc2fe5 + je short 03002h ; 74 18 ; 0xc2fe8 + cmp ax, 00190h ; 3d 90 01 ; 0xc2fea + je short 02ffeh ; 74 0f ; 0xc2fed + jmp short 03002h ; eb 11 ; 0xc2fef + cmp ax, 000c8h ; 3d c8 00 ; 0xc2ff1 + jne short 03002h ; 75 0c ; 0xc2ff4 + xor al, al ; 30 c0 ; 0xc2ff6 vgabios.c:2202 + jmp short 03004h ; eb 0a ; 0xc2ff8 + mov AL, strict byte 001h ; b0 01 ; 0xc2ffa vgabios.c:2203 + jmp short 03004h ; eb 06 ; 0xc2ffc + mov AL, strict byte 002h ; b0 02 ; 0xc2ffe vgabios.c:2204 + jmp short 03004h ; eb 02 ; 0xc3000 + mov AL, strict byte 003h ; b0 03 ; 0xc3002 vgabios.c:2206 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc3004 vgabios.c:2208 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc3007 vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc300a + lea di, [bx+033h] ; 8d 7f 33 ; 0xc300d vgabios.c:2211 + mov cx, strict word 0000dh ; b9 0d 00 ; 0xc3010 + xor ax, ax ; 31 c0 ; 0xc3013 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc3015 + jcxz 0301ch ; e3 02 ; 0xc3018 + rep stosb ; f3 aa ; 0xc301a + lea sp, [bp-006h] ; 8d 66 fa ; 0xc301c vgabios.c:2212 + pop di ; 5f ; 0xc301f + pop si ; 5e ; 0xc3020 + pop cx ; 59 ; 0xc3021 + pop bp ; 5d ; 0xc3022 + retn ; c3 ; 0xc3023 + ; disGetNextSymbol 0xc3024 LB 0x1295 -> off=0x0 cb=0000000000000023 uValue=00000000000c3024 'biosfn_read_video_state_size2' +biosfn_read_video_state_size2: ; 0xc3024 LB 0x23 + push dx ; 52 ; 0xc3024 vgabios.c:2215 + push bp ; 55 ; 0xc3025 + mov bp, sp ; 89 e5 ; 0xc3026 + mov dx, ax ; 89 c2 ; 0xc3028 + xor ax, ax ; 31 c0 ; 0xc302a vgabios.c:2219 + test dl, 001h ; f6 c2 01 ; 0xc302c vgabios.c:2220 + je short 03034h ; 74 03 ; 0xc302f + mov ax, strict word 00046h ; b8 46 00 ; 0xc3031 vgabios.c:2221 + test dl, 002h ; f6 c2 02 ; 0xc3034 vgabios.c:2223 + je short 0303ch ; 74 03 ; 0xc3037 + add ax, strict word 0002ah ; 05 2a 00 ; 0xc3039 vgabios.c:2224 + test dl, 004h ; f6 c2 04 ; 0xc303c vgabios.c:2226 + je short 03044h ; 74 03 ; 0xc303f + add ax, 00304h ; 05 04 03 ; 0xc3041 vgabios.c:2227 + pop bp ; 5d ; 0xc3044 vgabios.c:2230 + pop dx ; 5a ; 0xc3045 + retn ; c3 ; 0xc3046 + ; disGetNextSymbol 0xc3047 LB 0x1272 -> off=0x0 cb=0000000000000018 uValue=00000000000c3047 'vga_get_video_state_size' +vga_get_video_state_size: ; 0xc3047 LB 0x18 + push bp ; 55 ; 0xc3047 vgabios.c:2232 + mov bp, sp ; 89 e5 ; 0xc3048 + push bx ; 53 ; 0xc304a + mov bx, dx ; 89 d3 ; 0xc304b + call 03024h ; e8 d4 ff ; 0xc304d vgabios.c:2235 + add ax, strict word 0003fh ; 05 3f 00 ; 0xc3050 + shr ax, 006h ; c1 e8 06 ; 0xc3053 + mov word [ss:bx], ax ; 36 89 07 ; 0xc3056 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3059 vgabios.c:2236 + pop bx ; 5b ; 0xc305c + pop bp ; 5d ; 0xc305d + retn ; c3 ; 0xc305e + ; disGetNextSymbol 0xc305f LB 0x125a -> off=0x0 cb=00000000000002d6 uValue=00000000000c305f 'biosfn_save_video_state' +biosfn_save_video_state: ; 0xc305f LB 0x2d6 + push bp ; 55 ; 0xc305f vgabios.c:2238 + mov bp, sp ; 89 e5 ; 0xc3060 + push cx ; 51 ; 0xc3062 + push si ; 56 ; 0xc3063 + push di ; 57 ; 0xc3064 + push ax ; 50 ; 0xc3065 + push ax ; 50 ; 0xc3066 + push ax ; 50 ; 0xc3067 + mov cx, dx ; 89 d1 ; 0xc3068 + mov si, strict word 00063h ; be 63 00 ; 0xc306a vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc306d + mov es, ax ; 8e c0 ; 0xc3070 + mov di, word [es:si] ; 26 8b 3c ; 0xc3072 + mov si, di ; 89 fe ; 0xc3075 vgabios.c:58 + test byte [bp-00ch], 001h ; f6 46 f4 01 ; 0xc3077 vgabios.c:2243 + je near 03192h ; 0f 84 13 01 ; 0xc307b + mov dx, 003c4h ; ba c4 03 ; 0xc307f vgabios.c:2244 + in AL, DX ; ec ; 0xc3082 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3083 + mov es, cx ; 8e c1 ; 0xc3085 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3087 + inc bx ; 43 ; 0xc308a vgabios.c:2244 + mov dx, di ; 89 fa ; 0xc308b + in AL, DX ; ec ; 0xc308d + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc308e + mov byte [es:bx], al ; 26 88 07 ; 0xc3090 vgabios.c:52 + inc bx ; 43 ; 0xc3093 vgabios.c:2245 + mov dx, 003ceh ; ba ce 03 ; 0xc3094 + in AL, DX ; ec ; 0xc3097 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3098 + mov byte [es:bx], al ; 26 88 07 ; 0xc309a vgabios.c:52 + inc bx ; 43 ; 0xc309d vgabios.c:2246 + mov dx, 003dah ; ba da 03 ; 0xc309e + in AL, DX ; ec ; 0xc30a1 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc30a2 + mov dx, 003c0h ; ba c0 03 ; 0xc30a4 vgabios.c:2248 + in AL, DX ; ec ; 0xc30a7 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc30a8 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc30aa + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc30ad vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc30b0 + inc bx ; 43 ; 0xc30b3 vgabios.c:2249 + mov dx, 003cah ; ba ca 03 ; 0xc30b4 + in AL, DX ; ec ; 0xc30b7 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc30b8 + mov byte [es:bx], al ; 26 88 07 ; 0xc30ba vgabios.c:52 + mov ax, strict word 00001h ; b8 01 00 ; 0xc30bd vgabios.c:2252 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc30c0 + add bx, ax ; 01 c3 ; 0xc30c3 vgabios.c:2250 + jmp short 030cdh ; eb 06 ; 0xc30c5 + cmp word [bp-008h], strict byte 00004h ; 83 7e f8 04 ; 0xc30c7 + jnbe short 030e5h ; 77 18 ; 0xc30cb + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc30cd vgabios.c:2253 + mov dx, 003c4h ; ba c4 03 ; 0xc30d0 + out DX, AL ; ee ; 0xc30d3 + mov dx, 003c5h ; ba c5 03 ; 0xc30d4 vgabios.c:2254 + in AL, DX ; ec ; 0xc30d7 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc30d8 + mov es, cx ; 8e c1 ; 0xc30da vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc30dc + inc bx ; 43 ; 0xc30df vgabios.c:2254 + inc word [bp-008h] ; ff 46 f8 ; 0xc30e0 vgabios.c:2255 + jmp short 030c7h ; eb e2 ; 0xc30e3 + xor al, al ; 30 c0 ; 0xc30e5 vgabios.c:2256 + mov dx, 003c4h ; ba c4 03 ; 0xc30e7 + out DX, AL ; ee ; 0xc30ea + mov dx, 003c5h ; ba c5 03 ; 0xc30eb vgabios.c:2257 + in AL, DX ; ec ; 0xc30ee + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc30ef + mov es, cx ; 8e c1 ; 0xc30f1 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc30f3 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc30f6 vgabios.c:2259 + inc bx ; 43 ; 0xc30fb vgabios.c:2257 + jmp short 03104h ; eb 06 ; 0xc30fc + cmp word [bp-008h], strict byte 00018h ; 83 7e f8 18 ; 0xc30fe + jnbe short 0311bh ; 77 17 ; 0xc3102 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3104 vgabios.c:2260 + mov dx, si ; 89 f2 ; 0xc3107 + out DX, AL ; ee ; 0xc3109 + lea dx, [si+001h] ; 8d 54 01 ; 0xc310a vgabios.c:2261 + in AL, DX ; ec ; 0xc310d + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc310e + mov es, cx ; 8e c1 ; 0xc3110 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3112 + inc bx ; 43 ; 0xc3115 vgabios.c:2261 + inc word [bp-008h] ; ff 46 f8 ; 0xc3116 vgabios.c:2262 + jmp short 030feh ; eb e3 ; 0xc3119 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc311b vgabios.c:2264 + jmp short 03128h ; eb 06 ; 0xc3120 + cmp word [bp-008h], strict byte 00013h ; 83 7e f8 13 ; 0xc3122 + jnbe short 0314ch ; 77 24 ; 0xc3126 + mov dx, 003dah ; ba da 03 ; 0xc3128 vgabios.c:2265 + in AL, DX ; ec ; 0xc312b + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc312c + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc312e vgabios.c:2266 + and ax, strict word 00020h ; 25 20 00 ; 0xc3131 + or ax, word [bp-008h] ; 0b 46 f8 ; 0xc3134 + mov dx, 003c0h ; ba c0 03 ; 0xc3137 + out DX, AL ; ee ; 0xc313a + mov dx, 003c1h ; ba c1 03 ; 0xc313b vgabios.c:2267 + in AL, DX ; ec ; 0xc313e + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc313f + mov es, cx ; 8e c1 ; 0xc3141 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3143 + inc bx ; 43 ; 0xc3146 vgabios.c:2267 + inc word [bp-008h] ; ff 46 f8 ; 0xc3147 vgabios.c:2268 + jmp short 03122h ; eb d6 ; 0xc314a + mov dx, 003dah ; ba da 03 ; 0xc314c vgabios.c:2269 + in AL, DX ; ec ; 0xc314f + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3150 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc3152 vgabios.c:2271 + jmp short 0315fh ; eb 06 ; 0xc3157 + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc3159 + jnbe short 03177h ; 77 18 ; 0xc315d + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc315f vgabios.c:2272 + mov dx, 003ceh ; ba ce 03 ; 0xc3162 + out DX, AL ; ee ; 0xc3165 + mov dx, 003cfh ; ba cf 03 ; 0xc3166 vgabios.c:2273 + in AL, DX ; ec ; 0xc3169 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc316a + mov es, cx ; 8e c1 ; 0xc316c vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc316e + inc bx ; 43 ; 0xc3171 vgabios.c:2273 + inc word [bp-008h] ; ff 46 f8 ; 0xc3172 vgabios.c:2274 + jmp short 03159h ; eb e2 ; 0xc3175 + mov es, cx ; 8e c1 ; 0xc3177 vgabios.c:62 + mov word [es:bx], si ; 26 89 37 ; 0xc3179 + inc bx ; 43 ; 0xc317c vgabios.c:2276 + inc bx ; 43 ; 0xc317d + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc317e vgabios.c:52 + inc bx ; 43 ; 0xc3182 vgabios.c:2279 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc3183 vgabios.c:52 + inc bx ; 43 ; 0xc3187 vgabios.c:2280 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc3188 vgabios.c:52 + inc bx ; 43 ; 0xc318c vgabios.c:2281 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc318d vgabios.c:52 + inc bx ; 43 ; 0xc3191 vgabios.c:2282 + test byte [bp-00ch], 002h ; f6 46 f4 02 ; 0xc3192 vgabios.c:2284 + je near 032d9h ; 0f 84 3f 01 ; 0xc3196 + mov si, strict word 00049h ; be 49 00 ; 0xc319a vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc319d + mov es, ax ; 8e c0 ; 0xc31a0 + mov al, byte [es:si] ; 26 8a 04 ; 0xc31a2 + mov es, cx ; 8e c1 ; 0xc31a5 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc31a7 + inc bx ; 43 ; 0xc31aa vgabios.c:2285 + mov si, strict word 0004ah ; be 4a 00 ; 0xc31ab vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc31ae + mov es, ax ; 8e c0 ; 0xc31b1 + mov ax, word [es:si] ; 26 8b 04 ; 0xc31b3 + mov es, cx ; 8e c1 ; 0xc31b6 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc31b8 + inc bx ; 43 ; 0xc31bb vgabios.c:2286 + inc bx ; 43 ; 0xc31bc + mov si, strict word 0004ch ; be 4c 00 ; 0xc31bd vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc31c0 + mov es, ax ; 8e c0 ; 0xc31c3 + mov ax, word [es:si] ; 26 8b 04 ; 0xc31c5 + mov es, cx ; 8e c1 ; 0xc31c8 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc31ca + inc bx ; 43 ; 0xc31cd vgabios.c:2287 + inc bx ; 43 ; 0xc31ce + mov si, strict word 00063h ; be 63 00 ; 0xc31cf vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc31d2 + mov es, ax ; 8e c0 ; 0xc31d5 + mov ax, word [es:si] ; 26 8b 04 ; 0xc31d7 + mov es, cx ; 8e c1 ; 0xc31da vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc31dc + inc bx ; 43 ; 0xc31df vgabios.c:2288 + inc bx ; 43 ; 0xc31e0 + mov si, 00084h ; be 84 00 ; 0xc31e1 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc31e4 + mov es, ax ; 8e c0 ; 0xc31e7 + mov al, byte [es:si] ; 26 8a 04 ; 0xc31e9 + mov es, cx ; 8e c1 ; 0xc31ec vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc31ee + inc bx ; 43 ; 0xc31f1 vgabios.c:2289 + mov si, 00085h ; be 85 00 ; 0xc31f2 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc31f5 + mov es, ax ; 8e c0 ; 0xc31f8 + mov ax, word [es:si] ; 26 8b 04 ; 0xc31fa + mov es, cx ; 8e c1 ; 0xc31fd vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc31ff + inc bx ; 43 ; 0xc3202 vgabios.c:2290 + inc bx ; 43 ; 0xc3203 + mov si, 00087h ; be 87 00 ; 0xc3204 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3207 + mov es, ax ; 8e c0 ; 0xc320a + mov al, byte [es:si] ; 26 8a 04 ; 0xc320c + mov es, cx ; 8e c1 ; 0xc320f vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3211 + inc bx ; 43 ; 0xc3214 vgabios.c:2291 + mov si, 00088h ; be 88 00 ; 0xc3215 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3218 + mov es, ax ; 8e c0 ; 0xc321b + mov al, byte [es:si] ; 26 8a 04 ; 0xc321d + mov es, cx ; 8e c1 ; 0xc3220 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3222 + inc bx ; 43 ; 0xc3225 vgabios.c:2292 + mov si, 00089h ; be 89 00 ; 0xc3226 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3229 + mov es, ax ; 8e c0 ; 0xc322c + mov al, byte [es:si] ; 26 8a 04 ; 0xc322e + mov es, cx ; 8e c1 ; 0xc3231 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3233 + inc bx ; 43 ; 0xc3236 vgabios.c:2293 + mov si, strict word 00060h ; be 60 00 ; 0xc3237 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc323a + mov es, ax ; 8e c0 ; 0xc323d + mov ax, word [es:si] ; 26 8b 04 ; 0xc323f + mov es, cx ; 8e c1 ; 0xc3242 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3244 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc3247 vgabios.c:2295 + inc bx ; 43 ; 0xc324c vgabios.c:2294 + inc bx ; 43 ; 0xc324d + jmp short 03256h ; eb 06 ; 0xc324e + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc3250 + jnc short 03272h ; 73 1c ; 0xc3254 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc3256 vgabios.c:2296 + add si, si ; 01 f6 ; 0xc3259 + add si, strict byte 00050h ; 83 c6 50 ; 0xc325b + mov ax, strict word 00040h ; b8 40 00 ; 0xc325e vgabios.c:57 + mov es, ax ; 8e c0 ; 0xc3261 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3263 + mov es, cx ; 8e c1 ; 0xc3266 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3268 + inc bx ; 43 ; 0xc326b vgabios.c:2297 + inc bx ; 43 ; 0xc326c + inc word [bp-008h] ; ff 46 f8 ; 0xc326d vgabios.c:2298 + jmp short 03250h ; eb de ; 0xc3270 + mov si, strict word 0004eh ; be 4e 00 ; 0xc3272 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3275 + mov es, ax ; 8e c0 ; 0xc3278 + mov ax, word [es:si] ; 26 8b 04 ; 0xc327a + mov es, cx ; 8e c1 ; 0xc327d vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc327f + inc bx ; 43 ; 0xc3282 vgabios.c:2299 + inc bx ; 43 ; 0xc3283 + mov si, strict word 00062h ; be 62 00 ; 0xc3284 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3287 + mov es, ax ; 8e c0 ; 0xc328a + mov al, byte [es:si] ; 26 8a 04 ; 0xc328c + mov es, cx ; 8e c1 ; 0xc328f vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3291 + inc bx ; 43 ; 0xc3294 vgabios.c:2300 + mov si, strict word 0007ch ; be 7c 00 ; 0xc3295 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc3298 + mov es, ax ; 8e c0 ; 0xc329a + mov ax, word [es:si] ; 26 8b 04 ; 0xc329c + mov es, cx ; 8e c1 ; 0xc329f vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc32a1 + inc bx ; 43 ; 0xc32a4 vgabios.c:2302 + inc bx ; 43 ; 0xc32a5 + mov si, strict word 0007eh ; be 7e 00 ; 0xc32a6 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc32a9 + mov es, ax ; 8e c0 ; 0xc32ab + mov ax, word [es:si] ; 26 8b 04 ; 0xc32ad + mov es, cx ; 8e c1 ; 0xc32b0 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc32b2 + inc bx ; 43 ; 0xc32b5 vgabios.c:2303 + inc bx ; 43 ; 0xc32b6 + mov si, 0010ch ; be 0c 01 ; 0xc32b7 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc32ba + mov es, ax ; 8e c0 ; 0xc32bc + mov ax, word [es:si] ; 26 8b 04 ; 0xc32be + mov es, cx ; 8e c1 ; 0xc32c1 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc32c3 + inc bx ; 43 ; 0xc32c6 vgabios.c:2304 + inc bx ; 43 ; 0xc32c7 + mov si, 0010eh ; be 0e 01 ; 0xc32c8 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc32cb + mov es, ax ; 8e c0 ; 0xc32cd + mov ax, word [es:si] ; 26 8b 04 ; 0xc32cf + mov es, cx ; 8e c1 ; 0xc32d2 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc32d4 + inc bx ; 43 ; 0xc32d7 vgabios.c:2305 + inc bx ; 43 ; 0xc32d8 + test byte [bp-00ch], 004h ; f6 46 f4 04 ; 0xc32d9 vgabios.c:2307 + je short 0332bh ; 74 4c ; 0xc32dd + mov dx, 003c7h ; ba c7 03 ; 0xc32df vgabios.c:2309 + in AL, DX ; ec ; 0xc32e2 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32e3 + mov es, cx ; 8e c1 ; 0xc32e5 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc32e7 + inc bx ; 43 ; 0xc32ea vgabios.c:2309 + mov dx, 003c8h ; ba c8 03 ; 0xc32eb + in AL, DX ; ec ; 0xc32ee + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32ef + mov byte [es:bx], al ; 26 88 07 ; 0xc32f1 vgabios.c:52 + inc bx ; 43 ; 0xc32f4 vgabios.c:2310 + mov dx, 003c6h ; ba c6 03 ; 0xc32f5 + in AL, DX ; ec ; 0xc32f8 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc32f9 + mov byte [es:bx], al ; 26 88 07 ; 0xc32fb vgabios.c:52 + inc bx ; 43 ; 0xc32fe vgabios.c:2311 + xor al, al ; 30 c0 ; 0xc32ff + mov dx, 003c8h ; ba c8 03 ; 0xc3301 + out DX, AL ; ee ; 0xc3304 + xor ah, ah ; 30 e4 ; 0xc3305 vgabios.c:2314 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc3307 + jmp short 03313h ; eb 07 ; 0xc330a + cmp word [bp-008h], 00300h ; 81 7e f8 00 03 ; 0xc330c + jnc short 03324h ; 73 11 ; 0xc3311 + mov dx, 003c9h ; ba c9 03 ; 0xc3313 vgabios.c:2315 + in AL, DX ; ec ; 0xc3316 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3317 + mov es, cx ; 8e c1 ; 0xc3319 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc331b + inc bx ; 43 ; 0xc331e vgabios.c:2315 + inc word [bp-008h] ; ff 46 f8 ; 0xc331f vgabios.c:2316 + jmp short 0330ch ; eb e8 ; 0xc3322 + mov es, cx ; 8e c1 ; 0xc3324 vgabios.c:52 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc3326 + inc bx ; 43 ; 0xc332a vgabios.c:2317 + mov ax, bx ; 89 d8 ; 0xc332b vgabios.c:2320 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc332d + pop di ; 5f ; 0xc3330 + pop si ; 5e ; 0xc3331 + pop cx ; 59 ; 0xc3332 + pop bp ; 5d ; 0xc3333 + retn ; c3 ; 0xc3334 + ; disGetNextSymbol 0xc3335 LB 0xf84 -> off=0x0 cb=00000000000002b8 uValue=00000000000c3335 'biosfn_restore_video_state' +biosfn_restore_video_state: ; 0xc3335 LB 0x2b8 + push bp ; 55 ; 0xc3335 vgabios.c:2322 + mov bp, sp ; 89 e5 ; 0xc3336 + push cx ; 51 ; 0xc3338 + push si ; 56 ; 0xc3339 + push di ; 57 ; 0xc333a + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc333b + push ax ; 50 ; 0xc333e + mov cx, dx ; 89 d1 ; 0xc333f + test byte [bp-010h], 001h ; f6 46 f0 01 ; 0xc3341 vgabios.c:2326 + je near 0347dh ; 0f 84 34 01 ; 0xc3345 + mov dx, 003dah ; ba da 03 ; 0xc3349 vgabios.c:2328 + in AL, DX ; ec ; 0xc334c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc334d + lea si, [bx+040h] ; 8d 77 40 ; 0xc334f vgabios.c:2330 + mov es, cx ; 8e c1 ; 0xc3352 vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3354 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc3357 vgabios.c:58 + mov si, bx ; 89 de ; 0xc335a vgabios.c:2331 + mov word [bp-00eh], strict word 00001h ; c7 46 f2 01 00 ; 0xc335c vgabios.c:2334 + add bx, strict byte 00005h ; 83 c3 05 ; 0xc3361 vgabios.c:2332 + jmp short 0336ch ; eb 06 ; 0xc3364 + cmp word [bp-00eh], strict byte 00004h ; 83 7e f2 04 ; 0xc3366 + jnbe short 03382h ; 77 16 ; 0xc336a + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc336c vgabios.c:2335 + mov dx, 003c4h ; ba c4 03 ; 0xc336f + out DX, AL ; ee ; 0xc3372 + mov es, cx ; 8e c1 ; 0xc3373 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3375 + mov dx, 003c5h ; ba c5 03 ; 0xc3378 vgabios.c:48 + out DX, AL ; ee ; 0xc337b + inc bx ; 43 ; 0xc337c vgabios.c:2336 + inc word [bp-00eh] ; ff 46 f2 ; 0xc337d vgabios.c:2337 + jmp short 03366h ; eb e4 ; 0xc3380 + xor al, al ; 30 c0 ; 0xc3382 vgabios.c:2338 + mov dx, 003c4h ; ba c4 03 ; 0xc3384 + out DX, AL ; ee ; 0xc3387 + mov es, cx ; 8e c1 ; 0xc3388 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc338a + mov dx, 003c5h ; ba c5 03 ; 0xc338d vgabios.c:48 + out DX, AL ; ee ; 0xc3390 + inc bx ; 43 ; 0xc3391 vgabios.c:2339 + mov dx, 003cch ; ba cc 03 ; 0xc3392 + in AL, DX ; ec ; 0xc3395 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3396 + and AL, strict byte 0feh ; 24 fe ; 0xc3398 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc339a + cmp word [bp-00ah], 003d4h ; 81 7e f6 d4 03 ; 0xc339d vgabios.c:2343 + jne short 033a8h ; 75 04 ; 0xc33a2 + or byte [bp-008h], 001h ; 80 4e f8 01 ; 0xc33a4 vgabios.c:2344 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc33a8 vgabios.c:2345 + mov dx, 003c2h ; ba c2 03 ; 0xc33ab + out DX, AL ; ee ; 0xc33ae + mov ax, strict word 00011h ; b8 11 00 ; 0xc33af vgabios.c:2348 + mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xc33b2 + out DX, ax ; ef ; 0xc33b5 + mov word [bp-00eh], strict word 00000h ; c7 46 f2 00 00 ; 0xc33b6 vgabios.c:2350 + jmp short 033c3h ; eb 06 ; 0xc33bb + cmp word [bp-00eh], strict byte 00018h ; 83 7e f2 18 ; 0xc33bd + jnbe short 033ddh ; 77 1a ; 0xc33c1 + cmp word [bp-00eh], strict byte 00011h ; 83 7e f2 11 ; 0xc33c3 vgabios.c:2351 + je short 033d7h ; 74 0e ; 0xc33c7 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc33c9 vgabios.c:2352 + mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xc33cc + out DX, AL ; ee ; 0xc33cf + mov es, cx ; 8e c1 ; 0xc33d0 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc33d2 + inc dx ; 42 ; 0xc33d5 vgabios.c:48 + out DX, AL ; ee ; 0xc33d6 + inc bx ; 43 ; 0xc33d7 vgabios.c:2355 + inc word [bp-00eh] ; ff 46 f2 ; 0xc33d8 vgabios.c:2356 + jmp short 033bdh ; eb e0 ; 0xc33db + mov AL, strict byte 011h ; b0 11 ; 0xc33dd vgabios.c:2358 + mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xc33df + out DX, AL ; ee ; 0xc33e2 + lea di, [word bx-00007h] ; 8d bf f9 ff ; 0xc33e3 vgabios.c:2359 + mov es, cx ; 8e c1 ; 0xc33e7 vgabios.c:47 + mov al, byte [es:di] ; 26 8a 05 ; 0xc33e9 + inc dx ; 42 ; 0xc33ec vgabios.c:48 + out DX, AL ; ee ; 0xc33ed + lea di, [si+003h] ; 8d 7c 03 ; 0xc33ee vgabios.c:2362 + mov al, byte [es:di] ; 26 8a 05 ; 0xc33f1 vgabios.c:47 + xor ah, ah ; 30 e4 ; 0xc33f4 vgabios.c:48 + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc33f6 + mov dx, 003dah ; ba da 03 ; 0xc33f9 vgabios.c:2363 + in AL, DX ; ec ; 0xc33fc + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc33fd + mov word [bp-00eh], strict word 00000h ; c7 46 f2 00 00 ; 0xc33ff vgabios.c:2364 + jmp short 0340ch ; eb 06 ; 0xc3404 + cmp word [bp-00eh], strict byte 00013h ; 83 7e f2 13 ; 0xc3406 + jnbe short 03425h ; 77 19 ; 0xc340a + mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xc340c vgabios.c:2365 + and ax, strict word 00020h ; 25 20 00 ; 0xc340f + or ax, word [bp-00eh] ; 0b 46 f2 ; 0xc3412 + mov dx, 003c0h ; ba c0 03 ; 0xc3415 + out DX, AL ; ee ; 0xc3418 + mov es, cx ; 8e c1 ; 0xc3419 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc341b + out DX, AL ; ee ; 0xc341e vgabios.c:48 + inc bx ; 43 ; 0xc341f vgabios.c:2366 + inc word [bp-00eh] ; ff 46 f2 ; 0xc3420 vgabios.c:2367 + jmp short 03406h ; eb e1 ; 0xc3423 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc3425 vgabios.c:2368 + mov dx, 003c0h ; ba c0 03 ; 0xc3428 + out DX, AL ; ee ; 0xc342b + mov dx, 003dah ; ba da 03 ; 0xc342c vgabios.c:2369 + in AL, DX ; ec ; 0xc342f + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3430 + mov word [bp-00eh], strict word 00000h ; c7 46 f2 00 00 ; 0xc3432 vgabios.c:2371 + jmp short 0343fh ; eb 06 ; 0xc3437 + cmp word [bp-00eh], strict byte 00008h ; 83 7e f2 08 ; 0xc3439 + jnbe short 03455h ; 77 16 ; 0xc343d + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc343f vgabios.c:2372 + mov dx, 003ceh ; ba ce 03 ; 0xc3442 + out DX, AL ; ee ; 0xc3445 + mov es, cx ; 8e c1 ; 0xc3446 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3448 + mov dx, 003cfh ; ba cf 03 ; 0xc344b vgabios.c:48 + out DX, AL ; ee ; 0xc344e + inc bx ; 43 ; 0xc344f vgabios.c:2373 + inc word [bp-00eh] ; ff 46 f2 ; 0xc3450 vgabios.c:2374 + jmp short 03439h ; eb e4 ; 0xc3453 + add bx, strict byte 00006h ; 83 c3 06 ; 0xc3455 vgabios.c:2375 + mov es, cx ; 8e c1 ; 0xc3458 vgabios.c:47 + mov al, byte [es:si] ; 26 8a 04 ; 0xc345a + mov dx, 003c4h ; ba c4 03 ; 0xc345d vgabios.c:48 + out DX, AL ; ee ; 0xc3460 + inc si ; 46 ; 0xc3461 vgabios.c:2378 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3462 vgabios.c:47 + mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xc3465 vgabios.c:48 + out DX, AL ; ee ; 0xc3468 + inc si ; 46 ; 0xc3469 vgabios.c:2379 + mov al, byte [es:si] ; 26 8a 04 ; 0xc346a vgabios.c:47 + mov dx, 003ceh ; ba ce 03 ; 0xc346d vgabios.c:48 + out DX, AL ; ee ; 0xc3470 + inc si ; 46 ; 0xc3471 vgabios.c:2380 + inc si ; 46 ; 0xc3472 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3473 vgabios.c:47 + mov dx, word [bp-00ah] ; 8b 56 f6 ; 0xc3476 vgabios.c:48 + add dx, strict byte 00006h ; 83 c2 06 ; 0xc3479 + out DX, AL ; ee ; 0xc347c + test byte [bp-010h], 002h ; f6 46 f0 02 ; 0xc347d vgabios.c:2384 + je near 035a0h ; 0f 84 1b 01 ; 0xc3481 + mov es, cx ; 8e c1 ; 0xc3485 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3487 + mov si, strict word 00049h ; be 49 00 ; 0xc348a vgabios.c:52 + mov dx, strict word 00040h ; ba 40 00 ; 0xc348d + mov es, dx ; 8e c2 ; 0xc3490 + mov byte [es:si], al ; 26 88 04 ; 0xc3492 + inc bx ; 43 ; 0xc3495 vgabios.c:2385 + mov es, cx ; 8e c1 ; 0xc3496 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3498 + mov si, strict word 0004ah ; be 4a 00 ; 0xc349b vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc349e + mov word [es:si], ax ; 26 89 04 ; 0xc34a0 + inc bx ; 43 ; 0xc34a3 vgabios.c:2386 + inc bx ; 43 ; 0xc34a4 + mov es, cx ; 8e c1 ; 0xc34a5 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc34a7 + mov si, strict word 0004ch ; be 4c 00 ; 0xc34aa vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc34ad + mov word [es:si], ax ; 26 89 04 ; 0xc34af + inc bx ; 43 ; 0xc34b2 vgabios.c:2387 + inc bx ; 43 ; 0xc34b3 + mov es, cx ; 8e c1 ; 0xc34b4 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc34b6 + mov si, strict word 00063h ; be 63 00 ; 0xc34b9 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc34bc + mov word [es:si], ax ; 26 89 04 ; 0xc34be + inc bx ; 43 ; 0xc34c1 vgabios.c:2388 + inc bx ; 43 ; 0xc34c2 + mov es, cx ; 8e c1 ; 0xc34c3 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc34c5 + mov si, 00084h ; be 84 00 ; 0xc34c8 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc34cb + mov byte [es:si], al ; 26 88 04 ; 0xc34cd + inc bx ; 43 ; 0xc34d0 vgabios.c:2389 + mov es, cx ; 8e c1 ; 0xc34d1 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc34d3 + mov si, 00085h ; be 85 00 ; 0xc34d6 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc34d9 + mov word [es:si], ax ; 26 89 04 ; 0xc34db + inc bx ; 43 ; 0xc34de vgabios.c:2390 + inc bx ; 43 ; 0xc34df + mov es, cx ; 8e c1 ; 0xc34e0 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc34e2 + mov si, 00087h ; be 87 00 ; 0xc34e5 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc34e8 + mov byte [es:si], al ; 26 88 04 ; 0xc34ea + inc bx ; 43 ; 0xc34ed vgabios.c:2391 + mov es, cx ; 8e c1 ; 0xc34ee vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc34f0 + mov si, 00088h ; be 88 00 ; 0xc34f3 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc34f6 + mov byte [es:si], al ; 26 88 04 ; 0xc34f8 + inc bx ; 43 ; 0xc34fb vgabios.c:2392 + mov es, cx ; 8e c1 ; 0xc34fc vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc34fe + mov si, 00089h ; be 89 00 ; 0xc3501 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc3504 + mov byte [es:si], al ; 26 88 04 ; 0xc3506 + inc bx ; 43 ; 0xc3509 vgabios.c:2393 + mov es, cx ; 8e c1 ; 0xc350a vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc350c + mov si, strict word 00060h ; be 60 00 ; 0xc350f vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3512 + mov word [es:si], ax ; 26 89 04 ; 0xc3514 + mov word [bp-00eh], strict word 00000h ; c7 46 f2 00 00 ; 0xc3517 vgabios.c:2395 + inc bx ; 43 ; 0xc351c vgabios.c:2394 + inc bx ; 43 ; 0xc351d + jmp short 03526h ; eb 06 ; 0xc351e + cmp word [bp-00eh], strict byte 00008h ; 83 7e f2 08 ; 0xc3520 + jnc short 03542h ; 73 1c ; 0xc3524 + mov es, cx ; 8e c1 ; 0xc3526 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3528 + mov si, word [bp-00eh] ; 8b 76 f2 ; 0xc352b vgabios.c:58 + add si, si ; 01 f6 ; 0xc352e + add si, strict byte 00050h ; 83 c6 50 ; 0xc3530 + mov dx, strict word 00040h ; ba 40 00 ; 0xc3533 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3536 + mov word [es:si], ax ; 26 89 04 ; 0xc3538 + inc bx ; 43 ; 0xc353b vgabios.c:2397 + inc bx ; 43 ; 0xc353c + inc word [bp-00eh] ; ff 46 f2 ; 0xc353d vgabios.c:2398 + jmp short 03520h ; eb de ; 0xc3540 + mov es, cx ; 8e c1 ; 0xc3542 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3544 + mov si, strict word 0004eh ; be 4e 00 ; 0xc3547 vgabios.c:62 + mov dx, strict word 00040h ; ba 40 00 ; 0xc354a + mov es, dx ; 8e c2 ; 0xc354d + mov word [es:si], ax ; 26 89 04 ; 0xc354f + inc bx ; 43 ; 0xc3552 vgabios.c:2399 + inc bx ; 43 ; 0xc3553 + mov es, cx ; 8e c1 ; 0xc3554 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3556 + mov si, strict word 00062h ; be 62 00 ; 0xc3559 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc355c + mov byte [es:si], al ; 26 88 04 ; 0xc355e + inc bx ; 43 ; 0xc3561 vgabios.c:2400 + mov es, cx ; 8e c1 ; 0xc3562 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3564 + mov si, strict word 0007ch ; be 7c 00 ; 0xc3567 vgabios.c:62 + xor dx, dx ; 31 d2 ; 0xc356a + mov es, dx ; 8e c2 ; 0xc356c + mov word [es:si], ax ; 26 89 04 ; 0xc356e + inc bx ; 43 ; 0xc3571 vgabios.c:2402 + inc bx ; 43 ; 0xc3572 + mov es, cx ; 8e c1 ; 0xc3573 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3575 + mov si, strict word 0007eh ; be 7e 00 ; 0xc3578 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc357b + mov word [es:si], ax ; 26 89 04 ; 0xc357d + inc bx ; 43 ; 0xc3580 vgabios.c:2403 + inc bx ; 43 ; 0xc3581 + mov es, cx ; 8e c1 ; 0xc3582 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3584 + mov si, 0010ch ; be 0c 01 ; 0xc3587 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc358a + mov word [es:si], ax ; 26 89 04 ; 0xc358c + inc bx ; 43 ; 0xc358f vgabios.c:2404 + inc bx ; 43 ; 0xc3590 + mov es, cx ; 8e c1 ; 0xc3591 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3593 + mov si, 0010eh ; be 0e 01 ; 0xc3596 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3599 + mov word [es:si], ax ; 26 89 04 ; 0xc359b + inc bx ; 43 ; 0xc359e vgabios.c:2405 + inc bx ; 43 ; 0xc359f + test byte [bp-010h], 004h ; f6 46 f0 04 ; 0xc35a0 vgabios.c:2407 + je short 035e3h ; 74 3d ; 0xc35a4 + inc bx ; 43 ; 0xc35a6 vgabios.c:2408 + mov es, cx ; 8e c1 ; 0xc35a7 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc35a9 + xor ah, ah ; 30 e4 ; 0xc35ac vgabios.c:48 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc35ae + inc bx ; 43 ; 0xc35b1 vgabios.c:2409 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc35b2 vgabios.c:47 + mov dx, 003c6h ; ba c6 03 ; 0xc35b5 vgabios.c:48 + out DX, AL ; ee ; 0xc35b8 + inc bx ; 43 ; 0xc35b9 vgabios.c:2410 + xor al, al ; 30 c0 ; 0xc35ba + mov dx, 003c8h ; ba c8 03 ; 0xc35bc + out DX, AL ; ee ; 0xc35bf + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc35c0 vgabios.c:2413 + jmp short 035cch ; eb 07 ; 0xc35c3 + cmp word [bp-00eh], 00300h ; 81 7e f2 00 03 ; 0xc35c5 + jnc short 035dbh ; 73 0f ; 0xc35ca + mov es, cx ; 8e c1 ; 0xc35cc vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc35ce + mov dx, 003c9h ; ba c9 03 ; 0xc35d1 vgabios.c:48 + out DX, AL ; ee ; 0xc35d4 + inc bx ; 43 ; 0xc35d5 vgabios.c:2414 + inc word [bp-00eh] ; ff 46 f2 ; 0xc35d6 vgabios.c:2415 + jmp short 035c5h ; eb ea ; 0xc35d9 + inc bx ; 43 ; 0xc35db vgabios.c:2416 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc35dc + mov dx, 003c8h ; ba c8 03 ; 0xc35df + out DX, AL ; ee ; 0xc35e2 + mov ax, bx ; 89 d8 ; 0xc35e3 vgabios.c:2420 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc35e5 + pop di ; 5f ; 0xc35e8 + pop si ; 5e ; 0xc35e9 + pop cx ; 59 ; 0xc35ea + pop bp ; 5d ; 0xc35eb + retn ; c3 ; 0xc35ec + ; disGetNextSymbol 0xc35ed LB 0xccc -> off=0x0 cb=0000000000000027 uValue=00000000000c35ed 'find_vga_entry' +find_vga_entry: ; 0xc35ed LB 0x27 + push bx ; 53 ; 0xc35ed vgabios.c:2429 + push dx ; 52 ; 0xc35ee + push bp ; 55 ; 0xc35ef + mov bp, sp ; 89 e5 ; 0xc35f0 + mov dl, al ; 88 c2 ; 0xc35f2 + mov AH, strict byte 0ffh ; b4 ff ; 0xc35f4 vgabios.c:2431 + xor al, al ; 30 c0 ; 0xc35f6 vgabios.c:2432 + jmp short 03600h ; eb 06 ; 0xc35f8 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc35fa vgabios.c:2433 + cmp AL, strict byte 00fh ; 3c 0f ; 0xc35fc + jnbe short 0360eh ; 77 0e ; 0xc35fe + movzx bx, al ; 0f b6 d8 ; 0xc3600 + sal bx, 003h ; c1 e3 03 ; 0xc3603 + cmp dl, byte [bx+047afh] ; 3a 97 af 47 ; 0xc3606 + jne short 035fah ; 75 ee ; 0xc360a + mov ah, al ; 88 c4 ; 0xc360c + mov al, ah ; 88 e0 ; 0xc360e vgabios.c:2438 + pop bp ; 5d ; 0xc3610 + pop dx ; 5a ; 0xc3611 + pop bx ; 5b ; 0xc3612 + retn ; c3 ; 0xc3613 + ; disGetNextSymbol 0xc3614 LB 0xca5 -> off=0x0 cb=000000000000000e uValue=00000000000c3614 'readx_byte' +readx_byte: ; 0xc3614 LB 0xe + push bx ; 53 ; 0xc3614 vgabios.c:2450 + push bp ; 55 ; 0xc3615 + mov bp, sp ; 89 e5 ; 0xc3616 + mov bx, dx ; 89 d3 ; 0xc3618 + mov es, ax ; 8e c0 ; 0xc361a vgabios.c:2452 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc361c + pop bp ; 5d ; 0xc361f vgabios.c:2453 + pop bx ; 5b ; 0xc3620 + retn ; c3 ; 0xc3621 + ; disGetNextSymbol 0xc3622 LB 0xc97 -> off=0x8a cb=000000000000047c uValue=00000000000c36ac 'int10_func' + db 056h, 04fh, 01ch, 01bh, 013h, 012h, 011h, 010h, 00eh, 00dh, 00ch, 00ah, 009h, 008h, 007h, 006h + db 005h, 004h, 003h, 002h, 001h, 000h, 021h, 03bh, 0d7h, 036h, 014h, 037h, 028h, 037h, 039h, 037h + db 04dh, 037h, 05eh, 037h, 069h, 037h, 0a3h, 037h, 0a7h, 037h, 0b8h, 037h, 0d5h, 037h, 0f2h, 037h + db 012h, 038h, 02fh, 038h, 046h, 038h, 052h, 038h, 057h, 039h, 0e4h, 039h, 011h, 03ah, 026h, 03ah + db 068h, 03ah, 0f3h, 03ah, 030h, 024h, 023h, 022h, 021h, 020h, 014h, 012h, 011h, 010h, 004h, 003h + db 002h, 001h, 000h, 021h, 03bh, 073h, 038h, 093h, 038h, 0afh, 038h, 0c4h, 038h, 0cfh, 038h, 073h + db 038h, 093h, 038h, 0afh, 038h, 0cfh, 038h, 0e4h, 038h, 0f0h, 038h, 00bh, 039h, 01ch, 039h, 02dh + db 039h, 03eh, 039h, 00ah, 009h, 006h, 004h, 002h, 001h, 000h, 0e5h, 03ah, 090h, 03ah, 09eh, 03ah + db 0afh, 03ah, 0bfh, 03ah, 0d4h, 03ah, 0e5h, 03ah, 0e5h, 03ah +int10_func: ; 0xc36ac LB 0x47c + push bp ; 55 ; 0xc36ac vgabios.c:2531 + mov bp, sp ; 89 e5 ; 0xc36ad + push si ; 56 ; 0xc36af + push di ; 57 ; 0xc36b0 + push ax ; 50 ; 0xc36b1 + mov si, word [bp+004h] ; 8b 76 04 ; 0xc36b2 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc36b5 vgabios.c:2536 + shr ax, 008h ; c1 e8 08 ; 0xc36b8 + cmp ax, strict word 00056h ; 3d 56 00 ; 0xc36bb + jnbe near 03b21h ; 0f 87 5f 04 ; 0xc36be + push CS ; 0e ; 0xc36c2 + pop ES ; 07 ; 0xc36c3 + mov cx, strict word 00017h ; b9 17 00 ; 0xc36c4 + mov di, 03622h ; bf 22 36 ; 0xc36c7 + repne scasb ; f2 ae ; 0xc36ca + sal cx, 1 ; d1 e1 ; 0xc36cc + mov di, cx ; 89 cf ; 0xc36ce + mov ax, word [cs:di+03638h] ; 2e 8b 85 38 36 ; 0xc36d0 + jmp ax ; ff e0 ; 0xc36d5 + movzx ax, byte [bp+012h] ; 0f b6 46 12 ; 0xc36d7 vgabios.c:2539 + call 013ddh ; e8 ff dc ; 0xc36db + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc36de vgabios.c:2540 + and ax, strict word 0007fh ; 25 7f 00 ; 0xc36e1 + cmp ax, strict word 00007h ; 3d 07 00 ; 0xc36e4 + je short 036feh ; 74 15 ; 0xc36e7 + cmp ax, strict word 00006h ; 3d 06 00 ; 0xc36e9 + je short 036f5h ; 74 07 ; 0xc36ec + cmp ax, strict word 00005h ; 3d 05 00 ; 0xc36ee + jbe short 036feh ; 76 0b ; 0xc36f1 + jmp short 03707h ; eb 12 ; 0xc36f3 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc36f5 vgabios.c:2542 + xor al, al ; 30 c0 ; 0xc36f8 + or AL, strict byte 03fh ; 0c 3f ; 0xc36fa + jmp short 0370eh ; eb 10 ; 0xc36fc vgabios.c:2543 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc36fe vgabios.c:2551 + xor al, al ; 30 c0 ; 0xc3701 + or AL, strict byte 030h ; 0c 30 ; 0xc3703 + jmp short 0370eh ; eb 07 ; 0xc3705 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3707 vgabios.c:2554 + xor al, al ; 30 c0 ; 0xc370a + or AL, strict byte 020h ; 0c 20 ; 0xc370c + mov word [bp+012h], ax ; 89 46 12 ; 0xc370e + jmp near 03b21h ; e9 0d 04 ; 0xc3711 vgabios.c:2556 + mov al, byte [bp+010h] ; 8a 46 10 ; 0xc3714 vgabios.c:2558 + movzx dx, al ; 0f b6 d0 ; 0xc3717 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc371a + shr ax, 008h ; c1 e8 08 ; 0xc371d + xor ah, ah ; 30 e4 ; 0xc3720 + call 0114ch ; e8 27 da ; 0xc3722 + jmp near 03b21h ; e9 f9 03 ; 0xc3725 vgabios.c:2559 + mov dx, word [bp+00eh] ; 8b 56 0e ; 0xc3728 vgabios.c:2561 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc372b + shr ax, 008h ; c1 e8 08 ; 0xc372e + xor ah, ah ; 30 e4 ; 0xc3731 + call 01242h ; e8 0c db ; 0xc3733 + jmp near 03b21h ; e9 e8 03 ; 0xc3736 vgabios.c:2562 + lea bx, [bp+00eh] ; 8d 5e 0e ; 0xc3739 vgabios.c:2564 + lea dx, [bp+010h] ; 8d 56 10 ; 0xc373c + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc373f + shr ax, 008h ; c1 e8 08 ; 0xc3742 + xor ah, ah ; 30 e4 ; 0xc3745 + call 00a93h ; e8 49 d3 ; 0xc3747 + jmp near 03b21h ; e9 d4 03 ; 0xc374a vgabios.c:2565 + xor ax, ax ; 31 c0 ; 0xc374d vgabios.c:2571 + mov word [bp+012h], ax ; 89 46 12 ; 0xc374f + mov word [bp+00ch], ax ; 89 46 0c ; 0xc3752 vgabios.c:2572 + mov word [bp+010h], ax ; 89 46 10 ; 0xc3755 vgabios.c:2573 + mov word [bp+00eh], ax ; 89 46 0e ; 0xc3758 vgabios.c:2574 + jmp near 03b21h ; e9 c3 03 ; 0xc375b vgabios.c:2575 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc375e vgabios.c:2577 + xor ah, ah ; 30 e4 ; 0xc3761 + call 012cbh ; e8 65 db ; 0xc3763 + jmp near 03b21h ; e9 b8 03 ; 0xc3766 vgabios.c:2578 + mov ax, strict word 00001h ; b8 01 00 ; 0xc3769 vgabios.c:2580 + push ax ; 50 ; 0xc376c + mov ax, 000ffh ; b8 ff 00 ; 0xc376d + push ax ; 50 ; 0xc3770 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3771 + xor ah, ah ; 30 e4 ; 0xc3774 + push ax ; 50 ; 0xc3776 + mov ax, word [bp+00eh] ; 8b 46 0e ; 0xc3777 + shr ax, 008h ; c1 e8 08 ; 0xc377a + xor ah, ah ; 30 e4 ; 0xc377d + push ax ; 50 ; 0xc377f + mov al, byte [bp+010h] ; 8a 46 10 ; 0xc3780 + movzx cx, al ; 0f b6 c8 ; 0xc3783 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3786 + shr ax, 008h ; c1 e8 08 ; 0xc3789 + movzx bx, al ; 0f b6 d8 ; 0xc378c + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc378f + shr ax, 008h ; c1 e8 08 ; 0xc3792 + movzx dx, al ; 0f b6 d0 ; 0xc3795 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3798 + xor ah, ah ; 30 e4 ; 0xc379b + call 01b5dh ; e8 bd e3 ; 0xc379d + jmp near 03b21h ; e9 7e 03 ; 0xc37a0 vgabios.c:2581 + xor ax, ax ; 31 c0 ; 0xc37a3 vgabios.c:2583 + jmp short 0376ch ; eb c5 ; 0xc37a5 + lea dx, [bp+012h] ; 8d 56 12 ; 0xc37a7 vgabios.c:2586 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc37aa + shr ax, 008h ; c1 e8 08 ; 0xc37ad + xor ah, ah ; 30 e4 ; 0xc37b0 + call 00db0h ; e8 fb d5 ; 0xc37b2 + jmp near 03b21h ; e9 69 03 ; 0xc37b5 vgabios.c:2587 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc37b8 vgabios.c:2589 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc37bb + movzx bx, al ; 0f b6 d8 ; 0xc37be + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc37c1 + shr ax, 008h ; c1 e8 08 ; 0xc37c4 + movzx dx, al ; 0f b6 d0 ; 0xc37c7 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc37ca + xor ah, ah ; 30 e4 ; 0xc37cd + call 023e6h ; e8 14 ec ; 0xc37cf + jmp near 03b21h ; e9 4c 03 ; 0xc37d2 vgabios.c:2590 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc37d5 vgabios.c:2592 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc37d8 + movzx bx, al ; 0f b6 d8 ; 0xc37db + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc37de + shr ax, 008h ; c1 e8 08 ; 0xc37e1 + movzx dx, al ; 0f b6 d0 ; 0xc37e4 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc37e7 + xor ah, ah ; 30 e4 ; 0xc37ea + call 0254bh ; e8 5c ed ; 0xc37ec + jmp near 03b21h ; e9 2f 03 ; 0xc37ef vgabios.c:2593 + mov cx, word [bp+00eh] ; 8b 4e 0e ; 0xc37f2 vgabios.c:2595 + mov bx, word [bp+010h] ; 8b 5e 10 ; 0xc37f5 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc37f8 + movzx dx, al ; 0f b6 d0 ; 0xc37fb + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc37fe + shr ax, 008h ; c1 e8 08 ; 0xc3801 + mov word [bp-006h], ax ; 89 46 fa ; 0xc3804 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc3807 + xor ah, ah ; 30 e4 ; 0xc380a + call 026adh ; e8 9e ee ; 0xc380c + jmp near 03b21h ; e9 0f 03 ; 0xc380f vgabios.c:2596 + lea cx, [bp+012h] ; 8d 4e 12 ; 0xc3812 vgabios.c:2598 + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc3815 + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3818 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc381b + shr ax, 008h ; c1 e8 08 ; 0xc381e + mov word [bp-006h], ax ; 89 46 fa ; 0xc3821 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc3824 + xor ah, ah ; 30 e4 ; 0xc3827 + call 00f6ah ; e8 3e d7 ; 0xc3829 + jmp near 03b21h ; e9 f2 02 ; 0xc382c vgabios.c:2599 + mov cx, strict word 00002h ; b9 02 00 ; 0xc382f vgabios.c:2607 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3832 + movzx bx, al ; 0f b6 d8 ; 0xc3835 + mov dx, 000ffh ; ba ff 00 ; 0xc3838 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc383b + xor ah, ah ; 30 e4 ; 0xc383e + call 02812h ; e8 cf ef ; 0xc3840 + jmp near 03b21h ; e9 db 02 ; 0xc3843 vgabios.c:2608 + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3846 vgabios.c:2611 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3849 + call 010c0h ; e8 71 d8 ; 0xc384c + jmp near 03b21h ; e9 cf 02 ; 0xc384f vgabios.c:2612 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3852 vgabios.c:2614 + xor ah, ah ; 30 e4 ; 0xc3855 + cmp ax, strict word 00030h ; 3d 30 00 ; 0xc3857 + jnbe near 03b21h ; 0f 87 c3 02 ; 0xc385a + push CS ; 0e ; 0xc385e + pop ES ; 07 ; 0xc385f + mov cx, strict word 00010h ; b9 10 00 ; 0xc3860 + mov di, 03666h ; bf 66 36 ; 0xc3863 + repne scasb ; f2 ae ; 0xc3866 + sal cx, 1 ; d1 e1 ; 0xc3868 + mov di, cx ; 89 cf ; 0xc386a + mov ax, word [cs:di+03675h] ; 2e 8b 85 75 36 ; 0xc386c + jmp ax ; ff e0 ; 0xc3871 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3873 vgabios.c:2618 + shr ax, 008h ; c1 e8 08 ; 0xc3876 + xor ah, ah ; 30 e4 ; 0xc3879 + push ax ; 50 ; 0xc387b + movzx ax, byte [bp+00ch] ; 0f b6 46 0c ; 0xc387c + push ax ; 50 ; 0xc3880 + push word [bp+00eh] ; ff 76 0e ; 0xc3881 + movzx ax, byte [bp+012h] ; 0f b6 46 12 ; 0xc3884 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3888 + mov bx, word [bp+008h] ; 8b 5e 08 ; 0xc388b + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc388e + jmp short 038a9h ; eb 16 ; 0xc3891 + push strict byte 0000eh ; 6a 0e ; 0xc3893 vgabios.c:2622 + movzx ax, byte [bp+00ch] ; 0f b6 46 0c ; 0xc3895 + push ax ; 50 ; 0xc3899 + push strict byte 00000h ; 6a 00 ; 0xc389a + movzx ax, byte [bp+012h] ; 0f b6 46 12 ; 0xc389c + mov cx, 00100h ; b9 00 01 ; 0xc38a0 + mov bx, 05d6dh ; bb 6d 5d ; 0xc38a3 + mov dx, 0c000h ; ba 00 c0 ; 0xc38a6 + call 02c0ah ; e8 5e f3 ; 0xc38a9 + jmp near 03b21h ; e9 72 02 ; 0xc38ac + push strict byte 00008h ; 6a 08 ; 0xc38af vgabios.c:2626 + movzx ax, byte [bp+00ch] ; 0f b6 46 0c ; 0xc38b1 + push ax ; 50 ; 0xc38b5 + push strict byte 00000h ; 6a 00 ; 0xc38b6 + movzx ax, byte [bp+012h] ; 0f b6 46 12 ; 0xc38b8 + mov cx, 00100h ; b9 00 01 ; 0xc38bc + mov bx, 0556dh ; bb 6d 55 ; 0xc38bf + jmp short 038a6h ; eb e2 ; 0xc38c2 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc38c4 vgabios.c:2629 + xor ah, ah ; 30 e4 ; 0xc38c7 + call 02b73h ; e8 a7 f2 ; 0xc38c9 + jmp near 03b21h ; e9 52 02 ; 0xc38cc vgabios.c:2630 + push strict byte 00010h ; 6a 10 ; 0xc38cf vgabios.c:2633 + movzx ax, byte [bp+00ch] ; 0f b6 46 0c ; 0xc38d1 + push ax ; 50 ; 0xc38d5 + push strict byte 00000h ; 6a 00 ; 0xc38d6 + movzx ax, byte [bp+012h] ; 0f b6 46 12 ; 0xc38d8 + mov cx, 00100h ; b9 00 01 ; 0xc38dc + mov bx, 06b6dh ; bb 6d 6b ; 0xc38df + jmp short 038a6h ; eb c2 ; 0xc38e2 + mov dx, word [bp+008h] ; 8b 56 08 ; 0xc38e4 vgabios.c:2636 + mov ax, word [bp+016h] ; 8b 46 16 ; 0xc38e7 + call 02c86h ; e8 99 f3 ; 0xc38ea + jmp near 03b21h ; e9 31 02 ; 0xc38ed vgabios.c:2637 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc38f0 vgabios.c:2639 + xor ah, ah ; 30 e4 ; 0xc38f3 + push ax ; 50 ; 0xc38f5 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc38f6 + movzx cx, al ; 0f b6 c8 ; 0xc38f9 + mov bx, word [bp+010h] ; 8b 5e 10 ; 0xc38fc + mov dx, word [bp+008h] ; 8b 56 08 ; 0xc38ff + mov ax, word [bp+016h] ; 8b 46 16 ; 0xc3902 + call 02ce5h ; e8 dd f3 ; 0xc3905 + jmp near 03b21h ; e9 16 02 ; 0xc3908 vgabios.c:2640 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc390b vgabios.c:2642 + movzx dx, al ; 0f b6 d0 ; 0xc390e + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3911 + xor ah, ah ; 30 e4 ; 0xc3914 + call 02d01h ; e8 e8 f3 ; 0xc3916 + jmp near 03b21h ; e9 05 02 ; 0xc3919 vgabios.c:2643 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc391c vgabios.c:2645 + movzx dx, al ; 0f b6 d0 ; 0xc391f + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3922 + xor ah, ah ; 30 e4 ; 0xc3925 + call 02d1fh ; e8 f5 f3 ; 0xc3927 + jmp near 03b21h ; e9 f4 01 ; 0xc392a vgabios.c:2646 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc392d vgabios.c:2648 + movzx dx, al ; 0f b6 d0 ; 0xc3930 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3933 + xor ah, ah ; 30 e4 ; 0xc3936 + call 02d3dh ; e8 02 f4 ; 0xc3938 + jmp near 03b21h ; e9 e3 01 ; 0xc393b vgabios.c:2649 + lea ax, [bp+00eh] ; 8d 46 0e ; 0xc393e vgabios.c:2651 + push ax ; 50 ; 0xc3941 + lea cx, [bp+010h] ; 8d 4e 10 ; 0xc3942 + lea bx, [bp+008h] ; 8d 5e 08 ; 0xc3945 + lea dx, [bp+016h] ; 8d 56 16 ; 0xc3948 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc394b + shr ax, 008h ; c1 e8 08 ; 0xc394e + call 00ee7h ; e8 93 d5 ; 0xc3951 + jmp near 03b21h ; e9 ca 01 ; 0xc3954 vgabios.c:2659 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3957 vgabios.c:2661 + xor ah, ah ; 30 e4 ; 0xc395a + cmp ax, strict word 00034h ; 3d 34 00 ; 0xc395c + jc short 03970h ; 72 0f ; 0xc395f + jbe short 039a3h ; 76 40 ; 0xc3961 + cmp ax, strict word 00036h ; 3d 36 00 ; 0xc3963 + je short 039dah ; 74 72 ; 0xc3966 + cmp ax, strict word 00035h ; 3d 35 00 ; 0xc3968 + je short 039cbh ; 74 5e ; 0xc396b + jmp near 03b21h ; e9 b1 01 ; 0xc396d + cmp ax, strict word 00030h ; 3d 30 00 ; 0xc3970 + je short 03982h ; 74 0d ; 0xc3973 + cmp ax, strict word 00020h ; 3d 20 00 ; 0xc3975 + jne near 03b21h ; 0f 85 a5 01 ; 0xc3978 + call 02d5bh ; e8 dc f3 ; 0xc397c vgabios.c:2664 + jmp near 03b21h ; e9 9f 01 ; 0xc397f vgabios.c:2665 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3982 vgabios.c:2667 + xor ah, ah ; 30 e4 ; 0xc3985 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc3987 + jnbe near 03b21h ; 0f 87 93 01 ; 0xc398a + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc398e vgabios.c:2668 + xor ah, ah ; 30 e4 ; 0xc3991 + call 02d60h ; e8 ca f3 ; 0xc3993 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3996 vgabios.c:2669 + xor al, al ; 30 c0 ; 0xc3999 + or AL, strict byte 012h ; 0c 12 ; 0xc399b + mov word [bp+012h], ax ; 89 46 12 ; 0xc399d + jmp near 03b21h ; e9 7e 01 ; 0xc39a0 vgabios.c:2671 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc39a3 vgabios.c:2673 + xor ah, ah ; 30 e4 ; 0xc39a6 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc39a8 + jnc short 039c5h ; 73 18 ; 0xc39ab + mov ax, strict word 00040h ; b8 40 00 ; 0xc39ad vgabios.c:45 + mov si, 00087h ; be 87 00 ; 0xc39b0 + mov es, ax ; 8e c0 ; 0xc39b3 vgabios.c:47 + mov ah, byte [es:si] ; 26 8a 24 ; 0xc39b5 + and ah, 0feh ; 80 e4 fe ; 0xc39b8 vgabios.c:48 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc39bb + or al, ah ; 08 e0 ; 0xc39be + mov byte [es:si], al ; 26 88 04 ; 0xc39c0 vgabios.c:52 + jmp short 03996h ; eb d1 ; 0xc39c3 + mov byte [bp+012h], ah ; 88 66 12 ; 0xc39c5 vgabios.c:2679 + jmp near 03b21h ; e9 56 01 ; 0xc39c8 vgabios.c:2680 + movzx ax, byte [bp+012h] ; 0f b6 46 12 ; 0xc39cb vgabios.c:2682 + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc39cf + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc39d2 + call 02d92h ; e8 ba f3 ; 0xc39d5 + jmp short 03996h ; eb bc ; 0xc39d8 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc39da vgabios.c:2686 + xor ah, ah ; 30 e4 ; 0xc39dd + call 02d97h ; e8 b5 f3 ; 0xc39df + jmp short 03996h ; eb b2 ; 0xc39e2 + push word [bp+008h] ; ff 76 08 ; 0xc39e4 vgabios.c:2696 + push word [bp+016h] ; ff 76 16 ; 0xc39e7 + movzx ax, byte [bp+00eh] ; 0f b6 46 0e ; 0xc39ea + push ax ; 50 ; 0xc39ee + mov ax, word [bp+00eh] ; 8b 46 0e ; 0xc39ef + shr ax, 008h ; c1 e8 08 ; 0xc39f2 + xor ah, ah ; 30 e4 ; 0xc39f5 + push ax ; 50 ; 0xc39f7 + movzx bx, byte [bp+00ch] ; 0f b6 5e 0c ; 0xc39f8 + mov dx, word [bp+00ch] ; 8b 56 0c ; 0xc39fc + shr dx, 008h ; c1 ea 08 ; 0xc39ff + xor dh, dh ; 30 f6 ; 0xc3a02 + movzx ax, byte [bp+012h] ; 0f b6 46 12 ; 0xc3a04 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3a08 + call 02d9ch ; e8 8e f3 ; 0xc3a0b + jmp near 03b21h ; e9 10 01 ; 0xc3a0e vgabios.c:2697 + mov bx, si ; 89 f3 ; 0xc3a11 vgabios.c:2699 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3a13 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3a16 + call 02e32h ; e8 16 f4 ; 0xc3a19 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3a1c vgabios.c:2700 + xor al, al ; 30 c0 ; 0xc3a1f + or AL, strict byte 01bh ; 0c 1b ; 0xc3a21 + jmp near 0399dh ; e9 77 ff ; 0xc3a23 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3a26 vgabios.c:2703 + xor ah, ah ; 30 e4 ; 0xc3a29 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc3a2b + je short 03a52h ; 74 22 ; 0xc3a2e + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc3a30 + je short 03a44h ; 74 0f ; 0xc3a33 + test ax, ax ; 85 c0 ; 0xc3a35 + jne short 03a5eh ; 75 25 ; 0xc3a37 + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3a39 vgabios.c:2706 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3a3c + call 03047h ; e8 05 f6 ; 0xc3a3f + jmp short 03a5eh ; eb 1a ; 0xc3a42 vgabios.c:2707 + mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xc3a44 vgabios.c:2709 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3a47 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3a4a + call 0305fh ; e8 0f f6 ; 0xc3a4d + jmp short 03a5eh ; eb 0c ; 0xc3a50 vgabios.c:2710 + mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xc3a52 vgabios.c:2712 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3a55 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3a58 + call 03335h ; e8 d7 f8 ; 0xc3a5b + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3a5e vgabios.c:2719 + xor al, al ; 30 c0 ; 0xc3a61 + or AL, strict byte 01ch ; 0c 1c ; 0xc3a63 + jmp near 0399dh ; e9 35 ff ; 0xc3a65 + call 007bfh ; e8 54 cd ; 0xc3a68 vgabios.c:2724 + test ax, ax ; 85 c0 ; 0xc3a6b + je near 03aech ; 0f 84 7b 00 ; 0xc3a6d + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3a71 vgabios.c:2725 + xor ah, ah ; 30 e4 ; 0xc3a74 + cmp ax, strict word 0000ah ; 3d 0a 00 ; 0xc3a76 + jnbe short 03ae5h ; 77 6a ; 0xc3a79 + push CS ; 0e ; 0xc3a7b + pop ES ; 07 ; 0xc3a7c + mov cx, strict word 00008h ; b9 08 00 ; 0xc3a7d + mov di, 03695h ; bf 95 36 ; 0xc3a80 + repne scasb ; f2 ae ; 0xc3a83 + sal cx, 1 ; d1 e1 ; 0xc3a85 + mov di, cx ; 89 cf ; 0xc3a87 + mov ax, word [cs:di+0369ch] ; 2e 8b 85 9c 36 ; 0xc3a89 + jmp ax ; ff e0 ; 0xc3a8e + mov bx, si ; 89 f3 ; 0xc3a90 vgabios.c:2728 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3a92 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3a95 + call 03cf2h ; e8 57 02 ; 0xc3a98 + jmp near 03b21h ; e9 83 00 ; 0xc3a9b vgabios.c:2729 + mov cx, si ; 89 f1 ; 0xc3a9e vgabios.c:2731 + mov bx, word [bp+016h] ; 8b 5e 16 ; 0xc3aa0 + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3aa3 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3aa6 + call 03e17h ; e8 6b 03 ; 0xc3aa9 + jmp near 03b21h ; e9 72 00 ; 0xc3aac vgabios.c:2732 + mov cx, si ; 89 f1 ; 0xc3aaf vgabios.c:2734 + mov bx, word [bp+016h] ; 8b 5e 16 ; 0xc3ab1 + mov dx, word [bp+00ch] ; 8b 56 0c ; 0xc3ab4 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3ab7 + call 03eb2h ; e8 f5 03 ; 0xc3aba + jmp short 03b21h ; eb 62 ; 0xc3abd vgabios.c:2735 + lea ax, [bp+00ch] ; 8d 46 0c ; 0xc3abf vgabios.c:2737 + push ax ; 50 ; 0xc3ac2 + mov cx, word [bp+016h] ; 8b 4e 16 ; 0xc3ac3 + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc3ac6 + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3ac9 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3acc + call 04079h ; e8 a7 05 ; 0xc3acf + jmp short 03b21h ; eb 4d ; 0xc3ad2 vgabios.c:2738 + lea cx, [bp+00eh] ; 8d 4e 0e ; 0xc3ad4 vgabios.c:2740 + lea bx, [bp+010h] ; 8d 5e 10 ; 0xc3ad7 + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3ada + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3add + call 04105h ; e8 22 06 ; 0xc3ae0 + jmp short 03b21h ; eb 3c ; 0xc3ae3 vgabios.c:2741 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3ae5 vgabios.c:2763 + jmp short 03b21h ; eb 35 ; 0xc3aea vgabios.c:2766 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3aec vgabios.c:2768 + jmp short 03b21h ; eb 2e ; 0xc3af1 vgabios.c:2770 + call 007bfh ; e8 c9 cc ; 0xc3af3 vgabios.c:2772 + test ax, ax ; 85 c0 ; 0xc3af6 + je short 03b1ch ; 74 22 ; 0xc3af8 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3afa vgabios.c:2773 + xor ah, ah ; 30 e4 ; 0xc3afd + cmp ax, strict word 00042h ; 3d 42 00 ; 0xc3aff + jne short 03b15h ; 75 11 ; 0xc3b02 + lea cx, [bp+00eh] ; 8d 4e 0e ; 0xc3b04 vgabios.c:2776 + lea bx, [bp+010h] ; 8d 5e 10 ; 0xc3b07 + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3b0a + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3b0d + call 041d4h ; e8 c1 06 ; 0xc3b10 + jmp short 03b21h ; eb 0c ; 0xc3b13 vgabios.c:2777 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3b15 vgabios.c:2779 + jmp short 03b21h ; eb 05 ; 0xc3b1a vgabios.c:2782 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3b1c vgabios.c:2784 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3b21 vgabios.c:2794 + pop di ; 5f ; 0xc3b24 + pop si ; 5e ; 0xc3b25 + pop bp ; 5d ; 0xc3b26 + retn ; c3 ; 0xc3b27 + ; disGetNextSymbol 0xc3b28 LB 0x791 -> off=0x0 cb=000000000000001f uValue=00000000000c3b28 'dispi_set_xres' +dispi_set_xres: ; 0xc3b28 LB 0x1f + push bp ; 55 ; 0xc3b28 vbe.c:100 + mov bp, sp ; 89 e5 ; 0xc3b29 + push bx ; 53 ; 0xc3b2b + push dx ; 52 ; 0xc3b2c + mov bx, ax ; 89 c3 ; 0xc3b2d + mov ax, strict word 00001h ; b8 01 00 ; 0xc3b2f vbe.c:105 + mov dx, 001ceh ; ba ce 01 ; 0xc3b32 + call 00570h ; e8 38 ca ; 0xc3b35 + mov ax, bx ; 89 d8 ; 0xc3b38 vbe.c:106 + mov dx, 001cfh ; ba cf 01 ; 0xc3b3a + call 00570h ; e8 30 ca ; 0xc3b3d + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3b40 vbe.c:107 + pop dx ; 5a ; 0xc3b43 + pop bx ; 5b ; 0xc3b44 + pop bp ; 5d ; 0xc3b45 + retn ; c3 ; 0xc3b46 + ; disGetNextSymbol 0xc3b47 LB 0x772 -> off=0x0 cb=000000000000001f uValue=00000000000c3b47 'dispi_set_yres' +dispi_set_yres: ; 0xc3b47 LB 0x1f + push bp ; 55 ; 0xc3b47 vbe.c:109 + mov bp, sp ; 89 e5 ; 0xc3b48 + push bx ; 53 ; 0xc3b4a + push dx ; 52 ; 0xc3b4b + mov bx, ax ; 89 c3 ; 0xc3b4c + mov ax, strict word 00002h ; b8 02 00 ; 0xc3b4e vbe.c:114 + mov dx, 001ceh ; ba ce 01 ; 0xc3b51 + call 00570h ; e8 19 ca ; 0xc3b54 + mov ax, bx ; 89 d8 ; 0xc3b57 vbe.c:115 + mov dx, 001cfh ; ba cf 01 ; 0xc3b59 + call 00570h ; e8 11 ca ; 0xc3b5c + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3b5f vbe.c:116 + pop dx ; 5a ; 0xc3b62 + pop bx ; 5b ; 0xc3b63 + pop bp ; 5d ; 0xc3b64 + retn ; c3 ; 0xc3b65 + ; disGetNextSymbol 0xc3b66 LB 0x753 -> off=0x0 cb=0000000000000019 uValue=00000000000c3b66 'dispi_get_yres' +dispi_get_yres: ; 0xc3b66 LB 0x19 + push bp ; 55 ; 0xc3b66 vbe.c:118 + mov bp, sp ; 89 e5 ; 0xc3b67 + push dx ; 52 ; 0xc3b69 + mov ax, strict word 00002h ; b8 02 00 ; 0xc3b6a vbe.c:120 + mov dx, 001ceh ; ba ce 01 ; 0xc3b6d + call 00570h ; e8 fd c9 ; 0xc3b70 + mov dx, 001cfh ; ba cf 01 ; 0xc3b73 vbe.c:121 + call 00577h ; e8 fe c9 ; 0xc3b76 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3b79 vbe.c:122 + pop dx ; 5a ; 0xc3b7c + pop bp ; 5d ; 0xc3b7d + retn ; c3 ; 0xc3b7e + ; disGetNextSymbol 0xc3b7f LB 0x73a -> off=0x0 cb=000000000000001f uValue=00000000000c3b7f 'dispi_set_bpp' +dispi_set_bpp: ; 0xc3b7f LB 0x1f + push bp ; 55 ; 0xc3b7f vbe.c:124 + mov bp, sp ; 89 e5 ; 0xc3b80 + push bx ; 53 ; 0xc3b82 + push dx ; 52 ; 0xc3b83 + mov bx, ax ; 89 c3 ; 0xc3b84 + mov ax, strict word 00003h ; b8 03 00 ; 0xc3b86 vbe.c:129 + mov dx, 001ceh ; ba ce 01 ; 0xc3b89 + call 00570h ; e8 e1 c9 ; 0xc3b8c + mov ax, bx ; 89 d8 ; 0xc3b8f vbe.c:130 + mov dx, 001cfh ; ba cf 01 ; 0xc3b91 + call 00570h ; e8 d9 c9 ; 0xc3b94 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3b97 vbe.c:131 + pop dx ; 5a ; 0xc3b9a + pop bx ; 5b ; 0xc3b9b + pop bp ; 5d ; 0xc3b9c + retn ; c3 ; 0xc3b9d + ; disGetNextSymbol 0xc3b9e LB 0x71b -> off=0x0 cb=0000000000000019 uValue=00000000000c3b9e 'dispi_get_bpp' +dispi_get_bpp: ; 0xc3b9e LB 0x19 + push bp ; 55 ; 0xc3b9e vbe.c:133 + mov bp, sp ; 89 e5 ; 0xc3b9f + push dx ; 52 ; 0xc3ba1 + mov ax, strict word 00003h ; b8 03 00 ; 0xc3ba2 vbe.c:135 + mov dx, 001ceh ; ba ce 01 ; 0xc3ba5 + call 00570h ; e8 c5 c9 ; 0xc3ba8 + mov dx, 001cfh ; ba cf 01 ; 0xc3bab vbe.c:136 + call 00577h ; e8 c6 c9 ; 0xc3bae + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3bb1 vbe.c:137 + pop dx ; 5a ; 0xc3bb4 + pop bp ; 5d ; 0xc3bb5 + retn ; c3 ; 0xc3bb6 + ; disGetNextSymbol 0xc3bb7 LB 0x702 -> off=0x0 cb=000000000000001f uValue=00000000000c3bb7 'dispi_set_virt_width' +dispi_set_virt_width: ; 0xc3bb7 LB 0x1f + push bp ; 55 ; 0xc3bb7 vbe.c:139 + mov bp, sp ; 89 e5 ; 0xc3bb8 + push bx ; 53 ; 0xc3bba + push dx ; 52 ; 0xc3bbb + mov bx, ax ; 89 c3 ; 0xc3bbc + mov ax, strict word 00006h ; b8 06 00 ; 0xc3bbe vbe.c:144 + mov dx, 001ceh ; ba ce 01 ; 0xc3bc1 + call 00570h ; e8 a9 c9 ; 0xc3bc4 + mov ax, bx ; 89 d8 ; 0xc3bc7 vbe.c:145 + mov dx, 001cfh ; ba cf 01 ; 0xc3bc9 + call 00570h ; e8 a1 c9 ; 0xc3bcc + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3bcf vbe.c:146 + pop dx ; 5a ; 0xc3bd2 + pop bx ; 5b ; 0xc3bd3 + pop bp ; 5d ; 0xc3bd4 + retn ; c3 ; 0xc3bd5 + ; disGetNextSymbol 0xc3bd6 LB 0x6e3 -> off=0x0 cb=0000000000000019 uValue=00000000000c3bd6 'dispi_get_virt_width' +dispi_get_virt_width: ; 0xc3bd6 LB 0x19 + push bp ; 55 ; 0xc3bd6 vbe.c:148 + mov bp, sp ; 89 e5 ; 0xc3bd7 + push dx ; 52 ; 0xc3bd9 + mov ax, strict word 00006h ; b8 06 00 ; 0xc3bda vbe.c:150 + mov dx, 001ceh ; ba ce 01 ; 0xc3bdd + call 00570h ; e8 8d c9 ; 0xc3be0 + mov dx, 001cfh ; ba cf 01 ; 0xc3be3 vbe.c:151 + call 00577h ; e8 8e c9 ; 0xc3be6 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3be9 vbe.c:152 + pop dx ; 5a ; 0xc3bec + pop bp ; 5d ; 0xc3bed + retn ; c3 ; 0xc3bee + ; disGetNextSymbol 0xc3bef LB 0x6ca -> off=0x0 cb=0000000000000019 uValue=00000000000c3bef 'dispi_get_virt_height' +dispi_get_virt_height: ; 0xc3bef LB 0x19 + push bp ; 55 ; 0xc3bef vbe.c:154 + mov bp, sp ; 89 e5 ; 0xc3bf0 + push dx ; 52 ; 0xc3bf2 + mov ax, strict word 00007h ; b8 07 00 ; 0xc3bf3 vbe.c:156 + mov dx, 001ceh ; ba ce 01 ; 0xc3bf6 + call 00570h ; e8 74 c9 ; 0xc3bf9 + mov dx, 001cfh ; ba cf 01 ; 0xc3bfc vbe.c:157 + call 00577h ; e8 75 c9 ; 0xc3bff + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3c02 vbe.c:158 + pop dx ; 5a ; 0xc3c05 + pop bp ; 5d ; 0xc3c06 + retn ; c3 ; 0xc3c07 + ; disGetNextSymbol 0xc3c08 LB 0x6b1 -> off=0x0 cb=0000000000000012 uValue=00000000000c3c08 'in_word' +in_word: ; 0xc3c08 LB 0x12 + push bp ; 55 ; 0xc3c08 vbe.c:160 + mov bp, sp ; 89 e5 ; 0xc3c09 + push bx ; 53 ; 0xc3c0b + mov bx, ax ; 89 c3 ; 0xc3c0c + mov ax, dx ; 89 d0 ; 0xc3c0e + mov dx, bx ; 89 da ; 0xc3c10 vbe.c:162 + out DX, ax ; ef ; 0xc3c12 + in ax, DX ; ed ; 0xc3c13 vbe.c:163 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3c14 vbe.c:164 + pop bx ; 5b ; 0xc3c17 + pop bp ; 5d ; 0xc3c18 + retn ; c3 ; 0xc3c19 + ; disGetNextSymbol 0xc3c1a LB 0x69f -> off=0x0 cb=0000000000000014 uValue=00000000000c3c1a 'in_byte' +in_byte: ; 0xc3c1a LB 0x14 + push bp ; 55 ; 0xc3c1a vbe.c:166 + mov bp, sp ; 89 e5 ; 0xc3c1b + push bx ; 53 ; 0xc3c1d + mov bx, ax ; 89 c3 ; 0xc3c1e + mov ax, dx ; 89 d0 ; 0xc3c20 + mov dx, bx ; 89 da ; 0xc3c22 vbe.c:168 + out DX, ax ; ef ; 0xc3c24 + in AL, DX ; ec ; 0xc3c25 vbe.c:169 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3c26 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3c28 vbe.c:170 + pop bx ; 5b ; 0xc3c2b + pop bp ; 5d ; 0xc3c2c + retn ; c3 ; 0xc3c2d + ; disGetNextSymbol 0xc3c2e LB 0x68b -> off=0x0 cb=0000000000000014 uValue=00000000000c3c2e 'dispi_get_id' +dispi_get_id: ; 0xc3c2e LB 0x14 + push bp ; 55 ; 0xc3c2e vbe.c:173 + mov bp, sp ; 89 e5 ; 0xc3c2f + push dx ; 52 ; 0xc3c31 + xor ax, ax ; 31 c0 ; 0xc3c32 vbe.c:175 + mov dx, 001ceh ; ba ce 01 ; 0xc3c34 + out DX, ax ; ef ; 0xc3c37 + mov dx, 001cfh ; ba cf 01 ; 0xc3c38 vbe.c:176 + in ax, DX ; ed ; 0xc3c3b + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3c3c vbe.c:177 + pop dx ; 5a ; 0xc3c3f + pop bp ; 5d ; 0xc3c40 + retn ; c3 ; 0xc3c41 + ; disGetNextSymbol 0xc3c42 LB 0x677 -> off=0x0 cb=000000000000001a uValue=00000000000c3c42 'dispi_set_id' +dispi_set_id: ; 0xc3c42 LB 0x1a + push bp ; 55 ; 0xc3c42 vbe.c:179 + mov bp, sp ; 89 e5 ; 0xc3c43 + push bx ; 53 ; 0xc3c45 + push dx ; 52 ; 0xc3c46 + mov bx, ax ; 89 c3 ; 0xc3c47 + xor ax, ax ; 31 c0 ; 0xc3c49 vbe.c:181 + mov dx, 001ceh ; ba ce 01 ; 0xc3c4b + out DX, ax ; ef ; 0xc3c4e + mov ax, bx ; 89 d8 ; 0xc3c4f vbe.c:182 + mov dx, 001cfh ; ba cf 01 ; 0xc3c51 + out DX, ax ; ef ; 0xc3c54 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3c55 vbe.c:183 + pop dx ; 5a ; 0xc3c58 + pop bx ; 5b ; 0xc3c59 + pop bp ; 5d ; 0xc3c5a + retn ; c3 ; 0xc3c5b + ; disGetNextSymbol 0xc3c5c LB 0x65d -> off=0x0 cb=000000000000002a uValue=00000000000c3c5c 'vbe_init' +vbe_init: ; 0xc3c5c LB 0x2a + push bp ; 55 ; 0xc3c5c vbe.c:188 + mov bp, sp ; 89 e5 ; 0xc3c5d + push bx ; 53 ; 0xc3c5f + mov ax, 0b0c0h ; b8 c0 b0 ; 0xc3c60 vbe.c:190 + call 03c42h ; e8 dc ff ; 0xc3c63 + call 03c2eh ; e8 c5 ff ; 0xc3c66 vbe.c:191 + cmp ax, 0b0c0h ; 3d c0 b0 ; 0xc3c69 + jne short 03c80h ; 75 12 ; 0xc3c6c + mov bx, 000b9h ; bb b9 00 ; 0xc3c6e vbe.c:52 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3c71 + mov es, ax ; 8e c0 ; 0xc3c74 + mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xc3c76 + mov ax, 0b0c4h ; b8 c4 b0 ; 0xc3c7a vbe.c:194 + call 03c42h ; e8 c2 ff ; 0xc3c7d + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3c80 vbe.c:199 + pop bx ; 5b ; 0xc3c83 + pop bp ; 5d ; 0xc3c84 + retn ; c3 ; 0xc3c85 + ; disGetNextSymbol 0xc3c86 LB 0x633 -> off=0x0 cb=000000000000006c uValue=00000000000c3c86 'mode_info_find_mode' +mode_info_find_mode: ; 0xc3c86 LB 0x6c + push bp ; 55 ; 0xc3c86 vbe.c:202 + mov bp, sp ; 89 e5 ; 0xc3c87 + push bx ; 53 ; 0xc3c89 + push cx ; 51 ; 0xc3c8a + push si ; 56 ; 0xc3c8b + push di ; 57 ; 0xc3c8c + mov di, ax ; 89 c7 ; 0xc3c8d + mov si, dx ; 89 d6 ; 0xc3c8f + xor dx, dx ; 31 d2 ; 0xc3c91 vbe.c:208 + mov ax, 003b6h ; b8 b6 03 ; 0xc3c93 + call 03c08h ; e8 6f ff ; 0xc3c96 + cmp ax, 077cch ; 3d cc 77 ; 0xc3c99 vbe.c:209 + jne short 03ce7h ; 75 49 ; 0xc3c9c + test si, si ; 85 f6 ; 0xc3c9e vbe.c:213 + je short 03cb5h ; 74 13 ; 0xc3ca0 + mov ax, strict word 0000bh ; b8 0b 00 ; 0xc3ca2 vbe.c:220 + mov dx, 001ceh ; ba ce 01 ; 0xc3ca5 + call 00570h ; e8 c5 c8 ; 0xc3ca8 + mov dx, 001cfh ; ba cf 01 ; 0xc3cab vbe.c:221 + call 00577h ; e8 c6 c8 ; 0xc3cae + test ax, ax ; 85 c0 ; 0xc3cb1 vbe.c:222 + je short 03ce9h ; 74 34 ; 0xc3cb3 + mov bx, strict word 00004h ; bb 04 00 ; 0xc3cb5 vbe.c:226 + mov dx, bx ; 89 da ; 0xc3cb8 vbe.c:232 + mov ax, 003b6h ; b8 b6 03 ; 0xc3cba + call 03c08h ; e8 48 ff ; 0xc3cbd + mov cx, ax ; 89 c1 ; 0xc3cc0 + cmp cx, strict byte 0ffffh ; 83 f9 ff ; 0xc3cc2 vbe.c:233 + je short 03ce7h ; 74 20 ; 0xc3cc5 + lea dx, [bx+002h] ; 8d 57 02 ; 0xc3cc7 vbe.c:235 + mov ax, 003b6h ; b8 b6 03 ; 0xc3cca + call 03c08h ; e8 38 ff ; 0xc3ccd + lea dx, [bx+044h] ; 8d 57 44 ; 0xc3cd0 + cmp cx, di ; 39 f9 ; 0xc3cd3 vbe.c:237 + jne short 03ce3h ; 75 0c ; 0xc3cd5 + test si, si ; 85 f6 ; 0xc3cd7 vbe.c:239 + jne short 03cdfh ; 75 04 ; 0xc3cd9 + mov ax, bx ; 89 d8 ; 0xc3cdb vbe.c:240 + jmp short 03ce9h ; eb 0a ; 0xc3cdd + test AL, strict byte 080h ; a8 80 ; 0xc3cdf vbe.c:241 + jne short 03cdbh ; 75 f8 ; 0xc3ce1 + mov bx, dx ; 89 d3 ; 0xc3ce3 vbe.c:244 + jmp short 03cbah ; eb d3 ; 0xc3ce5 vbe.c:249 + xor ax, ax ; 31 c0 ; 0xc3ce7 vbe.c:252 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc3ce9 vbe.c:253 + pop di ; 5f ; 0xc3cec + pop si ; 5e ; 0xc3ced + pop cx ; 59 ; 0xc3cee + pop bx ; 5b ; 0xc3cef + pop bp ; 5d ; 0xc3cf0 + retn ; c3 ; 0xc3cf1 + ; disGetNextSymbol 0xc3cf2 LB 0x5c7 -> off=0x0 cb=0000000000000125 uValue=00000000000c3cf2 'vbe_biosfn_return_controller_information' +vbe_biosfn_return_controller_information: ; 0xc3cf2 LB 0x125 + push bp ; 55 ; 0xc3cf2 vbe.c:284 + mov bp, sp ; 89 e5 ; 0xc3cf3 + push cx ; 51 ; 0xc3cf5 + push si ; 56 ; 0xc3cf6 + push di ; 57 ; 0xc3cf7 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc3cf8 + mov si, ax ; 89 c6 ; 0xc3cfb + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc3cfd + mov di, bx ; 89 df ; 0xc3d00 + mov word [bp-00ch], strict word 00022h ; c7 46 f4 22 00 ; 0xc3d02 vbe.c:289 + call 005b7h ; e8 ad c8 ; 0xc3d07 vbe.c:292 + mov word [bp-010h], ax ; 89 46 f0 ; 0xc3d0a + mov bx, di ; 89 fb ; 0xc3d0d vbe.c:295 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3d0f + mov word [bp-008h], ax ; 89 46 f8 ; 0xc3d12 + xor dx, dx ; 31 d2 ; 0xc3d15 vbe.c:298 + mov ax, 003b6h ; b8 b6 03 ; 0xc3d17 + call 03c08h ; e8 eb fe ; 0xc3d1a + cmp ax, 077cch ; 3d cc 77 ; 0xc3d1d vbe.c:299 + je short 03d2ch ; 74 0a ; 0xc3d20 + push SS ; 16 ; 0xc3d22 vbe.c:301 + pop ES ; 07 ; 0xc3d23 + mov word [es:si], 00100h ; 26 c7 04 00 01 ; 0xc3d24 + jmp near 03e0fh ; e9 e3 00 ; 0xc3d29 vbe.c:305 + mov cx, strict word 00004h ; b9 04 00 ; 0xc3d2c vbe.c:307 + mov word [bp-00eh], strict word 00000h ; c7 46 f2 00 00 ; 0xc3d2f vbe.c:314 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc3d34 vbe.c:322 + cmp word [es:bx+002h], 03245h ; 26 81 7f 02 45 32 ; 0xc3d37 + jne short 03d46h ; 75 07 ; 0xc3d3d + cmp word [es:bx], 04256h ; 26 81 3f 56 42 ; 0xc3d3f + je short 03d55h ; 74 0f ; 0xc3d44 + cmp word [es:bx+002h], 04153h ; 26 81 7f 02 53 41 ; 0xc3d46 + jne short 03d5ah ; 75 0c ; 0xc3d4c + cmp word [es:bx], 04556h ; 26 81 3f 56 45 ; 0xc3d4e + jne short 03d5ah ; 75 05 ; 0xc3d53 + mov word [bp-00eh], strict word 00001h ; c7 46 f2 01 00 ; 0xc3d55 vbe.c:324 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc3d5a vbe.c:332 + db 066h, 026h, 0c7h, 007h, 056h, 045h, 053h, 041h + ; mov dword [es:bx], strict dword 041534556h ; 66 26 c7 07 56 45 53 41 ; 0xc3d5d + mov word [es:bx+004h], 00200h ; 26 c7 47 04 00 02 ; 0xc3d65 vbe.c:338 + mov word [es:bx+006h], 07e02h ; 26 c7 47 06 02 7e ; 0xc3d6b vbe.c:341 + mov [es:bx+008h], ds ; 26 8c 5f 08 ; 0xc3d71 + db 066h, 026h, 0c7h, 047h, 00ah, 001h, 000h, 000h, 000h + ; mov dword [es:bx+00ah], strict dword 000000001h ; 66 26 c7 47 0a 01 00 00 00; 0xc3d75 vbe.c:344 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3d7e vbe.c:350 + mov word [es:bx+010h], ax ; 26 89 47 10 ; 0xc3d81 + lea ax, [di+022h] ; 8d 45 22 ; 0xc3d85 vbe.c:351 + mov word [es:bx+00eh], ax ; 26 89 47 0e ; 0xc3d88 + mov dx, strict word 0ffffh ; ba ff ff ; 0xc3d8c vbe.c:354 + mov ax, 003b6h ; b8 b6 03 ; 0xc3d8f + call 03c08h ; e8 73 fe ; 0xc3d92 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc3d95 + mov word [es:bx+012h], ax ; 26 89 47 12 ; 0xc3d98 + cmp word [bp-00eh], strict byte 00000h ; 83 7e f2 00 ; 0xc3d9c vbe.c:356 + je short 03dc6h ; 74 24 ; 0xc3da0 + mov word [es:bx+014h], strict word 00003h ; 26 c7 47 14 03 00 ; 0xc3da2 vbe.c:359 + mov word [es:bx+016h], 07e17h ; 26 c7 47 16 17 7e ; 0xc3da8 vbe.c:360 + mov [es:bx+018h], ds ; 26 8c 5f 18 ; 0xc3dae + mov word [es:bx+01ah], 07e34h ; 26 c7 47 1a 34 7e ; 0xc3db2 vbe.c:361 + mov [es:bx+01ch], ds ; 26 8c 5f 1c ; 0xc3db8 + mov word [es:bx+01eh], 07e55h ; 26 c7 47 1e 55 7e ; 0xc3dbc vbe.c:362 + mov [es:bx+020h], ds ; 26 8c 5f 20 ; 0xc3dc2 + mov dx, cx ; 89 ca ; 0xc3dc6 vbe.c:369 + add dx, strict byte 0001bh ; 83 c2 1b ; 0xc3dc8 + mov ax, 003b6h ; b8 b6 03 ; 0xc3dcb + call 03c1ah ; e8 49 fe ; 0xc3dce + xor ah, ah ; 30 e4 ; 0xc3dd1 vbe.c:370 + cmp ax, word [bp-010h] ; 3b 46 f0 ; 0xc3dd3 + jnbe short 03defh ; 77 17 ; 0xc3dd6 + mov dx, cx ; 89 ca ; 0xc3dd8 vbe.c:372 + mov ax, 003b6h ; b8 b6 03 ; 0xc3dda + call 03c08h ; e8 28 fe ; 0xc3ddd + mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xc3de0 vbe.c:376 + add bx, di ; 01 fb ; 0xc3de3 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc3de5 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3de8 + add word [bp-00ch], strict byte 00002h ; 83 46 f4 02 ; 0xc3deb vbe.c:378 + add cx, strict byte 00044h ; 83 c1 44 ; 0xc3def vbe.c:380 + mov dx, cx ; 89 ca ; 0xc3df2 vbe.c:381 + mov ax, 003b6h ; b8 b6 03 ; 0xc3df4 + call 03c08h ; e8 0e fe ; 0xc3df7 + cmp ax, strict word 0ffffh ; 3d ff ff ; 0xc3dfa vbe.c:382 + jne short 03dc6h ; 75 c7 ; 0xc3dfd + add di, word [bp-00ch] ; 03 7e f4 ; 0xc3dff vbe.c:385 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc3e02 vbe.c:62 + mov word [es:di], ax ; 26 89 05 ; 0xc3e05 + push SS ; 16 ; 0xc3e08 vbe.c:386 + pop ES ; 07 ; 0xc3e09 + mov word [es:si], strict word 0004fh ; 26 c7 04 4f 00 ; 0xc3e0a + lea sp, [bp-006h] ; 8d 66 fa ; 0xc3e0f vbe.c:387 + pop di ; 5f ; 0xc3e12 + pop si ; 5e ; 0xc3e13 + pop cx ; 59 ; 0xc3e14 + pop bp ; 5d ; 0xc3e15 + retn ; c3 ; 0xc3e16 + ; disGetNextSymbol 0xc3e17 LB 0x4a2 -> off=0x0 cb=000000000000009b uValue=00000000000c3e17 'vbe_biosfn_return_mode_information' +vbe_biosfn_return_mode_information: ; 0xc3e17 LB 0x9b + push bp ; 55 ; 0xc3e17 vbe.c:399 + mov bp, sp ; 89 e5 ; 0xc3e18 + push si ; 56 ; 0xc3e1a + push di ; 57 ; 0xc3e1b + push ax ; 50 ; 0xc3e1c + push ax ; 50 ; 0xc3e1d + mov ax, dx ; 89 d0 ; 0xc3e1e + mov si, bx ; 89 de ; 0xc3e20 + mov bx, cx ; 89 cb ; 0xc3e22 + test dh, 040h ; f6 c6 40 ; 0xc3e24 vbe.c:410 + db 00fh, 095h, 0c2h + ; setne dl ; 0f 95 c2 ; 0xc3e27 + xor dh, dh ; 30 f6 ; 0xc3e2a + and ah, 001h ; 80 e4 01 ; 0xc3e2c vbe.c:411 + call 03c86h ; e8 54 fe ; 0xc3e2f vbe.c:413 + mov word [bp-006h], ax ; 89 46 fa ; 0xc3e32 + test ax, ax ; 85 c0 ; 0xc3e35 vbe.c:415 + je short 03ea0h ; 74 67 ; 0xc3e37 + mov cx, 00100h ; b9 00 01 ; 0xc3e39 vbe.c:420 + xor ax, ax ; 31 c0 ; 0xc3e3c + mov di, bx ; 89 df ; 0xc3e3e + mov es, si ; 8e c6 ; 0xc3e40 + jcxz 03e46h ; e3 02 ; 0xc3e42 + rep stosb ; f3 aa ; 0xc3e44 + xor cx, cx ; 31 c9 ; 0xc3e46 vbe.c:421 + jmp short 03e4fh ; eb 05 ; 0xc3e48 + cmp cx, strict byte 00042h ; 83 f9 42 ; 0xc3e4a + jnc short 03e68h ; 73 19 ; 0xc3e4d + mov dx, word [bp-006h] ; 8b 56 fa ; 0xc3e4f vbe.c:424 + inc dx ; 42 ; 0xc3e52 + inc dx ; 42 ; 0xc3e53 + add dx, cx ; 01 ca ; 0xc3e54 + mov ax, 003b6h ; b8 b6 03 ; 0xc3e56 + call 03c1ah ; e8 be fd ; 0xc3e59 + mov di, bx ; 89 df ; 0xc3e5c vbe.c:425 + add di, cx ; 01 cf ; 0xc3e5e + mov es, si ; 8e c6 ; 0xc3e60 vbe.c:52 + mov byte [es:di], al ; 26 88 05 ; 0xc3e62 + inc cx ; 41 ; 0xc3e65 vbe.c:426 + jmp short 03e4ah ; eb e2 ; 0xc3e66 + lea di, [bx+002h] ; 8d 7f 02 ; 0xc3e68 vbe.c:427 + mov es, si ; 8e c6 ; 0xc3e6b vbe.c:47 + mov al, byte [es:di] ; 26 8a 05 ; 0xc3e6d + test AL, strict byte 001h ; a8 01 ; 0xc3e70 vbe.c:428 + je short 03e84h ; 74 10 ; 0xc3e72 + lea di, [bx+00ch] ; 8d 7f 0c ; 0xc3e74 vbe.c:429 + mov word [es:di], 00629h ; 26 c7 05 29 06 ; 0xc3e77 vbe.c:62 + lea di, [bx+00eh] ; 8d 7f 0e ; 0xc3e7c vbe.c:431 + mov word [es:di], 0c000h ; 26 c7 05 00 c0 ; 0xc3e7f vbe.c:62 + mov ax, strict word 0000bh ; b8 0b 00 ; 0xc3e84 vbe.c:434 + mov dx, 001ceh ; ba ce 01 ; 0xc3e87 + call 00570h ; e8 e3 c6 ; 0xc3e8a + mov dx, 001cfh ; ba cf 01 ; 0xc3e8d vbe.c:435 + call 00577h ; e8 e4 c6 ; 0xc3e90 + add bx, strict byte 0002ah ; 83 c3 2a ; 0xc3e93 + mov es, si ; 8e c6 ; 0xc3e96 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3e98 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc3e9b vbe.c:437 + jmp short 03ea3h ; eb 03 ; 0xc3e9e vbe.c:438 + mov ax, 00100h ; b8 00 01 ; 0xc3ea0 vbe.c:442 + push SS ; 16 ; 0xc3ea3 vbe.c:445 + pop ES ; 07 ; 0xc3ea4 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc3ea5 + mov word [es:bx], ax ; 26 89 07 ; 0xc3ea8 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3eab vbe.c:446 + pop di ; 5f ; 0xc3eae + pop si ; 5e ; 0xc3eaf + pop bp ; 5d ; 0xc3eb0 + retn ; c3 ; 0xc3eb1 + ; disGetNextSymbol 0xc3eb2 LB 0x407 -> off=0x0 cb=00000000000000e5 uValue=00000000000c3eb2 'vbe_biosfn_set_mode' +vbe_biosfn_set_mode: ; 0xc3eb2 LB 0xe5 + push bp ; 55 ; 0xc3eb2 vbe.c:458 + mov bp, sp ; 89 e5 ; 0xc3eb3 + push si ; 56 ; 0xc3eb5 + push di ; 57 ; 0xc3eb6 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc3eb7 + mov si, ax ; 89 c6 ; 0xc3eba + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc3ebc + test byte [bp-009h], 040h ; f6 46 f7 40 ; 0xc3ebf vbe.c:466 + db 00fh, 095h, 0c0h + ; setne al ; 0f 95 c0 ; 0xc3ec3 + movzx dx, al ; 0f b6 d0 ; 0xc3ec6 + mov ax, dx ; 89 d0 ; 0xc3ec9 + test dx, dx ; 85 d2 ; 0xc3ecb vbe.c:467 + je short 03ed2h ; 74 03 ; 0xc3ecd + mov dx, strict word 00040h ; ba 40 00 ; 0xc3ecf + mov byte [bp-008h], dl ; 88 56 f8 ; 0xc3ed2 + test byte [bp-009h], 080h ; f6 46 f7 80 ; 0xc3ed5 vbe.c:468 + je short 03ee0h ; 74 05 ; 0xc3ed9 + mov dx, 00080h ; ba 80 00 ; 0xc3edb + jmp short 03ee2h ; eb 02 ; 0xc3ede + xor dx, dx ; 31 d2 ; 0xc3ee0 + mov byte [bp-006h], dl ; 88 56 fa ; 0xc3ee2 + and byte [bp-009h], 001h ; 80 66 f7 01 ; 0xc3ee5 vbe.c:470 + cmp word [bp-00ah], 00100h ; 81 7e f6 00 01 ; 0xc3ee9 vbe.c:473 + jnc short 03f02h ; 73 12 ; 0xc3eee + xor ax, ax ; 31 c0 ; 0xc3ef0 vbe.c:477 + call 005ddh ; e8 e8 c6 ; 0xc3ef2 + movzx ax, byte [bp-00ah] ; 0f b6 46 f6 ; 0xc3ef5 vbe.c:481 + call 013ddh ; e8 e1 d4 ; 0xc3ef9 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc3efc vbe.c:482 + jmp near 03f8bh ; e9 89 00 ; 0xc3eff vbe.c:483 + mov dx, ax ; 89 c2 ; 0xc3f02 vbe.c:486 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3f04 + call 03c86h ; e8 7c fd ; 0xc3f07 + mov bx, ax ; 89 c3 ; 0xc3f0a + test ax, ax ; 85 c0 ; 0xc3f0c vbe.c:488 + je short 03f88h ; 74 78 ; 0xc3f0e + lea dx, [bx+014h] ; 8d 57 14 ; 0xc3f10 vbe.c:493 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f13 + call 03c08h ; e8 ef fc ; 0xc3f16 + mov cx, ax ; 89 c1 ; 0xc3f19 + lea dx, [bx+016h] ; 8d 57 16 ; 0xc3f1b vbe.c:494 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f1e + call 03c08h ; e8 e4 fc ; 0xc3f21 + mov di, ax ; 89 c7 ; 0xc3f24 + lea dx, [bx+01bh] ; 8d 57 1b ; 0xc3f26 vbe.c:495 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f29 + call 03c1ah ; e8 eb fc ; 0xc3f2c + mov bl, al ; 88 c3 ; 0xc3f2f + mov dl, al ; 88 c2 ; 0xc3f31 + xor ax, ax ; 31 c0 ; 0xc3f33 vbe.c:503 + call 005ddh ; e8 a5 c6 ; 0xc3f35 + cmp bl, 004h ; 80 fb 04 ; 0xc3f38 vbe.c:505 + jne short 03f43h ; 75 06 ; 0xc3f3b + mov ax, strict word 0006ah ; b8 6a 00 ; 0xc3f3d vbe.c:507 + call 013ddh ; e8 9a d4 ; 0xc3f40 + movzx ax, dl ; 0f b6 c2 ; 0xc3f43 vbe.c:510 + call 03b7fh ; e8 36 fc ; 0xc3f46 + mov ax, cx ; 89 c8 ; 0xc3f49 vbe.c:511 + call 03b28h ; e8 da fb ; 0xc3f4b + mov ax, di ; 89 f8 ; 0xc3f4e vbe.c:512 + call 03b47h ; e8 f4 fb ; 0xc3f50 + xor ax, ax ; 31 c0 ; 0xc3f53 vbe.c:513 + call 00603h ; e8 ab c6 ; 0xc3f55 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc3f58 vbe.c:514 + or AL, strict byte 001h ; 0c 01 ; 0xc3f5b + movzx dx, al ; 0f b6 d0 ; 0xc3f5d + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc3f60 + or ax, dx ; 09 d0 ; 0xc3f64 + call 005ddh ; e8 74 c6 ; 0xc3f66 + call 006d2h ; e8 66 c7 ; 0xc3f69 vbe.c:515 + mov bx, 000bah ; bb ba 00 ; 0xc3f6c vbe.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3f6f + mov es, ax ; 8e c0 ; 0xc3f72 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3f74 + mov word [es:bx], ax ; 26 89 07 ; 0xc3f77 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc3f7a vbe.c:518 + or AL, strict byte 060h ; 0c 60 ; 0xc3f7d + mov bx, 00087h ; bb 87 00 ; 0xc3f7f vbe.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3f82 + jmp near 03efch ; e9 74 ff ; 0xc3f85 + mov ax, 00100h ; b8 00 01 ; 0xc3f88 vbe.c:527 + push SS ; 16 ; 0xc3f8b vbe.c:531 + pop ES ; 07 ; 0xc3f8c + mov word [es:si], ax ; 26 89 04 ; 0xc3f8d + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3f90 vbe.c:532 + pop di ; 5f ; 0xc3f93 + pop si ; 5e ; 0xc3f94 + pop bp ; 5d ; 0xc3f95 + retn ; c3 ; 0xc3f96 + ; disGetNextSymbol 0xc3f97 LB 0x322 -> off=0x0 cb=0000000000000008 uValue=00000000000c3f97 'vbe_biosfn_read_video_state_size' +vbe_biosfn_read_video_state_size: ; 0xc3f97 LB 0x8 + push bp ; 55 ; 0xc3f97 vbe.c:534 + mov bp, sp ; 89 e5 ; 0xc3f98 + mov ax, strict word 00012h ; b8 12 00 ; 0xc3f9a vbe.c:537 + pop bp ; 5d ; 0xc3f9d + retn ; c3 ; 0xc3f9e + ; disGetNextSymbol 0xc3f9f LB 0x31a -> off=0x0 cb=000000000000004b uValue=00000000000c3f9f 'vbe_biosfn_save_video_state' +vbe_biosfn_save_video_state: ; 0xc3f9f LB 0x4b + push bp ; 55 ; 0xc3f9f vbe.c:539 + mov bp, sp ; 89 e5 ; 0xc3fa0 + push bx ; 53 ; 0xc3fa2 + push cx ; 51 ; 0xc3fa3 + push si ; 56 ; 0xc3fa4 + mov si, ax ; 89 c6 ; 0xc3fa5 + mov bx, dx ; 89 d3 ; 0xc3fa7 + mov ax, strict word 00004h ; b8 04 00 ; 0xc3fa9 vbe.c:543 + mov dx, 001ceh ; ba ce 01 ; 0xc3fac + out DX, ax ; ef ; 0xc3faf + mov dx, 001cfh ; ba cf 01 ; 0xc3fb0 vbe.c:544 + in ax, DX ; ed ; 0xc3fb3 + mov es, si ; 8e c6 ; 0xc3fb4 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3fb6 + inc bx ; 43 ; 0xc3fb9 vbe.c:546 + inc bx ; 43 ; 0xc3fba + test AL, strict byte 001h ; a8 01 ; 0xc3fbb vbe.c:547 + je short 03fe2h ; 74 23 ; 0xc3fbd + mov cx, strict word 00001h ; b9 01 00 ; 0xc3fbf vbe.c:549 + jmp short 03fc9h ; eb 05 ; 0xc3fc2 + cmp cx, strict byte 00009h ; 83 f9 09 ; 0xc3fc4 + jnbe short 03fe2h ; 77 19 ; 0xc3fc7 + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc3fc9 vbe.c:550 + je short 03fdfh ; 74 11 ; 0xc3fcc + mov ax, cx ; 89 c8 ; 0xc3fce vbe.c:551 + mov dx, 001ceh ; ba ce 01 ; 0xc3fd0 + out DX, ax ; ef ; 0xc3fd3 + mov dx, 001cfh ; ba cf 01 ; 0xc3fd4 vbe.c:552 + in ax, DX ; ed ; 0xc3fd7 + mov es, si ; 8e c6 ; 0xc3fd8 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3fda + inc bx ; 43 ; 0xc3fdd vbe.c:553 + inc bx ; 43 ; 0xc3fde + inc cx ; 41 ; 0xc3fdf vbe.c:555 + jmp short 03fc4h ; eb e2 ; 0xc3fe0 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc3fe2 vbe.c:556 + pop si ; 5e ; 0xc3fe5 + pop cx ; 59 ; 0xc3fe6 + pop bx ; 5b ; 0xc3fe7 + pop bp ; 5d ; 0xc3fe8 + retn ; c3 ; 0xc3fe9 + ; disGetNextSymbol 0xc3fea LB 0x2cf -> off=0x0 cb=000000000000008f uValue=00000000000c3fea 'vbe_biosfn_restore_video_state' +vbe_biosfn_restore_video_state: ; 0xc3fea LB 0x8f + push bp ; 55 ; 0xc3fea vbe.c:559 + mov bp, sp ; 89 e5 ; 0xc3feb + push bx ; 53 ; 0xc3fed + push cx ; 51 ; 0xc3fee + push si ; 56 ; 0xc3fef + push ax ; 50 ; 0xc3ff0 + mov cx, ax ; 89 c1 ; 0xc3ff1 + mov bx, dx ; 89 d3 ; 0xc3ff3 + mov es, ax ; 8e c0 ; 0xc3ff5 vbe.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3ff7 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc3ffa + inc bx ; 43 ; 0xc3ffd vbe.c:564 + inc bx ; 43 ; 0xc3ffe + test byte [bp-008h], 001h ; f6 46 f8 01 ; 0xc3fff vbe.c:566 + jne short 04015h ; 75 10 ; 0xc4003 + mov ax, strict word 00004h ; b8 04 00 ; 0xc4005 vbe.c:567 + mov dx, 001ceh ; ba ce 01 ; 0xc4008 + out DX, ax ; ef ; 0xc400b + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc400c vbe.c:568 + mov dx, 001cfh ; ba cf 01 ; 0xc400f + out DX, ax ; ef ; 0xc4012 + jmp short 04071h ; eb 5c ; 0xc4013 vbe.c:569 + mov ax, strict word 00001h ; b8 01 00 ; 0xc4015 vbe.c:570 + mov dx, 001ceh ; ba ce 01 ; 0xc4018 + out DX, ax ; ef ; 0xc401b + mov ax, word [es:bx] ; 26 8b 07 ; 0xc401c vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc401f vbe.c:58 + out DX, ax ; ef ; 0xc4022 + inc bx ; 43 ; 0xc4023 vbe.c:572 + inc bx ; 43 ; 0xc4024 + mov ax, strict word 00002h ; b8 02 00 ; 0xc4025 + mov dx, 001ceh ; ba ce 01 ; 0xc4028 + out DX, ax ; ef ; 0xc402b + mov ax, word [es:bx] ; 26 8b 07 ; 0xc402c vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc402f vbe.c:58 + out DX, ax ; ef ; 0xc4032 + inc bx ; 43 ; 0xc4033 vbe.c:575 + inc bx ; 43 ; 0xc4034 + mov ax, strict word 00003h ; b8 03 00 ; 0xc4035 + mov dx, 001ceh ; ba ce 01 ; 0xc4038 + out DX, ax ; ef ; 0xc403b + mov ax, word [es:bx] ; 26 8b 07 ; 0xc403c vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc403f vbe.c:58 + out DX, ax ; ef ; 0xc4042 + inc bx ; 43 ; 0xc4043 vbe.c:578 + inc bx ; 43 ; 0xc4044 + mov ax, strict word 00004h ; b8 04 00 ; 0xc4045 + mov dx, 001ceh ; ba ce 01 ; 0xc4048 + out DX, ax ; ef ; 0xc404b + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc404c vbe.c:580 + mov dx, 001cfh ; ba cf 01 ; 0xc404f + out DX, ax ; ef ; 0xc4052 + mov si, strict word 00005h ; be 05 00 ; 0xc4053 vbe.c:582 + jmp short 0405dh ; eb 05 ; 0xc4056 + cmp si, strict byte 00009h ; 83 fe 09 ; 0xc4058 + jnbe short 04071h ; 77 14 ; 0xc405b + mov ax, si ; 89 f0 ; 0xc405d vbe.c:583 + mov dx, 001ceh ; ba ce 01 ; 0xc405f + out DX, ax ; ef ; 0xc4062 + mov es, cx ; 8e c1 ; 0xc4063 vbe.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc4065 + mov dx, 001cfh ; ba cf 01 ; 0xc4068 vbe.c:58 + out DX, ax ; ef ; 0xc406b + inc bx ; 43 ; 0xc406c vbe.c:585 + inc bx ; 43 ; 0xc406d + inc si ; 46 ; 0xc406e vbe.c:586 + jmp short 04058h ; eb e7 ; 0xc406f + lea sp, [bp-006h] ; 8d 66 fa ; 0xc4071 vbe.c:588 + pop si ; 5e ; 0xc4074 + pop cx ; 59 ; 0xc4075 + pop bx ; 5b ; 0xc4076 + pop bp ; 5d ; 0xc4077 + retn ; c3 ; 0xc4078 + ; disGetNextSymbol 0xc4079 LB 0x240 -> off=0x0 cb=000000000000008c uValue=00000000000c4079 'vbe_biosfn_save_restore_state' +vbe_biosfn_save_restore_state: ; 0xc4079 LB 0x8c + push bp ; 55 ; 0xc4079 vbe.c:604 + mov bp, sp ; 89 e5 ; 0xc407a + push si ; 56 ; 0xc407c + push di ; 57 ; 0xc407d + push ax ; 50 ; 0xc407e + mov si, ax ; 89 c6 ; 0xc407f + mov word [bp-006h], dx ; 89 56 fa ; 0xc4081 + mov ax, bx ; 89 d8 ; 0xc4084 + mov bx, word [bp+004h] ; 8b 5e 04 ; 0xc4086 + mov di, strict word 0004fh ; bf 4f 00 ; 0xc4089 vbe.c:609 + xor ah, ah ; 30 e4 ; 0xc408c vbe.c:610 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc408e + je short 040d8h ; 74 45 ; 0xc4091 + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc4093 + je short 040bch ; 74 24 ; 0xc4096 + test ax, ax ; 85 c0 ; 0xc4098 + jne short 040f4h ; 75 58 ; 0xc409a + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc409c vbe.c:612 + call 03024h ; e8 82 ef ; 0xc409f + mov cx, ax ; 89 c1 ; 0xc40a2 + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc40a4 vbe.c:616 + je short 040afh ; 74 05 ; 0xc40a8 + call 03f97h ; e8 ea fe ; 0xc40aa vbe.c:617 + add ax, cx ; 01 c8 ; 0xc40ad + add ax, strict word 0003fh ; 05 3f 00 ; 0xc40af vbe.c:618 + shr ax, 006h ; c1 e8 06 ; 0xc40b2 + push SS ; 16 ; 0xc40b5 + pop ES ; 07 ; 0xc40b6 + mov word [es:bx], ax ; 26 89 07 ; 0xc40b7 + jmp short 040f7h ; eb 3b ; 0xc40ba vbe.c:619 + push SS ; 16 ; 0xc40bc vbe.c:621 + pop ES ; 07 ; 0xc40bd + mov bx, word [es:bx] ; 26 8b 1f ; 0xc40be + mov dx, cx ; 89 ca ; 0xc40c1 vbe.c:622 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc40c3 + call 0305fh ; e8 96 ef ; 0xc40c6 + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc40c9 vbe.c:626 + je short 040f7h ; 74 28 ; 0xc40cd + mov dx, ax ; 89 c2 ; 0xc40cf vbe.c:627 + mov ax, cx ; 89 c8 ; 0xc40d1 + call 03f9fh ; e8 c9 fe ; 0xc40d3 + jmp short 040f7h ; eb 1f ; 0xc40d6 vbe.c:628 + push SS ; 16 ; 0xc40d8 vbe.c:630 + pop ES ; 07 ; 0xc40d9 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc40da + mov dx, cx ; 89 ca ; 0xc40dd vbe.c:631 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc40df + call 03335h ; e8 50 f2 ; 0xc40e2 + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc40e5 vbe.c:635 + je short 040f7h ; 74 0c ; 0xc40e9 + mov dx, ax ; 89 c2 ; 0xc40eb vbe.c:636 + mov ax, cx ; 89 c8 ; 0xc40ed + call 03feah ; e8 f8 fe ; 0xc40ef + jmp short 040f7h ; eb 03 ; 0xc40f2 vbe.c:637 + mov di, 00100h ; bf 00 01 ; 0xc40f4 vbe.c:640 + push SS ; 16 ; 0xc40f7 vbe.c:643 + pop ES ; 07 ; 0xc40f8 + mov word [es:si], di ; 26 89 3c ; 0xc40f9 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc40fc vbe.c:644 + pop di ; 5f ; 0xc40ff + pop si ; 5e ; 0xc4100 + pop bp ; 5d ; 0xc4101 + retn 00002h ; c2 02 00 ; 0xc4102 + ; disGetNextSymbol 0xc4105 LB 0x1b4 -> off=0x0 cb=00000000000000cf uValue=00000000000c4105 'vbe_biosfn_get_set_scanline_length' +vbe_biosfn_get_set_scanline_length: ; 0xc4105 LB 0xcf + push bp ; 55 ; 0xc4105 vbe.c:665 + mov bp, sp ; 89 e5 ; 0xc4106 + push si ; 56 ; 0xc4108 + push di ; 57 ; 0xc4109 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc410a + push ax ; 50 ; 0xc410d + mov di, dx ; 89 d7 ; 0xc410e + mov si, bx ; 89 de ; 0xc4110 + mov word [bp-008h], cx ; 89 4e f8 ; 0xc4112 + call 03b9eh ; e8 86 fa ; 0xc4115 vbe.c:674 + cmp AL, strict byte 00fh ; 3c 0f ; 0xc4118 vbe.c:675 + jne short 04121h ; 75 05 ; 0xc411a + mov cx, strict word 00010h ; b9 10 00 ; 0xc411c + jmp short 04124h ; eb 03 ; 0xc411f + movzx cx, al ; 0f b6 c8 ; 0xc4121 + call 03bd6h ; e8 af fa ; 0xc4124 vbe.c:676 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc4127 + mov word [bp-006h], strict word 0004fh ; c7 46 fa 4f 00 ; 0xc412a vbe.c:677 + push SS ; 16 ; 0xc412f vbe.c:678 + pop ES ; 07 ; 0xc4130 + mov bx, word [es:si] ; 26 8b 1c ; 0xc4131 + mov al, byte [es:di] ; 26 8a 05 ; 0xc4134 vbe.c:679 + cmp AL, strict byte 002h ; 3c 02 ; 0xc4137 vbe.c:683 + je short 04146h ; 74 0b ; 0xc4139 + cmp AL, strict byte 001h ; 3c 01 ; 0xc413b + je short 0416dh ; 74 2e ; 0xc413d + test al, al ; 84 c0 ; 0xc413f + je short 04168h ; 74 25 ; 0xc4141 + jmp near 041bdh ; e9 77 00 ; 0xc4143 + cmp cl, 004h ; 80 f9 04 ; 0xc4146 vbe.c:685 + jne short 04150h ; 75 05 ; 0xc4149 + sal bx, 003h ; c1 e3 03 ; 0xc414b vbe.c:686 + jmp short 04168h ; eb 18 ; 0xc414e vbe.c:687 + movzx ax, cl ; 0f b6 c1 ; 0xc4150 vbe.c:688 + cwd ; 99 ; 0xc4153 + sal dx, 003h ; c1 e2 03 ; 0xc4154 + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc4157 + sar ax, 003h ; c1 f8 03 ; 0xc4159 + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc415c + mov ax, bx ; 89 d8 ; 0xc415f + xor dx, dx ; 31 d2 ; 0xc4161 + div word [bp-00ch] ; f7 76 f4 ; 0xc4163 + mov bx, ax ; 89 c3 ; 0xc4166 + mov ax, bx ; 89 d8 ; 0xc4168 vbe.c:691 + call 03bb7h ; e8 4a fa ; 0xc416a + call 03bd6h ; e8 66 fa ; 0xc416d vbe.c:694 + mov bx, ax ; 89 c3 ; 0xc4170 + push SS ; 16 ; 0xc4172 vbe.c:695 + pop ES ; 07 ; 0xc4173 + mov word [es:si], ax ; 26 89 04 ; 0xc4174 + cmp cl, 004h ; 80 f9 04 ; 0xc4177 vbe.c:696 + jne short 04181h ; 75 05 ; 0xc417a + shr bx, 003h ; c1 eb 03 ; 0xc417c vbe.c:697 + jmp short 04190h ; eb 0f ; 0xc417f vbe.c:698 + movzx ax, cl ; 0f b6 c1 ; 0xc4181 vbe.c:699 + cwd ; 99 ; 0xc4184 + sal dx, 003h ; c1 e2 03 ; 0xc4185 + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc4188 + sar ax, 003h ; c1 f8 03 ; 0xc418a + imul bx, ax ; 0f af d8 ; 0xc418d + add bx, strict byte 00003h ; 83 c3 03 ; 0xc4190 vbe.c:700 + and bl, 0fch ; 80 e3 fc ; 0xc4193 + push SS ; 16 ; 0xc4196 vbe.c:701 + pop ES ; 07 ; 0xc4197 + mov word [es:di], bx ; 26 89 1d ; 0xc4198 + call 03befh ; e8 51 fa ; 0xc419b vbe.c:702 + push SS ; 16 ; 0xc419e + pop ES ; 07 ; 0xc419f + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc41a0 + mov word [es:bx], ax ; 26 89 07 ; 0xc41a3 + call 03b66h ; e8 bd f9 ; 0xc41a6 vbe.c:703 + push SS ; 16 ; 0xc41a9 + pop ES ; 07 ; 0xc41aa + cmp ax, word [es:bx] ; 26 3b 07 ; 0xc41ab + jbe short 041c2h ; 76 12 ; 0xc41ae + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc41b0 vbe.c:704 + call 03bb7h ; e8 01 fa ; 0xc41b3 + mov word [bp-006h], 00200h ; c7 46 fa 00 02 ; 0xc41b6 vbe.c:705 + jmp short 041c2h ; eb 05 ; 0xc41bb vbe.c:707 + mov word [bp-006h], 00100h ; c7 46 fa 00 01 ; 0xc41bd vbe.c:710 + push SS ; 16 ; 0xc41c2 vbe.c:713 + pop ES ; 07 ; 0xc41c3 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc41c4 + mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xc41c7 + mov word [es:bx], ax ; 26 89 07 ; 0xc41ca + lea sp, [bp-004h] ; 8d 66 fc ; 0xc41cd vbe.c:714 + pop di ; 5f ; 0xc41d0 + pop si ; 5e ; 0xc41d1 + pop bp ; 5d ; 0xc41d2 + retn ; c3 ; 0xc41d3 + ; disGetNextSymbol 0xc41d4 LB 0xe5 -> off=0x0 cb=00000000000000e5 uValue=00000000000c41d4 'private_biosfn_custom_mode' +private_biosfn_custom_mode: ; 0xc41d4 LB 0xe5 + push bp ; 55 ; 0xc41d4 vbe.c:740 + mov bp, sp ; 89 e5 ; 0xc41d5 + push si ; 56 ; 0xc41d7 + push di ; 57 ; 0xc41d8 + push ax ; 50 ; 0xc41d9 + push ax ; 50 ; 0xc41da + push ax ; 50 ; 0xc41db + mov si, dx ; 89 d6 ; 0xc41dc + mov dx, cx ; 89 ca ; 0xc41de + mov di, strict word 0004fh ; bf 4f 00 ; 0xc41e0 vbe.c:753 + push SS ; 16 ; 0xc41e3 vbe.c:754 + pop ES ; 07 ; 0xc41e4 + mov al, byte [es:si] ; 26 8a 04 ; 0xc41e5 + test al, al ; 84 c0 ; 0xc41e8 vbe.c:755 + jne short 0420eh ; 75 22 ; 0xc41ea + push SS ; 16 ; 0xc41ec vbe.c:757 + pop ES ; 07 ; 0xc41ed + mov cx, word [es:bx] ; 26 8b 0f ; 0xc41ee + mov bx, dx ; 89 d3 ; 0xc41f1 vbe.c:758 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc41f3 + mov ax, word [es:si] ; 26 8b 04 ; 0xc41f6 vbe.c:759 + shr ax, 008h ; c1 e8 08 ; 0xc41f9 + and ax, strict word 0007fh ; 25 7f 00 ; 0xc41fc + mov byte [bp-008h], al ; 88 46 f8 ; 0xc41ff + cmp AL, strict byte 008h ; 3c 08 ; 0xc4202 vbe.c:764 + je short 04214h ; 74 0e ; 0xc4204 + cmp AL, strict byte 010h ; 3c 10 ; 0xc4206 + je short 04214h ; 74 0a ; 0xc4208 + cmp AL, strict byte 020h ; 3c 20 ; 0xc420a + je short 04214h ; 74 06 ; 0xc420c + mov di, 00100h ; bf 00 01 ; 0xc420e vbe.c:765 + jmp near 042aah ; e9 96 00 ; 0xc4211 vbe.c:766 + push SS ; 16 ; 0xc4214 vbe.c:770 + pop ES ; 07 ; 0xc4215 + test byte [es:si+001h], 080h ; 26 f6 44 01 80 ; 0xc4216 + je short 04222h ; 74 05 ; 0xc421b + mov ax, strict word 00040h ; b8 40 00 ; 0xc421d + jmp short 04224h ; eb 02 ; 0xc4220 + xor ax, ax ; 31 c0 ; 0xc4222 + mov byte [bp-006h], al ; 88 46 fa ; 0xc4224 + cmp cx, 00280h ; 81 f9 80 02 ; 0xc4227 vbe.c:773 + jnc short 04232h ; 73 05 ; 0xc422b + mov cx, 00280h ; b9 80 02 ; 0xc422d vbe.c:774 + jmp short 0423bh ; eb 09 ; 0xc4230 vbe.c:775 + cmp cx, 00a00h ; 81 f9 00 0a ; 0xc4232 + jbe short 0423bh ; 76 03 ; 0xc4236 + mov cx, 00a00h ; b9 00 0a ; 0xc4238 vbe.c:776 + cmp bx, 001e0h ; 81 fb e0 01 ; 0xc423b vbe.c:777 + jnc short 04246h ; 73 05 ; 0xc423f + mov bx, 001e0h ; bb e0 01 ; 0xc4241 vbe.c:778 + jmp short 0424fh ; eb 09 ; 0xc4244 vbe.c:779 + cmp bx, 00780h ; 81 fb 80 07 ; 0xc4246 + jbe short 0424fh ; 76 03 ; 0xc424a + mov bx, 00780h ; bb 80 07 ; 0xc424c vbe.c:780 + mov dx, strict word 0ffffh ; ba ff ff ; 0xc424f vbe.c:786 + mov ax, 003b6h ; b8 b6 03 ; 0xc4252 + call 03c08h ; e8 b0 f9 ; 0xc4255 + mov si, ax ; 89 c6 ; 0xc4258 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc425a vbe.c:789 + cwd ; 99 ; 0xc425e + sal dx, 003h ; c1 e2 03 ; 0xc425f + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc4262 + sar ax, 003h ; c1 f8 03 ; 0xc4264 + imul ax, cx ; 0f af c1 ; 0xc4267 + add ax, strict word 00003h ; 05 03 00 ; 0xc426a vbe.c:790 + and AL, strict byte 0fch ; 24 fc ; 0xc426d + mov dx, bx ; 89 da ; 0xc426f vbe.c:792 + mul dx ; f7 e2 ; 0xc4271 + cmp dx, si ; 39 f2 ; 0xc4273 vbe.c:794 + jnbe short 0427dh ; 77 06 ; 0xc4275 + jne short 04282h ; 75 09 ; 0xc4277 + test ax, ax ; 85 c0 ; 0xc4279 + jbe short 04282h ; 76 05 ; 0xc427b + mov di, 00200h ; bf 00 02 ; 0xc427d vbe.c:796 + jmp short 042aah ; eb 28 ; 0xc4280 vbe.c:797 + xor ax, ax ; 31 c0 ; 0xc4282 vbe.c:801 + call 005ddh ; e8 56 c3 ; 0xc4284 + movzx ax, byte [bp-008h] ; 0f b6 46 f8 ; 0xc4287 vbe.c:802 + call 03b7fh ; e8 f1 f8 ; 0xc428b + mov ax, cx ; 89 c8 ; 0xc428e vbe.c:803 + call 03b28h ; e8 95 f8 ; 0xc4290 + mov ax, bx ; 89 d8 ; 0xc4293 vbe.c:804 + call 03b47h ; e8 af f8 ; 0xc4295 + xor ax, ax ; 31 c0 ; 0xc4298 vbe.c:805 + call 00603h ; e8 66 c3 ; 0xc429a + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc429d vbe.c:806 + or AL, strict byte 001h ; 0c 01 ; 0xc42a0 + xor ah, ah ; 30 e4 ; 0xc42a2 + call 005ddh ; e8 36 c3 ; 0xc42a4 + call 006d2h ; e8 28 c4 ; 0xc42a7 vbe.c:807 + push SS ; 16 ; 0xc42aa vbe.c:815 + pop ES ; 07 ; 0xc42ab + mov bx, word [bp-00ah] ; 8b 5e f6 ; 0xc42ac + mov word [es:bx], di ; 26 89 3f ; 0xc42af + lea sp, [bp-004h] ; 8d 66 fc ; 0xc42b2 vbe.c:816 + pop di ; 5f ; 0xc42b5 + pop si ; 5e ; 0xc42b6 + pop bp ; 5d ; 0xc42b7 + retn ; c3 ; 0xc42b8 + + ; Padding 0x387 bytes at 0xc42b9 + times 903 db 0 + +section VBE32 progbits vstart=0x4640 align=1 ; size=0x115 class=CODE group=AUTO + ; disGetNextSymbol 0xc4640 LB 0x115 -> off=0x0 cb=0000000000000114 uValue=00000000000c0000 'vesa_pm_start' +vesa_pm_start: ; 0xc4640 LB 0x114 + sbb byte [bx+si], al ; 18 00 ; 0xc4640 + dec di ; 4f ; 0xc4642 + add byte [bx+si], dl ; 00 10 ; 0xc4643 + add word [bx+si], cx ; 01 08 ; 0xc4645 + add dh, cl ; 00 ce ; 0xc4647 + add di, cx ; 01 cf ; 0xc4649 + add di, cx ; 01 cf ; 0xc464b + add ax, dx ; 01 d0 ; 0xc464d + add word [bp-048fdh], si ; 01 b6 03 b7 ; 0xc464f + db 003h, 0ffh + ; add di, di ; 03 ff ; 0xc4653 + db 0ffh + db 0ffh + jmp word [bp-07dh] ; ff 66 83 ; 0xc4657 + sti ; fb ; 0xc465a + add byte [si+005h], dh ; 00 74 05 ; 0xc465b + mov eax, strict dword 066c30100h ; 66 b8 00 01 c3 66 ; 0xc465e vberom.asm:825 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc4664 + push edx ; 66 52 ; 0xc4666 vberom.asm:829 + push eax ; 66 50 ; 0xc4668 vberom.asm:830 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc466a vberom.asm:831 + add ax, 06600h ; 05 00 66 ; 0xc4670 + out DX, ax ; ef ; 0xc4673 + pop eax ; 66 58 ; 0xc4674 vberom.asm:834 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc4676 vberom.asm:835 + in eax, DX ; 66 ed ; 0xc467c vberom.asm:837 + pop edx ; 66 5a ; 0xc467e vberom.asm:838 + db 066h, 03bh, 0d0h + ; cmp edx, eax ; 66 3b d0 ; 0xc4680 vberom.asm:839 + jne short 0468ah ; 75 05 ; 0xc4683 vberom.asm:840 + mov eax, strict dword 066c3004fh ; 66 b8 4f 00 c3 66 ; 0xc4685 vberom.asm:841 + mov ax, 0014fh ; b8 4f 01 ; 0xc468b + retn ; c3 ; 0xc468e vberom.asm:845 + cmp bl, 080h ; 80 fb 80 ; 0xc468f vberom.asm:847 + je short 0469eh ; 74 0a ; 0xc4692 vberom.asm:848 + cmp bl, 000h ; 80 fb 00 ; 0xc4694 vberom.asm:849 + je short 046aeh ; 74 15 ; 0xc4697 vberom.asm:850 + mov eax, strict dword 052c30100h ; 66 b8 00 01 c3 52 ; 0xc4699 vberom.asm:851 + mov edx, strict dword 0a8ec03dah ; 66 ba da 03 ec a8 ; 0xc469f vberom.asm:855 + or byte [di-005h], dh ; 08 75 fb ; 0xc46a5 + in AL, DX ; ec ; 0xc46a8 vberom.asm:861 + test AL, strict byte 008h ; a8 08 ; 0xc46a9 vberom.asm:862 + je short 046a8h ; 74 fb ; 0xc46ab vberom.asm:863 + pop dx ; 5a ; 0xc46ad vberom.asm:864 + push ax ; 50 ; 0xc46ae vberom.asm:868 + push cx ; 51 ; 0xc46af vberom.asm:869 + push dx ; 52 ; 0xc46b0 vberom.asm:870 + push si ; 56 ; 0xc46b1 vberom.asm:871 + push di ; 57 ; 0xc46b2 vberom.asm:872 + sal dx, 010h ; c1 e2 10 ; 0xc46b3 vberom.asm:873 + and cx, strict word 0ffffh ; 81 e1 ff ff ; 0xc46b6 vberom.asm:874 + add byte [bx+si], al ; 00 00 ; 0xc46ba + db 00bh, 0cah + ; or cx, dx ; 0b ca ; 0xc46bc vberom.asm:875 + sal cx, 002h ; c1 e1 02 ; 0xc46be vberom.asm:876 + db 08bh, 0c1h + ; mov ax, cx ; 8b c1 ; 0xc46c1 vberom.asm:877 + push ax ; 50 ; 0xc46c3 vberom.asm:878 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc46c4 vberom.asm:879 + push ES ; 06 ; 0xc46ca + add byte [bp-011h], ah ; 00 66 ef ; 0xc46cb + mov edx, strict dword 0ed6601cfh ; 66 ba cf 01 66 ed ; 0xc46ce vberom.asm:882 + db 00fh, 0b7h, 0c8h + ; movzx cx, ax ; 0f b7 c8 ; 0xc46d4 vberom.asm:884 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc46d7 vberom.asm:885 + add ax, word [bx+si] ; 03 00 ; 0xc46dd + out DX, eax ; 66 ef ; 0xc46df vberom.asm:887 + mov edx, strict dword 0ed6601cfh ; 66 ba cf 01 66 ed ; 0xc46e1 vberom.asm:888 + db 00fh, 0b7h, 0f0h + ; movzx si, ax ; 0f b7 f0 ; 0xc46e7 vberom.asm:890 + pop ax ; 58 ; 0xc46ea vberom.asm:891 + cmp si, strict byte 00004h ; 83 fe 04 ; 0xc46eb vberom.asm:893 + je short 04707h ; 74 17 ; 0xc46ee vberom.asm:894 + add si, strict byte 00007h ; 83 c6 07 ; 0xc46f0 vberom.asm:895 + shr si, 003h ; c1 ee 03 ; 0xc46f3 vberom.asm:896 + imul cx, si ; 0f af ce ; 0xc46f6 vberom.asm:897 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc46f9 vberom.asm:898 + div cx ; f7 f1 ; 0xc46fb vberom.asm:899 + db 08bh, 0f8h + ; mov di, ax ; 8b f8 ; 0xc46fd vberom.asm:900 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc46ff vberom.asm:901 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc4701 vberom.asm:902 + div si ; f7 f6 ; 0xc4703 vberom.asm:903 + jmp short 04713h ; eb 0c ; 0xc4705 vberom.asm:904 + shr cx, 1 ; d1 e9 ; 0xc4707 vberom.asm:907 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc4709 vberom.asm:908 + div cx ; f7 f1 ; 0xc470b vberom.asm:909 + db 08bh, 0f8h + ; mov di, ax ; 8b f8 ; 0xc470d vberom.asm:910 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc470f vberom.asm:911 + sal ax, 1 ; d1 e0 ; 0xc4711 vberom.asm:912 + push edx ; 66 52 ; 0xc4713 vberom.asm:915 + push eax ; 66 50 ; 0xc4715 vberom.asm:916 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc4717 vberom.asm:917 + or byte [bx+si], al ; 08 00 ; 0xc471d + out DX, eax ; 66 ef ; 0xc471f vberom.asm:919 + pop eax ; 66 58 ; 0xc4721 vberom.asm:920 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc4723 vberom.asm:921 + pop edx ; 66 5a ; 0xc4729 vberom.asm:923 + db 066h, 08bh, 0c7h + ; mov eax, edi ; 66 8b c7 ; 0xc472b vberom.asm:925 + push edx ; 66 52 ; 0xc472e vberom.asm:926 + push eax ; 66 50 ; 0xc4730 vberom.asm:927 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc4732 vberom.asm:928 + or word [bx+si], ax ; 09 00 ; 0xc4738 + out DX, eax ; 66 ef ; 0xc473a vberom.asm:930 + pop eax ; 66 58 ; 0xc473c vberom.asm:931 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc473e vberom.asm:932 + pop edx ; 66 5a ; 0xc4744 vberom.asm:934 + pop di ; 5f ; 0xc4746 vberom.asm:936 + pop si ; 5e ; 0xc4747 vberom.asm:937 + pop dx ; 5a ; 0xc4748 vberom.asm:938 + pop cx ; 59 ; 0xc4749 vberom.asm:939 + pop ax ; 58 ; 0xc474a vberom.asm:940 + mov eax, strict dword 066c3004fh ; 66 b8 4f 00 c3 66 ; 0xc474b vberom.asm:941 + mov ax, 0014fh ; b8 4f 01 ; 0xc4751 + ; disGetNextSymbol 0xc4754 LB 0x1 -> off=0x0 cb=0000000000000001 uValue=0000000000000114 'vesa_pm_end' +vesa_pm_end: ; 0xc4754 LB 0x1 + retn ; c3 ; 0xc4754 vberom.asm:946 + + ; Padding 0x2b bytes at 0xc4755 + times 43 db 0 + +section _DATA progbits vstart=0x4780 align=1 ; size=0x374d class=DATA group=DGROUP + ; disGetNextSymbol 0xc4780 LB 0x374d -> off=0x0 cb=000000000000002f uValue=00000000000c0000 '_msg_vga_init' +_msg_vga_init: ; 0xc4780 LB 0x2f + db 'Oracle VM VirtualBox Version 7.0.14 VGA BIOS', 00dh, 00ah, 000h + ; disGetNextSymbol 0xc47af LB 0x371e -> off=0x0 cb=0000000000000080 uValue=00000000000c002f 'vga_modes' +vga_modes: ; 0xc47af LB 0x80 + db 000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h + db 002h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 003h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h + db 004h, 001h, 002h, 002h, 000h, 0b8h, 0ffh, 001h, 005h, 001h, 002h, 002h, 000h, 0b8h, 0ffh, 001h + db 006h, 001h, 002h, 001h, 000h, 0b8h, 0ffh, 001h, 007h, 000h, 001h, 004h, 000h, 0b0h, 0ffh, 000h + db 00dh, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 001h, 00eh, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 001h + db 00fh, 001h, 003h, 001h, 000h, 0a0h, 0ffh, 000h, 010h, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + db 011h, 001h, 003h, 001h, 000h, 0a0h, 0ffh, 002h, 012h, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + db 013h, 001h, 005h, 008h, 000h, 0a0h, 0ffh, 003h, 06ah, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + ; disGetNextSymbol 0xc482f LB 0x369e -> off=0x0 cb=0000000000000010 uValue=00000000000c00af 'line_to_vpti' +line_to_vpti: ; 0xc482f LB 0x10 + db 017h, 017h, 018h, 018h, 004h, 005h, 006h, 007h, 00dh, 00eh, 011h, 012h, 01ah, 01bh, 01ch, 01dh + ; disGetNextSymbol 0xc483f LB 0x368e -> off=0x0 cb=0000000000000004 uValue=00000000000c00bf 'dac_regs' +dac_regs: ; 0xc483f LB 0x4 + dd 0ff3f3f3fh + ; disGetNextSymbol 0xc4843 LB 0x368a -> off=0x0 cb=0000000000000780 uValue=00000000000c00c3 'video_param_table' +video_param_table: ; 0xc4843 LB 0x780 + db 028h, 018h, 008h, 000h, 008h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 008h, 000h, 008h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 008h, 000h, 010h, 001h, 003h, 000h, 002h, 063h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 008h, 000h, 010h, 001h, 003h, 000h, 002h, 063h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 008h, 000h, 040h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0a2h, 0ffh, 000h, 013h, 015h, 017h, 002h, 004h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 003h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 00fh, 00fh, 0ffh + db 028h, 018h, 008h, 000h, 040h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0a2h, 0ffh, 000h, 013h, 015h, 017h, 002h, 004h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 003h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 00fh, 00fh, 0ffh + db 050h, 018h, 008h, 000h, 040h, 001h, 001h, 000h, 006h, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 000h, 096h + db 0b9h, 0c2h, 0ffh, 000h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h + db 017h, 017h, 017h, 001h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 00dh, 00fh, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 000h, 003h, 000h, 003h, 0a6h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00dh, 063h + db 0bah, 0a3h, 0ffh, 000h, 008h, 008h, 008h, 008h, 008h, 008h, 008h, 010h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 00eh, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00ah, 000h, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 028h, 018h, 008h, 000h, 020h, 009h, 00fh, 000h, 006h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 018h, 008h, 000h, 040h, 001h, 00fh, 000h, 006h, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 000h, 096h + db 0b9h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 050h, 018h, 00eh, 000h, 080h, 001h, 00fh, 000h, 006h, 0a3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00fh, 063h + db 0bah, 0e3h, 0ffh, 000h, 008h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 008h, 000h, 000h, 000h + db 018h, 000h, 000h, 001h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 018h, 00eh, 000h, 080h, 001h, 00fh, 000h, 006h, 0a3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00fh, 063h + db 0bah, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 028h, 018h, 00eh, 000h, 008h, 009h, 003h, 000h, 002h, 0a3h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 014h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 00eh, 000h, 008h, 009h, 003h, 000h, 002h, 0a3h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 014h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 001h, 003h, 000h, 002h, 0a3h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 001h, 003h, 000h, 002h, 0a3h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 010h, 000h, 008h, 008h, 003h, 000h, 002h, 067h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 00ch, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 00fh, 0ffh + db 050h, 018h, 010h, 000h, 010h, 000h, 003h, 000h, 002h, 067h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 00ch, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 00fh, 0ffh + db 050h, 018h, 010h, 000h, 010h, 000h, 003h, 000h, 002h, 066h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 00fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 008h, 008h, 008h, 008h, 008h, 008h, 008h, 010h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 00eh, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00ah, 00fh, 0ffh + db 050h, 01dh, 010h, 000h, 0a0h, 001h, 00fh, 000h, 006h, 0e3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 00bh, 03eh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 0eah, 08ch, 0dfh, 028h, 000h, 0e7h + db 004h, 0c3h, 0ffh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h + db 03fh, 000h, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 01dh, 010h, 000h, 0a0h, 001h, 00fh, 000h, 006h, 0e3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 00bh, 03eh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 0eah, 08ch, 0dfh, 028h, 000h, 0e7h + db 004h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 028h, 018h, 008h, 000h, 020h, 001h, 00fh, 000h, 00eh, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 041h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 040h, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 008h, 009h, 00ah, 00bh, 00ch + db 00dh, 00eh, 00fh, 041h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 040h, 005h, 00fh, 0ffh + db 064h, 024h, 010h, 000h, 000h, 001h, 00fh, 000h, 006h, 0e3h, 07fh, 063h, 063h, 083h, 06bh, 01bh + db 072h, 0f0h, 000h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 059h, 08dh, 057h, 032h, 000h, 057h + db 073h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + ; disGetNextSymbol 0xc4fc3 LB 0x2f0a -> off=0x0 cb=00000000000000c0 uValue=00000000000c0843 'palette0' +palette0: ; 0xc4fc3 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5083 LB 0x2e4a -> off=0x0 cb=00000000000000c0 uValue=00000000000c0903 'palette1' +palette1: ; 0xc5083 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah + db 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah, 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah + db 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh, 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh + db 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah + db 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah, 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah + db 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh, 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh + db 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5143 LB 0x2d8a -> off=0x0 cb=00000000000000c0 uValue=00000000000c09c3 'palette2' +palette2: ; 0xc5143 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 02ah, 000h, 02ah, 02ah, 02ah, 000h, 000h, 015h, 000h, 000h, 03fh, 000h, 02ah + db 015h, 000h, 02ah, 03fh, 02ah, 000h, 015h, 02ah, 000h, 03fh, 02ah, 02ah, 015h, 02ah, 02ah, 03fh + db 000h, 015h, 000h, 000h, 015h, 02ah, 000h, 03fh, 000h, 000h, 03fh, 02ah, 02ah, 015h, 000h, 02ah + db 015h, 02ah, 02ah, 03fh, 000h, 02ah, 03fh, 02ah, 000h, 015h, 015h, 000h, 015h, 03fh, 000h, 03fh + db 015h, 000h, 03fh, 03fh, 02ah, 015h, 015h, 02ah, 015h, 03fh, 02ah, 03fh, 015h, 02ah, 03fh, 03fh + db 015h, 000h, 000h, 015h, 000h, 02ah, 015h, 02ah, 000h, 015h, 02ah, 02ah, 03fh, 000h, 000h, 03fh + db 000h, 02ah, 03fh, 02ah, 000h, 03fh, 02ah, 02ah, 015h, 000h, 015h, 015h, 000h, 03fh, 015h, 02ah + db 015h, 015h, 02ah, 03fh, 03fh, 000h, 015h, 03fh, 000h, 03fh, 03fh, 02ah, 015h, 03fh, 02ah, 03fh + db 015h, 015h, 000h, 015h, 015h, 02ah, 015h, 03fh, 000h, 015h, 03fh, 02ah, 03fh, 015h, 000h, 03fh + db 015h, 02ah, 03fh, 03fh, 000h, 03fh, 03fh, 02ah, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5203 LB 0x2cca -> off=0x0 cb=0000000000000300 uValue=00000000000c0a83 'palette3' +palette3: ; 0xc5203 LB 0x300 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 005h, 005h, 005h, 008h, 008h, 008h, 00bh, 00bh, 00bh, 00eh, 00eh, 00eh, 011h + db 011h, 011h, 014h, 014h, 014h, 018h, 018h, 018h, 01ch, 01ch, 01ch, 020h, 020h, 020h, 024h, 024h + db 024h, 028h, 028h, 028h, 02dh, 02dh, 02dh, 032h, 032h, 032h, 038h, 038h, 038h, 03fh, 03fh, 03fh + db 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh, 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h, 03fh, 03fh + db 000h, 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh + db 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h, 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 000h + db 000h, 03fh, 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh, 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h + db 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh, 02fh, 01fh + db 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 03fh, 03fh, 01fh, 037h, 03fh, 01fh, 02fh, 03fh, 01fh, 027h + db 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh, 02fh, 01fh, 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 037h + db 03fh, 01fh, 02fh, 03fh, 01fh, 027h, 03fh, 01fh, 01fh, 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh + db 02fh, 01fh, 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 037h, 03fh, 01fh, 02fh, 03fh, 01fh, 027h, 03fh + db 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h, 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh, 03fh, 03fh + db 02dh, 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h + db 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh, 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 02dh + db 02dh, 03fh, 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h, 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh + db 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 000h, 000h, 01ch, 007h, 000h, 01ch, 00eh, 000h + db 01ch, 015h, 000h, 01ch, 01ch, 000h, 01ch, 01ch, 000h, 015h, 01ch, 000h, 00eh, 01ch, 000h, 007h + db 01ch, 000h, 000h, 01ch, 007h, 000h, 01ch, 00eh, 000h, 01ch, 015h, 000h, 01ch, 01ch, 000h, 015h + db 01ch, 000h, 00eh, 01ch, 000h, 007h, 01ch, 000h, 000h, 01ch, 000h, 000h, 01ch, 007h, 000h, 01ch + db 00eh, 000h, 01ch, 015h, 000h, 01ch, 01ch, 000h, 015h, 01ch, 000h, 00eh, 01ch, 000h, 007h, 01ch + db 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h, 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh, 01ch, 01ch + db 00eh, 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h + db 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh, 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 00eh + db 00eh, 01ch, 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h, 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh + db 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch, 018h, 014h + db 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ch, 01ch, 014h, 01ah, 01ch, 014h, 018h, 01ch, 014h, 016h + db 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch, 018h, 014h, 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ah + db 01ch, 014h, 018h, 01ch, 014h, 016h, 01ch, 014h, 014h, 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch + db 018h, 014h, 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ah, 01ch, 014h, 018h, 01ch, 014h, 016h, 01ch + db 000h, 000h, 010h, 004h, 000h, 010h, 008h, 000h, 010h, 00ch, 000h, 010h, 010h, 000h, 010h, 010h + db 000h, 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 000h, 000h, 010h, 004h, 000h, 010h, 008h + db 000h, 010h, 00ch, 000h, 010h, 010h, 000h, 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 000h + db 000h, 010h, 000h, 000h, 010h, 004h, 000h, 010h, 008h, 000h, 010h, 00ch, 000h, 010h, 010h, 000h + db 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 008h, 008h, 010h, 00ah, 008h, 010h, 00ch, 008h + db 010h, 00eh, 008h, 010h, 010h, 008h, 010h, 010h, 008h, 00eh, 010h, 008h, 00ch, 010h, 008h, 00ah + db 010h, 008h, 008h, 010h, 00ah, 008h, 010h, 00ch, 008h, 010h, 00eh, 008h, 010h, 010h, 008h, 00eh + db 010h, 008h, 00ch, 010h, 008h, 00ah, 010h, 008h, 008h, 010h, 008h, 008h, 010h, 00ah, 008h, 010h + db 00ch, 008h, 010h, 00eh, 008h, 010h, 010h, 008h, 00eh, 010h, 008h, 00ch, 010h, 008h, 00ah, 010h + db 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh, 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh, 010h, 010h + db 00bh, 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh + db 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh, 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 00bh + db 00bh, 010h, 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh, 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh + db 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5503 LB 0x29ca -> off=0x0 cb=0000000000000010 uValue=00000000000c0d83 'static_functionality' +static_functionality: ; 0xc5503 LB 0x10 + db 0ffh, 0e0h, 00fh, 000h, 000h, 000h, 000h, 007h, 002h, 008h, 0e7h, 00ch, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5513 LB 0x29ba -> off=0x0 cb=0000000000000024 uValue=00000000000c0d93 '_dcc_table' +_dcc_table: ; 0xc5513 LB 0x24 + db 010h, 001h, 007h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5537 LB 0x2996 -> off=0x0 cb=000000000000001a uValue=00000000000c0db7 '_secondary_save_area' +_secondary_save_area: ; 0xc5537 LB 0x1a + db 01ah, 000h, 013h, 055h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5551 LB 0x297c -> off=0x0 cb=000000000000001c uValue=00000000000c0dd1 '_video_save_pointer_table' +_video_save_pointer_table: ; 0xc5551 LB 0x1c + db 043h, 048h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 037h, 055h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc556d LB 0x2960 -> off=0x0 cb=0000000000000800 uValue=00000000000c0ded 'vgafont8' +vgafont8: ; 0xc556d LB 0x800 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 081h, 0a5h, 081h, 0bdh, 099h, 081h, 07eh + db 07eh, 0ffh, 0dbh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 06ch, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h + db 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 038h, 07ch, 038h, 0feh, 0feh, 07ch, 038h, 07ch + db 010h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 07ch, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h + db 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h + db 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 00fh, 007h, 00fh, 07dh, 0cch, 0cch, 0cch, 078h + db 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 03fh, 033h, 03fh, 030h, 030h, 070h, 0f0h, 0e0h + db 07fh, 063h, 07fh, 063h, 063h, 067h, 0e6h, 0c0h, 099h, 05ah, 03ch, 0e7h, 0e7h, 03ch, 05ah, 099h + db 080h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 080h, 000h, 002h, 00eh, 03eh, 0feh, 03eh, 00eh, 002h, 000h + db 018h, 03ch, 07eh, 018h, 018h, 07eh, 03ch, 018h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 000h + db 07fh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 000h, 03eh, 063h, 038h, 06ch, 06ch, 038h, 0cch, 078h + db 000h, 000h, 000h, 000h, 07eh, 07eh, 07eh, 000h, 018h, 03ch, 07eh, 018h, 07eh, 03ch, 018h, 0ffh + db 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h + db 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h + db 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h + db 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 000h, 000h, 000h, 0ffh, 0ffh, 07eh, 03ch, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 078h, 078h, 030h, 030h, 000h, 030h, 000h + db 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 0feh, 06ch, 06ch, 000h + db 030h, 07ch, 0c0h, 078h, 00ch, 0f8h, 030h, 000h, 000h, 0c6h, 0cch, 018h, 030h, 066h, 0c6h, 000h + db 038h, 06ch, 038h, 076h, 0dch, 0cch, 076h, 000h, 060h, 060h, 0c0h, 000h, 000h, 000h, 000h, 000h + db 018h, 030h, 060h, 060h, 060h, 030h, 018h, 000h, 060h, 030h, 018h, 018h, 018h, 030h, 060h, 000h + db 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 060h, 000h, 000h, 000h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 000h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h + db 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 07ch, 000h, 030h, 070h, 030h, 030h, 030h, 030h, 0fch, 000h + db 078h, 0cch, 00ch, 038h, 060h, 0cch, 0fch, 000h, 078h, 0cch, 00ch, 038h, 00ch, 0cch, 078h, 000h + db 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 01eh, 000h, 0fch, 0c0h, 0f8h, 00ch, 00ch, 0cch, 078h, 000h + db 038h, 060h, 0c0h, 0f8h, 0cch, 0cch, 078h, 000h, 0fch, 0cch, 00ch, 018h, 030h, 030h, 030h, 000h + db 078h, 0cch, 0cch, 078h, 0cch, 0cch, 078h, 000h, 078h, 0cch, 0cch, 07ch, 00ch, 018h, 070h, 000h + db 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 060h + db 018h, 030h, 060h, 0c0h, 060h, 030h, 018h, 000h, 000h, 000h, 0fch, 000h, 000h, 0fch, 000h, 000h + db 060h, 030h, 018h, 00ch, 018h, 030h, 060h, 000h, 078h, 0cch, 00ch, 018h, 030h, 000h, 030h, 000h + db 07ch, 0c6h, 0deh, 0deh, 0deh, 0c0h, 078h, 000h, 030h, 078h, 0cch, 0cch, 0fch, 0cch, 0cch, 000h + db 0fch, 066h, 066h, 07ch, 066h, 066h, 0fch, 000h, 03ch, 066h, 0c0h, 0c0h, 0c0h, 066h, 03ch, 000h + db 0f8h, 06ch, 066h, 066h, 066h, 06ch, 0f8h, 000h, 0feh, 062h, 068h, 078h, 068h, 062h, 0feh, 000h + db 0feh, 062h, 068h, 078h, 068h, 060h, 0f0h, 000h, 03ch, 066h, 0c0h, 0c0h, 0ceh, 066h, 03eh, 000h + db 0cch, 0cch, 0cch, 0fch, 0cch, 0cch, 0cch, 000h, 078h, 030h, 030h, 030h, 030h, 030h, 078h, 000h + db 01eh, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 0e6h, 066h, 06ch, 078h, 06ch, 066h, 0e6h, 000h + db 0f0h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 000h + db 0c6h, 0e6h, 0f6h, 0deh, 0ceh, 0c6h, 0c6h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h + db 0fch, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 078h, 0cch, 0cch, 0cch, 0dch, 078h, 01ch, 000h + db 0fch, 066h, 066h, 07ch, 06ch, 066h, 0e6h, 000h, 078h, 0cch, 0e0h, 070h, 01ch, 0cch, 078h, 000h + db 0fch, 0b4h, 030h, 030h, 030h, 030h, 078h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 0fch, 000h + db 0cch, 0cch, 0cch, 0cch, 0cch, 078h, 030h, 000h, 0c6h, 0c6h, 0c6h, 0d6h, 0feh, 0eeh, 0c6h, 000h + db 0c6h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 030h, 078h, 000h + db 0feh, 0c6h, 08ch, 018h, 032h, 066h, 0feh, 000h, 078h, 060h, 060h, 060h, 060h, 060h, 078h, 000h + db 0c0h, 060h, 030h, 018h, 00ch, 006h, 002h, 000h, 078h, 018h, 018h, 018h, 018h, 018h, 078h, 000h + db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 076h, 000h + db 0e0h, 060h, 060h, 07ch, 066h, 066h, 0dch, 000h, 000h, 000h, 078h, 0cch, 0c0h, 0cch, 078h, 000h + db 01ch, 00ch, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h + db 038h, 06ch, 060h, 0f0h, 060h, 060h, 0f0h, 000h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 0f8h + db 0e0h, 060h, 06ch, 076h, 066h, 066h, 0e6h, 000h, 030h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 00ch, 000h, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 0e0h, 060h, 066h, 06ch, 078h, 06ch, 0e6h, 000h + db 070h, 030h, 030h, 030h, 030h, 030h, 078h, 000h, 000h, 000h, 0cch, 0feh, 0feh, 0d6h, 0c6h, 000h + db 000h, 000h, 0f8h, 0cch, 0cch, 0cch, 0cch, 000h, 000h, 000h, 078h, 0cch, 0cch, 0cch, 078h, 000h + db 000h, 000h, 0dch, 066h, 066h, 07ch, 060h, 0f0h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 01eh + db 000h, 000h, 0dch, 076h, 066h, 060h, 0f0h, 000h, 000h, 000h, 07ch, 0c0h, 078h, 00ch, 0f8h, 000h + db 010h, 030h, 07ch, 030h, 030h, 034h, 018h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 000h, 000h, 000h, 0c6h, 0d6h, 0feh, 0feh, 06ch, 000h + db 000h, 000h, 0c6h, 06ch, 038h, 06ch, 0c6h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 07ch, 00ch, 0f8h + db 000h, 000h, 0fch, 098h, 030h, 064h, 0fch, 000h, 01ch, 030h, 030h, 0e0h, 030h, 030h, 01ch, 000h + db 018h, 018h, 018h, 000h, 018h, 018h, 018h, 000h, 0e0h, 030h, 030h, 01ch, 030h, 030h, 0e0h, 000h + db 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h + db 078h, 0cch, 0c0h, 0cch, 078h, 018h, 00ch, 078h, 000h, 0cch, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 01ch, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h, 07eh, 0c3h, 03ch, 006h, 03eh, 066h, 03fh, 000h + db 0cch, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 0e0h, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h + db 030h, 030h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 000h, 000h, 078h, 0c0h, 0c0h, 078h, 00ch, 038h + db 07eh, 0c3h, 03ch, 066h, 07eh, 060h, 03ch, 000h, 0cch, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h + db 0e0h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h, 0cch, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 07ch, 0c6h, 038h, 018h, 018h, 018h, 03ch, 000h, 0e0h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 0c6h, 038h, 06ch, 0c6h, 0feh, 0c6h, 0c6h, 000h, 030h, 030h, 000h, 078h, 0cch, 0fch, 0cch, 000h + db 01ch, 000h, 0fch, 060h, 078h, 060h, 0fch, 000h, 000h, 000h, 07fh, 00ch, 07fh, 0cch, 07fh, 000h + db 03eh, 06ch, 0cch, 0feh, 0cch, 0cch, 0ceh, 000h, 078h, 0cch, 000h, 078h, 0cch, 0cch, 078h, 000h + db 000h, 0cch, 000h, 078h, 0cch, 0cch, 078h, 000h, 000h, 0e0h, 000h, 078h, 0cch, 0cch, 078h, 000h + db 078h, 0cch, 000h, 0cch, 0cch, 0cch, 07eh, 000h, 000h, 0e0h, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 000h, 0cch, 000h, 0cch, 0cch, 07ch, 00ch, 0f8h, 0c3h, 018h, 03ch, 066h, 066h, 03ch, 018h, 000h + db 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 078h, 000h, 018h, 018h, 07eh, 0c0h, 0c0h, 07eh, 018h, 018h + db 038h, 06ch, 064h, 0f0h, 060h, 0e6h, 0fch, 000h, 0cch, 0cch, 078h, 0fch, 030h, 0fch, 030h, 030h + db 0f8h, 0cch, 0cch, 0fah, 0c6h, 0cfh, 0c6h, 0c7h, 00eh, 01bh, 018h, 03ch, 018h, 018h, 0d8h, 070h + db 01ch, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 038h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 000h, 01ch, 000h, 078h, 0cch, 0cch, 078h, 000h, 000h, 01ch, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 000h, 0f8h, 000h, 0f8h, 0cch, 0cch, 0cch, 000h, 0fch, 000h, 0cch, 0ech, 0fch, 0dch, 0cch, 000h + db 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h + db 030h, 000h, 030h, 060h, 0c0h, 0cch, 078h, 000h, 000h, 000h, 000h, 0fch, 0c0h, 0c0h, 000h, 000h + db 000h, 000h, 000h, 0fch, 00ch, 00ch, 000h, 000h, 0c3h, 0c6h, 0cch, 0deh, 033h, 066h, 0cch, 00fh + db 0c3h, 0c6h, 0cch, 0dbh, 037h, 06fh, 0cfh, 003h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 000h + db 000h, 033h, 066h, 0cch, 066h, 033h, 000h, 000h, 000h, 0cch, 066h, 033h, 066h, 0cch, 000h, 000h + db 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah + db 0dbh, 077h, 0dbh, 0eeh, 0dbh, 077h, 0dbh, 0eeh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h + db 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 0feh, 006h, 0f6h, 036h, 036h, 036h + db 036h, 036h, 0f6h, 006h, 0feh, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h, 000h + db 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h + db 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h + db 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h + db 036h, 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0f7h, 036h, 036h, 036h + db 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h, 000h + db 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 03fh, 000h, 000h, 000h + db 018h, 018h, 01fh, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h + db 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 0c8h, 0dch, 076h, 000h, 000h, 078h, 0cch, 0f8h, 0cch, 0f8h, 0c0h, 0c0h + db 000h, 0fch, 0cch, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 0feh, 06ch, 06ch, 06ch, 06ch, 06ch, 000h + db 0fch, 0cch, 060h, 030h, 060h, 0cch, 0fch, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 070h, 000h + db 000h, 066h, 066h, 066h, 066h, 07ch, 060h, 0c0h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 000h + db 0fch, 030h, 078h, 0cch, 0cch, 078h, 030h, 0fch, 038h, 06ch, 0c6h, 0feh, 0c6h, 06ch, 038h, 000h + db 038h, 06ch, 0c6h, 0c6h, 06ch, 06ch, 0eeh, 000h, 01ch, 030h, 018h, 07ch, 0cch, 0cch, 078h, 000h + db 000h, 000h, 07eh, 0dbh, 0dbh, 07eh, 000h, 000h, 006h, 00ch, 07eh, 0dbh, 0dbh, 07eh, 060h, 0c0h + db 038h, 060h, 0c0h, 0f8h, 0c0h, 060h, 038h, 000h, 078h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 000h + db 000h, 0fch, 000h, 0fch, 000h, 0fch, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 0fch, 000h + db 060h, 030h, 018h, 030h, 060h, 000h, 0fch, 000h, 018h, 030h, 060h, 030h, 018h, 000h, 0fch, 000h + db 00eh, 01bh, 01bh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h, 070h + db 030h, 030h, 000h, 0fch, 000h, 030h, 030h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h + db 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h, 00fh, 00ch, 00ch, 00ch, 0ech, 06ch, 03ch, 01ch + db 078h, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 070h, 018h, 030h, 060h, 078h, 000h, 000h, 000h + db 000h, 000h, 03ch, 03ch, 03ch, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5d6d LB 0x2160 -> off=0x0 cb=0000000000000e00 uValue=00000000000c15ed 'vgafont14' +vgafont14: ; 0xc5d6d LB 0xe00 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 07eh, 081h, 0a5h, 081h, 081h, 0bdh, 099h, 081h, 07eh, 000h, 000h, 000h, 000h, 000h, 07eh, 0ffh + db 0dbh, 0ffh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 06ch, 0feh, 0feh + db 0feh, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 07ch, 0feh, 07ch + db 038h, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 0e7h, 0e7h, 0e7h, 018h, 018h + db 03ch, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 07eh, 018h, 018h, 03ch, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h + db 000h, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh + db 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 01eh, 00eh, 01ah, 032h + db 078h, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 066h, 066h, 03ch, 018h + db 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 03fh, 033h, 03fh, 030h, 030h, 030h, 070h, 0f0h + db 0e0h, 000h, 000h, 000h, 000h, 000h, 07fh, 063h, 07fh, 063h, 063h, 063h, 067h, 0e7h, 0e6h, 0c0h + db 000h, 000h, 000h, 000h, 018h, 018h, 0dbh, 03ch, 0e7h, 03ch, 0dbh, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 080h, 0c0h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 0c0h, 080h, 000h, 000h, 000h, 000h, 000h + db 002h, 006h, 00eh, 03eh, 0feh, 03eh, 00eh, 006h, 002h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch + db 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h + db 066h, 066h, 000h, 066h, 066h, 000h, 000h, 000h, 000h, 000h, 07fh, 0dbh, 0dbh, 0dbh, 07bh, 01bh + db 01bh, 01bh, 01bh, 000h, 000h, 000h, 000h, 07ch, 0c6h, 060h, 038h, 06ch, 0c6h, 0c6h, 06ch, 038h + db 00ch, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 0feh, 000h + db 000h, 000h, 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 07eh, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 060h + db 0feh, 060h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c0h + db 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 028h, 06ch, 0feh, 06ch, 028h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 038h, 07ch, 07ch, 0feh, 0feh, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 07ch, 07ch, 038h, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 03ch, 03ch, 03ch, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 066h, 066h, 066h + db 024h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch + db 06ch, 06ch, 0feh, 06ch, 06ch, 000h, 000h, 000h, 018h, 018h, 07ch, 0c6h, 0c2h, 0c0h, 07ch, 006h + db 086h, 0c6h, 07ch, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 0c2h, 0c6h, 00ch, 018h, 030h, 066h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 038h, 06ch, 06ch, 038h, 076h, 0dch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 030h, 030h, 030h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 018h, 030h, 030h, 030h, 030h, 030h, 018h, 00ch, 000h, 000h, 000h, 000h, 000h + db 030h, 018h, 00ch, 00ch, 00ch, 00ch, 00ch, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h + db 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h + db 000h, 000h, 000h, 000h, 002h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 018h, 038h, 078h, 018h, 018h, 018h, 018h, 018h, 07eh, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h + db 006h, 00ch, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 006h, 006h + db 03ch, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 00ch, 01ch, 03ch, 06ch, 0cch, 0feh + db 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0fch, 006h, 006h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 038h, 060h, 0c0h, 0c0h, 0fch, 0c6h, 0c6h, 0c6h, 07ch, 000h + db 000h, 000h, 000h, 000h, 0feh, 0c6h, 006h, 00ch, 018h, 030h, 030h, 030h, 030h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 07ch, 0c6h, 0c6h, 0c6h, 07eh, 006h, 006h, 00ch, 078h, 000h, 000h, 000h, 000h, 000h, 000h, 018h + db 018h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h + db 000h, 000h, 018h, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 006h, 00ch, 018h, 030h, 060h, 030h + db 018h, 00ch, 006h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 000h, 000h, 07eh, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 060h, 000h + db 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 00ch, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0deh, 0deh, 0deh, 0dch, 0c0h, 07ch, 000h, 000h, 000h, 000h, 000h + db 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h, 0fch, 066h + db 066h, 066h, 07ch, 066h, 066h, 066h, 0fch, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 0c2h, 0c0h + db 0c0h, 0c0h, 0c2h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h, 0f8h, 06ch, 066h, 066h, 066h, 066h + db 066h, 06ch, 0f8h, 000h, 000h, 000h, 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 062h, 066h + db 0feh, 000h, 000h, 000h, 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0deh, 0c6h, 066h, 03ah, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h + db 03ch, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 01eh, 00ch + db 00ch, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h, 000h, 0e6h, 066h, 06ch, 06ch + db 078h, 06ch, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 0f0h, 060h, 060h, 060h, 060h, 060h + db 062h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 0c6h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 000h + db 000h, 000h, 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h, 000h + db 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0deh, 07ch, 00ch, 00eh, 000h, 000h, 000h, 000h, 0fch, 066h + db 066h, 066h, 07ch, 06ch, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 060h + db 038h, 00ch, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 07eh, 07eh, 05ah, 018h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 010h, 000h + db 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0d6h, 0feh, 07ch, 06ch, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 06ch, 038h, 038h, 038h, 06ch, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h + db 066h, 066h, 066h, 066h, 03ch, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 0feh, 0c6h + db 08ch, 018h, 030h, 060h, 0c2h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 03ch, 030h, 030h, 030h + db 030h, 030h, 030h, 030h, 03ch, 000h, 000h, 000h, 000h, 000h, 080h, 0c0h, 0e0h, 070h, 038h, 01ch + db 00eh, 006h, 002h, 000h, 000h, 000h, 000h, 000h, 03ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch + db 03ch, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 0e0h, 060h + db 060h, 078h, 06ch, 066h, 066h, 066h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch + db 0c6h, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 01ch, 00ch, 00ch, 03ch, 06ch, 0cch + db 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 07ch, 00ch, 0cch, 078h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 06ch, 076h, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 006h, 006h + db 000h, 00eh, 006h, 006h, 006h, 006h, 066h, 066h, 03ch, 000h, 000h, 000h, 0e0h, 060h, 060h, 066h + db 06ch, 078h, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ech, 0feh, 0d6h, 0d6h, 0d6h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 000h, 000h + db 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 07ch, 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h, 000h + db 000h, 0dch, 076h, 066h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch + db 0c6h, 070h, 01ch, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 010h, 030h, 030h, 0fch, 030h, 030h + db 030h, 036h, 01ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch + db 076h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 03ch, 018h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0d6h, 0d6h, 0feh, 06ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 0f8h, 000h, 000h, 000h, 000h, 000h + db 000h, 0feh, 0cch, 018h, 030h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h, 00eh, 018h, 018h, 018h + db 070h, 018h, 018h, 018h, 00eh, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 000h, 018h + db 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 070h, 018h, 018h, 018h, 00eh, 018h, 018h, 018h + db 070h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 00ch, 006h, 07ch, 000h, 000h, 000h + db 0cch, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 00ch, 018h, 030h + db 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 000h, 078h + db 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 000h, 078h, 00ch, 07ch + db 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 078h, 00ch, 07ch, 0cch, 0cch + db 076h, 000h, 000h, 000h, 000h, 038h, 06ch, 038h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 060h, 066h, 03ch, 00ch, 006h, 03ch, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 0cch, 0cch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h + db 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 000h, 038h + db 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 018h, 03ch, 066h, 000h, 038h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 038h, 018h, 018h, 018h, 018h + db 03ch, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 000h + db 000h, 000h, 038h, 06ch, 038h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 000h, 000h, 000h + db 018h, 030h, 060h, 000h, 0feh, 066h, 060h, 07ch, 060h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 0cch, 076h, 036h, 07eh, 0d8h, 0d8h, 06eh, 000h, 000h, 000h, 000h, 000h, 03eh, 06ch + db 0cch, 0cch, 0feh, 0cch, 0cch, 0cch, 0ceh, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 000h, 07ch + db 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 000h, 07ch, 0c6h, 0c6h + db 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 030h, 078h, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 060h, 030h, 018h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 078h, 000h, 000h, 0c6h + db 0c6h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 000h + db 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 018h, 018h, 03ch, 066h, 060h + db 060h, 066h, 03ch, 018h, 018h, 000h, 000h, 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h + db 060h, 0e6h, 0fch, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 03ch, 018h, 07eh, 018h, 07eh, 018h + db 018h, 000h, 000h, 000h, 000h, 0f8h, 0cch, 0cch, 0f8h, 0c4h, 0cch, 0deh, 0cch, 0cch, 0c6h, 000h + db 000h, 000h, 000h, 00eh, 01bh, 018h, 018h, 018h, 07eh, 018h, 018h, 018h, 018h, 0d8h, 070h, 000h + db 000h, 018h, 030h, 060h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 00ch + db 018h, 030h, 000h, 038h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 018h, 030h, 060h + db 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 018h, 030h, 060h, 000h, 0cch + db 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 0dch, 066h, 066h + db 066h, 066h, 066h, 000h, 000h, 000h, 076h, 0dch, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h + db 0c6h, 000h, 000h, 000h, 000h, 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 030h, 000h, 030h, 030h, 060h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 006h, 006h, 006h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c6h, 0cch, 0d8h + db 030h, 060h, 0dch, 086h, 00ch, 018h, 03eh, 000h, 000h, 0c0h, 0c0h, 0c6h, 0cch, 0d8h, 030h, 066h + db 0ceh, 09eh, 03eh, 006h, 006h, 000h, 000h, 000h, 018h, 018h, 000h, 018h, 018h, 03ch, 03ch, 03ch + db 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 036h, 06ch, 0d8h, 06ch, 036h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0d8h, 06ch, 036h, 06ch, 0d8h, 000h, 000h, 000h, 000h, 000h + db 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 055h, 0aah + db 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 0ddh, 077h, 0ddh, 077h + db 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h + db 018h, 018h, 018h, 018h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 036h + db 036h, 036h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 036h, 036h + db 036h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 000h, 0feh + db 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0feh + db 000h, 000h, 000h, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h + db 018h, 018h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 030h, 037h + db 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h + db 000h, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 036h + db 036h, 036h, 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h + db 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 0f0h, 0f0h, 0f0h, 0f0h, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh + db 00fh, 00fh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 0d8h, 0d8h, 0dch, 076h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0fch, 0c6h, 0c6h, 0fch, 0c0h, 0c0h, 040h, 000h, 000h, 000h, 0feh, 0c6h + db 0c6h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 06ch + db 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 0feh, 0c6h, 060h, 030h, 018h, 030h + db 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 0d8h + db 070h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0c0h + db 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 07eh, 018h, 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h, 000h + db 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 038h, 06ch + db 0c6h, 0c6h, 0c6h, 06ch, 06ch, 06ch, 0eeh, 000h, 000h, 000h, 000h, 000h, 01eh, 030h, 018h, 00ch + db 03eh, 066h, 066h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 0dbh, 0dbh + db 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 003h, 006h, 07eh, 0dbh, 0dbh, 0f3h, 07eh, 060h + db 0c0h, 000h, 000h, 000h, 000h, 000h, 01ch, 030h, 060h, 060h, 07ch, 060h, 060h, 030h, 01ch, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h + db 000h, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 030h, 018h + db 00ch, 006h, 00ch, 018h, 030h, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 00ch, 018h, 030h, 060h + db 030h, 018h, 00ch, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 00eh, 01bh, 01bh, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h + db 070h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 07eh, 000h, 018h, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 00fh, 00ch, 00ch, 00ch, 00ch + db 00ch, 0ech, 06ch, 03ch, 01ch, 000h, 000h, 000h, 000h, 0d8h, 06ch, 06ch, 06ch, 06ch, 06ch, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 070h, 0d8h, 030h, 060h, 0c8h, 0f8h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc6b6d LB 0x1360 -> off=0x0 cb=0000000000001000 uValue=00000000000c23ed 'vgafont16' +vgafont16: ; 0xc6b6d LB 0x1000 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 081h, 0a5h, 081h, 081h, 0bdh, 099h, 081h, 081h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 0ffh, 0dbh, 0ffh, 0ffh, 0c3h, 0e7h, 0ffh, 0ffh, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 06ch, 0feh, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 03ch, 03ch, 0e7h, 0e7h, 0e7h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 07eh, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 01eh, 00eh, 01ah, 032h, 078h, 0cch, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 03fh, 033h, 03fh, 030h, 030h, 030h, 030h, 070h, 0f0h, 0e0h, 000h, 000h, 000h, 000h + db 000h, 000h, 07fh, 063h, 07fh, 063h, 063h, 063h, 063h, 067h, 0e7h, 0e6h, 0c0h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 018h, 0dbh, 03ch, 0e7h, 03ch, 0dbh, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0feh, 0f8h, 0f0h, 0e0h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 002h, 006h, 00eh, 01eh, 03eh, 0feh, 03eh, 01eh, 00eh, 006h, 002h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 066h, 000h, 000h, 000h, 000h + db 000h, 000h, 07fh, 0dbh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 01bh, 01bh, 000h, 000h, 000h, 000h + db 000h, 07ch, 0c6h, 060h, 038h, 06ch, 0c6h, 0c6h, 06ch, 038h, 00ch, 0c6h, 07ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 0feh, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 028h, 06ch, 0feh, 06ch, 028h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 038h, 07ch, 07ch, 0feh, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 0feh, 07ch, 07ch, 038h, 038h, 010h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 03ch, 03ch, 018h, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 066h, 066h, 066h, 024h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 06ch, 06ch, 0feh, 06ch, 06ch, 000h, 000h, 000h, 000h + db 018h, 018h, 07ch, 0c6h, 0c2h, 0c0h, 07ch, 006h, 006h, 086h, 0c6h, 07ch, 018h, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 0c2h, 0c6h, 00ch, 018h, 030h, 060h, 0c6h, 086h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 06ch, 038h, 076h, 0dch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 030h, 030h, 030h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 018h, 030h, 030h, 030h, 030h, 030h, 030h, 018h, 00ch, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 018h, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 018h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 030h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 002h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0d6h, 0d6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 038h, 078h, 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 006h, 006h, 03ch, 006h, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0fch, 006h, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 060h, 0c0h, 0c0h, 0fch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 006h, 006h, 00ch, 018h, 030h, 030h, 030h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07eh, 006h, 006h, 006h, 00ch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 018h, 018h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 006h, 00ch, 018h, 030h, 060h, 030h, 018h, 00ch, 006h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 000h, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 060h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 060h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 00ch, 018h, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0deh, 0deh, 0deh, 0dch, 0c0h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 066h, 066h, 066h, 066h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0f8h, 06ch, 066h, 066h, 066h, 066h, 066h, 066h, 06ch, 0f8h, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 062h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0deh, 0c6h, 0c6h, 066h, 03ah, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 01eh, 00ch, 00ch, 00ch, 00ch, 00ch, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 0e6h, 066h, 066h, 06ch, 078h, 078h, 06ch, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0f0h, 060h, 060h, 060h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 060h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0deh, 07ch, 00ch, 00eh, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 06ch, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 060h, 038h, 00ch, 006h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 07eh, 05ah, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0d6h, 0d6h, 0feh, 0eeh, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 06ch, 07ch, 038h, 038h, 07ch, 06ch, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 066h, 066h, 03ch, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 086h, 00ch, 018h, 030h, 060h, 0c2h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 030h, 030h, 030h, 030h, 030h, 030h, 030h, 030h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 080h, 0c0h, 0e0h, 070h, 038h, 01ch, 00eh, 006h, 002h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 03ch, 000h, 000h, 000h, 000h + db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 000h + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 078h, 06ch, 066h, 066h, 066h, 066h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c0h, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 01ch, 00ch, 00ch, 03ch, 06ch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 0cch, 0cch, 07ch, 00ch, 0cch, 078h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 06ch, 076h, 066h, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 006h, 006h, 000h, 00eh, 006h, 006h, 006h, 006h, 006h, 006h, 066h, 066h, 03ch, 000h + db 000h, 000h, 0e0h, 060h, 060h, 066h, 06ch, 078h, 078h, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ech, 0feh, 0d6h, 0d6h, 0d6h, 0d6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 0cch, 0cch, 07ch, 00ch, 00ch, 01eh, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 076h, 066h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 060h, 038h, 00ch, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 010h, 030h, 030h, 0fch, 030h, 030h, 030h, 030h, 036h, 01ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 066h, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0d6h, 0d6h, 0d6h, 0feh, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 06ch, 038h, 038h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 0f8h, 000h + db 000h, 000h, 000h, 000h, 000h, 0feh, 0cch, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 00eh, 018h, 018h, 018h, 070h, 018h, 018h, 018h, 018h, 00eh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 070h, 018h, 018h, 018h, 00eh, 018h, 018h, 018h, 018h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 00ch, 006h, 07ch, 000h, 000h + db 000h, 000h, 0cch, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 00ch, 018h, 030h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0cch, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 038h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 03ch, 066h, 060h, 060h, 066h, 03ch, 00ch, 006h, 03ch, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 018h, 03ch, 066h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 0c6h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 038h, 06ch, 038h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 018h, 030h, 060h, 000h, 0feh, 066h, 060h, 07ch, 060h, 060h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0cch, 076h, 036h, 07eh, 0d8h, 0d8h, 06eh, 000h, 000h, 000h, 000h + db 000h, 000h, 03eh, 06ch, 0cch, 0cch, 0feh, 0cch, 0cch, 0cch, 0cch, 0ceh, 000h, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 030h, 078h, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 078h, 000h + db 000h, 0c6h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 0c6h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 018h, 018h, 03ch, 066h, 060h, 060h, 060h, 066h, 03ch, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 060h, 0e6h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 03ch, 018h, 07eh, 018h, 07eh, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 0f8h, 0cch, 0cch, 0f8h, 0c4h, 0cch, 0deh, 0cch, 0cch, 0cch, 0c6h, 000h, 000h, 000h, 000h + db 000h, 00eh, 01bh, 018h, 018h, 018h, 07eh, 018h, 018h, 018h, 018h, 018h, 0d8h, 070h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 00ch, 018h, 030h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 000h, 000h, 000h + db 076h, 0dch, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 030h, 000h, 030h, 030h, 060h, 0c0h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 006h, 006h, 006h, 006h, 000h, 000h, 000h, 000h, 000h + db 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 060h, 0dch, 086h, 00ch, 018h, 03eh, 000h, 000h + db 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 066h, 0ceh, 09eh, 03eh, 006h, 006h, 000h, 000h + db 000h, 000h, 018h, 018h, 000h, 018h, 018h, 018h, 03ch, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 036h, 06ch, 0d8h, 06ch, 036h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0d8h, 06ch, 036h, 06ch, 0d8h, 000h, 000h, 000h, 000h, 000h, 000h + db 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h + db 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah + db 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0feh, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 0d8h, 0d8h, 0d8h, 0dch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 078h, 0cch, 0cch, 0cch, 0d8h, 0cch, 0c6h, 0c6h, 0c6h, 0cch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 0c6h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 06ch, 06ch, 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0feh, 0c6h, 060h, 030h, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 0d8h, 0d8h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0c0h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07eh, 018h, 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 06ch, 06ch, 06ch, 0eeh, 000h, 000h, 000h, 000h + db 000h, 000h, 01eh, 030h, 018h, 00ch, 03eh, 066h, 066h, 066h, 066h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 0dbh, 0dbh, 0dbh, 07eh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 003h, 006h, 07eh, 0dbh, 0dbh, 0f3h, 07eh, 060h, 0c0h, 000h, 000h, 000h, 000h + db 000h, 000h, 01ch, 030h, 060h, 060h, 07ch, 060h, 060h, 060h, 030h, 01ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 000h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 00ch, 018h, 030h, 060h, 030h, 018h, 00ch, 000h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 00eh, 01bh, 01bh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h, 0d8h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 07eh, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 00fh, 00ch, 00ch, 00ch, 00ch, 00ch, 0ech, 06ch, 06ch, 03ch, 01ch, 000h, 000h, 000h, 000h + db 000h, 0d8h, 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 070h, 0d8h, 030h, 060h, 0c8h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7b6d LB 0x360 -> off=0x0 cb=000000000000012d uValue=00000000000c33ed 'vgafont14alt' +vgafont14alt: ; 0xc7b6d LB 0x12d + db 01dh, 000h, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h, 000h, 000h, 000h, 022h + db 000h, 063h, 063h, 063h, 022h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02bh, 000h + db 000h, 000h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 02dh, 000h, 000h + db 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04dh, 000h, 000h, 0c3h + db 0e7h, 0ffh, 0dbh, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 000h, 000h, 000h, 054h, 000h, 000h, 0ffh, 0dbh + db 099h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 056h, 000h, 000h, 0c3h, 0c3h, 0c3h + db 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h, 000h, 000h, 000h, 057h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h + db 0dbh, 0dbh, 0ffh, 066h, 066h, 000h, 000h, 000h, 058h, 000h, 000h, 0c3h, 0c3h, 066h, 03ch, 018h + db 03ch, 066h, 0c3h, 0c3h, 000h, 000h, 000h, 059h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 05ah, 000h, 000h, 0ffh, 0c3h, 086h, 00ch, 018h, 030h, 061h + db 0c3h, 0ffh, 000h, 000h, 000h, 06dh, 000h, 000h, 000h, 000h, 000h, 0e6h, 0ffh, 0dbh, 0dbh, 0dbh + db 0dbh, 000h, 000h, 000h, 076h, 000h, 000h, 000h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 000h, 000h, 000h, 077h, 000h, 000h, 000h, 000h, 000h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh, 066h, 000h + db 000h, 000h, 091h, 000h, 000h, 000h, 000h, 06eh, 03bh, 01bh, 07eh, 0d8h, 0dch, 077h, 000h, 000h + db 000h, 09bh, 000h, 018h, 018h, 07eh, 0c3h, 0c0h, 0c0h, 0c3h, 07eh, 018h, 018h, 000h, 000h, 000h + db 09dh, 000h, 000h, 0c3h, 066h, 03ch, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 000h, 000h, 000h, 09eh + db 000h, 0fch, 066h, 066h, 07ch, 062h, 066h, 06fh, 066h, 066h, 0f3h, 000h, 000h, 000h, 0f1h, 000h + db 000h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 000h, 0ffh, 000h, 000h, 000h, 0f6h, 000h, 000h + db 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7c9a LB 0x233 -> off=0x0 cb=0000000000000144 uValue=00000000000c351a 'vgafont16alt' +vgafont16alt: ; 0xc7c9a LB 0x144 + db 01dh, 000h, 000h, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h, 000h, 000h, 000h + db 000h, 030h, 000h, 000h, 03ch, 066h, 0c3h, 0c3h, 0dbh, 0dbh, 0c3h, 0c3h, 066h, 03ch, 000h, 000h + db 000h, 000h, 04dh, 000h, 000h, 0c3h, 0e7h, 0ffh, 0ffh, 0dbh, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 000h + db 000h, 000h, 000h, 054h, 000h, 000h, 0ffh, 0dbh, 099h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch + db 000h, 000h, 000h, 000h, 056h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 066h, 03ch + db 018h, 000h, 000h, 000h, 000h, 057h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh + db 066h, 066h, 000h, 000h, 000h, 000h, 058h, 000h, 000h, 0c3h, 0c3h, 066h, 03ch, 018h, 018h, 03ch + db 066h, 0c3h, 0c3h, 000h, 000h, 000h, 000h, 059h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 05ah, 000h, 000h, 0ffh, 0c3h, 086h, 00ch, 018h + db 030h, 060h, 0c1h, 0c3h, 0ffh, 000h, 000h, 000h, 000h, 06dh, 000h, 000h, 000h, 000h, 000h, 0e6h + db 0ffh, 0dbh, 0dbh, 0dbh, 0dbh, 0dbh, 000h, 000h, 000h, 000h, 076h, 000h, 000h, 000h, 000h, 000h + db 0c3h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h, 000h, 000h, 000h, 000h, 077h, 000h, 000h, 000h, 000h + db 000h, 0c3h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh, 066h, 000h, 000h, 000h, 000h, 078h, 000h, 000h, 000h + db 000h, 000h, 0c3h, 066h, 03ch, 018h, 03ch, 066h, 0c3h, 000h, 000h, 000h, 000h, 091h, 000h, 000h + db 000h, 000h, 000h, 06eh, 03bh, 01bh, 07eh, 0d8h, 0dch, 077h, 000h, 000h, 000h, 000h, 09bh, 000h + db 018h, 018h, 07eh, 0c3h, 0c0h, 0c0h, 0c0h, 0c3h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 09dh + db 000h, 000h, 0c3h, 066h, 03ch, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 09eh, 000h, 0fch, 066h, 066h, 07ch, 062h, 066h, 06fh, 066h, 066h, 066h, 0f3h, 000h, 000h, 000h + db 000h, 0abh, 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 060h, 0ceh, 09bh, 006h, 00ch, 01fh + db 000h, 000h, 0ach, 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 066h, 0ceh, 096h, 03eh, 006h + db 006h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7dde LB 0xef -> off=0x0 cb=0000000000000008 uValue=00000000000c365e '_cga_msr' +_cga_msr: ; 0xc7dde LB 0x8 + db 02ch, 028h, 02dh, 029h, 02ah, 02eh, 01eh, 029h + ; disGetNextSymbol 0xc7de6 LB 0xe7 -> off=0x0 cb=0000000000000008 uValue=00000000000c3666 'line_to_vpti_200' +line_to_vpti_200: ; 0xc7de6 LB 0x8 + db 000h, 001h, 002h, 003h, 0ffh, 0ffh, 0ffh, 007h + ; disGetNextSymbol 0xc7dee LB 0xdf -> off=0x0 cb=0000000000000008 uValue=00000000000c366e 'line_to_vpti_350' +line_to_vpti_350: ; 0xc7dee LB 0x8 + db 013h, 014h, 015h, 016h, 0ffh, 0ffh, 0ffh, 007h + ; disGetNextSymbol 0xc7df6 LB 0xd7 -> off=0x0 cb=0000000000000008 uValue=00000000000c3676 'line_to_vpti_400' +line_to_vpti_400: ; 0xc7df6 LB 0x8 + db 017h, 017h, 018h, 018h, 0ffh, 0ffh, 0ffh, 019h + ; disGetNextSymbol 0xc7dfe LB 0xcf -> off=0x0 cb=0000000000000004 uValue=00000000000c367e 'row_tbl' +row_tbl: ; 0xc7dfe LB 0x4 + dd 02b190e00h + ; disGetNextSymbol 0xc7e02 LB 0xcb -> off=0x0 cb=0000000000000015 uValue=00000000000c3682 '_vbebios_copyright' +_vbebios_copyright: ; 0xc7e02 LB 0x15 + db 'VirtualBox VESA BIOS', 000h + ; disGetNextSymbol 0xc7e17 LB 0xb6 -> off=0x0 cb=000000000000001d uValue=00000000000c3697 '_vbebios_vendor_name' +_vbebios_vendor_name: ; 0xc7e17 LB 0x1d + db 'Oracle and/or its affiliates', 000h + ; disGetNextSymbol 0xc7e34 LB 0x99 -> off=0x0 cb=0000000000000021 uValue=00000000000c36b4 '_vbebios_product_name' +_vbebios_product_name: ; 0xc7e34 LB 0x21 + db 'Oracle VM VirtualBox VBE Adapter', 000h + ; disGetNextSymbol 0xc7e55 LB 0x78 -> off=0x0 cb=0000000000000024 uValue=00000000000c36d5 '_vbebios_product_revision' +_vbebios_product_revision: ; 0xc7e55 LB 0x24 + db 'Oracle VM VirtualBox Version 7.0.14', 000h + ; disGetNextSymbol 0xc7e79 LB 0x54 -> off=0x0 cb=000000000000002b uValue=00000000000c36f9 '_vbebios_info_string' +_vbebios_info_string: ; 0xc7e79 LB 0x2b + db 'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h + ; disGetNextSymbol 0xc7ea4 LB 0x29 -> off=0x0 cb=0000000000000029 uValue=00000000000c3724 '_no_vbebios_info_string' +_no_vbebios_info_string: ; 0xc7ea4 LB 0x29 + db 'No VirtualBox VBE support available!', 00dh, 00ah, 00dh, 00ah, 000h + + ; Padding 0x1 bytes at 0xc7ecd + db 001h + +section CONST progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP + +section CONST2 progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP + + ; Padding 0x132 bytes at 0xc7ece + db 000h, 000h, 000h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 02fh, 068h, 06fh, 06dh, 065h + db 02fh, 073h, 062h, 075h, 072h, 063h, 068h, 069h, 06ch, 02fh, 076h, 062h, 05fh, 073h, 072h, 063h + db 02fh, 062h, 072h, 061h, 06eh, 063h, 068h, 065h, 073h, 02fh, 056h, 042h, 06fh, 078h, 02dh, 037h + db 02eh, 030h, 02fh, 06fh, 075h, 074h, 02fh, 06ch, 069h, 06eh, 075h, 078h, 02eh, 061h, 06dh, 064h + db 036h, 034h, 02fh, 072h, 065h, 06ch, 065h, 061h, 073h, 065h, 02fh, 06fh, 062h, 06ah, 02fh, 056h + db 042h, 06fh, 078h, 056h, 067h, 061h, 042h, 069h, 06fh, 073h, 033h, 038h, 036h, 02fh, 056h, 042h + db 06fh, 078h, 056h, 067h, 061h, 042h, 069h, 06fh, 073h, 033h, 038h, 036h, 02eh, 073h, 079h, 06dh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 057h diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum new file mode 100644 index 00000000..d0e0691d --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum @@ -0,0 +1 @@ +a0e84ee6aab110901a8d59aa1451cfd2 *VBoxVgaBios386.rom diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm new file mode 100644 index 00000000..89fd1abc --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm @@ -0,0 +1,9408 @@ +; $Id: VBoxVgaBiosAlternative8086.asm $ +;; @file +; Auto Generated source file. Do not edit. +; + +; +; Source file: vgarom.asm +; +; ============================================================================================ +; +; Copyright (C) 2001,2002 the LGPL VGABios developers Team +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this library; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; ============================================================================================ +; +; This VGA Bios is specific to the plex86/bochs Emulated VGA card. +; You can NOT drive any physical vga card with it. +; +; ============================================================================================ +; + +; +; Source file: vberom.asm +; +; ============================================================================================ +; +; Copyright (C) 2002 Jeroen Janssen +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this library; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; ============================================================================================ +; +; This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +; You can NOT drive any physical vga card with it. +; +; ============================================================================================ +; +; This VBE Bios is based on information taken from : +; - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +; +; ============================================================================================ + +; +; Source file: vgabios.c +; +; // ============================================================================================ +; +; vgabios.c +; +; // ============================================================================================ +; // +; // Copyright (C) 2001,2002 the LGPL VGABios developers Team +; // +; // This library is free software; you can redistribute it and/or +; // modify it under the terms of the GNU Lesser General Public +; // License as published by the Free Software Foundation; either +; // version 2 of the License, or (at your option) any later version. +; // +; // This library is distributed in the hope that it will be useful, +; // but WITHOUT ANY WARRANTY; without even the implied warranty of +; // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; // Lesser General Public License for more details. +; // +; // You should have received a copy of the GNU Lesser General Public +; // License along with this library; if not, write to the Free Software +; // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; // +; // ============================================================================================ +; // +; // This VGA Bios is specific to the plex86/bochs Emulated VGA card. +; // You can NOT drive any physical vga card with it. +; // +; // ============================================================================================ +; // +; // This file contains code ripped from : +; // - rombios.c of plex86 +; // +; // This VGA Bios contains fonts from : +; // - fntcol16.zip (c) by Joseph Gil avalable at : +; // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip +; // These fonts are public domain +; // +; // This VGA Bios is based on information taken from : +; // - Kevin Lawton's vga card emulation for bochs/plex86 +; // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html +; // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/ +; // - Michael Abrash's Graphics Programming Black Book +; // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex +; // - DOSEMU 1.0.1 source code for several tables values and formulas +; // +; // Thanks for patches, comments and ideas to : +; // - techt@pikeonline.net +; // +; // ============================================================================================ + +; +; Source file: vbe.c +; +; // ============================================================================================ +; // +; // Copyright (C) 2002 Jeroen Janssen +; // +; // This library is free software; you can redistribute it and/or +; // modify it under the terms of the GNU Lesser General Public +; // License as published by the Free Software Foundation; either +; // version 2 of the License, or (at your option) any later version. +; // +; // This library is distributed in the hope that it will be useful, +; // but WITHOUT ANY WARRANTY; without even the implied warranty of +; // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; // Lesser General Public License for more details. +; // +; // You should have received a copy of the GNU Lesser General Public +; // License along with this library; if not, write to the Free Software +; // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; // +; // ============================================================================================ +; // +; // This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +; // You can NOT drive any physical vga card with it. +; // +; // ============================================================================================ +; // +; // This VBE Bios is based on information taken from : +; // - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +; // +; // ============================================================================================ + +; +; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice +; other than GPL or LGPL is available it will apply instead, Oracle elects to use only +; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where +; a choice of LGPL license versions is made available with the language indicating +; that LGPLv2 or any later version may be used, or where a choice of which version +; of the LGPL is applied is otherwise unspecified. +; + + + + + +section VGAROM progbits vstart=0x0 align=1 ; size=0x94f class=CODE group=AUTO + ; disGetNextSymbol 0xc0000 LB 0x94f -> off=0x28 cb=0000000000000578 uValue=00000000000c0028 'vgabios_int10_handler' + db 055h, 0aah, 040h, 0ebh, 01dh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 049h, 042h + db 04dh, 000h, 00eh, 01fh, 0fch, 0e9h, 03eh, 00ah +vgabios_int10_handler: ; 0xc0028 LB 0x578 + pushfw ; 9c ; 0xc0028 vgarom.asm:91 + cmp ah, 00fh ; 80 fc 0f ; 0xc0029 vgarom.asm:104 + jne short 00034h ; 75 06 ; 0xc002c vgarom.asm:105 + call 0018dh ; e8 5c 01 ; 0xc002e vgarom.asm:106 + jmp near 000fdh ; e9 c9 00 ; 0xc0031 vgarom.asm:107 + cmp ah, 01ah ; 80 fc 1a ; 0xc0034 vgarom.asm:109 + jne short 0003fh ; 75 06 ; 0xc0037 vgarom.asm:110 + call 00560h ; e8 24 05 ; 0xc0039 vgarom.asm:111 + jmp near 000fdh ; e9 be 00 ; 0xc003c vgarom.asm:112 + cmp ah, 00bh ; 80 fc 0b ; 0xc003f vgarom.asm:114 + jne short 0004ah ; 75 06 ; 0xc0042 vgarom.asm:115 + call 000ffh ; e8 b8 00 ; 0xc0044 vgarom.asm:116 + jmp near 000fdh ; e9 b3 00 ; 0xc0047 vgarom.asm:117 + cmp ax, 01103h ; 3d 03 11 ; 0xc004a vgarom.asm:119 + jne short 00055h ; 75 06 ; 0xc004d vgarom.asm:120 + call 00454h ; e8 02 04 ; 0xc004f vgarom.asm:121 + jmp near 000fdh ; e9 a8 00 ; 0xc0052 vgarom.asm:122 + cmp ah, 012h ; 80 fc 12 ; 0xc0055 vgarom.asm:124 + jne short 00099h ; 75 3f ; 0xc0058 vgarom.asm:125 + cmp bl, 010h ; 80 fb 10 ; 0xc005a vgarom.asm:126 + jne short 00065h ; 75 06 ; 0xc005d vgarom.asm:127 + call 00461h ; e8 ff 03 ; 0xc005f vgarom.asm:128 + jmp near 000fdh ; e9 98 00 ; 0xc0062 vgarom.asm:129 + cmp bl, 030h ; 80 fb 30 ; 0xc0065 vgarom.asm:131 + jne short 00070h ; 75 06 ; 0xc0068 vgarom.asm:132 + call 00484h ; e8 17 04 ; 0xc006a vgarom.asm:133 + jmp near 000fdh ; e9 8d 00 ; 0xc006d vgarom.asm:134 + cmp bl, 031h ; 80 fb 31 ; 0xc0070 vgarom.asm:136 + jne short 0007bh ; 75 06 ; 0xc0073 vgarom.asm:137 + call 004d7h ; e8 5f 04 ; 0xc0075 vgarom.asm:138 + jmp near 000fdh ; e9 82 00 ; 0xc0078 vgarom.asm:139 + cmp bl, 032h ; 80 fb 32 ; 0xc007b vgarom.asm:141 + jne short 00085h ; 75 05 ; 0xc007e vgarom.asm:142 + call 004fch ; e8 79 04 ; 0xc0080 vgarom.asm:143 + jmp short 000fdh ; eb 78 ; 0xc0083 vgarom.asm:144 + cmp bl, 033h ; 80 fb 33 ; 0xc0085 vgarom.asm:146 + jne short 0008fh ; 75 05 ; 0xc0088 vgarom.asm:147 + call 0051ah ; e8 8d 04 ; 0xc008a vgarom.asm:148 + jmp short 000fdh ; eb 6e ; 0xc008d vgarom.asm:149 + cmp bl, 034h ; 80 fb 34 ; 0xc008f vgarom.asm:151 + jne short 000e3h ; 75 4f ; 0xc0092 vgarom.asm:152 + call 0053eh ; e8 a7 04 ; 0xc0094 vgarom.asm:153 + jmp short 000fdh ; eb 64 ; 0xc0097 vgarom.asm:154 + cmp ax, 0101bh ; 3d 1b 10 ; 0xc0099 vgarom.asm:156 + je short 000e3h ; 74 45 ; 0xc009c vgarom.asm:157 + cmp ah, 010h ; 80 fc 10 ; 0xc009e vgarom.asm:158 + jne short 000a8h ; 75 05 ; 0xc00a1 vgarom.asm:162 + call 001b4h ; e8 0e 01 ; 0xc00a3 vgarom.asm:164 + jmp short 000fdh ; eb 55 ; 0xc00a6 vgarom.asm:165 + cmp ah, 04fh ; 80 fc 4f ; 0xc00a8 vgarom.asm:168 + jne short 000e3h ; 75 36 ; 0xc00ab vgarom.asm:169 + cmp AL, strict byte 003h ; 3c 03 ; 0xc00ad vgarom.asm:170 + jne short 000b6h ; 75 05 ; 0xc00af vgarom.asm:171 + call 0080bh ; e8 57 07 ; 0xc00b1 vgarom.asm:172 + jmp short 000fdh ; eb 47 ; 0xc00b4 vgarom.asm:173 + cmp AL, strict byte 005h ; 3c 05 ; 0xc00b6 vgarom.asm:175 + jne short 000bfh ; 75 05 ; 0xc00b8 vgarom.asm:176 + call 00830h ; e8 73 07 ; 0xc00ba vgarom.asm:177 + jmp short 000fdh ; eb 3e ; 0xc00bd vgarom.asm:178 + cmp AL, strict byte 007h ; 3c 07 ; 0xc00bf vgarom.asm:180 + jne short 000c8h ; 75 05 ; 0xc00c1 vgarom.asm:181 + call 0085dh ; e8 97 07 ; 0xc00c3 vgarom.asm:182 + jmp short 000fdh ; eb 35 ; 0xc00c6 vgarom.asm:183 + cmp AL, strict byte 008h ; 3c 08 ; 0xc00c8 vgarom.asm:185 + jne short 000d1h ; 75 05 ; 0xc00ca vgarom.asm:186 + call 00891h ; e8 c2 07 ; 0xc00cc vgarom.asm:187 + jmp short 000fdh ; eb 2c ; 0xc00cf vgarom.asm:188 + cmp AL, strict byte 009h ; 3c 09 ; 0xc00d1 vgarom.asm:190 + jne short 000dah ; 75 05 ; 0xc00d3 vgarom.asm:191 + call 008c8h ; e8 f0 07 ; 0xc00d5 vgarom.asm:192 + jmp short 000fdh ; eb 23 ; 0xc00d8 vgarom.asm:193 + cmp AL, strict byte 00ah ; 3c 0a ; 0xc00da vgarom.asm:195 + jne short 000e3h ; 75 05 ; 0xc00dc vgarom.asm:196 + call 0093bh ; e8 5a 08 ; 0xc00de vgarom.asm:197 + jmp short 000fdh ; eb 1a ; 0xc00e1 vgarom.asm:198 + push ES ; 06 ; 0xc00e3 vgarom.asm:202 + push DS ; 1e ; 0xc00e4 vgarom.asm:203 + push ax ; 50 ; 0xc00e5 vgarom.asm:109 + push cx ; 51 ; 0xc00e6 vgarom.asm:110 + push dx ; 52 ; 0xc00e7 vgarom.asm:111 + push bx ; 53 ; 0xc00e8 vgarom.asm:112 + push sp ; 54 ; 0xc00e9 vgarom.asm:113 + push bp ; 55 ; 0xc00ea vgarom.asm:114 + push si ; 56 ; 0xc00eb vgarom.asm:115 + push di ; 57 ; 0xc00ec vgarom.asm:116 + push CS ; 0e ; 0xc00ed vgarom.asm:207 + pop DS ; 1f ; 0xc00ee vgarom.asm:208 + cld ; fc ; 0xc00ef vgarom.asm:209 + call 0394bh ; e8 58 38 ; 0xc00f0 vgarom.asm:210 + pop di ; 5f ; 0xc00f3 vgarom.asm:126 + pop si ; 5e ; 0xc00f4 vgarom.asm:127 + pop bp ; 5d ; 0xc00f5 vgarom.asm:128 + pop bx ; 5b ; 0xc00f6 vgarom.asm:129 + pop bx ; 5b ; 0xc00f7 vgarom.asm:130 + pop dx ; 5a ; 0xc00f8 vgarom.asm:131 + pop cx ; 59 ; 0xc00f9 vgarom.asm:132 + pop ax ; 58 ; 0xc00fa vgarom.asm:133 + pop DS ; 1f ; 0xc00fb vgarom.asm:213 + pop ES ; 07 ; 0xc00fc vgarom.asm:214 + popfw ; 9d ; 0xc00fd vgarom.asm:216 + iret ; cf ; 0xc00fe vgarom.asm:217 + cmp bh, 000h ; 80 ff 00 ; 0xc00ff vgarom.asm:222 + je short 0010ah ; 74 06 ; 0xc0102 vgarom.asm:223 + cmp bh, 001h ; 80 ff 01 ; 0xc0104 vgarom.asm:224 + je short 0015bh ; 74 52 ; 0xc0107 vgarom.asm:225 + retn ; c3 ; 0xc0109 vgarom.asm:229 + push ax ; 50 ; 0xc010a vgarom.asm:231 + push bx ; 53 ; 0xc010b vgarom.asm:232 + push cx ; 51 ; 0xc010c vgarom.asm:233 + push dx ; 52 ; 0xc010d vgarom.asm:234 + push DS ; 1e ; 0xc010e vgarom.asm:235 + mov dx, strict word 00040h ; ba 40 00 ; 0xc010f vgarom.asm:236 + mov ds, dx ; 8e da ; 0xc0112 vgarom.asm:237 + mov dx, 003dah ; ba da 03 ; 0xc0114 vgarom.asm:238 + in AL, DX ; ec ; 0xc0117 vgarom.asm:239 + cmp byte [word 00049h], 003h ; 80 3e 49 00 03 ; 0xc0118 vgarom.asm:240 + jbe short 0014eh ; 76 2f ; 0xc011d vgarom.asm:241 + mov dx, 003c0h ; ba c0 03 ; 0xc011f vgarom.asm:242 + mov AL, strict byte 000h ; b0 00 ; 0xc0122 vgarom.asm:243 + out DX, AL ; ee ; 0xc0124 vgarom.asm:244 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0125 vgarom.asm:245 + and AL, strict byte 00fh ; 24 0f ; 0xc0127 vgarom.asm:246 + test AL, strict byte 008h ; a8 08 ; 0xc0129 vgarom.asm:247 + je short 0012fh ; 74 02 ; 0xc012b vgarom.asm:248 + add AL, strict byte 008h ; 04 08 ; 0xc012d vgarom.asm:249 + out DX, AL ; ee ; 0xc012f vgarom.asm:251 + mov CL, strict byte 001h ; b1 01 ; 0xc0130 vgarom.asm:252 + and bl, 010h ; 80 e3 10 ; 0xc0132 vgarom.asm:253 + mov dx, 003c0h ; ba c0 03 ; 0xc0135 vgarom.asm:255 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc0138 vgarom.asm:256 + out DX, AL ; ee ; 0xc013a vgarom.asm:257 + mov dx, 003c1h ; ba c1 03 ; 0xc013b vgarom.asm:258 + in AL, DX ; ec ; 0xc013e vgarom.asm:259 + and AL, strict byte 0efh ; 24 ef ; 0xc013f vgarom.asm:260 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc0141 vgarom.asm:261 + mov dx, 003c0h ; ba c0 03 ; 0xc0143 vgarom.asm:262 + out DX, AL ; ee ; 0xc0146 vgarom.asm:263 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc0147 vgarom.asm:264 + cmp cl, 004h ; 80 f9 04 ; 0xc0149 vgarom.asm:265 + jne short 00135h ; 75 e7 ; 0xc014c vgarom.asm:266 + mov AL, strict byte 020h ; b0 20 ; 0xc014e vgarom.asm:268 + out DX, AL ; ee ; 0xc0150 vgarom.asm:269 + mov dx, 003dah ; ba da 03 ; 0xc0151 vgarom.asm:271 + in AL, DX ; ec ; 0xc0154 vgarom.asm:272 + pop DS ; 1f ; 0xc0155 vgarom.asm:274 + pop dx ; 5a ; 0xc0156 vgarom.asm:275 + pop cx ; 59 ; 0xc0157 vgarom.asm:276 + pop bx ; 5b ; 0xc0158 vgarom.asm:277 + pop ax ; 58 ; 0xc0159 vgarom.asm:278 + retn ; c3 ; 0xc015a vgarom.asm:279 + push ax ; 50 ; 0xc015b vgarom.asm:281 + push bx ; 53 ; 0xc015c vgarom.asm:282 + push cx ; 51 ; 0xc015d vgarom.asm:283 + push dx ; 52 ; 0xc015e vgarom.asm:284 + mov dx, 003dah ; ba da 03 ; 0xc015f vgarom.asm:285 + in AL, DX ; ec ; 0xc0162 vgarom.asm:286 + mov CL, strict byte 001h ; b1 01 ; 0xc0163 vgarom.asm:287 + and bl, 001h ; 80 e3 01 ; 0xc0165 vgarom.asm:288 + mov dx, 003c0h ; ba c0 03 ; 0xc0168 vgarom.asm:290 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc016b vgarom.asm:291 + out DX, AL ; ee ; 0xc016d vgarom.asm:292 + mov dx, 003c1h ; ba c1 03 ; 0xc016e vgarom.asm:293 + in AL, DX ; ec ; 0xc0171 vgarom.asm:294 + and AL, strict byte 0feh ; 24 fe ; 0xc0172 vgarom.asm:295 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc0174 vgarom.asm:296 + mov dx, 003c0h ; ba c0 03 ; 0xc0176 vgarom.asm:297 + out DX, AL ; ee ; 0xc0179 vgarom.asm:298 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc017a vgarom.asm:299 + cmp cl, 004h ; 80 f9 04 ; 0xc017c vgarom.asm:300 + jne short 00168h ; 75 e7 ; 0xc017f vgarom.asm:301 + mov AL, strict byte 020h ; b0 20 ; 0xc0181 vgarom.asm:302 + out DX, AL ; ee ; 0xc0183 vgarom.asm:303 + mov dx, 003dah ; ba da 03 ; 0xc0184 vgarom.asm:305 + in AL, DX ; ec ; 0xc0187 vgarom.asm:306 + pop dx ; 5a ; 0xc0188 vgarom.asm:308 + pop cx ; 59 ; 0xc0189 vgarom.asm:309 + pop bx ; 5b ; 0xc018a vgarom.asm:310 + pop ax ; 58 ; 0xc018b vgarom.asm:311 + retn ; c3 ; 0xc018c vgarom.asm:312 + push DS ; 1e ; 0xc018d vgarom.asm:317 + mov ax, strict word 00040h ; b8 40 00 ; 0xc018e vgarom.asm:318 + mov ds, ax ; 8e d8 ; 0xc0191 vgarom.asm:319 + push bx ; 53 ; 0xc0193 vgarom.asm:320 + mov bx, strict word 00062h ; bb 62 00 ; 0xc0194 vgarom.asm:321 + mov al, byte [bx] ; 8a 07 ; 0xc0197 vgarom.asm:322 + pop bx ; 5b ; 0xc0199 vgarom.asm:323 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc019a vgarom.asm:324 + push bx ; 53 ; 0xc019c vgarom.asm:325 + mov bx, 00087h ; bb 87 00 ; 0xc019d vgarom.asm:326 + mov ah, byte [bx] ; 8a 27 ; 0xc01a0 vgarom.asm:327 + and ah, 080h ; 80 e4 80 ; 0xc01a2 vgarom.asm:328 + mov bx, strict word 00049h ; bb 49 00 ; 0xc01a5 vgarom.asm:329 + mov al, byte [bx] ; 8a 07 ; 0xc01a8 vgarom.asm:330 + db 00ah, 0c4h + ; or al, ah ; 0a c4 ; 0xc01aa vgarom.asm:331 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc01ac vgarom.asm:332 + mov ah, byte [bx] ; 8a 27 ; 0xc01af vgarom.asm:333 + pop bx ; 5b ; 0xc01b1 vgarom.asm:334 + pop DS ; 1f ; 0xc01b2 vgarom.asm:335 + retn ; c3 ; 0xc01b3 vgarom.asm:336 + cmp AL, strict byte 000h ; 3c 00 ; 0xc01b4 vgarom.asm:341 + jne short 001bah ; 75 02 ; 0xc01b6 vgarom.asm:342 + jmp short 0021bh ; eb 61 ; 0xc01b8 vgarom.asm:343 + cmp AL, strict byte 001h ; 3c 01 ; 0xc01ba vgarom.asm:345 + jne short 001c0h ; 75 02 ; 0xc01bc vgarom.asm:346 + jmp short 00239h ; eb 79 ; 0xc01be vgarom.asm:347 + cmp AL, strict byte 002h ; 3c 02 ; 0xc01c0 vgarom.asm:349 + jne short 001c6h ; 75 02 ; 0xc01c2 vgarom.asm:350 + jmp short 00241h ; eb 7b ; 0xc01c4 vgarom.asm:351 + cmp AL, strict byte 003h ; 3c 03 ; 0xc01c6 vgarom.asm:353 + jne short 001cdh ; 75 03 ; 0xc01c8 vgarom.asm:354 + jmp near 00272h ; e9 a5 00 ; 0xc01ca vgarom.asm:355 + cmp AL, strict byte 007h ; 3c 07 ; 0xc01cd vgarom.asm:357 + jne short 001d4h ; 75 03 ; 0xc01cf vgarom.asm:358 + jmp near 0029fh ; e9 cb 00 ; 0xc01d1 vgarom.asm:359 + cmp AL, strict byte 008h ; 3c 08 ; 0xc01d4 vgarom.asm:361 + jne short 001dbh ; 75 03 ; 0xc01d6 vgarom.asm:362 + jmp near 002c7h ; e9 ec 00 ; 0xc01d8 vgarom.asm:363 + cmp AL, strict byte 009h ; 3c 09 ; 0xc01db vgarom.asm:365 + jne short 001e2h ; 75 03 ; 0xc01dd vgarom.asm:366 + jmp near 002d5h ; e9 f3 00 ; 0xc01df vgarom.asm:367 + cmp AL, strict byte 010h ; 3c 10 ; 0xc01e2 vgarom.asm:369 + jne short 001e9h ; 75 03 ; 0xc01e4 vgarom.asm:370 + jmp near 0031ah ; e9 31 01 ; 0xc01e6 vgarom.asm:371 + cmp AL, strict byte 012h ; 3c 12 ; 0xc01e9 vgarom.asm:373 + jne short 001f0h ; 75 03 ; 0xc01eb vgarom.asm:374 + jmp near 00333h ; e9 43 01 ; 0xc01ed vgarom.asm:375 + cmp AL, strict byte 013h ; 3c 13 ; 0xc01f0 vgarom.asm:377 + jne short 001f7h ; 75 03 ; 0xc01f2 vgarom.asm:378 + jmp near 0035bh ; e9 64 01 ; 0xc01f4 vgarom.asm:379 + cmp AL, strict byte 015h ; 3c 15 ; 0xc01f7 vgarom.asm:381 + jne short 001feh ; 75 03 ; 0xc01f9 vgarom.asm:382 + jmp near 003aeh ; e9 b0 01 ; 0xc01fb vgarom.asm:383 + cmp AL, strict byte 017h ; 3c 17 ; 0xc01fe vgarom.asm:385 + jne short 00205h ; 75 03 ; 0xc0200 vgarom.asm:386 + jmp near 003c9h ; e9 c4 01 ; 0xc0202 vgarom.asm:387 + cmp AL, strict byte 018h ; 3c 18 ; 0xc0205 vgarom.asm:389 + jne short 0020ch ; 75 03 ; 0xc0207 vgarom.asm:390 + jmp near 003f1h ; e9 e5 01 ; 0xc0209 vgarom.asm:391 + cmp AL, strict byte 019h ; 3c 19 ; 0xc020c vgarom.asm:393 + jne short 00213h ; 75 03 ; 0xc020e vgarom.asm:394 + jmp near 003fch ; e9 e9 01 ; 0xc0210 vgarom.asm:395 + cmp AL, strict byte 01ah ; 3c 1a ; 0xc0213 vgarom.asm:397 + jne short 0021ah ; 75 03 ; 0xc0215 vgarom.asm:398 + jmp near 00407h ; e9 ed 01 ; 0xc0217 vgarom.asm:399 + retn ; c3 ; 0xc021a vgarom.asm:404 + cmp bl, 014h ; 80 fb 14 ; 0xc021b vgarom.asm:407 + jnbe short 00238h ; 77 18 ; 0xc021e vgarom.asm:408 + push ax ; 50 ; 0xc0220 vgarom.asm:409 + push dx ; 52 ; 0xc0221 vgarom.asm:410 + mov dx, 003dah ; ba da 03 ; 0xc0222 vgarom.asm:411 + in AL, DX ; ec ; 0xc0225 vgarom.asm:412 + mov dx, 003c0h ; ba c0 03 ; 0xc0226 vgarom.asm:413 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc0229 vgarom.asm:414 + out DX, AL ; ee ; 0xc022b vgarom.asm:415 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc022c vgarom.asm:416 + out DX, AL ; ee ; 0xc022e vgarom.asm:417 + mov AL, strict byte 020h ; b0 20 ; 0xc022f vgarom.asm:418 + out DX, AL ; ee ; 0xc0231 vgarom.asm:419 + mov dx, 003dah ; ba da 03 ; 0xc0232 vgarom.asm:421 + in AL, DX ; ec ; 0xc0235 vgarom.asm:422 + pop dx ; 5a ; 0xc0236 vgarom.asm:424 + pop ax ; 58 ; 0xc0237 vgarom.asm:425 + retn ; c3 ; 0xc0238 vgarom.asm:427 + push bx ; 53 ; 0xc0239 vgarom.asm:432 + mov BL, strict byte 011h ; b3 11 ; 0xc023a vgarom.asm:433 + call 0021bh ; e8 dc ff ; 0xc023c vgarom.asm:434 + pop bx ; 5b ; 0xc023f vgarom.asm:435 + retn ; c3 ; 0xc0240 vgarom.asm:436 + push ax ; 50 ; 0xc0241 vgarom.asm:441 + push bx ; 53 ; 0xc0242 vgarom.asm:442 + push cx ; 51 ; 0xc0243 vgarom.asm:443 + push dx ; 52 ; 0xc0244 vgarom.asm:444 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc0245 vgarom.asm:445 + mov dx, 003dah ; ba da 03 ; 0xc0247 vgarom.asm:446 + in AL, DX ; ec ; 0xc024a vgarom.asm:447 + mov CL, strict byte 000h ; b1 00 ; 0xc024b vgarom.asm:448 + mov dx, 003c0h ; ba c0 03 ; 0xc024d vgarom.asm:449 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc0250 vgarom.asm:451 + out DX, AL ; ee ; 0xc0252 vgarom.asm:452 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0253 vgarom.asm:453 + out DX, AL ; ee ; 0xc0256 vgarom.asm:454 + inc bx ; 43 ; 0xc0257 vgarom.asm:455 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc0258 vgarom.asm:456 + cmp cl, 010h ; 80 f9 10 ; 0xc025a vgarom.asm:457 + jne short 00250h ; 75 f1 ; 0xc025d vgarom.asm:458 + mov AL, strict byte 011h ; b0 11 ; 0xc025f vgarom.asm:459 + out DX, AL ; ee ; 0xc0261 vgarom.asm:460 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0262 vgarom.asm:461 + out DX, AL ; ee ; 0xc0265 vgarom.asm:462 + mov AL, strict byte 020h ; b0 20 ; 0xc0266 vgarom.asm:463 + out DX, AL ; ee ; 0xc0268 vgarom.asm:464 + mov dx, 003dah ; ba da 03 ; 0xc0269 vgarom.asm:466 + in AL, DX ; ec ; 0xc026c vgarom.asm:467 + pop dx ; 5a ; 0xc026d vgarom.asm:469 + pop cx ; 59 ; 0xc026e vgarom.asm:470 + pop bx ; 5b ; 0xc026f vgarom.asm:471 + pop ax ; 58 ; 0xc0270 vgarom.asm:472 + retn ; c3 ; 0xc0271 vgarom.asm:473 + push ax ; 50 ; 0xc0272 vgarom.asm:478 + push bx ; 53 ; 0xc0273 vgarom.asm:479 + push dx ; 52 ; 0xc0274 vgarom.asm:480 + mov dx, 003dah ; ba da 03 ; 0xc0275 vgarom.asm:481 + in AL, DX ; ec ; 0xc0278 vgarom.asm:482 + mov dx, 003c0h ; ba c0 03 ; 0xc0279 vgarom.asm:483 + mov AL, strict byte 010h ; b0 10 ; 0xc027c vgarom.asm:484 + out DX, AL ; ee ; 0xc027e vgarom.asm:485 + mov dx, 003c1h ; ba c1 03 ; 0xc027f vgarom.asm:486 + in AL, DX ; ec ; 0xc0282 vgarom.asm:487 + and AL, strict byte 0f7h ; 24 f7 ; 0xc0283 vgarom.asm:488 + and bl, 001h ; 80 e3 01 ; 0xc0285 vgarom.asm:489 + sal bl, 1 ; d0 e3 ; 0xc0288 vgarom.asm:493 + sal bl, 1 ; d0 e3 ; 0xc028a vgarom.asm:494 + sal bl, 1 ; d0 e3 ; 0xc028c vgarom.asm:495 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc028e vgarom.asm:497 + mov dx, 003c0h ; ba c0 03 ; 0xc0290 vgarom.asm:498 + out DX, AL ; ee ; 0xc0293 vgarom.asm:499 + mov AL, strict byte 020h ; b0 20 ; 0xc0294 vgarom.asm:500 + out DX, AL ; ee ; 0xc0296 vgarom.asm:501 + mov dx, 003dah ; ba da 03 ; 0xc0297 vgarom.asm:503 + in AL, DX ; ec ; 0xc029a vgarom.asm:504 + pop dx ; 5a ; 0xc029b vgarom.asm:506 + pop bx ; 5b ; 0xc029c vgarom.asm:507 + pop ax ; 58 ; 0xc029d vgarom.asm:508 + retn ; c3 ; 0xc029e vgarom.asm:509 + cmp bl, 014h ; 80 fb 14 ; 0xc029f vgarom.asm:514 + jnbe short 002c6h ; 77 22 ; 0xc02a2 vgarom.asm:515 + push ax ; 50 ; 0xc02a4 vgarom.asm:516 + push dx ; 52 ; 0xc02a5 vgarom.asm:517 + mov dx, 003dah ; ba da 03 ; 0xc02a6 vgarom.asm:518 + in AL, DX ; ec ; 0xc02a9 vgarom.asm:519 + mov dx, 003c0h ; ba c0 03 ; 0xc02aa vgarom.asm:520 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc02ad vgarom.asm:521 + out DX, AL ; ee ; 0xc02af vgarom.asm:522 + mov dx, 003c1h ; ba c1 03 ; 0xc02b0 vgarom.asm:523 + in AL, DX ; ec ; 0xc02b3 vgarom.asm:524 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc02b4 vgarom.asm:525 + mov dx, 003dah ; ba da 03 ; 0xc02b6 vgarom.asm:526 + in AL, DX ; ec ; 0xc02b9 vgarom.asm:527 + mov dx, 003c0h ; ba c0 03 ; 0xc02ba vgarom.asm:528 + mov AL, strict byte 020h ; b0 20 ; 0xc02bd vgarom.asm:529 + out DX, AL ; ee ; 0xc02bf vgarom.asm:530 + mov dx, 003dah ; ba da 03 ; 0xc02c0 vgarom.asm:532 + in AL, DX ; ec ; 0xc02c3 vgarom.asm:533 + pop dx ; 5a ; 0xc02c4 vgarom.asm:535 + pop ax ; 58 ; 0xc02c5 vgarom.asm:536 + retn ; c3 ; 0xc02c6 vgarom.asm:538 + push ax ; 50 ; 0xc02c7 vgarom.asm:543 + push bx ; 53 ; 0xc02c8 vgarom.asm:544 + mov BL, strict byte 011h ; b3 11 ; 0xc02c9 vgarom.asm:545 + call 0029fh ; e8 d1 ff ; 0xc02cb vgarom.asm:546 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc02ce vgarom.asm:547 + pop bx ; 5b ; 0xc02d0 vgarom.asm:548 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc02d1 vgarom.asm:549 + pop ax ; 58 ; 0xc02d3 vgarom.asm:550 + retn ; c3 ; 0xc02d4 vgarom.asm:551 + push ax ; 50 ; 0xc02d5 vgarom.asm:556 + push bx ; 53 ; 0xc02d6 vgarom.asm:557 + push cx ; 51 ; 0xc02d7 vgarom.asm:558 + push dx ; 52 ; 0xc02d8 vgarom.asm:559 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc02d9 vgarom.asm:560 + mov CL, strict byte 000h ; b1 00 ; 0xc02db vgarom.asm:561 + mov dx, 003dah ; ba da 03 ; 0xc02dd vgarom.asm:563 + in AL, DX ; ec ; 0xc02e0 vgarom.asm:564 + mov dx, 003c0h ; ba c0 03 ; 0xc02e1 vgarom.asm:565 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc02e4 vgarom.asm:566 + out DX, AL ; ee ; 0xc02e6 vgarom.asm:567 + mov dx, 003c1h ; ba c1 03 ; 0xc02e7 vgarom.asm:568 + in AL, DX ; ec ; 0xc02ea vgarom.asm:569 + mov byte [es:bx], al ; 26 88 07 ; 0xc02eb vgarom.asm:570 + inc bx ; 43 ; 0xc02ee vgarom.asm:571 + db 0feh, 0c1h + ; inc cl ; fe c1 ; 0xc02ef vgarom.asm:572 + cmp cl, 010h ; 80 f9 10 ; 0xc02f1 vgarom.asm:573 + jne short 002ddh ; 75 e7 ; 0xc02f4 vgarom.asm:574 + mov dx, 003dah ; ba da 03 ; 0xc02f6 vgarom.asm:575 + in AL, DX ; ec ; 0xc02f9 vgarom.asm:576 + mov dx, 003c0h ; ba c0 03 ; 0xc02fa vgarom.asm:577 + mov AL, strict byte 011h ; b0 11 ; 0xc02fd vgarom.asm:578 + out DX, AL ; ee ; 0xc02ff vgarom.asm:579 + mov dx, 003c1h ; ba c1 03 ; 0xc0300 vgarom.asm:580 + in AL, DX ; ec ; 0xc0303 vgarom.asm:581 + mov byte [es:bx], al ; 26 88 07 ; 0xc0304 vgarom.asm:582 + mov dx, 003dah ; ba da 03 ; 0xc0307 vgarom.asm:583 + in AL, DX ; ec ; 0xc030a vgarom.asm:584 + mov dx, 003c0h ; ba c0 03 ; 0xc030b vgarom.asm:585 + mov AL, strict byte 020h ; b0 20 ; 0xc030e vgarom.asm:586 + out DX, AL ; ee ; 0xc0310 vgarom.asm:587 + mov dx, 003dah ; ba da 03 ; 0xc0311 vgarom.asm:589 + in AL, DX ; ec ; 0xc0314 vgarom.asm:590 + pop dx ; 5a ; 0xc0315 vgarom.asm:592 + pop cx ; 59 ; 0xc0316 vgarom.asm:593 + pop bx ; 5b ; 0xc0317 vgarom.asm:594 + pop ax ; 58 ; 0xc0318 vgarom.asm:595 + retn ; c3 ; 0xc0319 vgarom.asm:596 + push ax ; 50 ; 0xc031a vgarom.asm:601 + push dx ; 52 ; 0xc031b vgarom.asm:602 + mov dx, 003c8h ; ba c8 03 ; 0xc031c vgarom.asm:603 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc031f vgarom.asm:604 + out DX, AL ; ee ; 0xc0321 vgarom.asm:605 + mov dx, 003c9h ; ba c9 03 ; 0xc0322 vgarom.asm:606 + pop ax ; 58 ; 0xc0325 vgarom.asm:607 + push ax ; 50 ; 0xc0326 vgarom.asm:608 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc0327 vgarom.asm:609 + out DX, AL ; ee ; 0xc0329 vgarom.asm:610 + db 08ah, 0c5h + ; mov al, ch ; 8a c5 ; 0xc032a vgarom.asm:611 + out DX, AL ; ee ; 0xc032c vgarom.asm:612 + db 08ah, 0c1h + ; mov al, cl ; 8a c1 ; 0xc032d vgarom.asm:613 + out DX, AL ; ee ; 0xc032f vgarom.asm:614 + pop dx ; 5a ; 0xc0330 vgarom.asm:615 + pop ax ; 58 ; 0xc0331 vgarom.asm:616 + retn ; c3 ; 0xc0332 vgarom.asm:617 + push ax ; 50 ; 0xc0333 vgarom.asm:622 + push bx ; 53 ; 0xc0334 vgarom.asm:623 + push cx ; 51 ; 0xc0335 vgarom.asm:624 + push dx ; 52 ; 0xc0336 vgarom.asm:625 + mov dx, 003c8h ; ba c8 03 ; 0xc0337 vgarom.asm:626 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc033a vgarom.asm:627 + out DX, AL ; ee ; 0xc033c vgarom.asm:628 + pop dx ; 5a ; 0xc033d vgarom.asm:629 + push dx ; 52 ; 0xc033e vgarom.asm:630 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc033f vgarom.asm:631 + mov dx, 003c9h ; ba c9 03 ; 0xc0341 vgarom.asm:632 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0344 vgarom.asm:634 + out DX, AL ; ee ; 0xc0347 vgarom.asm:635 + inc bx ; 43 ; 0xc0348 vgarom.asm:636 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0349 vgarom.asm:637 + out DX, AL ; ee ; 0xc034c vgarom.asm:638 + inc bx ; 43 ; 0xc034d vgarom.asm:639 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc034e vgarom.asm:640 + out DX, AL ; ee ; 0xc0351 vgarom.asm:641 + inc bx ; 43 ; 0xc0352 vgarom.asm:642 + dec cx ; 49 ; 0xc0353 vgarom.asm:643 + jne short 00344h ; 75 ee ; 0xc0354 vgarom.asm:644 + pop dx ; 5a ; 0xc0356 vgarom.asm:645 + pop cx ; 59 ; 0xc0357 vgarom.asm:646 + pop bx ; 5b ; 0xc0358 vgarom.asm:647 + pop ax ; 58 ; 0xc0359 vgarom.asm:648 + retn ; c3 ; 0xc035a vgarom.asm:649 + push ax ; 50 ; 0xc035b vgarom.asm:654 + push bx ; 53 ; 0xc035c vgarom.asm:655 + push dx ; 52 ; 0xc035d vgarom.asm:656 + mov dx, 003dah ; ba da 03 ; 0xc035e vgarom.asm:657 + in AL, DX ; ec ; 0xc0361 vgarom.asm:658 + mov dx, 003c0h ; ba c0 03 ; 0xc0362 vgarom.asm:659 + mov AL, strict byte 010h ; b0 10 ; 0xc0365 vgarom.asm:660 + out DX, AL ; ee ; 0xc0367 vgarom.asm:661 + mov dx, 003c1h ; ba c1 03 ; 0xc0368 vgarom.asm:662 + in AL, DX ; ec ; 0xc036b vgarom.asm:663 + and bl, 001h ; 80 e3 01 ; 0xc036c vgarom.asm:664 + jne short 00389h ; 75 18 ; 0xc036f vgarom.asm:665 + and AL, strict byte 07fh ; 24 7f ; 0xc0371 vgarom.asm:666 + sal bh, 1 ; d0 e7 ; 0xc0373 vgarom.asm:670 + sal bh, 1 ; d0 e7 ; 0xc0375 vgarom.asm:671 + sal bh, 1 ; d0 e7 ; 0xc0377 vgarom.asm:672 + sal bh, 1 ; d0 e7 ; 0xc0379 vgarom.asm:673 + sal bh, 1 ; d0 e7 ; 0xc037b vgarom.asm:674 + sal bh, 1 ; d0 e7 ; 0xc037d vgarom.asm:675 + sal bh, 1 ; d0 e7 ; 0xc037f vgarom.asm:676 + db 00ah, 0c7h + ; or al, bh ; 0a c7 ; 0xc0381 vgarom.asm:678 + mov dx, 003c0h ; ba c0 03 ; 0xc0383 vgarom.asm:679 + out DX, AL ; ee ; 0xc0386 vgarom.asm:680 + jmp short 003a3h ; eb 1a ; 0xc0387 vgarom.asm:681 + push ax ; 50 ; 0xc0389 vgarom.asm:683 + mov dx, 003dah ; ba da 03 ; 0xc038a vgarom.asm:684 + in AL, DX ; ec ; 0xc038d vgarom.asm:685 + mov dx, 003c0h ; ba c0 03 ; 0xc038e vgarom.asm:686 + mov AL, strict byte 014h ; b0 14 ; 0xc0391 vgarom.asm:687 + out DX, AL ; ee ; 0xc0393 vgarom.asm:688 + pop ax ; 58 ; 0xc0394 vgarom.asm:689 + and AL, strict byte 080h ; 24 80 ; 0xc0395 vgarom.asm:690 + jne short 0039dh ; 75 04 ; 0xc0397 vgarom.asm:691 + sal bh, 1 ; d0 e7 ; 0xc0399 vgarom.asm:695 + sal bh, 1 ; d0 e7 ; 0xc039b vgarom.asm:696 + and bh, 00fh ; 80 e7 0f ; 0xc039d vgarom.asm:699 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc03a0 vgarom.asm:700 + out DX, AL ; ee ; 0xc03a2 vgarom.asm:701 + mov AL, strict byte 020h ; b0 20 ; 0xc03a3 vgarom.asm:703 + out DX, AL ; ee ; 0xc03a5 vgarom.asm:704 + mov dx, 003dah ; ba da 03 ; 0xc03a6 vgarom.asm:706 + in AL, DX ; ec ; 0xc03a9 vgarom.asm:707 + pop dx ; 5a ; 0xc03aa vgarom.asm:709 + pop bx ; 5b ; 0xc03ab vgarom.asm:710 + pop ax ; 58 ; 0xc03ac vgarom.asm:711 + retn ; c3 ; 0xc03ad vgarom.asm:712 + push ax ; 50 ; 0xc03ae vgarom.asm:717 + push dx ; 52 ; 0xc03af vgarom.asm:718 + mov dx, 003c7h ; ba c7 03 ; 0xc03b0 vgarom.asm:719 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc03b3 vgarom.asm:720 + out DX, AL ; ee ; 0xc03b5 vgarom.asm:721 + pop ax ; 58 ; 0xc03b6 vgarom.asm:722 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc03b7 vgarom.asm:723 + mov dx, 003c9h ; ba c9 03 ; 0xc03b9 vgarom.asm:724 + in AL, DX ; ec ; 0xc03bc vgarom.asm:725 + xchg al, ah ; 86 e0 ; 0xc03bd vgarom.asm:726 + push ax ; 50 ; 0xc03bf vgarom.asm:727 + in AL, DX ; ec ; 0xc03c0 vgarom.asm:728 + db 08ah, 0e8h + ; mov ch, al ; 8a e8 ; 0xc03c1 vgarom.asm:729 + in AL, DX ; ec ; 0xc03c3 vgarom.asm:730 + db 08ah, 0c8h + ; mov cl, al ; 8a c8 ; 0xc03c4 vgarom.asm:731 + pop dx ; 5a ; 0xc03c6 vgarom.asm:732 + pop ax ; 58 ; 0xc03c7 vgarom.asm:733 + retn ; c3 ; 0xc03c8 vgarom.asm:734 + push ax ; 50 ; 0xc03c9 vgarom.asm:739 + push bx ; 53 ; 0xc03ca vgarom.asm:740 + push cx ; 51 ; 0xc03cb vgarom.asm:741 + push dx ; 52 ; 0xc03cc vgarom.asm:742 + mov dx, 003c7h ; ba c7 03 ; 0xc03cd vgarom.asm:743 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc03d0 vgarom.asm:744 + out DX, AL ; ee ; 0xc03d2 vgarom.asm:745 + pop dx ; 5a ; 0xc03d3 vgarom.asm:746 + push dx ; 52 ; 0xc03d4 vgarom.asm:747 + db 08bh, 0dah + ; mov bx, dx ; 8b da ; 0xc03d5 vgarom.asm:748 + mov dx, 003c9h ; ba c9 03 ; 0xc03d7 vgarom.asm:749 + in AL, DX ; ec ; 0xc03da vgarom.asm:751 + mov byte [es:bx], al ; 26 88 07 ; 0xc03db vgarom.asm:752 + inc bx ; 43 ; 0xc03de vgarom.asm:753 + in AL, DX ; ec ; 0xc03df vgarom.asm:754 + mov byte [es:bx], al ; 26 88 07 ; 0xc03e0 vgarom.asm:755 + inc bx ; 43 ; 0xc03e3 vgarom.asm:756 + in AL, DX ; ec ; 0xc03e4 vgarom.asm:757 + mov byte [es:bx], al ; 26 88 07 ; 0xc03e5 vgarom.asm:758 + inc bx ; 43 ; 0xc03e8 vgarom.asm:759 + dec cx ; 49 ; 0xc03e9 vgarom.asm:760 + jne short 003dah ; 75 ee ; 0xc03ea vgarom.asm:761 + pop dx ; 5a ; 0xc03ec vgarom.asm:762 + pop cx ; 59 ; 0xc03ed vgarom.asm:763 + pop bx ; 5b ; 0xc03ee vgarom.asm:764 + pop ax ; 58 ; 0xc03ef vgarom.asm:765 + retn ; c3 ; 0xc03f0 vgarom.asm:766 + push ax ; 50 ; 0xc03f1 vgarom.asm:771 + push dx ; 52 ; 0xc03f2 vgarom.asm:772 + mov dx, 003c6h ; ba c6 03 ; 0xc03f3 vgarom.asm:773 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc03f6 vgarom.asm:774 + out DX, AL ; ee ; 0xc03f8 vgarom.asm:775 + pop dx ; 5a ; 0xc03f9 vgarom.asm:776 + pop ax ; 58 ; 0xc03fa vgarom.asm:777 + retn ; c3 ; 0xc03fb vgarom.asm:778 + push ax ; 50 ; 0xc03fc vgarom.asm:783 + push dx ; 52 ; 0xc03fd vgarom.asm:784 + mov dx, 003c6h ; ba c6 03 ; 0xc03fe vgarom.asm:785 + in AL, DX ; ec ; 0xc0401 vgarom.asm:786 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc0402 vgarom.asm:787 + pop dx ; 5a ; 0xc0404 vgarom.asm:788 + pop ax ; 58 ; 0xc0405 vgarom.asm:789 + retn ; c3 ; 0xc0406 vgarom.asm:790 + push ax ; 50 ; 0xc0407 vgarom.asm:795 + push dx ; 52 ; 0xc0408 vgarom.asm:796 + mov dx, 003dah ; ba da 03 ; 0xc0409 vgarom.asm:797 + in AL, DX ; ec ; 0xc040c vgarom.asm:798 + mov dx, 003c0h ; ba c0 03 ; 0xc040d vgarom.asm:799 + mov AL, strict byte 010h ; b0 10 ; 0xc0410 vgarom.asm:800 + out DX, AL ; ee ; 0xc0412 vgarom.asm:801 + mov dx, 003c1h ; ba c1 03 ; 0xc0413 vgarom.asm:802 + in AL, DX ; ec ; 0xc0416 vgarom.asm:803 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc0417 vgarom.asm:804 + shr bl, 1 ; d0 eb ; 0xc0419 vgarom.asm:808 + shr bl, 1 ; d0 eb ; 0xc041b vgarom.asm:809 + shr bl, 1 ; d0 eb ; 0xc041d vgarom.asm:810 + shr bl, 1 ; d0 eb ; 0xc041f vgarom.asm:811 + shr bl, 1 ; d0 eb ; 0xc0421 vgarom.asm:812 + shr bl, 1 ; d0 eb ; 0xc0423 vgarom.asm:813 + shr bl, 1 ; d0 eb ; 0xc0425 vgarom.asm:814 + mov dx, 003dah ; ba da 03 ; 0xc0427 vgarom.asm:816 + in AL, DX ; ec ; 0xc042a vgarom.asm:817 + mov dx, 003c0h ; ba c0 03 ; 0xc042b vgarom.asm:818 + mov AL, strict byte 014h ; b0 14 ; 0xc042e vgarom.asm:819 + out DX, AL ; ee ; 0xc0430 vgarom.asm:820 + mov dx, 003c1h ; ba c1 03 ; 0xc0431 vgarom.asm:821 + in AL, DX ; ec ; 0xc0434 vgarom.asm:822 + db 08ah, 0f8h + ; mov bh, al ; 8a f8 ; 0xc0435 vgarom.asm:823 + and bh, 00fh ; 80 e7 0f ; 0xc0437 vgarom.asm:824 + test bl, 001h ; f6 c3 01 ; 0xc043a vgarom.asm:825 + jne short 00443h ; 75 04 ; 0xc043d vgarom.asm:826 + shr bh, 1 ; d0 ef ; 0xc043f vgarom.asm:830 + shr bh, 1 ; d0 ef ; 0xc0441 vgarom.asm:831 + mov dx, 003dah ; ba da 03 ; 0xc0443 vgarom.asm:834 + in AL, DX ; ec ; 0xc0446 vgarom.asm:835 + mov dx, 003c0h ; ba c0 03 ; 0xc0447 vgarom.asm:836 + mov AL, strict byte 020h ; b0 20 ; 0xc044a vgarom.asm:837 + out DX, AL ; ee ; 0xc044c vgarom.asm:838 + mov dx, 003dah ; ba da 03 ; 0xc044d vgarom.asm:840 + in AL, DX ; ec ; 0xc0450 vgarom.asm:841 + pop dx ; 5a ; 0xc0451 vgarom.asm:843 + pop ax ; 58 ; 0xc0452 vgarom.asm:844 + retn ; c3 ; 0xc0453 vgarom.asm:845 + push ax ; 50 ; 0xc0454 vgarom.asm:850 + push dx ; 52 ; 0xc0455 vgarom.asm:851 + mov dx, 003c4h ; ba c4 03 ; 0xc0456 vgarom.asm:852 + db 08ah, 0e3h + ; mov ah, bl ; 8a e3 ; 0xc0459 vgarom.asm:853 + mov AL, strict byte 003h ; b0 03 ; 0xc045b vgarom.asm:854 + out DX, ax ; ef ; 0xc045d vgarom.asm:855 + pop dx ; 5a ; 0xc045e vgarom.asm:856 + pop ax ; 58 ; 0xc045f vgarom.asm:857 + retn ; c3 ; 0xc0460 vgarom.asm:858 + push DS ; 1e ; 0xc0461 vgarom.asm:863 + push ax ; 50 ; 0xc0462 vgarom.asm:864 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0463 vgarom.asm:865 + mov ds, ax ; 8e d8 ; 0xc0466 vgarom.asm:866 + db 032h, 0edh + ; xor ch, ch ; 32 ed ; 0xc0468 vgarom.asm:867 + mov bx, 00088h ; bb 88 00 ; 0xc046a vgarom.asm:868 + mov cl, byte [bx] ; 8a 0f ; 0xc046d vgarom.asm:869 + and cl, 00fh ; 80 e1 0f ; 0xc046f vgarom.asm:870 + mov bx, strict word 00063h ; bb 63 00 ; 0xc0472 vgarom.asm:871 + mov ax, word [bx] ; 8b 07 ; 0xc0475 vgarom.asm:872 + mov bx, strict word 00003h ; bb 03 00 ; 0xc0477 vgarom.asm:873 + cmp ax, 003b4h ; 3d b4 03 ; 0xc047a vgarom.asm:874 + jne short 00481h ; 75 02 ; 0xc047d vgarom.asm:875 + mov BH, strict byte 001h ; b7 01 ; 0xc047f vgarom.asm:876 + pop ax ; 58 ; 0xc0481 vgarom.asm:878 + pop DS ; 1f ; 0xc0482 vgarom.asm:879 + retn ; c3 ; 0xc0483 vgarom.asm:880 + push DS ; 1e ; 0xc0484 vgarom.asm:888 + push bx ; 53 ; 0xc0485 vgarom.asm:889 + push dx ; 52 ; 0xc0486 vgarom.asm:890 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc0487 vgarom.asm:891 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0489 vgarom.asm:892 + mov ds, ax ; 8e d8 ; 0xc048c vgarom.asm:893 + mov bx, 00089h ; bb 89 00 ; 0xc048e vgarom.asm:894 + mov al, byte [bx] ; 8a 07 ; 0xc0491 vgarom.asm:895 + mov bx, 00088h ; bb 88 00 ; 0xc0493 vgarom.asm:896 + mov ah, byte [bx] ; 8a 27 ; 0xc0496 vgarom.asm:897 + cmp dl, 001h ; 80 fa 01 ; 0xc0498 vgarom.asm:898 + je short 004b2h ; 74 15 ; 0xc049b vgarom.asm:899 + jc short 004bch ; 72 1d ; 0xc049d vgarom.asm:900 + cmp dl, 002h ; 80 fa 02 ; 0xc049f vgarom.asm:901 + je short 004a6h ; 74 02 ; 0xc04a2 vgarom.asm:902 + jmp short 004d0h ; eb 2a ; 0xc04a4 vgarom.asm:912 + and AL, strict byte 07fh ; 24 7f ; 0xc04a6 vgarom.asm:918 + or AL, strict byte 010h ; 0c 10 ; 0xc04a8 vgarom.asm:919 + and ah, 0f0h ; 80 e4 f0 ; 0xc04aa vgarom.asm:920 + or ah, 009h ; 80 cc 09 ; 0xc04ad vgarom.asm:921 + jne short 004c6h ; 75 14 ; 0xc04b0 vgarom.asm:922 + and AL, strict byte 06fh ; 24 6f ; 0xc04b2 vgarom.asm:928 + and ah, 0f0h ; 80 e4 f0 ; 0xc04b4 vgarom.asm:929 + or ah, 009h ; 80 cc 09 ; 0xc04b7 vgarom.asm:930 + jne short 004c6h ; 75 0a ; 0xc04ba vgarom.asm:931 + and AL, strict byte 0efh ; 24 ef ; 0xc04bc vgarom.asm:937 + or AL, strict byte 080h ; 0c 80 ; 0xc04be vgarom.asm:938 + and ah, 0f0h ; 80 e4 f0 ; 0xc04c0 vgarom.asm:939 + or ah, 008h ; 80 cc 08 ; 0xc04c3 vgarom.asm:940 + mov bx, 00089h ; bb 89 00 ; 0xc04c6 vgarom.asm:942 + mov byte [bx], al ; 88 07 ; 0xc04c9 vgarom.asm:943 + mov bx, 00088h ; bb 88 00 ; 0xc04cb vgarom.asm:944 + mov byte [bx], ah ; 88 27 ; 0xc04ce vgarom.asm:945 + mov ax, 01212h ; b8 12 12 ; 0xc04d0 vgarom.asm:947 + pop dx ; 5a ; 0xc04d3 vgarom.asm:948 + pop bx ; 5b ; 0xc04d4 vgarom.asm:949 + pop DS ; 1f ; 0xc04d5 vgarom.asm:950 + retn ; c3 ; 0xc04d6 vgarom.asm:951 + push DS ; 1e ; 0xc04d7 vgarom.asm:960 + push bx ; 53 ; 0xc04d8 vgarom.asm:961 + push dx ; 52 ; 0xc04d9 vgarom.asm:962 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc04da vgarom.asm:963 + and dl, 001h ; 80 e2 01 ; 0xc04dc vgarom.asm:964 + sal dl, 1 ; d0 e2 ; 0xc04df vgarom.asm:968 + sal dl, 1 ; d0 e2 ; 0xc04e1 vgarom.asm:969 + sal dl, 1 ; d0 e2 ; 0xc04e3 vgarom.asm:970 + mov ax, strict word 00040h ; b8 40 00 ; 0xc04e5 vgarom.asm:972 + mov ds, ax ; 8e d8 ; 0xc04e8 vgarom.asm:973 + mov bx, 00089h ; bb 89 00 ; 0xc04ea vgarom.asm:974 + mov al, byte [bx] ; 8a 07 ; 0xc04ed vgarom.asm:975 + and AL, strict byte 0f7h ; 24 f7 ; 0xc04ef vgarom.asm:976 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc04f1 vgarom.asm:977 + mov byte [bx], al ; 88 07 ; 0xc04f3 vgarom.asm:978 + mov ax, 01212h ; b8 12 12 ; 0xc04f5 vgarom.asm:979 + pop dx ; 5a ; 0xc04f8 vgarom.asm:980 + pop bx ; 5b ; 0xc04f9 vgarom.asm:981 + pop DS ; 1f ; 0xc04fa vgarom.asm:982 + retn ; c3 ; 0xc04fb vgarom.asm:983 + push bx ; 53 ; 0xc04fc vgarom.asm:987 + push dx ; 52 ; 0xc04fd vgarom.asm:988 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc04fe vgarom.asm:989 + and bl, 001h ; 80 e3 01 ; 0xc0500 vgarom.asm:990 + xor bl, 001h ; 80 f3 01 ; 0xc0503 vgarom.asm:991 + sal bl, 1 ; d0 e3 ; 0xc0506 vgarom.asm:992 + mov dx, 003cch ; ba cc 03 ; 0xc0508 vgarom.asm:993 + in AL, DX ; ec ; 0xc050b vgarom.asm:994 + and AL, strict byte 0fdh ; 24 fd ; 0xc050c vgarom.asm:995 + db 00ah, 0c3h + ; or al, bl ; 0a c3 ; 0xc050e vgarom.asm:996 + mov dx, 003c2h ; ba c2 03 ; 0xc0510 vgarom.asm:997 + out DX, AL ; ee ; 0xc0513 vgarom.asm:998 + mov ax, 01212h ; b8 12 12 ; 0xc0514 vgarom.asm:999 + pop dx ; 5a ; 0xc0517 vgarom.asm:1000 + pop bx ; 5b ; 0xc0518 vgarom.asm:1001 + retn ; c3 ; 0xc0519 vgarom.asm:1002 + push DS ; 1e ; 0xc051a vgarom.asm:1006 + push bx ; 53 ; 0xc051b vgarom.asm:1007 + push dx ; 52 ; 0xc051c vgarom.asm:1008 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc051d vgarom.asm:1009 + and dl, 001h ; 80 e2 01 ; 0xc051f vgarom.asm:1010 + xor dl, 001h ; 80 f2 01 ; 0xc0522 vgarom.asm:1011 + sal dl, 1 ; d0 e2 ; 0xc0525 vgarom.asm:1012 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0527 vgarom.asm:1013 + mov ds, ax ; 8e d8 ; 0xc052a vgarom.asm:1014 + mov bx, 00089h ; bb 89 00 ; 0xc052c vgarom.asm:1015 + mov al, byte [bx] ; 8a 07 ; 0xc052f vgarom.asm:1016 + and AL, strict byte 0fdh ; 24 fd ; 0xc0531 vgarom.asm:1017 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc0533 vgarom.asm:1018 + mov byte [bx], al ; 88 07 ; 0xc0535 vgarom.asm:1019 + mov ax, 01212h ; b8 12 12 ; 0xc0537 vgarom.asm:1020 + pop dx ; 5a ; 0xc053a vgarom.asm:1021 + pop bx ; 5b ; 0xc053b vgarom.asm:1022 + pop DS ; 1f ; 0xc053c vgarom.asm:1023 + retn ; c3 ; 0xc053d vgarom.asm:1024 + push DS ; 1e ; 0xc053e vgarom.asm:1028 + push bx ; 53 ; 0xc053f vgarom.asm:1029 + push dx ; 52 ; 0xc0540 vgarom.asm:1030 + db 08ah, 0d0h + ; mov dl, al ; 8a d0 ; 0xc0541 vgarom.asm:1031 + and dl, 001h ; 80 e2 01 ; 0xc0543 vgarom.asm:1032 + xor dl, 001h ; 80 f2 01 ; 0xc0546 vgarom.asm:1033 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0549 vgarom.asm:1034 + mov ds, ax ; 8e d8 ; 0xc054c vgarom.asm:1035 + mov bx, 00089h ; bb 89 00 ; 0xc054e vgarom.asm:1036 + mov al, byte [bx] ; 8a 07 ; 0xc0551 vgarom.asm:1037 + and AL, strict byte 0feh ; 24 fe ; 0xc0553 vgarom.asm:1038 + db 00ah, 0c2h + ; or al, dl ; 0a c2 ; 0xc0555 vgarom.asm:1039 + mov byte [bx], al ; 88 07 ; 0xc0557 vgarom.asm:1040 + mov ax, 01212h ; b8 12 12 ; 0xc0559 vgarom.asm:1041 + pop dx ; 5a ; 0xc055c vgarom.asm:1042 + pop bx ; 5b ; 0xc055d vgarom.asm:1043 + pop DS ; 1f ; 0xc055e vgarom.asm:1044 + retn ; c3 ; 0xc055f vgarom.asm:1045 + cmp AL, strict byte 000h ; 3c 00 ; 0xc0560 vgarom.asm:1050 + je short 00569h ; 74 05 ; 0xc0562 vgarom.asm:1051 + cmp AL, strict byte 001h ; 3c 01 ; 0xc0564 vgarom.asm:1052 + je short 0057eh ; 74 16 ; 0xc0566 vgarom.asm:1053 + retn ; c3 ; 0xc0568 vgarom.asm:1057 + push DS ; 1e ; 0xc0569 vgarom.asm:1059 + push ax ; 50 ; 0xc056a vgarom.asm:1060 + mov ax, strict word 00040h ; b8 40 00 ; 0xc056b vgarom.asm:1061 + mov ds, ax ; 8e d8 ; 0xc056e vgarom.asm:1062 + mov bx, 0008ah ; bb 8a 00 ; 0xc0570 vgarom.asm:1063 + mov al, byte [bx] ; 8a 07 ; 0xc0573 vgarom.asm:1064 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc0575 vgarom.asm:1065 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc0577 vgarom.asm:1066 + pop ax ; 58 ; 0xc0579 vgarom.asm:1067 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc057a vgarom.asm:1068 + pop DS ; 1f ; 0xc057c vgarom.asm:1069 + retn ; c3 ; 0xc057d vgarom.asm:1070 + push DS ; 1e ; 0xc057e vgarom.asm:1072 + push ax ; 50 ; 0xc057f vgarom.asm:1073 + push bx ; 53 ; 0xc0580 vgarom.asm:1074 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0581 vgarom.asm:1075 + mov ds, ax ; 8e d8 ; 0xc0584 vgarom.asm:1076 + db 08bh, 0c3h + ; mov ax, bx ; 8b c3 ; 0xc0586 vgarom.asm:1077 + mov bx, 0008ah ; bb 8a 00 ; 0xc0588 vgarom.asm:1078 + mov byte [bx], al ; 88 07 ; 0xc058b vgarom.asm:1079 + pop bx ; 5b ; 0xc058d vgarom.asm:1089 + pop ax ; 58 ; 0xc058e vgarom.asm:1090 + db 08ah, 0c4h + ; mov al, ah ; 8a c4 ; 0xc058f vgarom.asm:1091 + pop DS ; 1f ; 0xc0591 vgarom.asm:1092 + retn ; c3 ; 0xc0592 vgarom.asm:1093 + times 0xd db 0 + ; disGetNextSymbol 0xc05a0 LB 0x3af -> off=0x0 cb=0000000000000007 uValue=00000000000c05a0 'do_out_dx_ax' +do_out_dx_ax: ; 0xc05a0 LB 0x7 + xchg ah, al ; 86 c4 ; 0xc05a0 vberom.asm:69 + out DX, AL ; ee ; 0xc05a2 vberom.asm:70 + xchg ah, al ; 86 c4 ; 0xc05a3 vberom.asm:71 + out DX, AL ; ee ; 0xc05a5 vberom.asm:72 + retn ; c3 ; 0xc05a6 vberom.asm:73 + ; disGetNextSymbol 0xc05a7 LB 0x3a8 -> off=0x0 cb=0000000000000043 uValue=00000000000c05a7 'do_in_ax_dx' +do_in_ax_dx: ; 0xc05a7 LB 0x43 + in AL, DX ; ec ; 0xc05a7 vberom.asm:76 + xchg ah, al ; 86 c4 ; 0xc05a8 vberom.asm:77 + in AL, DX ; ec ; 0xc05aa vberom.asm:78 + retn ; c3 ; 0xc05ab vberom.asm:79 + push ax ; 50 ; 0xc05ac vberom.asm:90 + push dx ; 52 ; 0xc05ad vberom.asm:91 + mov dx, 003dah ; ba da 03 ; 0xc05ae vberom.asm:92 + in AL, DX ; ec ; 0xc05b1 vberom.asm:94 + test AL, strict byte 008h ; a8 08 ; 0xc05b2 vberom.asm:95 + je short 005b1h ; 74 fb ; 0xc05b4 vberom.asm:96 + pop dx ; 5a ; 0xc05b6 vberom.asm:97 + pop ax ; 58 ; 0xc05b7 vberom.asm:98 + retn ; c3 ; 0xc05b8 vberom.asm:99 + push ax ; 50 ; 0xc05b9 vberom.asm:102 + push dx ; 52 ; 0xc05ba vberom.asm:103 + mov dx, 003dah ; ba da 03 ; 0xc05bb vberom.asm:104 + in AL, DX ; ec ; 0xc05be vberom.asm:106 + test AL, strict byte 008h ; a8 08 ; 0xc05bf vberom.asm:107 + jne short 005beh ; 75 fb ; 0xc05c1 vberom.asm:108 + pop dx ; 5a ; 0xc05c3 vberom.asm:109 + pop ax ; 58 ; 0xc05c4 vberom.asm:110 + retn ; c3 ; 0xc05c5 vberom.asm:111 + push dx ; 52 ; 0xc05c6 vberom.asm:116 + mov dx, 001ceh ; ba ce 01 ; 0xc05c7 vberom.asm:117 + mov ax, strict word 00003h ; b8 03 00 ; 0xc05ca vberom.asm:118 + call 005a0h ; e8 d0 ff ; 0xc05cd vberom.asm:119 + mov dx, 001cfh ; ba cf 01 ; 0xc05d0 vberom.asm:120 + call 005a7h ; e8 d1 ff ; 0xc05d3 vberom.asm:121 + cmp AL, strict byte 004h ; 3c 04 ; 0xc05d6 vberom.asm:122 + jbe short 005e8h ; 76 0e ; 0xc05d8 vberom.asm:123 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc05da vberom.asm:124 + shr ah, 1 ; d0 ec ; 0xc05dc vberom.asm:128 + shr ah, 1 ; d0 ec ; 0xc05de vberom.asm:129 + shr ah, 1 ; d0 ec ; 0xc05e0 vberom.asm:130 + test AL, strict byte 007h ; a8 07 ; 0xc05e2 vberom.asm:132 + je short 005e8h ; 74 02 ; 0xc05e4 vberom.asm:133 + db 0feh, 0c4h + ; inc ah ; fe c4 ; 0xc05e6 vberom.asm:134 + pop dx ; 5a ; 0xc05e8 vberom.asm:136 + retn ; c3 ; 0xc05e9 vberom.asm:137 + ; disGetNextSymbol 0xc05ea LB 0x365 -> off=0x0 cb=0000000000000026 uValue=00000000000c05ea '_dispi_get_max_bpp' +_dispi_get_max_bpp: ; 0xc05ea LB 0x26 + push dx ; 52 ; 0xc05ea vberom.asm:142 + push bx ; 53 ; 0xc05eb vberom.asm:143 + call 00624h ; e8 35 00 ; 0xc05ec vberom.asm:144 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc05ef vberom.asm:145 + or ax, strict byte 00002h ; 83 c8 02 ; 0xc05f1 vberom.asm:146 + call 00610h ; e8 19 00 ; 0xc05f4 vberom.asm:147 + mov dx, 001ceh ; ba ce 01 ; 0xc05f7 vberom.asm:148 + mov ax, strict word 00003h ; b8 03 00 ; 0xc05fa vberom.asm:149 + call 005a0h ; e8 a0 ff ; 0xc05fd vberom.asm:150 + mov dx, 001cfh ; ba cf 01 ; 0xc0600 vberom.asm:151 + call 005a7h ; e8 a1 ff ; 0xc0603 vberom.asm:152 + push ax ; 50 ; 0xc0606 vberom.asm:153 + db 08bh, 0c3h + ; mov ax, bx ; 8b c3 ; 0xc0607 vberom.asm:154 + call 00610h ; e8 04 00 ; 0xc0609 vberom.asm:155 + pop ax ; 58 ; 0xc060c vberom.asm:156 + pop bx ; 5b ; 0xc060d vberom.asm:157 + pop dx ; 5a ; 0xc060e vberom.asm:158 + retn ; c3 ; 0xc060f vberom.asm:159 + ; disGetNextSymbol 0xc0610 LB 0x33f -> off=0x0 cb=0000000000000026 uValue=00000000000c0610 'dispi_set_enable_' +dispi_set_enable_: ; 0xc0610 LB 0x26 + push dx ; 52 ; 0xc0610 vberom.asm:162 + push ax ; 50 ; 0xc0611 vberom.asm:163 + mov dx, 001ceh ; ba ce 01 ; 0xc0612 vberom.asm:164 + mov ax, strict word 00004h ; b8 04 00 ; 0xc0615 vberom.asm:165 + call 005a0h ; e8 85 ff ; 0xc0618 vberom.asm:166 + pop ax ; 58 ; 0xc061b vberom.asm:167 + mov dx, 001cfh ; ba cf 01 ; 0xc061c vberom.asm:168 + call 005a0h ; e8 7e ff ; 0xc061f vberom.asm:169 + pop dx ; 5a ; 0xc0622 vberom.asm:170 + retn ; c3 ; 0xc0623 vberom.asm:171 + push dx ; 52 ; 0xc0624 vberom.asm:174 + mov dx, 001ceh ; ba ce 01 ; 0xc0625 vberom.asm:175 + mov ax, strict word 00004h ; b8 04 00 ; 0xc0628 vberom.asm:176 + call 005a0h ; e8 72 ff ; 0xc062b vberom.asm:177 + mov dx, 001cfh ; ba cf 01 ; 0xc062e vberom.asm:178 + call 005a7h ; e8 73 ff ; 0xc0631 vberom.asm:179 + pop dx ; 5a ; 0xc0634 vberom.asm:180 + retn ; c3 ; 0xc0635 vberom.asm:181 + ; disGetNextSymbol 0xc0636 LB 0x319 -> off=0x0 cb=0000000000000026 uValue=00000000000c0636 'dispi_set_bank_' +dispi_set_bank_: ; 0xc0636 LB 0x26 + push dx ; 52 ; 0xc0636 vberom.asm:184 + push ax ; 50 ; 0xc0637 vberom.asm:185 + mov dx, 001ceh ; ba ce 01 ; 0xc0638 vberom.asm:186 + mov ax, strict word 00005h ; b8 05 00 ; 0xc063b vberom.asm:187 + call 005a0h ; e8 5f ff ; 0xc063e vberom.asm:188 + pop ax ; 58 ; 0xc0641 vberom.asm:189 + mov dx, 001cfh ; ba cf 01 ; 0xc0642 vberom.asm:190 + call 005a0h ; e8 58 ff ; 0xc0645 vberom.asm:191 + pop dx ; 5a ; 0xc0648 vberom.asm:192 + retn ; c3 ; 0xc0649 vberom.asm:193 + push dx ; 52 ; 0xc064a vberom.asm:196 + mov dx, 001ceh ; ba ce 01 ; 0xc064b vberom.asm:197 + mov ax, strict word 00005h ; b8 05 00 ; 0xc064e vberom.asm:198 + call 005a0h ; e8 4c ff ; 0xc0651 vberom.asm:199 + mov dx, 001cfh ; ba cf 01 ; 0xc0654 vberom.asm:200 + call 005a7h ; e8 4d ff ; 0xc0657 vberom.asm:201 + pop dx ; 5a ; 0xc065a vberom.asm:202 + retn ; c3 ; 0xc065b vberom.asm:203 + ; disGetNextSymbol 0xc065c LB 0x2f3 -> off=0x0 cb=00000000000000ac uValue=00000000000c065c '_dispi_set_bank_farcall' +_dispi_set_bank_farcall: ; 0xc065c LB 0xac + cmp bx, 00100h ; 81 fb 00 01 ; 0xc065c vberom.asm:206 + je short 00686h ; 74 24 ; 0xc0660 vberom.asm:207 + db 00bh, 0dbh + ; or bx, bx ; 0b db ; 0xc0662 vberom.asm:208 + jne short 00698h ; 75 32 ; 0xc0664 vberom.asm:209 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc0666 vberom.asm:210 + push dx ; 52 ; 0xc0668 vberom.asm:211 + push ax ; 50 ; 0xc0669 vberom.asm:212 + mov ax, strict word 00005h ; b8 05 00 ; 0xc066a vberom.asm:213 + mov dx, 001ceh ; ba ce 01 ; 0xc066d vberom.asm:214 + call 005a0h ; e8 2d ff ; 0xc0670 vberom.asm:215 + pop ax ; 58 ; 0xc0673 vberom.asm:216 + mov dx, 001cfh ; ba cf 01 ; 0xc0674 vberom.asm:217 + call 005a0h ; e8 26 ff ; 0xc0677 vberom.asm:218 + call 005a7h ; e8 2a ff ; 0xc067a vberom.asm:219 + pop dx ; 5a ; 0xc067d vberom.asm:220 + db 03bh, 0d0h + ; cmp dx, ax ; 3b d0 ; 0xc067e vberom.asm:221 + jne short 00698h ; 75 16 ; 0xc0680 vberom.asm:222 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0682 vberom.asm:223 + retf ; cb ; 0xc0685 vberom.asm:224 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0686 vberom.asm:226 + mov dx, 001ceh ; ba ce 01 ; 0xc0689 vberom.asm:227 + call 005a0h ; e8 11 ff ; 0xc068c vberom.asm:228 + mov dx, 001cfh ; ba cf 01 ; 0xc068f vberom.asm:229 + call 005a7h ; e8 12 ff ; 0xc0692 vberom.asm:230 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc0695 vberom.asm:231 + retf ; cb ; 0xc0697 vberom.asm:232 + mov ax, 0014fh ; b8 4f 01 ; 0xc0698 vberom.asm:234 + retf ; cb ; 0xc069b vberom.asm:235 + push dx ; 52 ; 0xc069c vberom.asm:238 + push ax ; 50 ; 0xc069d vberom.asm:239 + mov dx, 001ceh ; ba ce 01 ; 0xc069e vberom.asm:240 + mov ax, strict word 00008h ; b8 08 00 ; 0xc06a1 vberom.asm:241 + call 005a0h ; e8 f9 fe ; 0xc06a4 vberom.asm:242 + pop ax ; 58 ; 0xc06a7 vberom.asm:243 + mov dx, 001cfh ; ba cf 01 ; 0xc06a8 vberom.asm:244 + call 005a0h ; e8 f2 fe ; 0xc06ab vberom.asm:245 + pop dx ; 5a ; 0xc06ae vberom.asm:246 + retn ; c3 ; 0xc06af vberom.asm:247 + push dx ; 52 ; 0xc06b0 vberom.asm:250 + mov dx, 001ceh ; ba ce 01 ; 0xc06b1 vberom.asm:251 + mov ax, strict word 00008h ; b8 08 00 ; 0xc06b4 vberom.asm:252 + call 005a0h ; e8 e6 fe ; 0xc06b7 vberom.asm:253 + mov dx, 001cfh ; ba cf 01 ; 0xc06ba vberom.asm:254 + call 005a7h ; e8 e7 fe ; 0xc06bd vberom.asm:255 + pop dx ; 5a ; 0xc06c0 vberom.asm:256 + retn ; c3 ; 0xc06c1 vberom.asm:257 + push dx ; 52 ; 0xc06c2 vberom.asm:260 + push ax ; 50 ; 0xc06c3 vberom.asm:261 + mov dx, 001ceh ; ba ce 01 ; 0xc06c4 vberom.asm:262 + mov ax, strict word 00009h ; b8 09 00 ; 0xc06c7 vberom.asm:263 + call 005a0h ; e8 d3 fe ; 0xc06ca vberom.asm:264 + pop ax ; 58 ; 0xc06cd vberom.asm:265 + mov dx, 001cfh ; ba cf 01 ; 0xc06ce vberom.asm:266 + call 005a0h ; e8 cc fe ; 0xc06d1 vberom.asm:267 + pop dx ; 5a ; 0xc06d4 vberom.asm:268 + retn ; c3 ; 0xc06d5 vberom.asm:269 + push dx ; 52 ; 0xc06d6 vberom.asm:272 + mov dx, 001ceh ; ba ce 01 ; 0xc06d7 vberom.asm:273 + mov ax, strict word 00009h ; b8 09 00 ; 0xc06da vberom.asm:274 + call 005a0h ; e8 c0 fe ; 0xc06dd vberom.asm:275 + mov dx, 001cfh ; ba cf 01 ; 0xc06e0 vberom.asm:276 + call 005a7h ; e8 c1 fe ; 0xc06e3 vberom.asm:277 + pop dx ; 5a ; 0xc06e6 vberom.asm:278 + retn ; c3 ; 0xc06e7 vberom.asm:279 + push ax ; 50 ; 0xc06e8 vberom.asm:282 + push bx ; 53 ; 0xc06e9 vberom.asm:283 + push dx ; 52 ; 0xc06ea vberom.asm:284 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc06eb vberom.asm:285 + call 005c6h ; e8 d6 fe ; 0xc06ed vberom.asm:286 + cmp AL, strict byte 004h ; 3c 04 ; 0xc06f0 vberom.asm:287 + jnbe short 006f6h ; 77 02 ; 0xc06f2 vberom.asm:288 + shr bx, 1 ; d1 eb ; 0xc06f4 vberom.asm:289 + shr bx, 1 ; d1 eb ; 0xc06f6 vberom.asm:294 + shr bx, 1 ; d1 eb ; 0xc06f8 vberom.asm:295 + shr bx, 1 ; d1 eb ; 0xc06fa vberom.asm:296 + mov dx, 003d4h ; ba d4 03 ; 0xc06fc vberom.asm:298 + db 08ah, 0e3h + ; mov ah, bl ; 8a e3 ; 0xc06ff vberom.asm:299 + mov AL, strict byte 013h ; b0 13 ; 0xc0701 vberom.asm:300 + out DX, ax ; ef ; 0xc0703 vberom.asm:301 + pop dx ; 5a ; 0xc0704 vberom.asm:302 + pop bx ; 5b ; 0xc0705 vberom.asm:303 + pop ax ; 58 ; 0xc0706 vberom.asm:304 + retn ; c3 ; 0xc0707 vberom.asm:305 + ; disGetNextSymbol 0xc0708 LB 0x247 -> off=0x0 cb=00000000000000f0 uValue=00000000000c0708 '_vga_compat_setup' +_vga_compat_setup: ; 0xc0708 LB 0xf0 + push ax ; 50 ; 0xc0708 vberom.asm:308 + push dx ; 52 ; 0xc0709 vberom.asm:309 + mov dx, 001ceh ; ba ce 01 ; 0xc070a vberom.asm:312 + mov ax, strict word 00001h ; b8 01 00 ; 0xc070d vberom.asm:313 + call 005a0h ; e8 8d fe ; 0xc0710 vberom.asm:314 + mov dx, 001cfh ; ba cf 01 ; 0xc0713 vberom.asm:315 + call 005a7h ; e8 8e fe ; 0xc0716 vberom.asm:316 + push ax ; 50 ; 0xc0719 vberom.asm:317 + mov dx, 003d4h ; ba d4 03 ; 0xc071a vberom.asm:318 + mov ax, strict word 00011h ; b8 11 00 ; 0xc071d vberom.asm:319 + out DX, ax ; ef ; 0xc0720 vberom.asm:320 + pop ax ; 58 ; 0xc0721 vberom.asm:321 + push ax ; 50 ; 0xc0722 vberom.asm:322 + shr ax, 1 ; d1 e8 ; 0xc0723 vberom.asm:326 + shr ax, 1 ; d1 e8 ; 0xc0725 vberom.asm:327 + shr ax, 1 ; d1 e8 ; 0xc0727 vberom.asm:328 + dec ax ; 48 ; 0xc0729 vberom.asm:330 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc072a vberom.asm:331 + mov AL, strict byte 001h ; b0 01 ; 0xc072c vberom.asm:332 + out DX, ax ; ef ; 0xc072e vberom.asm:333 + pop ax ; 58 ; 0xc072f vberom.asm:334 + call 006e8h ; e8 b5 ff ; 0xc0730 vberom.asm:335 + mov dx, 001ceh ; ba ce 01 ; 0xc0733 vberom.asm:338 + mov ax, strict word 00002h ; b8 02 00 ; 0xc0736 vberom.asm:339 + call 005a0h ; e8 64 fe ; 0xc0739 vberom.asm:340 + mov dx, 001cfh ; ba cf 01 ; 0xc073c vberom.asm:341 + call 005a7h ; e8 65 fe ; 0xc073f vberom.asm:342 + dec ax ; 48 ; 0xc0742 vberom.asm:343 + push ax ; 50 ; 0xc0743 vberom.asm:344 + mov dx, 003d4h ; ba d4 03 ; 0xc0744 vberom.asm:345 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc0747 vberom.asm:346 + mov AL, strict byte 012h ; b0 12 ; 0xc0749 vberom.asm:347 + out DX, ax ; ef ; 0xc074b vberom.asm:348 + pop ax ; 58 ; 0xc074c vberom.asm:349 + mov AL, strict byte 007h ; b0 07 ; 0xc074d vberom.asm:350 + out DX, AL ; ee ; 0xc074f vberom.asm:351 + inc dx ; 42 ; 0xc0750 vberom.asm:352 + in AL, DX ; ec ; 0xc0751 vberom.asm:353 + and AL, strict byte 0bdh ; 24 bd ; 0xc0752 vberom.asm:354 + test ah, 001h ; f6 c4 01 ; 0xc0754 vberom.asm:355 + je short 0075bh ; 74 02 ; 0xc0757 vberom.asm:356 + or AL, strict byte 002h ; 0c 02 ; 0xc0759 vberom.asm:357 + test ah, 002h ; f6 c4 02 ; 0xc075b vberom.asm:359 + je short 00762h ; 74 02 ; 0xc075e vberom.asm:360 + or AL, strict byte 040h ; 0c 40 ; 0xc0760 vberom.asm:361 + out DX, AL ; ee ; 0xc0762 vberom.asm:363 + mov dx, 003d4h ; ba d4 03 ; 0xc0763 vberom.asm:366 + mov ax, strict word 00009h ; b8 09 00 ; 0xc0766 vberom.asm:367 + out DX, AL ; ee ; 0xc0769 vberom.asm:368 + mov dx, 003d5h ; ba d5 03 ; 0xc076a vberom.asm:369 + in AL, DX ; ec ; 0xc076d vberom.asm:370 + and AL, strict byte 060h ; 24 60 ; 0xc076e vberom.asm:371 + out DX, AL ; ee ; 0xc0770 vberom.asm:372 + mov dx, 003d4h ; ba d4 03 ; 0xc0771 vberom.asm:373 + mov AL, strict byte 017h ; b0 17 ; 0xc0774 vberom.asm:374 + out DX, AL ; ee ; 0xc0776 vberom.asm:375 + mov dx, 003d5h ; ba d5 03 ; 0xc0777 vberom.asm:376 + in AL, DX ; ec ; 0xc077a vberom.asm:377 + or AL, strict byte 003h ; 0c 03 ; 0xc077b vberom.asm:378 + out DX, AL ; ee ; 0xc077d vberom.asm:379 + mov dx, 003dah ; ba da 03 ; 0xc077e vberom.asm:380 + in AL, DX ; ec ; 0xc0781 vberom.asm:381 + mov dx, 003c0h ; ba c0 03 ; 0xc0782 vberom.asm:382 + mov AL, strict byte 010h ; b0 10 ; 0xc0785 vberom.asm:383 + out DX, AL ; ee ; 0xc0787 vberom.asm:384 + mov dx, 003c1h ; ba c1 03 ; 0xc0788 vberom.asm:385 + in AL, DX ; ec ; 0xc078b vberom.asm:386 + or AL, strict byte 001h ; 0c 01 ; 0xc078c vberom.asm:387 + mov dx, 003c0h ; ba c0 03 ; 0xc078e vberom.asm:388 + out DX, AL ; ee ; 0xc0791 vberom.asm:389 + mov AL, strict byte 020h ; b0 20 ; 0xc0792 vberom.asm:390 + out DX, AL ; ee ; 0xc0794 vberom.asm:391 + mov dx, 003ceh ; ba ce 03 ; 0xc0795 vberom.asm:392 + mov ax, 00506h ; b8 06 05 ; 0xc0798 vberom.asm:393 + out DX, ax ; ef ; 0xc079b vberom.asm:394 + mov dx, 003c4h ; ba c4 03 ; 0xc079c vberom.asm:395 + mov ax, 00f02h ; b8 02 0f ; 0xc079f vberom.asm:396 + out DX, ax ; ef ; 0xc07a2 vberom.asm:397 + mov dx, 001ceh ; ba ce 01 ; 0xc07a3 vberom.asm:400 + mov ax, strict word 00003h ; b8 03 00 ; 0xc07a6 vberom.asm:401 + call 005a0h ; e8 f4 fd ; 0xc07a9 vberom.asm:402 + mov dx, 001cfh ; ba cf 01 ; 0xc07ac vberom.asm:403 + call 005a7h ; e8 f5 fd ; 0xc07af vberom.asm:404 + cmp AL, strict byte 008h ; 3c 08 ; 0xc07b2 vberom.asm:405 + jc short 007f6h ; 72 40 ; 0xc07b4 vberom.asm:406 + mov dx, 003d4h ; ba d4 03 ; 0xc07b6 vberom.asm:407 + mov AL, strict byte 014h ; b0 14 ; 0xc07b9 vberom.asm:408 + out DX, AL ; ee ; 0xc07bb vberom.asm:409 + mov dx, 003d5h ; ba d5 03 ; 0xc07bc vberom.asm:410 + in AL, DX ; ec ; 0xc07bf vberom.asm:411 + or AL, strict byte 040h ; 0c 40 ; 0xc07c0 vberom.asm:412 + out DX, AL ; ee ; 0xc07c2 vberom.asm:413 + mov dx, 003dah ; ba da 03 ; 0xc07c3 vberom.asm:414 + in AL, DX ; ec ; 0xc07c6 vberom.asm:415 + mov dx, 003c0h ; ba c0 03 ; 0xc07c7 vberom.asm:416 + mov AL, strict byte 010h ; b0 10 ; 0xc07ca vberom.asm:417 + out DX, AL ; ee ; 0xc07cc vberom.asm:418 + mov dx, 003c1h ; ba c1 03 ; 0xc07cd vberom.asm:419 + in AL, DX ; ec ; 0xc07d0 vberom.asm:420 + or AL, strict byte 040h ; 0c 40 ; 0xc07d1 vberom.asm:421 + mov dx, 003c0h ; ba c0 03 ; 0xc07d3 vberom.asm:422 + out DX, AL ; ee ; 0xc07d6 vberom.asm:423 + mov AL, strict byte 020h ; b0 20 ; 0xc07d7 vberom.asm:424 + out DX, AL ; ee ; 0xc07d9 vberom.asm:425 + mov dx, 003c4h ; ba c4 03 ; 0xc07da vberom.asm:426 + mov AL, strict byte 004h ; b0 04 ; 0xc07dd vberom.asm:427 + out DX, AL ; ee ; 0xc07df vberom.asm:428 + mov dx, 003c5h ; ba c5 03 ; 0xc07e0 vberom.asm:429 + in AL, DX ; ec ; 0xc07e3 vberom.asm:430 + or AL, strict byte 008h ; 0c 08 ; 0xc07e4 vberom.asm:431 + out DX, AL ; ee ; 0xc07e6 vberom.asm:432 + mov dx, 003ceh ; ba ce 03 ; 0xc07e7 vberom.asm:433 + mov AL, strict byte 005h ; b0 05 ; 0xc07ea vberom.asm:434 + out DX, AL ; ee ; 0xc07ec vberom.asm:435 + mov dx, 003cfh ; ba cf 03 ; 0xc07ed vberom.asm:436 + in AL, DX ; ec ; 0xc07f0 vberom.asm:437 + and AL, strict byte 09fh ; 24 9f ; 0xc07f1 vberom.asm:438 + or AL, strict byte 040h ; 0c 40 ; 0xc07f3 vberom.asm:439 + out DX, AL ; ee ; 0xc07f5 vberom.asm:440 + pop dx ; 5a ; 0xc07f6 vberom.asm:443 + pop ax ; 58 ; 0xc07f7 vberom.asm:444 + ; disGetNextSymbol 0xc07f8 LB 0x157 -> off=0x0 cb=0000000000000013 uValue=00000000000c07f8 '_vbe_has_vbe_display' +_vbe_has_vbe_display: ; 0xc07f8 LB 0x13 + push DS ; 1e ; 0xc07f8 vberom.asm:450 + push bx ; 53 ; 0xc07f9 vberom.asm:451 + mov ax, strict word 00040h ; b8 40 00 ; 0xc07fa vberom.asm:452 + mov ds, ax ; 8e d8 ; 0xc07fd vberom.asm:453 + mov bx, 000b9h ; bb b9 00 ; 0xc07ff vberom.asm:454 + mov al, byte [bx] ; 8a 07 ; 0xc0802 vberom.asm:455 + and AL, strict byte 001h ; 24 01 ; 0xc0804 vberom.asm:456 + db 032h, 0e4h + ; xor ah, ah ; 32 e4 ; 0xc0806 vberom.asm:457 + pop bx ; 5b ; 0xc0808 vberom.asm:458 + pop DS ; 1f ; 0xc0809 vberom.asm:459 + retn ; c3 ; 0xc080a vberom.asm:460 + ; disGetNextSymbol 0xc080b LB 0x144 -> off=0x0 cb=0000000000000025 uValue=00000000000c080b 'vbe_biosfn_return_current_mode' +vbe_biosfn_return_current_mode: ; 0xc080b LB 0x25 + push DS ; 1e ; 0xc080b vberom.asm:473 + mov ax, strict word 00040h ; b8 40 00 ; 0xc080c vberom.asm:474 + mov ds, ax ; 8e d8 ; 0xc080f vberom.asm:475 + call 00624h ; e8 10 fe ; 0xc0811 vberom.asm:476 + and ax, strict byte 00001h ; 83 e0 01 ; 0xc0814 vberom.asm:477 + je short 00822h ; 74 09 ; 0xc0817 vberom.asm:478 + mov bx, 000bah ; bb ba 00 ; 0xc0819 vberom.asm:479 + mov ax, word [bx] ; 8b 07 ; 0xc081c vberom.asm:480 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc081e vberom.asm:481 + jne short 0082bh ; 75 09 ; 0xc0820 vberom.asm:482 + mov bx, strict word 00049h ; bb 49 00 ; 0xc0822 vberom.asm:484 + mov al, byte [bx] ; 8a 07 ; 0xc0825 vberom.asm:485 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc0827 vberom.asm:486 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc0829 vberom.asm:487 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc082b vberom.asm:489 + pop DS ; 1f ; 0xc082e vberom.asm:490 + retn ; c3 ; 0xc082f vberom.asm:491 + ; disGetNextSymbol 0xc0830 LB 0x11f -> off=0x0 cb=000000000000002d uValue=00000000000c0830 'vbe_biosfn_display_window_control' +vbe_biosfn_display_window_control: ; 0xc0830 LB 0x2d + cmp bl, 000h ; 80 fb 00 ; 0xc0830 vberom.asm:515 + jne short 00859h ; 75 24 ; 0xc0833 vberom.asm:516 + cmp bh, 001h ; 80 ff 01 ; 0xc0835 vberom.asm:517 + je short 00850h ; 74 16 ; 0xc0838 vberom.asm:518 + jc short 00840h ; 72 04 ; 0xc083a vberom.asm:519 + mov ax, 00100h ; b8 00 01 ; 0xc083c vberom.asm:520 + retn ; c3 ; 0xc083f vberom.asm:521 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc0840 vberom.asm:523 + call 00636h ; e8 f1 fd ; 0xc0842 vberom.asm:524 + call 0064ah ; e8 02 fe ; 0xc0845 vberom.asm:525 + db 03bh, 0c2h + ; cmp ax, dx ; 3b c2 ; 0xc0848 vberom.asm:526 + jne short 00859h ; 75 0d ; 0xc084a vberom.asm:527 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc084c vberom.asm:528 + retn ; c3 ; 0xc084f vberom.asm:529 + call 0064ah ; e8 f7 fd ; 0xc0850 vberom.asm:531 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc0853 vberom.asm:532 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0855 vberom.asm:533 + retn ; c3 ; 0xc0858 vberom.asm:534 + mov ax, 0014fh ; b8 4f 01 ; 0xc0859 vberom.asm:536 + retn ; c3 ; 0xc085c vberom.asm:537 + ; disGetNextSymbol 0xc085d LB 0xf2 -> off=0x0 cb=0000000000000034 uValue=00000000000c085d 'vbe_biosfn_set_get_display_start' +vbe_biosfn_set_get_display_start: ; 0xc085d LB 0x34 + cmp bl, 080h ; 80 fb 80 ; 0xc085d vberom.asm:577 + je short 0086dh ; 74 0b ; 0xc0860 vberom.asm:578 + cmp bl, 001h ; 80 fb 01 ; 0xc0862 vberom.asm:579 + je short 00881h ; 74 1a ; 0xc0865 vberom.asm:580 + jc short 00873h ; 72 0a ; 0xc0867 vberom.asm:581 + mov ax, 00100h ; b8 00 01 ; 0xc0869 vberom.asm:582 + retn ; c3 ; 0xc086c vberom.asm:583 + call 005b9h ; e8 49 fd ; 0xc086d vberom.asm:585 + call 005ach ; e8 39 fd ; 0xc0870 vberom.asm:586 + db 08bh, 0c1h + ; mov ax, cx ; 8b c1 ; 0xc0873 vberom.asm:588 + call 0069ch ; e8 24 fe ; 0xc0875 vberom.asm:589 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc0878 vberom.asm:590 + call 006c2h ; e8 45 fe ; 0xc087a vberom.asm:591 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc087d vberom.asm:592 + retn ; c3 ; 0xc0880 vberom.asm:593 + call 006b0h ; e8 2c fe ; 0xc0881 vberom.asm:595 + db 08bh, 0c8h + ; mov cx, ax ; 8b c8 ; 0xc0884 vberom.asm:596 + call 006d6h ; e8 4d fe ; 0xc0886 vberom.asm:597 + db 08bh, 0d0h + ; mov dx, ax ; 8b d0 ; 0xc0889 vberom.asm:598 + db 032h, 0ffh + ; xor bh, bh ; 32 ff ; 0xc088b vberom.asm:599 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc088d vberom.asm:600 + retn ; c3 ; 0xc0890 vberom.asm:601 + ; disGetNextSymbol 0xc0891 LB 0xbe -> off=0x0 cb=0000000000000037 uValue=00000000000c0891 'vbe_biosfn_set_get_dac_palette_format' +vbe_biosfn_set_get_dac_palette_format: ; 0xc0891 LB 0x37 + cmp bl, 001h ; 80 fb 01 ; 0xc0891 vberom.asm:616 + je short 008b4h ; 74 1e ; 0xc0894 vberom.asm:617 + jc short 0089ch ; 72 04 ; 0xc0896 vberom.asm:618 + mov ax, 00100h ; b8 00 01 ; 0xc0898 vberom.asm:619 + retn ; c3 ; 0xc089b vberom.asm:620 + call 00624h ; e8 85 fd ; 0xc089c vberom.asm:622 + cmp bh, 006h ; 80 ff 06 ; 0xc089f vberom.asm:623 + je short 008aeh ; 74 0a ; 0xc08a2 vberom.asm:624 + cmp bh, 008h ; 80 ff 08 ; 0xc08a4 vberom.asm:625 + jne short 008c4h ; 75 1b ; 0xc08a7 vberom.asm:626 + or ax, strict byte 00020h ; 83 c8 20 ; 0xc08a9 vberom.asm:627 + jne short 008b1h ; 75 03 ; 0xc08ac vberom.asm:628 + and ax, strict byte 0ffdfh ; 83 e0 df ; 0xc08ae vberom.asm:630 + call 00610h ; e8 5c fd ; 0xc08b1 vberom.asm:632 + mov BH, strict byte 006h ; b7 06 ; 0xc08b4 vberom.asm:634 + call 00624h ; e8 6b fd ; 0xc08b6 vberom.asm:635 + and ax, strict byte 00020h ; 83 e0 20 ; 0xc08b9 vberom.asm:636 + je short 008c0h ; 74 02 ; 0xc08bc vberom.asm:637 + mov BH, strict byte 008h ; b7 08 ; 0xc08be vberom.asm:638 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc08c0 vberom.asm:640 + retn ; c3 ; 0xc08c3 vberom.asm:641 + mov ax, 0014fh ; b8 4f 01 ; 0xc08c4 vberom.asm:643 + retn ; c3 ; 0xc08c7 vberom.asm:644 + ; disGetNextSymbol 0xc08c8 LB 0x87 -> off=0x0 cb=0000000000000073 uValue=00000000000c08c8 'vbe_biosfn_set_get_palette_data' +vbe_biosfn_set_get_palette_data: ; 0xc08c8 LB 0x73 + test bl, bl ; 84 db ; 0xc08c8 vberom.asm:683 + je short 008dbh ; 74 0f ; 0xc08ca vberom.asm:684 + cmp bl, 001h ; 80 fb 01 ; 0xc08cc vberom.asm:685 + je short 00909h ; 74 38 ; 0xc08cf vberom.asm:686 + cmp bl, 003h ; 80 fb 03 ; 0xc08d1 vberom.asm:687 + jbe short 00937h ; 76 61 ; 0xc08d4 vberom.asm:688 + cmp bl, 080h ; 80 fb 80 ; 0xc08d6 vberom.asm:689 + jne short 00933h ; 75 58 ; 0xc08d9 vberom.asm:690 + push ax ; 50 ; 0xc08db vberom.asm:145 + push cx ; 51 ; 0xc08dc vberom.asm:146 + push dx ; 52 ; 0xc08dd vberom.asm:147 + push bx ; 53 ; 0xc08de vberom.asm:148 + push sp ; 54 ; 0xc08df vberom.asm:149 + push bp ; 55 ; 0xc08e0 vberom.asm:150 + push si ; 56 ; 0xc08e1 vberom.asm:151 + push di ; 57 ; 0xc08e2 vberom.asm:152 + push DS ; 1e ; 0xc08e3 vberom.asm:696 + push ES ; 06 ; 0xc08e4 vberom.asm:697 + pop DS ; 1f ; 0xc08e5 vberom.asm:698 + db 08ah, 0c2h + ; mov al, dl ; 8a c2 ; 0xc08e6 vberom.asm:699 + mov dx, 003c8h ; ba c8 03 ; 0xc08e8 vberom.asm:700 + out DX, AL ; ee ; 0xc08eb vberom.asm:701 + inc dx ; 42 ; 0xc08ec vberom.asm:702 + db 08bh, 0f7h + ; mov si, di ; 8b f7 ; 0xc08ed vberom.asm:703 + lodsw ; ad ; 0xc08ef vberom.asm:714 + db 08bh, 0d8h + ; mov bx, ax ; 8b d8 ; 0xc08f0 vberom.asm:715 + lodsw ; ad ; 0xc08f2 vberom.asm:716 + out DX, AL ; ee ; 0xc08f3 vberom.asm:717 + db 08ah, 0c7h + ; mov al, bh ; 8a c7 ; 0xc08f4 vberom.asm:718 + out DX, AL ; ee ; 0xc08f6 vberom.asm:719 + db 08ah, 0c3h + ; mov al, bl ; 8a c3 ; 0xc08f7 vberom.asm:720 + out DX, AL ; ee ; 0xc08f9 vberom.asm:721 + loop 008efh ; e2 f3 ; 0xc08fa vberom.asm:723 + pop DS ; 1f ; 0xc08fc vberom.asm:724 + pop di ; 5f ; 0xc08fd vberom.asm:164 + pop si ; 5e ; 0xc08fe vberom.asm:165 + pop bp ; 5d ; 0xc08ff vberom.asm:166 + pop bx ; 5b ; 0xc0900 vberom.asm:167 + pop bx ; 5b ; 0xc0901 vberom.asm:168 + pop dx ; 5a ; 0xc0902 vberom.asm:169 + pop cx ; 59 ; 0xc0903 vberom.asm:170 + pop ax ; 58 ; 0xc0904 vberom.asm:171 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0905 vberom.asm:727 + retn ; c3 ; 0xc0908 vberom.asm:728 + push ax ; 50 ; 0xc0909 vberom.asm:145 + push cx ; 51 ; 0xc090a vberom.asm:146 + push dx ; 52 ; 0xc090b vberom.asm:147 + push bx ; 53 ; 0xc090c vberom.asm:148 + push sp ; 54 ; 0xc090d vberom.asm:149 + push bp ; 55 ; 0xc090e vberom.asm:150 + push si ; 56 ; 0xc090f vberom.asm:151 + push di ; 57 ; 0xc0910 vberom.asm:152 + db 08ah, 0c2h + ; mov al, dl ; 8a c2 ; 0xc0911 vberom.asm:732 + mov dx, 003c7h ; ba c7 03 ; 0xc0913 vberom.asm:733 + out DX, AL ; ee ; 0xc0916 vberom.asm:734 + add dl, 002h ; 80 c2 02 ; 0xc0917 vberom.asm:735 + db 033h, 0dbh + ; xor bx, bx ; 33 db ; 0xc091a vberom.asm:746 + in AL, DX ; ec ; 0xc091c vberom.asm:748 + db 08ah, 0d8h + ; mov bl, al ; 8a d8 ; 0xc091d vberom.asm:749 + in AL, DX ; ec ; 0xc091f vberom.asm:750 + db 08ah, 0e0h + ; mov ah, al ; 8a e0 ; 0xc0920 vberom.asm:751 + in AL, DX ; ec ; 0xc0922 vberom.asm:752 + stosw ; ab ; 0xc0923 vberom.asm:753 + db 08bh, 0c3h + ; mov ax, bx ; 8b c3 ; 0xc0924 vberom.asm:754 + stosw ; ab ; 0xc0926 vberom.asm:755 + loop 0091ch ; e2 f3 ; 0xc0927 vberom.asm:757 + pop di ; 5f ; 0xc0929 vberom.asm:164 + pop si ; 5e ; 0xc092a vberom.asm:165 + pop bp ; 5d ; 0xc092b vberom.asm:166 + pop bx ; 5b ; 0xc092c vberom.asm:167 + pop bx ; 5b ; 0xc092d vberom.asm:168 + pop dx ; 5a ; 0xc092e vberom.asm:169 + pop cx ; 59 ; 0xc092f vberom.asm:170 + pop ax ; 58 ; 0xc0930 vberom.asm:171 + jmp short 00905h ; eb d2 ; 0xc0931 vberom.asm:759 + mov ax, 0014fh ; b8 4f 01 ; 0xc0933 vberom.asm:762 + retn ; c3 ; 0xc0936 vberom.asm:763 + mov ax, 0024fh ; b8 4f 02 ; 0xc0937 vberom.asm:765 + retn ; c3 ; 0xc093a vberom.asm:766 + ; disGetNextSymbol 0xc093b LB 0x14 -> off=0x0 cb=0000000000000014 uValue=00000000000c093b 'vbe_biosfn_return_protected_mode_interface' +vbe_biosfn_return_protected_mode_interface: ; 0xc093b LB 0x14 + test bl, bl ; 84 db ; 0xc093b vberom.asm:780 + jne short 0094bh ; 75 0c ; 0xc093d vberom.asm:781 + push CS ; 0e ; 0xc093f vberom.asm:782 + pop ES ; 07 ; 0xc0940 vberom.asm:783 + mov di, 04640h ; bf 40 46 ; 0xc0941 vberom.asm:784 + mov cx, 00115h ; b9 15 01 ; 0xc0944 vberom.asm:785 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc0947 vberom.asm:786 + retn ; c3 ; 0xc094a vberom.asm:787 + mov ax, 0014fh ; b8 4f 01 ; 0xc094b vberom.asm:789 + retn ; c3 ; 0xc094e vberom.asm:790 + + ; Padding 0xa1 bytes at 0xc094f + times 161 db 0 + +section _TEXT progbits vstart=0x9f0 align=1 ; size=0x3b74 class=CODE group=AUTO + ; disGetNextSymbol 0xc09f0 LB 0x3b74 -> off=0x0 cb=000000000000001c uValue=00000000000c09f0 'set_int_vector' +set_int_vector: ; 0xc09f0 LB 0x1c + push dx ; 52 ; 0xc09f0 vgabios.c:87 + push bp ; 55 ; 0xc09f1 + mov bp, sp ; 89 e5 ; 0xc09f2 + mov dx, bx ; 89 da ; 0xc09f4 + mov bl, al ; 88 c3 ; 0xc09f6 vgabios.c:91 + xor bh, bh ; 30 ff ; 0xc09f8 + sal bx, 1 ; d1 e3 ; 0xc09fa + sal bx, 1 ; d1 e3 ; 0xc09fc + xor ax, ax ; 31 c0 ; 0xc09fe + mov es, ax ; 8e c0 ; 0xc0a00 + mov word [es:bx], dx ; 26 89 17 ; 0xc0a02 + mov word [es:bx+002h], cx ; 26 89 4f 02 ; 0xc0a05 + pop bp ; 5d ; 0xc0a09 vgabios.c:92 + pop dx ; 5a ; 0xc0a0a + retn ; c3 ; 0xc0a0b + ; disGetNextSymbol 0xc0a0c LB 0x3b58 -> off=0x0 cb=000000000000001c uValue=00000000000c0a0c 'init_vga_card' +init_vga_card: ; 0xc0a0c LB 0x1c + push bp ; 55 ; 0xc0a0c vgabios.c:143 + mov bp, sp ; 89 e5 ; 0xc0a0d + push dx ; 52 ; 0xc0a0f + mov AL, strict byte 0c3h ; b0 c3 ; 0xc0a10 vgabios.c:146 + mov dx, 003c2h ; ba c2 03 ; 0xc0a12 + out DX, AL ; ee ; 0xc0a15 + mov AL, strict byte 004h ; b0 04 ; 0xc0a16 vgabios.c:149 + mov dx, 003c4h ; ba c4 03 ; 0xc0a18 + out DX, AL ; ee ; 0xc0a1b + mov AL, strict byte 002h ; b0 02 ; 0xc0a1c vgabios.c:150 + mov dx, 003c5h ; ba c5 03 ; 0xc0a1e + out DX, AL ; ee ; 0xc0a21 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc0a22 vgabios.c:155 + pop dx ; 5a ; 0xc0a25 + pop bp ; 5d ; 0xc0a26 + retn ; c3 ; 0xc0a27 + ; disGetNextSymbol 0xc0a28 LB 0x3b3c -> off=0x0 cb=000000000000003e uValue=00000000000c0a28 'init_bios_area' +init_bios_area: ; 0xc0a28 LB 0x3e + push bx ; 53 ; 0xc0a28 vgabios.c:221 + push bp ; 55 ; 0xc0a29 + mov bp, sp ; 89 e5 ; 0xc0a2a + xor bx, bx ; 31 db ; 0xc0a2c vgabios.c:225 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0a2e + mov es, ax ; 8e c0 ; 0xc0a31 + mov al, byte [es:bx+010h] ; 26 8a 47 10 ; 0xc0a33 vgabios.c:228 + and AL, strict byte 0cfh ; 24 cf ; 0xc0a37 + or AL, strict byte 020h ; 0c 20 ; 0xc0a39 + mov byte [es:bx+010h], al ; 26 88 47 10 ; 0xc0a3b + mov byte [es:bx+00085h], 010h ; 26 c6 87 85 00 10 ; 0xc0a3f vgabios.c:232 + mov word [es:bx+00087h], 0f960h ; 26 c7 87 87 00 60 f9 ; 0xc0a45 vgabios.c:234 + mov byte [es:bx+00089h], 051h ; 26 c6 87 89 00 51 ; 0xc0a4c vgabios.c:238 + mov byte [es:bx+065h], 009h ; 26 c6 47 65 09 ; 0xc0a52 vgabios.c:240 + mov word [es:bx+000a8h], 05551h ; 26 c7 87 a8 00 51 55 ; 0xc0a57 vgabios.c:242 + mov [es:bx+000aah], ds ; 26 8c 9f aa 00 ; 0xc0a5e + pop bp ; 5d ; 0xc0a63 vgabios.c:243 + pop bx ; 5b ; 0xc0a64 + retn ; c3 ; 0xc0a65 + ; disGetNextSymbol 0xc0a66 LB 0x3afe -> off=0x0 cb=0000000000000031 uValue=00000000000c0a66 'vgabios_init_func' +vgabios_init_func: ; 0xc0a66 LB 0x31 + inc bp ; 45 ; 0xc0a66 vgabios.c:250 + push bp ; 55 ; 0xc0a67 + mov bp, sp ; 89 e5 ; 0xc0a68 + call 00a0ch ; e8 9f ff ; 0xc0a6a vgabios.c:252 + call 00a28h ; e8 b8 ff ; 0xc0a6d vgabios.c:253 + call 03ed5h ; e8 62 34 ; 0xc0a70 vgabios.c:255 + mov bx, strict word 00028h ; bb 28 00 ; 0xc0a73 vgabios.c:257 + mov cx, 0c000h ; b9 00 c0 ; 0xc0a76 + mov ax, strict word 00010h ; b8 10 00 ; 0xc0a79 + call 009f0h ; e8 71 ff ; 0xc0a7c + mov bx, strict word 00028h ; bb 28 00 ; 0xc0a7f vgabios.c:258 + mov cx, 0c000h ; b9 00 c0 ; 0xc0a82 + mov ax, strict word 0006dh ; b8 6d 00 ; 0xc0a85 + call 009f0h ; e8 65 ff ; 0xc0a88 + mov ax, strict word 00003h ; b8 03 00 ; 0xc0a8b vgabios.c:284 + db 032h, 0e4h + ; xor ah, ah ; 32 e4 ; 0xc0a8e + int 010h ; cd 10 ; 0xc0a90 + mov sp, bp ; 89 ec ; 0xc0a92 vgabios.c:287 + pop bp ; 5d ; 0xc0a94 + dec bp ; 4d ; 0xc0a95 + retf ; cb ; 0xc0a96 + ; disGetNextSymbol 0xc0a97 LB 0x3acd -> off=0x0 cb=0000000000000040 uValue=00000000000c0a97 'vga_get_cursor_pos' +vga_get_cursor_pos: ; 0xc0a97 LB 0x40 + push si ; 56 ; 0xc0a97 vgabios.c:356 + push di ; 57 ; 0xc0a98 + push bp ; 55 ; 0xc0a99 + mov bp, sp ; 89 e5 ; 0xc0a9a + mov si, dx ; 89 d6 ; 0xc0a9c + cmp AL, strict byte 007h ; 3c 07 ; 0xc0a9e vgabios.c:358 + jbe short 00ab0h ; 76 0e ; 0xc0aa0 + push SS ; 16 ; 0xc0aa2 vgabios.c:359 + pop ES ; 07 ; 0xc0aa3 + mov word [es:si], strict word 00000h ; 26 c7 04 00 00 ; 0xc0aa4 + mov word [es:bx], strict word 00000h ; 26 c7 07 00 00 ; 0xc0aa9 vgabios.c:360 + jmp short 00ad3h ; eb 23 ; 0xc0aae vgabios.c:361 + mov di, strict word 00060h ; bf 60 00 ; 0xc0ab0 vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc0ab3 + mov es, dx ; 8e c2 ; 0xc0ab6 + mov di, word [es:di] ; 26 8b 3d ; 0xc0ab8 + push SS ; 16 ; 0xc0abb vgabios.c:58 + pop ES ; 07 ; 0xc0abc + mov word [es:si], di ; 26 89 3c ; 0xc0abd + xor ah, ah ; 30 e4 ; 0xc0ac0 vgabios.c:364 + mov si, ax ; 89 c6 ; 0xc0ac2 + sal si, 1 ; d1 e6 ; 0xc0ac4 + add si, strict byte 00050h ; 83 c6 50 ; 0xc0ac6 + mov es, dx ; 8e c2 ; 0xc0ac9 vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc0acb + push SS ; 16 ; 0xc0ace vgabios.c:58 + pop ES ; 07 ; 0xc0acf + mov word [es:bx], ax ; 26 89 07 ; 0xc0ad0 + pop bp ; 5d ; 0xc0ad3 vgabios.c:366 + pop di ; 5f ; 0xc0ad4 + pop si ; 5e ; 0xc0ad5 + retn ; c3 ; 0xc0ad6 + ; disGetNextSymbol 0xc0ad7 LB 0x3a8d -> off=0x0 cb=000000000000005e uValue=00000000000c0ad7 'vga_find_glyph' +vga_find_glyph: ; 0xc0ad7 LB 0x5e + push bp ; 55 ; 0xc0ad7 vgabios.c:369 + mov bp, sp ; 89 e5 ; 0xc0ad8 + push si ; 56 ; 0xc0ada + push di ; 57 ; 0xc0adb + push ax ; 50 ; 0xc0adc + push ax ; 50 ; 0xc0add + push dx ; 52 ; 0xc0ade + push bx ; 53 ; 0xc0adf + mov bl, cl ; 88 cb ; 0xc0ae0 + mov word [bp-006h], strict word 00000h ; c7 46 fa 00 00 ; 0xc0ae2 vgabios.c:371 + dec word [bp+004h] ; ff 4e 04 ; 0xc0ae7 vgabios.c:373 + cmp word [bp+004h], strict byte 0ffffh ; 83 7e 04 ff ; 0xc0aea + je short 00b29h ; 74 39 ; 0xc0aee + mov cl, byte [bp+006h] ; 8a 4e 06 ; 0xc0af0 vgabios.c:374 + xor ch, ch ; 30 ed ; 0xc0af3 + mov dx, ss ; 8c d2 ; 0xc0af5 + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc0af7 + mov di, word [bp-008h] ; 8b 7e f8 ; 0xc0afa + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc0afd + push DS ; 1e ; 0xc0b00 + mov ds, dx ; 8e da ; 0xc0b01 + rep cmpsb ; f3 a6 ; 0xc0b03 + pop DS ; 1f ; 0xc0b05 + mov ax, strict word 00000h ; b8 00 00 ; 0xc0b06 + je short 00b0dh ; 74 02 ; 0xc0b09 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc0b0b + test ax, ax ; 85 c0 ; 0xc0b0d + jne short 00b1dh ; 75 0c ; 0xc0b0f + mov al, bl ; 88 d8 ; 0xc0b11 vgabios.c:375 + xor ah, ah ; 30 e4 ; 0xc0b13 + or ah, 080h ; 80 cc 80 ; 0xc0b15 + mov word [bp-006h], ax ; 89 46 fa ; 0xc0b18 + jmp short 00b29h ; eb 0c ; 0xc0b1b vgabios.c:376 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc0b1d vgabios.c:378 + xor ah, ah ; 30 e4 ; 0xc0b20 + add word [bp-008h], ax ; 01 46 f8 ; 0xc0b22 + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc0b25 vgabios.c:379 + jmp short 00ae7h ; eb be ; 0xc0b27 vgabios.c:380 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc0b29 vgabios.c:382 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0b2c + pop di ; 5f ; 0xc0b2f + pop si ; 5e ; 0xc0b30 + pop bp ; 5d ; 0xc0b31 + retn 00004h ; c2 04 00 ; 0xc0b32 + ; disGetNextSymbol 0xc0b35 LB 0x3a2f -> off=0x0 cb=0000000000000046 uValue=00000000000c0b35 'vga_read_glyph_planar' +vga_read_glyph_planar: ; 0xc0b35 LB 0x46 + push bp ; 55 ; 0xc0b35 vgabios.c:384 + mov bp, sp ; 89 e5 ; 0xc0b36 + push si ; 56 ; 0xc0b38 + push di ; 57 ; 0xc0b39 + push ax ; 50 ; 0xc0b3a + push ax ; 50 ; 0xc0b3b + mov si, ax ; 89 c6 ; 0xc0b3c + mov word [bp-006h], dx ; 89 56 fa ; 0xc0b3e + mov word [bp-008h], bx ; 89 5e f8 ; 0xc0b41 + mov bx, cx ; 89 cb ; 0xc0b44 + mov ax, 00805h ; b8 05 08 ; 0xc0b46 vgabios.c:391 + mov dx, 003ceh ; ba ce 03 ; 0xc0b49 + out DX, ax ; ef ; 0xc0b4c + dec byte [bp+004h] ; fe 4e 04 ; 0xc0b4d vgabios.c:393 + cmp byte [bp+004h], 0ffh ; 80 7e 04 ff ; 0xc0b50 + je short 00b6bh ; 74 15 ; 0xc0b54 + mov es, [bp-006h] ; 8e 46 fa ; 0xc0b56 vgabios.c:394 + mov al, byte [es:si] ; 26 8a 04 ; 0xc0b59 + not al ; f6 d0 ; 0xc0b5c + mov di, bx ; 89 df ; 0xc0b5e + inc bx ; 43 ; 0xc0b60 + push SS ; 16 ; 0xc0b61 + pop ES ; 07 ; 0xc0b62 + mov byte [es:di], al ; 26 88 05 ; 0xc0b63 + add si, word [bp-008h] ; 03 76 f8 ; 0xc0b66 vgabios.c:395 + jmp short 00b4dh ; eb e2 ; 0xc0b69 vgabios.c:396 + mov ax, strict word 00005h ; b8 05 00 ; 0xc0b6b vgabios.c:399 + mov dx, 003ceh ; ba ce 03 ; 0xc0b6e + out DX, ax ; ef ; 0xc0b71 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0b72 vgabios.c:400 + pop di ; 5f ; 0xc0b75 + pop si ; 5e ; 0xc0b76 + pop bp ; 5d ; 0xc0b77 + retn 00002h ; c2 02 00 ; 0xc0b78 + ; disGetNextSymbol 0xc0b7b LB 0x39e9 -> off=0x0 cb=000000000000002f uValue=00000000000c0b7b 'vga_char_ofs_planar' +vga_char_ofs_planar: ; 0xc0b7b LB 0x2f + push si ; 56 ; 0xc0b7b vgabios.c:402 + push bp ; 55 ; 0xc0b7c + mov bp, sp ; 89 e5 ; 0xc0b7d + mov ch, al ; 88 c5 ; 0xc0b7f + mov al, dl ; 88 d0 ; 0xc0b81 + xor ah, ah ; 30 e4 ; 0xc0b83 vgabios.c:406 + mul bx ; f7 e3 ; 0xc0b85 + mov bl, byte [bp+006h] ; 8a 5e 06 ; 0xc0b87 + xor bh, bh ; 30 ff ; 0xc0b8a + mul bx ; f7 e3 ; 0xc0b8c + mov bl, ch ; 88 eb ; 0xc0b8e + add bx, ax ; 01 c3 ; 0xc0b90 + mov si, strict word 0004ch ; be 4c 00 ; 0xc0b92 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0b95 + mov es, ax ; 8e c0 ; 0xc0b98 + mov si, word [es:si] ; 26 8b 34 ; 0xc0b9a + mov al, cl ; 88 c8 ; 0xc0b9d vgabios.c:58 + xor ah, ah ; 30 e4 ; 0xc0b9f + mul si ; f7 e6 ; 0xc0ba1 + add ax, bx ; 01 d8 ; 0xc0ba3 + pop bp ; 5d ; 0xc0ba5 vgabios.c:410 + pop si ; 5e ; 0xc0ba6 + retn 00002h ; c2 02 00 ; 0xc0ba7 + ; disGetNextSymbol 0xc0baa LB 0x39ba -> off=0x0 cb=0000000000000045 uValue=00000000000c0baa 'vga_read_char_planar' +vga_read_char_planar: ; 0xc0baa LB 0x45 + push bp ; 55 ; 0xc0baa vgabios.c:412 + mov bp, sp ; 89 e5 ; 0xc0bab + push cx ; 51 ; 0xc0bad + push si ; 56 ; 0xc0bae + sub sp, strict byte 00012h ; 83 ec 12 ; 0xc0baf + mov si, ax ; 89 c6 ; 0xc0bb2 + mov ax, dx ; 89 d0 ; 0xc0bb4 + mov byte [bp-006h], bl ; 88 5e fa ; 0xc0bb6 vgabios.c:416 + mov byte [bp-005h], 000h ; c6 46 fb 00 ; 0xc0bb9 + push word [bp-006h] ; ff 76 fa ; 0xc0bbd + lea cx, [bp-016h] ; 8d 4e ea ; 0xc0bc0 + mov bx, si ; 89 f3 ; 0xc0bc3 + mov dx, 0a000h ; ba 00 a0 ; 0xc0bc5 + call 00b35h ; e8 6a ff ; 0xc0bc8 + push word [bp-006h] ; ff 76 fa ; 0xc0bcb vgabios.c:419 + mov ax, 00100h ; b8 00 01 ; 0xc0bce + push ax ; 50 ; 0xc0bd1 + mov bx, 0010ch ; bb 0c 01 ; 0xc0bd2 vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0bd5 + mov es, ax ; 8e c0 ; 0xc0bd7 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0bd9 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0bdc + xor cx, cx ; 31 c9 ; 0xc0be0 vgabios.c:68 + lea bx, [bp-016h] ; 8d 5e ea ; 0xc0be2 + call 00ad7h ; e8 ef fe ; 0xc0be5 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0be8 vgabios.c:420 + pop si ; 5e ; 0xc0beb + pop cx ; 59 ; 0xc0bec + pop bp ; 5d ; 0xc0bed + retn ; c3 ; 0xc0bee + ; disGetNextSymbol 0xc0bef LB 0x3975 -> off=0x0 cb=0000000000000027 uValue=00000000000c0bef 'vga_char_ofs_linear' +vga_char_ofs_linear: ; 0xc0bef LB 0x27 + push bp ; 55 ; 0xc0bef vgabios.c:422 + mov bp, sp ; 89 e5 ; 0xc0bf0 + push ax ; 50 ; 0xc0bf2 + mov byte [bp-002h], al ; 88 46 fe ; 0xc0bf3 + mov al, dl ; 88 d0 ; 0xc0bf6 vgabios.c:426 + xor ah, ah ; 30 e4 ; 0xc0bf8 + mul bx ; f7 e3 ; 0xc0bfa + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc0bfc + xor dh, dh ; 30 f6 ; 0xc0bff + mul dx ; f7 e2 ; 0xc0c01 + mov dx, ax ; 89 c2 ; 0xc0c03 + mov al, byte [bp-002h] ; 8a 46 fe ; 0xc0c05 + xor ah, ah ; 30 e4 ; 0xc0c08 + add ax, dx ; 01 d0 ; 0xc0c0a + mov CL, strict byte 003h ; b1 03 ; 0xc0c0c vgabios.c:427 + sal ax, CL ; d3 e0 ; 0xc0c0e + mov sp, bp ; 89 ec ; 0xc0c10 vgabios.c:429 + pop bp ; 5d ; 0xc0c12 + retn 00002h ; c2 02 00 ; 0xc0c13 + ; disGetNextSymbol 0xc0c16 LB 0x394e -> off=0x0 cb=000000000000004e uValue=00000000000c0c16 'vga_read_glyph_linear' +vga_read_glyph_linear: ; 0xc0c16 LB 0x4e + push si ; 56 ; 0xc0c16 vgabios.c:431 + push di ; 57 ; 0xc0c17 + push bp ; 55 ; 0xc0c18 + mov bp, sp ; 89 e5 ; 0xc0c19 + push ax ; 50 ; 0xc0c1b + push ax ; 50 ; 0xc0c1c + mov si, ax ; 89 c6 ; 0xc0c1d + mov word [bp-002h], dx ; 89 56 fe ; 0xc0c1f + mov word [bp-004h], bx ; 89 5e fc ; 0xc0c22 + mov bx, cx ; 89 cb ; 0xc0c25 + dec byte [bp+008h] ; fe 4e 08 ; 0xc0c27 vgabios.c:437 + cmp byte [bp+008h], 0ffh ; 80 7e 08 ff ; 0xc0c2a + je short 00c5ch ; 74 2c ; 0xc0c2e + xor dh, dh ; 30 f6 ; 0xc0c30 vgabios.c:438 + mov DL, strict byte 080h ; b2 80 ; 0xc0c32 vgabios.c:439 + xor ax, ax ; 31 c0 ; 0xc0c34 vgabios.c:440 + jmp short 00c3dh ; eb 05 ; 0xc0c36 + cmp ax, strict word 00008h ; 3d 08 00 ; 0xc0c38 + jnl short 00c51h ; 7d 14 ; 0xc0c3b + mov es, [bp-002h] ; 8e 46 fe ; 0xc0c3d vgabios.c:441 + mov di, si ; 89 f7 ; 0xc0c40 + add di, ax ; 01 c7 ; 0xc0c42 + cmp byte [es:di], 000h ; 26 80 3d 00 ; 0xc0c44 + je short 00c4ch ; 74 02 ; 0xc0c48 + or dh, dl ; 08 d6 ; 0xc0c4a vgabios.c:442 + shr dl, 1 ; d0 ea ; 0xc0c4c vgabios.c:443 + inc ax ; 40 ; 0xc0c4e vgabios.c:444 + jmp short 00c38h ; eb e7 ; 0xc0c4f + mov di, bx ; 89 df ; 0xc0c51 vgabios.c:445 + inc bx ; 43 ; 0xc0c53 + mov byte [ss:di], dh ; 36 88 35 ; 0xc0c54 + add si, word [bp-004h] ; 03 76 fc ; 0xc0c57 vgabios.c:446 + jmp short 00c27h ; eb cb ; 0xc0c5a vgabios.c:447 + mov sp, bp ; 89 ec ; 0xc0c5c vgabios.c:448 + pop bp ; 5d ; 0xc0c5e + pop di ; 5f ; 0xc0c5f + pop si ; 5e ; 0xc0c60 + retn 00002h ; c2 02 00 ; 0xc0c61 + ; disGetNextSymbol 0xc0c64 LB 0x3900 -> off=0x0 cb=0000000000000049 uValue=00000000000c0c64 'vga_read_char_linear' +vga_read_char_linear: ; 0xc0c64 LB 0x49 + push bp ; 55 ; 0xc0c64 vgabios.c:450 + mov bp, sp ; 89 e5 ; 0xc0c65 + push cx ; 51 ; 0xc0c67 + push si ; 56 ; 0xc0c68 + sub sp, strict byte 00012h ; 83 ec 12 ; 0xc0c69 + mov si, ax ; 89 c6 ; 0xc0c6c + mov ax, dx ; 89 d0 ; 0xc0c6e + mov byte [bp-006h], bl ; 88 5e fa ; 0xc0c70 vgabios.c:454 + mov byte [bp-005h], 000h ; c6 46 fb 00 ; 0xc0c73 + push word [bp-006h] ; ff 76 fa ; 0xc0c77 + mov CL, strict byte 003h ; b1 03 ; 0xc0c7a + mov bx, si ; 89 f3 ; 0xc0c7c + sal bx, CL ; d3 e3 ; 0xc0c7e + lea cx, [bp-016h] ; 8d 4e ea ; 0xc0c80 + mov dx, 0a000h ; ba 00 a0 ; 0xc0c83 + call 00c16h ; e8 8d ff ; 0xc0c86 + push word [bp-006h] ; ff 76 fa ; 0xc0c89 vgabios.c:457 + mov ax, 00100h ; b8 00 01 ; 0xc0c8c + push ax ; 50 ; 0xc0c8f + mov bx, 0010ch ; bb 0c 01 ; 0xc0c90 vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0c93 + mov es, ax ; 8e c0 ; 0xc0c95 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0c97 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0c9a + xor cx, cx ; 31 c9 ; 0xc0c9e vgabios.c:68 + lea bx, [bp-016h] ; 8d 5e ea ; 0xc0ca0 + call 00ad7h ; e8 31 fe ; 0xc0ca3 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0ca6 vgabios.c:458 + pop si ; 5e ; 0xc0ca9 + pop cx ; 59 ; 0xc0caa + pop bp ; 5d ; 0xc0cab + retn ; c3 ; 0xc0cac + ; disGetNextSymbol 0xc0cad LB 0x38b7 -> off=0x0 cb=0000000000000036 uValue=00000000000c0cad 'vga_read_2bpp_char' +vga_read_2bpp_char: ; 0xc0cad LB 0x36 + push bp ; 55 ; 0xc0cad vgabios.c:460 + mov bp, sp ; 89 e5 ; 0xc0cae + push bx ; 53 ; 0xc0cb0 + push cx ; 51 ; 0xc0cb1 + mov bx, ax ; 89 c3 ; 0xc0cb2 + mov es, dx ; 8e c2 ; 0xc0cb4 + mov cx, 0c000h ; b9 00 c0 ; 0xc0cb6 vgabios.c:466 + mov DH, strict byte 080h ; b6 80 ; 0xc0cb9 vgabios.c:467 + xor dl, dl ; 30 d2 ; 0xc0cbb vgabios.c:468 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0cbd vgabios.c:469 + xchg ah, al ; 86 c4 ; 0xc0cc0 + xor bx, bx ; 31 db ; 0xc0cc2 vgabios.c:471 + jmp short 00ccbh ; eb 05 ; 0xc0cc4 + cmp bx, strict byte 00008h ; 83 fb 08 ; 0xc0cc6 + jnl short 00cdah ; 7d 0f ; 0xc0cc9 + test ax, cx ; 85 c8 ; 0xc0ccb vgabios.c:472 + je short 00cd1h ; 74 02 ; 0xc0ccd + or dl, dh ; 08 f2 ; 0xc0ccf vgabios.c:473 + shr dh, 1 ; d0 ee ; 0xc0cd1 vgabios.c:474 + shr cx, 1 ; d1 e9 ; 0xc0cd3 vgabios.c:475 + shr cx, 1 ; d1 e9 ; 0xc0cd5 + inc bx ; 43 ; 0xc0cd7 vgabios.c:476 + jmp short 00cc6h ; eb ec ; 0xc0cd8 + mov al, dl ; 88 d0 ; 0xc0cda vgabios.c:478 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0cdc + pop cx ; 59 ; 0xc0cdf + pop bx ; 5b ; 0xc0ce0 + pop bp ; 5d ; 0xc0ce1 + retn ; c3 ; 0xc0ce2 + ; disGetNextSymbol 0xc0ce3 LB 0x3881 -> off=0x0 cb=0000000000000084 uValue=00000000000c0ce3 'vga_read_glyph_cga' +vga_read_glyph_cga: ; 0xc0ce3 LB 0x84 + push bp ; 55 ; 0xc0ce3 vgabios.c:480 + mov bp, sp ; 89 e5 ; 0xc0ce4 + push cx ; 51 ; 0xc0ce6 + push si ; 56 ; 0xc0ce7 + push di ; 57 ; 0xc0ce8 + push ax ; 50 ; 0xc0ce9 + mov si, dx ; 89 d6 ; 0xc0cea + cmp bl, 006h ; 80 fb 06 ; 0xc0cec vgabios.c:488 + je short 00d2bh ; 74 3a ; 0xc0cef + mov bx, ax ; 89 c3 ; 0xc0cf1 vgabios.c:490 + sal bx, 1 ; d1 e3 ; 0xc0cf3 + mov word [bp-008h], 0b800h ; c7 46 f8 00 b8 ; 0xc0cf5 + xor cx, cx ; 31 c9 ; 0xc0cfa vgabios.c:492 + jmp short 00d03h ; eb 05 ; 0xc0cfc + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc0cfe + jnl short 00d5fh ; 7d 5c ; 0xc0d01 + mov ax, bx ; 89 d8 ; 0xc0d03 vgabios.c:493 + mov dx, word [bp-008h] ; 8b 56 f8 ; 0xc0d05 + call 00cadh ; e8 a2 ff ; 0xc0d08 + mov di, si ; 89 f7 ; 0xc0d0b + inc si ; 46 ; 0xc0d0d + push SS ; 16 ; 0xc0d0e + pop ES ; 07 ; 0xc0d0f + mov byte [es:di], al ; 26 88 05 ; 0xc0d10 + lea ax, [bx+02000h] ; 8d 87 00 20 ; 0xc0d13 vgabios.c:494 + mov dx, word [bp-008h] ; 8b 56 f8 ; 0xc0d17 + call 00cadh ; e8 90 ff ; 0xc0d1a + mov di, si ; 89 f7 ; 0xc0d1d + inc si ; 46 ; 0xc0d1f + push SS ; 16 ; 0xc0d20 + pop ES ; 07 ; 0xc0d21 + mov byte [es:di], al ; 26 88 05 ; 0xc0d22 + add bx, strict byte 00050h ; 83 c3 50 ; 0xc0d25 vgabios.c:495 + inc cx ; 41 ; 0xc0d28 vgabios.c:496 + jmp short 00cfeh ; eb d3 ; 0xc0d29 + mov bx, ax ; 89 c3 ; 0xc0d2b vgabios.c:498 + mov word [bp-008h], 0b800h ; c7 46 f8 00 b8 ; 0xc0d2d + xor cx, cx ; 31 c9 ; 0xc0d32 vgabios.c:499 + jmp short 00d3bh ; eb 05 ; 0xc0d34 + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc0d36 + jnl short 00d5fh ; 7d 24 ; 0xc0d39 + mov di, si ; 89 f7 ; 0xc0d3b vgabios.c:500 + inc si ; 46 ; 0xc0d3d + mov es, [bp-008h] ; 8e 46 f8 ; 0xc0d3e + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0d41 + push SS ; 16 ; 0xc0d44 + pop ES ; 07 ; 0xc0d45 + mov byte [es:di], al ; 26 88 05 ; 0xc0d46 + mov di, si ; 89 f7 ; 0xc0d49 vgabios.c:501 + inc si ; 46 ; 0xc0d4b + mov es, [bp-008h] ; 8e 46 f8 ; 0xc0d4c + mov al, byte [es:bx+02000h] ; 26 8a 87 00 20 ; 0xc0d4f + push SS ; 16 ; 0xc0d54 + pop ES ; 07 ; 0xc0d55 + mov byte [es:di], al ; 26 88 05 ; 0xc0d56 + add bx, strict byte 00050h ; 83 c3 50 ; 0xc0d59 vgabios.c:502 + inc cx ; 41 ; 0xc0d5c vgabios.c:503 + jmp short 00d36h ; eb d7 ; 0xc0d5d + lea sp, [bp-006h] ; 8d 66 fa ; 0xc0d5f vgabios.c:505 + pop di ; 5f ; 0xc0d62 + pop si ; 5e ; 0xc0d63 + pop cx ; 59 ; 0xc0d64 + pop bp ; 5d ; 0xc0d65 + retn ; c3 ; 0xc0d66 + ; disGetNextSymbol 0xc0d67 LB 0x37fd -> off=0x0 cb=000000000000001b uValue=00000000000c0d67 'vga_char_ofs_cga' +vga_char_ofs_cga: ; 0xc0d67 LB 0x1b + push cx ; 51 ; 0xc0d67 vgabios.c:507 + push bp ; 55 ; 0xc0d68 + mov bp, sp ; 89 e5 ; 0xc0d69 + mov cl, al ; 88 c1 ; 0xc0d6b + mov al, dl ; 88 d0 ; 0xc0d6d + xor ah, ah ; 30 e4 ; 0xc0d6f vgabios.c:512 + mul bx ; f7 e3 ; 0xc0d71 + mov bx, ax ; 89 c3 ; 0xc0d73 + sal bx, 1 ; d1 e3 ; 0xc0d75 + sal bx, 1 ; d1 e3 ; 0xc0d77 + mov al, cl ; 88 c8 ; 0xc0d79 + xor ah, ah ; 30 e4 ; 0xc0d7b + add ax, bx ; 01 d8 ; 0xc0d7d + pop bp ; 5d ; 0xc0d7f vgabios.c:513 + pop cx ; 59 ; 0xc0d80 + retn ; c3 ; 0xc0d81 + ; disGetNextSymbol 0xc0d82 LB 0x37e2 -> off=0x0 cb=000000000000006b uValue=00000000000c0d82 'vga_read_char_cga' +vga_read_char_cga: ; 0xc0d82 LB 0x6b + push bp ; 55 ; 0xc0d82 vgabios.c:515 + mov bp, sp ; 89 e5 ; 0xc0d83 + push bx ; 53 ; 0xc0d85 + push cx ; 51 ; 0xc0d86 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc0d87 + mov bl, dl ; 88 d3 ; 0xc0d8a vgabios.c:521 + xor bh, bh ; 30 ff ; 0xc0d8c + lea dx, [bp-00eh] ; 8d 56 f2 ; 0xc0d8e + call 00ce3h ; e8 4f ff ; 0xc0d91 + mov ax, strict word 00008h ; b8 08 00 ; 0xc0d94 vgabios.c:524 + push ax ; 50 ; 0xc0d97 + mov ax, 00080h ; b8 80 00 ; 0xc0d98 + push ax ; 50 ; 0xc0d9b + mov bx, 0010ch ; bb 0c 01 ; 0xc0d9c vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0d9f + mov es, ax ; 8e c0 ; 0xc0da1 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0da3 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0da6 + xor cx, cx ; 31 c9 ; 0xc0daa vgabios.c:68 + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc0dac + call 00ad7h ; e8 25 fd ; 0xc0daf + mov word [bp-006h], ax ; 89 46 fa ; 0xc0db2 + test ah, 080h ; f6 c4 80 ; 0xc0db5 vgabios.c:526 + jne short 00de3h ; 75 29 ; 0xc0db8 + mov bx, strict word 0007ch ; bb 7c 00 ; 0xc0dba vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0dbd + mov es, ax ; 8e c0 ; 0xc0dbf + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0dc1 + mov dx, word [es:bx+002h] ; 26 8b 57 02 ; 0xc0dc4 + test dx, dx ; 85 d2 ; 0xc0dc8 vgabios.c:530 + jne short 00dd0h ; 75 04 ; 0xc0dca + test ax, ax ; 85 c0 ; 0xc0dcc + je short 00de3h ; 74 13 ; 0xc0dce + mov bx, strict word 00008h ; bb 08 00 ; 0xc0dd0 vgabios.c:531 + push bx ; 53 ; 0xc0dd3 + mov bx, 00080h ; bb 80 00 ; 0xc0dd4 + push bx ; 53 ; 0xc0dd7 + mov cx, bx ; 89 d9 ; 0xc0dd8 + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc0dda + call 00ad7h ; e8 f7 fc ; 0xc0ddd + mov word [bp-006h], ax ; 89 46 fa ; 0xc0de0 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc0de3 vgabios.c:534 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc0de6 + pop cx ; 59 ; 0xc0de9 + pop bx ; 5b ; 0xc0dea + pop bp ; 5d ; 0xc0deb + retn ; c3 ; 0xc0dec + ; disGetNextSymbol 0xc0ded LB 0x3777 -> off=0x0 cb=0000000000000147 uValue=00000000000c0ded 'vga_read_char_attr' +vga_read_char_attr: ; 0xc0ded LB 0x147 + push bp ; 55 ; 0xc0ded vgabios.c:536 + mov bp, sp ; 89 e5 ; 0xc0dee + push bx ; 53 ; 0xc0df0 + push cx ; 51 ; 0xc0df1 + push si ; 56 ; 0xc0df2 + push di ; 57 ; 0xc0df3 + sub sp, strict byte 00012h ; 83 ec 12 ; 0xc0df4 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc0df7 + mov si, dx ; 89 d6 ; 0xc0dfa + mov bx, strict word 00049h ; bb 49 00 ; 0xc0dfc vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0dff + mov es, ax ; 8e c0 ; 0xc0e02 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0e04 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc0e07 vgabios.c:48 + xor ah, ah ; 30 e4 ; 0xc0e0a vgabios.c:544 + call 03888h ; e8 79 2a ; 0xc0e0c + mov cl, al ; 88 c1 ; 0xc0e0f + cmp AL, strict byte 0ffh ; 3c ff ; 0xc0e11 vgabios.c:545 + jne short 00e18h ; 75 03 ; 0xc0e13 + jmp near 00f2bh ; e9 13 01 ; 0xc0e15 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc0e18 vgabios.c:549 + mov byte [bp-014h], al ; 88 46 ec ; 0xc0e1b + mov byte [bp-013h], 000h ; c6 46 ed 00 ; 0xc0e1e + lea bx, [bp-01ah] ; 8d 5e e6 ; 0xc0e22 + lea dx, [bp-018h] ; 8d 56 e8 ; 0xc0e25 + mov ax, word [bp-014h] ; 8b 46 ec ; 0xc0e28 + call 00a97h ; e8 69 fc ; 0xc0e2b + mov ch, byte [bp-01ah] ; 8a 6e e6 ; 0xc0e2e vgabios.c:550 + mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xc0e31 vgabios.c:551 + mov al, ah ; 88 e0 ; 0xc0e34 + xor ah, ah ; 30 e4 ; 0xc0e36 + mov word [bp-012h], ax ; 89 46 ee ; 0xc0e38 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc0e3b + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc0e3e + mov bx, 00084h ; bb 84 00 ; 0xc0e41 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0e44 + mov es, ax ; 8e c0 ; 0xc0e47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0e49 + xor ah, ah ; 30 e4 ; 0xc0e4c vgabios.c:48 + mov dx, ax ; 89 c2 ; 0xc0e4e + inc dx ; 42 ; 0xc0e50 + mov di, strict word 0004ah ; bf 4a 00 ; 0xc0e51 vgabios.c:57 + mov di, word [es:di] ; 26 8b 3d ; 0xc0e54 + mov word [bp-016h], di ; 89 7e ea ; 0xc0e57 vgabios.c:58 + mov bl, cl ; 88 cb ; 0xc0e5a vgabios.c:557 + xor bh, bh ; 30 ff ; 0xc0e5c + mov CL, strict byte 003h ; b1 03 ; 0xc0e5e + sal bx, CL ; d3 e3 ; 0xc0e60 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc0e62 + jne short 00e9fh ; 75 36 ; 0xc0e67 + mov ax, di ; 89 f8 ; 0xc0e69 vgabios.c:559 + mul dx ; f7 e2 ; 0xc0e6b + sal ax, 1 ; d1 e0 ; 0xc0e6d + or AL, strict byte 0ffh ; 0c ff ; 0xc0e6f + mov dl, byte [bp-00ch] ; 8a 56 f4 ; 0xc0e71 + xor dh, dh ; 30 f6 ; 0xc0e74 + inc ax ; 40 ; 0xc0e76 + mul dx ; f7 e2 ; 0xc0e77 + mov word [bp-010h], ax ; 89 46 f0 ; 0xc0e79 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc0e7c + xor ah, ah ; 30 e4 ; 0xc0e7f + mul di ; f7 e7 ; 0xc0e81 + mov dl, ch ; 88 ea ; 0xc0e83 + xor dh, dh ; 30 f6 ; 0xc0e85 + add ax, dx ; 01 d0 ; 0xc0e87 + sal ax, 1 ; d1 e0 ; 0xc0e89 + mov di, word [bp-010h] ; 8b 7e f0 ; 0xc0e8b + add di, ax ; 01 c7 ; 0xc0e8e + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc0e90 vgabios.c:55 + mov ax, word [es:di] ; 26 8b 05 ; 0xc0e94 + push SS ; 16 ; 0xc0e97 vgabios.c:58 + pop ES ; 07 ; 0xc0e98 + mov word [es:si], ax ; 26 89 04 ; 0xc0e99 + jmp near 00f2bh ; e9 8c 00 ; 0xc0e9c vgabios.c:561 + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc0e9f vgabios.c:562 + cmp bl, 005h ; 80 fb 05 ; 0xc0ea3 + je short 00efeh ; 74 56 ; 0xc0ea6 + cmp bl, 002h ; 80 fb 02 ; 0xc0ea8 + jc short 00eb4h ; 72 07 ; 0xc0eab + jbe short 00eb6h ; 76 07 ; 0xc0ead + cmp bl, 004h ; 80 fb 04 ; 0xc0eaf + jbe short 00ed1h ; 76 1d ; 0xc0eb2 + jmp short 00f2bh ; eb 75 ; 0xc0eb4 + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc0eb6 vgabios.c:565 + xor dh, dh ; 30 f6 ; 0xc0eb9 + mov al, ch ; 88 e8 ; 0xc0ebb + xor ah, ah ; 30 e4 ; 0xc0ebd + mov bx, word [bp-016h] ; 8b 5e ea ; 0xc0ebf + call 00d67h ; e8 a2 fe ; 0xc0ec2 + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc0ec5 vgabios.c:566 + xor dh, dh ; 30 f6 ; 0xc0ec8 + call 00d82h ; e8 b5 fe ; 0xc0eca + xor ah, ah ; 30 e4 ; 0xc0ecd + jmp short 00e97h ; eb c6 ; 0xc0ecf + mov bx, 00085h ; bb 85 00 ; 0xc0ed1 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0ed4 + mov byte [bp-010h], al ; 88 46 f0 ; 0xc0ed7 vgabios.c:571 + mov byte [bp-00fh], 000h ; c6 46 f1 00 ; 0xc0eda + push word [bp-010h] ; ff 76 f0 ; 0xc0ede + mov dl, byte [bp-012h] ; 8a 56 ee ; 0xc0ee1 + xor dh, dh ; 30 f6 ; 0xc0ee4 + mov al, ch ; 88 e8 ; 0xc0ee6 + xor ah, ah ; 30 e4 ; 0xc0ee8 + mov cx, word [bp-014h] ; 8b 4e ec ; 0xc0eea + mov bx, di ; 89 fb ; 0xc0eed + call 00b7bh ; e8 89 fc ; 0xc0eef + mov bx, word [bp-010h] ; 8b 5e f0 ; 0xc0ef2 vgabios.c:572 + mov dx, ax ; 89 c2 ; 0xc0ef5 + mov ax, di ; 89 f8 ; 0xc0ef7 + call 00baah ; e8 ae fc ; 0xc0ef9 + jmp short 00ecdh ; eb cf ; 0xc0efc + mov bx, 00085h ; bb 85 00 ; 0xc0efe vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc0f01 + mov byte [bp-010h], al ; 88 46 f0 ; 0xc0f04 vgabios.c:576 + mov byte [bp-00fh], 000h ; c6 46 f1 00 ; 0xc0f07 + push word [bp-010h] ; ff 76 f0 ; 0xc0f0b + mov dl, byte [bp-012h] ; 8a 56 ee ; 0xc0f0e + xor dh, dh ; 30 f6 ; 0xc0f11 + mov al, ch ; 88 e8 ; 0xc0f13 + xor ah, ah ; 30 e4 ; 0xc0f15 + mov cx, word [bp-014h] ; 8b 4e ec ; 0xc0f17 + mov bx, di ; 89 fb ; 0xc0f1a + call 00befh ; e8 d0 fc ; 0xc0f1c + mov bx, word [bp-010h] ; 8b 5e f0 ; 0xc0f1f vgabios.c:577 + mov dx, ax ; 89 c2 ; 0xc0f22 + mov ax, di ; 89 f8 ; 0xc0f24 + call 00c64h ; e8 3b fd ; 0xc0f26 + jmp short 00ecdh ; eb a2 ; 0xc0f29 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc0f2b vgabios.c:586 + pop di ; 5f ; 0xc0f2e + pop si ; 5e ; 0xc0f2f + pop cx ; 59 ; 0xc0f30 + pop bx ; 5b ; 0xc0f31 + pop bp ; 5d ; 0xc0f32 + retn ; c3 ; 0xc0f33 + ; disGetNextSymbol 0xc0f34 LB 0x3630 -> off=0x10 cb=0000000000000083 uValue=00000000000c0f44 'vga_get_font_info' + db 05bh, 00fh, 0a0h, 00fh, 0a5h, 00fh, 0ach, 00fh, 0b1h, 00fh, 0b6h, 00fh, 0bbh, 00fh, 0c0h, 00fh +vga_get_font_info: ; 0xc0f44 LB 0x83 + push si ; 56 ; 0xc0f44 vgabios.c:588 + push di ; 57 ; 0xc0f45 + push bp ; 55 ; 0xc0f46 + mov bp, sp ; 89 e5 ; 0xc0f47 + mov si, dx ; 89 d6 ; 0xc0f49 + mov di, bx ; 89 df ; 0xc0f4b + cmp ax, strict word 00007h ; 3d 07 00 ; 0xc0f4d vgabios.c:593 + jnbe short 00f9ah ; 77 48 ; 0xc0f50 + mov bx, ax ; 89 c3 ; 0xc0f52 + sal bx, 1 ; d1 e3 ; 0xc0f54 + jmp word [cs:bx+00f34h] ; 2e ff a7 34 0f ; 0xc0f56 + mov bx, strict word 0007ch ; bb 7c 00 ; 0xc0f5b vgabios.c:67 + xor ax, ax ; 31 c0 ; 0xc0f5e + mov es, ax ; 8e c0 ; 0xc0f60 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc0f62 + mov ax, word [es:bx+002h] ; 26 8b 47 02 ; 0xc0f65 + push SS ; 16 ; 0xc0f69 vgabios.c:596 + pop ES ; 07 ; 0xc0f6a + mov word [es:di], dx ; 26 89 15 ; 0xc0f6b + mov word [es:si], ax ; 26 89 04 ; 0xc0f6e + mov bx, 00085h ; bb 85 00 ; 0xc0f71 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0f74 + mov es, ax ; 8e c0 ; 0xc0f77 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0f79 + xor ah, ah ; 30 e4 ; 0xc0f7c + push SS ; 16 ; 0xc0f7e + pop ES ; 07 ; 0xc0f7f + mov bx, cx ; 89 cb ; 0xc0f80 + mov word [es:bx], ax ; 26 89 07 ; 0xc0f82 + mov bx, 00084h ; bb 84 00 ; 0xc0f85 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0f88 + mov es, ax ; 8e c0 ; 0xc0f8b + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0f8d + xor ah, ah ; 30 e4 ; 0xc0f90 + push SS ; 16 ; 0xc0f92 + pop ES ; 07 ; 0xc0f93 + mov bx, word [bp+008h] ; 8b 5e 08 ; 0xc0f94 + mov word [es:bx], ax ; 26 89 07 ; 0xc0f97 + pop bp ; 5d ; 0xc0f9a + pop di ; 5f ; 0xc0f9b + pop si ; 5e ; 0xc0f9c + retn 00002h ; c2 02 00 ; 0xc0f9d + mov bx, 0010ch ; bb 0c 01 ; 0xc0fa0 vgabios.c:67 + jmp short 00f5eh ; eb b9 ; 0xc0fa3 + mov dx, 05d6dh ; ba 6d 5d ; 0xc0fa5 vgabios.c:601 + mov ax, ds ; 8c d8 ; 0xc0fa8 + jmp short 00f69h ; eb bd ; 0xc0faa vgabios.c:602 + mov dx, 0556dh ; ba 6d 55 ; 0xc0fac vgabios.c:604 + jmp short 00fa8h ; eb f7 ; 0xc0faf + mov dx, 0596dh ; ba 6d 59 ; 0xc0fb1 vgabios.c:607 + jmp short 00fa8h ; eb f2 ; 0xc0fb4 + mov dx, 07b6dh ; ba 6d 7b ; 0xc0fb6 vgabios.c:610 + jmp short 00fa8h ; eb ed ; 0xc0fb9 + mov dx, 06b6dh ; ba 6d 6b ; 0xc0fbb vgabios.c:613 + jmp short 00fa8h ; eb e8 ; 0xc0fbe + mov dx, 07c9ah ; ba 9a 7c ; 0xc0fc0 vgabios.c:616 + jmp short 00fa8h ; eb e3 ; 0xc0fc3 + jmp short 00f9ah ; eb d3 ; 0xc0fc5 vgabios.c:622 + ; disGetNextSymbol 0xc0fc7 LB 0x359d -> off=0x0 cb=000000000000016d uValue=00000000000c0fc7 'vga_read_pixel' +vga_read_pixel: ; 0xc0fc7 LB 0x16d + push bp ; 55 ; 0xc0fc7 vgabios.c:635 + mov bp, sp ; 89 e5 ; 0xc0fc8 + push si ; 56 ; 0xc0fca + push di ; 57 ; 0xc0fcb + sub sp, strict byte 0000ch ; 83 ec 0c ; 0xc0fcc + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc0fcf + mov si, dx ; 89 d6 ; 0xc0fd2 + mov word [bp-010h], bx ; 89 5e f0 ; 0xc0fd4 + mov word [bp-00eh], cx ; 89 4e f2 ; 0xc0fd7 + mov bx, strict word 00049h ; bb 49 00 ; 0xc0fda vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc0fdd + mov es, ax ; 8e c0 ; 0xc0fe0 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc0fe2 + xor ah, ah ; 30 e4 ; 0xc0fe5 vgabios.c:642 + call 03888h ; e8 9e 28 ; 0xc0fe7 + mov byte [bp-006h], al ; 88 46 fa ; 0xc0fea + cmp AL, strict byte 0ffh ; 3c ff ; 0xc0fed vgabios.c:643 + je short 01000h ; 74 0f ; 0xc0fef + mov bl, al ; 88 c3 ; 0xc0ff1 vgabios.c:645 + xor bh, bh ; 30 ff ; 0xc0ff3 + mov CL, strict byte 003h ; b1 03 ; 0xc0ff5 + sal bx, CL ; d3 e3 ; 0xc0ff7 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc0ff9 + jne short 01003h ; 75 03 ; 0xc0ffe + jmp near 0112dh ; e9 2a 01 ; 0xc1000 vgabios.c:646 + mov ch, byte [bx+047b1h] ; 8a af b1 47 ; 0xc1003 vgabios.c:649 + cmp ch, cl ; 38 cd ; 0xc1007 + jc short 0101ah ; 72 0f ; 0xc1009 + jbe short 01022h ; 76 15 ; 0xc100b + cmp ch, 005h ; 80 fd 05 ; 0xc100d + je short 0105bh ; 74 49 ; 0xc1010 + cmp ch, 004h ; 80 fd 04 ; 0xc1012 + je short 01022h ; 74 0b ; 0xc1015 + jmp near 01123h ; e9 09 01 ; 0xc1017 + cmp ch, 002h ; 80 fd 02 ; 0xc101a + je short 0108fh ; 74 70 ; 0xc101d + jmp near 01123h ; e9 01 01 ; 0xc101f + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1022 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1025 + mov es, ax ; 8e c0 ; 0xc1028 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc102a + mov ax, word [bp-010h] ; 8b 46 f0 ; 0xc102d vgabios.c:58 + mul bx ; f7 e3 ; 0xc1030 + mov CL, strict byte 003h ; b1 03 ; 0xc1032 + mov bx, si ; 89 f3 ; 0xc1034 + shr bx, CL ; d3 eb ; 0xc1036 + add bx, ax ; 01 c3 ; 0xc1038 + mov di, strict word 0004ch ; bf 4c 00 ; 0xc103a vgabios.c:57 + mov ax, word [es:di] ; 26 8b 05 ; 0xc103d + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc1040 vgabios.c:58 + xor ch, ch ; 30 ed ; 0xc1043 + mul cx ; f7 e1 ; 0xc1045 + add bx, ax ; 01 c3 ; 0xc1047 + mov cx, si ; 89 f1 ; 0xc1049 vgabios.c:654 + and cx, strict byte 00007h ; 83 e1 07 ; 0xc104b + mov ax, 00080h ; b8 80 00 ; 0xc104e + sar ax, CL ; d3 f8 ; 0xc1051 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc1053 + mov byte [bp-008h], ch ; 88 6e f8 ; 0xc1056 vgabios.c:656 + jmp short 01064h ; eb 09 ; 0xc1059 + jmp near 01103h ; e9 a5 00 ; 0xc105b + cmp byte [bp-008h], 004h ; 80 7e f8 04 ; 0xc105e + jnc short 0108ch ; 73 28 ; 0xc1062 + mov ah, byte [bp-008h] ; 8a 66 f8 ; 0xc1064 vgabios.c:657 + xor al, al ; 30 c0 ; 0xc1067 + or AL, strict byte 004h ; 0c 04 ; 0xc1069 + mov dx, 003ceh ; ba ce 03 ; 0xc106b + out DX, ax ; ef ; 0xc106e + mov ax, 0a000h ; b8 00 a0 ; 0xc106f vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc1072 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1074 + and al, byte [bp-00ah] ; 22 46 f6 ; 0xc1077 vgabios.c:48 + test al, al ; 84 c0 ; 0xc107a vgabios.c:659 + jbe short 01087h ; 76 09 ; 0xc107c + mov cl, byte [bp-008h] ; 8a 4e f8 ; 0xc107e vgabios.c:660 + mov AL, strict byte 001h ; b0 01 ; 0xc1081 + sal al, CL ; d2 e0 ; 0xc1083 + or ch, al ; 08 c5 ; 0xc1085 + inc byte [bp-008h] ; fe 46 f8 ; 0xc1087 vgabios.c:661 + jmp short 0105eh ; eb d2 ; 0xc108a + jmp near 01125h ; e9 96 00 ; 0xc108c + mov al, byte [bx+047b2h] ; 8a 87 b2 47 ; 0xc108f vgabios.c:664 + xor ah, ah ; 30 e4 ; 0xc1093 + mov cx, strict word 00004h ; b9 04 00 ; 0xc1095 + sub cx, ax ; 29 c1 ; 0xc1098 + mov ax, dx ; 89 d0 ; 0xc109a + shr ax, CL ; d3 e8 ; 0xc109c + mov cx, ax ; 89 c1 ; 0xc109e + mov ax, word [bp-010h] ; 8b 46 f0 ; 0xc10a0 + shr ax, 1 ; d1 e8 ; 0xc10a3 + mov bx, strict word 00050h ; bb 50 00 ; 0xc10a5 + mul bx ; f7 e3 ; 0xc10a8 + mov bx, cx ; 89 cb ; 0xc10aa + add bx, ax ; 01 c3 ; 0xc10ac + test byte [bp-010h], 001h ; f6 46 f0 01 ; 0xc10ae vgabios.c:665 + je short 010b7h ; 74 03 ; 0xc10b2 + add bh, 020h ; 80 c7 20 ; 0xc10b4 vgabios.c:666 + mov ax, 0b800h ; b8 00 b8 ; 0xc10b7 vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc10ba + mov al, byte [es:bx] ; 26 8a 07 ; 0xc10bc + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc10bf vgabios.c:668 + xor bh, bh ; 30 ff ; 0xc10c2 + mov CL, strict byte 003h ; b1 03 ; 0xc10c4 + sal bx, CL ; d3 e3 ; 0xc10c6 + cmp byte [bx+047b2h], 002h ; 80 bf b2 47 02 ; 0xc10c8 + jne short 010eah ; 75 1b ; 0xc10cd + mov cx, si ; 89 f1 ; 0xc10cf vgabios.c:669 + xor ch, ch ; 30 ed ; 0xc10d1 + and cl, 003h ; 80 e1 03 ; 0xc10d3 + mov bx, strict word 00003h ; bb 03 00 ; 0xc10d6 + sub bx, cx ; 29 cb ; 0xc10d9 + mov cx, bx ; 89 d9 ; 0xc10db + sal cx, 1 ; d1 e1 ; 0xc10dd + xor ah, ah ; 30 e4 ; 0xc10df + sar ax, CL ; d3 f8 ; 0xc10e1 + mov ch, al ; 88 c5 ; 0xc10e3 + and ch, 003h ; 80 e5 03 ; 0xc10e5 + jmp short 01125h ; eb 3b ; 0xc10e8 vgabios.c:670 + mov cx, si ; 89 f1 ; 0xc10ea vgabios.c:671 + xor ch, ch ; 30 ed ; 0xc10ec + and cl, 007h ; 80 e1 07 ; 0xc10ee + mov bx, strict word 00007h ; bb 07 00 ; 0xc10f1 + sub bx, cx ; 29 cb ; 0xc10f4 + mov cx, bx ; 89 d9 ; 0xc10f6 + xor ah, ah ; 30 e4 ; 0xc10f8 + sar ax, CL ; d3 f8 ; 0xc10fa + mov ch, al ; 88 c5 ; 0xc10fc + and ch, 001h ; 80 e5 01 ; 0xc10fe + jmp short 01125h ; eb 22 ; 0xc1101 vgabios.c:672 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1103 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1106 + mov es, ax ; 8e c0 ; 0xc1109 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc110b + sal bx, CL ; d3 e3 ; 0xc110e vgabios.c:58 + mov ax, word [bp-010h] ; 8b 46 f0 ; 0xc1110 + mul bx ; f7 e3 ; 0xc1113 + mov bx, si ; 89 f3 ; 0xc1115 + add bx, ax ; 01 c3 ; 0xc1117 + mov ax, 0a000h ; b8 00 a0 ; 0xc1119 vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc111c + mov ch, byte [es:bx] ; 26 8a 2f ; 0xc111e + jmp short 01125h ; eb 02 ; 0xc1121 vgabios.c:676 + xor ch, ch ; 30 ed ; 0xc1123 vgabios.c:681 + push SS ; 16 ; 0xc1125 vgabios.c:683 + pop ES ; 07 ; 0xc1126 + mov bx, word [bp-00eh] ; 8b 5e f2 ; 0xc1127 + mov byte [es:bx], ch ; 26 88 2f ; 0xc112a + lea sp, [bp-004h] ; 8d 66 fc ; 0xc112d vgabios.c:684 + pop di ; 5f ; 0xc1130 + pop si ; 5e ; 0xc1131 + pop bp ; 5d ; 0xc1132 + retn ; c3 ; 0xc1133 + ; disGetNextSymbol 0xc1134 LB 0x3430 -> off=0x0 cb=000000000000009f uValue=00000000000c1134 'biosfn_perform_gray_scale_summing' +biosfn_perform_gray_scale_summing: ; 0xc1134 LB 0x9f + push bp ; 55 ; 0xc1134 vgabios.c:689 + mov bp, sp ; 89 e5 ; 0xc1135 + push bx ; 53 ; 0xc1137 + push cx ; 51 ; 0xc1138 + push si ; 56 ; 0xc1139 + push di ; 57 ; 0xc113a + push ax ; 50 ; 0xc113b + push ax ; 50 ; 0xc113c + mov bx, ax ; 89 c3 ; 0xc113d + mov di, dx ; 89 d7 ; 0xc113f + mov dx, 003dah ; ba da 03 ; 0xc1141 vgabios.c:694 + in AL, DX ; ec ; 0xc1144 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1145 + xor al, al ; 30 c0 ; 0xc1147 vgabios.c:695 + mov dx, 003c0h ; ba c0 03 ; 0xc1149 + out DX, AL ; ee ; 0xc114c + xor si, si ; 31 f6 ; 0xc114d vgabios.c:697 + cmp si, di ; 39 fe ; 0xc114f + jnc short 011b8h ; 73 65 ; 0xc1151 + mov al, bl ; 88 d8 ; 0xc1153 vgabios.c:700 + mov dx, 003c7h ; ba c7 03 ; 0xc1155 + out DX, AL ; ee ; 0xc1158 + mov dx, 003c9h ; ba c9 03 ; 0xc1159 vgabios.c:702 + in AL, DX ; ec ; 0xc115c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc115d + mov cx, ax ; 89 c1 ; 0xc115f + in AL, DX ; ec ; 0xc1161 vgabios.c:703 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1162 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc1164 + in AL, DX ; ec ; 0xc1167 vgabios.c:704 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1168 + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc116a + mov al, cl ; 88 c8 ; 0xc116d vgabios.c:707 + xor ah, ah ; 30 e4 ; 0xc116f + mov cx, strict word 0004dh ; b9 4d 00 ; 0xc1171 + imul cx ; f7 e9 ; 0xc1174 + mov cx, ax ; 89 c1 ; 0xc1176 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1178 + xor ah, ah ; 30 e4 ; 0xc117b + mov dx, 00097h ; ba 97 00 ; 0xc117d + imul dx ; f7 ea ; 0xc1180 + add cx, ax ; 01 c1 ; 0xc1182 + mov word [bp-00ah], cx ; 89 4e f6 ; 0xc1184 + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc1187 + xor ch, ch ; 30 ed ; 0xc118a + mov ax, cx ; 89 c8 ; 0xc118c + mov dx, strict word 0001ch ; ba 1c 00 ; 0xc118e + imul dx ; f7 ea ; 0xc1191 + add ax, word [bp-00ah] ; 03 46 f6 ; 0xc1193 + add ax, 00080h ; 05 80 00 ; 0xc1196 + mov al, ah ; 88 e0 ; 0xc1199 + cbw ; 98 ; 0xc119b + mov cx, ax ; 89 c1 ; 0xc119c + cmp ax, strict word 0003fh ; 3d 3f 00 ; 0xc119e vgabios.c:709 + jbe short 011a6h ; 76 03 ; 0xc11a1 + mov cx, strict word 0003fh ; b9 3f 00 ; 0xc11a3 + mov al, bl ; 88 d8 ; 0xc11a6 vgabios.c:712 + mov dx, 003c8h ; ba c8 03 ; 0xc11a8 + out DX, AL ; ee ; 0xc11ab + mov al, cl ; 88 c8 ; 0xc11ac vgabios.c:714 + mov dx, 003c9h ; ba c9 03 ; 0xc11ae + out DX, AL ; ee ; 0xc11b1 + out DX, AL ; ee ; 0xc11b2 vgabios.c:715 + out DX, AL ; ee ; 0xc11b3 vgabios.c:716 + inc bx ; 43 ; 0xc11b4 vgabios.c:717 + inc si ; 46 ; 0xc11b5 vgabios.c:718 + jmp short 0114fh ; eb 97 ; 0xc11b6 + mov dx, 003dah ; ba da 03 ; 0xc11b8 vgabios.c:719 + in AL, DX ; ec ; 0xc11bb + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc11bc + mov AL, strict byte 020h ; b0 20 ; 0xc11be vgabios.c:720 + mov dx, 003c0h ; ba c0 03 ; 0xc11c0 + out DX, AL ; ee ; 0xc11c3 + mov dx, 003dah ; ba da 03 ; 0xc11c4 vgabios.c:722 + in AL, DX ; ec ; 0xc11c7 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc11c8 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc11ca vgabios.c:724 + pop di ; 5f ; 0xc11cd + pop si ; 5e ; 0xc11ce + pop cx ; 59 ; 0xc11cf + pop bx ; 5b ; 0xc11d0 + pop bp ; 5d ; 0xc11d1 + retn ; c3 ; 0xc11d2 + ; disGetNextSymbol 0xc11d3 LB 0x3391 -> off=0x0 cb=00000000000000fc uValue=00000000000c11d3 'biosfn_set_cursor_shape' +biosfn_set_cursor_shape: ; 0xc11d3 LB 0xfc + push bp ; 55 ; 0xc11d3 vgabios.c:727 + mov bp, sp ; 89 e5 ; 0xc11d4 + push bx ; 53 ; 0xc11d6 + push cx ; 51 ; 0xc11d7 + push si ; 56 ; 0xc11d8 + push ax ; 50 ; 0xc11d9 + push ax ; 50 ; 0xc11da + mov ah, al ; 88 c4 ; 0xc11db + mov bl, dl ; 88 d3 ; 0xc11dd + mov dh, al ; 88 c6 ; 0xc11df vgabios.c:733 + mov si, strict word 00060h ; be 60 00 ; 0xc11e1 vgabios.c:62 + mov cx, strict word 00040h ; b9 40 00 ; 0xc11e4 + mov es, cx ; 8e c1 ; 0xc11e7 + mov word [es:si], dx ; 26 89 14 ; 0xc11e9 + mov si, 00087h ; be 87 00 ; 0xc11ec vgabios.c:47 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc11ef + test dl, 008h ; f6 c2 08 ; 0xc11f2 vgabios.c:48 + jne short 01234h ; 75 3d ; 0xc11f5 + mov dl, al ; 88 c2 ; 0xc11f7 vgabios.c:739 + and dl, 060h ; 80 e2 60 ; 0xc11f9 + cmp dl, 020h ; 80 fa 20 ; 0xc11fc + jne short 01207h ; 75 06 ; 0xc11ff + mov AH, strict byte 01eh ; b4 1e ; 0xc1201 vgabios.c:741 + xor bl, bl ; 30 db ; 0xc1203 vgabios.c:742 + jmp short 01234h ; eb 2d ; 0xc1205 vgabios.c:743 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc1207 vgabios.c:47 + test dl, 001h ; f6 c2 01 ; 0xc120a vgabios.c:48 + jne short 01269h ; 75 5a ; 0xc120d + cmp ah, 020h ; 80 fc 20 ; 0xc120f + jnc short 01269h ; 73 55 ; 0xc1212 + cmp bl, 020h ; 80 fb 20 ; 0xc1214 + jnc short 01269h ; 73 50 ; 0xc1217 + mov si, 00085h ; be 85 00 ; 0xc1219 vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc121c + mov es, dx ; 8e c2 ; 0xc121f + mov cx, word [es:si] ; 26 8b 0c ; 0xc1221 + mov dx, cx ; 89 ca ; 0xc1224 vgabios.c:58 + cmp bl, ah ; 38 e3 ; 0xc1226 vgabios.c:754 + jnc short 01236h ; 73 0c ; 0xc1228 + test bl, bl ; 84 db ; 0xc122a vgabios.c:756 + je short 01269h ; 74 3b ; 0xc122c + xor ah, ah ; 30 e4 ; 0xc122e vgabios.c:757 + mov bl, cl ; 88 cb ; 0xc1230 vgabios.c:758 + db 0feh, 0cbh + ; dec bl ; fe cb ; 0xc1232 + jmp short 01269h ; eb 33 ; 0xc1234 vgabios.c:760 + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc1236 vgabios.c:761 + xor al, al ; 30 c0 ; 0xc1239 + mov byte [bp-007h], al ; 88 46 f9 ; 0xc123b + mov byte [bp-00ah], ah ; 88 66 f6 ; 0xc123e + mov byte [bp-009h], al ; 88 46 f7 ; 0xc1241 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc1244 + or si, word [bp-00ah] ; 0b 76 f6 ; 0xc1247 + cmp si, cx ; 39 ce ; 0xc124a + jnc short 0126bh ; 73 1d ; 0xc124c + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc124e + mov byte [bp-007h], al ; 88 46 f9 ; 0xc1251 + mov si, cx ; 89 ce ; 0xc1254 + dec si ; 4e ; 0xc1256 + cmp si, word [bp-008h] ; 3b 76 f8 ; 0xc1257 + je short 012a5h ; 74 49 ; 0xc125a + mov byte [bp-008h], ah ; 88 66 f8 ; 0xc125c + mov byte [bp-007h], al ; 88 46 f9 ; 0xc125f + dec cx ; 49 ; 0xc1262 + dec cx ; 49 ; 0xc1263 + cmp cx, word [bp-008h] ; 3b 4e f8 ; 0xc1264 + jne short 0126bh ; 75 02 ; 0xc1267 + jmp short 012a5h ; eb 3a ; 0xc1269 + cmp bl, 003h ; 80 fb 03 ; 0xc126b vgabios.c:763 + jbe short 012a5h ; 76 35 ; 0xc126e + mov cl, ah ; 88 e1 ; 0xc1270 vgabios.c:764 + xor ch, ch ; 30 ed ; 0xc1272 + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc1274 + mov byte [bp-007h], ch ; 88 6e f9 ; 0xc1277 + mov si, cx ; 89 ce ; 0xc127a + inc si ; 46 ; 0xc127c + inc si ; 46 ; 0xc127d + mov cl, dl ; 88 d1 ; 0xc127e + db 0feh, 0c9h + ; dec cl ; fe c9 ; 0xc1280 + cmp si, word [bp-008h] ; 3b 76 f8 ; 0xc1282 + jl short 0129ah ; 7c 13 ; 0xc1285 + sub ah, bl ; 28 dc ; 0xc1287 vgabios.c:766 + add ah, dl ; 00 d4 ; 0xc1289 + db 0feh, 0cch + ; dec ah ; fe cc ; 0xc128b + mov bl, cl ; 88 cb ; 0xc128d vgabios.c:767 + cmp dx, strict byte 0000eh ; 83 fa 0e ; 0xc128f vgabios.c:768 + jc short 012a5h ; 72 11 ; 0xc1292 + db 0feh, 0cbh + ; dec bl ; fe cb ; 0xc1294 vgabios.c:770 + db 0feh, 0cch + ; dec ah ; fe cc ; 0xc1296 vgabios.c:771 + jmp short 012a5h ; eb 0b ; 0xc1298 vgabios.c:773 + cmp ah, 002h ; 80 fc 02 ; 0xc129a + jbe short 012a3h ; 76 04 ; 0xc129d + shr dx, 1 ; d1 ea ; 0xc129f vgabios.c:775 + mov ah, dl ; 88 d4 ; 0xc12a1 + mov bl, cl ; 88 cb ; 0xc12a3 vgabios.c:779 + mov si, strict word 00063h ; be 63 00 ; 0xc12a5 vgabios.c:57 + mov dx, strict word 00040h ; ba 40 00 ; 0xc12a8 + mov es, dx ; 8e c2 ; 0xc12ab + mov cx, word [es:si] ; 26 8b 0c ; 0xc12ad + mov AL, strict byte 00ah ; b0 0a ; 0xc12b0 vgabios.c:790 + mov dx, cx ; 89 ca ; 0xc12b2 + out DX, AL ; ee ; 0xc12b4 + mov si, cx ; 89 ce ; 0xc12b5 vgabios.c:791 + inc si ; 46 ; 0xc12b7 + mov al, ah ; 88 e0 ; 0xc12b8 + mov dx, si ; 89 f2 ; 0xc12ba + out DX, AL ; ee ; 0xc12bc + mov AL, strict byte 00bh ; b0 0b ; 0xc12bd vgabios.c:792 + mov dx, cx ; 89 ca ; 0xc12bf + out DX, AL ; ee ; 0xc12c1 + mov al, bl ; 88 d8 ; 0xc12c2 vgabios.c:793 + mov dx, si ; 89 f2 ; 0xc12c4 + out DX, AL ; ee ; 0xc12c6 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc12c7 vgabios.c:794 + pop si ; 5e ; 0xc12ca + pop cx ; 59 ; 0xc12cb + pop bx ; 5b ; 0xc12cc + pop bp ; 5d ; 0xc12cd + retn ; c3 ; 0xc12ce + ; disGetNextSymbol 0xc12cf LB 0x3295 -> off=0x0 cb=000000000000008d uValue=00000000000c12cf 'biosfn_set_cursor_pos' +biosfn_set_cursor_pos: ; 0xc12cf LB 0x8d + push bp ; 55 ; 0xc12cf vgabios.c:797 + mov bp, sp ; 89 e5 ; 0xc12d0 + push bx ; 53 ; 0xc12d2 + push cx ; 51 ; 0xc12d3 + push si ; 56 ; 0xc12d4 + push di ; 57 ; 0xc12d5 + push ax ; 50 ; 0xc12d6 + mov bl, al ; 88 c3 ; 0xc12d7 + mov cx, dx ; 89 d1 ; 0xc12d9 + cmp AL, strict byte 007h ; 3c 07 ; 0xc12db vgabios.c:803 + jnbe short 01353h ; 77 74 ; 0xc12dd + xor ah, ah ; 30 e4 ; 0xc12df vgabios.c:806 + mov si, ax ; 89 c6 ; 0xc12e1 + sal si, 1 ; d1 e6 ; 0xc12e3 + add si, strict byte 00050h ; 83 c6 50 ; 0xc12e5 + mov ax, strict word 00040h ; b8 40 00 ; 0xc12e8 vgabios.c:62 + mov es, ax ; 8e c0 ; 0xc12eb + mov word [es:si], dx ; 26 89 14 ; 0xc12ed + mov si, strict word 00062h ; be 62 00 ; 0xc12f0 vgabios.c:47 + mov al, byte [es:si] ; 26 8a 04 ; 0xc12f3 + cmp bl, al ; 38 c3 ; 0xc12f6 vgabios.c:810 + jne short 01353h ; 75 59 ; 0xc12f8 + mov si, strict word 0004ah ; be 4a 00 ; 0xc12fa vgabios.c:57 + mov si, word [es:si] ; 26 8b 34 ; 0xc12fd + mov di, 00084h ; bf 84 00 ; 0xc1300 vgabios.c:47 + mov al, byte [es:di] ; 26 8a 05 ; 0xc1303 + xor ah, ah ; 30 e4 ; 0xc1306 vgabios.c:48 + mov di, ax ; 89 c7 ; 0xc1308 + inc di ; 47 ; 0xc130a + mov ax, dx ; 89 d0 ; 0xc130b vgabios.c:816 + mov al, dh ; 88 f0 ; 0xc130d + xor ah, dh ; 30 f4 ; 0xc130f + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc1311 + mov ax, si ; 89 f0 ; 0xc1314 vgabios.c:819 + mul di ; f7 e7 ; 0xc1316 + or AL, strict byte 0ffh ; 0c ff ; 0xc1318 + xor bh, bh ; 30 ff ; 0xc131a + inc ax ; 40 ; 0xc131c + mul bx ; f7 e3 ; 0xc131d + mov bx, ax ; 89 c3 ; 0xc131f + mov al, cl ; 88 c8 ; 0xc1321 + xor ah, ah ; 30 e4 ; 0xc1323 + add bx, ax ; 01 c3 ; 0xc1325 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1327 + mul si ; f7 e6 ; 0xc132a + mov si, bx ; 89 de ; 0xc132c + add si, ax ; 01 c6 ; 0xc132e + mov bx, strict word 00063h ; bb 63 00 ; 0xc1330 vgabios.c:57 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc1333 + mov AL, strict byte 00eh ; b0 0e ; 0xc1336 vgabios.c:823 + mov dx, bx ; 89 da ; 0xc1338 + out DX, AL ; ee ; 0xc133a + mov ax, si ; 89 f0 ; 0xc133b vgabios.c:824 + mov al, ah ; 88 e0 ; 0xc133d + lea cx, [bx+001h] ; 8d 4f 01 ; 0xc133f + mov dx, cx ; 89 ca ; 0xc1342 + out DX, AL ; ee ; 0xc1344 + mov AL, strict byte 00fh ; b0 0f ; 0xc1345 vgabios.c:825 + mov dx, bx ; 89 da ; 0xc1347 + out DX, AL ; ee ; 0xc1349 + and si, 000ffh ; 81 e6 ff 00 ; 0xc134a vgabios.c:826 + mov ax, si ; 89 f0 ; 0xc134e + mov dx, cx ; 89 ca ; 0xc1350 + out DX, AL ; ee ; 0xc1352 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc1353 vgabios.c:828 + pop di ; 5f ; 0xc1356 + pop si ; 5e ; 0xc1357 + pop cx ; 59 ; 0xc1358 + pop bx ; 5b ; 0xc1359 + pop bp ; 5d ; 0xc135a + retn ; c3 ; 0xc135b + ; disGetNextSymbol 0xc135c LB 0x3208 -> off=0x0 cb=00000000000000d5 uValue=00000000000c135c 'biosfn_set_active_page' +biosfn_set_active_page: ; 0xc135c LB 0xd5 + push bp ; 55 ; 0xc135c vgabios.c:831 + mov bp, sp ; 89 e5 ; 0xc135d + push bx ; 53 ; 0xc135f + push cx ; 51 ; 0xc1360 + push dx ; 52 ; 0xc1361 + push si ; 56 ; 0xc1362 + push di ; 57 ; 0xc1363 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc1364 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc1367 + cmp AL, strict byte 007h ; 3c 07 ; 0xc136a vgabios.c:837 + jnbe short 01384h ; 77 16 ; 0xc136c + mov bx, strict word 00049h ; bb 49 00 ; 0xc136e vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1371 + mov es, ax ; 8e c0 ; 0xc1374 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1376 + xor ah, ah ; 30 e4 ; 0xc1379 vgabios.c:841 + call 03888h ; e8 0a 25 ; 0xc137b + mov cl, al ; 88 c1 ; 0xc137e + cmp AL, strict byte 0ffh ; 3c ff ; 0xc1380 vgabios.c:842 + jne short 01387h ; 75 03 ; 0xc1382 + jmp near 01427h ; e9 a0 00 ; 0xc1384 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1387 vgabios.c:845 + xor ah, ah ; 30 e4 ; 0xc138a + lea bx, [bp-010h] ; 8d 5e f0 ; 0xc138c + lea dx, [bp-00eh] ; 8d 56 f2 ; 0xc138f + call 00a97h ; e8 02 f7 ; 0xc1392 + mov bl, cl ; 88 cb ; 0xc1395 vgabios.c:847 + xor bh, bh ; 30 ff ; 0xc1397 + mov CL, strict byte 003h ; b1 03 ; 0xc1399 + mov si, bx ; 89 de ; 0xc139b + sal si, CL ; d3 e6 ; 0xc139d + cmp byte [si+047b0h], 000h ; 80 bc b0 47 00 ; 0xc139f + jne short 013e1h ; 75 3b ; 0xc13a4 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc13a6 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc13a9 + mov es, ax ; 8e c0 ; 0xc13ac + mov dx, word [es:bx] ; 26 8b 17 ; 0xc13ae + mov bx, 00084h ; bb 84 00 ; 0xc13b1 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc13b4 + xor ah, ah ; 30 e4 ; 0xc13b7 vgabios.c:48 + mov bx, ax ; 89 c3 ; 0xc13b9 + inc bx ; 43 ; 0xc13bb + mov ax, dx ; 89 d0 ; 0xc13bc vgabios.c:854 + mul bx ; f7 e3 ; 0xc13be + mov di, ax ; 89 c7 ; 0xc13c0 + sal ax, 1 ; d1 e0 ; 0xc13c2 + or AL, strict byte 0ffh ; 0c ff ; 0xc13c4 + mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xc13c6 + xor bh, bh ; 30 ff ; 0xc13c9 + inc ax ; 40 ; 0xc13cb + mul bx ; f7 e3 ; 0xc13cc + mov cx, ax ; 89 c1 ; 0xc13ce + mov si, strict word 0004eh ; be 4e 00 ; 0xc13d0 vgabios.c:62 + mov word [es:si], ax ; 26 89 04 ; 0xc13d3 + or di, 000ffh ; 81 cf ff 00 ; 0xc13d6 vgabios.c:858 + lea ax, [di+001h] ; 8d 45 01 ; 0xc13da + mul bx ; f7 e3 ; 0xc13dd + jmp short 013f2h ; eb 11 ; 0xc13df vgabios.c:860 + mov bl, byte [bx+0482fh] ; 8a 9f 2f 48 ; 0xc13e1 vgabios.c:862 + mov CL, strict byte 006h ; b1 06 ; 0xc13e5 + sal bx, CL ; d3 e3 ; 0xc13e7 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc13e9 + xor ah, ah ; 30 e4 ; 0xc13ec + mul word [bx+04846h] ; f7 a7 46 48 ; 0xc13ee + mov cx, ax ; 89 c1 ; 0xc13f2 + mov bx, strict word 00063h ; bb 63 00 ; 0xc13f4 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc13f7 + mov es, ax ; 8e c0 ; 0xc13fa + mov bx, word [es:bx] ; 26 8b 1f ; 0xc13fc + mov AL, strict byte 00ch ; b0 0c ; 0xc13ff vgabios.c:867 + mov dx, bx ; 89 da ; 0xc1401 + out DX, AL ; ee ; 0xc1403 + mov al, ch ; 88 e8 ; 0xc1404 vgabios.c:868 + lea si, [bx+001h] ; 8d 77 01 ; 0xc1406 + mov dx, si ; 89 f2 ; 0xc1409 + out DX, AL ; ee ; 0xc140b + mov AL, strict byte 00dh ; b0 0d ; 0xc140c vgabios.c:869 + mov dx, bx ; 89 da ; 0xc140e + out DX, AL ; ee ; 0xc1410 + xor ch, ch ; 30 ed ; 0xc1411 vgabios.c:870 + mov ax, cx ; 89 c8 ; 0xc1413 + mov dx, si ; 89 f2 ; 0xc1415 + out DX, AL ; ee ; 0xc1417 + mov bx, strict word 00062h ; bb 62 00 ; 0xc1418 vgabios.c:52 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc141b + mov byte [es:bx], al ; 26 88 07 ; 0xc141e + mov dx, word [bp-010h] ; 8b 56 f0 ; 0xc1421 vgabios.c:880 + call 012cfh ; e8 a8 fe ; 0xc1424 + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc1427 vgabios.c:881 + pop di ; 5f ; 0xc142a + pop si ; 5e ; 0xc142b + pop dx ; 5a ; 0xc142c + pop cx ; 59 ; 0xc142d + pop bx ; 5b ; 0xc142e + pop bp ; 5d ; 0xc142f + retn ; c3 ; 0xc1430 + ; disGetNextSymbol 0xc1431 LB 0x3133 -> off=0x0 cb=0000000000000048 uValue=00000000000c1431 'find_vpti' +find_vpti: ; 0xc1431 LB 0x48 + push bx ; 53 ; 0xc1431 vgabios.c:916 + push cx ; 51 ; 0xc1432 + push si ; 56 ; 0xc1433 + push bp ; 55 ; 0xc1434 + mov bp, sp ; 89 e5 ; 0xc1435 + mov bl, al ; 88 c3 ; 0xc1437 vgabios.c:921 + xor bh, bh ; 30 ff ; 0xc1439 + mov CL, strict byte 003h ; b1 03 ; 0xc143b + mov si, bx ; 89 de ; 0xc143d + sal si, CL ; d3 e6 ; 0xc143f + cmp byte [si+047b0h], 000h ; 80 bc b0 47 00 ; 0xc1441 + jne short 0146eh ; 75 26 ; 0xc1446 + mov si, 00089h ; be 89 00 ; 0xc1448 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc144b + mov es, ax ; 8e c0 ; 0xc144e + mov al, byte [es:si] ; 26 8a 04 ; 0xc1450 + test AL, strict byte 010h ; a8 10 ; 0xc1453 vgabios.c:923 + je short 0145dh ; 74 06 ; 0xc1455 + mov al, byte [bx+07df6h] ; 8a 87 f6 7d ; 0xc1457 vgabios.c:924 + jmp short 0146bh ; eb 0e ; 0xc145b vgabios.c:925 + test AL, strict byte 080h ; a8 80 ; 0xc145d + je short 01467h ; 74 06 ; 0xc145f + mov al, byte [bx+07de6h] ; 8a 87 e6 7d ; 0xc1461 vgabios.c:926 + jmp short 0146bh ; eb 04 ; 0xc1465 vgabios.c:927 + mov al, byte [bx+07deeh] ; 8a 87 ee 7d ; 0xc1467 vgabios.c:928 + cbw ; 98 ; 0xc146b + jmp short 01474h ; eb 06 ; 0xc146c vgabios.c:929 + mov al, byte [bx+0482fh] ; 8a 87 2f 48 ; 0xc146e vgabios.c:930 + xor ah, ah ; 30 e4 ; 0xc1472 + pop bp ; 5d ; 0xc1474 vgabios.c:933 + pop si ; 5e ; 0xc1475 + pop cx ; 59 ; 0xc1476 + pop bx ; 5b ; 0xc1477 + retn ; c3 ; 0xc1478 + ; disGetNextSymbol 0xc1479 LB 0x30eb -> off=0x0 cb=00000000000004e4 uValue=00000000000c1479 'biosfn_set_video_mode' +biosfn_set_video_mode: ; 0xc1479 LB 0x4e4 + push bp ; 55 ; 0xc1479 vgabios.c:938 + mov bp, sp ; 89 e5 ; 0xc147a + push bx ; 53 ; 0xc147c + push cx ; 51 ; 0xc147d + push dx ; 52 ; 0xc147e + push si ; 56 ; 0xc147f + push di ; 57 ; 0xc1480 + sub sp, strict byte 00018h ; 83 ec 18 ; 0xc1481 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc1484 + and AL, strict byte 080h ; 24 80 ; 0xc1487 vgabios.c:942 + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc1489 + call 007f8h ; e8 69 f3 ; 0xc148c vgabios.c:952 + test ax, ax ; 85 c0 ; 0xc148f + je short 0149fh ; 74 0c ; 0xc1491 + mov AL, strict byte 007h ; b0 07 ; 0xc1493 vgabios.c:954 + mov dx, 003c4h ; ba c4 03 ; 0xc1495 + out DX, AL ; ee ; 0xc1498 + xor al, al ; 30 c0 ; 0xc1499 vgabios.c:955 + mov dx, 003c5h ; ba c5 03 ; 0xc149b + out DX, AL ; ee ; 0xc149e + and byte [bp-00ch], 07fh ; 80 66 f4 7f ; 0xc149f vgabios.c:960 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc14a3 vgabios.c:966 + xor ah, ah ; 30 e4 ; 0xc14a6 + call 03888h ; e8 dd 23 ; 0xc14a8 + mov dl, al ; 88 c2 ; 0xc14ab + mov byte [bp-010h], al ; 88 46 f0 ; 0xc14ad + cmp AL, strict byte 0ffh ; 3c ff ; 0xc14b0 vgabios.c:972 + je short 01520h ; 74 6c ; 0xc14b2 + mov si, 000a8h ; be a8 00 ; 0xc14b4 vgabios.c:67 + mov ax, strict word 00040h ; b8 40 00 ; 0xc14b7 + mov es, ax ; 8e c0 ; 0xc14ba + mov bx, word [es:si] ; 26 8b 1c ; 0xc14bc + mov ax, word [es:si+002h] ; 26 8b 44 02 ; 0xc14bf + mov word [bp-014h], bx ; 89 5e ec ; 0xc14c3 vgabios.c:68 + mov word [bp-012h], ax ; 89 46 ee ; 0xc14c6 + xor dh, dh ; 30 f6 ; 0xc14c9 vgabios.c:978 + mov ax, dx ; 89 d0 ; 0xc14cb + call 01431h ; e8 61 ff ; 0xc14cd + mov es, [bp-012h] ; 8e 46 ee ; 0xc14d0 vgabios.c:979 + mov si, word [es:bx] ; 26 8b 37 ; 0xc14d3 + mov bx, word [es:bx+002h] ; 26 8b 5f 02 ; 0xc14d6 + mov word [bp-01ah], bx ; 89 5e e6 ; 0xc14da + xor ah, ah ; 30 e4 ; 0xc14dd vgabios.c:980 + mov CL, strict byte 006h ; b1 06 ; 0xc14df + sal ax, CL ; d3 e0 ; 0xc14e1 + add si, ax ; 01 c6 ; 0xc14e3 + mov bx, 00089h ; bb 89 00 ; 0xc14e5 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc14e8 + mov es, ax ; 8e c0 ; 0xc14eb + mov al, byte [es:bx] ; 26 8a 07 ; 0xc14ed + mov ch, al ; 88 c5 ; 0xc14f0 vgabios.c:48 + test AL, strict byte 008h ; a8 08 ; 0xc14f2 vgabios.c:997 + jne short 0153ch ; 75 46 ; 0xc14f4 + mov CL, strict byte 003h ; b1 03 ; 0xc14f6 vgabios.c:999 + mov bx, dx ; 89 d3 ; 0xc14f8 + sal bx, CL ; d3 e3 ; 0xc14fa + mov al, byte [bx+047b5h] ; 8a 87 b5 47 ; 0xc14fc + mov dx, 003c6h ; ba c6 03 ; 0xc1500 + out DX, AL ; ee ; 0xc1503 + xor al, al ; 30 c0 ; 0xc1504 vgabios.c:1002 + mov dx, 003c8h ; ba c8 03 ; 0xc1506 + out DX, AL ; ee ; 0xc1509 + mov bl, byte [bx+047b6h] ; 8a 9f b6 47 ; 0xc150a vgabios.c:1005 + cmp bl, 001h ; 80 fb 01 ; 0xc150e + jc short 01523h ; 72 10 ; 0xc1511 + jbe short 0152eh ; 76 19 ; 0xc1513 + cmp bl, cl ; 38 cb ; 0xc1515 + je short 0153fh ; 74 26 ; 0xc1517 + cmp bl, 002h ; 80 fb 02 ; 0xc1519 + je short 01535h ; 74 17 ; 0xc151c + jmp short 01544h ; eb 24 ; 0xc151e + jmp near 01953h ; e9 30 04 ; 0xc1520 + test bl, bl ; 84 db ; 0xc1523 + jne short 01544h ; 75 1d ; 0xc1525 + mov word [bp-016h], 04fc3h ; c7 46 ea c3 4f ; 0xc1527 vgabios.c:1007 + jmp short 01544h ; eb 16 ; 0xc152c vgabios.c:1008 + mov word [bp-016h], 05083h ; c7 46 ea 83 50 ; 0xc152e vgabios.c:1010 + jmp short 01544h ; eb 0f ; 0xc1533 vgabios.c:1011 + mov word [bp-016h], 05143h ; c7 46 ea 43 51 ; 0xc1535 vgabios.c:1013 + jmp short 01544h ; eb 08 ; 0xc153a vgabios.c:1014 + jmp near 015b8h ; e9 79 00 ; 0xc153c + mov word [bp-016h], 05203h ; c7 46 ea 03 52 ; 0xc153f vgabios.c:1016 + mov bl, byte [bp-010h] ; 8a 5e f0 ; 0xc1544 vgabios.c:1020 + xor bh, bh ; 30 ff ; 0xc1547 + mov CL, strict byte 003h ; b1 03 ; 0xc1549 + sal bx, CL ; d3 e3 ; 0xc154b + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc154d + jne short 01563h ; 75 0f ; 0xc1552 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1554 vgabios.c:1022 + cmp byte [es:si+002h], 008h ; 26 80 7c 02 08 ; 0xc1557 + jne short 01563h ; 75 05 ; 0xc155c + mov word [bp-016h], 05083h ; c7 46 ea 83 50 ; 0xc155e vgabios.c:1023 + xor bx, bx ; 31 db ; 0xc1563 vgabios.c:1026 + jmp short 01576h ; eb 0f ; 0xc1565 + xor al, al ; 30 c0 ; 0xc1567 vgabios.c:1033 + mov dx, 003c9h ; ba c9 03 ; 0xc1569 + out DX, AL ; ee ; 0xc156c + out DX, AL ; ee ; 0xc156d vgabios.c:1034 + out DX, AL ; ee ; 0xc156e vgabios.c:1035 + inc bx ; 43 ; 0xc156f vgabios.c:1037 + cmp bx, 00100h ; 81 fb 00 01 ; 0xc1570 + jnc short 015abh ; 73 35 ; 0xc1574 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc1576 + xor ah, ah ; 30 e4 ; 0xc1579 + mov CL, strict byte 003h ; b1 03 ; 0xc157b + mov di, ax ; 89 c7 ; 0xc157d + sal di, CL ; d3 e7 ; 0xc157f + mov al, byte [di+047b6h] ; 8a 85 b6 47 ; 0xc1581 + mov di, ax ; 89 c7 ; 0xc1585 + mov al, byte [di+0483fh] ; 8a 85 3f 48 ; 0xc1587 + cmp bx, ax ; 39 c3 ; 0xc158b + jnbe short 01567h ; 77 d8 ; 0xc158d + mov ax, bx ; 89 d8 ; 0xc158f + mov dx, strict word 00003h ; ba 03 00 ; 0xc1591 + mul dx ; f7 e2 ; 0xc1594 + mov di, word [bp-016h] ; 8b 7e ea ; 0xc1596 + add di, ax ; 01 c7 ; 0xc1599 + mov al, byte [di] ; 8a 05 ; 0xc159b + mov dx, 003c9h ; ba c9 03 ; 0xc159d + out DX, AL ; ee ; 0xc15a0 + mov al, byte [di+001h] ; 8a 45 01 ; 0xc15a1 + out DX, AL ; ee ; 0xc15a4 + mov al, byte [di+002h] ; 8a 45 02 ; 0xc15a5 + out DX, AL ; ee ; 0xc15a8 + jmp short 0156fh ; eb c4 ; 0xc15a9 + test ch, 002h ; f6 c5 02 ; 0xc15ab vgabios.c:1038 + je short 015b8h ; 74 08 ; 0xc15ae + mov dx, 00100h ; ba 00 01 ; 0xc15b0 vgabios.c:1040 + xor ax, ax ; 31 c0 ; 0xc15b3 + call 01134h ; e8 7c fb ; 0xc15b5 + mov dx, 003dah ; ba da 03 ; 0xc15b8 vgabios.c:1045 + in AL, DX ; ec ; 0xc15bb + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc15bc + xor bx, bx ; 31 db ; 0xc15be vgabios.c:1048 + jmp short 015c7h ; eb 05 ; 0xc15c0 + cmp bx, strict byte 00013h ; 83 fb 13 ; 0xc15c2 + jnbe short 015dch ; 77 15 ; 0xc15c5 + mov al, bl ; 88 d8 ; 0xc15c7 vgabios.c:1049 + mov dx, 003c0h ; ba c0 03 ; 0xc15c9 + out DX, AL ; ee ; 0xc15cc + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc15cd vgabios.c:1050 + mov di, si ; 89 f7 ; 0xc15d0 + add di, bx ; 01 df ; 0xc15d2 + mov al, byte [es:di+023h] ; 26 8a 45 23 ; 0xc15d4 + out DX, AL ; ee ; 0xc15d8 + inc bx ; 43 ; 0xc15d9 vgabios.c:1051 + jmp short 015c2h ; eb e6 ; 0xc15da + mov AL, strict byte 014h ; b0 14 ; 0xc15dc vgabios.c:1052 + mov dx, 003c0h ; ba c0 03 ; 0xc15de + out DX, AL ; ee ; 0xc15e1 + xor al, al ; 30 c0 ; 0xc15e2 vgabios.c:1053 + out DX, AL ; ee ; 0xc15e4 + les bx, [bp-014h] ; c4 5e ec ; 0xc15e5 vgabios.c:1056 + mov dx, word [es:bx+004h] ; 26 8b 57 04 ; 0xc15e8 + mov ax, word [es:bx+006h] ; 26 8b 47 06 ; 0xc15ec + test ax, ax ; 85 c0 ; 0xc15f0 + jne short 015f8h ; 75 04 ; 0xc15f2 + test dx, dx ; 85 d2 ; 0xc15f4 + je short 01634h ; 74 3c ; 0xc15f6 + mov word [bp-020h], ax ; 89 46 e0 ; 0xc15f8 vgabios.c:1060 + xor bx, bx ; 31 db ; 0xc15fb vgabios.c:1061 + jmp short 01604h ; eb 05 ; 0xc15fd + cmp bx, strict byte 00010h ; 83 fb 10 ; 0xc15ff + jnc short 01624h ; 73 20 ; 0xc1602 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1604 vgabios.c:1062 + mov di, si ; 89 f7 ; 0xc1607 + add di, bx ; 01 df ; 0xc1609 + mov ax, word [bp-020h] ; 8b 46 e0 ; 0xc160b + mov word [bp-022h], ax ; 89 46 de ; 0xc160e + mov cx, dx ; 89 d1 ; 0xc1611 + add cx, bx ; 01 d9 ; 0xc1613 + mov al, byte [es:di+023h] ; 26 8a 45 23 ; 0xc1615 + mov es, [bp-022h] ; 8e 46 de ; 0xc1619 + mov di, cx ; 89 cf ; 0xc161c + mov byte [es:di], al ; 26 88 05 ; 0xc161e + inc bx ; 43 ; 0xc1621 + jmp short 015ffh ; eb db ; 0xc1622 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1624 vgabios.c:1063 + mov al, byte [es:si+034h] ; 26 8a 44 34 ; 0xc1627 + mov es, [bp-020h] ; 8e 46 e0 ; 0xc162b + mov bx, dx ; 89 d3 ; 0xc162e + mov byte [es:bx+010h], al ; 26 88 47 10 ; 0xc1630 + xor al, al ; 30 c0 ; 0xc1634 vgabios.c:1067 + mov dx, 003c4h ; ba c4 03 ; 0xc1636 + out DX, AL ; ee ; 0xc1639 + mov AL, strict byte 003h ; b0 03 ; 0xc163a vgabios.c:1068 + mov dx, 003c5h ; ba c5 03 ; 0xc163c + out DX, AL ; ee ; 0xc163f + mov bx, strict word 00001h ; bb 01 00 ; 0xc1640 vgabios.c:1069 + jmp short 0164ah ; eb 05 ; 0xc1643 + cmp bx, strict byte 00004h ; 83 fb 04 ; 0xc1645 + jnbe short 01662h ; 77 18 ; 0xc1648 + mov al, bl ; 88 d8 ; 0xc164a vgabios.c:1070 + mov dx, 003c4h ; ba c4 03 ; 0xc164c + out DX, AL ; ee ; 0xc164f + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1650 vgabios.c:1071 + mov di, si ; 89 f7 ; 0xc1653 + add di, bx ; 01 df ; 0xc1655 + mov al, byte [es:di+004h] ; 26 8a 45 04 ; 0xc1657 + mov dx, 003c5h ; ba c5 03 ; 0xc165b + out DX, AL ; ee ; 0xc165e + inc bx ; 43 ; 0xc165f vgabios.c:1072 + jmp short 01645h ; eb e3 ; 0xc1660 + xor bx, bx ; 31 db ; 0xc1662 vgabios.c:1075 + jmp short 0166bh ; eb 05 ; 0xc1664 + cmp bx, strict byte 00008h ; 83 fb 08 ; 0xc1666 + jnbe short 01683h ; 77 18 ; 0xc1669 + mov al, bl ; 88 d8 ; 0xc166b vgabios.c:1076 + mov dx, 003ceh ; ba ce 03 ; 0xc166d + out DX, AL ; ee ; 0xc1670 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1671 vgabios.c:1077 + mov di, si ; 89 f7 ; 0xc1674 + add di, bx ; 01 df ; 0xc1676 + mov al, byte [es:di+037h] ; 26 8a 45 37 ; 0xc1678 + mov dx, 003cfh ; ba cf 03 ; 0xc167c + out DX, AL ; ee ; 0xc167f + inc bx ; 43 ; 0xc1680 vgabios.c:1078 + jmp short 01666h ; eb e3 ; 0xc1681 + mov bl, byte [bp-010h] ; 8a 5e f0 ; 0xc1683 vgabios.c:1081 + xor bh, bh ; 30 ff ; 0xc1686 + mov CL, strict byte 003h ; b1 03 ; 0xc1688 + sal bx, CL ; d3 e3 ; 0xc168a + cmp byte [bx+047b1h], 001h ; 80 bf b1 47 01 ; 0xc168c + jne short 01698h ; 75 05 ; 0xc1691 + mov bx, 003b4h ; bb b4 03 ; 0xc1693 + jmp short 0169bh ; eb 03 ; 0xc1696 + mov bx, 003d4h ; bb d4 03 ; 0xc1698 + mov word [bp-018h], bx ; 89 5e e8 ; 0xc169b + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc169e vgabios.c:1084 + mov al, byte [es:si+009h] ; 26 8a 44 09 ; 0xc16a1 + mov dx, 003c2h ; ba c2 03 ; 0xc16a5 + out DX, AL ; ee ; 0xc16a8 + mov ax, strict word 00011h ; b8 11 00 ; 0xc16a9 vgabios.c:1087 + mov dx, bx ; 89 da ; 0xc16ac + out DX, ax ; ef ; 0xc16ae + xor bx, bx ; 31 db ; 0xc16af vgabios.c:1089 + jmp short 016b8h ; eb 05 ; 0xc16b1 + cmp bx, strict byte 00018h ; 83 fb 18 ; 0xc16b3 + jnbe short 016ceh ; 77 16 ; 0xc16b6 + mov al, bl ; 88 d8 ; 0xc16b8 vgabios.c:1090 + mov dx, word [bp-018h] ; 8b 56 e8 ; 0xc16ba + out DX, AL ; ee ; 0xc16bd + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc16be vgabios.c:1091 + mov di, si ; 89 f7 ; 0xc16c1 + add di, bx ; 01 df ; 0xc16c3 + inc dx ; 42 ; 0xc16c5 + mov al, byte [es:di+00ah] ; 26 8a 45 0a ; 0xc16c6 + out DX, AL ; ee ; 0xc16ca + inc bx ; 43 ; 0xc16cb vgabios.c:1092 + jmp short 016b3h ; eb e5 ; 0xc16cc + mov AL, strict byte 020h ; b0 20 ; 0xc16ce vgabios.c:1095 + mov dx, 003c0h ; ba c0 03 ; 0xc16d0 + out DX, AL ; ee ; 0xc16d3 + mov dx, word [bp-018h] ; 8b 56 e8 ; 0xc16d4 vgabios.c:1096 + add dx, strict byte 00006h ; 83 c2 06 ; 0xc16d7 + in AL, DX ; ec ; 0xc16da + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc16db + cmp byte [bp-00eh], 000h ; 80 7e f2 00 ; 0xc16dd vgabios.c:1098 + jne short 01741h ; 75 5e ; 0xc16e1 + mov bl, byte [bp-010h] ; 8a 5e f0 ; 0xc16e3 vgabios.c:1100 + xor bh, bh ; 30 ff ; 0xc16e6 + mov CL, strict byte 003h ; b1 03 ; 0xc16e8 + sal bx, CL ; d3 e3 ; 0xc16ea + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc16ec + jne short 01705h ; 75 12 ; 0xc16f1 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc16f3 vgabios.c:1102 + mov cx, 04000h ; b9 00 40 ; 0xc16f7 + mov ax, 00720h ; b8 20 07 ; 0xc16fa + xor di, di ; 31 ff ; 0xc16fd + jcxz 01703h ; e3 02 ; 0xc16ff + rep stosw ; f3 ab ; 0xc1701 + jmp short 01741h ; eb 3c ; 0xc1703 vgabios.c:1104 + cmp byte [bp-00ch], 00dh ; 80 7e f4 0d ; 0xc1705 vgabios.c:1106 + jnc short 0171ch ; 73 11 ; 0xc1709 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc170b vgabios.c:1108 + mov cx, 04000h ; b9 00 40 ; 0xc170f + xor ax, ax ; 31 c0 ; 0xc1712 + xor di, di ; 31 ff ; 0xc1714 + jcxz 0171ah ; e3 02 ; 0xc1716 + rep stosw ; f3 ab ; 0xc1718 + jmp short 01741h ; eb 25 ; 0xc171a vgabios.c:1110 + mov AL, strict byte 002h ; b0 02 ; 0xc171c vgabios.c:1112 + mov dx, 003c4h ; ba c4 03 ; 0xc171e + out DX, AL ; ee ; 0xc1721 + mov dx, 003c5h ; ba c5 03 ; 0xc1722 vgabios.c:1113 + in AL, DX ; ec ; 0xc1725 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc1726 + mov word [bp-022h], ax ; 89 46 de ; 0xc1728 + mov AL, strict byte 00fh ; b0 0f ; 0xc172b vgabios.c:1114 + out DX, AL ; ee ; 0xc172d + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc172e vgabios.c:1115 + mov cx, 08000h ; b9 00 80 ; 0xc1732 + xor ax, ax ; 31 c0 ; 0xc1735 + xor di, di ; 31 ff ; 0xc1737 + jcxz 0173dh ; e3 02 ; 0xc1739 + rep stosw ; f3 ab ; 0xc173b + mov al, byte [bp-022h] ; 8a 46 de ; 0xc173d vgabios.c:1116 + out DX, AL ; ee ; 0xc1740 + mov bx, strict word 00049h ; bb 49 00 ; 0xc1741 vgabios.c:52 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1744 + mov es, ax ; 8e c0 ; 0xc1747 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1749 + mov byte [es:bx], al ; 26 88 07 ; 0xc174c + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc174f vgabios.c:1123 + mov al, byte [es:si] ; 26 8a 04 ; 0xc1752 + xor ah, ah ; 30 e4 ; 0xc1755 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1757 vgabios.c:62 + mov dx, strict word 00040h ; ba 40 00 ; 0xc175a + mov es, dx ; 8e c2 ; 0xc175d + mov word [es:bx], ax ; 26 89 07 ; 0xc175f + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1762 vgabios.c:60 + mov ax, word [es:si+003h] ; 26 8b 44 03 ; 0xc1765 + mov bx, strict word 0004ch ; bb 4c 00 ; 0xc1769 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc176c + mov word [es:bx], ax ; 26 89 07 ; 0xc176e + mov bx, strict word 00063h ; bb 63 00 ; 0xc1771 vgabios.c:62 + mov ax, word [bp-018h] ; 8b 46 e8 ; 0xc1774 + mov word [es:bx], ax ; 26 89 07 ; 0xc1777 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc177a vgabios.c:50 + mov al, byte [es:si+001h] ; 26 8a 44 01 ; 0xc177d + mov bx, 00084h ; bb 84 00 ; 0xc1781 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc1784 + mov byte [es:bx], al ; 26 88 07 ; 0xc1786 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1789 vgabios.c:1127 + mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xc178c + xor ah, ah ; 30 e4 ; 0xc1790 + mov bx, 00085h ; bb 85 00 ; 0xc1792 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc1795 + mov word [es:bx], ax ; 26 89 07 ; 0xc1797 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc179a vgabios.c:1128 + or AL, strict byte 060h ; 0c 60 ; 0xc179d + mov bx, 00087h ; bb 87 00 ; 0xc179f vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc17a2 + mov bx, 00088h ; bb 88 00 ; 0xc17a5 vgabios.c:52 + mov byte [es:bx], 0f9h ; 26 c6 07 f9 ; 0xc17a8 + mov bx, 0008ah ; bb 8a 00 ; 0xc17ac vgabios.c:52 + mov byte [es:bx], 008h ; 26 c6 07 08 ; 0xc17af + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc17b3 vgabios.c:1134 + cmp AL, strict byte 007h ; 3c 07 ; 0xc17b6 + jnbe short 017e1h ; 77 27 ; 0xc17b8 + mov bl, al ; 88 c3 ; 0xc17ba vgabios.c:1136 + xor bh, bh ; 30 ff ; 0xc17bc + mov al, byte [bx+07ddeh] ; 8a 87 de 7d ; 0xc17be vgabios.c:50 + mov bx, strict word 00065h ; bb 65 00 ; 0xc17c2 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc17c5 + cmp byte [bp-00ch], 006h ; 80 7e f4 06 ; 0xc17c8 vgabios.c:1137 + jne short 017d3h ; 75 05 ; 0xc17cc + mov ax, strict word 0003fh ; b8 3f 00 ; 0xc17ce + jmp short 017d6h ; eb 03 ; 0xc17d1 + mov ax, strict word 00030h ; b8 30 00 ; 0xc17d3 + mov bx, strict word 00066h ; bb 66 00 ; 0xc17d6 vgabios.c:52 + mov dx, strict word 00040h ; ba 40 00 ; 0xc17d9 + mov es, dx ; 8e c2 ; 0xc17dc + mov byte [es:bx], al ; 26 88 07 ; 0xc17de + mov bl, byte [bp-010h] ; 8a 5e f0 ; 0xc17e1 vgabios.c:1141 + xor bh, bh ; 30 ff ; 0xc17e4 + mov CL, strict byte 003h ; b1 03 ; 0xc17e6 + sal bx, CL ; d3 e3 ; 0xc17e8 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc17ea + jne short 017fah ; 75 09 ; 0xc17ef + mov dx, strict word 00007h ; ba 07 00 ; 0xc17f1 vgabios.c:1143 + mov ax, strict word 00006h ; b8 06 00 ; 0xc17f4 + call 011d3h ; e8 d9 f9 ; 0xc17f7 + xor bx, bx ; 31 db ; 0xc17fa vgabios.c:1148 + jmp short 01803h ; eb 05 ; 0xc17fc + cmp bx, strict byte 00008h ; 83 fb 08 ; 0xc17fe + jnc short 0180fh ; 73 0c ; 0xc1801 + mov al, bl ; 88 d8 ; 0xc1803 vgabios.c:1149 + xor ah, ah ; 30 e4 ; 0xc1805 + xor dx, dx ; 31 d2 ; 0xc1807 + call 012cfh ; e8 c3 fa ; 0xc1809 + inc bx ; 43 ; 0xc180c + jmp short 017feh ; eb ef ; 0xc180d + xor ax, ax ; 31 c0 ; 0xc180f vgabios.c:1152 + call 0135ch ; e8 48 fb ; 0xc1811 + mov bl, byte [bp-010h] ; 8a 5e f0 ; 0xc1814 vgabios.c:1155 + xor bh, bh ; 30 ff ; 0xc1817 + mov CL, strict byte 003h ; b1 03 ; 0xc1819 + sal bx, CL ; d3 e3 ; 0xc181b + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc181d + jne short 01892h ; 75 6e ; 0xc1822 + les bx, [bp-014h] ; c4 5e ec ; 0xc1824 vgabios.c:1157 + mov bx, word [es:bx+008h] ; 26 8b 5f 08 ; 0xc1827 + mov word [bp-01eh], bx ; 89 5e e2 ; 0xc182b + mov bx, word [bp-014h] ; 8b 5e ec ; 0xc182e + mov ax, word [es:bx+00ah] ; 26 8b 47 0a ; 0xc1831 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc1835 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1838 vgabios.c:1159 + mov bl, byte [es:si+002h] ; 26 8a 5c 02 ; 0xc183b + cmp bl, 00eh ; 80 fb 0e ; 0xc183f + je short 01865h ; 74 21 ; 0xc1842 + cmp bl, 008h ; 80 fb 08 ; 0xc1844 + jne short 01895h ; 75 4c ; 0xc1847 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1849 vgabios.c:1161 + mov al, byte [es:si+002h] ; 26 8a 44 02 ; 0xc184c + xor ah, ah ; 30 e4 ; 0xc1850 + push ax ; 50 ; 0xc1852 + xor al, al ; 30 c0 ; 0xc1853 + push ax ; 50 ; 0xc1855 + push ax ; 50 ; 0xc1856 + mov cx, 00100h ; b9 00 01 ; 0xc1857 + mov bx, 0556dh ; bb 6d 55 ; 0xc185a + mov dx, 0c000h ; ba 00 c0 ; 0xc185d + call 02e8ch ; e8 29 16 ; 0xc1860 + jmp short 018bah ; eb 55 ; 0xc1863 vgabios.c:1162 + mov al, bl ; 88 d8 ; 0xc1865 vgabios.c:1164 + xor ah, ah ; 30 e4 ; 0xc1867 + push ax ; 50 ; 0xc1869 + xor al, bl ; 30 d8 ; 0xc186a + push ax ; 50 ; 0xc186c + xor al, al ; 30 c0 ; 0xc186d + push ax ; 50 ; 0xc186f + mov cx, 00100h ; b9 00 01 ; 0xc1870 + mov bx, 05d6dh ; bb 6d 5d ; 0xc1873 + mov dx, 0c000h ; ba 00 c0 ; 0xc1876 + call 02e8ch ; e8 10 16 ; 0xc1879 + cmp byte [bp-00ch], 007h ; 80 7e f4 07 ; 0xc187c vgabios.c:1165 + jne short 018bah ; 75 38 ; 0xc1880 + mov cx, strict word 0000eh ; b9 0e 00 ; 0xc1882 vgabios.c:1166 + xor bx, bx ; 31 db ; 0xc1885 + mov dx, 07b6dh ; ba 6d 7b ; 0xc1887 + mov ax, 0c000h ; b8 00 c0 ; 0xc188a + call 02e14h ; e8 84 15 ; 0xc188d + jmp short 018bah ; eb 28 ; 0xc1890 vgabios.c:1167 + jmp near 0191bh ; e9 86 00 ; 0xc1892 + mov al, bl ; 88 d8 ; 0xc1895 vgabios.c:1169 + xor ah, ah ; 30 e4 ; 0xc1897 + push ax ; 50 ; 0xc1899 + xor al, bl ; 30 d8 ; 0xc189a + push ax ; 50 ; 0xc189c + xor al, al ; 30 c0 ; 0xc189d + push ax ; 50 ; 0xc189f + mov cx, 00100h ; b9 00 01 ; 0xc18a0 + mov bx, 06b6dh ; bb 6d 6b ; 0xc18a3 + mov dx, 0c000h ; ba 00 c0 ; 0xc18a6 + call 02e8ch ; e8 e0 15 ; 0xc18a9 + mov cx, strict word 00010h ; b9 10 00 ; 0xc18ac vgabios.c:1170 + xor bx, bx ; 31 db ; 0xc18af + mov dx, 07c9ah ; ba 9a 7c ; 0xc18b1 + mov ax, 0c000h ; b8 00 c0 ; 0xc18b4 + call 02e14h ; e8 5a 15 ; 0xc18b7 + cmp word [bp-01ch], strict byte 00000h ; 83 7e e4 00 ; 0xc18ba vgabios.c:1172 + jne short 018c6h ; 75 06 ; 0xc18be + cmp word [bp-01eh], strict byte 00000h ; 83 7e e2 00 ; 0xc18c0 + je short 01913h ; 74 4d ; 0xc18c4 + xor bx, bx ; 31 db ; 0xc18c6 vgabios.c:1177 + les di, [bp-01eh] ; c4 7e e2 ; 0xc18c8 vgabios.c:1179 + add di, bx ; 01 df ; 0xc18cb + mov al, byte [es:di+00bh] ; 26 8a 45 0b ; 0xc18cd + cmp AL, strict byte 0ffh ; 3c ff ; 0xc18d1 + je short 018ddh ; 74 08 ; 0xc18d3 + cmp al, byte [bp-00ch] ; 3a 46 f4 ; 0xc18d5 vgabios.c:1181 + je short 018ddh ; 74 03 ; 0xc18d8 + inc bx ; 43 ; 0xc18da vgabios.c:1183 + jmp short 018c8h ; eb eb ; 0xc18db vgabios.c:1184 + mov es, [bp-01ch] ; 8e 46 e4 ; 0xc18dd vgabios.c:1186 + add bx, word [bp-01eh] ; 03 5e e2 ; 0xc18e0 + mov al, byte [es:bx+00bh] ; 26 8a 47 0b ; 0xc18e3 + cmp al, byte [bp-00ch] ; 3a 46 f4 ; 0xc18e7 + jne short 01913h ; 75 27 ; 0xc18ea + mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xc18ec vgabios.c:1191 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc18ef + xor ah, ah ; 30 e4 ; 0xc18f2 + push ax ; 50 ; 0xc18f4 + mov al, byte [es:bx+001h] ; 26 8a 47 01 ; 0xc18f5 + push ax ; 50 ; 0xc18f9 + push word [es:bx+004h] ; 26 ff 77 04 ; 0xc18fa + mov cx, word [es:bx+002h] ; 26 8b 4f 02 ; 0xc18fe + mov bx, word [es:bx+006h] ; 26 8b 5f 06 ; 0xc1902 + mov di, word [bp-01eh] ; 8b 7e e2 ; 0xc1906 + mov dx, word [es:di+008h] ; 26 8b 55 08 ; 0xc1909 + mov ax, strict word 00010h ; b8 10 00 ; 0xc190d + call 02e8ch ; e8 79 15 ; 0xc1910 + xor bl, bl ; 30 db ; 0xc1913 vgabios.c:1195 + mov AL, strict byte 003h ; b0 03 ; 0xc1915 + mov AH, strict byte 011h ; b4 11 ; 0xc1917 + int 06dh ; cd 6d ; 0xc1919 + mov bx, 0596dh ; bb 6d 59 ; 0xc191b vgabios.c:1199 + mov cx, ds ; 8c d9 ; 0xc191e + mov ax, strict word 0001fh ; b8 1f 00 ; 0xc1920 + call 009f0h ; e8 ca f0 ; 0xc1923 + mov es, [bp-01ah] ; 8e 46 e6 ; 0xc1926 vgabios.c:1201 + mov dl, byte [es:si+002h] ; 26 8a 54 02 ; 0xc1929 + cmp dl, 010h ; 80 fa 10 ; 0xc192d + je short 0194eh ; 74 1c ; 0xc1930 + cmp dl, 00eh ; 80 fa 0e ; 0xc1932 + je short 01949h ; 74 12 ; 0xc1935 + cmp dl, 008h ; 80 fa 08 ; 0xc1937 + jne short 01953h ; 75 17 ; 0xc193a + mov bx, 0556dh ; bb 6d 55 ; 0xc193c vgabios.c:1203 + mov cx, ds ; 8c d9 ; 0xc193f + mov ax, strict word 00043h ; b8 43 00 ; 0xc1941 + call 009f0h ; e8 a9 f0 ; 0xc1944 + jmp short 01953h ; eb 0a ; 0xc1947 vgabios.c:1204 + mov bx, 05d6dh ; bb 6d 5d ; 0xc1949 vgabios.c:1206 + jmp short 0193fh ; eb f1 ; 0xc194c + mov bx, 06b6dh ; bb 6d 6b ; 0xc194e vgabios.c:1209 + jmp short 0193fh ; eb ec ; 0xc1951 + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc1953 vgabios.c:1212 + pop di ; 5f ; 0xc1956 + pop si ; 5e ; 0xc1957 + pop dx ; 5a ; 0xc1958 + pop cx ; 59 ; 0xc1959 + pop bx ; 5b ; 0xc195a + pop bp ; 5d ; 0xc195b + retn ; c3 ; 0xc195c + ; disGetNextSymbol 0xc195d LB 0x2c07 -> off=0x0 cb=000000000000008e uValue=00000000000c195d 'vgamem_copy_pl4' +vgamem_copy_pl4: ; 0xc195d LB 0x8e + push bp ; 55 ; 0xc195d vgabios.c:1215 + mov bp, sp ; 89 e5 ; 0xc195e + push si ; 56 ; 0xc1960 + push di ; 57 ; 0xc1961 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc1962 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc1965 + mov al, dl ; 88 d0 ; 0xc1968 + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc196a + mov byte [bp-006h], cl ; 88 4e fa ; 0xc196d + xor ah, ah ; 30 e4 ; 0xc1970 vgabios.c:1221 + mov dl, byte [bp+006h] ; 8a 56 06 ; 0xc1972 + xor dh, dh ; 30 f6 ; 0xc1975 + mov cx, dx ; 89 d1 ; 0xc1977 + imul dx ; f7 ea ; 0xc1979 + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc197b + xor dh, dh ; 30 f6 ; 0xc197e + mov si, dx ; 89 d6 ; 0xc1980 + imul dx ; f7 ea ; 0xc1982 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc1984 + xor dh, dh ; 30 f6 ; 0xc1987 + mov bx, dx ; 89 d3 ; 0xc1989 + add ax, dx ; 01 d0 ; 0xc198b + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc198d + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1990 vgabios.c:1222 + xor ah, ah ; 30 e4 ; 0xc1993 + imul cx ; f7 e9 ; 0xc1995 + imul si ; f7 ee ; 0xc1997 + add ax, bx ; 01 d8 ; 0xc1999 + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc199b + mov ax, 00105h ; b8 05 01 ; 0xc199e vgabios.c:1223 + mov dx, 003ceh ; ba ce 03 ; 0xc19a1 + out DX, ax ; ef ; 0xc19a4 + xor bl, bl ; 30 db ; 0xc19a5 vgabios.c:1224 + cmp bl, byte [bp+006h] ; 3a 5e 06 ; 0xc19a7 + jnc short 019dbh ; 73 2f ; 0xc19aa + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc19ac vgabios.c:1226 + xor ah, ah ; 30 e4 ; 0xc19af + mov cx, ax ; 89 c1 ; 0xc19b1 + mov al, bl ; 88 d8 ; 0xc19b3 + mov dx, ax ; 89 c2 ; 0xc19b5 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc19b7 + mov si, ax ; 89 c6 ; 0xc19ba + mov ax, dx ; 89 d0 ; 0xc19bc + imul si ; f7 ee ; 0xc19be + mov si, word [bp-00eh] ; 8b 76 f2 ; 0xc19c0 + add si, ax ; 01 c6 ; 0xc19c3 + mov di, word [bp-00ch] ; 8b 7e f4 ; 0xc19c5 + add di, ax ; 01 c7 ; 0xc19c8 + mov dx, 0a000h ; ba 00 a0 ; 0xc19ca + mov es, dx ; 8e c2 ; 0xc19cd + jcxz 019d7h ; e3 06 ; 0xc19cf + push DS ; 1e ; 0xc19d1 + mov ds, dx ; 8e da ; 0xc19d2 + rep movsb ; f3 a4 ; 0xc19d4 + pop DS ; 1f ; 0xc19d6 + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc19d7 vgabios.c:1227 + jmp short 019a7h ; eb cc ; 0xc19d9 + mov ax, strict word 00005h ; b8 05 00 ; 0xc19db vgabios.c:1228 + mov dx, 003ceh ; ba ce 03 ; 0xc19de + out DX, ax ; ef ; 0xc19e1 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc19e2 vgabios.c:1229 + pop di ; 5f ; 0xc19e5 + pop si ; 5e ; 0xc19e6 + pop bp ; 5d ; 0xc19e7 + retn 00004h ; c2 04 00 ; 0xc19e8 + ; disGetNextSymbol 0xc19eb LB 0x2b79 -> off=0x0 cb=000000000000007b uValue=00000000000c19eb 'vgamem_fill_pl4' +vgamem_fill_pl4: ; 0xc19eb LB 0x7b + push bp ; 55 ; 0xc19eb vgabios.c:1232 + mov bp, sp ; 89 e5 ; 0xc19ec + push si ; 56 ; 0xc19ee + push di ; 57 ; 0xc19ef + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc19f0 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc19f3 + mov al, dl ; 88 d0 ; 0xc19f6 + mov byte [bp-006h], bl ; 88 5e fa ; 0xc19f8 + mov bh, cl ; 88 cf ; 0xc19fb + xor ah, ah ; 30 e4 ; 0xc19fd vgabios.c:1238 + mov dx, ax ; 89 c2 ; 0xc19ff + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1a01 + mov cx, ax ; 89 c1 ; 0xc1a04 + mov ax, dx ; 89 d0 ; 0xc1a06 + imul cx ; f7 e9 ; 0xc1a08 + mov dl, bh ; 88 fa ; 0xc1a0a + xor dh, dh ; 30 f6 ; 0xc1a0c + imul dx ; f7 ea ; 0xc1a0e + mov dx, ax ; 89 c2 ; 0xc1a10 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1a12 + xor ah, ah ; 30 e4 ; 0xc1a15 + add dx, ax ; 01 c2 ; 0xc1a17 + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc1a19 + mov ax, 00205h ; b8 05 02 ; 0xc1a1c vgabios.c:1239 + mov dx, 003ceh ; ba ce 03 ; 0xc1a1f + out DX, ax ; ef ; 0xc1a22 + xor bl, bl ; 30 db ; 0xc1a23 vgabios.c:1240 + cmp bl, byte [bp+004h] ; 3a 5e 04 ; 0xc1a25 + jnc short 01a56h ; 73 2c ; 0xc1a28 + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc1a2a vgabios.c:1242 + xor ch, ch ; 30 ed ; 0xc1a2d + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1a2f + xor ah, ah ; 30 e4 ; 0xc1a32 + mov si, ax ; 89 c6 ; 0xc1a34 + mov al, bl ; 88 d8 ; 0xc1a36 + mov dx, ax ; 89 c2 ; 0xc1a38 + mov al, bh ; 88 f8 ; 0xc1a3a + mov di, ax ; 89 c7 ; 0xc1a3c + mov ax, dx ; 89 d0 ; 0xc1a3e + imul di ; f7 ef ; 0xc1a40 + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc1a42 + add di, ax ; 01 c7 ; 0xc1a45 + mov ax, si ; 89 f0 ; 0xc1a47 + mov dx, 0a000h ; ba 00 a0 ; 0xc1a49 + mov es, dx ; 8e c2 ; 0xc1a4c + jcxz 01a52h ; e3 02 ; 0xc1a4e + rep stosb ; f3 aa ; 0xc1a50 + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc1a52 vgabios.c:1243 + jmp short 01a25h ; eb cf ; 0xc1a54 + mov ax, strict word 00005h ; b8 05 00 ; 0xc1a56 vgabios.c:1244 + mov dx, 003ceh ; ba ce 03 ; 0xc1a59 + out DX, ax ; ef ; 0xc1a5c + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1a5d vgabios.c:1245 + pop di ; 5f ; 0xc1a60 + pop si ; 5e ; 0xc1a61 + pop bp ; 5d ; 0xc1a62 + retn 00004h ; c2 04 00 ; 0xc1a63 + ; disGetNextSymbol 0xc1a66 LB 0x2afe -> off=0x0 cb=00000000000000b6 uValue=00000000000c1a66 'vgamem_copy_cga' +vgamem_copy_cga: ; 0xc1a66 LB 0xb6 + push bp ; 55 ; 0xc1a66 vgabios.c:1248 + mov bp, sp ; 89 e5 ; 0xc1a67 + push si ; 56 ; 0xc1a69 + push di ; 57 ; 0xc1a6a + sub sp, strict byte 0000eh ; 83 ec 0e ; 0xc1a6b + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc1a6e + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc1a71 + mov byte [bp-00ah], cl ; 88 4e f6 ; 0xc1a74 + mov al, dl ; 88 d0 ; 0xc1a77 vgabios.c:1254 + xor ah, ah ; 30 e4 ; 0xc1a79 + mov bx, ax ; 89 c3 ; 0xc1a7b + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1a7d + mov si, ax ; 89 c6 ; 0xc1a80 + mov ax, bx ; 89 d8 ; 0xc1a82 + imul si ; f7 ee ; 0xc1a84 + mov bl, byte [bp+004h] ; 8a 5e 04 ; 0xc1a86 + mov di, bx ; 89 df ; 0xc1a89 + imul bx ; f7 eb ; 0xc1a8b + mov dx, ax ; 89 c2 ; 0xc1a8d + sar dx, 1 ; d1 fa ; 0xc1a8f + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1a91 + xor ah, ah ; 30 e4 ; 0xc1a94 + mov bx, ax ; 89 c3 ; 0xc1a96 + add dx, ax ; 01 c2 ; 0xc1a98 + mov word [bp-00eh], dx ; 89 56 f2 ; 0xc1a9a + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1a9d vgabios.c:1255 + imul si ; f7 ee ; 0xc1aa0 + imul di ; f7 ef ; 0xc1aa2 + sar ax, 1 ; d1 f8 ; 0xc1aa4 + add ax, bx ; 01 d8 ; 0xc1aa6 + mov word [bp-010h], ax ; 89 46 f0 ; 0xc1aa8 + mov byte [bp-006h], bh ; 88 7e fa ; 0xc1aab vgabios.c:1256 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1aae + xor ah, ah ; 30 e4 ; 0xc1ab1 + cwd ; 99 ; 0xc1ab3 + db 02bh, 0c2h + ; sub ax, dx ; 2b c2 ; 0xc1ab4 + sar ax, 1 ; d1 f8 ; 0xc1ab6 + mov bx, ax ; 89 c3 ; 0xc1ab8 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1aba + xor ah, ah ; 30 e4 ; 0xc1abd + cmp ax, bx ; 39 d8 ; 0xc1abf + jnl short 01b13h ; 7d 50 ; 0xc1ac1 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc1ac3 vgabios.c:1258 + xor bh, bh ; 30 ff ; 0xc1ac6 + mov word [bp-012h], bx ; 89 5e ee ; 0xc1ac8 + mov bl, byte [bp+004h] ; 8a 5e 04 ; 0xc1acb + imul bx ; f7 eb ; 0xc1ace + mov bx, ax ; 89 c3 ; 0xc1ad0 + mov si, word [bp-00eh] ; 8b 76 f2 ; 0xc1ad2 + add si, ax ; 01 c6 ; 0xc1ad5 + mov di, word [bp-010h] ; 8b 7e f0 ; 0xc1ad7 + add di, ax ; 01 c7 ; 0xc1ada + mov cx, word [bp-012h] ; 8b 4e ee ; 0xc1adc + mov dx, 0b800h ; ba 00 b8 ; 0xc1adf + mov es, dx ; 8e c2 ; 0xc1ae2 + jcxz 01aech ; e3 06 ; 0xc1ae4 + push DS ; 1e ; 0xc1ae6 + mov ds, dx ; 8e da ; 0xc1ae7 + rep movsb ; f3 a4 ; 0xc1ae9 + pop DS ; 1f ; 0xc1aeb + mov si, word [bp-00eh] ; 8b 76 f2 ; 0xc1aec vgabios.c:1259 + add si, 02000h ; 81 c6 00 20 ; 0xc1aef + add si, bx ; 01 de ; 0xc1af3 + mov di, word [bp-010h] ; 8b 7e f0 ; 0xc1af5 + add di, 02000h ; 81 c7 00 20 ; 0xc1af8 + add di, bx ; 01 df ; 0xc1afc + mov cx, word [bp-012h] ; 8b 4e ee ; 0xc1afe + mov dx, 0b800h ; ba 00 b8 ; 0xc1b01 + mov es, dx ; 8e c2 ; 0xc1b04 + jcxz 01b0eh ; e3 06 ; 0xc1b06 + push DS ; 1e ; 0xc1b08 + mov ds, dx ; 8e da ; 0xc1b09 + rep movsb ; f3 a4 ; 0xc1b0b + pop DS ; 1f ; 0xc1b0d + inc byte [bp-006h] ; fe 46 fa ; 0xc1b0e vgabios.c:1260 + jmp short 01aaeh ; eb 9b ; 0xc1b11 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1b13 vgabios.c:1261 + pop di ; 5f ; 0xc1b16 + pop si ; 5e ; 0xc1b17 + pop bp ; 5d ; 0xc1b18 + retn 00004h ; c2 04 00 ; 0xc1b19 + ; disGetNextSymbol 0xc1b1c LB 0x2a48 -> off=0x0 cb=0000000000000094 uValue=00000000000c1b1c 'vgamem_fill_cga' +vgamem_fill_cga: ; 0xc1b1c LB 0x94 + push bp ; 55 ; 0xc1b1c vgabios.c:1264 + mov bp, sp ; 89 e5 ; 0xc1b1d + push si ; 56 ; 0xc1b1f + push di ; 57 ; 0xc1b20 + sub sp, strict byte 0000ch ; 83 ec 0c ; 0xc1b21 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc1b24 + mov al, dl ; 88 d0 ; 0xc1b27 + mov byte [bp-00ch], bl ; 88 5e f4 ; 0xc1b29 + mov byte [bp-008h], cl ; 88 4e f8 ; 0xc1b2c + xor ah, ah ; 30 e4 ; 0xc1b2f vgabios.c:1270 + mov dx, ax ; 89 c2 ; 0xc1b31 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1b33 + mov bx, ax ; 89 c3 ; 0xc1b36 + mov ax, dx ; 89 d0 ; 0xc1b38 + imul bx ; f7 eb ; 0xc1b3a + mov dl, cl ; 88 ca ; 0xc1b3c + xor dh, dh ; 30 f6 ; 0xc1b3e + imul dx ; f7 ea ; 0xc1b40 + mov dx, ax ; 89 c2 ; 0xc1b42 + sar dx, 1 ; d1 fa ; 0xc1b44 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1b46 + xor ah, ah ; 30 e4 ; 0xc1b49 + add dx, ax ; 01 c2 ; 0xc1b4b + mov word [bp-00eh], dx ; 89 56 f2 ; 0xc1b4d + mov byte [bp-006h], ah ; 88 66 fa ; 0xc1b50 vgabios.c:1271 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1b53 + xor ah, ah ; 30 e4 ; 0xc1b56 + cwd ; 99 ; 0xc1b58 + db 02bh, 0c2h + ; sub ax, dx ; 2b c2 ; 0xc1b59 + sar ax, 1 ; d1 f8 ; 0xc1b5b + mov dx, ax ; 89 c2 ; 0xc1b5d + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1b5f + xor ah, ah ; 30 e4 ; 0xc1b62 + cmp ax, dx ; 39 d0 ; 0xc1b64 + jnl short 01ba7h ; 7d 3f ; 0xc1b66 + mov bl, byte [bp-00ch] ; 8a 5e f4 ; 0xc1b68 vgabios.c:1273 + xor bh, bh ; 30 ff ; 0xc1b6b + mov dl, byte [bp+006h] ; 8a 56 06 ; 0xc1b6d + xor dh, dh ; 30 f6 ; 0xc1b70 + mov si, dx ; 89 d6 ; 0xc1b72 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc1b74 + imul dx ; f7 ea ; 0xc1b77 + mov word [bp-010h], ax ; 89 46 f0 ; 0xc1b79 + mov di, word [bp-00eh] ; 8b 7e f2 ; 0xc1b7c + add di, ax ; 01 c7 ; 0xc1b7f + mov cx, bx ; 89 d9 ; 0xc1b81 + mov ax, si ; 89 f0 ; 0xc1b83 + mov dx, 0b800h ; ba 00 b8 ; 0xc1b85 + mov es, dx ; 8e c2 ; 0xc1b88 + jcxz 01b8eh ; e3 02 ; 0xc1b8a + rep stosb ; f3 aa ; 0xc1b8c + mov di, word [bp-00eh] ; 8b 7e f2 ; 0xc1b8e vgabios.c:1274 + add di, 02000h ; 81 c7 00 20 ; 0xc1b91 + add di, word [bp-010h] ; 03 7e f0 ; 0xc1b95 + mov cx, bx ; 89 d9 ; 0xc1b98 + mov ax, si ; 89 f0 ; 0xc1b9a + mov es, dx ; 8e c2 ; 0xc1b9c + jcxz 01ba2h ; e3 02 ; 0xc1b9e + rep stosb ; f3 aa ; 0xc1ba0 + inc byte [bp-006h] ; fe 46 fa ; 0xc1ba2 vgabios.c:1275 + jmp short 01b53h ; eb ac ; 0xc1ba5 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1ba7 vgabios.c:1276 + pop di ; 5f ; 0xc1baa + pop si ; 5e ; 0xc1bab + pop bp ; 5d ; 0xc1bac + retn 00004h ; c2 04 00 ; 0xc1bad + ; disGetNextSymbol 0xc1bb0 LB 0x29b4 -> off=0x0 cb=0000000000000083 uValue=00000000000c1bb0 'vgamem_copy_linear' +vgamem_copy_linear: ; 0xc1bb0 LB 0x83 + push bp ; 55 ; 0xc1bb0 vgabios.c:1279 + mov bp, sp ; 89 e5 ; 0xc1bb1 + push si ; 56 ; 0xc1bb3 + push di ; 57 ; 0xc1bb4 + sub sp, strict byte 0000ch ; 83 ec 0c ; 0xc1bb5 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc1bb8 + mov al, dl ; 88 d0 ; 0xc1bbb + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc1bbd + mov bx, cx ; 89 cb ; 0xc1bc0 + xor ah, ah ; 30 e4 ; 0xc1bc2 vgabios.c:1285 + mov si, ax ; 89 c6 ; 0xc1bc4 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1bc6 + mov word [bp-010h], ax ; 89 46 f0 ; 0xc1bc9 + mov ax, si ; 89 f0 ; 0xc1bcc + imul word [bp-010h] ; f7 6e f0 ; 0xc1bce + mul word [bp+004h] ; f7 66 04 ; 0xc1bd1 + mov si, ax ; 89 c6 ; 0xc1bd4 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1bd6 + xor ah, ah ; 30 e4 ; 0xc1bd9 + mov di, ax ; 89 c7 ; 0xc1bdb + add si, ax ; 01 c6 ; 0xc1bdd + mov CL, strict byte 003h ; b1 03 ; 0xc1bdf + sal si, CL ; d3 e6 ; 0xc1be1 + mov word [bp-00ch], si ; 89 76 f4 ; 0xc1be3 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1be6 vgabios.c:1286 + imul word [bp-010h] ; f7 6e f0 ; 0xc1be9 + mul word [bp+004h] ; f7 66 04 ; 0xc1bec + add ax, di ; 01 f8 ; 0xc1bef + sal ax, CL ; d3 e0 ; 0xc1bf1 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc1bf3 + sal bx, CL ; d3 e3 ; 0xc1bf6 vgabios.c:1287 + sal word [bp+004h], CL ; d3 66 04 ; 0xc1bf8 vgabios.c:1288 + mov byte [bp-006h], 000h ; c6 46 fa 00 ; 0xc1bfb vgabios.c:1289 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1bff + cmp al, byte [bp+006h] ; 3a 46 06 ; 0xc1c02 + jnc short 01c2ah ; 73 23 ; 0xc1c05 + xor ah, ah ; 30 e4 ; 0xc1c07 vgabios.c:1291 + mul word [bp+004h] ; f7 66 04 ; 0xc1c09 + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc1c0c + add si, ax ; 01 c6 ; 0xc1c0f + mov di, word [bp-00eh] ; 8b 7e f2 ; 0xc1c11 + add di, ax ; 01 c7 ; 0xc1c14 + mov cx, bx ; 89 d9 ; 0xc1c16 + mov dx, 0a000h ; ba 00 a0 ; 0xc1c18 + mov es, dx ; 8e c2 ; 0xc1c1b + jcxz 01c25h ; e3 06 ; 0xc1c1d + push DS ; 1e ; 0xc1c1f + mov ds, dx ; 8e da ; 0xc1c20 + rep movsb ; f3 a4 ; 0xc1c22 + pop DS ; 1f ; 0xc1c24 + inc byte [bp-006h] ; fe 46 fa ; 0xc1c25 vgabios.c:1292 + jmp short 01bffh ; eb d5 ; 0xc1c28 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1c2a vgabios.c:1293 + pop di ; 5f ; 0xc1c2d + pop si ; 5e ; 0xc1c2e + pop bp ; 5d ; 0xc1c2f + retn 00004h ; c2 04 00 ; 0xc1c30 + ; disGetNextSymbol 0xc1c33 LB 0x2931 -> off=0x0 cb=000000000000006c uValue=00000000000c1c33 'vgamem_fill_linear' +vgamem_fill_linear: ; 0xc1c33 LB 0x6c + push bp ; 55 ; 0xc1c33 vgabios.c:1296 + mov bp, sp ; 89 e5 ; 0xc1c34 + push si ; 56 ; 0xc1c36 + push di ; 57 ; 0xc1c37 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc1c38 + mov byte [bp-006h], al ; 88 46 fa ; 0xc1c3b + mov al, dl ; 88 d0 ; 0xc1c3e + mov si, cx ; 89 ce ; 0xc1c40 + xor ah, ah ; 30 e4 ; 0xc1c42 vgabios.c:1302 + mov dx, ax ; 89 c2 ; 0xc1c44 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1c46 + mov di, ax ; 89 c7 ; 0xc1c49 + mov ax, dx ; 89 d0 ; 0xc1c4b + imul di ; f7 ef ; 0xc1c4d + mul cx ; f7 e1 ; 0xc1c4f + mov dx, ax ; 89 c2 ; 0xc1c51 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1c53 + xor ah, ah ; 30 e4 ; 0xc1c56 + add ax, dx ; 01 d0 ; 0xc1c58 + mov CL, strict byte 003h ; b1 03 ; 0xc1c5a + sal ax, CL ; d3 e0 ; 0xc1c5c + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc1c5e + sal bx, CL ; d3 e3 ; 0xc1c61 vgabios.c:1303 + sal si, CL ; d3 e6 ; 0xc1c63 vgabios.c:1304 + mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xc1c65 vgabios.c:1305 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1c69 + cmp al, byte [bp+004h] ; 3a 46 04 ; 0xc1c6c + jnc short 01c96h ; 73 25 ; 0xc1c6f + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc1c71 vgabios.c:1307 + xor ah, ah ; 30 e4 ; 0xc1c74 + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc1c76 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1c79 + mul si ; f7 e6 ; 0xc1c7c + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc1c7e + add di, ax ; 01 c7 ; 0xc1c81 + mov cx, bx ; 89 d9 ; 0xc1c83 + mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xc1c85 + mov dx, 0a000h ; ba 00 a0 ; 0xc1c88 + mov es, dx ; 8e c2 ; 0xc1c8b + jcxz 01c91h ; e3 02 ; 0xc1c8d + rep stosb ; f3 aa ; 0xc1c8f + inc byte [bp-008h] ; fe 46 f8 ; 0xc1c91 vgabios.c:1308 + jmp short 01c69h ; eb d3 ; 0xc1c94 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc1c96 vgabios.c:1309 + pop di ; 5f ; 0xc1c99 + pop si ; 5e ; 0xc1c9a + pop bp ; 5d ; 0xc1c9b + retn 00004h ; c2 04 00 ; 0xc1c9c + ; disGetNextSymbol 0xc1c9f LB 0x28c5 -> off=0x0 cb=00000000000006a3 uValue=00000000000c1c9f 'biosfn_scroll' +biosfn_scroll: ; 0xc1c9f LB 0x6a3 + push bp ; 55 ; 0xc1c9f vgabios.c:1312 + mov bp, sp ; 89 e5 ; 0xc1ca0 + push si ; 56 ; 0xc1ca2 + push di ; 57 ; 0xc1ca3 + sub sp, strict byte 00020h ; 83 ec 20 ; 0xc1ca4 + mov byte [bp-006h], al ; 88 46 fa ; 0xc1ca7 + mov byte [bp-010h], dl ; 88 56 f0 ; 0xc1caa + mov byte [bp-00ch], bl ; 88 5e f4 ; 0xc1cad + mov byte [bp-008h], cl ; 88 4e f8 ; 0xc1cb0 + mov ch, byte [bp+006h] ; 8a 6e 06 ; 0xc1cb3 + cmp bl, byte [bp+004h] ; 3a 5e 04 ; 0xc1cb6 vgabios.c:1321 + jnbe short 01cd6h ; 77 1b ; 0xc1cb9 + cmp ch, cl ; 38 cd ; 0xc1cbb vgabios.c:1322 + jc short 01cd6h ; 72 17 ; 0xc1cbd + mov bx, strict word 00049h ; bb 49 00 ; 0xc1cbf vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1cc2 + mov es, ax ; 8e c0 ; 0xc1cc5 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1cc7 + xor ah, ah ; 30 e4 ; 0xc1cca vgabios.c:1326 + call 03888h ; e8 b9 1b ; 0xc1ccc + mov byte [bp-012h], al ; 88 46 ee ; 0xc1ccf + cmp AL, strict byte 0ffh ; 3c ff ; 0xc1cd2 vgabios.c:1327 + jne short 01cd9h ; 75 03 ; 0xc1cd4 + jmp near 02339h ; e9 60 06 ; 0xc1cd6 + mov bx, 00084h ; bb 84 00 ; 0xc1cd9 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc1cdc + mov es, ax ; 8e c0 ; 0xc1cdf + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1ce1 + xor ah, ah ; 30 e4 ; 0xc1ce4 vgabios.c:48 + inc ax ; 40 ; 0xc1ce6 + mov word [bp-024h], ax ; 89 46 dc ; 0xc1ce7 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc1cea vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc1ced + mov word [bp-018h], ax ; 89 46 e8 ; 0xc1cf0 vgabios.c:58 + cmp byte [bp+008h], 0ffh ; 80 7e 08 ff ; 0xc1cf3 vgabios.c:1334 + jne short 01d02h ; 75 09 ; 0xc1cf7 + mov bx, strict word 00062h ; bb 62 00 ; 0xc1cf9 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc1cfc + mov byte [bp+008h], al ; 88 46 08 ; 0xc1cff vgabios.c:48 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1d02 vgabios.c:1337 + xor ah, ah ; 30 e4 ; 0xc1d05 + cmp ax, word [bp-024h] ; 3b 46 dc ; 0xc1d07 + jc short 01d14h ; 72 08 ; 0xc1d0a + mov al, byte [bp-024h] ; 8a 46 dc ; 0xc1d0c + db 0feh, 0c8h + ; dec al ; fe c8 ; 0xc1d0f + mov byte [bp+004h], al ; 88 46 04 ; 0xc1d11 + mov al, ch ; 88 e8 ; 0xc1d14 vgabios.c:1338 + xor ah, ah ; 30 e4 ; 0xc1d16 + cmp ax, word [bp-018h] ; 3b 46 e8 ; 0xc1d18 + jc short 01d22h ; 72 05 ; 0xc1d1b + mov ch, byte [bp-018h] ; 8a 6e e8 ; 0xc1d1d + db 0feh, 0cdh + ; dec ch ; fe cd ; 0xc1d20 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1d22 vgabios.c:1339 + xor ah, ah ; 30 e4 ; 0xc1d25 + cmp ax, word [bp-024h] ; 3b 46 dc ; 0xc1d27 + jbe short 01d2fh ; 76 03 ; 0xc1d2a + mov byte [bp-006h], ah ; 88 66 fa ; 0xc1d2c + mov al, ch ; 88 e8 ; 0xc1d2f vgabios.c:1340 + sub al, byte [bp-008h] ; 2a 46 f8 ; 0xc1d31 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc1d34 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc1d36 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc1d39 vgabios.c:1342 + mov byte [bp-01eh], al ; 88 46 e2 ; 0xc1d3c + mov byte [bp-01dh], 000h ; c6 46 e3 00 ; 0xc1d3f + mov CL, strict byte 003h ; b1 03 ; 0xc1d43 + mov bx, word [bp-01eh] ; 8b 5e e2 ; 0xc1d45 + sal bx, CL ; d3 e3 ; 0xc1d48 + mov ax, word [bp-018h] ; 8b 46 e8 ; 0xc1d4a + dec ax ; 48 ; 0xc1d4d + mov word [bp-020h], ax ; 89 46 e0 ; 0xc1d4e + mov ax, word [bp-024h] ; 8b 46 dc ; 0xc1d51 + dec ax ; 48 ; 0xc1d54 + mov word [bp-022h], ax ; 89 46 de ; 0xc1d55 + mov ax, word [bp-018h] ; 8b 46 e8 ; 0xc1d58 + mul word [bp-024h] ; f7 66 dc ; 0xc1d5b + mov di, ax ; 89 c7 ; 0xc1d5e + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc1d60 + jne short 01db1h ; 75 4a ; 0xc1d65 + sal ax, 1 ; d1 e0 ; 0xc1d67 vgabios.c:1345 + or AL, strict byte 0ffh ; 0c ff ; 0xc1d69 + mov dl, byte [bp+008h] ; 8a 56 08 ; 0xc1d6b + xor dh, dh ; 30 f6 ; 0xc1d6e + inc ax ; 40 ; 0xc1d70 + mul dx ; f7 e2 ; 0xc1d71 + mov word [bp-01ch], ax ; 89 46 e4 ; 0xc1d73 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1d76 vgabios.c:1350 + jne short 01db4h ; 75 38 ; 0xc1d7a + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc1d7c + jne short 01db4h ; 75 32 ; 0xc1d80 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1d82 + jne short 01db4h ; 75 2c ; 0xc1d86 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1d88 + xor ah, ah ; 30 e4 ; 0xc1d8b + cmp ax, word [bp-022h] ; 3b 46 de ; 0xc1d8d + jne short 01db4h ; 75 22 ; 0xc1d90 + mov al, ch ; 88 e8 ; 0xc1d92 + cmp ax, word [bp-020h] ; 3b 46 e0 ; 0xc1d94 + jne short 01db4h ; 75 1b ; 0xc1d97 + mov ah, byte [bp-010h] ; 8a 66 f0 ; 0xc1d99 vgabios.c:1352 + xor al, ch ; 30 e8 ; 0xc1d9c + add ax, strict word 00020h ; 05 20 00 ; 0xc1d9e + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1da1 + mov cx, di ; 89 f9 ; 0xc1da5 + mov di, word [bp-01ch] ; 8b 7e e4 ; 0xc1da7 + jcxz 01daeh ; e3 02 ; 0xc1daa + rep stosw ; f3 ab ; 0xc1dac + jmp near 02339h ; e9 88 05 ; 0xc1dae vgabios.c:1354 + jmp near 01f3eh ; e9 8a 01 ; 0xc1db1 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc1db4 vgabios.c:1356 + jne short 01e1fh ; 75 65 ; 0xc1db8 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1dba vgabios.c:1357 + xor ah, ah ; 30 e4 ; 0xc1dbd + mov word [bp-016h], ax ; 89 46 ea ; 0xc1dbf + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc1dc2 + xor dh, dh ; 30 f6 ; 0xc1dc5 + cmp dx, word [bp-016h] ; 3b 56 ea ; 0xc1dc7 + jc short 01e21h ; 72 55 ; 0xc1dca + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1dcc vgabios.c:1359 + xor ah, ah ; 30 e4 ; 0xc1dcf + add ax, word [bp-016h] ; 03 46 ea ; 0xc1dd1 + cmp ax, dx ; 39 d0 ; 0xc1dd4 + jnbe short 01ddeh ; 77 06 ; 0xc1dd6 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1dd8 + jne short 01e24h ; 75 46 ; 0xc1ddc + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1dde vgabios.c:1360 + mov byte [bp-01ah], al ; 88 46 e6 ; 0xc1de1 + xor al, al ; 30 c0 ; 0xc1de4 + mov byte [bp-019h], al ; 88 46 e7 ; 0xc1de6 + mov ah, byte [bp-010h] ; 8a 66 f0 ; 0xc1de9 + mov si, ax ; 89 c6 ; 0xc1dec + add si, strict byte 00020h ; 83 c6 20 ; 0xc1dee + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc1df1 + mul word [bp-018h] ; f7 66 e8 ; 0xc1df4 + mov dx, ax ; 89 c2 ; 0xc1df7 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1df9 + xor ah, ah ; 30 e4 ; 0xc1dfc + add ax, dx ; 01 d0 ; 0xc1dfe + sal ax, 1 ; d1 e0 ; 0xc1e00 + mov di, word [bp-01ch] ; 8b 7e e4 ; 0xc1e02 + add di, ax ; 01 c7 ; 0xc1e05 + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1e07 + xor bh, bh ; 30 ff ; 0xc1e0a + mov CL, strict byte 003h ; b1 03 ; 0xc1e0c + sal bx, CL ; d3 e3 ; 0xc1e0e + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc1e10 + mov cx, word [bp-01ah] ; 8b 4e e6 ; 0xc1e14 + mov ax, si ; 89 f0 ; 0xc1e17 + jcxz 01e1dh ; e3 02 ; 0xc1e19 + rep stosw ; f3 ab ; 0xc1e1b + jmp short 01e6dh ; eb 4e ; 0xc1e1d vgabios.c:1361 + jmp short 01e73h ; eb 52 ; 0xc1e1f + jmp near 02339h ; e9 15 05 ; 0xc1e21 + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc1e24 vgabios.c:1362 + mov byte [bp-014h], dl ; 88 56 ec ; 0xc1e27 + mov byte [bp-013h], dh ; 88 76 ed ; 0xc1e2a + mul word [bp-018h] ; f7 66 e8 ; 0xc1e2d + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc1e30 + mov byte [bp-01ah], dl ; 88 56 e6 ; 0xc1e33 + mov byte [bp-019h], 000h ; c6 46 e7 00 ; 0xc1e36 + mov si, ax ; 89 c6 ; 0xc1e3a + add si, word [bp-01ah] ; 03 76 e6 ; 0xc1e3c + sal si, 1 ; d1 e6 ; 0xc1e3f + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1e41 + xor bh, bh ; 30 ff ; 0xc1e44 + mov CL, strict byte 003h ; b1 03 ; 0xc1e46 + sal bx, CL ; d3 e3 ; 0xc1e48 + mov bx, word [bx+047b3h] ; 8b 9f b3 47 ; 0xc1e4a + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc1e4e + mul word [bp-018h] ; f7 66 e8 ; 0xc1e51 + add ax, word [bp-01ah] ; 03 46 e6 ; 0xc1e54 + sal ax, 1 ; d1 e0 ; 0xc1e57 + mov di, word [bp-01ch] ; 8b 7e e4 ; 0xc1e59 + add di, ax ; 01 c7 ; 0xc1e5c + mov cx, word [bp-014h] ; 8b 4e ec ; 0xc1e5e + mov dx, bx ; 89 da ; 0xc1e61 + mov es, bx ; 8e c3 ; 0xc1e63 + jcxz 01e6dh ; e3 06 ; 0xc1e65 + push DS ; 1e ; 0xc1e67 + mov ds, dx ; 8e da ; 0xc1e68 + rep movsw ; f3 a5 ; 0xc1e6a + pop DS ; 1f ; 0xc1e6c + inc word [bp-016h] ; ff 46 ea ; 0xc1e6d vgabios.c:1363 + jmp near 01dc2h ; e9 4f ff ; 0xc1e70 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1e73 vgabios.c:1366 + xor ah, ah ; 30 e4 ; 0xc1e76 + mov word [bp-016h], ax ; 89 46 ea ; 0xc1e78 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1e7b + xor ah, ah ; 30 e4 ; 0xc1e7e + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc1e80 + jnbe short 01e21h ; 77 9c ; 0xc1e83 + mov dl, al ; 88 c2 ; 0xc1e85 vgabios.c:1368 + xor dh, dh ; 30 f6 ; 0xc1e87 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1e89 + add ax, dx ; 01 d0 ; 0xc1e8c + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc1e8e + jnbe short 01e99h ; 77 06 ; 0xc1e91 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1e93 + jne short 01ed9h ; 75 40 ; 0xc1e97 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc1e99 vgabios.c:1369 + xor bh, bh ; 30 ff ; 0xc1e9c + mov ah, byte [bp-010h] ; 8a 66 f0 ; 0xc1e9e + xor al, al ; 30 c0 ; 0xc1ea1 + mov si, ax ; 89 c6 ; 0xc1ea3 + add si, strict byte 00020h ; 83 c6 20 ; 0xc1ea5 + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc1ea8 + mul word [bp-018h] ; f7 66 e8 ; 0xc1eab + mov dx, ax ; 89 c2 ; 0xc1eae + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc1eb0 + xor ah, ah ; 30 e4 ; 0xc1eb3 + add ax, dx ; 01 d0 ; 0xc1eb5 + sal ax, 1 ; d1 e0 ; 0xc1eb7 + mov dx, word [bp-01ch] ; 8b 56 e4 ; 0xc1eb9 + add dx, ax ; 01 c2 ; 0xc1ebc + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc1ebe + xor ah, ah ; 30 e4 ; 0xc1ec1 + mov CL, strict byte 003h ; b1 03 ; 0xc1ec3 + mov di, ax ; 89 c7 ; 0xc1ec5 + sal di, CL ; d3 e7 ; 0xc1ec7 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc1ec9 + mov cx, bx ; 89 d9 ; 0xc1ecd + mov ax, si ; 89 f0 ; 0xc1ecf + mov di, dx ; 89 d7 ; 0xc1ed1 + jcxz 01ed7h ; e3 02 ; 0xc1ed3 + rep stosw ; f3 ab ; 0xc1ed5 + jmp short 01f2eh ; eb 55 ; 0xc1ed7 vgabios.c:1370 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc1ed9 vgabios.c:1371 + mov byte [bp-01ah], al ; 88 46 e6 ; 0xc1edc + mov byte [bp-019h], dh ; 88 76 e7 ; 0xc1edf + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc1ee2 + xor ah, ah ; 30 e4 ; 0xc1ee5 + mov dx, word [bp-016h] ; 8b 56 ea ; 0xc1ee7 + sub dx, ax ; 29 c2 ; 0xc1eea + mov ax, dx ; 89 d0 ; 0xc1eec + mul word [bp-018h] ; f7 66 e8 ; 0xc1eee + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc1ef1 + mov byte [bp-014h], dl ; 88 56 ec ; 0xc1ef4 + mov byte [bp-013h], 000h ; c6 46 ed 00 ; 0xc1ef7 + mov si, ax ; 89 c6 ; 0xc1efb + add si, word [bp-014h] ; 03 76 ec ; 0xc1efd + sal si, 1 ; d1 e6 ; 0xc1f00 + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1f02 + xor bh, bh ; 30 ff ; 0xc1f05 + mov CL, strict byte 003h ; b1 03 ; 0xc1f07 + sal bx, CL ; d3 e3 ; 0xc1f09 + mov bx, word [bx+047b3h] ; 8b 9f b3 47 ; 0xc1f0b + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc1f0f + mul word [bp-018h] ; f7 66 e8 ; 0xc1f12 + add ax, word [bp-014h] ; 03 46 ec ; 0xc1f15 + sal ax, 1 ; d1 e0 ; 0xc1f18 + mov di, word [bp-01ch] ; 8b 7e e4 ; 0xc1f1a + add di, ax ; 01 c7 ; 0xc1f1d + mov cx, word [bp-01ah] ; 8b 4e e6 ; 0xc1f1f + mov dx, bx ; 89 da ; 0xc1f22 + mov es, bx ; 8e c3 ; 0xc1f24 + jcxz 01f2eh ; e3 06 ; 0xc1f26 + push DS ; 1e ; 0xc1f28 + mov ds, dx ; 8e da ; 0xc1f29 + rep movsw ; f3 a5 ; 0xc1f2b + pop DS ; 1f ; 0xc1f2d + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1f2e vgabios.c:1372 + xor ah, ah ; 30 e4 ; 0xc1f31 + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc1f33 + jc short 01f6ch ; 72 34 ; 0xc1f36 + dec word [bp-016h] ; ff 4e ea ; 0xc1f38 vgabios.c:1373 + jmp near 01e7bh ; e9 3d ff ; 0xc1f3b + mov si, word [bp-01eh] ; 8b 76 e2 ; 0xc1f3e vgabios.c:1379 + mov al, byte [si+0482fh] ; 8a 84 2f 48 ; 0xc1f41 + xor ah, ah ; 30 e4 ; 0xc1f45 + mov CL, strict byte 006h ; b1 06 ; 0xc1f47 + mov si, ax ; 89 c6 ; 0xc1f49 + sal si, CL ; d3 e6 ; 0xc1f4b + mov al, byte [si+04845h] ; 8a 84 45 48 ; 0xc1f4d + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc1f51 + mov al, byte [bx+047b1h] ; 8a 87 b1 47 ; 0xc1f54 vgabios.c:1380 + cmp AL, strict byte 003h ; 3c 03 ; 0xc1f58 + jc short 01f68h ; 72 0c ; 0xc1f5a + jbe short 01f6fh ; 76 11 ; 0xc1f5c + cmp AL, strict byte 005h ; 3c 05 ; 0xc1f5e + je short 01f9ch ; 74 3a ; 0xc1f60 + cmp AL, strict byte 004h ; 3c 04 ; 0xc1f62 + je short 01f6fh ; 74 09 ; 0xc1f64 + jmp short 01f6ch ; eb 04 ; 0xc1f66 + cmp AL, strict byte 002h ; 3c 02 ; 0xc1f68 + je short 01f9fh ; 74 33 ; 0xc1f6a + jmp near 02339h ; e9 ca 03 ; 0xc1f6c + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc1f6f vgabios.c:1384 + jne short 01f9ah ; 75 25 ; 0xc1f73 + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc1f75 + jne short 01fddh ; 75 62 ; 0xc1f79 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc1f7b + jne short 01fddh ; 75 5c ; 0xc1f7f + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1f81 + xor ah, ah ; 30 e4 ; 0xc1f84 + mov dx, word [bp-024h] ; 8b 56 dc ; 0xc1f86 + dec dx ; 4a ; 0xc1f89 + cmp ax, dx ; 39 d0 ; 0xc1f8a + jne short 01fddh ; 75 4f ; 0xc1f8c + mov al, ch ; 88 e8 ; 0xc1f8e + xor ah, dh ; 30 f4 ; 0xc1f90 + mov dx, word [bp-018h] ; 8b 56 e8 ; 0xc1f92 + dec dx ; 4a ; 0xc1f95 + cmp ax, dx ; 39 d0 ; 0xc1f96 + je short 01fa2h ; 74 08 ; 0xc1f98 + jmp short 01fddh ; eb 41 ; 0xc1f9a + jmp near 0221dh ; e9 7e 02 ; 0xc1f9c + jmp near 020c9h ; e9 27 01 ; 0xc1f9f + mov ax, 00205h ; b8 05 02 ; 0xc1fa2 vgabios.c:1386 + mov dx, 003ceh ; ba ce 03 ; 0xc1fa5 + out DX, ax ; ef ; 0xc1fa8 + mov ax, word [bp-024h] ; 8b 46 dc ; 0xc1fa9 vgabios.c:1387 + mul word [bp-018h] ; f7 66 e8 ; 0xc1fac + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc1faf + xor dh, dh ; 30 f6 ; 0xc1fb2 + mul dx ; f7 e2 ; 0xc1fb4 + mov dx, ax ; 89 c2 ; 0xc1fb6 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc1fb8 + xor ah, ah ; 30 e4 ; 0xc1fbb + mov bl, byte [bp-012h] ; 8a 5e ee ; 0xc1fbd + xor bh, bh ; 30 ff ; 0xc1fc0 + mov CL, strict byte 003h ; b1 03 ; 0xc1fc2 + sal bx, CL ; d3 e3 ; 0xc1fc4 + mov bx, word [bx+047b3h] ; 8b 9f b3 47 ; 0xc1fc6 + mov cx, dx ; 89 d1 ; 0xc1fca + xor di, di ; 31 ff ; 0xc1fcc + mov es, bx ; 8e c3 ; 0xc1fce + jcxz 01fd4h ; e3 02 ; 0xc1fd0 + rep stosb ; f3 aa ; 0xc1fd2 + mov ax, strict word 00005h ; b8 05 00 ; 0xc1fd4 vgabios.c:1388 + mov dx, 003ceh ; ba ce 03 ; 0xc1fd7 + out DX, ax ; ef ; 0xc1fda + jmp short 01f6ch ; eb 8f ; 0xc1fdb vgabios.c:1390 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc1fdd vgabios.c:1392 + jne short 0204fh ; 75 6c ; 0xc1fe1 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc1fe3 vgabios.c:1393 + xor ah, ah ; 30 e4 ; 0xc1fe6 + mov word [bp-016h], ax ; 89 46 ea ; 0xc1fe8 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc1feb + xor ah, ah ; 30 e4 ; 0xc1fee + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc1ff0 + jc short 0204ch ; 72 57 ; 0xc1ff3 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc1ff5 vgabios.c:1395 + xor dh, dh ; 30 f6 ; 0xc1ff8 + add dx, word [bp-016h] ; 03 56 ea ; 0xc1ffa + cmp dx, ax ; 39 c2 ; 0xc1ffd + jnbe short 02007h ; 77 06 ; 0xc1fff + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc2001 + jne short 02028h ; 75 21 ; 0xc2005 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2007 vgabios.c:1396 + xor ah, ah ; 30 e4 ; 0xc200a + push ax ; 50 ; 0xc200c + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc200d + push ax ; 50 ; 0xc2010 + mov cl, byte [bp-018h] ; 8a 4e e8 ; 0xc2011 + xor ch, ch ; 30 ed ; 0xc2014 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc2016 + xor bh, bh ; 30 ff ; 0xc2019 + mov dl, byte [bp-016h] ; 8a 56 ea ; 0xc201b + xor dh, dh ; 30 f6 ; 0xc201e + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2020 + call 019ebh ; e8 c5 f9 ; 0xc2023 + jmp short 02047h ; eb 1f ; 0xc2026 vgabios.c:1397 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2028 vgabios.c:1398 + push ax ; 50 ; 0xc202b + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc202c + push ax ; 50 ; 0xc202f + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc2030 + xor ch, ch ; 30 ed ; 0xc2033 + mov bl, byte [bp-016h] ; 8a 5e ea ; 0xc2035 + xor bh, bh ; 30 ff ; 0xc2038 + mov dl, bl ; 88 da ; 0xc203a + add dl, byte [bp-006h] ; 02 56 fa ; 0xc203c + xor dh, dh ; 30 f6 ; 0xc203f + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2041 + call 0195dh ; e8 16 f9 ; 0xc2044 + inc word [bp-016h] ; ff 46 ea ; 0xc2047 vgabios.c:1399 + jmp short 01febh ; eb 9f ; 0xc204a + jmp near 02339h ; e9 ea 02 ; 0xc204c + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc204f vgabios.c:1402 + xor ah, ah ; 30 e4 ; 0xc2052 + mov word [bp-016h], ax ; 89 46 ea ; 0xc2054 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2057 + xor ah, ah ; 30 e4 ; 0xc205a + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc205c + jnbe short 0204ch ; 77 eb ; 0xc205f + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc2061 vgabios.c:1404 + xor dh, dh ; 30 f6 ; 0xc2064 + add ax, dx ; 01 d0 ; 0xc2066 + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc2068 + jnbe short 02071h ; 77 04 ; 0xc206b + test dl, dl ; 84 d2 ; 0xc206d + jne short 02092h ; 75 21 ; 0xc206f + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2071 vgabios.c:1405 + xor ah, ah ; 30 e4 ; 0xc2074 + push ax ; 50 ; 0xc2076 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2077 + push ax ; 50 ; 0xc207a + mov cl, byte [bp-018h] ; 8a 4e e8 ; 0xc207b + xor ch, ch ; 30 ed ; 0xc207e + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc2080 + xor bh, bh ; 30 ff ; 0xc2083 + mov dl, byte [bp-016h] ; 8a 56 ea ; 0xc2085 + xor dh, dh ; 30 f6 ; 0xc2088 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc208a + call 019ebh ; e8 5b f9 ; 0xc208d + jmp short 020bah ; eb 28 ; 0xc2090 vgabios.c:1406 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2092 vgabios.c:1407 + xor ah, ah ; 30 e4 ; 0xc2095 + push ax ; 50 ; 0xc2097 + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc2098 + push ax ; 50 ; 0xc209b + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc209c + xor ch, ch ; 30 ed ; 0xc209f + mov bl, byte [bp-016h] ; 8a 5e ea ; 0xc20a1 + xor bh, bh ; 30 ff ; 0xc20a4 + mov dl, bl ; 88 da ; 0xc20a6 + sub dl, byte [bp-006h] ; 2a 56 fa ; 0xc20a8 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc20ab + mov byte [bp-01ah], al ; 88 46 e6 ; 0xc20ae + mov byte [bp-019h], dh ; 88 76 e7 ; 0xc20b1 + mov ax, word [bp-01ah] ; 8b 46 e6 ; 0xc20b4 + call 0195dh ; e8 a3 f8 ; 0xc20b7 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc20ba vgabios.c:1408 + xor ah, ah ; 30 e4 ; 0xc20bd + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc20bf + jc short 02112h ; 72 4e ; 0xc20c2 + dec word [bp-016h] ; ff 4e ea ; 0xc20c4 vgabios.c:1409 + jmp short 02057h ; eb 8e ; 0xc20c7 + mov cl, byte [bx+047b2h] ; 8a 8f b2 47 ; 0xc20c9 vgabios.c:1414 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc20cd vgabios.c:1415 + jne short 02115h ; 75 42 ; 0xc20d1 + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc20d3 + jne short 02115h ; 75 3c ; 0xc20d7 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc20d9 + jne short 02115h ; 75 36 ; 0xc20dd + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc20df + cmp ax, word [bp-022h] ; 3b 46 de ; 0xc20e2 + jne short 02115h ; 75 2e ; 0xc20e5 + mov al, ch ; 88 e8 ; 0xc20e7 + cmp ax, word [bp-020h] ; 3b 46 e0 ; 0xc20e9 + jne short 02115h ; 75 27 ; 0xc20ec + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc20ee vgabios.c:1417 + xor dh, dh ; 30 f6 ; 0xc20f1 + mov ax, di ; 89 f8 ; 0xc20f3 + mul dx ; f7 e2 ; 0xc20f5 + mov dl, cl ; 88 ca ; 0xc20f7 + xor dh, dh ; 30 f6 ; 0xc20f9 + mul dx ; f7 e2 ; 0xc20fb + mov dl, byte [bp-010h] ; 8a 56 f0 ; 0xc20fd + xor dh, dh ; 30 f6 ; 0xc2100 + mov bx, word [bx+047b3h] ; 8b 9f b3 47 ; 0xc2102 + mov cx, ax ; 89 c1 ; 0xc2106 + mov ax, dx ; 89 d0 ; 0xc2108 + xor di, di ; 31 ff ; 0xc210a + mov es, bx ; 8e c3 ; 0xc210c + jcxz 02112h ; e3 02 ; 0xc210e + rep stosb ; f3 aa ; 0xc2110 + jmp near 02339h ; e9 24 02 ; 0xc2112 vgabios.c:1419 + cmp cl, 002h ; 80 f9 02 ; 0xc2115 vgabios.c:1421 + jne short 02123h ; 75 09 ; 0xc2118 + sal byte [bp-008h], 1 ; d0 66 f8 ; 0xc211a vgabios.c:1423 + sal byte [bp-00ah], 1 ; d0 66 f6 ; 0xc211d vgabios.c:1424 + sal word [bp-018h], 1 ; d1 66 e8 ; 0xc2120 vgabios.c:1425 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc2123 vgabios.c:1428 + jne short 02192h ; 75 69 ; 0xc2127 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2129 vgabios.c:1429 + xor ah, ah ; 30 e4 ; 0xc212c + mov word [bp-016h], ax ; 89 46 ea ; 0xc212e + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc2131 + xor ah, ah ; 30 e4 ; 0xc2134 + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc2136 + jc short 02112h ; 72 d7 ; 0xc2139 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc213b vgabios.c:1431 + xor dh, dh ; 30 f6 ; 0xc213e + add dx, word [bp-016h] ; 03 56 ea ; 0xc2140 + cmp dx, ax ; 39 c2 ; 0xc2143 + jnbe short 0214dh ; 77 06 ; 0xc2145 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc2147 + jne short 0216eh ; 75 21 ; 0xc214b + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc214d vgabios.c:1432 + xor ah, ah ; 30 e4 ; 0xc2150 + push ax ; 50 ; 0xc2152 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2153 + push ax ; 50 ; 0xc2156 + mov cl, byte [bp-018h] ; 8a 4e e8 ; 0xc2157 + xor ch, ch ; 30 ed ; 0xc215a + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc215c + xor bh, bh ; 30 ff ; 0xc215f + mov dl, byte [bp-016h] ; 8a 56 ea ; 0xc2161 + xor dh, dh ; 30 f6 ; 0xc2164 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2166 + call 01b1ch ; e8 b0 f9 ; 0xc2169 + jmp short 0218dh ; eb 1f ; 0xc216c vgabios.c:1433 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc216e vgabios.c:1434 + push ax ; 50 ; 0xc2171 + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc2172 + push ax ; 50 ; 0xc2175 + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc2176 + xor ch, ch ; 30 ed ; 0xc2179 + mov bl, byte [bp-016h] ; 8a 5e ea ; 0xc217b + xor bh, bh ; 30 ff ; 0xc217e + mov dl, bl ; 88 da ; 0xc2180 + add dl, byte [bp-006h] ; 02 56 fa ; 0xc2182 + xor dh, dh ; 30 f6 ; 0xc2185 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2187 + call 01a66h ; e8 d9 f8 ; 0xc218a + inc word [bp-016h] ; ff 46 ea ; 0xc218d vgabios.c:1435 + jmp short 02131h ; eb 9f ; 0xc2190 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc2192 vgabios.c:1438 + xor ah, ah ; 30 e4 ; 0xc2195 + mov word [bp-016h], ax ; 89 46 ea ; 0xc2197 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc219a + xor ah, ah ; 30 e4 ; 0xc219d + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc219f + jnbe short 021e2h ; 77 3e ; 0xc21a2 + mov dl, al ; 88 c2 ; 0xc21a4 vgabios.c:1440 + xor dh, dh ; 30 f6 ; 0xc21a6 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc21a8 + add ax, dx ; 01 d0 ; 0xc21ab + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc21ad + jnbe short 021b8h ; 77 06 ; 0xc21b0 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc21b2 + jne short 021e5h ; 75 2d ; 0xc21b6 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc21b8 vgabios.c:1441 + xor ah, ah ; 30 e4 ; 0xc21bb + push ax ; 50 ; 0xc21bd + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc21be + push ax ; 50 ; 0xc21c1 + mov cl, byte [bp-018h] ; 8a 4e e8 ; 0xc21c2 + xor ch, ch ; 30 ed ; 0xc21c5 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc21c7 + xor bh, bh ; 30 ff ; 0xc21ca + mov dl, byte [bp-016h] ; 8a 56 ea ; 0xc21cc + xor dh, dh ; 30 f6 ; 0xc21cf + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc21d1 + mov byte [bp-014h], al ; 88 46 ec ; 0xc21d4 + mov byte [bp-013h], ah ; 88 66 ed ; 0xc21d7 + mov ax, word [bp-014h] ; 8b 46 ec ; 0xc21da + call 01b1ch ; e8 3c f9 ; 0xc21dd + jmp short 0220dh ; eb 2b ; 0xc21e0 vgabios.c:1442 + jmp near 02339h ; e9 54 01 ; 0xc21e2 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc21e5 vgabios.c:1443 + xor ah, ah ; 30 e4 ; 0xc21e8 + push ax ; 50 ; 0xc21ea + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc21eb + push ax ; 50 ; 0xc21ee + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc21ef + xor ch, ch ; 30 ed ; 0xc21f2 + mov bl, byte [bp-016h] ; 8a 5e ea ; 0xc21f4 + xor bh, bh ; 30 ff ; 0xc21f7 + mov dl, bl ; 88 da ; 0xc21f9 + sub dl, byte [bp-006h] ; 2a 56 fa ; 0xc21fb + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc21fe + mov byte [bp-014h], al ; 88 46 ec ; 0xc2201 + mov byte [bp-013h], dh ; 88 76 ed ; 0xc2204 + mov ax, word [bp-014h] ; 8b 46 ec ; 0xc2207 + call 01a66h ; e8 59 f8 ; 0xc220a + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc220d vgabios.c:1444 + xor ah, ah ; 30 e4 ; 0xc2210 + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc2212 + jc short 0225ch ; 72 45 ; 0xc2215 + dec word [bp-016h] ; ff 4e ea ; 0xc2217 vgabios.c:1445 + jmp near 0219ah ; e9 7d ff ; 0xc221a + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc221d vgabios.c:1450 + jne short 0225fh ; 75 3c ; 0xc2221 + cmp byte [bp-00ch], 000h ; 80 7e f4 00 ; 0xc2223 + jne short 0225fh ; 75 36 ; 0xc2227 + cmp byte [bp-008h], 000h ; 80 7e f8 00 ; 0xc2229 + jne short 0225fh ; 75 30 ; 0xc222d + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc222f + cmp ax, word [bp-022h] ; 3b 46 de ; 0xc2232 + jne short 0225fh ; 75 28 ; 0xc2235 + mov al, ch ; 88 e8 ; 0xc2237 + cmp ax, word [bp-020h] ; 3b 46 e0 ; 0xc2239 + jne short 0225fh ; 75 21 ; 0xc223c + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc223e vgabios.c:1452 + xor dh, dh ; 30 f6 ; 0xc2241 + mov ax, di ; 89 f8 ; 0xc2243 + mul dx ; f7 e2 ; 0xc2245 + mov CL, strict byte 003h ; b1 03 ; 0xc2247 + sal ax, CL ; d3 e0 ; 0xc2249 + mov cx, ax ; 89 c1 ; 0xc224b + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc224d + xor ah, ah ; 30 e4 ; 0xc2250 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2252 + xor di, di ; 31 ff ; 0xc2256 + jcxz 0225ch ; e3 02 ; 0xc2258 + rep stosb ; f3 aa ; 0xc225a + jmp near 02339h ; e9 da 00 ; 0xc225c vgabios.c:1454 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc225f vgabios.c:1457 + jne short 022cbh ; 75 66 ; 0xc2263 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2265 vgabios.c:1458 + xor ah, ah ; 30 e4 ; 0xc2268 + mov word [bp-016h], ax ; 89 46 ea ; 0xc226a + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc226d + xor ah, ah ; 30 e4 ; 0xc2270 + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc2272 + jc short 0225ch ; 72 e5 ; 0xc2275 + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc2277 vgabios.c:1460 + xor dh, dh ; 30 f6 ; 0xc227a + add dx, word [bp-016h] ; 03 56 ea ; 0xc227c + cmp dx, ax ; 39 c2 ; 0xc227f + jnbe short 02289h ; 77 06 ; 0xc2281 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc2283 + jne short 022a8h ; 75 1f ; 0xc2287 + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc2289 vgabios.c:1461 + xor ah, ah ; 30 e4 ; 0xc228c + push ax ; 50 ; 0xc228e + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc228f + push ax ; 50 ; 0xc2292 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc2293 + xor bh, bh ; 30 ff ; 0xc2296 + mov dl, byte [bp-016h] ; 8a 56 ea ; 0xc2298 + xor dh, dh ; 30 f6 ; 0xc229b + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc229d + mov cx, word [bp-018h] ; 8b 4e e8 ; 0xc22a0 + call 01c33h ; e8 8d f9 ; 0xc22a3 + jmp short 022c6h ; eb 1e ; 0xc22a6 vgabios.c:1462 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc22a8 vgabios.c:1463 + push ax ; 50 ; 0xc22ab + push word [bp-018h] ; ff 76 e8 ; 0xc22ac + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc22af + xor ch, ch ; 30 ed ; 0xc22b2 + mov bl, byte [bp-016h] ; 8a 5e ea ; 0xc22b4 + xor bh, bh ; 30 ff ; 0xc22b7 + mov dl, bl ; 88 da ; 0xc22b9 + add dl, byte [bp-006h] ; 02 56 fa ; 0xc22bb + xor dh, dh ; 30 f6 ; 0xc22be + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc22c0 + call 01bb0h ; e8 ea f8 ; 0xc22c3 + inc word [bp-016h] ; ff 46 ea ; 0xc22c6 vgabios.c:1464 + jmp short 0226dh ; eb a2 ; 0xc22c9 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc22cb vgabios.c:1467 + xor ah, ah ; 30 e4 ; 0xc22ce + mov word [bp-016h], ax ; 89 46 ea ; 0xc22d0 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc22d3 + xor ah, ah ; 30 e4 ; 0xc22d6 + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc22d8 + jnbe short 02339h ; 77 5c ; 0xc22db + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc22dd vgabios.c:1469 + xor dh, dh ; 30 f6 ; 0xc22e0 + add ax, dx ; 01 d0 ; 0xc22e2 + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc22e4 + jnbe short 022edh ; 77 04 ; 0xc22e7 + test dl, dl ; 84 d2 ; 0xc22e9 + jne short 0230ch ; 75 1f ; 0xc22eb + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc22ed vgabios.c:1470 + xor ah, ah ; 30 e4 ; 0xc22f0 + push ax ; 50 ; 0xc22f2 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc22f3 + push ax ; 50 ; 0xc22f6 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc22f7 + xor bh, bh ; 30 ff ; 0xc22fa + mov dl, byte [bp-016h] ; 8a 56 ea ; 0xc22fc + xor dh, dh ; 30 f6 ; 0xc22ff + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2301 + mov cx, word [bp-018h] ; 8b 4e e8 ; 0xc2304 + call 01c33h ; e8 29 f9 ; 0xc2307 + jmp short 0232ah ; eb 1e ; 0xc230a vgabios.c:1471 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc230c vgabios.c:1472 + xor ah, ah ; 30 e4 ; 0xc230f + push ax ; 50 ; 0xc2311 + push word [bp-018h] ; ff 76 e8 ; 0xc2312 + mov cl, byte [bp-00ah] ; 8a 4e f6 ; 0xc2315 + xor ch, ch ; 30 ed ; 0xc2318 + mov bl, byte [bp-016h] ; 8a 5e ea ; 0xc231a + xor bh, bh ; 30 ff ; 0xc231d + mov dl, bl ; 88 da ; 0xc231f + sub dl, byte [bp-006h] ; 2a 56 fa ; 0xc2321 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2324 + call 01bb0h ; e8 86 f8 ; 0xc2327 + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc232a vgabios.c:1473 + xor ah, ah ; 30 e4 ; 0xc232d + cmp ax, word [bp-016h] ; 3b 46 ea ; 0xc232f + jc short 02339h ; 72 05 ; 0xc2332 + dec word [bp-016h] ; ff 4e ea ; 0xc2334 vgabios.c:1474 + jmp short 022d3h ; eb 9a ; 0xc2337 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2339 vgabios.c:1485 + pop di ; 5f ; 0xc233c + pop si ; 5e ; 0xc233d + pop bp ; 5d ; 0xc233e + retn 00008h ; c2 08 00 ; 0xc233f + ; disGetNextSymbol 0xc2342 LB 0x2222 -> off=0x0 cb=0000000000000112 uValue=00000000000c2342 'write_gfx_char_pl4' +write_gfx_char_pl4: ; 0xc2342 LB 0x112 + push bp ; 55 ; 0xc2342 vgabios.c:1488 + mov bp, sp ; 89 e5 ; 0xc2343 + push si ; 56 ; 0xc2345 + push di ; 57 ; 0xc2346 + sub sp, strict byte 00010h ; 83 ec 10 ; 0xc2347 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc234a + mov byte [bp-00ah], dl ; 88 56 f6 ; 0xc234d + mov byte [bp-006h], bl ; 88 5e fa ; 0xc2350 + mov al, cl ; 88 c8 ; 0xc2353 + mov bx, 0010ch ; bb 0c 01 ; 0xc2355 vgabios.c:67 + xor cx, cx ; 31 c9 ; 0xc2358 + mov es, cx ; 8e c1 ; 0xc235a + mov cx, word [es:bx] ; 26 8b 0f ; 0xc235c + mov bx, word [es:bx+002h] ; 26 8b 5f 02 ; 0xc235f + mov word [bp-014h], cx ; 89 4e ec ; 0xc2363 vgabios.c:68 + mov word [bp-010h], bx ; 89 5e f0 ; 0xc2366 + xor ah, ah ; 30 e4 ; 0xc2369 vgabios.c:1497 + mov cl, byte [bp+006h] ; 8a 4e 06 ; 0xc236b + xor ch, ch ; 30 ed ; 0xc236e + imul cx ; f7 e9 ; 0xc2370 + mov bl, byte [bp+004h] ; 8a 5e 04 ; 0xc2372 + xor bh, bh ; 30 ff ; 0xc2375 + imul bx ; f7 eb ; 0xc2377 + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc2379 + mov si, bx ; 89 de ; 0xc237c + add si, ax ; 01 c6 ; 0xc237e + mov bx, strict word 0004ch ; bb 4c 00 ; 0xc2380 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2383 + mov es, ax ; 8e c0 ; 0xc2386 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc2388 + mov bl, byte [bp+008h] ; 8a 5e 08 ; 0xc238b vgabios.c:58 + xor bh, bh ; 30 ff ; 0xc238e + mul bx ; f7 e3 ; 0xc2390 + add si, ax ; 01 c6 ; 0xc2392 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2394 vgabios.c:1499 + xor ah, ah ; 30 e4 ; 0xc2397 + imul cx ; f7 e9 ; 0xc2399 + mov word [bp-012h], ax ; 89 46 ee ; 0xc239b + mov ax, 00f02h ; b8 02 0f ; 0xc239e vgabios.c:1500 + mov dx, 003c4h ; ba c4 03 ; 0xc23a1 + out DX, ax ; ef ; 0xc23a4 + mov ax, 00205h ; b8 05 02 ; 0xc23a5 vgabios.c:1501 + mov dx, 003ceh ; ba ce 03 ; 0xc23a8 + out DX, ax ; ef ; 0xc23ab + test byte [bp-00ah], 080h ; f6 46 f6 80 ; 0xc23ac vgabios.c:1502 + je short 023b8h ; 74 06 ; 0xc23b0 + mov ax, 01803h ; b8 03 18 ; 0xc23b2 vgabios.c:1504 + out DX, ax ; ef ; 0xc23b5 + jmp short 023bch ; eb 04 ; 0xc23b6 vgabios.c:1506 + mov ax, strict word 00003h ; b8 03 00 ; 0xc23b8 vgabios.c:1508 + out DX, ax ; ef ; 0xc23bb + xor ch, ch ; 30 ed ; 0xc23bc vgabios.c:1510 + cmp ch, byte [bp+006h] ; 3a 6e 06 ; 0xc23be + jnc short 023d8h ; 73 15 ; 0xc23c1 + mov al, ch ; 88 e8 ; 0xc23c3 vgabios.c:1512 + xor ah, ah ; 30 e4 ; 0xc23c5 + mov bl, byte [bp+004h] ; 8a 5e 04 ; 0xc23c7 + xor bh, bh ; 30 ff ; 0xc23ca + imul bx ; f7 eb ; 0xc23cc + mov bx, si ; 89 f3 ; 0xc23ce + add bx, ax ; 01 c3 ; 0xc23d0 + mov byte [bp-008h], 000h ; c6 46 f8 00 ; 0xc23d2 vgabios.c:1513 + jmp short 023ech ; eb 14 ; 0xc23d6 + jmp short 0243ch ; eb 62 ; 0xc23d8 vgabios.c:1522 + mov ax, 0a000h ; b8 00 a0 ; 0xc23da vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc23dd + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc23df + inc byte [bp-008h] ; fe 46 f8 ; 0xc23e3 vgabios.c:1526 + cmp byte [bp-008h], 008h ; 80 7e f8 08 ; 0xc23e6 + jnc short 02438h ; 73 4c ; 0xc23ea + mov cl, byte [bp-008h] ; 8a 4e f8 ; 0xc23ec + mov ax, 00080h ; b8 80 00 ; 0xc23ef + sar ax, CL ; d3 f8 ; 0xc23f2 + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc23f4 + mov byte [bp-00dh], 000h ; c6 46 f3 00 ; 0xc23f7 + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc23fb + mov ah, al ; 88 c4 ; 0xc23fe + xor al, al ; 30 c0 ; 0xc2400 + or AL, strict byte 008h ; 0c 08 ; 0xc2402 + mov dx, 003ceh ; ba ce 03 ; 0xc2404 + out DX, ax ; ef ; 0xc2407 + mov dx, bx ; 89 da ; 0xc2408 + mov ax, 0a000h ; b8 00 a0 ; 0xc240a + call 038b3h ; e8 a3 14 ; 0xc240d + mov al, ch ; 88 e8 ; 0xc2410 + xor ah, ah ; 30 e4 ; 0xc2412 + add ax, word [bp-012h] ; 03 46 ee ; 0xc2414 + mov es, [bp-010h] ; 8e 46 f0 ; 0xc2417 + mov di, word [bp-014h] ; 8b 7e ec ; 0xc241a + add di, ax ; 01 c7 ; 0xc241d + mov al, byte [es:di] ; 26 8a 05 ; 0xc241f + xor ah, ah ; 30 e4 ; 0xc2422 + test word [bp-00eh], ax ; 85 46 f2 ; 0xc2424 + je short 023dah ; 74 b1 ; 0xc2427 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2429 + and AL, strict byte 00fh ; 24 0f ; 0xc242c + mov di, 0a000h ; bf 00 a0 ; 0xc242e + mov es, di ; 8e c7 ; 0xc2431 + mov byte [es:bx], al ; 26 88 07 ; 0xc2433 + jmp short 023e3h ; eb ab ; 0xc2436 + db 0feh, 0c5h + ; inc ch ; fe c5 ; 0xc2438 vgabios.c:1527 + jmp short 023beh ; eb 82 ; 0xc243a + mov ax, 0ff08h ; b8 08 ff ; 0xc243c vgabios.c:1528 + mov dx, 003ceh ; ba ce 03 ; 0xc243f + out DX, ax ; ef ; 0xc2442 + mov ax, strict word 00005h ; b8 05 00 ; 0xc2443 vgabios.c:1529 + out DX, ax ; ef ; 0xc2446 + mov ax, strict word 00003h ; b8 03 00 ; 0xc2447 vgabios.c:1530 + out DX, ax ; ef ; 0xc244a + lea sp, [bp-004h] ; 8d 66 fc ; 0xc244b vgabios.c:1531 + pop di ; 5f ; 0xc244e + pop si ; 5e ; 0xc244f + pop bp ; 5d ; 0xc2450 + retn 00006h ; c2 06 00 ; 0xc2451 + ; disGetNextSymbol 0xc2454 LB 0x2110 -> off=0x0 cb=0000000000000112 uValue=00000000000c2454 'write_gfx_char_cga' +write_gfx_char_cga: ; 0xc2454 LB 0x112 + push si ; 56 ; 0xc2454 vgabios.c:1534 + push di ; 57 ; 0xc2455 + push bp ; 55 ; 0xc2456 + mov bp, sp ; 89 e5 ; 0xc2457 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc2459 + mov ch, al ; 88 c5 ; 0xc245c + mov byte [bp-002h], dl ; 88 56 fe ; 0xc245e + mov al, bl ; 88 d8 ; 0xc2461 + mov si, 0556dh ; be 6d 55 ; 0xc2463 vgabios.c:1541 + xor ah, ah ; 30 e4 ; 0xc2466 vgabios.c:1542 + mov bl, byte [bp+00ah] ; 8a 5e 0a ; 0xc2468 + xor bh, bh ; 30 ff ; 0xc246b + imul bx ; f7 eb ; 0xc246d + mov bx, ax ; 89 c3 ; 0xc246f + mov al, cl ; 88 c8 ; 0xc2471 + xor ah, ah ; 30 e4 ; 0xc2473 + mov di, 00140h ; bf 40 01 ; 0xc2475 + imul di ; f7 ef ; 0xc2478 + add bx, ax ; 01 c3 ; 0xc247a + mov word [bp-004h], bx ; 89 5e fc ; 0xc247c + mov al, ch ; 88 e8 ; 0xc247f vgabios.c:1543 + xor ah, ah ; 30 e4 ; 0xc2481 + mov CL, strict byte 003h ; b1 03 ; 0xc2483 + sal ax, CL ; d3 e0 ; 0xc2485 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc2487 + xor ch, ch ; 30 ed ; 0xc248a vgabios.c:1544 + jmp near 024abh ; e9 1c 00 ; 0xc248c + mov al, ch ; 88 e8 ; 0xc248f vgabios.c:1559 + xor ah, ah ; 30 e4 ; 0xc2491 + add ax, word [bp-008h] ; 03 46 f8 ; 0xc2493 + mov di, si ; 89 f7 ; 0xc2496 + add di, ax ; 01 c7 ; 0xc2498 + mov al, byte [di] ; 8a 05 ; 0xc249a + mov di, 0b800h ; bf 00 b8 ; 0xc249c vgabios.c:52 + mov es, di ; 8e c7 ; 0xc249f + mov byte [es:bx], al ; 26 88 07 ; 0xc24a1 + db 0feh, 0c5h + ; inc ch ; fe c5 ; 0xc24a4 vgabios.c:1563 + cmp ch, 008h ; 80 fd 08 ; 0xc24a6 + jnc short 02503h ; 73 58 ; 0xc24a9 + mov al, ch ; 88 e8 ; 0xc24ab + xor ah, ah ; 30 e4 ; 0xc24ad + sar ax, 1 ; d1 f8 ; 0xc24af + mov bx, strict word 00050h ; bb 50 00 ; 0xc24b1 + imul bx ; f7 eb ; 0xc24b4 + mov bx, word [bp-004h] ; 8b 5e fc ; 0xc24b6 + add bx, ax ; 01 c3 ; 0xc24b9 + test ch, 001h ; f6 c5 01 ; 0xc24bb + je short 024c3h ; 74 03 ; 0xc24be + add bh, 020h ; 80 c7 20 ; 0xc24c0 + mov DL, strict byte 080h ; b2 80 ; 0xc24c3 + cmp byte [bp+00ah], 001h ; 80 7e 0a 01 ; 0xc24c5 + jne short 024e9h ; 75 1e ; 0xc24c9 + test byte [bp-002h], dl ; 84 56 fe ; 0xc24cb + je short 0248fh ; 74 bf ; 0xc24ce + mov ax, 0b800h ; b8 00 b8 ; 0xc24d0 + mov es, ax ; 8e c0 ; 0xc24d3 + mov dl, byte [es:bx] ; 26 8a 17 ; 0xc24d5 + mov al, ch ; 88 e8 ; 0xc24d8 + xor ah, ah ; 30 e4 ; 0xc24da + add ax, word [bp-008h] ; 03 46 f8 ; 0xc24dc + mov di, si ; 89 f7 ; 0xc24df + add di, ax ; 01 c7 ; 0xc24e1 + mov al, byte [di] ; 8a 05 ; 0xc24e3 + xor al, dl ; 30 d0 ; 0xc24e5 + jmp short 0249ch ; eb b3 ; 0xc24e7 + test dl, dl ; 84 d2 ; 0xc24e9 vgabios.c:1565 + jbe short 024a4h ; 76 b7 ; 0xc24eb + test byte [bp-002h], 080h ; f6 46 fe 80 ; 0xc24ed vgabios.c:1567 + je short 024fdh ; 74 0a ; 0xc24f1 + mov ax, 0b800h ; b8 00 b8 ; 0xc24f3 vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc24f6 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc24f8 + jmp short 024ffh ; eb 02 ; 0xc24fb vgabios.c:1571 + xor al, al ; 30 c0 ; 0xc24fd vgabios.c:1573 + xor ah, ah ; 30 e4 ; 0xc24ff vgabios.c:1575 + jmp short 0250ah ; eb 07 ; 0xc2501 + jmp short 0255eh ; eb 59 ; 0xc2503 + cmp ah, 004h ; 80 fc 04 ; 0xc2505 + jnc short 02553h ; 73 49 ; 0xc2508 + mov byte [bp-006h], ch ; 88 6e fa ; 0xc250a vgabios.c:1577 + mov byte [bp-005h], 000h ; c6 46 fb 00 ; 0xc250d + mov di, word [bp-008h] ; 8b 7e f8 ; 0xc2511 + add di, word [bp-006h] ; 03 7e fa ; 0xc2514 + add di, si ; 01 f7 ; 0xc2517 + mov cl, byte [di] ; 8a 0d ; 0xc2519 + mov byte [bp-00ah], cl ; 88 4e f6 ; 0xc251b + mov byte [bp-009h], 000h ; c6 46 f7 00 ; 0xc251e + mov byte [bp-006h], dl ; 88 56 fa ; 0xc2522 + mov byte [bp-005h], 000h ; c6 46 fb 00 ; 0xc2525 + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc2529 + test word [bp-006h], di ; 85 7e fa ; 0xc252c + je short 0254dh ; 74 1c ; 0xc252f + mov CL, strict byte 003h ; b1 03 ; 0xc2531 vgabios.c:1578 + sub cl, ah ; 28 e1 ; 0xc2533 + mov dh, byte [bp-002h] ; 8a 76 fe ; 0xc2535 + and dh, 003h ; 80 e6 03 ; 0xc2538 + sal cl, 1 ; d0 e1 ; 0xc253b + sal dh, CL ; d2 e6 ; 0xc253d + mov cl, dh ; 88 f1 ; 0xc253f + test byte [bp-002h], 080h ; f6 46 fe 80 ; 0xc2541 vgabios.c:1579 + je short 0254bh ; 74 04 ; 0xc2545 + xor al, dh ; 30 f0 ; 0xc2547 vgabios.c:1581 + jmp short 0254dh ; eb 02 ; 0xc2549 vgabios.c:1583 + or al, dh ; 08 f0 ; 0xc254b vgabios.c:1585 + shr dl, 1 ; d0 ea ; 0xc254d vgabios.c:1588 + db 0feh, 0c4h + ; inc ah ; fe c4 ; 0xc254f vgabios.c:1589 + jmp short 02505h ; eb b2 ; 0xc2551 + mov di, 0b800h ; bf 00 b8 ; 0xc2553 vgabios.c:52 + mov es, di ; 8e c7 ; 0xc2556 + mov byte [es:bx], al ; 26 88 07 ; 0xc2558 + inc bx ; 43 ; 0xc255b vgabios.c:1591 + jmp short 024e9h ; eb 8b ; 0xc255c vgabios.c:1592 + mov sp, bp ; 89 ec ; 0xc255e vgabios.c:1595 + pop bp ; 5d ; 0xc2560 + pop di ; 5f ; 0xc2561 + pop si ; 5e ; 0xc2562 + retn 00004h ; c2 04 00 ; 0xc2563 + ; disGetNextSymbol 0xc2566 LB 0x1ffe -> off=0x0 cb=00000000000000a1 uValue=00000000000c2566 'write_gfx_char_lin' +write_gfx_char_lin: ; 0xc2566 LB 0xa1 + push si ; 56 ; 0xc2566 vgabios.c:1598 + push di ; 57 ; 0xc2567 + push bp ; 55 ; 0xc2568 + mov bp, sp ; 89 e5 ; 0xc2569 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc256b + mov bh, al ; 88 c7 ; 0xc256e + mov ch, dl ; 88 d5 ; 0xc2570 + mov al, cl ; 88 c8 ; 0xc2572 + mov di, 0556dh ; bf 6d 55 ; 0xc2574 vgabios.c:1605 + xor ah, ah ; 30 e4 ; 0xc2577 vgabios.c:1606 + mov dl, byte [bp+008h] ; 8a 56 08 ; 0xc2579 + xor dh, dh ; 30 f6 ; 0xc257c + imul dx ; f7 ea ; 0xc257e + mov CL, strict byte 006h ; b1 06 ; 0xc2580 + mov dx, ax ; 89 c2 ; 0xc2582 + sal dx, CL ; d3 e2 ; 0xc2584 + mov al, bl ; 88 d8 ; 0xc2586 + xor ah, ah ; 30 e4 ; 0xc2588 + mov CL, strict byte 003h ; b1 03 ; 0xc258a + sal ax, CL ; d3 e0 ; 0xc258c + add ax, dx ; 01 d0 ; 0xc258e + mov word [bp-002h], ax ; 89 46 fe ; 0xc2590 + mov al, bh ; 88 f8 ; 0xc2593 vgabios.c:1607 + xor ah, ah ; 30 e4 ; 0xc2595 + sal ax, CL ; d3 e0 ; 0xc2597 + mov word [bp-006h], ax ; 89 46 fa ; 0xc2599 + xor bl, bl ; 30 db ; 0xc259c vgabios.c:1608 + jmp short 025e2h ; eb 42 ; 0xc259e + cmp AL, strict byte 008h ; 3c 08 ; 0xc25a0 vgabios.c:1612 + jnc short 025dbh ; 73 37 ; 0xc25a2 + xor bh, bh ; 30 ff ; 0xc25a4 vgabios.c:1614 + mov dl, bl ; 88 da ; 0xc25a6 vgabios.c:1615 + xor dh, dh ; 30 f6 ; 0xc25a8 + add dx, word [bp-006h] ; 03 56 fa ; 0xc25aa + mov si, di ; 89 fe ; 0xc25ad + add si, dx ; 01 d6 ; 0xc25af + mov dl, byte [si] ; 8a 14 ; 0xc25b1 + mov byte [bp-004h], dl ; 88 56 fc ; 0xc25b3 + mov byte [bp-003h], bh ; 88 7e fd ; 0xc25b6 + mov dl, ah ; 88 e2 ; 0xc25b9 + xor dh, dh ; 30 f6 ; 0xc25bb + test word [bp-004h], dx ; 85 56 fc ; 0xc25bd + je short 025c4h ; 74 02 ; 0xc25c0 + mov bh, ch ; 88 ef ; 0xc25c2 vgabios.c:1617 + mov dl, al ; 88 c2 ; 0xc25c4 vgabios.c:1619 + xor dh, dh ; 30 f6 ; 0xc25c6 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc25c8 + add si, dx ; 01 d6 ; 0xc25cb + mov dx, 0a000h ; ba 00 a0 ; 0xc25cd vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc25d0 + mov byte [es:si], bh ; 26 88 3c ; 0xc25d2 + shr ah, 1 ; d0 ec ; 0xc25d5 vgabios.c:1620 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc25d7 vgabios.c:1621 + jmp short 025a0h ; eb c5 ; 0xc25d9 + db 0feh, 0c3h + ; inc bl ; fe c3 ; 0xc25db vgabios.c:1622 + cmp bl, 008h ; 80 fb 08 ; 0xc25dd + jnc short 025ffh ; 73 1d ; 0xc25e0 + mov al, bl ; 88 d8 ; 0xc25e2 + xor ah, ah ; 30 e4 ; 0xc25e4 + mov dl, byte [bp+008h] ; 8a 56 08 ; 0xc25e6 + xor dh, dh ; 30 f6 ; 0xc25e9 + imul dx ; f7 ea ; 0xc25eb + mov CL, strict byte 003h ; b1 03 ; 0xc25ed + sal ax, CL ; d3 e0 ; 0xc25ef + mov dx, word [bp-002h] ; 8b 56 fe ; 0xc25f1 + add dx, ax ; 01 c2 ; 0xc25f4 + mov word [bp-008h], dx ; 89 56 f8 ; 0xc25f6 + mov AH, strict byte 080h ; b4 80 ; 0xc25f9 + xor al, al ; 30 c0 ; 0xc25fb + jmp short 025a4h ; eb a5 ; 0xc25fd + mov sp, bp ; 89 ec ; 0xc25ff vgabios.c:1623 + pop bp ; 5d ; 0xc2601 + pop di ; 5f ; 0xc2602 + pop si ; 5e ; 0xc2603 + retn 00002h ; c2 02 00 ; 0xc2604 + ; disGetNextSymbol 0xc2607 LB 0x1f5d -> off=0x0 cb=0000000000000172 uValue=00000000000c2607 'biosfn_write_char_attr' +biosfn_write_char_attr: ; 0xc2607 LB 0x172 + push bp ; 55 ; 0xc2607 vgabios.c:1626 + mov bp, sp ; 89 e5 ; 0xc2608 + push si ; 56 ; 0xc260a + push di ; 57 ; 0xc260b + sub sp, strict byte 0001ah ; 83 ec 1a ; 0xc260c + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc260f + mov byte [bp-00eh], dl ; 88 56 f2 ; 0xc2612 + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc2615 + mov si, cx ; 89 ce ; 0xc2618 + mov bx, strict word 00049h ; bb 49 00 ; 0xc261a vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc261d + mov es, ax ; 8e c0 ; 0xc2620 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2622 + xor ah, ah ; 30 e4 ; 0xc2625 vgabios.c:1634 + call 03888h ; e8 5e 12 ; 0xc2627 + mov cl, al ; 88 c1 ; 0xc262a + mov byte [bp-014h], al ; 88 46 ec ; 0xc262c + cmp AL, strict byte 0ffh ; 3c ff ; 0xc262f vgabios.c:1635 + jne short 02636h ; 75 03 ; 0xc2631 + jmp near 02772h ; e9 3c 01 ; 0xc2633 + mov al, dl ; 88 d0 ; 0xc2636 vgabios.c:1638 + xor ah, ah ; 30 e4 ; 0xc2638 + lea bx, [bp-01ch] ; 8d 5e e4 ; 0xc263a + lea dx, [bp-01eh] ; 8d 56 e2 ; 0xc263d + call 00a97h ; e8 54 e4 ; 0xc2640 + mov al, byte [bp-01ch] ; 8a 46 e4 ; 0xc2643 vgabios.c:1639 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc2646 + mov ax, word [bp-01ch] ; 8b 46 e4 ; 0xc2649 + mov al, ah ; 88 e0 ; 0xc264c + xor ah, ah ; 30 e4 ; 0xc264e + mov word [bp-018h], ax ; 89 46 e8 ; 0xc2650 + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc2653 + mov byte [bp-006h], al ; 88 46 fa ; 0xc2656 + mov bx, 00084h ; bb 84 00 ; 0xc2659 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc265c + mov es, ax ; 8e c0 ; 0xc265f + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2661 + xor ah, ah ; 30 e4 ; 0xc2664 vgabios.c:48 + mov dx, ax ; 89 c2 ; 0xc2666 + inc dx ; 42 ; 0xc2668 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2669 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc266c + mov word [bp-016h], ax ; 89 46 ea ; 0xc266f + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc2672 vgabios.c:58 + mov bl, cl ; 88 cb ; 0xc2675 vgabios.c:1645 + xor bh, bh ; 30 ff ; 0xc2677 + mov CL, strict byte 003h ; b1 03 ; 0xc2679 + mov di, bx ; 89 df ; 0xc267b + sal di, CL ; d3 e7 ; 0xc267d + cmp byte [di+047b0h], 000h ; 80 bd b0 47 00 ; 0xc267f + jne short 026c6h ; 75 40 ; 0xc2684 + mul dx ; f7 e2 ; 0xc2686 vgabios.c:1648 + sal ax, 1 ; d1 e0 ; 0xc2688 + or AL, strict byte 0ffh ; 0c ff ; 0xc268a + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc268c + xor dh, dh ; 30 f6 ; 0xc268f + inc ax ; 40 ; 0xc2691 + mul dx ; f7 e2 ; 0xc2692 + mov bx, ax ; 89 c3 ; 0xc2694 + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc2696 + xor ah, ah ; 30 e4 ; 0xc2699 + mul word [bp-016h] ; f7 66 ea ; 0xc269b + mov dx, ax ; 89 c2 ; 0xc269e + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc26a0 + xor ah, ah ; 30 e4 ; 0xc26a3 + add ax, dx ; 01 d0 ; 0xc26a5 + sal ax, 1 ; d1 e0 ; 0xc26a7 + add bx, ax ; 01 c3 ; 0xc26a9 + mov ah, byte [bp-008h] ; 8a 66 f8 ; 0xc26ab vgabios.c:1650 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc26ae + mov word [bp-01eh], ax ; 89 46 e2 ; 0xc26b1 + mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xc26b4 vgabios.c:1651 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc26b7 + mov cx, si ; 89 f1 ; 0xc26bb + mov di, bx ; 89 df ; 0xc26bd + jcxz 026c3h ; e3 02 ; 0xc26bf + rep stosw ; f3 ab ; 0xc26c1 + jmp near 02772h ; e9 ac 00 ; 0xc26c3 vgabios.c:1653 + mov bl, byte [bx+0482fh] ; 8a 9f 2f 48 ; 0xc26c6 vgabios.c:1656 + mov CL, strict byte 006h ; b1 06 ; 0xc26ca + sal bx, CL ; d3 e3 ; 0xc26cc + mov al, byte [bx+04845h] ; 8a 87 45 48 ; 0xc26ce + mov byte [bp-010h], al ; 88 46 f0 ; 0xc26d2 + mov al, byte [di+047b2h] ; 8a 85 b2 47 ; 0xc26d5 vgabios.c:1657 + mov byte [bp-012h], al ; 88 46 ee ; 0xc26d9 + dec si ; 4e ; 0xc26dc vgabios.c:1658 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc26dd + je short 0272eh ; 74 4c ; 0xc26e0 + mov bl, byte [bp-014h] ; 8a 5e ec ; 0xc26e2 vgabios.c:1660 + xor bh, bh ; 30 ff ; 0xc26e5 + mov CL, strict byte 003h ; b1 03 ; 0xc26e7 + sal bx, CL ; d3 e3 ; 0xc26e9 + mov al, byte [bx+047b1h] ; 8a 87 b1 47 ; 0xc26eb + cmp al, cl ; 38 c8 ; 0xc26ef + jc short 026ffh ; 72 0c ; 0xc26f1 + jbe short 02705h ; 76 10 ; 0xc26f3 + cmp AL, strict byte 005h ; 3c 05 ; 0xc26f5 + je short 02751h ; 74 58 ; 0xc26f7 + cmp AL, strict byte 004h ; 3c 04 ; 0xc26f9 + je short 02709h ; 74 0c ; 0xc26fb + jmp short 0276ch ; eb 6d ; 0xc26fd + cmp AL, strict byte 002h ; 3c 02 ; 0xc26ff + je short 02730h ; 74 2d ; 0xc2701 + jmp short 0276ch ; eb 67 ; 0xc2703 + or byte [bp-008h], 001h ; 80 4e f8 01 ; 0xc2705 vgabios.c:1663 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2709 vgabios.c:1665 + xor ah, ah ; 30 e4 ; 0xc270c + push ax ; 50 ; 0xc270e + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc270f + push ax ; 50 ; 0xc2712 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc2713 + push ax ; 50 ; 0xc2716 + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc2717 + xor ch, ch ; 30 ed ; 0xc271a + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc271c + xor bh, bh ; 30 ff ; 0xc271f + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc2721 + xor dh, dh ; 30 f6 ; 0xc2724 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2726 + call 02342h ; e8 16 fc ; 0xc2729 + jmp short 0276ch ; eb 3e ; 0xc272c vgabios.c:1666 + jmp short 02772h ; eb 42 ; 0xc272e + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc2730 vgabios.c:1668 + xor ah, ah ; 30 e4 ; 0xc2733 + push ax ; 50 ; 0xc2735 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc2736 + push ax ; 50 ; 0xc2739 + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc273a + xor ch, ch ; 30 ed ; 0xc273d + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc273f + xor bh, bh ; 30 ff ; 0xc2742 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc2744 + xor dh, dh ; 30 f6 ; 0xc2747 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2749 + call 02454h ; e8 05 fd ; 0xc274c + jmp short 0276ch ; eb 1b ; 0xc274f vgabios.c:1669 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc2751 vgabios.c:1671 + xor ah, ah ; 30 e4 ; 0xc2754 + push ax ; 50 ; 0xc2756 + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc2757 + xor ch, ch ; 30 ed ; 0xc275a + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc275c + xor bh, bh ; 30 ff ; 0xc275f + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc2761 + xor dh, dh ; 30 f6 ; 0xc2764 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2766 + call 02566h ; e8 fa fd ; 0xc2769 + inc byte [bp-00ah] ; fe 46 f6 ; 0xc276c vgabios.c:1678 + jmp near 026dch ; e9 6a ff ; 0xc276f vgabios.c:1679 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2772 vgabios.c:1681 + pop di ; 5f ; 0xc2775 + pop si ; 5e ; 0xc2776 + pop bp ; 5d ; 0xc2777 + retn ; c3 ; 0xc2778 + ; disGetNextSymbol 0xc2779 LB 0x1deb -> off=0x0 cb=0000000000000183 uValue=00000000000c2779 'biosfn_write_char_only' +biosfn_write_char_only: ; 0xc2779 LB 0x183 + push bp ; 55 ; 0xc2779 vgabios.c:1684 + mov bp, sp ; 89 e5 ; 0xc277a + push si ; 56 ; 0xc277c + push di ; 57 ; 0xc277d + sub sp, strict byte 0001ah ; 83 ec 1a ; 0xc277e + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc2781 + mov byte [bp-00eh], dl ; 88 56 f2 ; 0xc2784 + mov byte [bp-008h], bl ; 88 5e f8 ; 0xc2787 + mov si, cx ; 89 ce ; 0xc278a + mov bx, strict word 00049h ; bb 49 00 ; 0xc278c vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc278f + mov es, ax ; 8e c0 ; 0xc2792 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2794 + xor ah, ah ; 30 e4 ; 0xc2797 vgabios.c:1692 + call 03888h ; e8 ec 10 ; 0xc2799 + mov cl, al ; 88 c1 ; 0xc279c + mov byte [bp-010h], al ; 88 46 f0 ; 0xc279e + cmp AL, strict byte 0ffh ; 3c ff ; 0xc27a1 vgabios.c:1693 + jne short 027a8h ; 75 03 ; 0xc27a3 + jmp near 028f5h ; e9 4d 01 ; 0xc27a5 + mov al, dl ; 88 d0 ; 0xc27a8 vgabios.c:1696 + xor ah, ah ; 30 e4 ; 0xc27aa + lea bx, [bp-01eh] ; 8d 5e e2 ; 0xc27ac + lea dx, [bp-01ch] ; 8d 56 e4 ; 0xc27af + call 00a97h ; e8 e2 e2 ; 0xc27b2 + mov al, byte [bp-01eh] ; 8a 46 e2 ; 0xc27b5 vgabios.c:1697 + mov byte [bp-006h], al ; 88 46 fa ; 0xc27b8 + mov ax, word [bp-01eh] ; 8b 46 e2 ; 0xc27bb + mov al, ah ; 88 e0 ; 0xc27be + xor ah, ah ; 30 e4 ; 0xc27c0 + mov word [bp-01ah], ax ; 89 46 e6 ; 0xc27c2 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc27c5 + mov byte [bp-00ch], al ; 88 46 f4 ; 0xc27c8 + mov bx, 00084h ; bb 84 00 ; 0xc27cb vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc27ce + mov es, ax ; 8e c0 ; 0xc27d1 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc27d3 + xor ah, ah ; 30 e4 ; 0xc27d6 vgabios.c:48 + mov dx, ax ; 89 c2 ; 0xc27d8 + inc dx ; 42 ; 0xc27da + mov di, strict word 0004ah ; bf 4a 00 ; 0xc27db vgabios.c:57 + mov di, word [es:di] ; 26 8b 3d ; 0xc27de + mov word [bp-018h], di ; 89 7e e8 ; 0xc27e1 vgabios.c:58 + mov al, cl ; 88 c8 ; 0xc27e4 vgabios.c:1703 + mov CL, strict byte 003h ; b1 03 ; 0xc27e6 + mov bx, ax ; 89 c3 ; 0xc27e8 + sal bx, CL ; d3 e3 ; 0xc27ea + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc27ec + jne short 02838h ; 75 45 ; 0xc27f1 + mov ax, di ; 89 f8 ; 0xc27f3 vgabios.c:1706 + mul dx ; f7 e2 ; 0xc27f5 + sal ax, 1 ; d1 e0 ; 0xc27f7 + or AL, strict byte 0ffh ; 0c ff ; 0xc27f9 + mov dl, byte [bp-00eh] ; 8a 56 f2 ; 0xc27fb + xor dh, dh ; 30 f6 ; 0xc27fe + inc ax ; 40 ; 0xc2800 + mul dx ; f7 e2 ; 0xc2801 + mov bx, ax ; 89 c3 ; 0xc2803 + mov al, byte [bp-01ah] ; 8a 46 e6 ; 0xc2805 + xor ah, ah ; 30 e4 ; 0xc2808 + mul di ; f7 e7 ; 0xc280a + mov dx, ax ; 89 c2 ; 0xc280c + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc280e + xor ah, ah ; 30 e4 ; 0xc2811 + add ax, dx ; 01 d0 ; 0xc2813 + sal ax, 1 ; d1 e0 ; 0xc2815 + add bx, ax ; 01 c3 ; 0xc2817 + dec si ; 4e ; 0xc2819 vgabios.c:1708 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc281a + je short 027a5h ; 74 86 ; 0xc281d + mov al, byte [bp-010h] ; 8a 46 f0 ; 0xc281f vgabios.c:1709 + xor ah, ah ; 30 e4 ; 0xc2822 + mov CL, strict byte 003h ; b1 03 ; 0xc2824 + mov di, ax ; 89 c7 ; 0xc2826 + sal di, CL ; d3 e7 ; 0xc2828 + mov es, [di+047b3h] ; 8e 85 b3 47 ; 0xc282a vgabios.c:50 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc282e vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc2831 + inc bx ; 43 ; 0xc2834 vgabios.c:1710 + inc bx ; 43 ; 0xc2835 + jmp short 02819h ; eb e1 ; 0xc2836 vgabios.c:1711 + mov di, ax ; 89 c7 ; 0xc2838 vgabios.c:1716 + mov al, byte [di+0482fh] ; 8a 85 2f 48 ; 0xc283a + mov CL, strict byte 006h ; b1 06 ; 0xc283e + mov di, ax ; 89 c7 ; 0xc2840 + sal di, CL ; d3 e7 ; 0xc2842 + mov al, byte [di+04845h] ; 8a 85 45 48 ; 0xc2844 + mov byte [bp-012h], al ; 88 46 ee ; 0xc2848 + mov al, byte [bx+047b2h] ; 8a 87 b2 47 ; 0xc284b vgabios.c:1717 + mov byte [bp-014h], al ; 88 46 ec ; 0xc284f + dec si ; 4e ; 0xc2852 vgabios.c:1718 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc2853 + je short 028a8h ; 74 50 ; 0xc2856 + mov bl, byte [bp-010h] ; 8a 5e f0 ; 0xc2858 vgabios.c:1720 + xor bh, bh ; 30 ff ; 0xc285b + mov CL, strict byte 003h ; b1 03 ; 0xc285d + sal bx, CL ; d3 e3 ; 0xc285f + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc2861 + cmp bl, cl ; 38 cb ; 0xc2865 + jc short 02878h ; 72 0f ; 0xc2867 + jbe short 0287fh ; 76 14 ; 0xc2869 + cmp bl, 005h ; 80 fb 05 ; 0xc286b + je short 028d4h ; 74 64 ; 0xc286e + cmp bl, 004h ; 80 fb 04 ; 0xc2870 + je short 02883h ; 74 0e ; 0xc2873 + jmp near 028efh ; e9 77 00 ; 0xc2875 + cmp bl, 002h ; 80 fb 02 ; 0xc2878 + je short 028aah ; 74 2d ; 0xc287b + jmp short 028efh ; eb 70 ; 0xc287d + or byte [bp-008h], 001h ; 80 4e f8 01 ; 0xc287f vgabios.c:1723 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2883 vgabios.c:1725 + xor ah, ah ; 30 e4 ; 0xc2886 + push ax ; 50 ; 0xc2888 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc2889 + push ax ; 50 ; 0xc288c + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc288d + push ax ; 50 ; 0xc2890 + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc2891 + xor ch, ch ; 30 ed ; 0xc2894 + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc2896 + xor bh, bh ; 30 ff ; 0xc2899 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc289b + xor dh, dh ; 30 f6 ; 0xc289e + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc28a0 + call 02342h ; e8 9c fa ; 0xc28a3 + jmp short 028efh ; eb 47 ; 0xc28a6 vgabios.c:1726 + jmp short 028f5h ; eb 4b ; 0xc28a8 + mov al, byte [bp-014h] ; 8a 46 ec ; 0xc28aa vgabios.c:1728 + xor ah, ah ; 30 e4 ; 0xc28ad + push ax ; 50 ; 0xc28af + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc28b0 + push ax ; 50 ; 0xc28b3 + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc28b4 + xor ch, ch ; 30 ed ; 0xc28b7 + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc28b9 + xor bh, bh ; 30 ff ; 0xc28bc + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc28be + xor dh, dh ; 30 f6 ; 0xc28c1 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc28c3 + mov byte [bp-016h], al ; 88 46 ea ; 0xc28c6 + mov byte [bp-015h], ah ; 88 66 eb ; 0xc28c9 + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc28cc + call 02454h ; e8 82 fb ; 0xc28cf + jmp short 028efh ; eb 1b ; 0xc28d2 vgabios.c:1729 + mov al, byte [bp-018h] ; 8a 46 e8 ; 0xc28d4 vgabios.c:1731 + xor ah, ah ; 30 e4 ; 0xc28d7 + push ax ; 50 ; 0xc28d9 + mov cl, byte [bp-00ch] ; 8a 4e f4 ; 0xc28da + xor ch, ch ; 30 ed ; 0xc28dd + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc28df + xor bh, bh ; 30 ff ; 0xc28e2 + mov dl, byte [bp-008h] ; 8a 56 f8 ; 0xc28e4 + xor dh, dh ; 30 f6 ; 0xc28e7 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc28e9 + call 02566h ; e8 77 fc ; 0xc28ec + inc byte [bp-006h] ; fe 46 fa ; 0xc28ef vgabios.c:1738 + jmp near 02852h ; e9 5d ff ; 0xc28f2 vgabios.c:1739 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc28f5 vgabios.c:1741 + pop di ; 5f ; 0xc28f8 + pop si ; 5e ; 0xc28f9 + pop bp ; 5d ; 0xc28fa + retn ; c3 ; 0xc28fb + ; disGetNextSymbol 0xc28fc LB 0x1c68 -> off=0x0 cb=000000000000017a uValue=00000000000c28fc 'biosfn_write_pixel' +biosfn_write_pixel: ; 0xc28fc LB 0x17a + push bp ; 55 ; 0xc28fc vgabios.c:1744 + mov bp, sp ; 89 e5 ; 0xc28fd + push si ; 56 ; 0xc28ff + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc2900 + mov byte [bp-006h], al ; 88 46 fa ; 0xc2903 + mov byte [bp-004h], dl ; 88 56 fc ; 0xc2906 + mov word [bp-008h], bx ; 89 5e f8 ; 0xc2909 + mov word [bp-00ah], cx ; 89 4e f6 ; 0xc290c + mov bx, strict word 00049h ; bb 49 00 ; 0xc290f vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2912 + mov es, ax ; 8e c0 ; 0xc2915 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2917 + xor ah, ah ; 30 e4 ; 0xc291a vgabios.c:1751 + call 03888h ; e8 69 0f ; 0xc291c + mov ch, al ; 88 c5 ; 0xc291f + cmp AL, strict byte 0ffh ; 3c ff ; 0xc2921 vgabios.c:1752 + je short 0294ch ; 74 27 ; 0xc2923 + mov bl, al ; 88 c3 ; 0xc2925 vgabios.c:1753 + xor bh, bh ; 30 ff ; 0xc2927 + mov CL, strict byte 003h ; b1 03 ; 0xc2929 + sal bx, CL ; d3 e3 ; 0xc292b + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc292d + je short 0294ch ; 74 18 ; 0xc2932 + mov al, byte [bx+047b1h] ; 8a 87 b1 47 ; 0xc2934 vgabios.c:1755 + cmp al, cl ; 38 c8 ; 0xc2938 + jc short 02948h ; 72 0c ; 0xc293a + jbe short 02952h ; 76 14 ; 0xc293c + cmp AL, strict byte 005h ; 3c 05 ; 0xc293e + je short 0294fh ; 74 0d ; 0xc2940 + cmp AL, strict byte 004h ; 3c 04 ; 0xc2942 + je short 02952h ; 74 0c ; 0xc2944 + jmp short 0294ch ; eb 04 ; 0xc2946 + cmp AL, strict byte 002h ; 3c 02 ; 0xc2948 + je short 029c4h ; 74 78 ; 0xc294a + jmp near 02a4fh ; e9 00 01 ; 0xc294c + jmp near 02a55h ; e9 03 01 ; 0xc294f + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2952 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2955 + mov es, ax ; 8e c0 ; 0xc2958 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc295a + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc295d vgabios.c:58 + mul dx ; f7 e2 ; 0xc2960 + mov CL, strict byte 003h ; b1 03 ; 0xc2962 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc2964 + shr bx, CL ; d3 eb ; 0xc2967 + add bx, ax ; 01 c3 ; 0xc2969 + mov si, strict word 0004ch ; be 4c 00 ; 0xc296b vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc296e + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc2971 vgabios.c:58 + xor dh, dh ; 30 f6 ; 0xc2974 + mul dx ; f7 e2 ; 0xc2976 + add bx, ax ; 01 c3 ; 0xc2978 + mov cx, word [bp-008h] ; 8b 4e f8 ; 0xc297a vgabios.c:1761 + and cl, 007h ; 80 e1 07 ; 0xc297d + mov ax, 00080h ; b8 80 00 ; 0xc2980 + sar ax, CL ; d3 f8 ; 0xc2983 + mov ah, al ; 88 c4 ; 0xc2985 vgabios.c:1762 + xor al, al ; 30 c0 ; 0xc2987 + or AL, strict byte 008h ; 0c 08 ; 0xc2989 + mov dx, 003ceh ; ba ce 03 ; 0xc298b + out DX, ax ; ef ; 0xc298e + mov ax, 00205h ; b8 05 02 ; 0xc298f vgabios.c:1763 + out DX, ax ; ef ; 0xc2992 + mov dx, bx ; 89 da ; 0xc2993 vgabios.c:1764 + mov ax, 0a000h ; b8 00 a0 ; 0xc2995 + call 038b3h ; e8 18 0f ; 0xc2998 + test byte [bp-004h], 080h ; f6 46 fc 80 ; 0xc299b vgabios.c:1765 + je short 029a8h ; 74 07 ; 0xc299f + mov ax, 01803h ; b8 03 18 ; 0xc29a1 vgabios.c:1767 + mov dx, 003ceh ; ba ce 03 ; 0xc29a4 + out DX, ax ; ef ; 0xc29a7 + mov ax, 0a000h ; b8 00 a0 ; 0xc29a8 vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc29ab + mov al, byte [bp-004h] ; 8a 46 fc ; 0xc29ad + mov byte [es:bx], al ; 26 88 07 ; 0xc29b0 + mov ax, 0ff08h ; b8 08 ff ; 0xc29b3 vgabios.c:1770 + mov dx, 003ceh ; ba ce 03 ; 0xc29b6 + out DX, ax ; ef ; 0xc29b9 + mov ax, strict word 00005h ; b8 05 00 ; 0xc29ba vgabios.c:1771 + out DX, ax ; ef ; 0xc29bd + mov ax, strict word 00003h ; b8 03 00 ; 0xc29be vgabios.c:1772 + out DX, ax ; ef ; 0xc29c1 + jmp short 0294ch ; eb 88 ; 0xc29c2 vgabios.c:1773 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc29c4 vgabios.c:1775 + shr ax, 1 ; d1 e8 ; 0xc29c7 + mov dx, strict word 00050h ; ba 50 00 ; 0xc29c9 + mul dx ; f7 e2 ; 0xc29cc + cmp byte [bx+047b2h], 002h ; 80 bf b2 47 02 ; 0xc29ce + jne short 029deh ; 75 09 ; 0xc29d3 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc29d5 vgabios.c:1777 + shr bx, 1 ; d1 eb ; 0xc29d8 + shr bx, 1 ; d1 eb ; 0xc29da + jmp short 029e3h ; eb 05 ; 0xc29dc vgabios.c:1779 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc29de vgabios.c:1781 + shr bx, CL ; d3 eb ; 0xc29e1 + add bx, ax ; 01 c3 ; 0xc29e3 + test byte [bp-00ah], 001h ; f6 46 f6 01 ; 0xc29e5 vgabios.c:1783 + je short 029eeh ; 74 03 ; 0xc29e9 + add bh, 020h ; 80 c7 20 ; 0xc29eb + mov ax, 0b800h ; b8 00 b8 ; 0xc29ee vgabios.c:47 + mov es, ax ; 8e c0 ; 0xc29f1 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc29f3 + mov dl, ch ; 88 ea ; 0xc29f6 vgabios.c:1785 + xor dh, dh ; 30 f6 ; 0xc29f8 + mov CL, strict byte 003h ; b1 03 ; 0xc29fa + mov si, dx ; 89 d6 ; 0xc29fc + sal si, CL ; d3 e6 ; 0xc29fe + cmp byte [si+047b2h], 002h ; 80 bc b2 47 02 ; 0xc2a00 + jne short 02a21h ; 75 1a ; 0xc2a05 + mov ah, byte [bp-008h] ; 8a 66 f8 ; 0xc2a07 vgabios.c:1787 + and ah, cl ; 20 cc ; 0xc2a0a + mov dl, cl ; 88 ca ; 0xc2a0c + sub dl, ah ; 28 e2 ; 0xc2a0e + mov ah, dl ; 88 d4 ; 0xc2a10 + sal ah, 1 ; d0 e4 ; 0xc2a12 + mov dl, byte [bp-004h] ; 8a 56 fc ; 0xc2a14 + and dl, cl ; 20 ca ; 0xc2a17 + mov cl, ah ; 88 e1 ; 0xc2a19 + sal dl, CL ; d2 e2 ; 0xc2a1b + mov AH, strict byte 003h ; b4 03 ; 0xc2a1d vgabios.c:1788 + jmp short 02a35h ; eb 14 ; 0xc2a1f vgabios.c:1790 + mov ah, byte [bp-008h] ; 8a 66 f8 ; 0xc2a21 vgabios.c:1792 + and ah, 007h ; 80 e4 07 ; 0xc2a24 + mov CL, strict byte 007h ; b1 07 ; 0xc2a27 + sub cl, ah ; 28 e1 ; 0xc2a29 + mov dl, byte [bp-004h] ; 8a 56 fc ; 0xc2a2b + and dl, 001h ; 80 e2 01 ; 0xc2a2e + sal dl, CL ; d2 e2 ; 0xc2a31 + mov AH, strict byte 001h ; b4 01 ; 0xc2a33 vgabios.c:1793 + sal ah, CL ; d2 e4 ; 0xc2a35 + test byte [bp-004h], 080h ; f6 46 fc 80 ; 0xc2a37 vgabios.c:1795 + je short 02a41h ; 74 04 ; 0xc2a3b + xor al, dl ; 30 d0 ; 0xc2a3d vgabios.c:1797 + jmp short 02a47h ; eb 06 ; 0xc2a3f vgabios.c:1799 + not ah ; f6 d4 ; 0xc2a41 vgabios.c:1801 + and al, ah ; 20 e0 ; 0xc2a43 + or al, dl ; 08 d0 ; 0xc2a45 vgabios.c:1802 + mov dx, 0b800h ; ba 00 b8 ; 0xc2a47 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc2a4a + mov byte [es:bx], al ; 26 88 07 ; 0xc2a4c + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2a4f vgabios.c:1805 + pop si ; 5e ; 0xc2a52 + pop bp ; 5d ; 0xc2a53 + retn ; c3 ; 0xc2a54 + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2a55 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2a58 + mov es, ax ; 8e c0 ; 0xc2a5b + mov dx, word [es:bx] ; 26 8b 17 ; 0xc2a5d + sal dx, CL ; d3 e2 ; 0xc2a60 vgabios.c:58 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc2a62 + mul dx ; f7 e2 ; 0xc2a65 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc2a67 + add bx, ax ; 01 c3 ; 0xc2a6a + mov ax, 0a000h ; b8 00 a0 ; 0xc2a6c vgabios.c:52 + mov es, ax ; 8e c0 ; 0xc2a6f + mov al, byte [bp-004h] ; 8a 46 fc ; 0xc2a71 + jmp short 02a4ch ; eb d6 ; 0xc2a74 + ; disGetNextSymbol 0xc2a76 LB 0x1aee -> off=0x0 cb=0000000000000263 uValue=00000000000c2a76 'biosfn_write_teletype' +biosfn_write_teletype: ; 0xc2a76 LB 0x263 + push bp ; 55 ; 0xc2a76 vgabios.c:1818 + mov bp, sp ; 89 e5 ; 0xc2a77 + push si ; 56 ; 0xc2a79 + sub sp, strict byte 00016h ; 83 ec 16 ; 0xc2a7a + mov ch, al ; 88 c5 ; 0xc2a7d + mov byte [bp-00ah], dl ; 88 56 f6 ; 0xc2a7f + mov byte [bp-00ch], bl ; 88 5e f4 ; 0xc2a82 + mov byte [bp-004h], cl ; 88 4e fc ; 0xc2a85 + cmp dl, 0ffh ; 80 fa ff ; 0xc2a88 vgabios.c:1826 + jne short 02a9bh ; 75 0e ; 0xc2a8b + mov bx, strict word 00062h ; bb 62 00 ; 0xc2a8d vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2a90 + mov es, ax ; 8e c0 ; 0xc2a93 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2a95 + mov byte [bp-00ah], al ; 88 46 f6 ; 0xc2a98 vgabios.c:48 + mov bx, strict word 00049h ; bb 49 00 ; 0xc2a9b vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2a9e + mov es, ax ; 8e c0 ; 0xc2aa1 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2aa3 + xor ah, ah ; 30 e4 ; 0xc2aa6 vgabios.c:1831 + call 03888h ; e8 dd 0d ; 0xc2aa8 + mov byte [bp-00eh], al ; 88 46 f2 ; 0xc2aab + cmp AL, strict byte 0ffh ; 3c ff ; 0xc2aae vgabios.c:1832 + je short 02b17h ; 74 65 ; 0xc2ab0 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2ab2 vgabios.c:1835 + xor ah, ah ; 30 e4 ; 0xc2ab5 + lea bx, [bp-016h] ; 8d 5e ea ; 0xc2ab7 + lea dx, [bp-018h] ; 8d 56 e8 ; 0xc2aba + call 00a97h ; e8 d7 df ; 0xc2abd + mov al, byte [bp-016h] ; 8a 46 ea ; 0xc2ac0 vgabios.c:1836 + mov byte [bp-006h], al ; 88 46 fa ; 0xc2ac3 + mov ax, word [bp-016h] ; 8b 46 ea ; 0xc2ac6 + mov al, ah ; 88 e0 ; 0xc2ac9 + xor ah, ah ; 30 e4 ; 0xc2acb + mov byte [bp-008h], al ; 88 46 f8 ; 0xc2acd + mov bx, 00084h ; bb 84 00 ; 0xc2ad0 vgabios.c:47 + mov dx, strict word 00040h ; ba 40 00 ; 0xc2ad3 + mov es, dx ; 8e c2 ; 0xc2ad6 + mov dl, byte [es:bx] ; 26 8a 17 ; 0xc2ad8 + xor dh, dh ; 30 f6 ; 0xc2adb vgabios.c:48 + inc dx ; 42 ; 0xc2add + mov word [bp-014h], dx ; 89 56 ec ; 0xc2ade + mov bx, strict word 0004ah ; bb 4a 00 ; 0xc2ae1 vgabios.c:57 + mov dx, word [es:bx] ; 26 8b 17 ; 0xc2ae4 + mov word [bp-012h], dx ; 89 56 ee ; 0xc2ae7 vgabios.c:58 + cmp ch, 008h ; 80 fd 08 ; 0xc2aea vgabios.c:1842 + jc short 02afdh ; 72 0e ; 0xc2aed + jbe short 02b05h ; 76 14 ; 0xc2aef + cmp ch, 00dh ; 80 fd 0d ; 0xc2af1 + je short 02b1ah ; 74 24 ; 0xc2af4 + cmp ch, 00ah ; 80 fd 0a ; 0xc2af6 + je short 02b10h ; 74 15 ; 0xc2af9 + jmp short 02b20h ; eb 23 ; 0xc2afb + cmp ch, 007h ; 80 fd 07 ; 0xc2afd + jne short 02b20h ; 75 1e ; 0xc2b00 + jmp near 02c28h ; e9 23 01 ; 0xc2b02 + cmp byte [bp-006h], 000h ; 80 7e fa 00 ; 0xc2b05 vgabios.c:1849 + jbe short 02b1dh ; 76 12 ; 0xc2b09 + dec byte [bp-006h] ; fe 4e fa ; 0xc2b0b + jmp short 02b1dh ; eb 0d ; 0xc2b0e vgabios.c:1850 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc2b10 vgabios.c:1853 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc2b12 + jmp short 02b1dh ; eb 06 ; 0xc2b15 vgabios.c:1854 + jmp near 02cd3h ; e9 b9 01 ; 0xc2b17 + mov byte [bp-006h], ah ; 88 66 fa ; 0xc2b1a vgabios.c:1857 + jmp near 02c28h ; e9 08 01 ; 0xc2b1d vgabios.c:1858 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc2b20 vgabios.c:1862 + xor ah, ah ; 30 e4 ; 0xc2b23 + mov CL, strict byte 003h ; b1 03 ; 0xc2b25 + mov bx, ax ; 89 c3 ; 0xc2b27 + sal bx, CL ; d3 e3 ; 0xc2b29 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc2b2b + jne short 02b74h ; 75 42 ; 0xc2b30 + mov ax, word [bp-012h] ; 8b 46 ee ; 0xc2b32 vgabios.c:1865 + mul word [bp-014h] ; f7 66 ec ; 0xc2b35 + sal ax, 1 ; d1 e0 ; 0xc2b38 + or AL, strict byte 0ffh ; 0c ff ; 0xc2b3a + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc2b3c + xor dh, dh ; 30 f6 ; 0xc2b3f + inc ax ; 40 ; 0xc2b41 + mul dx ; f7 e2 ; 0xc2b42 + mov si, ax ; 89 c6 ; 0xc2b44 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2b46 + xor ah, ah ; 30 e4 ; 0xc2b49 + mul word [bp-012h] ; f7 66 ee ; 0xc2b4b + mov dx, ax ; 89 c2 ; 0xc2b4e + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2b50 + xor ah, ah ; 30 e4 ; 0xc2b53 + add ax, dx ; 01 d0 ; 0xc2b55 + sal ax, 1 ; d1 e0 ; 0xc2b57 + add si, ax ; 01 c6 ; 0xc2b59 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2b5b vgabios.c:50 + mov byte [es:si], ch ; 26 88 2c ; 0xc2b5f vgabios.c:52 + cmp cl, byte [bp-004h] ; 3a 4e fc ; 0xc2b62 vgabios.c:1870 + jne short 02ba4h ; 75 3d ; 0xc2b65 + inc si ; 46 ; 0xc2b67 vgabios.c:1871 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2b68 vgabios.c:50 + mov al, byte [bp-00ch] ; 8a 46 f4 ; 0xc2b6c + mov byte [es:si], al ; 26 88 04 ; 0xc2b6f + jmp short 02ba4h ; eb 30 ; 0xc2b72 vgabios.c:1873 + mov si, ax ; 89 c6 ; 0xc2b74 vgabios.c:1876 + mov al, byte [si+0482fh] ; 8a 84 2f 48 ; 0xc2b76 + mov CL, strict byte 006h ; b1 06 ; 0xc2b7a + mov si, ax ; 89 c6 ; 0xc2b7c + sal si, CL ; d3 e6 ; 0xc2b7e + mov dl, byte [si+04845h] ; 8a 94 45 48 ; 0xc2b80 + mov al, byte [bx+047b2h] ; 8a 87 b2 47 ; 0xc2b84 vgabios.c:1877 + mov bl, byte [bx+047b1h] ; 8a 9f b1 47 ; 0xc2b88 vgabios.c:1878 + cmp bl, 003h ; 80 fb 03 ; 0xc2b8c + jc short 02b9fh ; 72 0e ; 0xc2b8f + jbe short 02ba6h ; 76 13 ; 0xc2b91 + cmp bl, 005h ; 80 fb 05 ; 0xc2b93 + je short 02bf6h ; 74 5e ; 0xc2b96 + cmp bl, 004h ; 80 fb 04 ; 0xc2b98 + je short 02baah ; 74 0d ; 0xc2b9b + jmp short 02c15h ; eb 76 ; 0xc2b9d + cmp bl, 002h ; 80 fb 02 ; 0xc2b9f + je short 02bd4h ; 74 30 ; 0xc2ba2 + jmp short 02c15h ; eb 6f ; 0xc2ba4 + or byte [bp-00ch], 001h ; 80 4e f4 01 ; 0xc2ba6 vgabios.c:1881 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2baa vgabios.c:1883 + xor ah, ah ; 30 e4 ; 0xc2bad + push ax ; 50 ; 0xc2baf + mov al, dl ; 88 d0 ; 0xc2bb0 + push ax ; 50 ; 0xc2bb2 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc2bb3 + push ax ; 50 ; 0xc2bb6 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2bb7 + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc2bba + xor bh, bh ; 30 ff ; 0xc2bbd + mov dl, byte [bp-00ch] ; 8a 56 f4 ; 0xc2bbf + xor dh, dh ; 30 f6 ; 0xc2bc2 + mov byte [bp-010h], ch ; 88 6e f0 ; 0xc2bc4 + mov byte [bp-00fh], ah ; 88 66 f1 ; 0xc2bc7 + mov cx, ax ; 89 c1 ; 0xc2bca + mov ax, word [bp-010h] ; 8b 46 f0 ; 0xc2bcc + call 02342h ; e8 70 f7 ; 0xc2bcf + jmp short 02c15h ; eb 41 ; 0xc2bd2 vgabios.c:1884 + push ax ; 50 ; 0xc2bd4 vgabios.c:1886 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc2bd5 + push ax ; 50 ; 0xc2bd8 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2bd9 + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc2bdc + xor bh, bh ; 30 ff ; 0xc2bdf + mov dl, byte [bp-00ch] ; 8a 56 f4 ; 0xc2be1 + xor dh, dh ; 30 f6 ; 0xc2be4 + mov byte [bp-010h], ch ; 88 6e f0 ; 0xc2be6 + mov byte [bp-00fh], ah ; 88 66 f1 ; 0xc2be9 + mov cx, ax ; 89 c1 ; 0xc2bec + mov ax, word [bp-010h] ; 8b 46 f0 ; 0xc2bee + call 02454h ; e8 60 f8 ; 0xc2bf1 + jmp short 02c15h ; eb 1f ; 0xc2bf4 vgabios.c:1887 + mov al, byte [bp-012h] ; 8a 46 ee ; 0xc2bf6 vgabios.c:1889 + push ax ; 50 ; 0xc2bf9 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2bfa + mov byte [bp-010h], al ; 88 46 f0 ; 0xc2bfd + mov byte [bp-00fh], ah ; 88 66 f1 ; 0xc2c00 + mov bl, byte [bp-006h] ; 8a 5e fa ; 0xc2c03 + xor bh, bh ; 30 ff ; 0xc2c06 + mov dl, byte [bp-00ch] ; 8a 56 f4 ; 0xc2c08 + xor dh, dh ; 30 f6 ; 0xc2c0b + mov al, ch ; 88 e8 ; 0xc2c0d + mov cx, word [bp-010h] ; 8b 4e f0 ; 0xc2c0f + call 02566h ; e8 51 f9 ; 0xc2c12 + inc byte [bp-006h] ; fe 46 fa ; 0xc2c15 vgabios.c:1897 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2c18 vgabios.c:1899 + xor ah, ah ; 30 e4 ; 0xc2c1b + cmp ax, word [bp-012h] ; 3b 46 ee ; 0xc2c1d + jne short 02c28h ; 75 06 ; 0xc2c20 + mov byte [bp-006h], ah ; 88 66 fa ; 0xc2c22 vgabios.c:1900 + inc byte [bp-008h] ; fe 46 f8 ; 0xc2c25 vgabios.c:1901 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2c28 vgabios.c:1906 + xor ah, ah ; 30 e4 ; 0xc2c2b + cmp ax, word [bp-014h] ; 3b 46 ec ; 0xc2c2d + jne short 02c96h ; 75 64 ; 0xc2c30 + mov bl, byte [bp-00eh] ; 8a 5e f2 ; 0xc2c32 vgabios.c:1908 + xor bh, bh ; 30 ff ; 0xc2c35 + mov CL, strict byte 003h ; b1 03 ; 0xc2c37 + sal bx, CL ; d3 e3 ; 0xc2c39 + mov cl, byte [bp-014h] ; 8a 4e ec ; 0xc2c3b + db 0feh, 0c9h + ; dec cl ; fe c9 ; 0xc2c3e + mov ch, byte [bp-012h] ; 8a 6e ee ; 0xc2c40 + db 0feh, 0cdh + ; dec ch ; fe cd ; 0xc2c43 + cmp byte [bx+047b0h], 000h ; 80 bf b0 47 00 ; 0xc2c45 + jne short 02c98h ; 75 4c ; 0xc2c4a + mov ax, word [bp-012h] ; 8b 46 ee ; 0xc2c4c vgabios.c:1910 + mul word [bp-014h] ; f7 66 ec ; 0xc2c4f + sal ax, 1 ; d1 e0 ; 0xc2c52 + or AL, strict byte 0ffh ; 0c ff ; 0xc2c54 + mov dl, byte [bp-00ah] ; 8a 56 f6 ; 0xc2c56 + xor dh, dh ; 30 f6 ; 0xc2c59 + inc ax ; 40 ; 0xc2c5b + mul dx ; f7 e2 ; 0xc2c5c + mov si, ax ; 89 c6 ; 0xc2c5e + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2c60 + xor ah, ah ; 30 e4 ; 0xc2c63 + dec ax ; 48 ; 0xc2c65 + mul word [bp-012h] ; f7 66 ee ; 0xc2c66 + mov dx, ax ; 89 c2 ; 0xc2c69 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2c6b + xor ah, ah ; 30 e4 ; 0xc2c6e + add ax, dx ; 01 d0 ; 0xc2c70 + sal ax, 1 ; d1 e0 ; 0xc2c72 + add si, ax ; 01 c6 ; 0xc2c74 + inc si ; 46 ; 0xc2c76 vgabios.c:1911 + mov es, [bx+047b3h] ; 8e 87 b3 47 ; 0xc2c77 vgabios.c:45 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc2c7b vgabios.c:47 + mov ax, strict word 00001h ; b8 01 00 ; 0xc2c7e vgabios.c:1912 + push ax ; 50 ; 0xc2c81 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2c82 + xor ah, ah ; 30 e4 ; 0xc2c85 + push ax ; 50 ; 0xc2c87 + mov al, ch ; 88 e8 ; 0xc2c88 + push ax ; 50 ; 0xc2c8a + mov al, cl ; 88 c8 ; 0xc2c8b + push ax ; 50 ; 0xc2c8d + xor dh, dh ; 30 f6 ; 0xc2c8e + xor cx, cx ; 31 c9 ; 0xc2c90 + xor bx, bx ; 31 db ; 0xc2c92 + jmp short 02caeh ; eb 18 ; 0xc2c94 vgabios.c:1914 + jmp short 02cb7h ; eb 1f ; 0xc2c96 + mov ax, strict word 00001h ; b8 01 00 ; 0xc2c98 vgabios.c:1916 + push ax ; 50 ; 0xc2c9b + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2c9c + xor ah, ah ; 30 e4 ; 0xc2c9f + push ax ; 50 ; 0xc2ca1 + mov al, ch ; 88 e8 ; 0xc2ca2 + push ax ; 50 ; 0xc2ca4 + mov al, cl ; 88 c8 ; 0xc2ca5 + push ax ; 50 ; 0xc2ca7 + xor cx, cx ; 31 c9 ; 0xc2ca8 + xor bx, bx ; 31 db ; 0xc2caa + xor dx, dx ; 31 d2 ; 0xc2cac + mov ax, strict word 00001h ; b8 01 00 ; 0xc2cae + call 01c9fh ; e8 eb ef ; 0xc2cb1 + dec byte [bp-008h] ; fe 4e f8 ; 0xc2cb4 vgabios.c:1918 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc2cb7 vgabios.c:1922 + xor ah, ah ; 30 e4 ; 0xc2cba + mov word [bp-016h], ax ; 89 46 ea ; 0xc2cbc + mov CL, strict byte 008h ; b1 08 ; 0xc2cbf + sal word [bp-016h], CL ; d3 66 ea ; 0xc2cc1 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2cc4 + add word [bp-016h], ax ; 01 46 ea ; 0xc2cc7 + mov dx, word [bp-016h] ; 8b 56 ea ; 0xc2cca vgabios.c:1923 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc2ccd + call 012cfh ; e8 fc e5 ; 0xc2cd0 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2cd3 vgabios.c:1924 + pop si ; 5e ; 0xc2cd6 + pop bp ; 5d ; 0xc2cd7 + retn ; c3 ; 0xc2cd8 + ; disGetNextSymbol 0xc2cd9 LB 0x188b -> off=0x0 cb=0000000000000035 uValue=00000000000c2cd9 'get_font_access' +get_font_access: ; 0xc2cd9 LB 0x35 + push bp ; 55 ; 0xc2cd9 vgabios.c:1927 + mov bp, sp ; 89 e5 ; 0xc2cda + push dx ; 52 ; 0xc2cdc + mov ax, strict word 00005h ; b8 05 00 ; 0xc2cdd vgabios.c:1929 + mov dx, 003ceh ; ba ce 03 ; 0xc2ce0 + out DX, ax ; ef ; 0xc2ce3 + mov AL, strict byte 006h ; b0 06 ; 0xc2ce4 vgabios.c:1930 + out DX, AL ; ee ; 0xc2ce6 + mov dx, 003cfh ; ba cf 03 ; 0xc2ce7 vgabios.c:1931 + in AL, DX ; ec ; 0xc2cea + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2ceb + mov ah, al ; 88 c4 ; 0xc2ced + and ah, 001h ; 80 e4 01 ; 0xc2cef + or ah, 004h ; 80 cc 04 ; 0xc2cf2 + xor al, al ; 30 c0 ; 0xc2cf5 + or AL, strict byte 006h ; 0c 06 ; 0xc2cf7 + mov dx, 003ceh ; ba ce 03 ; 0xc2cf9 + out DX, ax ; ef ; 0xc2cfc + mov ax, 00402h ; b8 02 04 ; 0xc2cfd vgabios.c:1932 + mov dx, 003c4h ; ba c4 03 ; 0xc2d00 + out DX, ax ; ef ; 0xc2d03 + mov ax, 00604h ; b8 04 06 ; 0xc2d04 vgabios.c:1933 + out DX, ax ; ef ; 0xc2d07 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2d08 vgabios.c:1934 + pop dx ; 5a ; 0xc2d0b + pop bp ; 5d ; 0xc2d0c + retn ; c3 ; 0xc2d0d + ; disGetNextSymbol 0xc2d0e LB 0x1856 -> off=0x0 cb=0000000000000033 uValue=00000000000c2d0e 'release_font_access' +release_font_access: ; 0xc2d0e LB 0x33 + push bp ; 55 ; 0xc2d0e vgabios.c:1936 + mov bp, sp ; 89 e5 ; 0xc2d0f + push dx ; 52 ; 0xc2d11 + mov dx, 003cch ; ba cc 03 ; 0xc2d12 vgabios.c:1938 + in AL, DX ; ec ; 0xc2d15 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2d16 + and ax, strict word 00001h ; 25 01 00 ; 0xc2d18 + sal ax, 1 ; d1 e0 ; 0xc2d1b + sal ax, 1 ; d1 e0 ; 0xc2d1d + mov ah, al ; 88 c4 ; 0xc2d1f + or ah, 00ah ; 80 cc 0a ; 0xc2d21 + xor al, al ; 30 c0 ; 0xc2d24 + or AL, strict byte 006h ; 0c 06 ; 0xc2d26 + mov dx, 003ceh ; ba ce 03 ; 0xc2d28 + out DX, ax ; ef ; 0xc2d2b + mov ax, 01005h ; b8 05 10 ; 0xc2d2c vgabios.c:1939 + out DX, ax ; ef ; 0xc2d2f + mov ax, 00302h ; b8 02 03 ; 0xc2d30 vgabios.c:1940 + mov dx, 003c4h ; ba c4 03 ; 0xc2d33 + out DX, ax ; ef ; 0xc2d36 + mov ax, 00204h ; b8 04 02 ; 0xc2d37 vgabios.c:1941 + out DX, ax ; ef ; 0xc2d3a + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2d3b vgabios.c:1942 + pop dx ; 5a ; 0xc2d3e + pop bp ; 5d ; 0xc2d3f + retn ; c3 ; 0xc2d40 + ; disGetNextSymbol 0xc2d41 LB 0x1823 -> off=0x0 cb=00000000000000b3 uValue=00000000000c2d41 'set_scan_lines' +set_scan_lines: ; 0xc2d41 LB 0xb3 + push bp ; 55 ; 0xc2d41 vgabios.c:1944 + mov bp, sp ; 89 e5 ; 0xc2d42 + push bx ; 53 ; 0xc2d44 + push cx ; 51 ; 0xc2d45 + push dx ; 52 ; 0xc2d46 + push si ; 56 ; 0xc2d47 + push di ; 57 ; 0xc2d48 + mov bl, al ; 88 c3 ; 0xc2d49 + mov si, strict word 00063h ; be 63 00 ; 0xc2d4b vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2d4e + mov es, ax ; 8e c0 ; 0xc2d51 + mov si, word [es:si] ; 26 8b 34 ; 0xc2d53 + mov cx, si ; 89 f1 ; 0xc2d56 vgabios.c:58 + mov AL, strict byte 009h ; b0 09 ; 0xc2d58 vgabios.c:1950 + mov dx, si ; 89 f2 ; 0xc2d5a + out DX, AL ; ee ; 0xc2d5c + lea dx, [si+001h] ; 8d 54 01 ; 0xc2d5d vgabios.c:1951 + in AL, DX ; ec ; 0xc2d60 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2d61 + mov ah, al ; 88 c4 ; 0xc2d63 vgabios.c:1952 + and ah, 0e0h ; 80 e4 e0 ; 0xc2d65 + mov al, bl ; 88 d8 ; 0xc2d68 + db 0feh, 0c8h + ; dec al ; fe c8 ; 0xc2d6a + or al, ah ; 08 e0 ; 0xc2d6c + out DX, AL ; ee ; 0xc2d6e vgabios.c:1953 + cmp bl, 008h ; 80 fb 08 ; 0xc2d6f vgabios.c:1954 + jne short 02d7ch ; 75 08 ; 0xc2d72 + mov dx, strict word 00007h ; ba 07 00 ; 0xc2d74 vgabios.c:1956 + mov ax, strict word 00006h ; b8 06 00 ; 0xc2d77 + jmp short 02d89h ; eb 0d ; 0xc2d7a vgabios.c:1958 + mov dl, bl ; 88 da ; 0xc2d7c vgabios.c:1960 + sub dl, 003h ; 80 ea 03 ; 0xc2d7e + xor dh, dh ; 30 f6 ; 0xc2d81 + mov al, bl ; 88 d8 ; 0xc2d83 + sub AL, strict byte 004h ; 2c 04 ; 0xc2d85 + xor ah, ah ; 30 e4 ; 0xc2d87 + call 011d3h ; e8 47 e4 ; 0xc2d89 + xor bh, bh ; 30 ff ; 0xc2d8c vgabios.c:1962 + mov si, 00085h ; be 85 00 ; 0xc2d8e vgabios.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2d91 + mov es, ax ; 8e c0 ; 0xc2d94 + mov word [es:si], bx ; 26 89 1c ; 0xc2d96 + mov AL, strict byte 012h ; b0 12 ; 0xc2d99 vgabios.c:1963 + mov dx, cx ; 89 ca ; 0xc2d9b + out DX, AL ; ee ; 0xc2d9d + mov si, cx ; 89 ce ; 0xc2d9e vgabios.c:1964 + inc si ; 46 ; 0xc2da0 + mov dx, si ; 89 f2 ; 0xc2da1 + in AL, DX ; ec ; 0xc2da3 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2da4 + mov di, ax ; 89 c7 ; 0xc2da6 + mov AL, strict byte 007h ; b0 07 ; 0xc2da8 vgabios.c:1965 + mov dx, cx ; 89 ca ; 0xc2daa + out DX, AL ; ee ; 0xc2dac + mov dx, si ; 89 f2 ; 0xc2dad vgabios.c:1966 + in AL, DX ; ec ; 0xc2daf + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc2db0 + mov dl, al ; 88 c2 ; 0xc2db2 vgabios.c:1967 + and dl, 002h ; 80 e2 02 ; 0xc2db4 + xor dh, dh ; 30 f6 ; 0xc2db7 + mov CL, strict byte 007h ; b1 07 ; 0xc2db9 + sal dx, CL ; d3 e2 ; 0xc2dbb + and AL, strict byte 040h ; 24 40 ; 0xc2dbd + xor ah, ah ; 30 e4 ; 0xc2dbf + mov CL, strict byte 003h ; b1 03 ; 0xc2dc1 + sal ax, CL ; d3 e0 ; 0xc2dc3 + add ax, dx ; 01 d0 ; 0xc2dc5 + inc ax ; 40 ; 0xc2dc7 + add ax, di ; 01 f8 ; 0xc2dc8 + xor dx, dx ; 31 d2 ; 0xc2dca vgabios.c:1968 + div bx ; f7 f3 ; 0xc2dcc + mov dl, al ; 88 c2 ; 0xc2dce vgabios.c:1969 + db 0feh, 0cah + ; dec dl ; fe ca ; 0xc2dd0 + mov si, 00084h ; be 84 00 ; 0xc2dd2 vgabios.c:52 + mov byte [es:si], dl ; 26 88 14 ; 0xc2dd5 + mov si, strict word 0004ah ; be 4a 00 ; 0xc2dd8 vgabios.c:57 + mov dx, word [es:si] ; 26 8b 14 ; 0xc2ddb + xor ah, ah ; 30 e4 ; 0xc2dde vgabios.c:1971 + mul dx ; f7 e2 ; 0xc2de0 + sal ax, 1 ; d1 e0 ; 0xc2de2 + mov si, strict word 0004ch ; be 4c 00 ; 0xc2de4 vgabios.c:62 + mov word [es:si], ax ; 26 89 04 ; 0xc2de7 + lea sp, [bp-00ah] ; 8d 66 f6 ; 0xc2dea vgabios.c:1972 + pop di ; 5f ; 0xc2ded + pop si ; 5e ; 0xc2dee + pop dx ; 5a ; 0xc2def + pop cx ; 59 ; 0xc2df0 + pop bx ; 5b ; 0xc2df1 + pop bp ; 5d ; 0xc2df2 + retn ; c3 ; 0xc2df3 + ; disGetNextSymbol 0xc2df4 LB 0x1770 -> off=0x0 cb=0000000000000020 uValue=00000000000c2df4 'biosfn_set_font_block' +biosfn_set_font_block: ; 0xc2df4 LB 0x20 + push bp ; 55 ; 0xc2df4 vgabios.c:1974 + mov bp, sp ; 89 e5 ; 0xc2df5 + push bx ; 53 ; 0xc2df7 + push dx ; 52 ; 0xc2df8 + mov bl, al ; 88 c3 ; 0xc2df9 + mov ax, 00100h ; b8 00 01 ; 0xc2dfb vgabios.c:1976 + mov dx, 003c4h ; ba c4 03 ; 0xc2dfe + out DX, ax ; ef ; 0xc2e01 + mov ah, bl ; 88 dc ; 0xc2e02 vgabios.c:1977 + xor al, al ; 30 c0 ; 0xc2e04 + or AL, strict byte 003h ; 0c 03 ; 0xc2e06 + out DX, ax ; ef ; 0xc2e08 + mov ax, 00300h ; b8 00 03 ; 0xc2e09 vgabios.c:1978 + out DX, ax ; ef ; 0xc2e0c + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2e0d vgabios.c:1979 + pop dx ; 5a ; 0xc2e10 + pop bx ; 5b ; 0xc2e11 + pop bp ; 5d ; 0xc2e12 + retn ; c3 ; 0xc2e13 + ; disGetNextSymbol 0xc2e14 LB 0x1750 -> off=0x0 cb=0000000000000078 uValue=00000000000c2e14 'load_text_patch' +load_text_patch: ; 0xc2e14 LB 0x78 + push bp ; 55 ; 0xc2e14 vgabios.c:1981 + mov bp, sp ; 89 e5 ; 0xc2e15 + push si ; 56 ; 0xc2e17 + push di ; 57 ; 0xc2e18 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc2e19 + push ax ; 50 ; 0xc2e1c + mov byte [bp-006h], cl ; 88 4e fa ; 0xc2e1d + call 02cd9h ; e8 b6 fe ; 0xc2e20 vgabios.c:1986 + mov al, bl ; 88 d8 ; 0xc2e23 vgabios.c:1988 + and AL, strict byte 003h ; 24 03 ; 0xc2e25 + xor ah, ah ; 30 e4 ; 0xc2e27 + mov CL, strict byte 00eh ; b1 0e ; 0xc2e29 + mov di, ax ; 89 c7 ; 0xc2e2b + sal di, CL ; d3 e7 ; 0xc2e2d + mov al, bl ; 88 d8 ; 0xc2e2f + and AL, strict byte 004h ; 24 04 ; 0xc2e31 + mov CL, strict byte 00bh ; b1 0b ; 0xc2e33 + sal ax, CL ; d3 e0 ; 0xc2e35 + add di, ax ; 01 c7 ; 0xc2e37 + mov word [bp-00ah], di ; 89 7e f6 ; 0xc2e39 + mov bx, dx ; 89 d3 ; 0xc2e3c vgabios.c:1989 + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc2e3e + mov word [bp-008h], ax ; 89 46 f8 ; 0xc2e41 + inc dx ; 42 ; 0xc2e44 vgabios.c:1990 + mov word [bp-00ch], dx ; 89 56 f4 ; 0xc2e45 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc2e48 vgabios.c:1991 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc2e4b + test al, al ; 84 c0 ; 0xc2e4e + je short 02e82h ; 74 30 ; 0xc2e50 + xor ah, ah ; 30 e4 ; 0xc2e52 vgabios.c:1992 + mov CL, strict byte 005h ; b1 05 ; 0xc2e54 + sal ax, CL ; d3 e0 ; 0xc2e56 + mov di, word [bp-00ah] ; 8b 7e f6 ; 0xc2e58 + add di, ax ; 01 c7 ; 0xc2e5b + mov cl, byte [bp-006h] ; 8a 4e fa ; 0xc2e5d vgabios.c:1993 + xor ch, ch ; 30 ed ; 0xc2e60 + mov si, word [bp-00ch] ; 8b 76 f4 ; 0xc2e62 + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc2e65 + mov ax, 0a000h ; b8 00 a0 ; 0xc2e68 + mov es, ax ; 8e c0 ; 0xc2e6b + jcxz 02e75h ; e3 06 ; 0xc2e6d + push DS ; 1e ; 0xc2e6f + mov ds, dx ; 8e da ; 0xc2e70 + rep movsb ; f3 a4 ; 0xc2e72 + pop DS ; 1f ; 0xc2e74 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc2e75 vgabios.c:1994 + xor ah, ah ; 30 e4 ; 0xc2e78 + inc ax ; 40 ; 0xc2e7a + add word [bp-00ch], ax ; 01 46 f4 ; 0xc2e7b + add bx, ax ; 01 c3 ; 0xc2e7e vgabios.c:1995 + jmp short 02e48h ; eb c6 ; 0xc2e80 vgabios.c:1996 + call 02d0eh ; e8 89 fe ; 0xc2e82 vgabios.c:1998 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2e85 vgabios.c:1999 + pop di ; 5f ; 0xc2e88 + pop si ; 5e ; 0xc2e89 + pop bp ; 5d ; 0xc2e8a + retn ; c3 ; 0xc2e8b + ; disGetNextSymbol 0xc2e8c LB 0x16d8 -> off=0x0 cb=0000000000000084 uValue=00000000000c2e8c 'biosfn_load_text_user_pat' +biosfn_load_text_user_pat: ; 0xc2e8c LB 0x84 + push bp ; 55 ; 0xc2e8c vgabios.c:2001 + mov bp, sp ; 89 e5 ; 0xc2e8d + push si ; 56 ; 0xc2e8f + push di ; 57 ; 0xc2e90 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc2e91 + mov byte [bp-006h], al ; 88 46 fa ; 0xc2e94 + mov word [bp-00eh], dx ; 89 56 f2 ; 0xc2e97 + mov word [bp-00ah], bx ; 89 5e f6 ; 0xc2e9a + mov word [bp-00ch], cx ; 89 4e f4 ; 0xc2e9d + call 02cd9h ; e8 36 fe ; 0xc2ea0 vgabios.c:2006 + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc2ea3 vgabios.c:2007 + and AL, strict byte 003h ; 24 03 ; 0xc2ea6 + xor ah, ah ; 30 e4 ; 0xc2ea8 + mov CL, strict byte 00eh ; b1 0e ; 0xc2eaa + mov bx, ax ; 89 c3 ; 0xc2eac + sal bx, CL ; d3 e3 ; 0xc2eae + mov al, byte [bp+006h] ; 8a 46 06 ; 0xc2eb0 + and AL, strict byte 004h ; 24 04 ; 0xc2eb3 + mov CL, strict byte 00bh ; b1 0b ; 0xc2eb5 + sal ax, CL ; d3 e0 ; 0xc2eb7 + add bx, ax ; 01 c3 ; 0xc2eb9 + mov word [bp-008h], bx ; 89 5e f8 ; 0xc2ebb + xor bx, bx ; 31 db ; 0xc2ebe vgabios.c:2008 + cmp bx, word [bp-00ch] ; 3b 5e f4 ; 0xc2ec0 + jnc short 02ef6h ; 73 31 ; 0xc2ec3 + mov al, byte [bp+008h] ; 8a 46 08 ; 0xc2ec5 vgabios.c:2010 + xor ah, ah ; 30 e4 ; 0xc2ec8 + mov si, ax ; 89 c6 ; 0xc2eca + mov ax, bx ; 89 d8 ; 0xc2ecc + mul si ; f7 e6 ; 0xc2ece + add ax, word [bp-00ah] ; 03 46 f6 ; 0xc2ed0 + mov di, word [bp+004h] ; 8b 7e 04 ; 0xc2ed3 vgabios.c:2011 + add di, bx ; 01 df ; 0xc2ed6 + mov CL, strict byte 005h ; b1 05 ; 0xc2ed8 + sal di, CL ; d3 e7 ; 0xc2eda + add di, word [bp-008h] ; 03 7e f8 ; 0xc2edc + mov cx, si ; 89 f1 ; 0xc2edf vgabios.c:2012 + mov si, ax ; 89 c6 ; 0xc2ee1 + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc2ee3 + mov ax, 0a000h ; b8 00 a0 ; 0xc2ee6 + mov es, ax ; 8e c0 ; 0xc2ee9 + jcxz 02ef3h ; e3 06 ; 0xc2eeb + push DS ; 1e ; 0xc2eed + mov ds, dx ; 8e da ; 0xc2eee + rep movsb ; f3 a4 ; 0xc2ef0 + pop DS ; 1f ; 0xc2ef2 + inc bx ; 43 ; 0xc2ef3 vgabios.c:2013 + jmp short 02ec0h ; eb ca ; 0xc2ef4 + call 02d0eh ; e8 15 fe ; 0xc2ef6 vgabios.c:2014 + cmp byte [bp-006h], 010h ; 80 7e fa 10 ; 0xc2ef9 vgabios.c:2015 + jc short 02f07h ; 72 08 ; 0xc2efd + mov al, byte [bp+008h] ; 8a 46 08 ; 0xc2eff vgabios.c:2017 + xor ah, ah ; 30 e4 ; 0xc2f02 + call 02d41h ; e8 3a fe ; 0xc2f04 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2f07 vgabios.c:2019 + pop di ; 5f ; 0xc2f0a + pop si ; 5e ; 0xc2f0b + pop bp ; 5d ; 0xc2f0c + retn 00006h ; c2 06 00 ; 0xc2f0d + ; disGetNextSymbol 0xc2f10 LB 0x1654 -> off=0x0 cb=0000000000000016 uValue=00000000000c2f10 'biosfn_load_gfx_8_8_chars' +biosfn_load_gfx_8_8_chars: ; 0xc2f10 LB 0x16 + push bp ; 55 ; 0xc2f10 vgabios.c:2021 + mov bp, sp ; 89 e5 ; 0xc2f11 + push bx ; 53 ; 0xc2f13 + push cx ; 51 ; 0xc2f14 + mov bx, dx ; 89 d3 ; 0xc2f15 vgabios.c:2023 + mov cx, ax ; 89 c1 ; 0xc2f17 + mov ax, strict word 0001fh ; b8 1f 00 ; 0xc2f19 + call 009f0h ; e8 d1 da ; 0xc2f1c + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2f1f vgabios.c:2024 + pop cx ; 59 ; 0xc2f22 + pop bx ; 5b ; 0xc2f23 + pop bp ; 5d ; 0xc2f24 + retn ; c3 ; 0xc2f25 + ; disGetNextSymbol 0xc2f26 LB 0x163e -> off=0x0 cb=000000000000004d uValue=00000000000c2f26 'set_gfx_font' +set_gfx_font: ; 0xc2f26 LB 0x4d + push bp ; 55 ; 0xc2f26 vgabios.c:2026 + mov bp, sp ; 89 e5 ; 0xc2f27 + push si ; 56 ; 0xc2f29 + push di ; 57 ; 0xc2f2a + mov si, ax ; 89 c6 ; 0xc2f2b + mov ax, dx ; 89 d0 ; 0xc2f2d + mov di, bx ; 89 df ; 0xc2f2f + mov dl, cl ; 88 ca ; 0xc2f31 + mov bx, si ; 89 f3 ; 0xc2f33 vgabios.c:2030 + mov cx, ax ; 89 c1 ; 0xc2f35 + mov ax, strict word 00043h ; b8 43 00 ; 0xc2f37 + call 009f0h ; e8 b3 da ; 0xc2f3a + test dl, dl ; 84 d2 ; 0xc2f3d vgabios.c:2031 + je short 02f53h ; 74 12 ; 0xc2f3f + cmp dl, 003h ; 80 fa 03 ; 0xc2f41 vgabios.c:2032 + jbe short 02f48h ; 76 02 ; 0xc2f44 + mov DL, strict byte 002h ; b2 02 ; 0xc2f46 vgabios.c:2033 + mov bl, dl ; 88 d3 ; 0xc2f48 vgabios.c:2034 + xor bh, bh ; 30 ff ; 0xc2f4a + mov al, byte [bx+07dfeh] ; 8a 87 fe 7d ; 0xc2f4c + mov byte [bp+004h], al ; 88 46 04 ; 0xc2f50 + mov bx, 00085h ; bb 85 00 ; 0xc2f53 vgabios.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc2f56 + mov es, ax ; 8e c0 ; 0xc2f59 + mov word [es:bx], di ; 26 89 3f ; 0xc2f5b + mov al, byte [bp+004h] ; 8a 46 04 ; 0xc2f5e vgabios.c:2039 + xor ah, ah ; 30 e4 ; 0xc2f61 + dec ax ; 48 ; 0xc2f63 + mov bx, 00084h ; bb 84 00 ; 0xc2f64 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc2f67 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2f6a vgabios.c:2040 + pop di ; 5f ; 0xc2f6d + pop si ; 5e ; 0xc2f6e + pop bp ; 5d ; 0xc2f6f + retn 00002h ; c2 02 00 ; 0xc2f70 + ; disGetNextSymbol 0xc2f73 LB 0x15f1 -> off=0x0 cb=000000000000001d uValue=00000000000c2f73 'biosfn_load_gfx_user_chars' +biosfn_load_gfx_user_chars: ; 0xc2f73 LB 0x1d + push bp ; 55 ; 0xc2f73 vgabios.c:2042 + mov bp, sp ; 89 e5 ; 0xc2f74 + push si ; 56 ; 0xc2f76 + mov si, ax ; 89 c6 ; 0xc2f77 + mov ax, dx ; 89 d0 ; 0xc2f79 + mov dl, byte [bp+004h] ; 8a 56 04 ; 0xc2f7b vgabios.c:2045 + xor dh, dh ; 30 f6 ; 0xc2f7e + push dx ; 52 ; 0xc2f80 + xor ch, ch ; 30 ed ; 0xc2f81 + mov dx, si ; 89 f2 ; 0xc2f83 + call 02f26h ; e8 9e ff ; 0xc2f85 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc2f88 vgabios.c:2046 + pop si ; 5e ; 0xc2f8b + pop bp ; 5d ; 0xc2f8c + retn 00002h ; c2 02 00 ; 0xc2f8d + ; disGetNextSymbol 0xc2f90 LB 0x15d4 -> off=0x0 cb=0000000000000022 uValue=00000000000c2f90 'biosfn_load_gfx_8_14_chars' +biosfn_load_gfx_8_14_chars: ; 0xc2f90 LB 0x22 + push bp ; 55 ; 0xc2f90 vgabios.c:2051 + mov bp, sp ; 89 e5 ; 0xc2f91 + push bx ; 53 ; 0xc2f93 + push cx ; 51 ; 0xc2f94 + mov bl, al ; 88 c3 ; 0xc2f95 + mov al, dl ; 88 d0 ; 0xc2f97 + xor ah, ah ; 30 e4 ; 0xc2f99 vgabios.c:2053 + push ax ; 50 ; 0xc2f9b + mov al, bl ; 88 d8 ; 0xc2f9c + mov cx, ax ; 89 c1 ; 0xc2f9e + mov bx, strict word 0000eh ; bb 0e 00 ; 0xc2fa0 + mov ax, 05d6dh ; b8 6d 5d ; 0xc2fa3 + mov dx, ds ; 8c da ; 0xc2fa6 + call 02f26h ; e8 7b ff ; 0xc2fa8 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2fab vgabios.c:2054 + pop cx ; 59 ; 0xc2fae + pop bx ; 5b ; 0xc2faf + pop bp ; 5d ; 0xc2fb0 + retn ; c3 ; 0xc2fb1 + ; disGetNextSymbol 0xc2fb2 LB 0x15b2 -> off=0x0 cb=0000000000000022 uValue=00000000000c2fb2 'biosfn_load_gfx_8_8_dd_chars' +biosfn_load_gfx_8_8_dd_chars: ; 0xc2fb2 LB 0x22 + push bp ; 55 ; 0xc2fb2 vgabios.c:2055 + mov bp, sp ; 89 e5 ; 0xc2fb3 + push bx ; 53 ; 0xc2fb5 + push cx ; 51 ; 0xc2fb6 + mov bl, al ; 88 c3 ; 0xc2fb7 + mov al, dl ; 88 d0 ; 0xc2fb9 + xor ah, ah ; 30 e4 ; 0xc2fbb vgabios.c:2057 + push ax ; 50 ; 0xc2fbd + mov al, bl ; 88 d8 ; 0xc2fbe + mov cx, ax ; 89 c1 ; 0xc2fc0 + mov bx, strict word 00008h ; bb 08 00 ; 0xc2fc2 + mov ax, 0556dh ; b8 6d 55 ; 0xc2fc5 + mov dx, ds ; 8c da ; 0xc2fc8 + call 02f26h ; e8 59 ff ; 0xc2fca + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2fcd vgabios.c:2058 + pop cx ; 59 ; 0xc2fd0 + pop bx ; 5b ; 0xc2fd1 + pop bp ; 5d ; 0xc2fd2 + retn ; c3 ; 0xc2fd3 + ; disGetNextSymbol 0xc2fd4 LB 0x1590 -> off=0x0 cb=0000000000000022 uValue=00000000000c2fd4 'biosfn_load_gfx_8_16_chars' +biosfn_load_gfx_8_16_chars: ; 0xc2fd4 LB 0x22 + push bp ; 55 ; 0xc2fd4 vgabios.c:2059 + mov bp, sp ; 89 e5 ; 0xc2fd5 + push bx ; 53 ; 0xc2fd7 + push cx ; 51 ; 0xc2fd8 + mov bl, al ; 88 c3 ; 0xc2fd9 + mov al, dl ; 88 d0 ; 0xc2fdb + xor ah, ah ; 30 e4 ; 0xc2fdd vgabios.c:2061 + push ax ; 50 ; 0xc2fdf + mov al, bl ; 88 d8 ; 0xc2fe0 + mov cx, ax ; 89 c1 ; 0xc2fe2 + mov bx, strict word 00010h ; bb 10 00 ; 0xc2fe4 + mov ax, 06b6dh ; b8 6d 6b ; 0xc2fe7 + mov dx, ds ; 8c da ; 0xc2fea + call 02f26h ; e8 37 ff ; 0xc2fec + lea sp, [bp-004h] ; 8d 66 fc ; 0xc2fef vgabios.c:2062 + pop cx ; 59 ; 0xc2ff2 + pop bx ; 5b ; 0xc2ff3 + pop bp ; 5d ; 0xc2ff4 + retn ; c3 ; 0xc2ff5 + ; disGetNextSymbol 0xc2ff6 LB 0x156e -> off=0x0 cb=0000000000000005 uValue=00000000000c2ff6 'biosfn_alternate_prtsc' +biosfn_alternate_prtsc: ; 0xc2ff6 LB 0x5 + push bp ; 55 ; 0xc2ff6 vgabios.c:2064 + mov bp, sp ; 89 e5 ; 0xc2ff7 + pop bp ; 5d ; 0xc2ff9 vgabios.c:2069 + retn ; c3 ; 0xc2ffa + ; disGetNextSymbol 0xc2ffb LB 0x1569 -> off=0x0 cb=0000000000000032 uValue=00000000000c2ffb 'biosfn_set_txt_lines' +biosfn_set_txt_lines: ; 0xc2ffb LB 0x32 + push bx ; 53 ; 0xc2ffb vgabios.c:2071 + push si ; 56 ; 0xc2ffc + push bp ; 55 ; 0xc2ffd + mov bp, sp ; 89 e5 ; 0xc2ffe + mov bl, al ; 88 c3 ; 0xc3000 + mov si, 00089h ; be 89 00 ; 0xc3002 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3005 + mov es, ax ; 8e c0 ; 0xc3008 + mov al, byte [es:si] ; 26 8a 04 ; 0xc300a + and AL, strict byte 06fh ; 24 6f ; 0xc300d vgabios.c:2077 + cmp bl, 002h ; 80 fb 02 ; 0xc300f vgabios.c:2079 + je short 0301ch ; 74 08 ; 0xc3012 + test bl, bl ; 84 db ; 0xc3014 + jne short 0301eh ; 75 06 ; 0xc3016 + or AL, strict byte 080h ; 0c 80 ; 0xc3018 vgabios.c:2082 + jmp short 0301eh ; eb 02 ; 0xc301a vgabios.c:2083 + or AL, strict byte 010h ; 0c 10 ; 0xc301c vgabios.c:2085 + mov bx, 00089h ; bb 89 00 ; 0xc301e vgabios.c:52 + mov si, strict word 00040h ; be 40 00 ; 0xc3021 + mov es, si ; 8e c6 ; 0xc3024 + mov byte [es:bx], al ; 26 88 07 ; 0xc3026 + pop bp ; 5d ; 0xc3029 vgabios.c:2089 + pop si ; 5e ; 0xc302a + pop bx ; 5b ; 0xc302b + retn ; c3 ; 0xc302c + ; disGetNextSymbol 0xc302d LB 0x1537 -> off=0x0 cb=0000000000000005 uValue=00000000000c302d 'biosfn_switch_video_interface' +biosfn_switch_video_interface: ; 0xc302d LB 0x5 + push bp ; 55 ; 0xc302d vgabios.c:2092 + mov bp, sp ; 89 e5 ; 0xc302e + pop bp ; 5d ; 0xc3030 vgabios.c:2097 + retn ; c3 ; 0xc3031 + ; disGetNextSymbol 0xc3032 LB 0x1532 -> off=0x0 cb=0000000000000005 uValue=00000000000c3032 'biosfn_enable_video_refresh_control' +biosfn_enable_video_refresh_control: ; 0xc3032 LB 0x5 + push bp ; 55 ; 0xc3032 vgabios.c:2098 + mov bp, sp ; 89 e5 ; 0xc3033 + pop bp ; 5d ; 0xc3035 vgabios.c:2103 + retn ; c3 ; 0xc3036 + ; disGetNextSymbol 0xc3037 LB 0x152d -> off=0x0 cb=000000000000008f uValue=00000000000c3037 'biosfn_write_string' +biosfn_write_string: ; 0xc3037 LB 0x8f + push bp ; 55 ; 0xc3037 vgabios.c:2106 + mov bp, sp ; 89 e5 ; 0xc3038 + push si ; 56 ; 0xc303a + push di ; 57 ; 0xc303b + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc303c + mov byte [bp-008h], al ; 88 46 f8 ; 0xc303f + mov byte [bp-006h], dl ; 88 56 fa ; 0xc3042 + mov byte [bp-00ah], bl ; 88 5e f6 ; 0xc3045 + mov si, cx ; 89 ce ; 0xc3048 + mov di, word [bp+00ah] ; 8b 7e 0a ; 0xc304a + mov al, dl ; 88 d0 ; 0xc304d vgabios.c:2113 + xor ah, ah ; 30 e4 ; 0xc304f + lea bx, [bp-00eh] ; 8d 5e f2 ; 0xc3051 + lea dx, [bp-00ch] ; 8d 56 f4 ; 0xc3054 + call 00a97h ; e8 3d da ; 0xc3057 + cmp byte [bp+004h], 0ffh ; 80 7e 04 ff ; 0xc305a vgabios.c:2116 + jne short 0306ch ; 75 0c ; 0xc305e + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc3060 vgabios.c:2117 + mov byte [bp+006h], al ; 88 46 06 ; 0xc3063 + mov ax, word [bp-00eh] ; 8b 46 f2 ; 0xc3066 vgabios.c:2118 + mov byte [bp+004h], ah ; 88 66 04 ; 0xc3069 + mov dh, byte [bp+004h] ; 8a 76 04 ; 0xc306c vgabios.c:2121 + mov dl, byte [bp+006h] ; 8a 56 06 ; 0xc306f + xor ah, ah ; 30 e4 ; 0xc3072 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc3074 vgabios.c:2122 + call 012cfh ; e8 55 e2 ; 0xc3077 + dec si ; 4e ; 0xc307a vgabios.c:2124 + cmp si, strict byte 0ffffh ; 83 fe ff ; 0xc307b + je short 030ach ; 74 2c ; 0xc307e + mov bx, di ; 89 fb ; 0xc3080 vgabios.c:2126 + inc di ; 47 ; 0xc3082 + mov es, [bp+008h] ; 8e 46 08 ; 0xc3083 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3086 + test byte [bp-008h], 002h ; f6 46 f8 02 ; 0xc3089 vgabios.c:2127 + je short 03098h ; 74 09 ; 0xc308d + mov bx, di ; 89 fb ; 0xc308f vgabios.c:2128 + inc di ; 47 ; 0xc3091 + mov ah, byte [es:bx] ; 26 8a 27 ; 0xc3092 vgabios.c:47 + mov byte [bp-00ah], ah ; 88 66 f6 ; 0xc3095 vgabios.c:48 + mov bl, byte [bp-00ah] ; 8a 5e f6 ; 0xc3098 vgabios.c:2130 + xor bh, bh ; 30 ff ; 0xc309b + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc309d + xor dh, dh ; 30 f6 ; 0xc30a0 + xor ah, ah ; 30 e4 ; 0xc30a2 + mov cx, strict word 00003h ; b9 03 00 ; 0xc30a4 + call 02a76h ; e8 cc f9 ; 0xc30a7 + jmp short 0307ah ; eb ce ; 0xc30aa vgabios.c:2131 + test byte [bp-008h], 001h ; f6 46 f8 01 ; 0xc30ac vgabios.c:2134 + jne short 030bdh ; 75 0b ; 0xc30b0 + mov dx, word [bp-00eh] ; 8b 56 f2 ; 0xc30b2 vgabios.c:2135 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc30b5 + xor ah, ah ; 30 e4 ; 0xc30b8 + call 012cfh ; e8 12 e2 ; 0xc30ba + lea sp, [bp-004h] ; 8d 66 fc ; 0xc30bd vgabios.c:2136 + pop di ; 5f ; 0xc30c0 + pop si ; 5e ; 0xc30c1 + pop bp ; 5d ; 0xc30c2 + retn 00008h ; c2 08 00 ; 0xc30c3 + ; disGetNextSymbol 0xc30c6 LB 0x149e -> off=0x0 cb=00000000000001f2 uValue=00000000000c30c6 'biosfn_read_state_info' +biosfn_read_state_info: ; 0xc30c6 LB 0x1f2 + push bp ; 55 ; 0xc30c6 vgabios.c:2139 + mov bp, sp ; 89 e5 ; 0xc30c7 + push cx ; 51 ; 0xc30c9 + push si ; 56 ; 0xc30ca + push di ; 57 ; 0xc30cb + push ax ; 50 ; 0xc30cc + push ax ; 50 ; 0xc30cd + push dx ; 52 ; 0xc30ce + mov si, strict word 00049h ; be 49 00 ; 0xc30cf vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc30d2 + mov es, ax ; 8e c0 ; 0xc30d5 + mov al, byte [es:si] ; 26 8a 04 ; 0xc30d7 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc30da vgabios.c:48 + mov si, strict word 0004ch ; be 4c 00 ; 0xc30dd vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc30e0 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc30e3 vgabios.c:58 + mov ax, ds ; 8c d8 ; 0xc30e6 vgabios.c:2150 + mov es, dx ; 8e c2 ; 0xc30e8 vgabios.c:72 + mov word [es:bx], 05503h ; 26 c7 07 03 55 ; 0xc30ea + mov [es:bx+002h], ds ; 26 8c 5f 02 ; 0xc30ef + lea di, [bx+004h] ; 8d 7f 04 ; 0xc30f3 vgabios.c:2155 + mov cx, strict word 0001eh ; b9 1e 00 ; 0xc30f6 + mov si, strict word 00049h ; be 49 00 ; 0xc30f9 + mov dx, strict word 00040h ; ba 40 00 ; 0xc30fc + jcxz 03107h ; e3 06 ; 0xc30ff + push DS ; 1e ; 0xc3101 + mov ds, dx ; 8e da ; 0xc3102 + rep movsb ; f3 a4 ; 0xc3104 + pop DS ; 1f ; 0xc3106 + mov si, 00084h ; be 84 00 ; 0xc3107 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc310a + mov es, ax ; 8e c0 ; 0xc310d + mov al, byte [es:si] ; 26 8a 04 ; 0xc310f + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc3112 vgabios.c:48 + lea si, [bx+022h] ; 8d 77 22 ; 0xc3114 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc3117 vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc311a + lea di, [bx+023h] ; 8d 7f 23 ; 0xc311d vgabios.c:2157 + mov cx, strict word 00002h ; b9 02 00 ; 0xc3120 + mov si, 00085h ; be 85 00 ; 0xc3123 + mov dx, strict word 00040h ; ba 40 00 ; 0xc3126 + jcxz 03131h ; e3 06 ; 0xc3129 + push DS ; 1e ; 0xc312b + mov ds, dx ; 8e da ; 0xc312c + rep movsb ; f3 a4 ; 0xc312e + pop DS ; 1f ; 0xc3130 + mov si, 0008ah ; be 8a 00 ; 0xc3131 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3134 + mov es, ax ; 8e c0 ; 0xc3137 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3139 + lea si, [bx+025h] ; 8d 77 25 ; 0xc313c vgabios.c:48 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc313f vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc3142 + lea si, [bx+026h] ; 8d 77 26 ; 0xc3145 vgabios.c:2160 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc3148 vgabios.c:52 + lea si, [bx+027h] ; 8d 77 27 ; 0xc314c vgabios.c:2161 + mov word [es:si], strict word 00010h ; 26 c7 04 10 00 ; 0xc314f vgabios.c:62 + lea si, [bx+029h] ; 8d 77 29 ; 0xc3154 vgabios.c:2162 + mov byte [es:si], 008h ; 26 c6 04 08 ; 0xc3157 vgabios.c:52 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc315b vgabios.c:2163 + mov byte [es:si], 002h ; 26 c6 04 02 ; 0xc315e vgabios.c:52 + lea si, [bx+02bh] ; 8d 77 2b ; 0xc3162 vgabios.c:2164 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc3165 vgabios.c:52 + lea si, [bx+02ch] ; 8d 77 2c ; 0xc3169 vgabios.c:2165 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc316c vgabios.c:52 + lea si, [bx+02dh] ; 8d 77 2d ; 0xc3170 vgabios.c:2166 + mov byte [es:si], 021h ; 26 c6 04 21 ; 0xc3173 vgabios.c:52 + lea si, [bx+031h] ; 8d 77 31 ; 0xc3177 vgabios.c:2167 + mov byte [es:si], 003h ; 26 c6 04 03 ; 0xc317a vgabios.c:52 + lea si, [bx+032h] ; 8d 77 32 ; 0xc317e vgabios.c:2168 + mov byte [es:si], 000h ; 26 c6 04 00 ; 0xc3181 vgabios.c:52 + mov si, 00089h ; be 89 00 ; 0xc3185 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3188 + mov es, ax ; 8e c0 ; 0xc318b + mov al, byte [es:si] ; 26 8a 04 ; 0xc318d + mov dl, al ; 88 c2 ; 0xc3190 vgabios.c:2173 + and dl, 080h ; 80 e2 80 ; 0xc3192 + xor dh, dh ; 30 f6 ; 0xc3195 + mov CL, strict byte 006h ; b1 06 ; 0xc3197 + sar dx, CL ; d3 fa ; 0xc3199 + and AL, strict byte 010h ; 24 10 ; 0xc319b + xor ah, ah ; 30 e4 ; 0xc319d + mov CL, strict byte 004h ; b1 04 ; 0xc319f + sar ax, CL ; d3 f8 ; 0xc31a1 + or ax, dx ; 09 d0 ; 0xc31a3 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc31a5 vgabios.c:2174 + je short 031bbh ; 74 11 ; 0xc31a8 + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc31aa + je short 031b7h ; 74 08 ; 0xc31ad + test ax, ax ; 85 c0 ; 0xc31af + jne short 031bbh ; 75 08 ; 0xc31b1 + mov AL, strict byte 001h ; b0 01 ; 0xc31b3 vgabios.c:2175 + jmp short 031bdh ; eb 06 ; 0xc31b5 + mov AL, strict byte 002h ; b0 02 ; 0xc31b7 vgabios.c:2176 + jmp short 031bdh ; eb 02 ; 0xc31b9 + xor al, al ; 30 c0 ; 0xc31bb vgabios.c:2178 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc31bd vgabios.c:2180 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc31c0 vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc31c3 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc31c6 vgabios.c:2183 + cmp AL, strict byte 00eh ; 3c 0e ; 0xc31c9 + jc short 031edh ; 72 20 ; 0xc31cb + cmp AL, strict byte 012h ; 3c 12 ; 0xc31cd + jnbe short 031edh ; 77 1c ; 0xc31cf + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc31d1 vgabios.c:2184 + test ax, ax ; 85 c0 ; 0xc31d4 + je short 0322fh ; 74 57 ; 0xc31d6 + mov si, ax ; 89 c6 ; 0xc31d8 vgabios.c:2185 + shr si, 1 ; d1 ee ; 0xc31da + shr si, 1 ; d1 ee ; 0xc31dc + mov ax, 04000h ; b8 00 40 ; 0xc31de + xor dx, dx ; 31 d2 ; 0xc31e1 + div si ; f7 f6 ; 0xc31e3 + lea si, [bx+029h] ; 8d 77 29 ; 0xc31e5 + mov byte [es:si], al ; 26 88 04 ; 0xc31e8 vgabios.c:52 + jmp short 0322fh ; eb 42 ; 0xc31eb vgabios.c:2186 + lea si, [bx+029h] ; 8d 77 29 ; 0xc31ed + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc31f0 + cmp AL, strict byte 013h ; 3c 13 ; 0xc31f3 + jne short 03208h ; 75 11 ; 0xc31f5 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc31f7 vgabios.c:52 + mov byte [es:si], 001h ; 26 c6 04 01 ; 0xc31fa + lea si, [bx+027h] ; 8d 77 27 ; 0xc31fe vgabios.c:2188 + mov word [es:si], 00100h ; 26 c7 04 00 01 ; 0xc3201 vgabios.c:62 + jmp short 0322fh ; eb 27 ; 0xc3206 vgabios.c:2189 + cmp AL, strict byte 004h ; 3c 04 ; 0xc3208 + jc short 0322fh ; 72 23 ; 0xc320a + cmp AL, strict byte 006h ; 3c 06 ; 0xc320c + jnbe short 0322fh ; 77 1f ; 0xc320e + cmp word [bp-00ah], strict byte 00000h ; 83 7e f6 00 ; 0xc3210 vgabios.c:2191 + je short 03224h ; 74 0e ; 0xc3214 + mov ax, 04000h ; b8 00 40 ; 0xc3216 vgabios.c:2192 + xor dx, dx ; 31 d2 ; 0xc3219 + div word [bp-00ah] ; f7 76 f6 ; 0xc321b + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc321e vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc3221 + lea si, [bx+027h] ; 8d 77 27 ; 0xc3224 vgabios.c:2193 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc3227 vgabios.c:62 + mov word [es:si], strict word 00004h ; 26 c7 04 04 00 ; 0xc322a + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc322f vgabios.c:2195 + cmp AL, strict byte 006h ; 3c 06 ; 0xc3232 + je short 0323ah ; 74 04 ; 0xc3234 + cmp AL, strict byte 011h ; 3c 11 ; 0xc3236 + jne short 03245h ; 75 0b ; 0xc3238 + lea si, [bx+027h] ; 8d 77 27 ; 0xc323a vgabios.c:2196 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc323d vgabios.c:62 + mov word [es:si], strict word 00002h ; 26 c7 04 02 00 ; 0xc3240 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3245 vgabios.c:2198 + cmp AL, strict byte 004h ; 3c 04 ; 0xc3248 + jc short 032a1h ; 72 55 ; 0xc324a + cmp AL, strict byte 007h ; 3c 07 ; 0xc324c + je short 032a1h ; 74 51 ; 0xc324e + lea si, [bx+02dh] ; 8d 77 2d ; 0xc3250 vgabios.c:2199 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc3253 vgabios.c:52 + mov byte [es:si], 001h ; 26 c6 04 01 ; 0xc3256 + mov si, 00084h ; be 84 00 ; 0xc325a vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc325d + mov es, ax ; 8e c0 ; 0xc3260 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3262 + xor ah, ah ; 30 e4 ; 0xc3265 vgabios.c:48 + inc ax ; 40 ; 0xc3267 + mov si, 00085h ; be 85 00 ; 0xc3268 vgabios.c:47 + mov dl, byte [es:si] ; 26 8a 14 ; 0xc326b + xor dh, dh ; 30 f6 ; 0xc326e vgabios.c:48 + imul dx ; f7 ea ; 0xc3270 + cmp ax, 0015eh ; 3d 5e 01 ; 0xc3272 vgabios.c:2201 + jc short 03285h ; 72 0e ; 0xc3275 + jbe short 0328eh ; 76 15 ; 0xc3277 + cmp ax, 001e0h ; 3d e0 01 ; 0xc3279 + je short 03296h ; 74 18 ; 0xc327c + cmp ax, 00190h ; 3d 90 01 ; 0xc327e + je short 03292h ; 74 0f ; 0xc3281 + jmp short 03296h ; eb 11 ; 0xc3283 + cmp ax, 000c8h ; 3d c8 00 ; 0xc3285 + jne short 03296h ; 75 0c ; 0xc3288 + xor al, al ; 30 c0 ; 0xc328a vgabios.c:2202 + jmp short 03298h ; eb 0a ; 0xc328c + mov AL, strict byte 001h ; b0 01 ; 0xc328e vgabios.c:2203 + jmp short 03298h ; eb 06 ; 0xc3290 + mov AL, strict byte 002h ; b0 02 ; 0xc3292 vgabios.c:2204 + jmp short 03298h ; eb 02 ; 0xc3294 + mov AL, strict byte 003h ; b0 03 ; 0xc3296 vgabios.c:2206 + lea si, [bx+02ah] ; 8d 77 2a ; 0xc3298 vgabios.c:2208 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc329b vgabios.c:52 + mov byte [es:si], al ; 26 88 04 ; 0xc329e + lea di, [bx+033h] ; 8d 7f 33 ; 0xc32a1 vgabios.c:2211 + mov cx, strict word 0000dh ; b9 0d 00 ; 0xc32a4 + xor ax, ax ; 31 c0 ; 0xc32a7 + mov es, [bp-00ch] ; 8e 46 f4 ; 0xc32a9 + jcxz 032b0h ; e3 02 ; 0xc32ac + rep stosb ; f3 aa ; 0xc32ae + lea sp, [bp-006h] ; 8d 66 fa ; 0xc32b0 vgabios.c:2212 + pop di ; 5f ; 0xc32b3 + pop si ; 5e ; 0xc32b4 + pop cx ; 59 ; 0xc32b5 + pop bp ; 5d ; 0xc32b6 + retn ; c3 ; 0xc32b7 + ; disGetNextSymbol 0xc32b8 LB 0x12ac -> off=0x0 cb=0000000000000023 uValue=00000000000c32b8 'biosfn_read_video_state_size2' +biosfn_read_video_state_size2: ; 0xc32b8 LB 0x23 + push dx ; 52 ; 0xc32b8 vgabios.c:2215 + push bp ; 55 ; 0xc32b9 + mov bp, sp ; 89 e5 ; 0xc32ba + mov dx, ax ; 89 c2 ; 0xc32bc + xor ax, ax ; 31 c0 ; 0xc32be vgabios.c:2219 + test dl, 001h ; f6 c2 01 ; 0xc32c0 vgabios.c:2220 + je short 032c8h ; 74 03 ; 0xc32c3 + mov ax, strict word 00046h ; b8 46 00 ; 0xc32c5 vgabios.c:2221 + test dl, 002h ; f6 c2 02 ; 0xc32c8 vgabios.c:2223 + je short 032d0h ; 74 03 ; 0xc32cb + add ax, strict word 0002ah ; 05 2a 00 ; 0xc32cd vgabios.c:2224 + test dl, 004h ; f6 c2 04 ; 0xc32d0 vgabios.c:2226 + je short 032d8h ; 74 03 ; 0xc32d3 + add ax, 00304h ; 05 04 03 ; 0xc32d5 vgabios.c:2227 + pop bp ; 5d ; 0xc32d8 vgabios.c:2230 + pop dx ; 5a ; 0xc32d9 + retn ; c3 ; 0xc32da + ; disGetNextSymbol 0xc32db LB 0x1289 -> off=0x0 cb=000000000000001b uValue=00000000000c32db 'vga_get_video_state_size' +vga_get_video_state_size: ; 0xc32db LB 0x1b + push bp ; 55 ; 0xc32db vgabios.c:2232 + mov bp, sp ; 89 e5 ; 0xc32dc + push bx ; 53 ; 0xc32de + push cx ; 51 ; 0xc32df + mov bx, dx ; 89 d3 ; 0xc32e0 + call 032b8h ; e8 d3 ff ; 0xc32e2 vgabios.c:2235 + add ax, strict word 0003fh ; 05 3f 00 ; 0xc32e5 + mov CL, strict byte 006h ; b1 06 ; 0xc32e8 + shr ax, CL ; d3 e8 ; 0xc32ea + mov word [ss:bx], ax ; 36 89 07 ; 0xc32ec + lea sp, [bp-004h] ; 8d 66 fc ; 0xc32ef vgabios.c:2236 + pop cx ; 59 ; 0xc32f2 + pop bx ; 5b ; 0xc32f3 + pop bp ; 5d ; 0xc32f4 + retn ; c3 ; 0xc32f5 + ; disGetNextSymbol 0xc32f6 LB 0x126e -> off=0x0 cb=00000000000002d8 uValue=00000000000c32f6 'biosfn_save_video_state' +biosfn_save_video_state: ; 0xc32f6 LB 0x2d8 + push bp ; 55 ; 0xc32f6 vgabios.c:2238 + mov bp, sp ; 89 e5 ; 0xc32f7 + push cx ; 51 ; 0xc32f9 + push si ; 56 ; 0xc32fa + push di ; 57 ; 0xc32fb + push ax ; 50 ; 0xc32fc + push ax ; 50 ; 0xc32fd + push ax ; 50 ; 0xc32fe + mov cx, dx ; 89 d1 ; 0xc32ff + mov si, strict word 00063h ; be 63 00 ; 0xc3301 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3304 + mov es, ax ; 8e c0 ; 0xc3307 + mov di, word [es:si] ; 26 8b 3c ; 0xc3309 + mov si, di ; 89 fe ; 0xc330c vgabios.c:58 + test byte [bp-00ch], 001h ; f6 46 f4 01 ; 0xc330e vgabios.c:2243 + je short 0337ah ; 74 66 ; 0xc3312 + mov dx, 003c4h ; ba c4 03 ; 0xc3314 vgabios.c:2244 + in AL, DX ; ec ; 0xc3317 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3318 + mov es, cx ; 8e c1 ; 0xc331a vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc331c + inc bx ; 43 ; 0xc331f vgabios.c:2244 + mov dx, di ; 89 fa ; 0xc3320 + in AL, DX ; ec ; 0xc3322 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3323 + mov byte [es:bx], al ; 26 88 07 ; 0xc3325 vgabios.c:52 + inc bx ; 43 ; 0xc3328 vgabios.c:2245 + mov dx, 003ceh ; ba ce 03 ; 0xc3329 + in AL, DX ; ec ; 0xc332c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc332d + mov byte [es:bx], al ; 26 88 07 ; 0xc332f vgabios.c:52 + inc bx ; 43 ; 0xc3332 vgabios.c:2246 + mov dx, 003dah ; ba da 03 ; 0xc3333 + in AL, DX ; ec ; 0xc3336 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3337 + mov dx, 003c0h ; ba c0 03 ; 0xc3339 vgabios.c:2248 + in AL, DX ; ec ; 0xc333c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc333d + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc333f + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc3342 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3345 + inc bx ; 43 ; 0xc3348 vgabios.c:2249 + mov dx, 003cah ; ba ca 03 ; 0xc3349 + in AL, DX ; ec ; 0xc334c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc334d + mov byte [es:bx], al ; 26 88 07 ; 0xc334f vgabios.c:52 + mov ax, strict word 00001h ; b8 01 00 ; 0xc3352 vgabios.c:2252 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc3355 + add bx, ax ; 01 c3 ; 0xc3358 vgabios.c:2250 + jmp short 03362h ; eb 06 ; 0xc335a + cmp word [bp-008h], strict byte 00004h ; 83 7e f8 04 ; 0xc335c + jnbe short 0337dh ; 77 1b ; 0xc3360 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3362 vgabios.c:2253 + mov dx, 003c4h ; ba c4 03 ; 0xc3365 + out DX, AL ; ee ; 0xc3368 + mov dx, 003c5h ; ba c5 03 ; 0xc3369 vgabios.c:2254 + in AL, DX ; ec ; 0xc336c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc336d + mov es, cx ; 8e c1 ; 0xc336f vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3371 + inc bx ; 43 ; 0xc3374 vgabios.c:2254 + inc word [bp-008h] ; ff 46 f8 ; 0xc3375 vgabios.c:2255 + jmp short 0335ch ; eb e2 ; 0xc3378 + jmp near 0342ah ; e9 ad 00 ; 0xc337a + xor al, al ; 30 c0 ; 0xc337d vgabios.c:2256 + mov dx, 003c4h ; ba c4 03 ; 0xc337f + out DX, AL ; ee ; 0xc3382 + mov dx, 003c5h ; ba c5 03 ; 0xc3383 vgabios.c:2257 + in AL, DX ; ec ; 0xc3386 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3387 + mov es, cx ; 8e c1 ; 0xc3389 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc338b + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc338e vgabios.c:2259 + inc bx ; 43 ; 0xc3393 vgabios.c:2257 + jmp short 0339ch ; eb 06 ; 0xc3394 + cmp word [bp-008h], strict byte 00018h ; 83 7e f8 18 ; 0xc3396 + jnbe short 033b3h ; 77 17 ; 0xc339a + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc339c vgabios.c:2260 + mov dx, si ; 89 f2 ; 0xc339f + out DX, AL ; ee ; 0xc33a1 + lea dx, [si+001h] ; 8d 54 01 ; 0xc33a2 vgabios.c:2261 + in AL, DX ; ec ; 0xc33a5 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc33a6 + mov es, cx ; 8e c1 ; 0xc33a8 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc33aa + inc bx ; 43 ; 0xc33ad vgabios.c:2261 + inc word [bp-008h] ; ff 46 f8 ; 0xc33ae vgabios.c:2262 + jmp short 03396h ; eb e3 ; 0xc33b1 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc33b3 vgabios.c:2264 + jmp short 033c0h ; eb 06 ; 0xc33b8 + cmp word [bp-008h], strict byte 00013h ; 83 7e f8 13 ; 0xc33ba + jnbe short 033e4h ; 77 24 ; 0xc33be + mov dx, 003dah ; ba da 03 ; 0xc33c0 vgabios.c:2265 + in AL, DX ; ec ; 0xc33c3 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc33c4 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc33c6 vgabios.c:2266 + and ax, strict word 00020h ; 25 20 00 ; 0xc33c9 + or ax, word [bp-008h] ; 0b 46 f8 ; 0xc33cc + mov dx, 003c0h ; ba c0 03 ; 0xc33cf + out DX, AL ; ee ; 0xc33d2 + mov dx, 003c1h ; ba c1 03 ; 0xc33d3 vgabios.c:2267 + in AL, DX ; ec ; 0xc33d6 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc33d7 + mov es, cx ; 8e c1 ; 0xc33d9 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc33db + inc bx ; 43 ; 0xc33de vgabios.c:2267 + inc word [bp-008h] ; ff 46 f8 ; 0xc33df vgabios.c:2268 + jmp short 033bah ; eb d6 ; 0xc33e2 + mov dx, 003dah ; ba da 03 ; 0xc33e4 vgabios.c:2269 + in AL, DX ; ec ; 0xc33e7 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc33e8 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc33ea vgabios.c:2271 + jmp short 033f7h ; eb 06 ; 0xc33ef + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc33f1 + jnbe short 0340fh ; 77 18 ; 0xc33f5 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc33f7 vgabios.c:2272 + mov dx, 003ceh ; ba ce 03 ; 0xc33fa + out DX, AL ; ee ; 0xc33fd + mov dx, 003cfh ; ba cf 03 ; 0xc33fe vgabios.c:2273 + in AL, DX ; ec ; 0xc3401 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3402 + mov es, cx ; 8e c1 ; 0xc3404 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3406 + inc bx ; 43 ; 0xc3409 vgabios.c:2273 + inc word [bp-008h] ; ff 46 f8 ; 0xc340a vgabios.c:2274 + jmp short 033f1h ; eb e2 ; 0xc340d + mov es, cx ; 8e c1 ; 0xc340f vgabios.c:62 + mov word [es:bx], si ; 26 89 37 ; 0xc3411 + inc bx ; 43 ; 0xc3414 vgabios.c:2276 + inc bx ; 43 ; 0xc3415 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc3416 vgabios.c:52 + inc bx ; 43 ; 0xc341a vgabios.c:2279 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc341b vgabios.c:52 + inc bx ; 43 ; 0xc341f vgabios.c:2280 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc3420 vgabios.c:52 + inc bx ; 43 ; 0xc3424 vgabios.c:2281 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc3425 vgabios.c:52 + inc bx ; 43 ; 0xc3429 vgabios.c:2282 + test byte [bp-00ch], 002h ; f6 46 f4 02 ; 0xc342a vgabios.c:2284 + jne short 03433h ; 75 03 ; 0xc342e + jmp near 03572h ; e9 3f 01 ; 0xc3430 + mov si, strict word 00049h ; be 49 00 ; 0xc3433 vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3436 + mov es, ax ; 8e c0 ; 0xc3439 + mov al, byte [es:si] ; 26 8a 04 ; 0xc343b + mov es, cx ; 8e c1 ; 0xc343e vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3440 + inc bx ; 43 ; 0xc3443 vgabios.c:2285 + mov si, strict word 0004ah ; be 4a 00 ; 0xc3444 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3447 + mov es, ax ; 8e c0 ; 0xc344a + mov ax, word [es:si] ; 26 8b 04 ; 0xc344c + mov es, cx ; 8e c1 ; 0xc344f vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3451 + inc bx ; 43 ; 0xc3454 vgabios.c:2286 + inc bx ; 43 ; 0xc3455 + mov si, strict word 0004ch ; be 4c 00 ; 0xc3456 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3459 + mov es, ax ; 8e c0 ; 0xc345c + mov ax, word [es:si] ; 26 8b 04 ; 0xc345e + mov es, cx ; 8e c1 ; 0xc3461 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3463 + inc bx ; 43 ; 0xc3466 vgabios.c:2287 + inc bx ; 43 ; 0xc3467 + mov si, strict word 00063h ; be 63 00 ; 0xc3468 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc346b + mov es, ax ; 8e c0 ; 0xc346e + mov ax, word [es:si] ; 26 8b 04 ; 0xc3470 + mov es, cx ; 8e c1 ; 0xc3473 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3475 + inc bx ; 43 ; 0xc3478 vgabios.c:2288 + inc bx ; 43 ; 0xc3479 + mov si, 00084h ; be 84 00 ; 0xc347a vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc347d + mov es, ax ; 8e c0 ; 0xc3480 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3482 + mov es, cx ; 8e c1 ; 0xc3485 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3487 + inc bx ; 43 ; 0xc348a vgabios.c:2289 + mov si, 00085h ; be 85 00 ; 0xc348b vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc348e + mov es, ax ; 8e c0 ; 0xc3491 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3493 + mov es, cx ; 8e c1 ; 0xc3496 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3498 + inc bx ; 43 ; 0xc349b vgabios.c:2290 + inc bx ; 43 ; 0xc349c + mov si, 00087h ; be 87 00 ; 0xc349d vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc34a0 + mov es, ax ; 8e c0 ; 0xc34a3 + mov al, byte [es:si] ; 26 8a 04 ; 0xc34a5 + mov es, cx ; 8e c1 ; 0xc34a8 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc34aa + inc bx ; 43 ; 0xc34ad vgabios.c:2291 + mov si, 00088h ; be 88 00 ; 0xc34ae vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc34b1 + mov es, ax ; 8e c0 ; 0xc34b4 + mov al, byte [es:si] ; 26 8a 04 ; 0xc34b6 + mov es, cx ; 8e c1 ; 0xc34b9 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc34bb + inc bx ; 43 ; 0xc34be vgabios.c:2292 + mov si, 00089h ; be 89 00 ; 0xc34bf vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc34c2 + mov es, ax ; 8e c0 ; 0xc34c5 + mov al, byte [es:si] ; 26 8a 04 ; 0xc34c7 + mov es, cx ; 8e c1 ; 0xc34ca vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc34cc + inc bx ; 43 ; 0xc34cf vgabios.c:2293 + mov si, strict word 00060h ; be 60 00 ; 0xc34d0 vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc34d3 + mov es, ax ; 8e c0 ; 0xc34d6 + mov ax, word [es:si] ; 26 8b 04 ; 0xc34d8 + mov es, cx ; 8e c1 ; 0xc34db vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc34dd + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc34e0 vgabios.c:2295 + inc bx ; 43 ; 0xc34e5 vgabios.c:2294 + inc bx ; 43 ; 0xc34e6 + jmp short 034efh ; eb 06 ; 0xc34e7 + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc34e9 + jnc short 0350bh ; 73 1c ; 0xc34ed + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc34ef vgabios.c:2296 + sal si, 1 ; d1 e6 ; 0xc34f2 + add si, strict byte 00050h ; 83 c6 50 ; 0xc34f4 + mov ax, strict word 00040h ; b8 40 00 ; 0xc34f7 vgabios.c:57 + mov es, ax ; 8e c0 ; 0xc34fa + mov ax, word [es:si] ; 26 8b 04 ; 0xc34fc + mov es, cx ; 8e c1 ; 0xc34ff vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3501 + inc bx ; 43 ; 0xc3504 vgabios.c:2297 + inc bx ; 43 ; 0xc3505 + inc word [bp-008h] ; ff 46 f8 ; 0xc3506 vgabios.c:2298 + jmp short 034e9h ; eb de ; 0xc3509 + mov si, strict word 0004eh ; be 4e 00 ; 0xc350b vgabios.c:57 + mov ax, strict word 00040h ; b8 40 00 ; 0xc350e + mov es, ax ; 8e c0 ; 0xc3511 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3513 + mov es, cx ; 8e c1 ; 0xc3516 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc3518 + inc bx ; 43 ; 0xc351b vgabios.c:2299 + inc bx ; 43 ; 0xc351c + mov si, strict word 00062h ; be 62 00 ; 0xc351d vgabios.c:47 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3520 + mov es, ax ; 8e c0 ; 0xc3523 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3525 + mov es, cx ; 8e c1 ; 0xc3528 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc352a + inc bx ; 43 ; 0xc352d vgabios.c:2300 + mov si, strict word 0007ch ; be 7c 00 ; 0xc352e vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc3531 + mov es, ax ; 8e c0 ; 0xc3533 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3535 + mov es, cx ; 8e c1 ; 0xc3538 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc353a + inc bx ; 43 ; 0xc353d vgabios.c:2302 + inc bx ; 43 ; 0xc353e + mov si, strict word 0007eh ; be 7e 00 ; 0xc353f vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc3542 + mov es, ax ; 8e c0 ; 0xc3544 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3546 + mov es, cx ; 8e c1 ; 0xc3549 vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc354b + inc bx ; 43 ; 0xc354e vgabios.c:2303 + inc bx ; 43 ; 0xc354f + mov si, 0010ch ; be 0c 01 ; 0xc3550 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc3553 + mov es, ax ; 8e c0 ; 0xc3555 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3557 + mov es, cx ; 8e c1 ; 0xc355a vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc355c + inc bx ; 43 ; 0xc355f vgabios.c:2304 + inc bx ; 43 ; 0xc3560 + mov si, 0010eh ; be 0e 01 ; 0xc3561 vgabios.c:57 + xor ax, ax ; 31 c0 ; 0xc3564 + mov es, ax ; 8e c0 ; 0xc3566 + mov ax, word [es:si] ; 26 8b 04 ; 0xc3568 + mov es, cx ; 8e c1 ; 0xc356b vgabios.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc356d + inc bx ; 43 ; 0xc3570 vgabios.c:2305 + inc bx ; 43 ; 0xc3571 + test byte [bp-00ch], 004h ; f6 46 f4 04 ; 0xc3572 vgabios.c:2307 + je short 035c4h ; 74 4c ; 0xc3576 + mov dx, 003c7h ; ba c7 03 ; 0xc3578 vgabios.c:2309 + in AL, DX ; ec ; 0xc357b + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc357c + mov es, cx ; 8e c1 ; 0xc357e vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc3580 + inc bx ; 43 ; 0xc3583 vgabios.c:2309 + mov dx, 003c8h ; ba c8 03 ; 0xc3584 + in AL, DX ; ec ; 0xc3587 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3588 + mov byte [es:bx], al ; 26 88 07 ; 0xc358a vgabios.c:52 + inc bx ; 43 ; 0xc358d vgabios.c:2310 + mov dx, 003c6h ; ba c6 03 ; 0xc358e + in AL, DX ; ec ; 0xc3591 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3592 + mov byte [es:bx], al ; 26 88 07 ; 0xc3594 vgabios.c:52 + inc bx ; 43 ; 0xc3597 vgabios.c:2311 + xor al, al ; 30 c0 ; 0xc3598 + mov dx, 003c8h ; ba c8 03 ; 0xc359a + out DX, AL ; ee ; 0xc359d + xor ah, ah ; 30 e4 ; 0xc359e vgabios.c:2314 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc35a0 + jmp short 035ach ; eb 07 ; 0xc35a3 + cmp word [bp-008h], 00300h ; 81 7e f8 00 03 ; 0xc35a5 + jnc short 035bdh ; 73 11 ; 0xc35aa + mov dx, 003c9h ; ba c9 03 ; 0xc35ac vgabios.c:2315 + in AL, DX ; ec ; 0xc35af + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc35b0 + mov es, cx ; 8e c1 ; 0xc35b2 vgabios.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc35b4 + inc bx ; 43 ; 0xc35b7 vgabios.c:2315 + inc word [bp-008h] ; ff 46 f8 ; 0xc35b8 vgabios.c:2316 + jmp short 035a5h ; eb e8 ; 0xc35bb + mov es, cx ; 8e c1 ; 0xc35bd vgabios.c:52 + mov byte [es:bx], 000h ; 26 c6 07 00 ; 0xc35bf + inc bx ; 43 ; 0xc35c3 vgabios.c:2317 + mov ax, bx ; 89 d8 ; 0xc35c4 vgabios.c:2320 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc35c6 + pop di ; 5f ; 0xc35c9 + pop si ; 5e ; 0xc35ca + pop cx ; 59 ; 0xc35cb + pop bp ; 5d ; 0xc35cc + retn ; c3 ; 0xc35cd + ; disGetNextSymbol 0xc35ce LB 0xf96 -> off=0x0 cb=00000000000002ba uValue=00000000000c35ce 'biosfn_restore_video_state' +biosfn_restore_video_state: ; 0xc35ce LB 0x2ba + push bp ; 55 ; 0xc35ce vgabios.c:2322 + mov bp, sp ; 89 e5 ; 0xc35cf + push cx ; 51 ; 0xc35d1 + push si ; 56 ; 0xc35d2 + push di ; 57 ; 0xc35d3 + sub sp, strict byte 00008h ; 83 ec 08 ; 0xc35d4 + push ax ; 50 ; 0xc35d7 + mov cx, dx ; 89 d1 ; 0xc35d8 + test byte [bp-010h], 001h ; f6 46 f0 01 ; 0xc35da vgabios.c:2326 + je short 03654h ; 74 74 ; 0xc35de + mov dx, 003dah ; ba da 03 ; 0xc35e0 vgabios.c:2328 + in AL, DX ; ec ; 0xc35e3 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc35e4 + lea si, [bx+040h] ; 8d 77 40 ; 0xc35e6 vgabios.c:2330 + mov es, cx ; 8e c1 ; 0xc35e9 vgabios.c:57 + mov ax, word [es:si] ; 26 8b 04 ; 0xc35eb + mov word [bp-00ch], ax ; 89 46 f4 ; 0xc35ee vgabios.c:58 + mov si, bx ; 89 de ; 0xc35f1 vgabios.c:2331 + mov word [bp-008h], strict word 00001h ; c7 46 f8 01 00 ; 0xc35f3 vgabios.c:2334 + add bx, strict byte 00005h ; 83 c3 05 ; 0xc35f8 vgabios.c:2332 + jmp short 03603h ; eb 06 ; 0xc35fb + cmp word [bp-008h], strict byte 00004h ; 83 7e f8 04 ; 0xc35fd + jnbe short 03619h ; 77 16 ; 0xc3601 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3603 vgabios.c:2335 + mov dx, 003c4h ; ba c4 03 ; 0xc3606 + out DX, AL ; ee ; 0xc3609 + mov es, cx ; 8e c1 ; 0xc360a vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc360c + mov dx, 003c5h ; ba c5 03 ; 0xc360f vgabios.c:48 + out DX, AL ; ee ; 0xc3612 + inc bx ; 43 ; 0xc3613 vgabios.c:2336 + inc word [bp-008h] ; ff 46 f8 ; 0xc3614 vgabios.c:2337 + jmp short 035fdh ; eb e4 ; 0xc3617 + xor al, al ; 30 c0 ; 0xc3619 vgabios.c:2338 + mov dx, 003c4h ; ba c4 03 ; 0xc361b + out DX, AL ; ee ; 0xc361e + mov es, cx ; 8e c1 ; 0xc361f vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3621 + mov dx, 003c5h ; ba c5 03 ; 0xc3624 vgabios.c:48 + out DX, AL ; ee ; 0xc3627 + inc bx ; 43 ; 0xc3628 vgabios.c:2339 + mov dx, 003cch ; ba cc 03 ; 0xc3629 + in AL, DX ; ec ; 0xc362c + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc362d + and AL, strict byte 0feh ; 24 fe ; 0xc362f + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc3631 + cmp word [bp-00ch], 003d4h ; 81 7e f4 d4 03 ; 0xc3634 vgabios.c:2343 + jne short 0363fh ; 75 04 ; 0xc3639 + or byte [bp-00eh], 001h ; 80 4e f2 01 ; 0xc363b vgabios.c:2344 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc363f vgabios.c:2345 + mov dx, 003c2h ; ba c2 03 ; 0xc3642 + out DX, AL ; ee ; 0xc3645 + mov ax, strict word 00011h ; b8 11 00 ; 0xc3646 vgabios.c:2348 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc3649 + out DX, ax ; ef ; 0xc364c + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc364d vgabios.c:2350 + jmp short 0365dh ; eb 09 ; 0xc3652 + jmp near 03717h ; e9 c0 00 ; 0xc3654 + cmp word [bp-008h], strict byte 00018h ; 83 7e f8 18 ; 0xc3657 + jnbe short 03677h ; 77 1a ; 0xc365b + cmp word [bp-008h], strict byte 00011h ; 83 7e f8 11 ; 0xc365d vgabios.c:2351 + je short 03671h ; 74 0e ; 0xc3661 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc3663 vgabios.c:2352 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc3666 + out DX, AL ; ee ; 0xc3669 + mov es, cx ; 8e c1 ; 0xc366a vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc366c + inc dx ; 42 ; 0xc366f vgabios.c:48 + out DX, AL ; ee ; 0xc3670 + inc bx ; 43 ; 0xc3671 vgabios.c:2355 + inc word [bp-008h] ; ff 46 f8 ; 0xc3672 vgabios.c:2356 + jmp short 03657h ; eb e0 ; 0xc3675 + mov AL, strict byte 011h ; b0 11 ; 0xc3677 vgabios.c:2358 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc3679 + out DX, AL ; ee ; 0xc367c + lea di, [word bx-00007h] ; 8d bf f9 ff ; 0xc367d vgabios.c:2359 + mov es, cx ; 8e c1 ; 0xc3681 vgabios.c:47 + mov al, byte [es:di] ; 26 8a 05 ; 0xc3683 + inc dx ; 42 ; 0xc3686 vgabios.c:48 + out DX, AL ; ee ; 0xc3687 + lea di, [si+003h] ; 8d 7c 03 ; 0xc3688 vgabios.c:2362 + mov dl, byte [es:di] ; 26 8a 15 ; 0xc368b vgabios.c:47 + xor dh, dh ; 30 f6 ; 0xc368e vgabios.c:48 + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc3690 + mov dx, 003dah ; ba da 03 ; 0xc3693 vgabios.c:2363 + in AL, DX ; ec ; 0xc3696 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3697 + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc3699 vgabios.c:2364 + jmp short 036a6h ; eb 06 ; 0xc369e + cmp word [bp-008h], strict byte 00013h ; 83 7e f8 13 ; 0xc36a0 + jnbe short 036bfh ; 77 19 ; 0xc36a4 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc36a6 vgabios.c:2365 + and ax, strict word 00020h ; 25 20 00 ; 0xc36a9 + or ax, word [bp-008h] ; 0b 46 f8 ; 0xc36ac + mov dx, 003c0h ; ba c0 03 ; 0xc36af + out DX, AL ; ee ; 0xc36b2 + mov es, cx ; 8e c1 ; 0xc36b3 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc36b5 + out DX, AL ; ee ; 0xc36b8 vgabios.c:48 + inc bx ; 43 ; 0xc36b9 vgabios.c:2366 + inc word [bp-008h] ; ff 46 f8 ; 0xc36ba vgabios.c:2367 + jmp short 036a0h ; eb e1 ; 0xc36bd + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc36bf vgabios.c:2368 + mov dx, 003c0h ; ba c0 03 ; 0xc36c2 + out DX, AL ; ee ; 0xc36c5 + mov dx, 003dah ; ba da 03 ; 0xc36c6 vgabios.c:2369 + in AL, DX ; ec ; 0xc36c9 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc36ca + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc36cc vgabios.c:2371 + jmp short 036d9h ; eb 06 ; 0xc36d1 + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc36d3 + jnbe short 036efh ; 77 16 ; 0xc36d7 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc36d9 vgabios.c:2372 + mov dx, 003ceh ; ba ce 03 ; 0xc36dc + out DX, AL ; ee ; 0xc36df + mov es, cx ; 8e c1 ; 0xc36e0 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc36e2 + mov dx, 003cfh ; ba cf 03 ; 0xc36e5 vgabios.c:48 + out DX, AL ; ee ; 0xc36e8 + inc bx ; 43 ; 0xc36e9 vgabios.c:2373 + inc word [bp-008h] ; ff 46 f8 ; 0xc36ea vgabios.c:2374 + jmp short 036d3h ; eb e4 ; 0xc36ed + add bx, strict byte 00006h ; 83 c3 06 ; 0xc36ef vgabios.c:2375 + mov es, cx ; 8e c1 ; 0xc36f2 vgabios.c:47 + mov al, byte [es:si] ; 26 8a 04 ; 0xc36f4 + mov dx, 003c4h ; ba c4 03 ; 0xc36f7 vgabios.c:48 + out DX, AL ; ee ; 0xc36fa + inc si ; 46 ; 0xc36fb vgabios.c:2378 + mov al, byte [es:si] ; 26 8a 04 ; 0xc36fc vgabios.c:47 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc36ff vgabios.c:48 + out DX, AL ; ee ; 0xc3702 + inc si ; 46 ; 0xc3703 vgabios.c:2379 + mov al, byte [es:si] ; 26 8a 04 ; 0xc3704 vgabios.c:47 + mov dx, 003ceh ; ba ce 03 ; 0xc3707 vgabios.c:48 + out DX, AL ; ee ; 0xc370a + inc si ; 46 ; 0xc370b vgabios.c:2380 + inc si ; 46 ; 0xc370c + mov al, byte [es:si] ; 26 8a 04 ; 0xc370d vgabios.c:47 + mov dx, word [bp-00ch] ; 8b 56 f4 ; 0xc3710 vgabios.c:48 + add dx, strict byte 00006h ; 83 c2 06 ; 0xc3713 + out DX, AL ; ee ; 0xc3716 + test byte [bp-010h], 002h ; f6 46 f0 02 ; 0xc3717 vgabios.c:2384 + jne short 03720h ; 75 03 ; 0xc371b + jmp near 0383bh ; e9 1b 01 ; 0xc371d + mov es, cx ; 8e c1 ; 0xc3720 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3722 + mov si, strict word 00049h ; be 49 00 ; 0xc3725 vgabios.c:52 + mov dx, strict word 00040h ; ba 40 00 ; 0xc3728 + mov es, dx ; 8e c2 ; 0xc372b + mov byte [es:si], al ; 26 88 04 ; 0xc372d + inc bx ; 43 ; 0xc3730 vgabios.c:2385 + mov es, cx ; 8e c1 ; 0xc3731 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3733 + mov si, strict word 0004ah ; be 4a 00 ; 0xc3736 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3739 + mov word [es:si], ax ; 26 89 04 ; 0xc373b + inc bx ; 43 ; 0xc373e vgabios.c:2386 + inc bx ; 43 ; 0xc373f + mov es, cx ; 8e c1 ; 0xc3740 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3742 + mov si, strict word 0004ch ; be 4c 00 ; 0xc3745 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3748 + mov word [es:si], ax ; 26 89 04 ; 0xc374a + inc bx ; 43 ; 0xc374d vgabios.c:2387 + inc bx ; 43 ; 0xc374e + mov es, cx ; 8e c1 ; 0xc374f vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3751 + mov si, strict word 00063h ; be 63 00 ; 0xc3754 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3757 + mov word [es:si], ax ; 26 89 04 ; 0xc3759 + inc bx ; 43 ; 0xc375c vgabios.c:2388 + inc bx ; 43 ; 0xc375d + mov es, cx ; 8e c1 ; 0xc375e vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3760 + mov si, 00084h ; be 84 00 ; 0xc3763 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc3766 + mov byte [es:si], al ; 26 88 04 ; 0xc3768 + inc bx ; 43 ; 0xc376b vgabios.c:2389 + mov es, cx ; 8e c1 ; 0xc376c vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc376e + mov si, 00085h ; be 85 00 ; 0xc3771 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3774 + mov word [es:si], ax ; 26 89 04 ; 0xc3776 + inc bx ; 43 ; 0xc3779 vgabios.c:2390 + inc bx ; 43 ; 0xc377a + mov es, cx ; 8e c1 ; 0xc377b vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc377d + mov si, 00087h ; be 87 00 ; 0xc3780 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc3783 + mov byte [es:si], al ; 26 88 04 ; 0xc3785 + inc bx ; 43 ; 0xc3788 vgabios.c:2391 + mov es, cx ; 8e c1 ; 0xc3789 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc378b + mov si, 00088h ; be 88 00 ; 0xc378e vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc3791 + mov byte [es:si], al ; 26 88 04 ; 0xc3793 + inc bx ; 43 ; 0xc3796 vgabios.c:2392 + mov es, cx ; 8e c1 ; 0xc3797 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3799 + mov si, 00089h ; be 89 00 ; 0xc379c vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc379f + mov byte [es:si], al ; 26 88 04 ; 0xc37a1 + inc bx ; 43 ; 0xc37a4 vgabios.c:2393 + mov es, cx ; 8e c1 ; 0xc37a5 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc37a7 + mov si, strict word 00060h ; be 60 00 ; 0xc37aa vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc37ad + mov word [es:si], ax ; 26 89 04 ; 0xc37af + mov word [bp-008h], strict word 00000h ; c7 46 f8 00 00 ; 0xc37b2 vgabios.c:2395 + inc bx ; 43 ; 0xc37b7 vgabios.c:2394 + inc bx ; 43 ; 0xc37b8 + jmp short 037c1h ; eb 06 ; 0xc37b9 + cmp word [bp-008h], strict byte 00008h ; 83 7e f8 08 ; 0xc37bb + jnc short 037ddh ; 73 1c ; 0xc37bf + mov es, cx ; 8e c1 ; 0xc37c1 vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc37c3 + mov si, word [bp-008h] ; 8b 76 f8 ; 0xc37c6 vgabios.c:58 + sal si, 1 ; d1 e6 ; 0xc37c9 + add si, strict byte 00050h ; 83 c6 50 ; 0xc37cb + mov dx, strict word 00040h ; ba 40 00 ; 0xc37ce vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc37d1 + mov word [es:si], ax ; 26 89 04 ; 0xc37d3 + inc bx ; 43 ; 0xc37d6 vgabios.c:2397 + inc bx ; 43 ; 0xc37d7 + inc word [bp-008h] ; ff 46 f8 ; 0xc37d8 vgabios.c:2398 + jmp short 037bbh ; eb de ; 0xc37db + mov es, cx ; 8e c1 ; 0xc37dd vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc37df + mov si, strict word 0004eh ; be 4e 00 ; 0xc37e2 vgabios.c:62 + mov dx, strict word 00040h ; ba 40 00 ; 0xc37e5 + mov es, dx ; 8e c2 ; 0xc37e8 + mov word [es:si], ax ; 26 89 04 ; 0xc37ea + inc bx ; 43 ; 0xc37ed vgabios.c:2399 + inc bx ; 43 ; 0xc37ee + mov es, cx ; 8e c1 ; 0xc37ef vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc37f1 + mov si, strict word 00062h ; be 62 00 ; 0xc37f4 vgabios.c:52 + mov es, dx ; 8e c2 ; 0xc37f7 + mov byte [es:si], al ; 26 88 04 ; 0xc37f9 + inc bx ; 43 ; 0xc37fc vgabios.c:2400 + mov es, cx ; 8e c1 ; 0xc37fd vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc37ff + mov si, strict word 0007ch ; be 7c 00 ; 0xc3802 vgabios.c:62 + xor dx, dx ; 31 d2 ; 0xc3805 + mov es, dx ; 8e c2 ; 0xc3807 + mov word [es:si], ax ; 26 89 04 ; 0xc3809 + inc bx ; 43 ; 0xc380c vgabios.c:2402 + inc bx ; 43 ; 0xc380d + mov es, cx ; 8e c1 ; 0xc380e vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc3810 + mov si, strict word 0007eh ; be 7e 00 ; 0xc3813 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3816 + mov word [es:si], ax ; 26 89 04 ; 0xc3818 + inc bx ; 43 ; 0xc381b vgabios.c:2403 + inc bx ; 43 ; 0xc381c + mov es, cx ; 8e c1 ; 0xc381d vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc381f + mov si, 0010ch ; be 0c 01 ; 0xc3822 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3825 + mov word [es:si], ax ; 26 89 04 ; 0xc3827 + inc bx ; 43 ; 0xc382a vgabios.c:2404 + inc bx ; 43 ; 0xc382b + mov es, cx ; 8e c1 ; 0xc382c vgabios.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc382e + mov si, 0010eh ; be 0e 01 ; 0xc3831 vgabios.c:62 + mov es, dx ; 8e c2 ; 0xc3834 + mov word [es:si], ax ; 26 89 04 ; 0xc3836 + inc bx ; 43 ; 0xc3839 vgabios.c:2405 + inc bx ; 43 ; 0xc383a + test byte [bp-010h], 004h ; f6 46 f0 04 ; 0xc383b vgabios.c:2407 + je short 0387eh ; 74 3d ; 0xc383f + inc bx ; 43 ; 0xc3841 vgabios.c:2408 + mov es, cx ; 8e c1 ; 0xc3842 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3844 + xor ah, ah ; 30 e4 ; 0xc3847 vgabios.c:48 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc3849 + inc bx ; 43 ; 0xc384c vgabios.c:2409 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc384d vgabios.c:47 + mov dx, 003c6h ; ba c6 03 ; 0xc3850 vgabios.c:48 + out DX, AL ; ee ; 0xc3853 + inc bx ; 43 ; 0xc3854 vgabios.c:2410 + xor al, al ; 30 c0 ; 0xc3855 + mov dx, 003c8h ; ba c8 03 ; 0xc3857 + out DX, AL ; ee ; 0xc385a + mov word [bp-008h], ax ; 89 46 f8 ; 0xc385b vgabios.c:2413 + jmp short 03867h ; eb 07 ; 0xc385e + cmp word [bp-008h], 00300h ; 81 7e f8 00 03 ; 0xc3860 + jnc short 03876h ; 73 0f ; 0xc3865 + mov es, cx ; 8e c1 ; 0xc3867 vgabios.c:47 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc3869 + mov dx, 003c9h ; ba c9 03 ; 0xc386c vgabios.c:48 + out DX, AL ; ee ; 0xc386f + inc bx ; 43 ; 0xc3870 vgabios.c:2414 + inc word [bp-008h] ; ff 46 f8 ; 0xc3871 vgabios.c:2415 + jmp short 03860h ; eb ea ; 0xc3874 + inc bx ; 43 ; 0xc3876 vgabios.c:2416 + mov al, byte [bp-00eh] ; 8a 46 f2 ; 0xc3877 + mov dx, 003c8h ; ba c8 03 ; 0xc387a + out DX, AL ; ee ; 0xc387d + mov ax, bx ; 89 d8 ; 0xc387e vgabios.c:2420 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc3880 + pop di ; 5f ; 0xc3883 + pop si ; 5e ; 0xc3884 + pop cx ; 59 ; 0xc3885 + pop bp ; 5d ; 0xc3886 + retn ; c3 ; 0xc3887 + ; disGetNextSymbol 0xc3888 LB 0xcdc -> off=0x0 cb=000000000000002b uValue=00000000000c3888 'find_vga_entry' +find_vga_entry: ; 0xc3888 LB 0x2b + push bx ; 53 ; 0xc3888 vgabios.c:2429 + push cx ; 51 ; 0xc3889 + push dx ; 52 ; 0xc388a + push bp ; 55 ; 0xc388b + mov bp, sp ; 89 e5 ; 0xc388c + mov dl, al ; 88 c2 ; 0xc388e + mov AH, strict byte 0ffh ; b4 ff ; 0xc3890 vgabios.c:2431 + xor al, al ; 30 c0 ; 0xc3892 vgabios.c:2432 + jmp short 0389ch ; eb 06 ; 0xc3894 + db 0feh, 0c0h + ; inc al ; fe c0 ; 0xc3896 vgabios.c:2433 + cmp AL, strict byte 00fh ; 3c 0f ; 0xc3898 + jnbe short 038ach ; 77 10 ; 0xc389a + mov bl, al ; 88 c3 ; 0xc389c + xor bh, bh ; 30 ff ; 0xc389e + mov CL, strict byte 003h ; b1 03 ; 0xc38a0 + sal bx, CL ; d3 e3 ; 0xc38a2 + cmp dl, byte [bx+047afh] ; 3a 97 af 47 ; 0xc38a4 + jne short 03896h ; 75 ec ; 0xc38a8 + mov ah, al ; 88 c4 ; 0xc38aa + mov al, ah ; 88 e0 ; 0xc38ac vgabios.c:2438 + pop bp ; 5d ; 0xc38ae + pop dx ; 5a ; 0xc38af + pop cx ; 59 ; 0xc38b0 + pop bx ; 5b ; 0xc38b1 + retn ; c3 ; 0xc38b2 + ; disGetNextSymbol 0xc38b3 LB 0xcb1 -> off=0x0 cb=000000000000000e uValue=00000000000c38b3 'readx_byte' +readx_byte: ; 0xc38b3 LB 0xe + push bx ; 53 ; 0xc38b3 vgabios.c:2450 + push bp ; 55 ; 0xc38b4 + mov bp, sp ; 89 e5 ; 0xc38b5 + mov bx, dx ; 89 d3 ; 0xc38b7 + mov es, ax ; 8e c0 ; 0xc38b9 vgabios.c:2452 + mov al, byte [es:bx] ; 26 8a 07 ; 0xc38bb + pop bp ; 5d ; 0xc38be vgabios.c:2453 + pop bx ; 5b ; 0xc38bf + retn ; c3 ; 0xc38c0 + ; disGetNextSymbol 0xc38c1 LB 0xca3 -> off=0x8a cb=0000000000000456 uValue=00000000000c394b 'int10_func' + db 056h, 04fh, 01ch, 01bh, 013h, 012h, 011h, 010h, 00eh, 00dh, 00ch, 00ah, 009h, 008h, 007h, 006h + db 005h, 004h, 003h, 002h, 001h, 000h, 09ah, 03dh, 075h, 039h, 0b2h, 039h, 0c1h, 039h, 0cfh, 039h + db 0dfh, 039h, 0efh, 039h, 0f9h, 039h, 022h, 03ah, 04bh, 03ah, 059h, 03ah, 06fh, 03ah, 087h, 03ah + db 0aah, 03ah, 0beh, 03ah, 0d4h, 03ah, 0e0h, 03ah, 0e2h, 03bh, 068h, 03ch, 08bh, 03ch, 09fh, 03ch + db 0e1h, 03ch, 06ch, 03dh, 030h, 024h, 023h, 022h, 021h, 020h, 014h, 012h, 011h, 010h, 004h, 003h + db 002h, 001h, 000h, 09ah, 03dh, 0ffh, 03ah, 01ah, 03bh, 038h, 03bh, 050h, 03bh, 05bh, 03bh, 0ffh + db 03ah, 01ah, 03bh, 038h, 03bh, 05bh, 03bh, 073h, 03bh, 07eh, 03bh, 097h, 03bh, 0a6h, 03bh, 0b5h + db 03bh, 0c2h, 03bh, 00ah, 009h, 006h, 004h, 002h, 001h, 000h, 05eh, 03dh, 007h, 03dh, 015h, 03dh + db 026h, 03dh, 036h, 03dh, 04bh, 03dh, 05eh, 03dh, 05eh, 03dh +int10_func: ; 0xc394b LB 0x456 + push bp ; 55 ; 0xc394b vgabios.c:2531 + mov bp, sp ; 89 e5 ; 0xc394c + push si ; 56 ; 0xc394e + push di ; 57 ; 0xc394f + push ax ; 50 ; 0xc3950 + mov si, word [bp+004h] ; 8b 76 04 ; 0xc3951 + mov al, byte [bp+013h] ; 8a 46 13 ; 0xc3954 vgabios.c:2536 + xor ah, ah ; 30 e4 ; 0xc3957 + mov dx, ax ; 89 c2 ; 0xc3959 + cmp ax, strict word 00056h ; 3d 56 00 ; 0xc395b + jnbe short 039cch ; 77 6c ; 0xc395e + push CS ; 0e ; 0xc3960 + pop ES ; 07 ; 0xc3961 + mov cx, strict word 00017h ; b9 17 00 ; 0xc3962 + mov di, 038c1h ; bf c1 38 ; 0xc3965 + repne scasb ; f2 ae ; 0xc3968 + sal cx, 1 ; d1 e1 ; 0xc396a + mov di, cx ; 89 cf ; 0xc396c + mov ax, word [cs:di+038d7h] ; 2e 8b 85 d7 38 ; 0xc396e + jmp ax ; ff e0 ; 0xc3973 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3975 vgabios.c:2539 + xor ah, ah ; 30 e4 ; 0xc3978 + call 01479h ; e8 fc da ; 0xc397a + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc397d vgabios.c:2540 + and ax, strict word 0007fh ; 25 7f 00 ; 0xc3980 + cmp ax, strict word 00007h ; 3d 07 00 ; 0xc3983 + je short 0399dh ; 74 15 ; 0xc3986 + cmp ax, strict word 00006h ; 3d 06 00 ; 0xc3988 + je short 03994h ; 74 07 ; 0xc398b + cmp ax, strict word 00005h ; 3d 05 00 ; 0xc398d + jbe short 0399dh ; 76 0b ; 0xc3990 + jmp short 039a6h ; eb 12 ; 0xc3992 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3994 vgabios.c:2542 + xor al, al ; 30 c0 ; 0xc3997 + or AL, strict byte 03fh ; 0c 3f ; 0xc3999 + jmp short 039adh ; eb 10 ; 0xc399b vgabios.c:2543 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc399d vgabios.c:2551 + xor al, al ; 30 c0 ; 0xc39a0 + or AL, strict byte 030h ; 0c 30 ; 0xc39a2 + jmp short 039adh ; eb 07 ; 0xc39a4 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc39a6 vgabios.c:2554 + xor al, al ; 30 c0 ; 0xc39a9 + or AL, strict byte 020h ; 0c 20 ; 0xc39ab + mov word [bp+012h], ax ; 89 46 12 ; 0xc39ad + jmp short 039cch ; eb 1a ; 0xc39b0 vgabios.c:2556 + mov al, byte [bp+010h] ; 8a 46 10 ; 0xc39b2 vgabios.c:2558 + xor ah, ah ; 30 e4 ; 0xc39b5 + mov dx, ax ; 89 c2 ; 0xc39b7 + mov al, byte [bp+011h] ; 8a 46 11 ; 0xc39b9 + call 011d3h ; e8 14 d8 ; 0xc39bc + jmp short 039cch ; eb 0b ; 0xc39bf vgabios.c:2559 + mov dx, word [bp+00eh] ; 8b 56 0e ; 0xc39c1 vgabios.c:2561 + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc39c4 + xor ah, ah ; 30 e4 ; 0xc39c7 + call 012cfh ; e8 03 d9 ; 0xc39c9 + jmp near 03d9ah ; e9 cb 03 ; 0xc39cc vgabios.c:2562 + lea bx, [bp+00eh] ; 8d 5e 0e ; 0xc39cf vgabios.c:2564 + lea dx, [bp+010h] ; 8d 56 10 ; 0xc39d2 + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc39d5 + xor ah, ah ; 30 e4 ; 0xc39d8 + call 00a97h ; e8 ba d0 ; 0xc39da + jmp short 039cch ; eb ed ; 0xc39dd vgabios.c:2565 + xor ax, ax ; 31 c0 ; 0xc39df vgabios.c:2571 + mov word [bp+012h], ax ; 89 46 12 ; 0xc39e1 + mov word [bp+00ch], ax ; 89 46 0c ; 0xc39e4 vgabios.c:2572 + mov word [bp+010h], ax ; 89 46 10 ; 0xc39e7 vgabios.c:2573 + mov word [bp+00eh], ax ; 89 46 0e ; 0xc39ea vgabios.c:2574 + jmp short 039cch ; eb dd ; 0xc39ed vgabios.c:2575 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc39ef vgabios.c:2577 + xor ah, ah ; 30 e4 ; 0xc39f2 + call 0135ch ; e8 65 d9 ; 0xc39f4 + jmp short 039cch ; eb d3 ; 0xc39f7 vgabios.c:2578 + mov ax, strict word 00001h ; b8 01 00 ; 0xc39f9 vgabios.c:2580 + push ax ; 50 ; 0xc39fc + mov ax, 000ffh ; b8 ff 00 ; 0xc39fd + push ax ; 50 ; 0xc3a00 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3a01 + xor ah, ah ; 30 e4 ; 0xc3a04 + push ax ; 50 ; 0xc3a06 + mov al, byte [bp+00fh] ; 8a 46 0f ; 0xc3a07 + push ax ; 50 ; 0xc3a0a + mov al, byte [bp+010h] ; 8a 46 10 ; 0xc3a0b + mov cx, ax ; 89 c1 ; 0xc3a0e + mov bl, byte [bp+011h] ; 8a 5e 11 ; 0xc3a10 + xor bh, bh ; 30 ff ; 0xc3a13 + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc3a15 + mov dx, ax ; 89 c2 ; 0xc3a18 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3a1a + call 01c9fh ; e8 7f e2 ; 0xc3a1d + jmp short 039cch ; eb aa ; 0xc3a20 vgabios.c:2581 + xor ax, ax ; 31 c0 ; 0xc3a22 vgabios.c:2583 + push ax ; 50 ; 0xc3a24 + mov ax, 000ffh ; b8 ff 00 ; 0xc3a25 + push ax ; 50 ; 0xc3a28 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3a29 + xor ah, ah ; 30 e4 ; 0xc3a2c + push ax ; 50 ; 0xc3a2e + mov al, byte [bp+00fh] ; 8a 46 0f ; 0xc3a2f + push ax ; 50 ; 0xc3a32 + mov al, byte [bp+010h] ; 8a 46 10 ; 0xc3a33 + mov cx, ax ; 89 c1 ; 0xc3a36 + mov al, byte [bp+011h] ; 8a 46 11 ; 0xc3a38 + mov bx, ax ; 89 c3 ; 0xc3a3b + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc3a3d + mov dl, byte [bp+012h] ; 8a 56 12 ; 0xc3a40 + mov si, dx ; 89 d6 ; 0xc3a43 + mov dx, ax ; 89 c2 ; 0xc3a45 + mov ax, si ; 89 f0 ; 0xc3a47 + jmp short 03a1dh ; eb d2 ; 0xc3a49 + lea dx, [bp+012h] ; 8d 56 12 ; 0xc3a4b vgabios.c:2586 + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc3a4e + xor ah, ah ; 30 e4 ; 0xc3a51 + call 00dedh ; e8 97 d3 ; 0xc3a53 + jmp near 03d9ah ; e9 41 03 ; 0xc3a56 vgabios.c:2587 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3a59 vgabios.c:2589 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3a5c + xor ah, ah ; 30 e4 ; 0xc3a5f + mov bx, ax ; 89 c3 ; 0xc3a61 + mov dl, byte [bp+00dh] ; 8a 56 0d ; 0xc3a63 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3a66 + call 02607h ; e8 9b eb ; 0xc3a69 + jmp near 03d9ah ; e9 2b 03 ; 0xc3a6c vgabios.c:2590 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3a6f vgabios.c:2592 + mov bl, byte [bp+00ch] ; 8a 5e 0c ; 0xc3a72 + xor bh, bh ; 30 ff ; 0xc3a75 + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc3a77 + xor ah, ah ; 30 e4 ; 0xc3a7a + mov dx, ax ; 89 c2 ; 0xc3a7c + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3a7e + call 02779h ; e8 f5 ec ; 0xc3a81 + jmp near 03d9ah ; e9 13 03 ; 0xc3a84 vgabios.c:2593 + mov cx, word [bp+00eh] ; 8b 4e 0e ; 0xc3a87 vgabios.c:2595 + mov bx, word [bp+010h] ; 8b 5e 10 ; 0xc3a8a + mov dl, byte [bp+012h] ; 8a 56 12 ; 0xc3a8d + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc3a90 + mov byte [bp-006h], al ; 88 46 fa ; 0xc3a93 + mov byte [bp-005h], dh ; 88 76 fb ; 0xc3a96 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc3a99 + mov word [bp-006h], ax ; 89 46 fa ; 0xc3a9c + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc3a9f + xor ah, ah ; 30 e4 ; 0xc3aa2 + call 028fch ; e8 55 ee ; 0xc3aa4 + jmp near 03d9ah ; e9 f0 02 ; 0xc3aa7 vgabios.c:2596 + lea cx, [bp+012h] ; 8d 4e 12 ; 0xc3aaa vgabios.c:2598 + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc3aad + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3ab0 + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc3ab3 + xor ah, ah ; 30 e4 ; 0xc3ab6 + call 00fc7h ; e8 0c d5 ; 0xc3ab8 + jmp near 03d9ah ; e9 dc 02 ; 0xc3abb vgabios.c:2599 + mov cx, strict word 00002h ; b9 02 00 ; 0xc3abe vgabios.c:2607 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3ac1 + xor ah, ah ; 30 e4 ; 0xc3ac4 + mov bx, ax ; 89 c3 ; 0xc3ac6 + mov dx, 000ffh ; ba ff 00 ; 0xc3ac8 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3acb + call 02a76h ; e8 a5 ef ; 0xc3ace + jmp near 03d9ah ; e9 c6 02 ; 0xc3ad1 vgabios.c:2608 + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3ad4 vgabios.c:2611 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3ad7 + call 01134h ; e8 57 d6 ; 0xc3ada + jmp near 03d9ah ; e9 ba 02 ; 0xc3add vgabios.c:2612 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3ae0 vgabios.c:2614 + xor ah, ah ; 30 e4 ; 0xc3ae3 + cmp ax, strict word 00030h ; 3d 30 00 ; 0xc3ae5 + jnbe short 03b58h ; 77 6e ; 0xc3ae8 + push CS ; 0e ; 0xc3aea + pop ES ; 07 ; 0xc3aeb + mov cx, strict word 00010h ; b9 10 00 ; 0xc3aec + mov di, 03905h ; bf 05 39 ; 0xc3aef + repne scasb ; f2 ae ; 0xc3af2 + sal cx, 1 ; d1 e1 ; 0xc3af4 + mov di, cx ; 89 cf ; 0xc3af6 + mov ax, word [cs:di+03914h] ; 2e 8b 85 14 39 ; 0xc3af8 + jmp ax ; ff e0 ; 0xc3afd + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc3aff vgabios.c:2618 + xor ah, ah ; 30 e4 ; 0xc3b02 + push ax ; 50 ; 0xc3b04 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b05 + push ax ; 50 ; 0xc3b08 + push word [bp+00eh] ; ff 76 0e ; 0xc3b09 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3b0c + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3b0f + mov bx, word [bp+008h] ; 8b 5e 08 ; 0xc3b12 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3b15 + jmp short 03b33h ; eb 19 ; 0xc3b18 + mov ax, strict word 0000eh ; b8 0e 00 ; 0xc3b1a vgabios.c:2622 + push ax ; 50 ; 0xc3b1d + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b1e + xor ah, ah ; 30 e4 ; 0xc3b21 + push ax ; 50 ; 0xc3b23 + xor al, al ; 30 c0 ; 0xc3b24 + push ax ; 50 ; 0xc3b26 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3b27 + mov cx, 00100h ; b9 00 01 ; 0xc3b2a + mov bx, 05d6dh ; bb 6d 5d ; 0xc3b2d + mov dx, 0c000h ; ba 00 c0 ; 0xc3b30 + call 02e8ch ; e8 56 f3 ; 0xc3b33 + jmp short 03b58h ; eb 20 ; 0xc3b36 + mov ax, strict word 00008h ; b8 08 00 ; 0xc3b38 vgabios.c:2626 + push ax ; 50 ; 0xc3b3b + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b3c + xor ah, ah ; 30 e4 ; 0xc3b3f + push ax ; 50 ; 0xc3b41 + xor al, al ; 30 c0 ; 0xc3b42 + push ax ; 50 ; 0xc3b44 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3b45 + mov cx, 00100h ; b9 00 01 ; 0xc3b48 + mov bx, 0556dh ; bb 6d 55 ; 0xc3b4b + jmp short 03b30h ; eb e0 ; 0xc3b4e + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b50 vgabios.c:2629 + xor ah, ah ; 30 e4 ; 0xc3b53 + call 02df4h ; e8 9c f2 ; 0xc3b55 + jmp near 03d9ah ; e9 3f 02 ; 0xc3b58 vgabios.c:2630 + mov ax, strict word 00010h ; b8 10 00 ; 0xc3b5b vgabios.c:2633 + push ax ; 50 ; 0xc3b5e + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b5f + xor ah, ah ; 30 e4 ; 0xc3b62 + push ax ; 50 ; 0xc3b64 + xor al, al ; 30 c0 ; 0xc3b65 + push ax ; 50 ; 0xc3b67 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3b68 + mov cx, 00100h ; b9 00 01 ; 0xc3b6b + mov bx, 06b6dh ; bb 6d 6b ; 0xc3b6e + jmp short 03b30h ; eb bd ; 0xc3b71 + mov dx, word [bp+008h] ; 8b 56 08 ; 0xc3b73 vgabios.c:2636 + mov ax, word [bp+016h] ; 8b 46 16 ; 0xc3b76 + call 02f10h ; e8 94 f3 ; 0xc3b79 + jmp short 03b58h ; eb da ; 0xc3b7c vgabios.c:2637 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3b7e vgabios.c:2639 + xor ah, ah ; 30 e4 ; 0xc3b81 + push ax ; 50 ; 0xc3b83 + mov cl, byte [bp+00ch] ; 8a 4e 0c ; 0xc3b84 + xor ch, ch ; 30 ed ; 0xc3b87 + mov bx, word [bp+010h] ; 8b 5e 10 ; 0xc3b89 + mov dx, word [bp+008h] ; 8b 56 08 ; 0xc3b8c + mov ax, word [bp+016h] ; 8b 46 16 ; 0xc3b8f + call 02f73h ; e8 de f3 ; 0xc3b92 + jmp short 03b58h ; eb c1 ; 0xc3b95 vgabios.c:2640 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3b97 vgabios.c:2642 + xor ah, ah ; 30 e4 ; 0xc3b9a + mov dx, ax ; 89 c2 ; 0xc3b9c + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3b9e + call 02f90h ; e8 ec f3 ; 0xc3ba1 + jmp short 03b58h ; eb b2 ; 0xc3ba4 vgabios.c:2643 + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3ba6 vgabios.c:2645 + xor ah, ah ; 30 e4 ; 0xc3ba9 + mov dx, ax ; 89 c2 ; 0xc3bab + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3bad + call 02fb2h ; e8 ff f3 ; 0xc3bb0 + jmp short 03b58h ; eb a3 ; 0xc3bb3 vgabios.c:2646 + mov dl, byte [bp+00eh] ; 8a 56 0e ; 0xc3bb5 vgabios.c:2648 + mov al, byte [bp+00ch] ; 8a 46 0c ; 0xc3bb8 + xor ah, ah ; 30 e4 ; 0xc3bbb + call 02fd4h ; e8 14 f4 ; 0xc3bbd + jmp short 03b58h ; eb 96 ; 0xc3bc0 vgabios.c:2649 + lea ax, [bp+00eh] ; 8d 46 0e ; 0xc3bc2 vgabios.c:2651 + push ax ; 50 ; 0xc3bc5 + lea cx, [bp+010h] ; 8d 4e 10 ; 0xc3bc6 + lea bx, [bp+008h] ; 8d 5e 08 ; 0xc3bc9 + lea dx, [bp+016h] ; 8d 56 16 ; 0xc3bcc + mov al, byte [bp+00dh] ; 8a 46 0d ; 0xc3bcf + mov byte [bp-006h], al ; 88 46 fa ; 0xc3bd2 + mov byte [bp-005h], 000h ; c6 46 fb 00 ; 0xc3bd5 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc3bd9 + call 00f44h ; e8 65 d3 ; 0xc3bdc + jmp near 03d9ah ; e9 b8 01 ; 0xc3bdf vgabios.c:2659 + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3be2 vgabios.c:2661 + xor ah, ah ; 30 e4 ; 0xc3be5 + cmp ax, strict word 00034h ; 3d 34 00 ; 0xc3be7 + jc short 03bfbh ; 72 0f ; 0xc3bea + jbe short 03c26h ; 76 38 ; 0xc3bec + cmp ax, strict word 00036h ; 3d 36 00 ; 0xc3bee + je short 03c50h ; 74 5d ; 0xc3bf1 + cmp ax, strict word 00035h ; 3d 35 00 ; 0xc3bf3 + je short 03c52h ; 74 5a ; 0xc3bf6 + jmp near 03d9ah ; e9 9f 01 ; 0xc3bf8 + cmp ax, strict word 00030h ; 3d 30 00 ; 0xc3bfb + je short 03c0ah ; 74 0a ; 0xc3bfe + cmp ax, strict word 00020h ; 3d 20 00 ; 0xc3c00 + jne short 03c4dh ; 75 48 ; 0xc3c03 + call 02ff6h ; e8 ee f3 ; 0xc3c05 vgabios.c:2664 + jmp short 03c4dh ; eb 43 ; 0xc3c08 vgabios.c:2665 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3c0a vgabios.c:2667 + xor ah, ah ; 30 e4 ; 0xc3c0d + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc3c0f + jnbe short 03c4dh ; 77 39 ; 0xc3c12 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c14 vgabios.c:2668 + call 02ffbh ; e8 e1 f3 ; 0xc3c17 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3c1a vgabios.c:2669 + xor al, al ; 30 c0 ; 0xc3c1d + or AL, strict byte 012h ; 0c 12 ; 0xc3c1f + mov word [bp+012h], ax ; 89 46 12 ; 0xc3c21 + jmp short 03c4dh ; eb 27 ; 0xc3c24 vgabios.c:2671 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3c26 vgabios.c:2673 + xor ah, ah ; 30 e4 ; 0xc3c29 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc3c2b + jnc short 03c4ah ; 73 1a ; 0xc3c2e + mov ax, strict word 00040h ; b8 40 00 ; 0xc3c30 vgabios.c:45 + mov es, ax ; 8e c0 ; 0xc3c33 + mov bx, 00087h ; bb 87 00 ; 0xc3c35 + mov ah, byte [es:bx] ; 26 8a 27 ; 0xc3c38 vgabios.c:47 + and ah, 0feh ; 80 e4 fe ; 0xc3c3b vgabios.c:48 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c3e + or al, ah ; 08 e0 ; 0xc3c41 + mov si, bx ; 89 de ; 0xc3c43 vgabios.c:50 + mov byte [es:si], al ; 26 88 04 ; 0xc3c45 vgabios.c:52 + jmp short 03c1ah ; eb d0 ; 0xc3c48 + mov byte [bp+012h], ah ; 88 66 12 ; 0xc3c4a vgabios.c:2679 + jmp near 03d9ah ; e9 4a 01 ; 0xc3c4d vgabios.c:2680 + jmp short 03c60h ; eb 0e ; 0xc3c50 + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c52 vgabios.c:2682 + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc3c55 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3c58 + call 0302dh ; e8 cf f3 ; 0xc3c5b + jmp short 03c1ah ; eb ba ; 0xc3c5e + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c60 vgabios.c:2686 + call 03032h ; e8 cc f3 ; 0xc3c63 + jmp short 03c1ah ; eb b2 ; 0xc3c66 + push word [bp+008h] ; ff 76 08 ; 0xc3c68 vgabios.c:2696 + push word [bp+016h] ; ff 76 16 ; 0xc3c6b + mov al, byte [bp+00eh] ; 8a 46 0e ; 0xc3c6e + xor ah, ah ; 30 e4 ; 0xc3c71 + push ax ; 50 ; 0xc3c73 + mov al, byte [bp+00fh] ; 8a 46 0f ; 0xc3c74 + push ax ; 50 ; 0xc3c77 + mov bl, byte [bp+00ch] ; 8a 5e 0c ; 0xc3c78 + xor bh, bh ; 30 ff ; 0xc3c7b + mov dl, byte [bp+00dh] ; 8a 56 0d ; 0xc3c7d + mov al, byte [bp+012h] ; 8a 46 12 ; 0xc3c80 + mov cx, word [bp+010h] ; 8b 4e 10 ; 0xc3c83 + call 03037h ; e8 ae f3 ; 0xc3c86 + jmp short 03c4dh ; eb c2 ; 0xc3c89 vgabios.c:2697 + mov bx, si ; 89 f3 ; 0xc3c8b vgabios.c:2699 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3c8d + mov ax, word [bp+00ch] ; 8b 46 0c ; 0xc3c90 + call 030c6h ; e8 30 f4 ; 0xc3c93 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3c96 vgabios.c:2700 + xor al, al ; 30 c0 ; 0xc3c99 + or AL, strict byte 01bh ; 0c 1b ; 0xc3c9b + jmp short 03c21h ; eb 82 ; 0xc3c9d + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3c9f vgabios.c:2703 + xor ah, ah ; 30 e4 ; 0xc3ca2 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc3ca4 + je short 03ccbh ; 74 22 ; 0xc3ca7 + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc3ca9 + je short 03cbdh ; 74 0f ; 0xc3cac + test ax, ax ; 85 c0 ; 0xc3cae + jne short 03cd7h ; 75 25 ; 0xc3cb0 + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3cb2 vgabios.c:2706 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3cb5 + call 032dbh ; e8 20 f6 ; 0xc3cb8 + jmp short 03cd7h ; eb 1a ; 0xc3cbb vgabios.c:2707 + mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xc3cbd vgabios.c:2709 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3cc0 + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3cc3 + call 032f6h ; e8 2d f6 ; 0xc3cc6 + jmp short 03cd7h ; eb 0c ; 0xc3cc9 vgabios.c:2710 + mov bx, word [bp+00ch] ; 8b 5e 0c ; 0xc3ccb vgabios.c:2712 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3cce + mov ax, word [bp+010h] ; 8b 46 10 ; 0xc3cd1 + call 035ceh ; e8 f7 f8 ; 0xc3cd4 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3cd7 vgabios.c:2719 + xor al, al ; 30 c0 ; 0xc3cda + or AL, strict byte 01ch ; 0c 1c ; 0xc3cdc + jmp near 03c21h ; e9 40 ff ; 0xc3cde + call 007f8h ; e8 14 cb ; 0xc3ce1 vgabios.c:2724 + test ax, ax ; 85 c0 ; 0xc3ce4 + je short 03d5ch ; 74 74 ; 0xc3ce6 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3ce8 vgabios.c:2725 + xor ah, ah ; 30 e4 ; 0xc3ceb + cmp ax, strict word 0000ah ; 3d 0a 00 ; 0xc3ced + jnbe short 03d5eh ; 77 6c ; 0xc3cf0 + push CS ; 0e ; 0xc3cf2 + pop ES ; 07 ; 0xc3cf3 + mov cx, strict word 00008h ; b9 08 00 ; 0xc3cf4 + mov di, 03934h ; bf 34 39 ; 0xc3cf7 + repne scasb ; f2 ae ; 0xc3cfa + sal cx, 1 ; d1 e1 ; 0xc3cfc + mov di, cx ; 89 cf ; 0xc3cfe + mov ax, word [cs:di+0393bh] ; 2e 8b 85 3b 39 ; 0xc3d00 + jmp ax ; ff e0 ; 0xc3d05 + mov bx, si ; 89 f3 ; 0xc3d07 vgabios.c:2728 + mov dx, word [bp+016h] ; 8b 56 16 ; 0xc3d09 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d0c + call 03f6bh ; e8 59 02 ; 0xc3d0f + jmp near 03d9ah ; e9 85 00 ; 0xc3d12 vgabios.c:2729 + mov cx, si ; 89 f1 ; 0xc3d15 vgabios.c:2731 + mov bx, word [bp+016h] ; 8b 5e 16 ; 0xc3d17 + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3d1a + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d1d + call 04096h ; e8 73 03 ; 0xc3d20 + jmp near 03d9ah ; e9 74 00 ; 0xc3d23 vgabios.c:2732 + mov cx, si ; 89 f1 ; 0xc3d26 vgabios.c:2734 + mov bx, word [bp+016h] ; 8b 5e 16 ; 0xc3d28 + mov dx, word [bp+00ch] ; 8b 56 0c ; 0xc3d2b + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d2e + call 04135h ; e8 01 04 ; 0xc3d31 + jmp short 03d9ah ; eb 64 ; 0xc3d34 vgabios.c:2735 + lea ax, [bp+00ch] ; 8d 46 0c ; 0xc3d36 vgabios.c:2737 + push ax ; 50 ; 0xc3d39 + mov cx, word [bp+016h] ; 8b 4e 16 ; 0xc3d3a + mov bx, word [bp+00eh] ; 8b 5e 0e ; 0xc3d3d + mov dx, word [bp+010h] ; 8b 56 10 ; 0xc3d40 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d43 + call 042feh ; e8 b5 05 ; 0xc3d46 + jmp short 03d9ah ; eb 4f ; 0xc3d49 vgabios.c:2738 + lea cx, [bp+00eh] ; 8d 4e 0e ; 0xc3d4b vgabios.c:2740 + lea bx, [bp+010h] ; 8d 5e 10 ; 0xc3d4e + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3d51 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d54 + call 0438bh ; e8 31 06 ; 0xc3d57 + jmp short 03d9ah ; eb 3e ; 0xc3d5a vgabios.c:2741 + jmp short 03d65h ; eb 07 ; 0xc3d5c + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3d5e vgabios.c:2763 + jmp short 03d9ah ; eb 35 ; 0xc3d63 vgabios.c:2766 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3d65 vgabios.c:2768 + jmp short 03d9ah ; eb 2e ; 0xc3d6a vgabios.c:2770 + call 007f8h ; e8 89 ca ; 0xc3d6c vgabios.c:2772 + test ax, ax ; 85 c0 ; 0xc3d6f + je short 03d95h ; 74 22 ; 0xc3d71 + mov ax, word [bp+012h] ; 8b 46 12 ; 0xc3d73 vgabios.c:2773 + xor ah, ah ; 30 e4 ; 0xc3d76 + cmp ax, strict word 00042h ; 3d 42 00 ; 0xc3d78 + jne short 03d8eh ; 75 11 ; 0xc3d7b + lea cx, [bp+00eh] ; 8d 4e 0e ; 0xc3d7d vgabios.c:2776 + lea bx, [bp+010h] ; 8d 5e 10 ; 0xc3d80 + lea dx, [bp+00ch] ; 8d 56 0c ; 0xc3d83 + lea ax, [bp+012h] ; 8d 46 12 ; 0xc3d86 + call 0446dh ; e8 e1 06 ; 0xc3d89 + jmp short 03d9ah ; eb 0c ; 0xc3d8c vgabios.c:2777 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3d8e vgabios.c:2779 + jmp short 03d9ah ; eb 05 ; 0xc3d93 vgabios.c:2782 + mov word [bp+012h], 00100h ; c7 46 12 00 01 ; 0xc3d95 vgabios.c:2784 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3d9a vgabios.c:2794 + pop di ; 5f ; 0xc3d9d + pop si ; 5e ; 0xc3d9e + pop bp ; 5d ; 0xc3d9f + retn ; c3 ; 0xc3da0 + ; disGetNextSymbol 0xc3da1 LB 0x7c3 -> off=0x0 cb=000000000000001f uValue=00000000000c3da1 'dispi_set_xres' +dispi_set_xres: ; 0xc3da1 LB 0x1f + push bp ; 55 ; 0xc3da1 vbe.c:100 + mov bp, sp ; 89 e5 ; 0xc3da2 + push bx ; 53 ; 0xc3da4 + push dx ; 52 ; 0xc3da5 + mov bx, ax ; 89 c3 ; 0xc3da6 + mov ax, strict word 00001h ; b8 01 00 ; 0xc3da8 vbe.c:105 + mov dx, 001ceh ; ba ce 01 ; 0xc3dab + call 005a0h ; e8 ef c7 ; 0xc3dae + mov ax, bx ; 89 d8 ; 0xc3db1 vbe.c:106 + mov dx, 001cfh ; ba cf 01 ; 0xc3db3 + call 005a0h ; e8 e7 c7 ; 0xc3db6 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3db9 vbe.c:107 + pop dx ; 5a ; 0xc3dbc + pop bx ; 5b ; 0xc3dbd + pop bp ; 5d ; 0xc3dbe + retn ; c3 ; 0xc3dbf + ; disGetNextSymbol 0xc3dc0 LB 0x7a4 -> off=0x0 cb=000000000000001f uValue=00000000000c3dc0 'dispi_set_yres' +dispi_set_yres: ; 0xc3dc0 LB 0x1f + push bp ; 55 ; 0xc3dc0 vbe.c:109 + mov bp, sp ; 89 e5 ; 0xc3dc1 + push bx ; 53 ; 0xc3dc3 + push dx ; 52 ; 0xc3dc4 + mov bx, ax ; 89 c3 ; 0xc3dc5 + mov ax, strict word 00002h ; b8 02 00 ; 0xc3dc7 vbe.c:114 + mov dx, 001ceh ; ba ce 01 ; 0xc3dca + call 005a0h ; e8 d0 c7 ; 0xc3dcd + mov ax, bx ; 89 d8 ; 0xc3dd0 vbe.c:115 + mov dx, 001cfh ; ba cf 01 ; 0xc3dd2 + call 005a0h ; e8 c8 c7 ; 0xc3dd5 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3dd8 vbe.c:116 + pop dx ; 5a ; 0xc3ddb + pop bx ; 5b ; 0xc3ddc + pop bp ; 5d ; 0xc3ddd + retn ; c3 ; 0xc3dde + ; disGetNextSymbol 0xc3ddf LB 0x785 -> off=0x0 cb=0000000000000019 uValue=00000000000c3ddf 'dispi_get_yres' +dispi_get_yres: ; 0xc3ddf LB 0x19 + push bp ; 55 ; 0xc3ddf vbe.c:118 + mov bp, sp ; 89 e5 ; 0xc3de0 + push dx ; 52 ; 0xc3de2 + mov ax, strict word 00002h ; b8 02 00 ; 0xc3de3 vbe.c:120 + mov dx, 001ceh ; ba ce 01 ; 0xc3de6 + call 005a0h ; e8 b4 c7 ; 0xc3de9 + mov dx, 001cfh ; ba cf 01 ; 0xc3dec vbe.c:121 + call 005a7h ; e8 b5 c7 ; 0xc3def + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3df2 vbe.c:122 + pop dx ; 5a ; 0xc3df5 + pop bp ; 5d ; 0xc3df6 + retn ; c3 ; 0xc3df7 + ; disGetNextSymbol 0xc3df8 LB 0x76c -> off=0x0 cb=000000000000001f uValue=00000000000c3df8 'dispi_set_bpp' +dispi_set_bpp: ; 0xc3df8 LB 0x1f + push bp ; 55 ; 0xc3df8 vbe.c:124 + mov bp, sp ; 89 e5 ; 0xc3df9 + push bx ; 53 ; 0xc3dfb + push dx ; 52 ; 0xc3dfc + mov bx, ax ; 89 c3 ; 0xc3dfd + mov ax, strict word 00003h ; b8 03 00 ; 0xc3dff vbe.c:129 + mov dx, 001ceh ; ba ce 01 ; 0xc3e02 + call 005a0h ; e8 98 c7 ; 0xc3e05 + mov ax, bx ; 89 d8 ; 0xc3e08 vbe.c:130 + mov dx, 001cfh ; ba cf 01 ; 0xc3e0a + call 005a0h ; e8 90 c7 ; 0xc3e0d + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3e10 vbe.c:131 + pop dx ; 5a ; 0xc3e13 + pop bx ; 5b ; 0xc3e14 + pop bp ; 5d ; 0xc3e15 + retn ; c3 ; 0xc3e16 + ; disGetNextSymbol 0xc3e17 LB 0x74d -> off=0x0 cb=0000000000000019 uValue=00000000000c3e17 'dispi_get_bpp' +dispi_get_bpp: ; 0xc3e17 LB 0x19 + push bp ; 55 ; 0xc3e17 vbe.c:133 + mov bp, sp ; 89 e5 ; 0xc3e18 + push dx ; 52 ; 0xc3e1a + mov ax, strict word 00003h ; b8 03 00 ; 0xc3e1b vbe.c:135 + mov dx, 001ceh ; ba ce 01 ; 0xc3e1e + call 005a0h ; e8 7c c7 ; 0xc3e21 + mov dx, 001cfh ; ba cf 01 ; 0xc3e24 vbe.c:136 + call 005a7h ; e8 7d c7 ; 0xc3e27 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e2a vbe.c:137 + pop dx ; 5a ; 0xc3e2d + pop bp ; 5d ; 0xc3e2e + retn ; c3 ; 0xc3e2f + ; disGetNextSymbol 0xc3e30 LB 0x734 -> off=0x0 cb=000000000000001f uValue=00000000000c3e30 'dispi_set_virt_width' +dispi_set_virt_width: ; 0xc3e30 LB 0x1f + push bp ; 55 ; 0xc3e30 vbe.c:139 + mov bp, sp ; 89 e5 ; 0xc3e31 + push bx ; 53 ; 0xc3e33 + push dx ; 52 ; 0xc3e34 + mov bx, ax ; 89 c3 ; 0xc3e35 + mov ax, strict word 00006h ; b8 06 00 ; 0xc3e37 vbe.c:144 + mov dx, 001ceh ; ba ce 01 ; 0xc3e3a + call 005a0h ; e8 60 c7 ; 0xc3e3d + mov ax, bx ; 89 d8 ; 0xc3e40 vbe.c:145 + mov dx, 001cfh ; ba cf 01 ; 0xc3e42 + call 005a0h ; e8 58 c7 ; 0xc3e45 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3e48 vbe.c:146 + pop dx ; 5a ; 0xc3e4b + pop bx ; 5b ; 0xc3e4c + pop bp ; 5d ; 0xc3e4d + retn ; c3 ; 0xc3e4e + ; disGetNextSymbol 0xc3e4f LB 0x715 -> off=0x0 cb=0000000000000019 uValue=00000000000c3e4f 'dispi_get_virt_width' +dispi_get_virt_width: ; 0xc3e4f LB 0x19 + push bp ; 55 ; 0xc3e4f vbe.c:148 + mov bp, sp ; 89 e5 ; 0xc3e50 + push dx ; 52 ; 0xc3e52 + mov ax, strict word 00006h ; b8 06 00 ; 0xc3e53 vbe.c:150 + mov dx, 001ceh ; ba ce 01 ; 0xc3e56 + call 005a0h ; e8 44 c7 ; 0xc3e59 + mov dx, 001cfh ; ba cf 01 ; 0xc3e5c vbe.c:151 + call 005a7h ; e8 45 c7 ; 0xc3e5f + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e62 vbe.c:152 + pop dx ; 5a ; 0xc3e65 + pop bp ; 5d ; 0xc3e66 + retn ; c3 ; 0xc3e67 + ; disGetNextSymbol 0xc3e68 LB 0x6fc -> off=0x0 cb=0000000000000019 uValue=00000000000c3e68 'dispi_get_virt_height' +dispi_get_virt_height: ; 0xc3e68 LB 0x19 + push bp ; 55 ; 0xc3e68 vbe.c:154 + mov bp, sp ; 89 e5 ; 0xc3e69 + push dx ; 52 ; 0xc3e6b + mov ax, strict word 00007h ; b8 07 00 ; 0xc3e6c vbe.c:156 + mov dx, 001ceh ; ba ce 01 ; 0xc3e6f + call 005a0h ; e8 2b c7 ; 0xc3e72 + mov dx, 001cfh ; ba cf 01 ; 0xc3e75 vbe.c:157 + call 005a7h ; e8 2c c7 ; 0xc3e78 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e7b vbe.c:158 + pop dx ; 5a ; 0xc3e7e + pop bp ; 5d ; 0xc3e7f + retn ; c3 ; 0xc3e80 + ; disGetNextSymbol 0xc3e81 LB 0x6e3 -> off=0x0 cb=0000000000000012 uValue=00000000000c3e81 'in_word' +in_word: ; 0xc3e81 LB 0x12 + push bp ; 55 ; 0xc3e81 vbe.c:160 + mov bp, sp ; 89 e5 ; 0xc3e82 + push bx ; 53 ; 0xc3e84 + mov bx, ax ; 89 c3 ; 0xc3e85 + mov ax, dx ; 89 d0 ; 0xc3e87 + mov dx, bx ; 89 da ; 0xc3e89 vbe.c:162 + out DX, ax ; ef ; 0xc3e8b + in ax, DX ; ed ; 0xc3e8c vbe.c:163 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3e8d vbe.c:164 + pop bx ; 5b ; 0xc3e90 + pop bp ; 5d ; 0xc3e91 + retn ; c3 ; 0xc3e92 + ; disGetNextSymbol 0xc3e93 LB 0x6d1 -> off=0x0 cb=0000000000000014 uValue=00000000000c3e93 'in_byte' +in_byte: ; 0xc3e93 LB 0x14 + push bp ; 55 ; 0xc3e93 vbe.c:166 + mov bp, sp ; 89 e5 ; 0xc3e94 + push bx ; 53 ; 0xc3e96 + mov bx, ax ; 89 c3 ; 0xc3e97 + mov ax, dx ; 89 d0 ; 0xc3e99 + mov dx, bx ; 89 da ; 0xc3e9b vbe.c:168 + out DX, ax ; ef ; 0xc3e9d + in AL, DX ; ec ; 0xc3e9e vbe.c:169 + db 02ah, 0e4h + ; sub ah, ah ; 2a e4 ; 0xc3e9f + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3ea1 vbe.c:170 + pop bx ; 5b ; 0xc3ea4 + pop bp ; 5d ; 0xc3ea5 + retn ; c3 ; 0xc3ea6 + ; disGetNextSymbol 0xc3ea7 LB 0x6bd -> off=0x0 cb=0000000000000014 uValue=00000000000c3ea7 'dispi_get_id' +dispi_get_id: ; 0xc3ea7 LB 0x14 + push bp ; 55 ; 0xc3ea7 vbe.c:173 + mov bp, sp ; 89 e5 ; 0xc3ea8 + push dx ; 52 ; 0xc3eaa + xor ax, ax ; 31 c0 ; 0xc3eab vbe.c:175 + mov dx, 001ceh ; ba ce 01 ; 0xc3ead + out DX, ax ; ef ; 0xc3eb0 + mov dx, 001cfh ; ba cf 01 ; 0xc3eb1 vbe.c:176 + in ax, DX ; ed ; 0xc3eb4 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3eb5 vbe.c:177 + pop dx ; 5a ; 0xc3eb8 + pop bp ; 5d ; 0xc3eb9 + retn ; c3 ; 0xc3eba + ; disGetNextSymbol 0xc3ebb LB 0x6a9 -> off=0x0 cb=000000000000001a uValue=00000000000c3ebb 'dispi_set_id' +dispi_set_id: ; 0xc3ebb LB 0x1a + push bp ; 55 ; 0xc3ebb vbe.c:179 + mov bp, sp ; 89 e5 ; 0xc3ebc + push bx ; 53 ; 0xc3ebe + push dx ; 52 ; 0xc3ebf + mov bx, ax ; 89 c3 ; 0xc3ec0 + xor ax, ax ; 31 c0 ; 0xc3ec2 vbe.c:181 + mov dx, 001ceh ; ba ce 01 ; 0xc3ec4 + out DX, ax ; ef ; 0xc3ec7 + mov ax, bx ; 89 d8 ; 0xc3ec8 vbe.c:182 + mov dx, 001cfh ; ba cf 01 ; 0xc3eca + out DX, ax ; ef ; 0xc3ecd + lea sp, [bp-004h] ; 8d 66 fc ; 0xc3ece vbe.c:183 + pop dx ; 5a ; 0xc3ed1 + pop bx ; 5b ; 0xc3ed2 + pop bp ; 5d ; 0xc3ed3 + retn ; c3 ; 0xc3ed4 + ; disGetNextSymbol 0xc3ed5 LB 0x68f -> off=0x0 cb=000000000000002a uValue=00000000000c3ed5 'vbe_init' +vbe_init: ; 0xc3ed5 LB 0x2a + push bp ; 55 ; 0xc3ed5 vbe.c:188 + mov bp, sp ; 89 e5 ; 0xc3ed6 + push bx ; 53 ; 0xc3ed8 + mov ax, 0b0c0h ; b8 c0 b0 ; 0xc3ed9 vbe.c:190 + call 03ebbh ; e8 dc ff ; 0xc3edc + call 03ea7h ; e8 c5 ff ; 0xc3edf vbe.c:191 + cmp ax, 0b0c0h ; 3d c0 b0 ; 0xc3ee2 + jne short 03ef9h ; 75 12 ; 0xc3ee5 + mov bx, 000b9h ; bb b9 00 ; 0xc3ee7 vbe.c:52 + mov ax, strict word 00040h ; b8 40 00 ; 0xc3eea + mov es, ax ; 8e c0 ; 0xc3eed + mov byte [es:bx], 001h ; 26 c6 07 01 ; 0xc3eef + mov ax, 0b0c4h ; b8 c4 b0 ; 0xc3ef3 vbe.c:194 + call 03ebbh ; e8 c2 ff ; 0xc3ef6 + lea sp, [bp-002h] ; 8d 66 fe ; 0xc3ef9 vbe.c:199 + pop bx ; 5b ; 0xc3efc + pop bp ; 5d ; 0xc3efd + retn ; c3 ; 0xc3efe + ; disGetNextSymbol 0xc3eff LB 0x665 -> off=0x0 cb=000000000000006c uValue=00000000000c3eff 'mode_info_find_mode' +mode_info_find_mode: ; 0xc3eff LB 0x6c + push bp ; 55 ; 0xc3eff vbe.c:202 + mov bp, sp ; 89 e5 ; 0xc3f00 + push bx ; 53 ; 0xc3f02 + push cx ; 51 ; 0xc3f03 + push si ; 56 ; 0xc3f04 + push di ; 57 ; 0xc3f05 + mov di, ax ; 89 c7 ; 0xc3f06 + mov si, dx ; 89 d6 ; 0xc3f08 + xor dx, dx ; 31 d2 ; 0xc3f0a vbe.c:208 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f0c + call 03e81h ; e8 6f ff ; 0xc3f0f + cmp ax, 077cch ; 3d cc 77 ; 0xc3f12 vbe.c:209 + jne short 03f60h ; 75 49 ; 0xc3f15 + test si, si ; 85 f6 ; 0xc3f17 vbe.c:213 + je short 03f2eh ; 74 13 ; 0xc3f19 + mov ax, strict word 0000bh ; b8 0b 00 ; 0xc3f1b vbe.c:220 + mov dx, 001ceh ; ba ce 01 ; 0xc3f1e + call 005a0h ; e8 7c c6 ; 0xc3f21 + mov dx, 001cfh ; ba cf 01 ; 0xc3f24 vbe.c:221 + call 005a7h ; e8 7d c6 ; 0xc3f27 + test ax, ax ; 85 c0 ; 0xc3f2a vbe.c:222 + je short 03f62h ; 74 34 ; 0xc3f2c + mov bx, strict word 00004h ; bb 04 00 ; 0xc3f2e vbe.c:226 + mov dx, bx ; 89 da ; 0xc3f31 vbe.c:232 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f33 + call 03e81h ; e8 48 ff ; 0xc3f36 + mov cx, ax ; 89 c1 ; 0xc3f39 + cmp cx, strict byte 0ffffh ; 83 f9 ff ; 0xc3f3b vbe.c:233 + je short 03f60h ; 74 20 ; 0xc3f3e + lea dx, [bx+002h] ; 8d 57 02 ; 0xc3f40 vbe.c:235 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f43 + call 03e81h ; e8 38 ff ; 0xc3f46 + lea dx, [bx+044h] ; 8d 57 44 ; 0xc3f49 + cmp cx, di ; 39 f9 ; 0xc3f4c vbe.c:237 + jne short 03f5ch ; 75 0c ; 0xc3f4e + test si, si ; 85 f6 ; 0xc3f50 vbe.c:239 + jne short 03f58h ; 75 04 ; 0xc3f52 + mov ax, bx ; 89 d8 ; 0xc3f54 vbe.c:240 + jmp short 03f62h ; eb 0a ; 0xc3f56 + test AL, strict byte 080h ; a8 80 ; 0xc3f58 vbe.c:241 + jne short 03f54h ; 75 f8 ; 0xc3f5a + mov bx, dx ; 89 d3 ; 0xc3f5c vbe.c:244 + jmp short 03f33h ; eb d3 ; 0xc3f5e vbe.c:249 + xor ax, ax ; 31 c0 ; 0xc3f60 vbe.c:252 + lea sp, [bp-008h] ; 8d 66 f8 ; 0xc3f62 vbe.c:253 + pop di ; 5f ; 0xc3f65 + pop si ; 5e ; 0xc3f66 + pop cx ; 59 ; 0xc3f67 + pop bx ; 5b ; 0xc3f68 + pop bp ; 5d ; 0xc3f69 + retn ; c3 ; 0xc3f6a + ; disGetNextSymbol 0xc3f6b LB 0x5f9 -> off=0x0 cb=000000000000012b uValue=00000000000c3f6b 'vbe_biosfn_return_controller_information' +vbe_biosfn_return_controller_information: ; 0xc3f6b LB 0x12b + push bp ; 55 ; 0xc3f6b vbe.c:284 + mov bp, sp ; 89 e5 ; 0xc3f6c + push cx ; 51 ; 0xc3f6e + push si ; 56 ; 0xc3f6f + push di ; 57 ; 0xc3f70 + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc3f71 + mov si, ax ; 89 c6 ; 0xc3f74 + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc3f76 + mov di, bx ; 89 df ; 0xc3f79 + mov word [bp-00ch], strict word 00022h ; c7 46 f4 22 00 ; 0xc3f7b vbe.c:289 + call 005eah ; e8 67 c6 ; 0xc3f80 vbe.c:292 + mov word [bp-010h], ax ; 89 46 f0 ; 0xc3f83 + mov bx, di ; 89 fb ; 0xc3f86 vbe.c:295 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3f88 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc3f8b + xor dx, dx ; 31 d2 ; 0xc3f8e vbe.c:298 + mov ax, 003b6h ; b8 b6 03 ; 0xc3f90 + call 03e81h ; e8 eb fe ; 0xc3f93 + cmp ax, 077cch ; 3d cc 77 ; 0xc3f96 vbe.c:299 + je short 03fa5h ; 74 0a ; 0xc3f99 + push SS ; 16 ; 0xc3f9b vbe.c:301 + pop ES ; 07 ; 0xc3f9c + mov word [es:si], 00100h ; 26 c7 04 00 01 ; 0xc3f9d + jmp near 0408eh ; e9 e9 00 ; 0xc3fa2 vbe.c:305 + mov cx, strict word 00004h ; b9 04 00 ; 0xc3fa5 vbe.c:307 + mov word [bp-00eh], strict word 00000h ; c7 46 f2 00 00 ; 0xc3fa8 vbe.c:314 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc3fad vbe.c:322 + cmp word [es:bx+002h], 03245h ; 26 81 7f 02 45 32 ; 0xc3fb0 + jne short 03fbfh ; 75 07 ; 0xc3fb6 + cmp word [es:bx], 04256h ; 26 81 3f 56 42 ; 0xc3fb8 + je short 03fceh ; 74 0f ; 0xc3fbd + cmp word [es:bx+002h], 04153h ; 26 81 7f 02 53 41 ; 0xc3fbf + jne short 03fd3h ; 75 0c ; 0xc3fc5 + cmp word [es:bx], 04556h ; 26 81 3f 56 45 ; 0xc3fc7 + jne short 03fd3h ; 75 05 ; 0xc3fcc + mov word [bp-00eh], strict word 00001h ; c7 46 f2 01 00 ; 0xc3fce vbe.c:324 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc3fd3 vbe.c:332 + mov word [es:bx], 04556h ; 26 c7 07 56 45 ; 0xc3fd6 + mov word [es:bx+002h], 04153h ; 26 c7 47 02 53 41 ; 0xc3fdb vbe.c:334 + mov word [es:bx+004h], 00200h ; 26 c7 47 04 00 02 ; 0xc3fe1 vbe.c:338 + mov word [es:bx+006h], 07e02h ; 26 c7 47 06 02 7e ; 0xc3fe7 vbe.c:341 + mov [es:bx+008h], ds ; 26 8c 5f 08 ; 0xc3fed + mov word [es:bx+00ah], strict word 00001h ; 26 c7 47 0a 01 00 ; 0xc3ff1 vbe.c:344 + mov word [es:bx+00ch], strict word 00000h ; 26 c7 47 0c 00 00 ; 0xc3ff7 vbe.c:346 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc3ffd vbe.c:350 + mov word [es:bx+010h], ax ; 26 89 47 10 ; 0xc4000 + lea ax, [di+022h] ; 8d 45 22 ; 0xc4004 vbe.c:351 + mov word [es:bx+00eh], ax ; 26 89 47 0e ; 0xc4007 + mov dx, strict word 0ffffh ; ba ff ff ; 0xc400b vbe.c:354 + mov ax, 003b6h ; b8 b6 03 ; 0xc400e + call 03e81h ; e8 6d fe ; 0xc4011 + mov es, [bp-008h] ; 8e 46 f8 ; 0xc4014 + mov word [es:bx+012h], ax ; 26 89 47 12 ; 0xc4017 + cmp word [bp-00eh], strict byte 00000h ; 83 7e f2 00 ; 0xc401b vbe.c:356 + je short 04045h ; 74 24 ; 0xc401f + mov word [es:bx+014h], strict word 00003h ; 26 c7 47 14 03 00 ; 0xc4021 vbe.c:359 + mov word [es:bx+016h], 07e17h ; 26 c7 47 16 17 7e ; 0xc4027 vbe.c:360 + mov [es:bx+018h], ds ; 26 8c 5f 18 ; 0xc402d + mov word [es:bx+01ah], 07e34h ; 26 c7 47 1a 34 7e ; 0xc4031 vbe.c:361 + mov [es:bx+01ch], ds ; 26 8c 5f 1c ; 0xc4037 + mov word [es:bx+01eh], 07e55h ; 26 c7 47 1e 55 7e ; 0xc403b vbe.c:362 + mov [es:bx+020h], ds ; 26 8c 5f 20 ; 0xc4041 + mov dx, cx ; 89 ca ; 0xc4045 vbe.c:369 + add dx, strict byte 0001bh ; 83 c2 1b ; 0xc4047 + mov ax, 003b6h ; b8 b6 03 ; 0xc404a + call 03e93h ; e8 43 fe ; 0xc404d + xor ah, ah ; 30 e4 ; 0xc4050 vbe.c:370 + cmp ax, word [bp-010h] ; 3b 46 f0 ; 0xc4052 + jnbe short 0406eh ; 77 17 ; 0xc4055 + mov dx, cx ; 89 ca ; 0xc4057 vbe.c:372 + mov ax, 003b6h ; b8 b6 03 ; 0xc4059 + call 03e81h ; e8 22 fe ; 0xc405c + mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xc405f vbe.c:376 + add bx, di ; 01 fb ; 0xc4062 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc4064 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc4067 + add word [bp-00ch], strict byte 00002h ; 83 46 f4 02 ; 0xc406a vbe.c:378 + add cx, strict byte 00044h ; 83 c1 44 ; 0xc406e vbe.c:380 + mov dx, cx ; 89 ca ; 0xc4071 vbe.c:381 + mov ax, 003b6h ; b8 b6 03 ; 0xc4073 + call 03e81h ; e8 08 fe ; 0xc4076 + cmp ax, strict word 0ffffh ; 3d ff ff ; 0xc4079 vbe.c:382 + jne short 04045h ; 75 c7 ; 0xc407c + add di, word [bp-00ch] ; 03 7e f4 ; 0xc407e vbe.c:385 + mov es, [bp-00ah] ; 8e 46 f6 ; 0xc4081 vbe.c:62 + mov word [es:di], ax ; 26 89 05 ; 0xc4084 + push SS ; 16 ; 0xc4087 vbe.c:386 + pop ES ; 07 ; 0xc4088 + mov word [es:si], strict word 0004fh ; 26 c7 04 4f 00 ; 0xc4089 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc408e vbe.c:387 + pop di ; 5f ; 0xc4091 + pop si ; 5e ; 0xc4092 + pop cx ; 59 ; 0xc4093 + pop bp ; 5d ; 0xc4094 + retn ; c3 ; 0xc4095 + ; disGetNextSymbol 0xc4096 LB 0x4ce -> off=0x0 cb=000000000000009f uValue=00000000000c4096 'vbe_biosfn_return_mode_information' +vbe_biosfn_return_mode_information: ; 0xc4096 LB 0x9f + push bp ; 55 ; 0xc4096 vbe.c:399 + mov bp, sp ; 89 e5 ; 0xc4097 + push si ; 56 ; 0xc4099 + push di ; 57 ; 0xc409a + push ax ; 50 ; 0xc409b + push ax ; 50 ; 0xc409c + mov ax, dx ; 89 d0 ; 0xc409d + mov si, bx ; 89 de ; 0xc409f + mov bx, cx ; 89 cb ; 0xc40a1 + test dh, 040h ; f6 c6 40 ; 0xc40a3 vbe.c:410 + je short 040adh ; 74 05 ; 0xc40a6 + mov dx, strict word 00001h ; ba 01 00 ; 0xc40a8 + jmp short 040afh ; eb 02 ; 0xc40ab + xor dx, dx ; 31 d2 ; 0xc40ad + and ah, 001h ; 80 e4 01 ; 0xc40af vbe.c:411 + call 03effh ; e8 4a fe ; 0xc40b2 vbe.c:413 + mov word [bp-006h], ax ; 89 46 fa ; 0xc40b5 + test ax, ax ; 85 c0 ; 0xc40b8 vbe.c:415 + je short 04123h ; 74 67 ; 0xc40ba + mov cx, 00100h ; b9 00 01 ; 0xc40bc vbe.c:420 + xor ax, ax ; 31 c0 ; 0xc40bf + mov di, bx ; 89 df ; 0xc40c1 + mov es, si ; 8e c6 ; 0xc40c3 + jcxz 040c9h ; e3 02 ; 0xc40c5 + rep stosb ; f3 aa ; 0xc40c7 + xor cx, cx ; 31 c9 ; 0xc40c9 vbe.c:421 + jmp short 040d2h ; eb 05 ; 0xc40cb + cmp cx, strict byte 00042h ; 83 f9 42 ; 0xc40cd + jnc short 040ebh ; 73 19 ; 0xc40d0 + mov dx, word [bp-006h] ; 8b 56 fa ; 0xc40d2 vbe.c:424 + inc dx ; 42 ; 0xc40d5 + inc dx ; 42 ; 0xc40d6 + add dx, cx ; 01 ca ; 0xc40d7 + mov ax, 003b6h ; b8 b6 03 ; 0xc40d9 + call 03e93h ; e8 b4 fd ; 0xc40dc + mov di, bx ; 89 df ; 0xc40df vbe.c:425 + add di, cx ; 01 cf ; 0xc40e1 + mov es, si ; 8e c6 ; 0xc40e3 vbe.c:52 + mov byte [es:di], al ; 26 88 05 ; 0xc40e5 + inc cx ; 41 ; 0xc40e8 vbe.c:426 + jmp short 040cdh ; eb e2 ; 0xc40e9 + lea di, [bx+002h] ; 8d 7f 02 ; 0xc40eb vbe.c:427 + mov es, si ; 8e c6 ; 0xc40ee vbe.c:47 + mov al, byte [es:di] ; 26 8a 05 ; 0xc40f0 + test AL, strict byte 001h ; a8 01 ; 0xc40f3 vbe.c:428 + je short 04107h ; 74 10 ; 0xc40f5 + lea di, [bx+00ch] ; 8d 7f 0c ; 0xc40f7 vbe.c:429 + mov word [es:di], 0065ch ; 26 c7 05 5c 06 ; 0xc40fa vbe.c:62 + lea di, [bx+00eh] ; 8d 7f 0e ; 0xc40ff vbe.c:431 + mov word [es:di], 0c000h ; 26 c7 05 00 c0 ; 0xc4102 vbe.c:62 + mov ax, strict word 0000bh ; b8 0b 00 ; 0xc4107 vbe.c:434 + mov dx, 001ceh ; ba ce 01 ; 0xc410a + call 005a0h ; e8 90 c4 ; 0xc410d + mov dx, 001cfh ; ba cf 01 ; 0xc4110 vbe.c:435 + call 005a7h ; e8 91 c4 ; 0xc4113 + add bx, strict byte 0002ah ; 83 c3 2a ; 0xc4116 + mov es, si ; 8e c6 ; 0xc4119 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc411b + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc411e vbe.c:437 + jmp short 04126h ; eb 03 ; 0xc4121 vbe.c:438 + mov ax, 00100h ; b8 00 01 ; 0xc4123 vbe.c:442 + push SS ; 16 ; 0xc4126 vbe.c:445 + pop ES ; 07 ; 0xc4127 + mov bx, word [bp-008h] ; 8b 5e f8 ; 0xc4128 + mov word [es:bx], ax ; 26 89 07 ; 0xc412b + lea sp, [bp-004h] ; 8d 66 fc ; 0xc412e vbe.c:446 + pop di ; 5f ; 0xc4131 + pop si ; 5e ; 0xc4132 + pop bp ; 5d ; 0xc4133 + retn ; c3 ; 0xc4134 + ; disGetNextSymbol 0xc4135 LB 0x42f -> off=0x0 cb=00000000000000e7 uValue=00000000000c4135 'vbe_biosfn_set_mode' +vbe_biosfn_set_mode: ; 0xc4135 LB 0xe7 + push bp ; 55 ; 0xc4135 vbe.c:458 + mov bp, sp ; 89 e5 ; 0xc4136 + push si ; 56 ; 0xc4138 + push di ; 57 ; 0xc4139 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc413a + mov si, ax ; 89 c6 ; 0xc413d + mov word [bp-00ah], dx ; 89 56 f6 ; 0xc413f + test byte [bp-009h], 040h ; f6 46 f7 40 ; 0xc4142 vbe.c:466 + je short 0414dh ; 74 05 ; 0xc4146 + mov ax, strict word 00001h ; b8 01 00 ; 0xc4148 + jmp short 0414fh ; eb 02 ; 0xc414b + xor ax, ax ; 31 c0 ; 0xc414d + mov dx, ax ; 89 c2 ; 0xc414f + test ax, ax ; 85 c0 ; 0xc4151 vbe.c:467 + je short 04158h ; 74 03 ; 0xc4153 + mov ax, strict word 00040h ; b8 40 00 ; 0xc4155 + mov byte [bp-008h], al ; 88 46 f8 ; 0xc4158 + test byte [bp-009h], 080h ; f6 46 f7 80 ; 0xc415b vbe.c:468 + je short 04166h ; 74 05 ; 0xc415f + mov ax, 00080h ; b8 80 00 ; 0xc4161 + jmp short 04168h ; eb 02 ; 0xc4164 + xor ax, ax ; 31 c0 ; 0xc4166 + mov byte [bp-006h], al ; 88 46 fa ; 0xc4168 + and byte [bp-009h], 001h ; 80 66 f7 01 ; 0xc416b vbe.c:470 + cmp word [bp-00ah], 00100h ; 81 7e f6 00 01 ; 0xc416f vbe.c:473 + jnc short 04189h ; 73 13 ; 0xc4174 + xor ax, ax ; 31 c0 ; 0xc4176 vbe.c:477 + call 00610h ; e8 95 c4 ; 0xc4178 + mov al, byte [bp-00ah] ; 8a 46 f6 ; 0xc417b vbe.c:481 + xor ah, ah ; 30 e4 ; 0xc417e + call 01479h ; e8 f6 d2 ; 0xc4180 + mov ax, strict word 0004fh ; b8 4f 00 ; 0xc4183 vbe.c:482 + jmp near 04210h ; e9 87 00 ; 0xc4186 vbe.c:483 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc4189 vbe.c:486 + call 03effh ; e8 70 fd ; 0xc418c + mov bx, ax ; 89 c3 ; 0xc418f + test ax, ax ; 85 c0 ; 0xc4191 vbe.c:488 + je short 0420dh ; 74 78 ; 0xc4193 + lea dx, [bx+014h] ; 8d 57 14 ; 0xc4195 vbe.c:493 + mov ax, 003b6h ; b8 b6 03 ; 0xc4198 + call 03e81h ; e8 e3 fc ; 0xc419b + mov cx, ax ; 89 c1 ; 0xc419e + lea dx, [bx+016h] ; 8d 57 16 ; 0xc41a0 vbe.c:494 + mov ax, 003b6h ; b8 b6 03 ; 0xc41a3 + call 03e81h ; e8 d8 fc ; 0xc41a6 + mov di, ax ; 89 c7 ; 0xc41a9 + lea dx, [bx+01bh] ; 8d 57 1b ; 0xc41ab vbe.c:495 + mov ax, 003b6h ; b8 b6 03 ; 0xc41ae + call 03e93h ; e8 df fc ; 0xc41b1 + mov bl, al ; 88 c3 ; 0xc41b4 + mov dl, al ; 88 c2 ; 0xc41b6 + xor ax, ax ; 31 c0 ; 0xc41b8 vbe.c:503 + call 00610h ; e8 53 c4 ; 0xc41ba + cmp bl, 004h ; 80 fb 04 ; 0xc41bd vbe.c:505 + jne short 041c8h ; 75 06 ; 0xc41c0 + mov ax, strict word 0006ah ; b8 6a 00 ; 0xc41c2 vbe.c:507 + call 01479h ; e8 b1 d2 ; 0xc41c5 + mov al, dl ; 88 d0 ; 0xc41c8 vbe.c:510 + xor ah, ah ; 30 e4 ; 0xc41ca + call 03df8h ; e8 29 fc ; 0xc41cc + mov ax, cx ; 89 c8 ; 0xc41cf vbe.c:511 + call 03da1h ; e8 cd fb ; 0xc41d1 + mov ax, di ; 89 f8 ; 0xc41d4 vbe.c:512 + call 03dc0h ; e8 e7 fb ; 0xc41d6 + xor ax, ax ; 31 c0 ; 0xc41d9 vbe.c:513 + call 00636h ; e8 58 c4 ; 0xc41db + mov dl, byte [bp-006h] ; 8a 56 fa ; 0xc41de vbe.c:514 + or dl, 001h ; 80 ca 01 ; 0xc41e1 + mov al, byte [bp-008h] ; 8a 46 f8 ; 0xc41e4 + xor ah, ah ; 30 e4 ; 0xc41e7 + or al, dl ; 08 d0 ; 0xc41e9 + call 00610h ; e8 22 c4 ; 0xc41eb + call 00708h ; e8 17 c5 ; 0xc41ee vbe.c:515 + mov bx, 000bah ; bb ba 00 ; 0xc41f1 vbe.c:62 + mov ax, strict word 00040h ; b8 40 00 ; 0xc41f4 + mov es, ax ; 8e c0 ; 0xc41f7 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc41f9 + mov word [es:bx], ax ; 26 89 07 ; 0xc41fc + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc41ff vbe.c:518 + or AL, strict byte 060h ; 0c 60 ; 0xc4202 + mov bx, 00087h ; bb 87 00 ; 0xc4204 vbe.c:52 + mov byte [es:bx], al ; 26 88 07 ; 0xc4207 + jmp near 04183h ; e9 76 ff ; 0xc420a + mov ax, 00100h ; b8 00 01 ; 0xc420d vbe.c:527 + push SS ; 16 ; 0xc4210 vbe.c:531 + pop ES ; 07 ; 0xc4211 + mov word [es:si], ax ; 26 89 04 ; 0xc4212 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc4215 vbe.c:532 + pop di ; 5f ; 0xc4218 + pop si ; 5e ; 0xc4219 + pop bp ; 5d ; 0xc421a + retn ; c3 ; 0xc421b + ; disGetNextSymbol 0xc421c LB 0x348 -> off=0x0 cb=0000000000000008 uValue=00000000000c421c 'vbe_biosfn_read_video_state_size' +vbe_biosfn_read_video_state_size: ; 0xc421c LB 0x8 + push bp ; 55 ; 0xc421c vbe.c:534 + mov bp, sp ; 89 e5 ; 0xc421d + mov ax, strict word 00012h ; b8 12 00 ; 0xc421f vbe.c:537 + pop bp ; 5d ; 0xc4222 + retn ; c3 ; 0xc4223 + ; disGetNextSymbol 0xc4224 LB 0x340 -> off=0x0 cb=000000000000004b uValue=00000000000c4224 'vbe_biosfn_save_video_state' +vbe_biosfn_save_video_state: ; 0xc4224 LB 0x4b + push bp ; 55 ; 0xc4224 vbe.c:539 + mov bp, sp ; 89 e5 ; 0xc4225 + push bx ; 53 ; 0xc4227 + push cx ; 51 ; 0xc4228 + push si ; 56 ; 0xc4229 + mov si, ax ; 89 c6 ; 0xc422a + mov bx, dx ; 89 d3 ; 0xc422c + mov ax, strict word 00004h ; b8 04 00 ; 0xc422e vbe.c:543 + mov dx, 001ceh ; ba ce 01 ; 0xc4231 + out DX, ax ; ef ; 0xc4234 + mov dx, 001cfh ; ba cf 01 ; 0xc4235 vbe.c:544 + in ax, DX ; ed ; 0xc4238 + mov es, si ; 8e c6 ; 0xc4239 vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc423b + inc bx ; 43 ; 0xc423e vbe.c:546 + inc bx ; 43 ; 0xc423f + test AL, strict byte 001h ; a8 01 ; 0xc4240 vbe.c:547 + je short 04267h ; 74 23 ; 0xc4242 + mov cx, strict word 00001h ; b9 01 00 ; 0xc4244 vbe.c:549 + jmp short 0424eh ; eb 05 ; 0xc4247 + cmp cx, strict byte 00009h ; 83 f9 09 ; 0xc4249 + jnbe short 04267h ; 77 19 ; 0xc424c + cmp cx, strict byte 00004h ; 83 f9 04 ; 0xc424e vbe.c:550 + je short 04264h ; 74 11 ; 0xc4251 + mov ax, cx ; 89 c8 ; 0xc4253 vbe.c:551 + mov dx, 001ceh ; ba ce 01 ; 0xc4255 + out DX, ax ; ef ; 0xc4258 + mov dx, 001cfh ; ba cf 01 ; 0xc4259 vbe.c:552 + in ax, DX ; ed ; 0xc425c + mov es, si ; 8e c6 ; 0xc425d vbe.c:62 + mov word [es:bx], ax ; 26 89 07 ; 0xc425f + inc bx ; 43 ; 0xc4262 vbe.c:553 + inc bx ; 43 ; 0xc4263 + inc cx ; 41 ; 0xc4264 vbe.c:555 + jmp short 04249h ; eb e2 ; 0xc4265 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc4267 vbe.c:556 + pop si ; 5e ; 0xc426a + pop cx ; 59 ; 0xc426b + pop bx ; 5b ; 0xc426c + pop bp ; 5d ; 0xc426d + retn ; c3 ; 0xc426e + ; disGetNextSymbol 0xc426f LB 0x2f5 -> off=0x0 cb=000000000000008f uValue=00000000000c426f 'vbe_biosfn_restore_video_state' +vbe_biosfn_restore_video_state: ; 0xc426f LB 0x8f + push bp ; 55 ; 0xc426f vbe.c:559 + mov bp, sp ; 89 e5 ; 0xc4270 + push bx ; 53 ; 0xc4272 + push cx ; 51 ; 0xc4273 + push si ; 56 ; 0xc4274 + push ax ; 50 ; 0xc4275 + mov cx, ax ; 89 c1 ; 0xc4276 + mov bx, dx ; 89 d3 ; 0xc4278 + mov es, ax ; 8e c0 ; 0xc427a vbe.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc427c + mov word [bp-008h], ax ; 89 46 f8 ; 0xc427f + inc bx ; 43 ; 0xc4282 vbe.c:564 + inc bx ; 43 ; 0xc4283 + test byte [bp-008h], 001h ; f6 46 f8 01 ; 0xc4284 vbe.c:566 + jne short 0429ah ; 75 10 ; 0xc4288 + mov ax, strict word 00004h ; b8 04 00 ; 0xc428a vbe.c:567 + mov dx, 001ceh ; ba ce 01 ; 0xc428d + out DX, ax ; ef ; 0xc4290 + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc4291 vbe.c:568 + mov dx, 001cfh ; ba cf 01 ; 0xc4294 + out DX, ax ; ef ; 0xc4297 + jmp short 042f6h ; eb 5c ; 0xc4298 vbe.c:569 + mov ax, strict word 00001h ; b8 01 00 ; 0xc429a vbe.c:570 + mov dx, 001ceh ; ba ce 01 ; 0xc429d + out DX, ax ; ef ; 0xc42a0 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc42a1 vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc42a4 vbe.c:58 + out DX, ax ; ef ; 0xc42a7 + inc bx ; 43 ; 0xc42a8 vbe.c:572 + inc bx ; 43 ; 0xc42a9 + mov ax, strict word 00002h ; b8 02 00 ; 0xc42aa + mov dx, 001ceh ; ba ce 01 ; 0xc42ad + out DX, ax ; ef ; 0xc42b0 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc42b1 vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc42b4 vbe.c:58 + out DX, ax ; ef ; 0xc42b7 + inc bx ; 43 ; 0xc42b8 vbe.c:575 + inc bx ; 43 ; 0xc42b9 + mov ax, strict word 00003h ; b8 03 00 ; 0xc42ba + mov dx, 001ceh ; ba ce 01 ; 0xc42bd + out DX, ax ; ef ; 0xc42c0 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc42c1 vbe.c:57 + mov dx, 001cfh ; ba cf 01 ; 0xc42c4 vbe.c:58 + out DX, ax ; ef ; 0xc42c7 + inc bx ; 43 ; 0xc42c8 vbe.c:578 + inc bx ; 43 ; 0xc42c9 + mov ax, strict word 00004h ; b8 04 00 ; 0xc42ca + mov dx, 001ceh ; ba ce 01 ; 0xc42cd + out DX, ax ; ef ; 0xc42d0 + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc42d1 vbe.c:580 + mov dx, 001cfh ; ba cf 01 ; 0xc42d4 + out DX, ax ; ef ; 0xc42d7 + mov si, strict word 00005h ; be 05 00 ; 0xc42d8 vbe.c:582 + jmp short 042e2h ; eb 05 ; 0xc42db + cmp si, strict byte 00009h ; 83 fe 09 ; 0xc42dd + jnbe short 042f6h ; 77 14 ; 0xc42e0 + mov ax, si ; 89 f0 ; 0xc42e2 vbe.c:583 + mov dx, 001ceh ; ba ce 01 ; 0xc42e4 + out DX, ax ; ef ; 0xc42e7 + mov es, cx ; 8e c1 ; 0xc42e8 vbe.c:57 + mov ax, word [es:bx] ; 26 8b 07 ; 0xc42ea + mov dx, 001cfh ; ba cf 01 ; 0xc42ed vbe.c:58 + out DX, ax ; ef ; 0xc42f0 + inc bx ; 43 ; 0xc42f1 vbe.c:585 + inc bx ; 43 ; 0xc42f2 + inc si ; 46 ; 0xc42f3 vbe.c:586 + jmp short 042ddh ; eb e7 ; 0xc42f4 + lea sp, [bp-006h] ; 8d 66 fa ; 0xc42f6 vbe.c:588 + pop si ; 5e ; 0xc42f9 + pop cx ; 59 ; 0xc42fa + pop bx ; 5b ; 0xc42fb + pop bp ; 5d ; 0xc42fc + retn ; c3 ; 0xc42fd + ; disGetNextSymbol 0xc42fe LB 0x266 -> off=0x0 cb=000000000000008d uValue=00000000000c42fe 'vbe_biosfn_save_restore_state' +vbe_biosfn_save_restore_state: ; 0xc42fe LB 0x8d + push bp ; 55 ; 0xc42fe vbe.c:604 + mov bp, sp ; 89 e5 ; 0xc42ff + push si ; 56 ; 0xc4301 + push di ; 57 ; 0xc4302 + push ax ; 50 ; 0xc4303 + mov si, ax ; 89 c6 ; 0xc4304 + mov word [bp-006h], dx ; 89 56 fa ; 0xc4306 + mov ax, bx ; 89 d8 ; 0xc4309 + mov bx, word [bp+004h] ; 8b 5e 04 ; 0xc430b + mov di, strict word 0004fh ; bf 4f 00 ; 0xc430e vbe.c:609 + xor ah, ah ; 30 e4 ; 0xc4311 vbe.c:610 + cmp ax, strict word 00002h ; 3d 02 00 ; 0xc4313 + je short 0435eh ; 74 46 ; 0xc4316 + cmp ax, strict word 00001h ; 3d 01 00 ; 0xc4318 + je short 04342h ; 74 25 ; 0xc431b + test ax, ax ; 85 c0 ; 0xc431d + jne short 0437ah ; 75 59 ; 0xc431f + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc4321 vbe.c:612 + call 032b8h ; e8 91 ef ; 0xc4324 + mov cx, ax ; 89 c1 ; 0xc4327 + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc4329 vbe.c:616 + je short 04334h ; 74 05 ; 0xc432d + call 0421ch ; e8 ea fe ; 0xc432f vbe.c:617 + add ax, cx ; 01 c8 ; 0xc4332 + add ax, strict word 0003fh ; 05 3f 00 ; 0xc4334 vbe.c:618 + mov CL, strict byte 006h ; b1 06 ; 0xc4337 + shr ax, CL ; d3 e8 ; 0xc4339 + push SS ; 16 ; 0xc433b + pop ES ; 07 ; 0xc433c + mov word [es:bx], ax ; 26 89 07 ; 0xc433d + jmp short 0437dh ; eb 3b ; 0xc4340 vbe.c:619 + push SS ; 16 ; 0xc4342 vbe.c:621 + pop ES ; 07 ; 0xc4343 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc4344 + mov dx, cx ; 89 ca ; 0xc4347 vbe.c:622 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc4349 + call 032f6h ; e8 a7 ef ; 0xc434c + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc434f vbe.c:626 + je short 0437dh ; 74 28 ; 0xc4353 + mov dx, ax ; 89 c2 ; 0xc4355 vbe.c:627 + mov ax, cx ; 89 c8 ; 0xc4357 + call 04224h ; e8 c8 fe ; 0xc4359 + jmp short 0437dh ; eb 1f ; 0xc435c vbe.c:628 + push SS ; 16 ; 0xc435e vbe.c:630 + pop ES ; 07 ; 0xc435f + mov bx, word [es:bx] ; 26 8b 1f ; 0xc4360 + mov dx, cx ; 89 ca ; 0xc4363 vbe.c:631 + mov ax, word [bp-006h] ; 8b 46 fa ; 0xc4365 + call 035ceh ; e8 63 f2 ; 0xc4368 + test byte [bp-006h], 008h ; f6 46 fa 08 ; 0xc436b vbe.c:635 + je short 0437dh ; 74 0c ; 0xc436f + mov dx, ax ; 89 c2 ; 0xc4371 vbe.c:636 + mov ax, cx ; 89 c8 ; 0xc4373 + call 0426fh ; e8 f7 fe ; 0xc4375 + jmp short 0437dh ; eb 03 ; 0xc4378 vbe.c:637 + mov di, 00100h ; bf 00 01 ; 0xc437a vbe.c:640 + push SS ; 16 ; 0xc437d vbe.c:643 + pop ES ; 07 ; 0xc437e + mov word [es:si], di ; 26 89 3c ; 0xc437f + lea sp, [bp-004h] ; 8d 66 fc ; 0xc4382 vbe.c:644 + pop di ; 5f ; 0xc4385 + pop si ; 5e ; 0xc4386 + pop bp ; 5d ; 0xc4387 + retn 00002h ; c2 02 00 ; 0xc4388 + ; disGetNextSymbol 0xc438b LB 0x1d9 -> off=0x0 cb=00000000000000e2 uValue=00000000000c438b 'vbe_biosfn_get_set_scanline_length' +vbe_biosfn_get_set_scanline_length: ; 0xc438b LB 0xe2 + push bp ; 55 ; 0xc438b vbe.c:665 + mov bp, sp ; 89 e5 ; 0xc438c + push si ; 56 ; 0xc438e + push di ; 57 ; 0xc438f + sub sp, strict byte 0000ah ; 83 ec 0a ; 0xc4390 + push ax ; 50 ; 0xc4393 + mov di, dx ; 89 d7 ; 0xc4394 + mov word [bp-006h], bx ; 89 5e fa ; 0xc4396 + mov si, cx ; 89 ce ; 0xc4399 + call 03e17h ; e8 79 fa ; 0xc439b vbe.c:674 + cmp AL, strict byte 00fh ; 3c 0f ; 0xc439e vbe.c:675 + jne short 043a7h ; 75 05 ; 0xc43a0 + mov cx, strict word 00010h ; b9 10 00 ; 0xc43a2 + jmp short 043abh ; eb 04 ; 0xc43a5 + xor ah, ah ; 30 e4 ; 0xc43a7 + mov cx, ax ; 89 c1 ; 0xc43a9 + mov ch, cl ; 88 cd ; 0xc43ab + call 03e4fh ; e8 9f fa ; 0xc43ad vbe.c:676 + mov word [bp-00ah], ax ; 89 46 f6 ; 0xc43b0 + mov word [bp-00ch], strict word 0004fh ; c7 46 f4 4f 00 ; 0xc43b3 vbe.c:677 + push SS ; 16 ; 0xc43b8 vbe.c:678 + pop ES ; 07 ; 0xc43b9 + mov bx, word [bp-006h] ; 8b 5e fa ; 0xc43ba + mov bx, word [es:bx] ; 26 8b 1f ; 0xc43bd + mov al, byte [es:di] ; 26 8a 05 ; 0xc43c0 vbe.c:679 + cmp AL, strict byte 002h ; 3c 02 ; 0xc43c3 vbe.c:683 + je short 043d2h ; 74 0b ; 0xc43c5 + cmp AL, strict byte 001h ; 3c 01 ; 0xc43c7 + je short 043fbh ; 74 30 ; 0xc43c9 + test al, al ; 84 c0 ; 0xc43cb + je short 043f6h ; 74 27 ; 0xc43cd + jmp near 04456h ; e9 84 00 ; 0xc43cf + cmp ch, 004h ; 80 fd 04 ; 0xc43d2 vbe.c:685 + jne short 043ddh ; 75 06 ; 0xc43d5 + mov CL, strict byte 003h ; b1 03 ; 0xc43d7 vbe.c:686 + sal bx, CL ; d3 e3 ; 0xc43d9 + jmp short 043f6h ; eb 19 ; 0xc43db vbe.c:687 + mov al, ch ; 88 e8 ; 0xc43dd vbe.c:688 + xor ah, ah ; 30 e4 ; 0xc43df + cwd ; 99 ; 0xc43e1 + mov CL, strict byte 003h ; b1 03 ; 0xc43e2 + sal dx, CL ; d3 e2 ; 0xc43e4 + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc43e6 + sar ax, CL ; d3 f8 ; 0xc43e8 + mov word [bp-00eh], ax ; 89 46 f2 ; 0xc43ea + mov ax, bx ; 89 d8 ; 0xc43ed + xor dx, dx ; 31 d2 ; 0xc43ef + div word [bp-00eh] ; f7 76 f2 ; 0xc43f1 + mov bx, ax ; 89 c3 ; 0xc43f4 + mov ax, bx ; 89 d8 ; 0xc43f6 vbe.c:691 + call 03e30h ; e8 35 fa ; 0xc43f8 + call 03e4fh ; e8 51 fa ; 0xc43fb vbe.c:694 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc43fe + push SS ; 16 ; 0xc4401 vbe.c:695 + pop ES ; 07 ; 0xc4402 + mov bx, word [bp-006h] ; 8b 5e fa ; 0xc4403 + mov word [es:bx], ax ; 26 89 07 ; 0xc4406 + cmp ch, 004h ; 80 fd 04 ; 0xc4409 vbe.c:696 + jne short 04416h ; 75 08 ; 0xc440c + mov CL, strict byte 003h ; b1 03 ; 0xc440e vbe.c:697 + mov bx, ax ; 89 c3 ; 0xc4410 + shr bx, CL ; d3 eb ; 0xc4412 + jmp short 0442ch ; eb 16 ; 0xc4414 vbe.c:698 + mov al, ch ; 88 e8 ; 0xc4416 vbe.c:699 + xor ah, ah ; 30 e4 ; 0xc4418 + cwd ; 99 ; 0xc441a + mov CL, strict byte 003h ; b1 03 ; 0xc441b + sal dx, CL ; d3 e2 ; 0xc441d + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc441f + sar ax, CL ; d3 f8 ; 0xc4421 + mov bx, ax ; 89 c3 ; 0xc4423 + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc4425 + mul bx ; f7 e3 ; 0xc4428 + mov bx, ax ; 89 c3 ; 0xc442a + add bx, strict byte 00003h ; 83 c3 03 ; 0xc442c vbe.c:700 + and bl, 0fch ; 80 e3 fc ; 0xc442f + push SS ; 16 ; 0xc4432 vbe.c:701 + pop ES ; 07 ; 0xc4433 + mov word [es:di], bx ; 26 89 1d ; 0xc4434 + call 03e68h ; e8 2e fa ; 0xc4437 vbe.c:702 + push SS ; 16 ; 0xc443a + pop ES ; 07 ; 0xc443b + mov word [es:si], ax ; 26 89 04 ; 0xc443c + call 03ddfh ; e8 9d f9 ; 0xc443f vbe.c:703 + push SS ; 16 ; 0xc4442 + pop ES ; 07 ; 0xc4443 + cmp ax, word [es:si] ; 26 3b 04 ; 0xc4444 + jbe short 0445bh ; 76 12 ; 0xc4447 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc4449 vbe.c:704 + call 03e30h ; e8 e1 f9 ; 0xc444c + mov word [bp-00ch], 00200h ; c7 46 f4 00 02 ; 0xc444f vbe.c:705 + jmp short 0445bh ; eb 05 ; 0xc4454 vbe.c:707 + mov word [bp-00ch], 00100h ; c7 46 f4 00 01 ; 0xc4456 vbe.c:710 + push SS ; 16 ; 0xc445b vbe.c:713 + pop ES ; 07 ; 0xc445c + mov ax, word [bp-00ch] ; 8b 46 f4 ; 0xc445d + mov bx, word [bp-010h] ; 8b 5e f0 ; 0xc4460 + mov word [es:bx], ax ; 26 89 07 ; 0xc4463 + lea sp, [bp-004h] ; 8d 66 fc ; 0xc4466 vbe.c:714 + pop di ; 5f ; 0xc4469 + pop si ; 5e ; 0xc446a + pop bp ; 5d ; 0xc446b + retn ; c3 ; 0xc446c + ; disGetNextSymbol 0xc446d LB 0xf7 -> off=0x0 cb=00000000000000f7 uValue=00000000000c446d 'private_biosfn_custom_mode' +private_biosfn_custom_mode: ; 0xc446d LB 0xf7 + push bp ; 55 ; 0xc446d vbe.c:740 + mov bp, sp ; 89 e5 ; 0xc446e + push si ; 56 ; 0xc4470 + push di ; 57 ; 0xc4471 + sub sp, strict byte 00006h ; 83 ec 06 ; 0xc4472 + push ax ; 50 ; 0xc4475 + mov si, dx ; 89 d6 ; 0xc4476 + mov di, cx ; 89 cf ; 0xc4478 + mov word [bp-00ah], strict word 0004fh ; c7 46 f6 4f 00 ; 0xc447a vbe.c:753 + push SS ; 16 ; 0xc447f vbe.c:754 + pop ES ; 07 ; 0xc4480 + mov al, byte [es:si] ; 26 8a 04 ; 0xc4481 + test al, al ; 84 c0 ; 0xc4484 vbe.c:755 + jne short 044a8h ; 75 20 ; 0xc4486 + push SS ; 16 ; 0xc4488 vbe.c:757 + pop ES ; 07 ; 0xc4489 + mov bx, word [es:bx] ; 26 8b 1f ; 0xc448a + mov ax, word [es:di] ; 26 8b 05 ; 0xc448d vbe.c:758 + mov word [bp-008h], ax ; 89 46 f8 ; 0xc4490 + mov al, byte [es:si+001h] ; 26 8a 44 01 ; 0xc4493 vbe.c:759 + and ax, strict word 0007fh ; 25 7f 00 ; 0xc4497 + mov ch, al ; 88 c5 ; 0xc449a + cmp AL, strict byte 008h ; 3c 08 ; 0xc449c vbe.c:764 + je short 044b0h ; 74 10 ; 0xc449e + cmp AL, strict byte 010h ; 3c 10 ; 0xc44a0 + je short 044b0h ; 74 0c ; 0xc44a2 + cmp AL, strict byte 020h ; 3c 20 ; 0xc44a4 + je short 044b0h ; 74 08 ; 0xc44a6 + mov word [bp-00ah], 00100h ; c7 46 f6 00 01 ; 0xc44a8 vbe.c:765 + jmp near 04552h ; e9 a2 00 ; 0xc44ad vbe.c:766 + push SS ; 16 ; 0xc44b0 vbe.c:770 + pop ES ; 07 ; 0xc44b1 + test byte [es:si+001h], 080h ; 26 f6 44 01 80 ; 0xc44b2 + je short 044beh ; 74 05 ; 0xc44b7 + mov ax, strict word 00040h ; b8 40 00 ; 0xc44b9 + jmp short 044c0h ; eb 02 ; 0xc44bc + xor ax, ax ; 31 c0 ; 0xc44be + mov byte [bp-006h], al ; 88 46 fa ; 0xc44c0 + cmp bx, 00280h ; 81 fb 80 02 ; 0xc44c3 vbe.c:773 + jnc short 044ceh ; 73 05 ; 0xc44c7 + mov bx, 00280h ; bb 80 02 ; 0xc44c9 vbe.c:774 + jmp short 044d7h ; eb 09 ; 0xc44cc vbe.c:775 + cmp bx, 00a00h ; 81 fb 00 0a ; 0xc44ce + jbe short 044d7h ; 76 03 ; 0xc44d2 + mov bx, 00a00h ; bb 00 0a ; 0xc44d4 vbe.c:776 + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc44d7 vbe.c:777 + cmp ax, 001e0h ; 3d e0 01 ; 0xc44da + jnc short 044e6h ; 73 07 ; 0xc44dd + mov word [bp-008h], 001e0h ; c7 46 f8 e0 01 ; 0xc44df vbe.c:778 + jmp short 044f0h ; eb 0a ; 0xc44e4 vbe.c:779 + cmp ax, 00780h ; 3d 80 07 ; 0xc44e6 + jbe short 044f0h ; 76 05 ; 0xc44e9 + mov word [bp-008h], 00780h ; c7 46 f8 80 07 ; 0xc44eb vbe.c:780 + mov dx, strict word 0ffffh ; ba ff ff ; 0xc44f0 vbe.c:786 + mov ax, 003b6h ; b8 b6 03 ; 0xc44f3 + call 03e81h ; e8 88 f9 ; 0xc44f6 + mov si, ax ; 89 c6 ; 0xc44f9 + mov al, ch ; 88 e8 ; 0xc44fb vbe.c:789 + xor ah, ah ; 30 e4 ; 0xc44fd + cwd ; 99 ; 0xc44ff + mov CL, strict byte 003h ; b1 03 ; 0xc4500 + sal dx, CL ; d3 e2 ; 0xc4502 + db 01bh, 0c2h + ; sbb ax, dx ; 1b c2 ; 0xc4504 + sar ax, CL ; d3 f8 ; 0xc4506 + mov dx, ax ; 89 c2 ; 0xc4508 + mov ax, bx ; 89 d8 ; 0xc450a + mul dx ; f7 e2 ; 0xc450c + add ax, strict word 00003h ; 05 03 00 ; 0xc450e vbe.c:790 + and AL, strict byte 0fch ; 24 fc ; 0xc4511 + mov dx, word [bp-008h] ; 8b 56 f8 ; 0xc4513 vbe.c:792 + mul dx ; f7 e2 ; 0xc4516 + cmp dx, si ; 39 f2 ; 0xc4518 vbe.c:794 + jnbe short 04522h ; 77 06 ; 0xc451a + jne short 04529h ; 75 0b ; 0xc451c + test ax, ax ; 85 c0 ; 0xc451e + jbe short 04529h ; 76 07 ; 0xc4520 + mov word [bp-00ah], 00200h ; c7 46 f6 00 02 ; 0xc4522 vbe.c:796 + jmp short 04552h ; eb 29 ; 0xc4527 vbe.c:797 + xor ax, ax ; 31 c0 ; 0xc4529 vbe.c:801 + call 00610h ; e8 e2 c0 ; 0xc452b + mov al, ch ; 88 e8 ; 0xc452e vbe.c:802 + xor ah, ah ; 30 e4 ; 0xc4530 + call 03df8h ; e8 c3 f8 ; 0xc4532 + mov ax, bx ; 89 d8 ; 0xc4535 vbe.c:803 + call 03da1h ; e8 67 f8 ; 0xc4537 + mov ax, word [bp-008h] ; 8b 46 f8 ; 0xc453a vbe.c:804 + call 03dc0h ; e8 80 f8 ; 0xc453d + xor ax, ax ; 31 c0 ; 0xc4540 vbe.c:805 + call 00636h ; e8 f1 c0 ; 0xc4542 + mov al, byte [bp-006h] ; 8a 46 fa ; 0xc4545 vbe.c:806 + or AL, strict byte 001h ; 0c 01 ; 0xc4548 + xor ah, ah ; 30 e4 ; 0xc454a + call 00610h ; e8 c1 c0 ; 0xc454c + call 00708h ; e8 b6 c1 ; 0xc454f vbe.c:807 + push SS ; 16 ; 0xc4552 vbe.c:815 + pop ES ; 07 ; 0xc4553 + mov ax, word [bp-00ah] ; 8b 46 f6 ; 0xc4554 + mov bx, word [bp-00ch] ; 8b 5e f4 ; 0xc4557 + mov word [es:bx], ax ; 26 89 07 ; 0xc455a + lea sp, [bp-004h] ; 8d 66 fc ; 0xc455d vbe.c:816 + pop di ; 5f ; 0xc4560 + pop si ; 5e ; 0xc4561 + pop bp ; 5d ; 0xc4562 + retn ; c3 ; 0xc4563 + + ; Padding 0xdc bytes at 0xc4564 + times 220 db 0 + +section VBE32 progbits vstart=0x4640 align=1 ; size=0x115 class=CODE group=AUTO + ; disGetNextSymbol 0xc4640 LB 0x115 -> off=0x0 cb=0000000000000114 uValue=00000000000c0000 'vesa_pm_start' +vesa_pm_start: ; 0xc4640 LB 0x114 + sbb byte [bx+si], al ; 18 00 ; 0xc4640 + dec di ; 4f ; 0xc4642 + add byte [bx+si], dl ; 00 10 ; 0xc4643 + add word [bx+si], cx ; 01 08 ; 0xc4645 + add dh, cl ; 00 ce ; 0xc4647 + add di, cx ; 01 cf ; 0xc4649 + add di, cx ; 01 cf ; 0xc464b + add ax, dx ; 01 d0 ; 0xc464d + add word [bp-048fdh], si ; 01 b6 03 b7 ; 0xc464f + db 003h, 0ffh + ; add di, di ; 03 ff ; 0xc4653 + db 0ffh + db 0ffh + jmp word [bp-07dh] ; ff 66 83 ; 0xc4657 + sti ; fb ; 0xc465a + add byte [si+005h], dh ; 00 74 05 ; 0xc465b + mov eax, strict dword 066c30100h ; 66 b8 00 01 c3 66 ; 0xc465e vberom.asm:825 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc4664 + push edx ; 66 52 ; 0xc4666 vberom.asm:829 + push eax ; 66 50 ; 0xc4668 vberom.asm:830 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc466a vberom.asm:831 + add ax, 06600h ; 05 00 66 ; 0xc4670 + out DX, ax ; ef ; 0xc4673 + pop eax ; 66 58 ; 0xc4674 vberom.asm:834 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc4676 vberom.asm:835 + in eax, DX ; 66 ed ; 0xc467c vberom.asm:837 + pop edx ; 66 5a ; 0xc467e vberom.asm:838 + db 066h, 03bh, 0d0h + ; cmp edx, eax ; 66 3b d0 ; 0xc4680 vberom.asm:839 + jne short 0468ah ; 75 05 ; 0xc4683 vberom.asm:840 + mov eax, strict dword 066c3004fh ; 66 b8 4f 00 c3 66 ; 0xc4685 vberom.asm:841 + mov ax, 0014fh ; b8 4f 01 ; 0xc468b + retn ; c3 ; 0xc468e vberom.asm:845 + cmp bl, 080h ; 80 fb 80 ; 0xc468f vberom.asm:847 + je short 0469eh ; 74 0a ; 0xc4692 vberom.asm:848 + cmp bl, 000h ; 80 fb 00 ; 0xc4694 vberom.asm:849 + je short 046aeh ; 74 15 ; 0xc4697 vberom.asm:850 + mov eax, strict dword 052c30100h ; 66 b8 00 01 c3 52 ; 0xc4699 vberom.asm:851 + mov edx, strict dword 0a8ec03dah ; 66 ba da 03 ec a8 ; 0xc469f vberom.asm:855 + or byte [di-005h], dh ; 08 75 fb ; 0xc46a5 + in AL, DX ; ec ; 0xc46a8 vberom.asm:861 + test AL, strict byte 008h ; a8 08 ; 0xc46a9 vberom.asm:862 + je short 046a8h ; 74 fb ; 0xc46ab vberom.asm:863 + pop dx ; 5a ; 0xc46ad vberom.asm:864 + push ax ; 50 ; 0xc46ae vberom.asm:868 + push cx ; 51 ; 0xc46af vberom.asm:869 + push dx ; 52 ; 0xc46b0 vberom.asm:870 + push si ; 56 ; 0xc46b1 vberom.asm:871 + push di ; 57 ; 0xc46b2 vberom.asm:872 + sal dx, 010h ; c1 e2 10 ; 0xc46b3 vberom.asm:873 + and cx, strict word 0ffffh ; 81 e1 ff ff ; 0xc46b6 vberom.asm:874 + add byte [bx+si], al ; 00 00 ; 0xc46ba + db 00bh, 0cah + ; or cx, dx ; 0b ca ; 0xc46bc vberom.asm:875 + sal cx, 002h ; c1 e1 02 ; 0xc46be vberom.asm:876 + db 08bh, 0c1h + ; mov ax, cx ; 8b c1 ; 0xc46c1 vberom.asm:877 + push ax ; 50 ; 0xc46c3 vberom.asm:878 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc46c4 vberom.asm:879 + push ES ; 06 ; 0xc46ca + add byte [bp-011h], ah ; 00 66 ef ; 0xc46cb + mov edx, strict dword 0ed6601cfh ; 66 ba cf 01 66 ed ; 0xc46ce vberom.asm:882 + db 00fh, 0b7h, 0c8h + ; movzx cx, ax ; 0f b7 c8 ; 0xc46d4 vberom.asm:884 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc46d7 vberom.asm:885 + add ax, word [bx+si] ; 03 00 ; 0xc46dd + out DX, eax ; 66 ef ; 0xc46df vberom.asm:887 + mov edx, strict dword 0ed6601cfh ; 66 ba cf 01 66 ed ; 0xc46e1 vberom.asm:888 + db 00fh, 0b7h, 0f0h + ; movzx si, ax ; 0f b7 f0 ; 0xc46e7 vberom.asm:890 + pop ax ; 58 ; 0xc46ea vberom.asm:891 + cmp si, strict byte 00004h ; 83 fe 04 ; 0xc46eb vberom.asm:893 + je short 04707h ; 74 17 ; 0xc46ee vberom.asm:894 + add si, strict byte 00007h ; 83 c6 07 ; 0xc46f0 vberom.asm:895 + shr si, 003h ; c1 ee 03 ; 0xc46f3 vberom.asm:896 + imul cx, si ; 0f af ce ; 0xc46f6 vberom.asm:897 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc46f9 vberom.asm:898 + div cx ; f7 f1 ; 0xc46fb vberom.asm:899 + db 08bh, 0f8h + ; mov di, ax ; 8b f8 ; 0xc46fd vberom.asm:900 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc46ff vberom.asm:901 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc4701 vberom.asm:902 + div si ; f7 f6 ; 0xc4703 vberom.asm:903 + jmp short 04713h ; eb 0c ; 0xc4705 vberom.asm:904 + shr cx, 1 ; d1 e9 ; 0xc4707 vberom.asm:907 + db 033h, 0d2h + ; xor dx, dx ; 33 d2 ; 0xc4709 vberom.asm:908 + div cx ; f7 f1 ; 0xc470b vberom.asm:909 + db 08bh, 0f8h + ; mov di, ax ; 8b f8 ; 0xc470d vberom.asm:910 + db 08bh, 0c2h + ; mov ax, dx ; 8b c2 ; 0xc470f vberom.asm:911 + sal ax, 1 ; d1 e0 ; 0xc4711 vberom.asm:912 + push edx ; 66 52 ; 0xc4713 vberom.asm:915 + push eax ; 66 50 ; 0xc4715 vberom.asm:916 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc4717 vberom.asm:917 + or byte [bx+si], al ; 08 00 ; 0xc471d + out DX, eax ; 66 ef ; 0xc471f vberom.asm:919 + pop eax ; 66 58 ; 0xc4721 vberom.asm:920 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc4723 vberom.asm:921 + pop edx ; 66 5a ; 0xc4729 vberom.asm:923 + db 066h, 08bh, 0c7h + ; mov eax, edi ; 66 8b c7 ; 0xc472b vberom.asm:925 + push edx ; 66 52 ; 0xc472e vberom.asm:926 + push eax ; 66 50 ; 0xc4730 vberom.asm:927 + mov edx, strict dword 0b86601ceh ; 66 ba ce 01 66 b8 ; 0xc4732 vberom.asm:928 + or word [bx+si], ax ; 09 00 ; 0xc4738 + out DX, eax ; 66 ef ; 0xc473a vberom.asm:930 + pop eax ; 66 58 ; 0xc473c vberom.asm:931 + mov edx, strict dword 0ef6601cfh ; 66 ba cf 01 66 ef ; 0xc473e vberom.asm:932 + pop edx ; 66 5a ; 0xc4744 vberom.asm:934 + pop di ; 5f ; 0xc4746 vberom.asm:936 + pop si ; 5e ; 0xc4747 vberom.asm:937 + pop dx ; 5a ; 0xc4748 vberom.asm:938 + pop cx ; 59 ; 0xc4749 vberom.asm:939 + pop ax ; 58 ; 0xc474a vberom.asm:940 + mov eax, strict dword 066c3004fh ; 66 b8 4f 00 c3 66 ; 0xc474b vberom.asm:941 + mov ax, 0014fh ; b8 4f 01 ; 0xc4751 + ; disGetNextSymbol 0xc4754 LB 0x1 -> off=0x0 cb=0000000000000001 uValue=0000000000000114 'vesa_pm_end' +vesa_pm_end: ; 0xc4754 LB 0x1 + retn ; c3 ; 0xc4754 vberom.asm:946 + + ; Padding 0x2b bytes at 0xc4755 + times 43 db 0 + +section _DATA progbits vstart=0x4780 align=1 ; size=0x374d class=DATA group=DGROUP + ; disGetNextSymbol 0xc4780 LB 0x374d -> off=0x0 cb=000000000000002f uValue=00000000000c0000 '_msg_vga_init' +_msg_vga_init: ; 0xc4780 LB 0x2f + db 'Oracle VM VirtualBox Version 7.0.14 VGA BIOS', 00dh, 00ah, 000h + ; disGetNextSymbol 0xc47af LB 0x371e -> off=0x0 cb=0000000000000080 uValue=00000000000c002f 'vga_modes' +vga_modes: ; 0xc47af LB 0x80 + db 000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h + db 002h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 003h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h + db 004h, 001h, 002h, 002h, 000h, 0b8h, 0ffh, 001h, 005h, 001h, 002h, 002h, 000h, 0b8h, 0ffh, 001h + db 006h, 001h, 002h, 001h, 000h, 0b8h, 0ffh, 001h, 007h, 000h, 001h, 004h, 000h, 0b0h, 0ffh, 000h + db 00dh, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 001h, 00eh, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 001h + db 00fh, 001h, 003h, 001h, 000h, 0a0h, 0ffh, 000h, 010h, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + db 011h, 001h, 003h, 001h, 000h, 0a0h, 0ffh, 002h, 012h, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + db 013h, 001h, 005h, 008h, 000h, 0a0h, 0ffh, 003h, 06ah, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h + ; disGetNextSymbol 0xc482f LB 0x369e -> off=0x0 cb=0000000000000010 uValue=00000000000c00af 'line_to_vpti' +line_to_vpti: ; 0xc482f LB 0x10 + db 017h, 017h, 018h, 018h, 004h, 005h, 006h, 007h, 00dh, 00eh, 011h, 012h, 01ah, 01bh, 01ch, 01dh + ; disGetNextSymbol 0xc483f LB 0x368e -> off=0x0 cb=0000000000000004 uValue=00000000000c00bf 'dac_regs' +dac_regs: ; 0xc483f LB 0x4 + dd 0ff3f3f3fh + ; disGetNextSymbol 0xc4843 LB 0x368a -> off=0x0 cb=0000000000000780 uValue=00000000000c00c3 'video_param_table' +video_param_table: ; 0xc4843 LB 0x780 + db 028h, 018h, 008h, 000h, 008h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 008h, 000h, 008h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 008h, 000h, 010h, 001h, 003h, 000h, 002h, 063h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 008h, 000h, 010h, 001h, 003h, 000h, 002h, 063h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 0c7h, 006h, 007h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 008h, 000h, 040h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0a2h, 0ffh, 000h, 013h, 015h, 017h, 002h, 004h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 003h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 00fh, 00fh, 0ffh + db 028h, 018h, 008h, 000h, 040h, 009h, 003h, 000h, 002h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0a2h, 0ffh, 000h, 013h, 015h, 017h, 002h, 004h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 003h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 00fh, 00fh, 0ffh + db 050h, 018h, 008h, 000h, 040h, 001h, 001h, 000h, 006h, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 0c1h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 000h, 096h + db 0b9h, 0c2h, 0ffh, 000h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h, 017h + db 017h, 017h, 017h, 001h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 00dh, 00fh, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 000h, 003h, 000h, 003h, 0a6h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00dh, 063h + db 0bah, 0a3h, 0ffh, 000h, 008h, 008h, 008h, 008h, 008h, 008h, 008h, 010h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 00eh, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00ah, 000h, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 028h, 018h, 008h, 000h, 020h, 009h, 00fh, 000h, 006h, 063h, 02dh, 027h, 028h, 090h, 02bh, 080h + db 0bfh, 01fh, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 000h, 096h + db 0b9h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 018h, 008h, 000h, 040h, 001h, 00fh, 000h, 006h, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 000h, 096h + db 0b9h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 010h, 011h, 012h, 013h, 014h + db 015h, 016h, 017h, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 050h, 018h, 00eh, 000h, 080h, 001h, 00fh, 000h, 006h, 0a3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00fh, 063h + db 0bah, 0e3h, 0ffh, 000h, 008h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 008h, 000h, 000h, 000h + db 018h, 000h, 000h, 001h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 018h, 00eh, 000h, 080h, 001h, 00fh, 000h, 006h, 0a3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 00fh, 063h + db 0bah, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 028h, 018h, 00eh, 000h, 008h, 009h, 003h, 000h, 002h, 0a3h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 014h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 00eh, 000h, 008h, 009h, 003h, 000h, 002h, 0a3h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 014h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 001h, 003h, 000h, 002h, 0a3h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 050h, 018h, 00eh, 000h, 010h, 001h, 003h, 000h, 002h, 0a3h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04dh, 00bh, 00ch, 000h, 000h, 000h, 000h, 083h, 085h, 05dh, 028h, 01fh, 063h + db 0bah, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 008h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 000h, 0ffh + db 028h, 018h, 010h, 000h, 008h, 008h, 003h, 000h, 002h, 067h, 02dh, 027h, 028h, 090h, 02bh, 0a0h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 014h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 00ch, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 00fh, 0ffh + db 050h, 018h, 010h, 000h, 010h, 000h, 003h, 000h, 002h, 067h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 01fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 00ch, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00eh, 00fh, 0ffh + db 050h, 018h, 010h, 000h, 010h, 000h, 003h, 000h, 002h, 066h, 05fh, 04fh, 050h, 082h, 055h, 081h + db 0bfh, 01fh, 000h, 04fh, 00dh, 00eh, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 00fh, 096h + db 0b9h, 0a3h, 0ffh, 000h, 008h, 008h, 008h, 008h, 008h, 008h, 008h, 010h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 00eh, 000h, 00fh, 008h, 000h, 000h, 000h, 000h, 000h, 010h, 00ah, 00fh, 0ffh + db 050h, 01dh, 010h, 000h, 0a0h, 001h, 00fh, 000h, 006h, 0e3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 00bh, 03eh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 0eah, 08ch, 0dfh, 028h, 000h, 0e7h + db 004h, 0c3h, 0ffh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h, 03fh, 000h + db 03fh, 000h, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 050h, 01dh, 010h, 000h, 0a0h, 001h, 00fh, 000h, 006h, 0e3h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 00bh, 03eh, 000h, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 0eah, 08ch, 0dfh, 028h, 000h, 0e7h + db 004h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + db 028h, 018h, 008h, 000h, 020h, 001h, 00fh, 000h, 00eh, 063h, 05fh, 04fh, 050h, 082h, 054h, 080h + db 0bfh, 01fh, 000h, 041h, 000h, 000h, 000h, 000h, 000h, 000h, 09ch, 08eh, 08fh, 028h, 040h, 096h + db 0b9h, 0a3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 008h, 009h, 00ah, 00bh, 00ch + db 00dh, 00eh, 00fh, 041h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 040h, 005h, 00fh, 0ffh + db 064h, 024h, 010h, 000h, 000h, 001h, 00fh, 000h, 006h, 0e3h, 07fh, 063h, 063h, 083h, 06bh, 01bh + db 072h, 0f0h, 000h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 059h, 08dh, 057h, 032h, 000h, 057h + db 073h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch + db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh + ; disGetNextSymbol 0xc4fc3 LB 0x2f0a -> off=0x0 cb=00000000000000c0 uValue=00000000000c0843 'palette0' +palette0: ; 0xc4fc3 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah + db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + db 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5083 LB 0x2e4a -> off=0x0 cb=00000000000000c0 uValue=00000000000c0903 'palette1' +palette1: ; 0xc5083 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah + db 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah, 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah + db 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh, 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh + db 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah + db 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah, 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah + db 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh, 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh + db 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5143 LB 0x2d8a -> off=0x0 cb=00000000000000c0 uValue=00000000000c09c3 'palette2' +palette2: ; 0xc5143 LB 0xc0 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 02ah, 000h, 02ah, 02ah, 02ah, 000h, 000h, 015h, 000h, 000h, 03fh, 000h, 02ah + db 015h, 000h, 02ah, 03fh, 02ah, 000h, 015h, 02ah, 000h, 03fh, 02ah, 02ah, 015h, 02ah, 02ah, 03fh + db 000h, 015h, 000h, 000h, 015h, 02ah, 000h, 03fh, 000h, 000h, 03fh, 02ah, 02ah, 015h, 000h, 02ah + db 015h, 02ah, 02ah, 03fh, 000h, 02ah, 03fh, 02ah, 000h, 015h, 015h, 000h, 015h, 03fh, 000h, 03fh + db 015h, 000h, 03fh, 03fh, 02ah, 015h, 015h, 02ah, 015h, 03fh, 02ah, 03fh, 015h, 02ah, 03fh, 03fh + db 015h, 000h, 000h, 015h, 000h, 02ah, 015h, 02ah, 000h, 015h, 02ah, 02ah, 03fh, 000h, 000h, 03fh + db 000h, 02ah, 03fh, 02ah, 000h, 03fh, 02ah, 02ah, 015h, 000h, 015h, 015h, 000h, 03fh, 015h, 02ah + db 015h, 015h, 02ah, 03fh, 03fh, 000h, 015h, 03fh, 000h, 03fh, 03fh, 02ah, 015h, 03fh, 02ah, 03fh + db 015h, 015h, 000h, 015h, 015h, 02ah, 015h, 03fh, 000h, 015h, 03fh, 02ah, 03fh, 015h, 000h, 03fh + db 015h, 02ah, 03fh, 03fh, 000h, 03fh, 03fh, 02ah, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + ; disGetNextSymbol 0xc5203 LB 0x2cca -> off=0x0 cb=0000000000000300 uValue=00000000000c0a83 'palette3' +palette3: ; 0xc5203 LB 0x300 + db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah + db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh + db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh + db 000h, 000h, 000h, 005h, 005h, 005h, 008h, 008h, 008h, 00bh, 00bh, 00bh, 00eh, 00eh, 00eh, 011h + db 011h, 011h, 014h, 014h, 014h, 018h, 018h, 018h, 01ch, 01ch, 01ch, 020h, 020h, 020h, 024h, 024h + db 024h, 028h, 028h, 028h, 02dh, 02dh, 02dh, 032h, 032h, 032h, 038h, 038h, 038h, 03fh, 03fh, 03fh + db 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh, 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h, 03fh, 03fh + db 000h, 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh + db 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h, 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 000h + db 000h, 03fh, 000h, 000h, 03fh, 010h, 000h, 03fh, 01fh, 000h, 03fh, 02fh, 000h, 03fh, 03fh, 000h + db 02fh, 03fh, 000h, 01fh, 03fh, 000h, 010h, 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh, 02fh, 01fh + db 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 03fh, 03fh, 01fh, 037h, 03fh, 01fh, 02fh, 03fh, 01fh, 027h + db 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh, 02fh, 01fh, 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 037h + db 03fh, 01fh, 02fh, 03fh, 01fh, 027h, 03fh, 01fh, 01fh, 03fh, 01fh, 01fh, 03fh, 027h, 01fh, 03fh + db 02fh, 01fh, 03fh, 037h, 01fh, 03fh, 03fh, 01fh, 037h, 03fh, 01fh, 02fh, 03fh, 01fh, 027h, 03fh + db 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h, 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh, 03fh, 03fh + db 02dh, 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h + db 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh, 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 02dh + db 02dh, 03fh, 02dh, 02dh, 03fh, 031h, 02dh, 03fh, 036h, 02dh, 03fh, 03ah, 02dh, 03fh, 03fh, 02dh + db 03ah, 03fh, 02dh, 036h, 03fh, 02dh, 031h, 03fh, 000h, 000h, 01ch, 007h, 000h, 01ch, 00eh, 000h + db 01ch, 015h, 000h, 01ch, 01ch, 000h, 01ch, 01ch, 000h, 015h, 01ch, 000h, 00eh, 01ch, 000h, 007h + db 01ch, 000h, 000h, 01ch, 007h, 000h, 01ch, 00eh, 000h, 01ch, 015h, 000h, 01ch, 01ch, 000h, 015h + db 01ch, 000h, 00eh, 01ch, 000h, 007h, 01ch, 000h, 000h, 01ch, 000h, 000h, 01ch, 007h, 000h, 01ch + db 00eh, 000h, 01ch, 015h, 000h, 01ch, 01ch, 000h, 015h, 01ch, 000h, 00eh, 01ch, 000h, 007h, 01ch + db 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h, 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh, 01ch, 01ch + db 00eh, 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h + db 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh, 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 00eh + db 00eh, 01ch, 00eh, 00eh, 01ch, 011h, 00eh, 01ch, 015h, 00eh, 01ch, 018h, 00eh, 01ch, 01ch, 00eh + db 018h, 01ch, 00eh, 015h, 01ch, 00eh, 011h, 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch, 018h, 014h + db 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ch, 01ch, 014h, 01ah, 01ch, 014h, 018h, 01ch, 014h, 016h + db 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch, 018h, 014h, 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ah + db 01ch, 014h, 018h, 01ch, 014h, 016h, 01ch, 014h, 014h, 01ch, 014h, 014h, 01ch, 016h, 014h, 01ch + db 018h, 014h, 01ch, 01ah, 014h, 01ch, 01ch, 014h, 01ah, 01ch, 014h, 018h, 01ch, 014h, 016h, 01ch + db 000h, 000h, 010h, 004h, 000h, 010h, 008h, 000h, 010h, 00ch, 000h, 010h, 010h, 000h, 010h, 010h + db 000h, 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 000h, 000h, 010h, 004h, 000h, 010h, 008h + db 000h, 010h, 00ch, 000h, 010h, 010h, 000h, 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 000h + db 000h, 010h, 000h, 000h, 010h, 004h, 000h, 010h, 008h, 000h, 010h, 00ch, 000h, 010h, 010h, 000h + db 00ch, 010h, 000h, 008h, 010h, 000h, 004h, 010h, 008h, 008h, 010h, 00ah, 008h, 010h, 00ch, 008h + db 010h, 00eh, 008h, 010h, 010h, 008h, 010h, 010h, 008h, 00eh, 010h, 008h, 00ch, 010h, 008h, 00ah + db 010h, 008h, 008h, 010h, 00ah, 008h, 010h, 00ch, 008h, 010h, 00eh, 008h, 010h, 010h, 008h, 00eh + db 010h, 008h, 00ch, 010h, 008h, 00ah, 010h, 008h, 008h, 010h, 008h, 008h, 010h, 00ah, 008h, 010h + db 00ch, 008h, 010h, 00eh, 008h, 010h, 010h, 008h, 00eh, 010h, 008h, 00ch, 010h, 008h, 00ah, 010h + db 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh, 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh, 010h, 010h + db 00bh, 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh + db 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh, 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 00bh + db 00bh, 010h, 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh, 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh + db 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5503 LB 0x29ca -> off=0x0 cb=0000000000000010 uValue=00000000000c0d83 'static_functionality' +static_functionality: ; 0xc5503 LB 0x10 + db 0ffh, 0e0h, 00fh, 000h, 000h, 000h, 000h, 007h, 002h, 008h, 0e7h, 00ch, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5513 LB 0x29ba -> off=0x0 cb=0000000000000024 uValue=00000000000c0d93 '_dcc_table' +_dcc_table: ; 0xc5513 LB 0x24 + db 010h, 001h, 007h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5537 LB 0x2996 -> off=0x0 cb=000000000000001a uValue=00000000000c0db7 '_secondary_save_area' +_secondary_save_area: ; 0xc5537 LB 0x1a + db 01ah, 000h, 013h, 055h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5551 LB 0x297c -> off=0x0 cb=000000000000001c uValue=00000000000c0dd1 '_video_save_pointer_table' +_video_save_pointer_table: ; 0xc5551 LB 0x1c + db 043h, 048h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 037h, 055h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc556d LB 0x2960 -> off=0x0 cb=0000000000000800 uValue=00000000000c0ded 'vgafont8' +vgafont8: ; 0xc556d LB 0x800 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 081h, 0a5h, 081h, 0bdh, 099h, 081h, 07eh + db 07eh, 0ffh, 0dbh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 06ch, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h + db 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 038h, 07ch, 038h, 0feh, 0feh, 07ch, 038h, 07ch + db 010h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 07ch, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h + db 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h + db 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 00fh, 007h, 00fh, 07dh, 0cch, 0cch, 0cch, 078h + db 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 03fh, 033h, 03fh, 030h, 030h, 070h, 0f0h, 0e0h + db 07fh, 063h, 07fh, 063h, 063h, 067h, 0e6h, 0c0h, 099h, 05ah, 03ch, 0e7h, 0e7h, 03ch, 05ah, 099h + db 080h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 080h, 000h, 002h, 00eh, 03eh, 0feh, 03eh, 00eh, 002h, 000h + db 018h, 03ch, 07eh, 018h, 018h, 07eh, 03ch, 018h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 000h + db 07fh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 000h, 03eh, 063h, 038h, 06ch, 06ch, 038h, 0cch, 078h + db 000h, 000h, 000h, 000h, 07eh, 07eh, 07eh, 000h, 018h, 03ch, 07eh, 018h, 07eh, 03ch, 018h, 0ffh + db 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h + db 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h + db 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h + db 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 000h, 000h, 000h, 0ffh, 0ffh, 07eh, 03ch, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 078h, 078h, 030h, 030h, 000h, 030h, 000h + db 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 0feh, 06ch, 06ch, 000h + db 030h, 07ch, 0c0h, 078h, 00ch, 0f8h, 030h, 000h, 000h, 0c6h, 0cch, 018h, 030h, 066h, 0c6h, 000h + db 038h, 06ch, 038h, 076h, 0dch, 0cch, 076h, 000h, 060h, 060h, 0c0h, 000h, 000h, 000h, 000h, 000h + db 018h, 030h, 060h, 060h, 060h, 030h, 018h, 000h, 060h, 030h, 018h, 018h, 018h, 030h, 060h, 000h + db 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 060h, 000h, 000h, 000h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 030h, 000h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h + db 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 07ch, 000h, 030h, 070h, 030h, 030h, 030h, 030h, 0fch, 000h + db 078h, 0cch, 00ch, 038h, 060h, 0cch, 0fch, 000h, 078h, 0cch, 00ch, 038h, 00ch, 0cch, 078h, 000h + db 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 01eh, 000h, 0fch, 0c0h, 0f8h, 00ch, 00ch, 0cch, 078h, 000h + db 038h, 060h, 0c0h, 0f8h, 0cch, 0cch, 078h, 000h, 0fch, 0cch, 00ch, 018h, 030h, 030h, 030h, 000h + db 078h, 0cch, 0cch, 078h, 0cch, 0cch, 078h, 000h, 078h, 0cch, 0cch, 07ch, 00ch, 018h, 070h, 000h + db 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 000h, 000h, 030h, 030h, 060h + db 018h, 030h, 060h, 0c0h, 060h, 030h, 018h, 000h, 000h, 000h, 0fch, 000h, 000h, 0fch, 000h, 000h + db 060h, 030h, 018h, 00ch, 018h, 030h, 060h, 000h, 078h, 0cch, 00ch, 018h, 030h, 000h, 030h, 000h + db 07ch, 0c6h, 0deh, 0deh, 0deh, 0c0h, 078h, 000h, 030h, 078h, 0cch, 0cch, 0fch, 0cch, 0cch, 000h + db 0fch, 066h, 066h, 07ch, 066h, 066h, 0fch, 000h, 03ch, 066h, 0c0h, 0c0h, 0c0h, 066h, 03ch, 000h + db 0f8h, 06ch, 066h, 066h, 066h, 06ch, 0f8h, 000h, 0feh, 062h, 068h, 078h, 068h, 062h, 0feh, 000h + db 0feh, 062h, 068h, 078h, 068h, 060h, 0f0h, 000h, 03ch, 066h, 0c0h, 0c0h, 0ceh, 066h, 03eh, 000h + db 0cch, 0cch, 0cch, 0fch, 0cch, 0cch, 0cch, 000h, 078h, 030h, 030h, 030h, 030h, 030h, 078h, 000h + db 01eh, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 0e6h, 066h, 06ch, 078h, 06ch, 066h, 0e6h, 000h + db 0f0h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 000h + db 0c6h, 0e6h, 0f6h, 0deh, 0ceh, 0c6h, 0c6h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h + db 0fch, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 078h, 0cch, 0cch, 0cch, 0dch, 078h, 01ch, 000h + db 0fch, 066h, 066h, 07ch, 06ch, 066h, 0e6h, 000h, 078h, 0cch, 0e0h, 070h, 01ch, 0cch, 078h, 000h + db 0fch, 0b4h, 030h, 030h, 030h, 030h, 078h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 0fch, 000h + db 0cch, 0cch, 0cch, 0cch, 0cch, 078h, 030h, 000h, 0c6h, 0c6h, 0c6h, 0d6h, 0feh, 0eeh, 0c6h, 000h + db 0c6h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 030h, 078h, 000h + db 0feh, 0c6h, 08ch, 018h, 032h, 066h, 0feh, 000h, 078h, 060h, 060h, 060h, 060h, 060h, 078h, 000h + db 0c0h, 060h, 030h, 018h, 00ch, 006h, 002h, 000h, 078h, 018h, 018h, 018h, 018h, 018h, 078h, 000h + db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 076h, 000h + db 0e0h, 060h, 060h, 07ch, 066h, 066h, 0dch, 000h, 000h, 000h, 078h, 0cch, 0c0h, 0cch, 078h, 000h + db 01ch, 00ch, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h + db 038h, 06ch, 060h, 0f0h, 060h, 060h, 0f0h, 000h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 0f8h + db 0e0h, 060h, 06ch, 076h, 066h, 066h, 0e6h, 000h, 030h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 00ch, 000h, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 0e0h, 060h, 066h, 06ch, 078h, 06ch, 0e6h, 000h + db 070h, 030h, 030h, 030h, 030h, 030h, 078h, 000h, 000h, 000h, 0cch, 0feh, 0feh, 0d6h, 0c6h, 000h + db 000h, 000h, 0f8h, 0cch, 0cch, 0cch, 0cch, 000h, 000h, 000h, 078h, 0cch, 0cch, 0cch, 078h, 000h + db 000h, 000h, 0dch, 066h, 066h, 07ch, 060h, 0f0h, 000h, 000h, 076h, 0cch, 0cch, 07ch, 00ch, 01eh + db 000h, 000h, 0dch, 076h, 066h, 060h, 0f0h, 000h, 000h, 000h, 07ch, 0c0h, 078h, 00ch, 0f8h, 000h + db 010h, 030h, 07ch, 030h, 030h, 034h, 018h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 0cch, 0cch, 0cch, 078h, 030h, 000h, 000h, 000h, 0c6h, 0d6h, 0feh, 0feh, 06ch, 000h + db 000h, 000h, 0c6h, 06ch, 038h, 06ch, 0c6h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 07ch, 00ch, 0f8h + db 000h, 000h, 0fch, 098h, 030h, 064h, 0fch, 000h, 01ch, 030h, 030h, 0e0h, 030h, 030h, 01ch, 000h + db 018h, 018h, 018h, 000h, 018h, 018h, 018h, 000h, 0e0h, 030h, 030h, 01ch, 030h, 030h, 0e0h, 000h + db 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h + db 078h, 0cch, 0c0h, 0cch, 078h, 018h, 00ch, 078h, 000h, 0cch, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 01ch, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h, 07eh, 0c3h, 03ch, 006h, 03eh, 066h, 03fh, 000h + db 0cch, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 0e0h, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h + db 030h, 030h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 000h, 000h, 078h, 0c0h, 0c0h, 078h, 00ch, 038h + db 07eh, 0c3h, 03ch, 066h, 07eh, 060h, 03ch, 000h, 0cch, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h + db 0e0h, 000h, 078h, 0cch, 0fch, 0c0h, 078h, 000h, 0cch, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 07ch, 0c6h, 038h, 018h, 018h, 018h, 03ch, 000h, 0e0h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 0c6h, 038h, 06ch, 0c6h, 0feh, 0c6h, 0c6h, 000h, 030h, 030h, 000h, 078h, 0cch, 0fch, 0cch, 000h + db 01ch, 000h, 0fch, 060h, 078h, 060h, 0fch, 000h, 000h, 000h, 07fh, 00ch, 07fh, 0cch, 07fh, 000h + db 03eh, 06ch, 0cch, 0feh, 0cch, 0cch, 0ceh, 000h, 078h, 0cch, 000h, 078h, 0cch, 0cch, 078h, 000h + db 000h, 0cch, 000h, 078h, 0cch, 0cch, 078h, 000h, 000h, 0e0h, 000h, 078h, 0cch, 0cch, 078h, 000h + db 078h, 0cch, 000h, 0cch, 0cch, 0cch, 07eh, 000h, 000h, 0e0h, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 000h, 0cch, 000h, 0cch, 0cch, 07ch, 00ch, 0f8h, 0c3h, 018h, 03ch, 066h, 066h, 03ch, 018h, 000h + db 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 078h, 000h, 018h, 018h, 07eh, 0c0h, 0c0h, 07eh, 018h, 018h + db 038h, 06ch, 064h, 0f0h, 060h, 0e6h, 0fch, 000h, 0cch, 0cch, 078h, 0fch, 030h, 0fch, 030h, 030h + db 0f8h, 0cch, 0cch, 0fah, 0c6h, 0cfh, 0c6h, 0c7h, 00eh, 01bh, 018h, 03ch, 018h, 018h, 0d8h, 070h + db 01ch, 000h, 078h, 00ch, 07ch, 0cch, 07eh, 000h, 038h, 000h, 070h, 030h, 030h, 030h, 078h, 000h + db 000h, 01ch, 000h, 078h, 0cch, 0cch, 078h, 000h, 000h, 01ch, 000h, 0cch, 0cch, 0cch, 07eh, 000h + db 000h, 0f8h, 000h, 0f8h, 0cch, 0cch, 0cch, 000h, 0fch, 000h, 0cch, 0ech, 0fch, 0dch, 0cch, 000h + db 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h + db 030h, 000h, 030h, 060h, 0c0h, 0cch, 078h, 000h, 000h, 000h, 000h, 0fch, 0c0h, 0c0h, 000h, 000h + db 000h, 000h, 000h, 0fch, 00ch, 00ch, 000h, 000h, 0c3h, 0c6h, 0cch, 0deh, 033h, 066h, 0cch, 00fh + db 0c3h, 0c6h, 0cch, 0dbh, 037h, 06fh, 0cfh, 003h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 000h + db 000h, 033h, 066h, 0cch, 066h, 033h, 000h, 000h, 000h, 0cch, 066h, 033h, 066h, 0cch, 000h, 000h + db 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah + db 0dbh, 077h, 0dbh, 0eeh, 0dbh, 077h, 0dbh, 0eeh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h + db 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 0feh, 006h, 0f6h, 036h, 036h, 036h + db 036h, 036h, 0f6h, 006h, 0feh, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h, 000h + db 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h + db 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h + db 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h + db 036h, 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0f7h, 036h, 036h, 036h + db 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h, 000h + db 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 03fh, 000h, 000h, 000h + db 018h, 018h, 01fh, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h + db 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 0c8h, 0dch, 076h, 000h, 000h, 078h, 0cch, 0f8h, 0cch, 0f8h, 0c0h, 0c0h + db 000h, 0fch, 0cch, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 0feh, 06ch, 06ch, 06ch, 06ch, 06ch, 000h + db 0fch, 0cch, 060h, 030h, 060h, 0cch, 0fch, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 070h, 000h + db 000h, 066h, 066h, 066h, 066h, 07ch, 060h, 0c0h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 000h + db 0fch, 030h, 078h, 0cch, 0cch, 078h, 030h, 0fch, 038h, 06ch, 0c6h, 0feh, 0c6h, 06ch, 038h, 000h + db 038h, 06ch, 0c6h, 0c6h, 06ch, 06ch, 0eeh, 000h, 01ch, 030h, 018h, 07ch, 0cch, 0cch, 078h, 000h + db 000h, 000h, 07eh, 0dbh, 0dbh, 07eh, 000h, 000h, 006h, 00ch, 07eh, 0dbh, 0dbh, 07eh, 060h, 0c0h + db 038h, 060h, 0c0h, 0f8h, 0c0h, 060h, 038h, 000h, 078h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 000h + db 000h, 0fch, 000h, 0fch, 000h, 0fch, 000h, 000h, 030h, 030h, 0fch, 030h, 030h, 000h, 0fch, 000h + db 060h, 030h, 018h, 030h, 060h, 000h, 0fch, 000h, 018h, 030h, 060h, 030h, 018h, 000h, 0fch, 000h + db 00eh, 01bh, 01bh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h, 070h + db 030h, 030h, 000h, 0fch, 000h, 030h, 030h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h + db 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h, 00fh, 00ch, 00ch, 00ch, 0ech, 06ch, 03ch, 01ch + db 078h, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 070h, 018h, 030h, 060h, 078h, 000h, 000h, 000h + db 000h, 000h, 03ch, 03ch, 03ch, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc5d6d LB 0x2160 -> off=0x0 cb=0000000000000e00 uValue=00000000000c15ed 'vgafont14' +vgafont14: ; 0xc5d6d LB 0xe00 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 07eh, 081h, 0a5h, 081h, 081h, 0bdh, 099h, 081h, 07eh, 000h, 000h, 000h, 000h, 000h, 07eh, 0ffh + db 0dbh, 0ffh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 06ch, 0feh, 0feh + db 0feh, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 07ch, 0feh, 07ch + db 038h, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 0e7h, 0e7h, 0e7h, 018h, 018h + db 03ch, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 07eh, 018h, 018h, 03ch, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h + db 000h, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh + db 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 01eh, 00eh, 01ah, 032h + db 078h, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 066h, 066h, 03ch, 018h + db 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 03fh, 033h, 03fh, 030h, 030h, 030h, 070h, 0f0h + db 0e0h, 000h, 000h, 000h, 000h, 000h, 07fh, 063h, 07fh, 063h, 063h, 063h, 067h, 0e7h, 0e6h, 0c0h + db 000h, 000h, 000h, 000h, 018h, 018h, 0dbh, 03ch, 0e7h, 03ch, 0dbh, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 080h, 0c0h, 0e0h, 0f8h, 0feh, 0f8h, 0e0h, 0c0h, 080h, 000h, 000h, 000h, 000h, 000h + db 002h, 006h, 00eh, 03eh, 0feh, 03eh, 00eh, 006h, 002h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch + db 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h + db 066h, 066h, 000h, 066h, 066h, 000h, 000h, 000h, 000h, 000h, 07fh, 0dbh, 0dbh, 0dbh, 07bh, 01bh + db 01bh, 01bh, 01bh, 000h, 000h, 000h, 000h, 07ch, 0c6h, 060h, 038h, 06ch, 0c6h, 0c6h, 06ch, 038h + db 00ch, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 0feh, 000h + db 000h, 000h, 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 07eh, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 030h, 060h + db 0feh, 060h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c0h + db 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 028h, 06ch, 0feh, 06ch, 028h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 038h, 07ch, 07ch, 0feh, 0feh, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 07ch, 07ch, 038h, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 03ch, 03ch, 03ch, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 066h, 066h, 066h + db 024h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch + db 06ch, 06ch, 0feh, 06ch, 06ch, 000h, 000h, 000h, 018h, 018h, 07ch, 0c6h, 0c2h, 0c0h, 07ch, 006h + db 086h, 0c6h, 07ch, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 0c2h, 0c6h, 00ch, 018h, 030h, 066h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 038h, 06ch, 06ch, 038h, 076h, 0dch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 030h, 030h, 030h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 018h, 030h, 030h, 030h, 030h, 030h, 018h, 00ch, 000h, 000h, 000h, 000h, 000h + db 030h, 018h, 00ch, 00ch, 00ch, 00ch, 00ch, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h + db 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h + db 000h, 000h, 000h, 000h, 002h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0ceh, 0deh, 0f6h, 0e6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 018h, 038h, 078h, 018h, 018h, 018h, 018h, 018h, 07eh, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h + db 006h, 00ch, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 006h, 006h + db 03ch, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 00ch, 01ch, 03ch, 06ch, 0cch, 0feh + db 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0fch, 006h, 006h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 038h, 060h, 0c0h, 0c0h, 0fch, 0c6h, 0c6h, 0c6h, 07ch, 000h + db 000h, 000h, 000h, 000h, 0feh, 0c6h, 006h, 00ch, 018h, 030h, 030h, 030h, 030h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 07ch, 0c6h, 0c6h, 0c6h, 07eh, 006h, 006h, 00ch, 078h, 000h, 000h, 000h, 000h, 000h, 000h, 018h + db 018h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h + db 000h, 000h, 018h, 018h, 030h, 000h, 000h, 000h, 000h, 000h, 006h, 00ch, 018h, 030h, 060h, 030h + db 018h, 00ch, 006h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 000h, 000h, 07eh, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 060h, 000h + db 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 00ch, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0deh, 0deh, 0deh, 0dch, 0c0h, 07ch, 000h, 000h, 000h, 000h, 000h + db 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h, 0fch, 066h + db 066h, 066h, 07ch, 066h, 066h, 066h, 0fch, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 0c2h, 0c0h + db 0c0h, 0c0h, 0c2h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h, 0f8h, 06ch, 066h, 066h, 066h, 066h + db 066h, 06ch, 0f8h, 000h, 000h, 000h, 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 062h, 066h + db 0feh, 000h, 000h, 000h, 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0deh, 0c6h, 066h, 03ah, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h + db 03ch, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 01eh, 00ch + db 00ch, 00ch, 00ch, 00ch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h, 000h, 0e6h, 066h, 06ch, 06ch + db 078h, 06ch, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 0f0h, 060h, 060h, 060h, 060h, 060h + db 062h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 0c6h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 000h + db 000h, 000h, 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h, 000h + db 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0deh, 07ch, 00ch, 00eh, 000h, 000h, 000h, 000h, 0fch, 066h + db 066h, 066h, 07ch, 06ch, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 060h + db 038h, 00ch, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 07eh, 07eh, 05ah, 018h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 010h, 000h + db 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0d6h, 0feh, 07ch, 06ch, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 06ch, 038h, 038h, 038h, 06ch, 0c6h, 0c6h, 000h, 000h, 000h, 000h, 000h + db 066h, 066h, 066h, 066h, 03ch, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 0feh, 0c6h + db 08ch, 018h, 030h, 060h, 0c2h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 03ch, 030h, 030h, 030h + db 030h, 030h, 030h, 030h, 03ch, 000h, 000h, 000h, 000h, 000h, 080h, 0c0h, 0e0h, 070h, 038h, 01ch + db 00eh, 006h, 002h, 000h, 000h, 000h, 000h, 000h, 03ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch + db 03ch, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 0e0h, 060h + db 060h, 078h, 06ch, 066h, 066h, 066h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch + db 0c6h, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 01ch, 00ch, 00ch, 03ch, 06ch, 0cch + db 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 07ch, 00ch, 0cch, 078h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 06ch, 076h, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 006h, 006h + db 000h, 00eh, 006h, 006h, 006h, 006h, 066h, 066h, 03ch, 000h, 000h, 000h, 0e0h, 060h, 060h, 066h + db 06ch, 078h, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ech, 0feh, 0d6h, 0d6h, 0d6h + db 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h, 000h, 000h + db 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 07ch, 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h, 000h + db 000h, 0dch, 076h, 066h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch + db 0c6h, 070h, 01ch, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 010h, 030h, 030h, 0fch, 030h, 030h + db 030h, 036h, 01ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch + db 076h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 03ch, 018h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0d6h, 0d6h, 0feh, 06ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 06ch, 038h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 0f8h, 000h, 000h, 000h, 000h, 000h + db 000h, 0feh, 0cch, 018h, 030h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h, 00eh, 018h, 018h, 018h + db 070h, 018h, 018h, 018h, 00eh, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 000h, 018h + db 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 070h, 018h, 018h, 018h, 00eh, 018h, 018h, 018h + db 070h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 00ch, 006h, 07ch, 000h, 000h, 000h + db 0cch, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 00ch, 018h, 030h + db 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 000h, 078h + db 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 000h, 078h, 00ch, 07ch + db 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 078h, 00ch, 07ch, 0cch, 0cch + db 076h, 000h, 000h, 000h, 000h, 038h, 06ch, 038h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 060h, 066h, 03ch, 00ch, 006h, 03ch, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 0cch, 0cch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h + db 000h, 07ch, 0c6h, 0feh, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 000h, 038h + db 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 018h, 03ch, 066h, 000h, 038h, 018h, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 038h, 018h, 018h, 018h, 018h + db 03ch, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 000h + db 000h, 000h, 038h, 06ch, 038h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 000h, 000h, 000h + db 018h, 030h, 060h, 000h, 0feh, 066h, 060h, 07ch, 060h, 066h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 0cch, 076h, 036h, 07eh, 0d8h, 0d8h, 06eh, 000h, 000h, 000h, 000h, 000h, 03eh, 06ch + db 0cch, 0cch, 0feh, 0cch, 0cch, 0cch, 0ceh, 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 000h, 07ch + db 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 000h, 07ch, 0c6h, 0c6h + db 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h + db 07ch, 000h, 000h, 000h, 000h, 030h, 078h, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h + db 000h, 000h, 000h, 060h, 030h, 018h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 078h, 000h, 000h, 0c6h + db 0c6h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 000h + db 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 018h, 018h, 03ch, 066h, 060h + db 060h, 066h, 03ch, 018h, 018h, 000h, 000h, 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h + db 060h, 0e6h, 0fch, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 03ch, 018h, 07eh, 018h, 07eh, 018h + db 018h, 000h, 000h, 000h, 000h, 0f8h, 0cch, 0cch, 0f8h, 0c4h, 0cch, 0deh, 0cch, 0cch, 0c6h, 000h + db 000h, 000h, 000h, 00eh, 01bh, 018h, 018h, 018h, 07eh, 018h, 018h, 018h, 018h, 0d8h, 070h, 000h + db 000h, 018h, 030h, 060h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 00ch + db 018h, 030h, 000h, 038h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 018h, 030h, 060h + db 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 018h, 030h, 060h, 000h, 0cch + db 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 0dch, 066h, 066h + db 066h, 066h, 066h, 000h, 000h, 000h, 076h, 0dch, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h + db 0c6h, 000h, 000h, 000h, 000h, 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 030h, 000h, 030h, 030h, 060h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 006h, 006h, 006h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c6h, 0cch, 0d8h + db 030h, 060h, 0dch, 086h, 00ch, 018h, 03eh, 000h, 000h, 0c0h, 0c0h, 0c6h, 0cch, 0d8h, 030h, 066h + db 0ceh, 09eh, 03eh, 006h, 006h, 000h, 000h, 000h, 018h, 018h, 000h, 018h, 018h, 03ch, 03ch, 03ch + db 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 036h, 06ch, 0d8h, 06ch, 036h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0d8h, 06ch, 036h, 06ch, 0d8h, 000h, 000h, 000h, 000h, 000h + db 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 055h, 0aah + db 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 0ddh, 077h, 0ddh, 077h + db 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h + db 018h, 018h, 018h, 018h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 036h + db 036h, 036h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 036h, 036h + db 036h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 000h, 0feh + db 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0feh + db 000h, 000h, 000h, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h + db 018h, 018h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 030h, 037h + db 036h, 036h, 036h, 036h, 036h, 036h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h + db 000h, 000h, 000h, 000h, 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 036h + db 036h, 036h, 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h + db 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 0f0h, 0f0h, 0f0h, 0f0h, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh + db 00fh, 00fh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 0d8h, 0d8h, 0dch, 076h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0fch, 0c6h, 0c6h, 0fch, 0c0h, 0c0h, 040h, 000h, 000h, 000h, 0feh, 0c6h + db 0c6h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 06ch + db 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 0feh, 0c6h, 060h, 030h, 018h, 030h + db 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 0d8h + db 070h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0c0h + db 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h + db 000h, 000h, 07eh, 018h, 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h, 000h + db 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 038h, 06ch + db 0c6h, 0c6h, 0c6h, 06ch, 06ch, 06ch, 0eeh, 000h, 000h, 000h, 000h, 000h, 01eh, 030h, 018h, 00ch + db 03eh, 066h, 066h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 0dbh, 0dbh + db 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 003h, 006h, 07eh, 0dbh, 0dbh, 0f3h, 07eh, 060h + db 0c0h, 000h, 000h, 000h, 000h, 000h, 01ch, 030h, 060h, 060h, 07ch, 060h, 060h, 030h, 01ch, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h + db 000h, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 030h, 018h + db 00ch, 006h, 00ch, 018h, 030h, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 00ch, 018h, 030h, 060h + db 030h, 018h, 00ch, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 00eh, 01bh, 01bh, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h + db 070h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 07eh, 000h, 018h, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 00fh, 00ch, 00ch, 00ch, 00ch + db 00ch, 0ech, 06ch, 03ch, 01ch, 000h, 000h, 000h, 000h, 0d8h, 06ch, 06ch, 06ch, 06ch, 06ch, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 070h, 0d8h, 030h, 060h, 0c8h, 0f8h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc6b6d LB 0x1360 -> off=0x0 cb=0000000000001000 uValue=00000000000c23ed 'vgafont16' +vgafont16: ; 0xc6b6d LB 0x1000 + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 081h, 0a5h, 081h, 081h, 0bdh, 099h, 081h, 081h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 0ffh, 0dbh, 0ffh, 0ffh, 0c3h, 0e7h, 0ffh, 0ffh, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 06ch, 0feh, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 03ch, 03ch, 0e7h, 0e7h, 0e7h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 03ch, 07eh, 0ffh, 0ffh, 07eh, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 018h, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0e7h, 0c3h, 0c3h, 0e7h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 03ch, 066h, 042h, 042h, 066h, 03ch, 000h, 000h, 000h, 000h, 000h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0c3h, 099h, 0bdh, 0bdh, 099h, 0c3h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 01eh, 00eh, 01ah, 032h, 078h, 0cch, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 066h, 066h, 066h, 03ch, 018h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 03fh, 033h, 03fh, 030h, 030h, 030h, 030h, 070h, 0f0h, 0e0h, 000h, 000h, 000h, 000h + db 000h, 000h, 07fh, 063h, 07fh, 063h, 063h, 063h, 063h, 067h, 0e7h, 0e6h, 0c0h, 000h, 000h, 000h + db 000h, 000h, 000h, 018h, 018h, 0dbh, 03ch, 0e7h, 03ch, 0dbh, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0feh, 0f8h, 0f0h, 0e0h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 002h, 006h, 00eh, 01eh, 03eh, 0feh, 03eh, 01eh, 00eh, 006h, 002h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 066h, 066h, 000h, 000h, 000h, 000h + db 000h, 000h, 07fh, 0dbh, 0dbh, 0dbh, 07bh, 01bh, 01bh, 01bh, 01bh, 01bh, 000h, 000h, 000h, 000h + db 000h, 07ch, 0c6h, 060h, 038h, 06ch, 0c6h, 0c6h, 06ch, 038h, 00ch, 0c6h, 07ch, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0feh, 0feh, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 07eh, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 07eh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 018h, 00ch, 0feh, 00ch, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 030h, 060h, 0feh, 060h, 030h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0c0h, 0c0h, 0c0h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 028h, 06ch, 0feh, 06ch, 028h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 038h, 07ch, 07ch, 0feh, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 0feh, 07ch, 07ch, 038h, 038h, 010h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 03ch, 03ch, 03ch, 018h, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 066h, 066h, 066h, 024h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 06ch, 06ch, 0feh, 06ch, 06ch, 06ch, 0feh, 06ch, 06ch, 000h, 000h, 000h, 000h + db 018h, 018h, 07ch, 0c6h, 0c2h, 0c0h, 07ch, 006h, 006h, 086h, 0c6h, 07ch, 018h, 018h, 000h, 000h + db 000h, 000h, 000h, 000h, 0c2h, 0c6h, 00ch, 018h, 030h, 060h, 0c6h, 086h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 06ch, 038h, 076h, 0dch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 030h, 030h, 030h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 018h, 030h, 030h, 030h, 030h, 030h, 030h, 018h, 00ch, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 018h, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 018h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 066h, 03ch, 0ffh, 03ch, 066h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 018h, 030h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 002h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 080h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0d6h, 0d6h, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 038h, 078h, 018h, 018h, 018h, 018h, 018h, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 006h, 00ch, 018h, 030h, 060h, 0c0h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 006h, 006h, 03ch, 006h, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 00ch, 01ch, 03ch, 06ch, 0cch, 0feh, 00ch, 00ch, 00ch, 01eh, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0fch, 006h, 006h, 006h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 060h, 0c0h, 0c0h, 0fch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 006h, 006h, 00ch, 018h, 030h, 030h, 030h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 07eh, 006h, 006h, 006h, 00ch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 018h, 018h, 030h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 006h, 00ch, 018h, 030h, 060h, 030h, 018h, 00ch, 006h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 000h, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 060h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 060h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 00ch, 018h, 018h, 018h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0deh, 0deh, 0deh, 0dch, 0c0h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 066h, 066h, 066h, 066h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0f8h, 06ch, 066h, 066h, 066h, 066h, 066h, 066h, 06ch, 0f8h, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 062h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 066h, 062h, 068h, 078h, 068h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0deh, 0c6h, 0c6h, 066h, 03ah, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 01eh, 00ch, 00ch, 00ch, 00ch, 00ch, 0cch, 0cch, 0cch, 078h, 000h, 000h, 000h, 000h + db 000h, 000h, 0e6h, 066h, 066h, 06ch, 078h, 078h, 06ch, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0f0h, 060h, 060h, 060h, 060h, 060h, 060h, 062h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0eeh, 0feh, 0feh, 0d6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 060h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0deh, 07ch, 00ch, 00eh, 000h, 000h + db 000h, 000h, 0fch, 066h, 066h, 066h, 07ch, 06ch, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 07ch, 0c6h, 0c6h, 060h, 038h, 00ch, 006h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 07eh, 07eh, 05ah, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 06ch, 038h, 010h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0d6h, 0d6h, 0d6h, 0feh, 0eeh, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 0c6h, 06ch, 07ch, 038h, 038h, 07ch, 06ch, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 066h, 066h, 03ch, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 086h, 00ch, 018h, 030h, 060h, 0c2h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 030h, 030h, 030h, 030h, 030h, 030h, 030h, 030h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 080h, 0c0h, 0e0h, 070h, 038h, 01ch, 00eh, 006h, 002h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 00ch, 03ch, 000h, 000h, 000h, 000h + db 010h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 000h + db 030h, 030h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 078h, 06ch, 066h, 066h, 066h, 066h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c0h, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 01ch, 00ch, 00ch, 03ch, 06ch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 0cch, 0cch, 07ch, 00ch, 0cch, 078h, 000h + db 000h, 000h, 0e0h, 060h, 060h, 06ch, 076h, 066h, 066h, 066h, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 006h, 006h, 000h, 00eh, 006h, 006h, 006h, 006h, 006h, 006h, 066h, 066h, 03ch, 000h + db 000h, 000h, 0e0h, 060h, 060h, 066h, 06ch, 078h, 078h, 06ch, 066h, 0e6h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ech, 0feh, 0d6h, 0d6h, 0d6h, 0d6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0f0h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0cch, 0cch, 0cch, 0cch, 0cch, 07ch, 00ch, 00ch, 01eh, 000h + db 000h, 000h, 000h, 000h, 000h, 0dch, 076h, 066h, 060h, 060h, 060h, 0f0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07ch, 0c6h, 060h, 038h, 00ch, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 010h, 030h, 030h, 0fch, 030h, 030h, 030h, 030h, 036h, 01ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 066h, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0d6h, 0d6h, 0d6h, 0feh, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 06ch, 038h, 038h, 038h, 06ch, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 0f8h, 000h + db 000h, 000h, 000h, 000h, 000h, 0feh, 0cch, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 00eh, 018h, 018h, 018h, 070h, 018h, 018h, 018h, 018h, 00eh, 000h, 000h, 000h, 000h + db 000h, 000h, 018h, 018h, 018h, 018h, 000h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 070h, 018h, 018h, 018h, 00eh, 018h, 018h, 018h, 018h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 03ch, 066h, 0c2h, 0c0h, 0c0h, 0c0h, 0c2h, 066h, 03ch, 00ch, 006h, 07ch, 000h, 000h + db 000h, 000h, 0cch, 000h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 00ch, 018h, 030h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0cch, 000h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 038h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 03ch, 066h, 060h, 060h, 066h, 03ch, 00ch, 006h, 03ch, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0feh, 0c0h, 0c0h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 000h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 018h, 03ch, 066h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 0c6h, 000h, 010h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 038h, 06ch, 038h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 018h, 030h, 060h, 000h, 0feh, 066h, 060h, 07ch, 060h, 060h, 066h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0cch, 076h, 036h, 07eh, 0d8h, 0d8h, 06eh, 000h, 000h, 000h, 000h + db 000h, 000h, 03eh, 06ch, 0cch, 0cch, 0feh, 0cch, 0cch, 0cch, 0cch, 0ceh, 000h, 000h, 000h, 000h + db 000h, 010h, 038h, 06ch, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 030h, 078h, 0cch, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 060h, 030h, 018h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 0c6h, 000h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07eh, 006h, 00ch, 078h, 000h + db 000h, 0c6h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 0c6h, 000h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 018h, 018h, 03ch, 066h, 060h, 060h, 060h, 066h, 03ch, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 064h, 060h, 0f0h, 060h, 060h, 060h, 060h, 0e6h, 0fch, 000h, 000h, 000h, 000h + db 000h, 000h, 066h, 066h, 03ch, 018h, 07eh, 018h, 07eh, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 0f8h, 0cch, 0cch, 0f8h, 0c4h, 0cch, 0deh, 0cch, 0cch, 0cch, 0c6h, 000h, 000h, 000h, 000h + db 000h, 00eh, 01bh, 018h, 018h, 018h, 07eh, 018h, 018h, 018h, 018h, 018h, 0d8h, 070h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 078h, 00ch, 07ch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 00ch, 018h, 030h, 000h, 038h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 018h, 030h, 060h, 000h, 0cch, 0cch, 0cch, 0cch, 0cch, 0cch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 076h, 0dch, 000h, 0dch, 066h, 066h, 066h, 066h, 066h, 066h, 000h, 000h, 000h, 000h + db 076h, 0dch, 000h, 0c6h, 0e6h, 0f6h, 0feh, 0deh, 0ceh, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 03ch, 06ch, 06ch, 03eh, 000h, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 07ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 030h, 030h, 000h, 030h, 030h, 060h, 0c0h, 0c6h, 0c6h, 07ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 006h, 006h, 006h, 006h, 000h, 000h, 000h, 000h, 000h + db 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 060h, 0dch, 086h, 00ch, 018h, 03eh, 000h, 000h + db 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 066h, 0ceh, 09eh, 03eh, 006h, 006h, 000h, 000h + db 000h, 000h, 018h, 018h, 000h, 018h, 018h, 018h, 03ch, 03ch, 03ch, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 036h, 06ch, 0d8h, 06ch, 036h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0d8h, 06ch, 036h, 06ch, 0d8h, 000h, 000h, 000h, 000h, 000h, 000h + db 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h, 011h, 044h + db 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah, 055h, 0aah + db 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h, 0ddh, 077h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0feh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0feh, 006h, 0f6h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 0f6h, 006h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0feh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 0f8h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f8h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 03fh, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 0f7h, 000h, 0f7h, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 0ffh, 000h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 03fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 018h, 018h, 018h, 018h, 018h, 01fh, 018h, 01fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 03fh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 036h, 036h, 036h, 036h, 036h, 036h, 036h, 0ffh, 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h + db 018h, 018h, 018h, 018h, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 01fh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h, 0f0h + db 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh, 00fh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 0d8h, 0d8h, 0d8h, 0dch, 076h, 000h, 000h, 000h, 000h + db 000h, 000h, 078h, 0cch, 0cch, 0cch, 0d8h, 0cch, 0c6h, 0c6h, 0c6h, 0cch, 000h, 000h, 000h, 000h + db 000h, 000h, 0feh, 0c6h, 0c6h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 0c0h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 06ch, 06ch, 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0feh, 0c6h, 060h, 030h, 018h, 030h, 060h, 0c6h, 0feh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 0d8h, 0d8h, 0d8h, 0d8h, 0d8h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 066h, 066h, 066h, 066h, 066h, 07ch, 060h, 060h, 0c0h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 076h, 0dch, 018h, 018h, 018h, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07eh, 018h, 03ch, 066h, 066h, 066h, 03ch, 018h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0feh, 0c6h, 0c6h, 06ch, 038h, 000h, 000h, 000h, 000h + db 000h, 000h, 038h, 06ch, 0c6h, 0c6h, 0c6h, 06ch, 06ch, 06ch, 06ch, 0eeh, 000h, 000h, 000h, 000h + db 000h, 000h, 01eh, 030h, 018h, 00ch, 03eh, 066h, 066h, 066h, 066h, 03ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 07eh, 0dbh, 0dbh, 0dbh, 07eh, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 003h, 006h, 07eh, 0dbh, 0dbh, 0f3h, 07eh, 060h, 0c0h, 000h, 000h, 000h, 000h + db 000h, 000h, 01ch, 030h, 060h, 060h, 07ch, 060h, 060h, 060h, 030h, 01ch, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 07ch, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 0c6h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 0feh, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 07eh, 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 030h, 018h, 00ch, 006h, 00ch, 018h, 030h, 000h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 00ch, 018h, 030h, 060h, 030h, 018h, 00ch, 000h, 07eh, 000h, 000h, 000h, 000h + db 000h, 000h, 00eh, 01bh, 01bh, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h + db 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h, 0d8h, 0d8h, 0d8h, 070h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 018h, 018h, 000h, 07eh, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 076h, 0dch, 000h, 076h, 0dch, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 038h, 06ch, 06ch, 038h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 00fh, 00ch, 00ch, 00ch, 00ch, 00ch, 0ech, 06ch, 06ch, 03ch, 01ch, 000h, 000h, 000h, 000h + db 000h, 0d8h, 06ch, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 070h, 0d8h, 030h, 060h, 0c8h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7b6d LB 0x360 -> off=0x0 cb=000000000000012d uValue=00000000000c33ed 'vgafont14alt' +vgafont14alt: ; 0xc7b6d LB 0x12d + db 01dh, 000h, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h, 000h, 000h, 000h, 022h + db 000h, 063h, 063h, 063h, 022h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02bh, 000h + db 000h, 000h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 02dh, 000h, 000h + db 000h, 000h, 000h, 000h, 0ffh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 04dh, 000h, 000h, 0c3h + db 0e7h, 0ffh, 0dbh, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 000h, 000h, 000h, 054h, 000h, 000h, 0ffh, 0dbh + db 099h, 018h, 018h, 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 056h, 000h, 000h, 0c3h, 0c3h, 0c3h + db 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h, 000h, 000h, 000h, 057h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h + db 0dbh, 0dbh, 0ffh, 066h, 066h, 000h, 000h, 000h, 058h, 000h, 000h, 0c3h, 0c3h, 066h, 03ch, 018h + db 03ch, 066h, 0c3h, 0c3h, 000h, 000h, 000h, 059h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 018h, 018h, 03ch, 000h, 000h, 000h, 05ah, 000h, 000h, 0ffh, 0c3h, 086h, 00ch, 018h, 030h, 061h + db 0c3h, 0ffh, 000h, 000h, 000h, 06dh, 000h, 000h, 000h, 000h, 000h, 0e6h, 0ffh, 0dbh, 0dbh, 0dbh + db 0dbh, 000h, 000h, 000h, 076h, 000h, 000h, 000h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 000h, 000h, 000h, 077h, 000h, 000h, 000h, 000h, 000h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh, 066h, 000h + db 000h, 000h, 091h, 000h, 000h, 000h, 000h, 06eh, 03bh, 01bh, 07eh, 0d8h, 0dch, 077h, 000h, 000h + db 000h, 09bh, 000h, 018h, 018h, 07eh, 0c3h, 0c0h, 0c0h, 0c3h, 07eh, 018h, 018h, 000h, 000h, 000h + db 09dh, 000h, 000h, 0c3h, 066h, 03ch, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 000h, 000h, 000h, 09eh + db 000h, 0fch, 066h, 066h, 07ch, 062h, 066h, 06fh, 066h, 066h, 0f3h, 000h, 000h, 000h, 0f1h, 000h + db 000h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 000h, 0ffh, 000h, 000h, 000h, 0f6h, 000h, 000h + db 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7c9a LB 0x233 -> off=0x0 cb=0000000000000144 uValue=00000000000c351a 'vgafont16alt' +vgafont16alt: ; 0xc7c9a LB 0x144 + db 01dh, 000h, 000h, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h, 000h, 000h, 000h + db 000h, 030h, 000h, 000h, 03ch, 066h, 0c3h, 0c3h, 0dbh, 0dbh, 0c3h, 0c3h, 066h, 03ch, 000h, 000h + db 000h, 000h, 04dh, 000h, 000h, 0c3h, 0e7h, 0ffh, 0ffh, 0dbh, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 000h + db 000h, 000h, 000h, 054h, 000h, 000h, 0ffh, 0dbh, 099h, 018h, 018h, 018h, 018h, 018h, 018h, 03ch + db 000h, 000h, 000h, 000h, 056h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 066h, 03ch + db 018h, 000h, 000h, 000h, 000h, 057h, 000h, 000h, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh + db 066h, 066h, 000h, 000h, 000h, 000h, 058h, 000h, 000h, 0c3h, 0c3h, 066h, 03ch, 018h, 018h, 03ch + db 066h, 0c3h, 0c3h, 000h, 000h, 000h, 000h, 059h, 000h, 000h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h + db 018h, 018h, 018h, 03ch, 000h, 000h, 000h, 000h, 05ah, 000h, 000h, 0ffh, 0c3h, 086h, 00ch, 018h + db 030h, 060h, 0c1h, 0c3h, 0ffh, 000h, 000h, 000h, 000h, 06dh, 000h, 000h, 000h, 000h, 000h, 0e6h + db 0ffh, 0dbh, 0dbh, 0dbh, 0dbh, 0dbh, 000h, 000h, 000h, 000h, 076h, 000h, 000h, 000h, 000h, 000h + db 0c3h, 0c3h, 0c3h, 0c3h, 066h, 03ch, 018h, 000h, 000h, 000h, 000h, 077h, 000h, 000h, 000h, 000h + db 000h, 0c3h, 0c3h, 0c3h, 0dbh, 0dbh, 0ffh, 066h, 000h, 000h, 000h, 000h, 078h, 000h, 000h, 000h + db 000h, 000h, 0c3h, 066h, 03ch, 018h, 03ch, 066h, 0c3h, 000h, 000h, 000h, 000h, 091h, 000h, 000h + db 000h, 000h, 000h, 06eh, 03bh, 01bh, 07eh, 0d8h, 0dch, 077h, 000h, 000h, 000h, 000h, 09bh, 000h + db 018h, 018h, 07eh, 0c3h, 0c0h, 0c0h, 0c0h, 0c3h, 07eh, 018h, 018h, 000h, 000h, 000h, 000h, 09dh + db 000h, 000h, 0c3h, 066h, 03ch, 018h, 0ffh, 018h, 0ffh, 018h, 018h, 018h, 000h, 000h, 000h, 000h + db 09eh, 000h, 0fch, 066h, 066h, 07ch, 062h, 066h, 06fh, 066h, 066h, 066h, 0f3h, 000h, 000h, 000h + db 000h, 0abh, 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 060h, 0ceh, 09bh, 006h, 00ch, 01fh + db 000h, 000h, 0ach, 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 066h, 0ceh, 096h, 03eh, 006h + db 006h, 000h, 000h, 000h + ; disGetNextSymbol 0xc7dde LB 0xef -> off=0x0 cb=0000000000000008 uValue=00000000000c365e '_cga_msr' +_cga_msr: ; 0xc7dde LB 0x8 + db 02ch, 028h, 02dh, 029h, 02ah, 02eh, 01eh, 029h + ; disGetNextSymbol 0xc7de6 LB 0xe7 -> off=0x0 cb=0000000000000008 uValue=00000000000c3666 'line_to_vpti_200' +line_to_vpti_200: ; 0xc7de6 LB 0x8 + db 000h, 001h, 002h, 003h, 0ffh, 0ffh, 0ffh, 007h + ; disGetNextSymbol 0xc7dee LB 0xdf -> off=0x0 cb=0000000000000008 uValue=00000000000c366e 'line_to_vpti_350' +line_to_vpti_350: ; 0xc7dee LB 0x8 + db 013h, 014h, 015h, 016h, 0ffh, 0ffh, 0ffh, 007h + ; disGetNextSymbol 0xc7df6 LB 0xd7 -> off=0x0 cb=0000000000000008 uValue=00000000000c3676 'line_to_vpti_400' +line_to_vpti_400: ; 0xc7df6 LB 0x8 + db 017h, 017h, 018h, 018h, 0ffh, 0ffh, 0ffh, 019h + ; disGetNextSymbol 0xc7dfe LB 0xcf -> off=0x0 cb=0000000000000004 uValue=00000000000c367e 'row_tbl' +row_tbl: ; 0xc7dfe LB 0x4 + dd 02b190e00h + ; disGetNextSymbol 0xc7e02 LB 0xcb -> off=0x0 cb=0000000000000015 uValue=00000000000c3682 '_vbebios_copyright' +_vbebios_copyright: ; 0xc7e02 LB 0x15 + db 'VirtualBox VESA BIOS', 000h + ; disGetNextSymbol 0xc7e17 LB 0xb6 -> off=0x0 cb=000000000000001d uValue=00000000000c3697 '_vbebios_vendor_name' +_vbebios_vendor_name: ; 0xc7e17 LB 0x1d + db 'Oracle and/or its affiliates', 000h + ; disGetNextSymbol 0xc7e34 LB 0x99 -> off=0x0 cb=0000000000000021 uValue=00000000000c36b4 '_vbebios_product_name' +_vbebios_product_name: ; 0xc7e34 LB 0x21 + db 'Oracle VM VirtualBox VBE Adapter', 000h + ; disGetNextSymbol 0xc7e55 LB 0x78 -> off=0x0 cb=0000000000000024 uValue=00000000000c36d5 '_vbebios_product_revision' +_vbebios_product_revision: ; 0xc7e55 LB 0x24 + db 'Oracle VM VirtualBox Version 7.0.14', 000h + ; disGetNextSymbol 0xc7e79 LB 0x54 -> off=0x0 cb=000000000000002b uValue=00000000000c36f9 '_vbebios_info_string' +_vbebios_info_string: ; 0xc7e79 LB 0x2b + db 'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h + ; disGetNextSymbol 0xc7ea4 LB 0x29 -> off=0x0 cb=0000000000000029 uValue=00000000000c3724 '_no_vbebios_info_string' +_no_vbebios_info_string: ; 0xc7ea4 LB 0x29 + db 'No VirtualBox VBE support available!', 00dh, 00ah, 00dh, 00ah, 000h + + ; Padding 0x1 bytes at 0xc7ecd + db 001h + +section CONST progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP + +section CONST2 progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP + + ; Padding 0x132 bytes at 0xc7ece + db 000h, 000h, 000h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 02fh, 068h, 06fh, 06dh, 065h + db 02fh, 073h, 062h, 075h, 072h, 063h, 068h, 069h, 06ch, 02fh, 076h, 062h, 05fh, 073h, 072h, 063h + db 02fh, 062h, 072h, 061h, 06eh, 063h, 068h, 065h, 073h, 02fh, 056h, 042h, 06fh, 078h, 02dh, 037h + db 02eh, 030h, 02fh, 06fh, 075h, 074h, 02fh, 06ch, 069h, 06eh, 075h, 078h, 02eh, 061h, 06dh, 064h + db 036h, 034h, 02fh, 072h, 065h, 06ch, 065h, 061h, 073h, 065h, 02fh, 06fh, 062h, 06ah, 02fh, 056h + db 042h, 06fh, 078h, 056h, 067h, 061h, 042h, 069h, 06fh, 073h, 038h, 030h, 038h, 036h, 02fh, 056h + db 042h, 06fh, 078h, 056h, 067h, 061h, 042h, 069h, 06fh, 073h, 038h, 030h, 038h, 036h, 02eh, 073h + db 079h, 06dh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 021h diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum new file mode 100644 index 00000000..437a4099 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum @@ -0,0 +1 @@ +fe9decb70cbd4b2ae6fa11107ac955ae *VBoxVgaBios8086.rom diff --git a/src/VBox/Devices/Graphics/BIOS/inlines.h b/src/VBox/Devices/Graphics/BIOS/inlines.h new file mode 100644 index 00000000..6047f23a --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/inlines.h @@ -0,0 +1,180 @@ +/** @file + * Inline routines for Watcom C. + */ + +/* + * Copyright (C) 2010-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_BIOS_inlines_h +#define VBOX_INCLUDED_SRC_Graphics_BIOS_inlines_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +extern unsigned inp(unsigned port); +extern unsigned outp(unsigned port, unsigned value); +extern unsigned inpw(unsigned port); +extern unsigned outpw(unsigned port, unsigned value); +#pragma intrinsic(inp,outp,inpw,outpw) +#define inb(p) inp(p) +#define outb(p, v) outp(p, v) +#define inw(p) inpw(p) +#define outw(p, v) outpw(p, v) + +/* Far byte/word/dword access routines. */ + +inline uint8_t read_byte(uint16_t seg, uint16_t offset) +{ + return( *(seg:>(uint8_t *)offset) ); +} + +inline void write_byte(uint16_t seg, uint16_t offset, uint8_t data) +{ + *(seg:>(uint8_t *)offset) = data; +} + +inline uint16_t read_word(uint16_t seg, uint16_t offset) +{ + return( *(seg:>(uint16_t *)offset) ); +} + +inline void write_word(uint16_t seg, uint16_t offset, uint16_t data) +{ + *(seg:>(uint16_t *)offset) = data; +} + +inline uint32_t read_dword(uint16_t seg, uint16_t offset) +{ + return( *(seg:>(uint32_t *)offset) ); +} + +inline void write_dword(uint16_t seg, uint16_t offset, uint32_t data) +{ + *(seg:>(uint32_t *)offset) = data; +} + +void int_enable(void); +#pragma aux int_enable = "sti" modify exact [] nomemory; + +void int_disable(void); +#pragma aux int_disable = "cli" modify exact [] nomemory; + +uint16_t int_query(void); +#pragma aux int_query = \ + "pushf" \ + "pop ax" \ + value [ax] modify exact [ax] nomemory; + +void int_restore(uint16_t old_flags); +#pragma aux int_restore = \ + "push ax" \ + "popf" \ + parm [ax] modify exact [] nomemory; + +void halt(void); +#pragma aux halt = "hlt" modify exact [] nomemory; + +void halt_forever(void); +#pragma aux halt_forever = \ + "forever:" \ + "hlt" \ + "jmp forever" \ + modify exact [] nomemory aborts; + +void rep_movsw(void __far *d, void __far *s, int nwords); +#pragma aux rep_movsw = \ + "push ds" \ + "mov ds, dx" \ + "rep movsw" \ + "pop ds" \ + parm [es di] [dx si] [cx]; + +int repe_cmpsb(void __far *d, void __far *s, int nbytes); +#pragma aux repe_cmpsb = \ + "push ds" \ + "mov ds, dx" \ + "repe cmpsb" \ + "pop ds" \ + "mov ax, 0" \ + "jz match" \ + "inc al" \ + "match:" \ + parm [es di] [dx si] [cx] value [ax] modify nomemory; + +char __far *rep_insb(char __far *buffer, unsigned nbytes, unsigned port); +#pragma aux rep_insb = ".286" "rep insb" parm [es di] [cx] [dx] value [es di] modify exact [cx di]; + +char __far *rep_insw(char __far *buffer, unsigned nwords, unsigned port); +#pragma aux rep_insw = ".286" "rep insw" parm [es di] [cx] [dx] value [es di] modify exact [cx di]; + +char __far *rep_outsb(char __far *buffer, unsigned nbytes, unsigned port); +#pragma aux rep_outsb = ".286" "rep outs dx,byte ptr es:[si]" parm [es si] [cx] [dx] value [es si] modify exact [cx si]; + +char __far *rep_outsw(char __far *buffer, unsigned nwords, unsigned port); +#pragma aux rep_outsw = ".286" "rep outs dx,word ptr es:[si]" parm [es si] [cx] [dx] value [es si] modify exact [cx si]; + +uint16_t __far swap_16(uint16_t val); +#pragma aux swap_16 = "xchg ah,al" parm [ax] value [ax] modify exact [ax] nomemory; + +uint32_t __far swap_32(uint32_t val); +#pragma aux swap_32 = \ + "xchg ah, al" \ + "xchg dh, dl" \ + "xchg ax, dx" \ + parm [dx ax] value [dx ax] modify exact [dx ax] nomemory; + +extern void memsetb(uint16_t seg, uint16_t offset, uint16_t value, uint16_t count); +#pragma aux memsetb = \ + "jcxz no_copy" \ + "rep stosb" \ + "no_copy:" \ + parm [es] [di] [ax] [cx]; + +extern void memsetw(uint16_t seg, uint16_t offset, uint16_t value, uint16_t count); +#pragma aux memsetw = \ + "jcxz no_copy" \ + "rep stosw" \ + "no_copy:" \ + parm [es] [di] [ax] [cx]; + +extern void memcpyb(uint16_t dseg, uint16_t doffset, uint16_t sseg, uint16_t soffset, uint16_t count); +#pragma aux memcpyb = \ + "jcxz no_copy" \ + "push ds" \ + "mov ds, dx" \ + "rep movsb" \ + "pop ds" \ + "no_copy:" \ + parm [es] [di] [dx] [si] [cx]; + +extern void memcpyw(uint16_t dseg, uint16_t doffset, uint16_t sseg, uint16_t soffset, uint16_t count); +#pragma aux memcpyw = \ + "jcxz no_copy" \ + "push ds" \ + "mov ds, dx" \ + "rep movsw" \ + "pop ds" \ + "no_copy:" \ + parm [es] [di] [dx] [si] [cx]; + +#endif /* !VBOX_INCLUDED_SRC_Graphics_BIOS_inlines_h */ + diff --git a/src/VBox/Devices/Graphics/BIOS/makefile b/src/VBox/Devices/Graphics/BIOS/makefile new file mode 100644 index 00000000..0173ae56 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/makefile @@ -0,0 +1,48 @@ +# Compiler flags: +# -q no banner +# -wx max warnings +# -0 generate 8086 code +# -ms force small model (default) +# -s remove runtime stack checks (required) +# -os optimize for size +# -zu assume that SS != DS (required) +# -zl do not emit default library information +# +!ifdef __UNIX__ +Q=\" +!else +Q=" +!endif +CFLAGS = -q -3 -wx -zu -zl -s -oas -d1 -ms +DEFS = -DVBOX -DVBE -DVBOX_VERSION_STRING=$(Q)0.9.90$(Q) -DVBOX_VENDOR=$(Q)Oracle_Corporation$(Q) -DVBOX_PRODUCT=$(Q)Oracle_VM_VirtualBox$(Q) -DVBOX_BIOS_CPU=80386 +#DEFS = -DVBOX -DVBOX_VERSION_STRING=$(Q)0.9$(Q) -DVBOX_VENDOR=$(Q)Oracle$(Q) -DVBOX_PRODUCT=$(Q)VirtualBox$(Q) + +AFLAGS = -q -0 -wx + +INCLS = -I$(Q)../../../../../include$(Q) -I$(Q)../../../../../include/VBox/Graphics$(Q) +AINCS = -I$(Q)../../BiosCommonCode$(Q) + +.c.obj : .autodepend + wcc -fo=.obj $(CFLAGS) $(DEFS) $(INCLS) $< + +.asm.obj : .autodepend + wasm -fo=.obj $(AFLAGS) $(DEFS) $(AINCS) $< + +OBJS = vgarom.obj vberom.obj vgabios.obj vbe.obj + +vgabios.rom : vgabios.bin + biossums $< $@ + +vgabios.bin : $(OBJS) $(__MAKEFILES__) + wlink name $@ system dos debug all option quiet & + option nofarcalls, map, verbose, statics, symfile & + output raw offset=0xC0000 order & + clname CODE segment VGAROM segaddr=0xC000 & + segment _TEXT segaddr=0xC000 offset=0xA00 & + segment VBE32 segaddr=0xC000 offset=0x4600 & + clname DATA segment _DATA segaddr=0xC000 offset=0x4800 & + file { $(OBJS) } disable 1014, 1023, 2120 + +clean : .symbolic + @rm -f *.obj *.err + @rm -f vgabios.bin vgabios.rom vgabios.map vgabios.sym diff --git a/src/VBox/Devices/Graphics/BIOS/ose_logo.bmp b/src/VBox/Devices/Graphics/BIOS/ose_logo.bmp new file mode 100644 index 00000000..a4d5008d Binary files /dev/null and b/src/VBox/Devices/Graphics/BIOS/ose_logo.bmp differ diff --git a/src/VBox/Devices/Graphics/BIOS/tests/testbios.c b/src/VBox/Devices/Graphics/BIOS/tests/testbios.c new file mode 100644 index 00000000..92295d1d --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/tests/testbios.c @@ -0,0 +1,353 @@ +/* + This is a little turbo C program that executes + several int10, and let you inspect the content + of the vgabios area + + It is used to test the behavior of the vgabios +*/ + +#include +#include +#include + + +typedef unsigned char Bit8u; +typedef unsigned short Bit16u; + +typedef struct +{Bit8u initial; + Bit8u current; + Bit16u nbcols; + Bit16u regen; + Bit16u start; + Bit16u curpos[8]; + Bit8u curtyp; + Bit8u curpage; + Bit16u crtc; + Bit16u msr; + Bit16u cgapal; + Bit8u nbrows; + Bit16u cheight; + Bit8u ctl; + Bit8u switches; + Bit8u modeset; + Bit8u dcc; + Bit16u vsseg; + Bit16u vsoffset; +} BIOSAREA; + +void int10ax0003(struct REGPACK *regs) +{ + regs->r_ax=0x0003; + intr(0x10,regs); +} + +void int10ax02(struct REGPACK *regs) +{ + regs->r_ax=0x0200; + regs->r_bx=0x0000; + regs->r_dx=0x1710; + intr(0x10,regs); + printf("We are now at 24/17"); +} + +void int10ax03(struct REGPACK *regs) +{ + regs->r_ax=0x0300; + regs->r_bx=0x0000; + intr(0x10,regs); + printf("\nCursor is ax%04x cx%04x dx%04x\n",regs->r_ax,regs->r_cx,regs->r_dx); +} + +void int10ax0501(struct REGPACK *regs) +{ + regs->r_ax=0x0501; + intr(0x10,regs); + regs->r_ax=0x0e61; + regs->r_bx=0x0000; + intr(0x10,regs); + printf("We are now on page 2"); +} + +void int10ax0602(struct REGPACK *regs) +{ + regs->r_ax=0x0602; + regs->r_bx=0x0700; + regs->r_cx=0x0101; + regs->r_dx=0x0a0a; + intr(0x10,regs); + printf("Scrolled 2 up"); +} + +void int10ax0702(struct REGPACK *regs) +{ + regs->r_ax=0x0702; + regs->r_bx=0x0700; + regs->r_cx=0x0101; + regs->r_dx=0x0a0a; + intr(0x10,regs); + printf("Scrolled 2 down"); +} + +void int10ax08(struct REGPACK *regs) +{ + regs->r_ax=0x0800; + regs->r_bx=0x0000; + intr(0x10,regs); +} + +void int10ax09(struct REGPACK *regs) +{ + char attr; + regs->r_ax=0x0501; + intr(0x10,regs); + for(attr=0;attr<16;attr++) + {printf("%02x ",attr); + regs->r_ax=0x0961+attr; + regs->r_bx=0x0100+attr; + regs->r_cx=0x0016; + intr(0x10,regs); + printf("\n"); + } +} + +void int10ax0a(struct REGPACK *regs) +{ + regs->r_ax=0x0501; + intr(0x10,regs); + regs->r_ax=0x0a62; + regs->r_bx=0x0101; + regs->r_cx=0x0016; + intr(0x10,regs); +} + +void int10ax0f(struct REGPACK *regs) +{ + regs->r_ax=0x0501; + intr(0x10,regs); + regs->r_ax=0x0f00; + intr(0x10,regs); +} + +void int10ax1b(struct REGPACK *regs) +{unsigned char table[64]; + unsigned char far *ptable; + int i; + + regs->r_ax=0x0501; + intr(0x10,regs); + regs->r_ax=0x1b00; + regs->r_bx=0x0000; + ptable=&table; + regs->r_es=FP_SEG(ptable); + regs->r_di=FP_OFF(ptable); + printf("Read state info in %04x:%04x\n",regs->r_es,regs->r_di); + intr(0x10,regs); + + for(i=0;i<64;i++) + {if(i%16==0)printf("\n%02x ",i); + printf("%02x ",table[i]); + } + printf("\n"); +} + +static unsigned char var[64]; + +void int10ax13(struct REGPACK *regs) +{unsigned char far *pvar; + + pvar=&var; + + regs->r_ax=0x1300; + regs->r_bx=0x000b; + regs->r_dx=0x1010; + regs->r_cx=0x0002; + regs->r_es=FP_SEG(pvar); + regs->r_bp=FP_OFF(pvar); + pokeb(regs->r_es,regs->r_bp,'t'); + pokeb(regs->r_es,regs->r_bp+1,'b'); + printf("Writing from %04x:%04x\n",regs->r_es,regs->r_bp); + intr(0x10,regs); + +} + +void switch_50(struct REGPACK *regs) +{ + regs->r_ax=0x1202; + regs->r_bx=0x3000; + intr(0x10,regs); + regs->r_ax=0x0003; + intr(0x10,regs); + regs->r_ax=0x1112; + regs->r_bx=0x0000; + intr(0x10,regs); +} + +char exec_function(struct REGPACK *regs) +{char c; + + printf("--- Functions --------------------\n"); + printf("a. int10 ax0003\t"); + printf("b. int10 ax02\t"); + printf("c. int10 ax03\t"); + printf("d. int10 ax0501\n"); + printf("e. int10 ax0602\t"); + printf("f. int10 ax0702\t"); + printf("g. int10 ax08\t"); + printf("h. int10 ax09\t"); + printf("i. int10 ax0a\n"); + printf("j. int10 ax0f\t"); + printf("k. int10 ax1b\t"); + printf("l. int10 ax13\n"); + printf("q. Quit\t"); + printf("r. switch to 50 lines\n"); + c=getche(); + + switch(c) + {case 'a': + int10ax0003(regs); + break; + case 'b': + int10ax02(regs); + break; + case 'c': + int10ax03(regs); + break; + case 'd': + int10ax0501(regs); + break; + case 'e': + int10ax0602(regs); + break; + case 'f': + int10ax0702(regs); + break; + case 'g': + int10ax08(regs); + break; + case 'h': + int10ax09(regs); + break; + case 'i': + int10ax0a(regs); + break; + case 'j': + int10ax0f(regs); + break; + case 'k': + int10ax1b(regs); + break; + case 'l': + int10ax13(regs); + break; + case 'q': + break; + case 'r': + switch_50(regs); + break; + default: + printf("No such function!\n"); + } + + if(c=='q')return 1; + while(kbhit()==0); + c=getch(); + + return 0; +} + +void read_bios_area(BIOSAREA *biosarea) +{ + biosarea->initial=peekb(0x40,0x10); + biosarea->current=peekb(0x40,0x49); + biosarea->nbcols=peek(0x40,0x4a); + biosarea->regen=peek(0x40,0x4c); + biosarea->start=peek(0x40,0x4e); + biosarea->curpos[0]=peek(0x40,0x50); + biosarea->curpos[1]=peek(0x40,0x52); + biosarea->curpos[2]=peek(0x40,0x54); + biosarea->curpos[3]=peek(0x40,0x56); + biosarea->curpos[4]=peek(0x40,0x58); + biosarea->curpos[5]=peek(0x40,0x5a); + biosarea->curpos[6]=peek(0x40,0x5c); + biosarea->curpos[7]=peek(0x40,0x5e); + biosarea->curtyp=peek(0x40,0x60); + biosarea->curpage=peekb(0x40,0x62); + biosarea->crtc=peek(0x40,0x63); + biosarea->msr=peekb(0x40,0x65); + biosarea->cgapal=peekb(0x40,0x66); + biosarea->nbrows=peekb(0x40,0x84); + biosarea->cheight=peek(0x40,0x85); + biosarea->ctl=peekb(0x40,0x87); + biosarea->switches=peekb(0x40,0x88); + biosarea->modeset=peekb(0x40,0x89); + biosarea->dcc=peekb(0x40,0x8a); + biosarea->vsseg=peek(0x40,0xa8); + biosarea->vsoffset=peek(0x40,0xaa); +} + +void show_bios_area(BIOSAREA *biosarea) +{ + printf("--- BIOS area --------------------\n"); + printf("initial : %02x\t",biosarea->initial); + printf("current : %02x\t",biosarea->current); + printf("nbcols : %04x\t",biosarea->nbcols); + printf("regen : %04x\t",biosarea->regen); + printf("start : %04x\n",biosarea->start); + printf("curpos : %04x %04x %04x %04x %04x %04x %04x %04x\n", + biosarea->curpos[0], biosarea->curpos[1], biosarea->curpos[2], biosarea->curpos[3], + biosarea->curpos[4], biosarea->curpos[5], biosarea->curpos[6], biosarea->curpos[7]); + printf("curtyp : %04x\t",biosarea->curtyp); + printf("curpage : %02x\t",biosarea->curpage); + printf("crtc : %04x\t",biosarea->crtc); + printf("msr : %04x\n",biosarea->msr); + printf("cgapal : %04x\t",biosarea->cgapal); + printf("nbrows-1: %02x\t",biosarea->nbrows); + printf("cheight : %04x\t",biosarea->cheight); + printf("ctl : %02x\n",biosarea->ctl); + printf("switches: %02x\t",biosarea->switches); + printf("modeset : %02x\t",biosarea->modeset); + printf("dcc : %02x\t",biosarea->dcc); + printf("vs : %04x:%04x\n",biosarea->vsseg,biosarea->vsoffset); +} + +void show_regs(struct REGPACK *regs) +{ + printf("--- Registers --------------------\n"); + printf("ax %04x\t",regs->r_ax); + printf("bx %04x\t",regs->r_bx); + printf("cx %04x\t",regs->r_cx); + printf("dx %04x\t",regs->r_dx); + printf("ds %04x\t",regs->r_ds); + printf("si %04x\t",regs->r_si); + printf("es %04x\t",regs->r_es); + printf("di %04x\n",regs->r_di); +} + +void reset_videomode() +{ + struct REGPACK regs; + + regs.r_ax=0x0003; + intr(0x10,®s); +} + +void main() +{ + + BIOSAREA biosarea; + struct REGPACK regs; + + directvideo=0; + + while(1) + { + read_bios_area(&biosarea); + + reset_videomode(); + show_bios_area(&biosarea); + show_regs(®s); + + if(exec_function(®s)!=0)break; + } +} diff --git a/src/VBox/Devices/Graphics/BIOS/vbe.c b/src/VBox/Devices/Graphics/BIOS/vbe.c new file mode 100644 index 00000000..066c2cb0 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vbe.c @@ -0,0 +1,816 @@ +// ============================================================================================ +// +// Copyright (C) 2002 Jeroen Janssen +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// ============================================================================================ +// +// This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +// You can NOT drive any physical vga card with it. +// +// ============================================================================================ +// +// This VBE Bios is based on information taken from : +// - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +// +// ============================================================================================ + + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include +#include +#include "vbe.h" +#include "vgadefs.h" +#include "inlines.h" + +// disable VESA/VBE2 check in vbe info +//#define VBE2_NO_VESA_CHECK + +// use bytewise i/o (Longhorn beta issue, not in released Vista) +#define VBE_BYTEWISE_IO + +#ifdef VBE_BYTEWISE_IO + extern void do_out_dx_ax(); + #pragma aux do_out_dx_ax "*"; + extern void out_w(uint16_t port, uint16_t value); + #pragma aux out_w = \ + "call do_out_dx_ax" \ + parm [dx] [ax] modify nomemory; + extern void do_in_ax_dx(); + #pragma aux do_in_ax_dx "*"; + extern uint16_t in_w(uint16_t port); + #pragma aux in_w = \ + "call do_in_ax_dx" \ + parm [dx] value [ax] modify nomemory; +#else + #define out_w outw + #define in_w inw +#endif + + +/* VESA signatures as integer constants. */ +#define SIG_VBE2 0x32454256 /* 'VBE2' */ +#define SIG_VESA 0x41534556 /* 'VESA' */ + + +/* Implemented in assembler. */ +extern void __cdecl vga_compat_setup(void); +extern void dispi_set_enable(uint16_t enable); +extern void dispi_set_bank(uint16_t bank); +extern uint16_t __cdecl dispi_get_max_bpp(void); +extern void __cdecl dispi_set_bank_farcall(void); + +// The current OEM Software Revision of this VBE Bios +#define VBE_OEM_SOFTWARE_REV 0x0003 + +// FIXME: 'merge' these (c) etc strings with the vgabios.c strings? +char vbebios_copyright[] = "VirtualBox VESA BIOS"; +char vbebios_vendor_name[] = VBOX_VENDOR; +char vbebios_product_name[] = VBOX_PRODUCT " VBE Adapter"; +char vbebios_product_revision[] = VBOX_PRODUCT " Version " VBOX_VERSION_STRING; + +char vbebios_info_string[] = "VirtualBox VBE Display Adapter enabled\r\n\r\n"; +char no_vbebios_info_string[] = "No VirtualBox VBE support available!\r\n\r\n"; + +#ifdef VGA_DEBUG +char msg_vbe_init[] = "VirtualBox Version " VBOX_VERSION_STRING " VBE Display Adapter\r\n"; +#endif + +static void dispi_set_xres(uint16_t xres) +{ +#ifdef VGA_DEBUG + printf("vbe_set_xres: %04x\n", xres); +#endif + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES); + out_w(VBE_DISPI_IOPORT_DATA, xres); +} + +static void dispi_set_yres(uint16_t yres) +{ +#ifdef VGA_DEBUG + printf("vbe_set_yres: %04x\n", yres); +#endif + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES); + out_w(VBE_DISPI_IOPORT_DATA, yres); +} + +static uint16_t dispi_get_yres(void) +{ + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES); + return in_w(VBE_DISPI_IOPORT_DATA); +} + +static void dispi_set_bpp(uint16_t bpp) +{ +#ifdef VGA_DEBUG + printf("vbe_set_bpp: %02x\n", bpp); +#endif + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP); + out_w(VBE_DISPI_IOPORT_DATA, bpp); +} + +static uint16_t dispi_get_bpp(void) +{ + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP); + return in_w(VBE_DISPI_IOPORT_DATA); +} + +static void dispi_set_virt_width(uint16_t vwidth) +{ +#ifdef VGA_DEBUG + printf("vbe_set_virt_width: %04x\n", vwidth); +#endif + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH); + out_w(VBE_DISPI_IOPORT_DATA, vwidth); +} + +static uint16_t dispi_get_virt_width(void) +{ + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH); + return in_w(VBE_DISPI_IOPORT_DATA); +} + +static uint16_t dispi_get_virt_height(void) +{ + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_HEIGHT); + return in_w(VBE_DISPI_IOPORT_DATA); +} + +uint16_t in_word(uint16_t port, uint16_t addr) +{ + outw(port, addr); + return inw(port); +} + +uint8_t in_byte(uint16_t port, uint16_t addr) +{ + outw(port, addr); + return inb(port); +} + +/* Display "chip" identification helpers. */ +static uint16_t dispi_get_id(void) +{ + outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); + return inw(VBE_DISPI_IOPORT_DATA); +} + +static void dispi_set_id(uint16_t chip_id) +{ + outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); + outw(VBE_DISPI_IOPORT_DATA, chip_id); +} + +/* VBE Init - Initialise the VESA BIOS Extension (VBE) support + * This function does a sanity check on the host side display code interface. + */ +void vbe_init(void) +{ + dispi_set_id(VBE_DISPI_ID0); + if (dispi_get_id() == VBE_DISPI_ID0) { + /* VBE support was detected. */ + write_byte(BIOSMEM_SEG, BIOSMEM_VBE_FLAG, 1); + dispi_set_id(VBE_DISPI_ID4); + } +#ifdef DEBUG_VGA + printf(msg_vbe_init); +#endif +} + +/* Find the offset of the desired mode, given its number. */ +static uint16_t mode_info_find_mode(uint16_t mode, Boolean using_lfb) +{ + uint16_t sig, vmode, attrs; + uint16_t cur_info_ofs; /* Current offset in mode list. */ + + /* Read and check the VBE Extra Data signature. */ + sig = in_word(VBE_EXTRA_PORT, 0); + if (sig != VBEHEADER_MAGIC) { +#ifdef DEBUG_VGA + printf("Signature NOT found! %x\n", sig); +#endif + return 0; + } + + /* The LFB may be disabled. If so, LFB modes must not be reported. */ + if (using_lfb) { + uint16_t lfb_addr_hi; + + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_FB_BASE_HI); + lfb_addr_hi = in_w(VBE_DISPI_IOPORT_DATA); + if (!lfb_addr_hi) { +#ifdef DEBUG_VGA + printf("LFB disabled, LFB modes unavailable!\n"); +#endif + return 0; + } + } + + cur_info_ofs = sizeof(VBEHeader); + + vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/); + while (vmode != VBE_VESA_MODE_END_OF_LIST) + { + attrs = in_word(VBE_EXTRA_PORT, /*&cur_info->info.ModeAttributes*/cur_info_ofs + offsetof(ModeInfoListItem, info.ModeAttributes) ); + + if (vmode == mode) + { + if (!using_lfb) + return cur_info_ofs; + else if (attrs & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE) + return cur_info_ofs; + else { + cur_info_ofs += sizeof(ModeInfoListItem); + vmode = in_word(VBE_EXTRA_PORT, /*&cur_info->mode*/cur_info_ofs + offsetof(ModeInfoListItem, mode)); + } + } else { + cur_info_ofs += sizeof(ModeInfoListItem); + vmode = in_word(VBE_EXTRA_PORT, /*&cur_info->mode*/cur_info_ofs + offsetof(ModeInfoListItem, mode)); + } + } + return 0; +} + +#ifndef VBOX +; VBE Display Info - Display information on screen about the VBE + +vbe_display_info: + call _vbe_has_vbe_display + test ax, ax + jz no_vbe_flag + mov ax, #0xc000 + mov ds, ax + mov si, #_vbebios_info_string + jmp _display_string +no_vbe_flag: + mov ax, #0xc000 + mov ds, ax + mov si, #_no_vbebios_info_string + jmp _display_string +#endif + +/** Function 00h - Return VBE Controller Information + * + * Input: + * AX = 4F00h + * ES:DI = Pointer to buffer in which to place VbeInfoBlock structure + * (VbeSignature should be VBE2 when VBE 2.0 information is desired and + * the info block is 512 bytes in size) + * Output: + * AX = VBE Return Status + * + */ +void vbe_biosfn_return_controller_information(uint16_t STACK_BASED *AX, uint16_t ES, uint16_t DI) +{ + uint16_t status; + uint16_t vbe2_info; + uint16_t cur_mode = 0; + uint16_t cur_ptr=34; + uint16_t cur_info_ofs; + uint16_t sig, vmode; + uint16_t max_bpp = dispi_get_max_bpp(); + VbeInfoBlock __far *info_block; + + info_block = ES :> (VbeInfoBlock *)DI; + + /* Read VBE Extra Data signature */ + sig = in_word(VBE_EXTRA_PORT, 0); + if (sig != VBEHEADER_MAGIC) + { + *AX = 0x0100; +#ifdef DEBUG_VGA + printf("Signature NOT found\n"); +#endif + return; + } + cur_info_ofs = sizeof(VBEHeader); + status = *AX; + +#ifdef VGA_DEBUG + printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status); +#endif + + vbe2_info = 0; + + /* Don't use a local copy of VbeInfoBlock on the stack; it's too big. + * The Ubuntu 8.04 64 bits splash screen emulator can't handle this. + */ +#ifdef VBE2_NO_VESA_CHECK +#else /* !VBE2_NO_VESA_CHECK */ + // check for VBE2 signature + if (info_block->VbeSignature.Sig32 == SIG_VBE2 || info_block->VbeSignature.Sig32 == SIG_VESA) + { + vbe2_info = 1; +#ifdef VGA_DEBUG + printf("VBE correct VESA/VBE2 signature found\n"); +#endif + } +#endif /* !VBE2_NO_VESA_CHECK */ + + /* VBE Signature - the compiler will optimize this into something sane. */ + info_block->VbeSignature.SigChr[0] = 'V'; + info_block->VbeSignature.SigChr[1] = 'E'; + info_block->VbeSignature.SigChr[2] = 'S'; + info_block->VbeSignature.SigChr[3] = 'A'; + + /* VBE Version supported. */ + info_block->VbeVersion = 0x0200; /* Version 2.0. */ + + /* OEM String. */ + info_block->OemString.Ptr = &vbebios_copyright; + + /* Capabilities if this implementation. */ + info_block->Capabilities[0] = VBE_CAPABILITY_8BIT_DAC; + info_block->Capabilities[1] = 0; + info_block->Capabilities[2] = 0; + info_block->Capabilities[3] = 0; + + /* Video mode list pointer (dynamically generated). */ + info_block->VideoModePtr_Seg = ES; + info_block->VideoModePtr_Off = DI + 34; + + /* Total controller memory in 64K units. */ + info_block->TotalMemory = in_word(VBE_EXTRA_PORT, 0xffff); + + if (vbe2_info) + { + /* OEM information. */ + info_block->OemSoftwareRev = VBE_OEM_SOFTWARE_REV; + info_block->OemVendorName.Ptr = &vbebios_vendor_name; + info_block->OemProductName.Ptr = &vbebios_product_name; + info_block->OemProductRev.Ptr = &vbebios_product_revision; + } + + do + { + uint8_t data_b; + + data_b = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.BitsPerPixel) /*&cur_info->info.BitsPerPixel*/); + if (data_b <= max_bpp) + { + vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/); +#ifdef VGA_DEBUG + printf("VBE found mode %x => %x\n", vmode, cur_mode); +#endif + write_word(ES, DI + cur_ptr, vmode); + cur_mode++; + cur_ptr+=2; + } + cur_info_ofs += sizeof(ModeInfoListItem); + vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/); + } while (vmode != VBE_VESA_MODE_END_OF_LIST); + + // Add vesa mode list terminator + write_word(ES, DI + cur_ptr, vmode); + *AX = 0x004F; +} + +/** Function 01h - Return VBE Mode Information + * + * Input: + * AX = 4F01h + * CX = Mode Number + * ES:DI = Pointer to buffer in which to place ModeInfoBlock structure + * Output: + * AX = VBE Return Status + * + */ +void vbe_biosfn_return_mode_information(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t ES, uint16_t DI) +{ + uint16_t result = 0x0100; + uint16_t cur_info_ofs; + Boolean using_lfb; + uint8_t win_attr; + +#ifdef VGA_DEBUG + printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX); +#endif + + using_lfb = ((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER); + CX = (CX & 0x1ff); + + cur_info_ofs = mode_info_find_mode(CX, using_lfb); + + if (cur_info_ofs) { + uint16_t i; +#ifdef VGA_DEBUG + printf("VBE found mode %x\n",CX); +#endif + memsetb(ES, DI, 0, 256); // The mode info size is fixed + for (i = 0; i < sizeof(ModeInfoBlockCompact); i++) { + uint8_t b; + + b = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info) + i/*(char *)(&(cur_info->info)) + i*/); + write_byte(ES, DI + i, b); + } + win_attr = read_byte(ES, DI + offsetof(ModeInfoBlock, WinAAttributes)); + if (win_attr & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) { + write_word(ES, DI + offsetof(ModeInfoBlock, WinFuncPtr), (uint16_t)(dispi_set_bank_farcall)); + // If BIOS not at 0xC000 -> boom + write_word(ES, DI + offsetof(ModeInfoBlock, WinFuncPtr) + 2, 0xC000); + } + // Update the LFB physical address which may change at runtime + out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_FB_BASE_HI); + write_word(ES, DI + offsetof(ModeInfoBlock, PhysBasePtr) + 2, in_w(VBE_DISPI_IOPORT_DATA)); + + result = 0x4f; + } else { +#ifdef VGA_DEBUG + printf("VBE *NOT* found mode %x\n",CX); +#endif + result = 0x100; + } + + *AX = result; +} + +/** Function 02h - Set VBE Mode + * + * Input: + * AX = 4F02h + * BX = Desired Mode to set + * ES:DI = Pointer to CRTCInfoBlock structure + * Output: + * AX = VBE Return Status + * + */ +void vbe_biosfn_set_mode(uint16_t STACK_BASED *AX, uint16_t BX, uint16_t ES, uint16_t DI) +{ + uint16_t result; + uint16_t cur_info_ofs; + Boolean using_lfb; + uint8_t no_clear; + uint8_t lfb_flag; + + using_lfb = ((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER); + lfb_flag = using_lfb ? VBE_DISPI_LFB_ENABLED : 0; + no_clear = ((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY) ? VBE_DISPI_NOCLEARMEM : 0; + + BX = (BX & 0x1ff); + + // check for non vesa mode + if (BX < VBE_MODE_VESA_DEFINED) + { + uint8_t mode; + + dispi_set_enable(VBE_DISPI_DISABLED); + // call the vgabios in order to set the video mode + // this allows for going back to textmode with a VBE call (some applications expect that to work) + mode = (BX & 0xff); + biosfn_set_video_mode(mode); + result = 0x4f; + goto leave; + } + + cur_info_ofs = mode_info_find_mode(BX, using_lfb); + + if (cur_info_ofs != 0) + { + uint16_t xres, yres; + uint8_t bpp; + + xres = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.XResolution) /*&cur_info->info.XResolution*/); + yres = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.YResolution) /*&cur_info->info.YResolution*/); + bpp = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.BitsPerPixel) /*&cur_info->info.BitsPerPixel*/); + +#ifdef VGA_DEBUG + printf("VBE found mode %x, setting:\n", BX); + printf("\txres%x yres%x bpp%x\n", xres, yres, bpp); +#endif + + // first disable current mode (when switching between vesa modi) + dispi_set_enable(VBE_DISPI_DISABLED); + + if (bpp == 4) + { + biosfn_set_video_mode(0x6a); + } + + dispi_set_bpp(bpp); + dispi_set_xres(xres); + dispi_set_yres(yres); + dispi_set_bank(0); + dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag); + vga_compat_setup(); + + write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX); + write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear)); + + result = 0x4f; + } + else + { +#ifdef VGA_DEBUG + printf("VBE *NOT* found mode %x\n" , BX); +#endif + result = 0x100; + } + +leave: + *AX = result; +} + +uint16_t vbe_biosfn_read_video_state_size(void) +{ + return 9 * 2; +} + +void vbe_biosfn_save_video_state(uint16_t ES, uint16_t BX) +{ + uint16_t enable, i; + + outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE); + enable = inw(VBE_DISPI_IOPORT_DATA); + write_word(ES, BX, enable); + BX += 2; + if (!(enable & VBE_DISPI_ENABLED)) + return; + for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) { + if (i != VBE_DISPI_INDEX_ENABLE) { + outw(VBE_DISPI_IOPORT_INDEX, i); + write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA)); + BX += 2; + } + } +} + + +void vbe_biosfn_restore_video_state(uint16_t ES, uint16_t BX) +{ + uint16_t enable, i; + + enable = read_word(ES, BX); + BX += 2; + + if (!(enable & VBE_DISPI_ENABLED)) { + outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE); + outw(VBE_DISPI_IOPORT_DATA, enable); + } else { + outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES); + outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX)); + BX += 2; + outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES); + outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX)); + BX += 2; + outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP); + outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX)); + BX += 2; + outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE); + outw(VBE_DISPI_IOPORT_DATA, enable); + + for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) { + outw(VBE_DISPI_IOPORT_INDEX, i); + outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX)); + BX += 2; + } + } +} + +/** Function 04h - Save/Restore State + * + * Input: + * AX = 4F04h + * DL = 00h Return Save/Restore State buffer size + * 01h Save State + * 02h Restore State + * CX = Requested states + * ES:BX = Pointer to buffer (if DL <> 00h) + * Output: + * AX = VBE Return Status + * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h) + * + */ +void vbe_biosfn_save_restore_state(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t DX, + uint16_t ES, uint16_t STACK_BASED *BX) +{ + uint16_t result, val; + + result = 0x004F; + switch(GET_DL()) { + case 0x00: + val = biosfn_read_video_state_size2(CX); +#ifdef VGA_DEBUG + printf("VGA state size=%x\n", val); +#endif + if (CX & 8) + val += vbe_biosfn_read_video_state_size(); + *BX = (val + 63) / 64; + break; + case 0x01: + val = *BX; + val = biosfn_save_video_state(CX, ES, val); +#ifdef VGA_DEBUG + printf("VGA save_state offset=%x\n", val); +#endif + if (CX & 8) + vbe_biosfn_save_video_state(ES, val); + break; + case 0x02: + val = *BX; + val = biosfn_restore_video_state(CX, ES, val); +#ifdef VGA_DEBUG + printf("VGA restore_state offset=%x\n", val); +#endif + if (CX & 8) + vbe_biosfn_restore_video_state(ES, val); + break; + default: + // function failed + result = 0x100; + break; + } + *AX = result; +} + +/** Function 06h - Set/Get Logical Scan Line Length + * + * Input: + * AX = 4F06h + * BL = 00h Set Scan Line Length in Pixels + * = 01h Get Scan Line Length + * = 02h Set Scan Line Length in Bytes + * = 03h Get Maximum Scan Line Length + * CX = If BL=00h Desired Width in Pixels + * If BL=02h Desired Width in Bytes + * (Ignored for Get Functions) + * + * Output: + * AX = VBE Return Status + * BX = Bytes Per Scan Line + * CX = Actual Pixels Per Scan Line (truncated to + * nearest complete pixel) + * DX = Maximum Number of Scan Lines + */ +void vbe_biosfn_get_set_scanline_length(uint16_t STACK_BASED *AX, uint16_t STACK_BASED *BX, + uint16_t STACK_BASED *CX, uint16_t STACK_BASED *DX) +{ + uint16_t val; + uint16_t result; + uint8_t bpp; + uint8_t subfn; + uint16_t old_vw; + + bpp = dispi_get_bpp(); + bpp = bpp == 15 ? 16 : bpp; + old_vw = dispi_get_virt_width(); + result = 0x004F; + val = *CX; + subfn = *BX & 0xFF; +#ifdef VGA_DEBUG + printf("VBE get/set scanline len fn=%x, CX=%x\n", subfn, *CX); +#endif + switch(subfn) { + case 0x02: + if (bpp == 4) + val = val * 8; + else + val = val / (bpp / 8); + /* fall through */ + case 0x00: + dispi_set_virt_width(val); + /* fall through */ + case 0x01: + val = dispi_get_virt_width(); + *CX = val; /* Width in pixels. */ + if (bpp == 4) + val = val / 8; + else + val = val * (bpp / 8); + val = (val + 3) & ~3; + *BX = val; /* Bytes per scanline. */ + *DX = dispi_get_virt_height(); /* Height in lines. */ + if (*DX < dispi_get_yres()) { + dispi_set_virt_width(old_vw); + result = 0x200; + } + break; + default: + // function failed + result = 0x100; + break; + } + *AX = result; +} + + +/* We would very much like to avoid dragging in the long multiply library + * routine, and we really just need to multiply two 16-bit numbers to + * obtain a 32-bit result, so... + */ +uint32_t mul32_16x16(uint16_t a, uint16_t b); +#pragma aux mul32_16x16 = \ + "mul dx" \ + parm [ax] [dx] modify nomemory; + + +/** Private INT 10h function 5642h - Manage custom video modes using X/Y + * resolution and bit depth rather than mode number + * + * Input: + * AX = 5642h ('VB') + * BL = 00h Set video mode + * BH = If BL=00h Desired bit depth in pixels + * CX = If BL=00h Desired width in pixels + * DX = If BL=00h Desired height in pixels + * + * Output: + * AX = VBE style return status + */ +void private_biosfn_custom_mode(uint16_t STACK_BASED *AX, uint16_t STACK_BASED *BX, + uint16_t STACK_BASED *CX, uint16_t STACK_BASED *DX) +{ + uint16_t result; + uint8_t subfn; + uint8_t bpp; + uint8_t lfb_flag; + uint16_t xres; + uint16_t yres; + uint16_t line_size; + uint32_t vram_size; + uint32_t mode_size; + + result = 0x004F; + subfn = *BX & 0xFF; + switch (subfn) { + case 0x00: + xres = *CX; + yres = *DX; + bpp = (*BX >> 8) & 0x7F; +#ifdef VGA_DEBUG + printf("Set custom mode %04x by %04x %xbpp\n", xres, yres, bpp); +#endif + /* Only allow 32/16/8bpp. */ + if (bpp != 8 && bpp != 16 && bpp != 32) { + result = 0x100; + break; + } + + /* Determine the LFB flag. */ + lfb_flag = *BX & 0x8000 ? VBE_DISPI_LFB_ENABLED : 0; + + /* Cap the resolution to something not insanely high or low. */ + if (xres < 640) + xres = 640; + else if (xres > 2560) + xres = 2560; + if (yres < 480) + yres = 480; + else if (yres > 1920) + yres = 1920; +#ifdef VGA_DEBUG + printf("Adjusted resolution %04x by %04x\n", xres, yres); +#endif + + /* Calculate the VRAM size in bytes. */ + vram_size = (uint32_t)in_word(VBE_EXTRA_PORT, 0xffff) << 16; + + /* Calculate the scanline size in bytes. */ + line_size = xres * (bpp / 8); + line_size = (line_size + 3) & ~3; + /* And now the memory required for the mode. */ + mode_size = mul32_16x16(line_size, yres); + + if (mode_size > vram_size) { + /* No can do. Don't have that much VRAM. */ + result = 0x200; + break; + } + + /* Mode looks valid, let's get cracking. */ + dispi_set_enable(VBE_DISPI_DISABLED); + dispi_set_bpp(bpp); + dispi_set_xres(xres); + dispi_set_yres(yres); + dispi_set_bank(0); + dispi_set_enable(VBE_DISPI_ENABLED | lfb_flag); + vga_compat_setup(); + break; + + default: + // unsupported sub-function + result = 0x100; + break; + } + *AX = result; +} diff --git a/src/VBox/Devices/Graphics/BIOS/vbe.h b/src/VBox/Devices/Graphics/BIOS/vbe.h new file mode 100644 index 00000000..eb2ea867 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vbe.h @@ -0,0 +1,117 @@ + +#ifndef VBOX_INCLUDED_SRC_Graphics_BIOS_vbe_h +#define VBOX_INCLUDED_SRC_Graphics_BIOS_vbe_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "vgabios.h" + +#include +#include + +// DISPI helper function +//void dispi_set_enable(Boolean enable); + +/** VBE int10 API + * + * See the function descriptions in vbe.c for more information + */ + +/* Far pointer for VBE info block usage. */ +typedef union vbe_ptr { + uint32_t Ptr32; + void __far *Ptr; + union { + uint16_t Off; + uint16_t Seg; + }; +} vbe_ptr; + +// The official VBE Information Block +typedef struct VbeInfoBlock +{ + union { + uint8_t SigChr[4]; + uint32_t Sig32; + } VbeSignature; + uint16_t VbeVersion; + vbe_ptr OemString; + uint8_t Capabilities[4]; + uint16_t VideoModePtr_Off; + uint16_t VideoModePtr_Seg; + uint16_t TotalMemory; + uint16_t OemSoftwareRev; + vbe_ptr OemVendorName; + vbe_ptr OemProductName; + vbe_ptr OemProductRev; + uint16_t Reserved[111]; // used for dynamically generated mode list + uint8_t OemData[256]; +} VbeInfoBlock; + + +typedef struct ModeInfoBlock +{ +// Mandatory information for all VBE revisions + uint16_t ModeAttributes; + uint8_t WinAAttributes; + uint8_t WinBAttributes; + uint16_t WinGranularity; + uint16_t WinSize; + uint16_t WinASegment; + uint16_t WinBSegment; + uint32_t WinFuncPtr; + uint16_t BytesPerScanLine; +// Mandatory information for VBE 1.2 and above + uint16_t XResolution; + uint16_t YResolution; + uint8_t XCharSize; + uint8_t YCharSize; + uint8_t NumberOfPlanes; + uint8_t BitsPerPixel; + uint8_t NumberOfBanks; + uint8_t MemoryModel; + uint8_t BankSize; + uint8_t NumberOfImagePages; + uint8_t Reserved_page; +// Direct Color fields (required for direct/6 and YUV/7 memory models) + uint8_t RedMaskSize; + uint8_t RedFieldPosition; + uint8_t GreenMaskSize; + uint8_t GreenFieldPosition; + uint8_t BlueMaskSize; + uint8_t BlueFieldPosition; + uint8_t RsvdMaskSize; + uint8_t RsvdFieldPosition; + uint8_t DirectColorModeInfo; +// Mandatory information for VBE 2.0 and above + uint32_t PhysBasePtr; + uint32_t OffScreenMemOffset; + uint16_t OffScreenMemSize; +// Mandatory information for VBE 3.0 and above + uint16_t LinBytesPerScanLine; + uint8_t BnkNumberOfPages; + uint8_t LinNumberOfPages; + uint8_t LinRedMaskSize; + uint8_t LinRedFieldPosition; + uint8_t LinGreenMaskSize; + uint8_t LinGreenFieldPosition; + uint8_t LinBlueMaskSize; + uint8_t LinBlueFieldPosition; + uint8_t LinRsvdMaskSize; + uint8_t LinRsvdFieldPosition; + uint32_t MaxPixelClock; + uint8_t Reserved[189]; +} ModeInfoBlock; + +// VBE Return Status Info +// AL +#define VBE_RETURN_STATUS_SUPPORTED 0x4F +#define VBE_RETURN_STATUS_UNSUPPORTED 0x00 +// AH +#define VBE_RETURN_STATUS_SUCCESSFULL 0x00 +#define VBE_RETURN_STATUS_FAILED 0x01 +#define VBE_RETURN_STATUS_NOT_SUPPORTED 0x02 +#define VBE_RETURN_STATUS_INVALID 0x03 + +#endif /* !VBOX_INCLUDED_SRC_Graphics_BIOS_vbe_h */ diff --git a/src/VBox/Devices/Graphics/BIOS/vbe_display_api.txt b/src/VBox/Devices/Graphics/BIOS/vbe_display_api.txt new file mode 100644 index 00000000..ddec277e --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vbe_display_api.txt @@ -0,0 +1,237 @@ +VBE Display API +------------------------------------------------------------------------------------------------------------- + This document is part of the Bochs/VBEBios documentation, + it specifies the bochs host <-> vbebios client communication. + + That means, the display code implementation and the vbebios code depend + very heavily on each other. As such, this documents needs be synchronised + between bochs CVS and the vgabios CVS. + + This document does not describe how the VBEBios implements the VBE2/3 spec. + This document does not describe how the Bochs display code will display gfx based upon this spec. + + +API History +----------- +0xb0c0 supports the following VBE_DISPI_ interfaces (present in Bochs 1.4): + VBE_DISPI_INDEX_ID + VBE_DISPI_INDEX_XRES + VBE_DISPI_INDEX_YRES + VBE_DISPI_INDEX_BPP + VBE_DISPI_INDEX_ENABLE + VBE_DISPI_INDEX_BANK + + Bpp format supported is: + VBE_DISPI_BPP_8 + +0xb0c1 supports 0xb0c0 VBE_DISPI_ interfaces, additional interfaces (present in Bochs 2.0): + VBE_DISPI_INDEX_VIRT_WIDTH + VBE_DISPI_INDEX_VIRT_HEIGHT + VBE_DISPI_INDEX_X_OFFSET + VBE_DISPI_INDEX_Y_OFFSET + +0xb0c2 supports 0xb0c1 VBE_DISPI_ interfaces, interfaces updated for + additional features (present in Bochs 2.1): + VBE_DISPI_INDEX_BPP supports >8bpp color depth (value = bits) + VBE_DISPI_INDEX_ENABLE supports new flags VBE_DISPI_NOCLEARMEM and VBE_DISPI_LFB_ENABLED + VBE i/o registers changed from 0xFF80/81 to 0x01CE/CF + +0xb0c3 supports 0xb0c2 VBE_DISPI_ interfaces, interfaces updated for + additional features: + VBE_DISPI_INDEX_ENABLE supports new flags VBE_DISPI_GETCAPS and VBE_DISPI_8BIT_DAC + +0xb0c4 VBE video memory increased to 8 MB + + +History +------- + Version 0.6 2002 Nov 23 Jeroen Janssen + - Added LFB support + - Added Virt width, height and x,y offset + + Version 0.5 2002 March 08 Jeroen Janssen + - Added documentation about panic behaviour / current limits of the data values. + - Changed BPP API (in order to include future (A)RGB formats) + - Initial version (based upon extended display text of the vbe bochs display patch) + + +Todo +---- + Version 0.6+ [random order] + - Add lots of different (A)RGB formats + +References +---------- + [VBE3] VBE 3 Specification at + http://www.vesa.org/vbe3.pdf + + [BOCHS] Bochs Open Source IA-32 Emulator at + http://bochs.sourceforge.net + + [VBEBIOS] VBE Bios for Bochs at + http://savannah.gnu.org/projects/vgabios/ + + [Screenshots] Screenshots of programs using the VBE Bios at + http://japj.org/projects/bochs_plex86/screenshots.html + +Abbreviations +------------- + VBE Vesa Bios Extension + DISPI (Bochs) Display Interface + BPP Bits Per Pixel + LFB Linear Frame Buffer + + +#defines +-------- +vbetables-gen.c + #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 8 + +vbe.h + #define VBE_DISPI_BANK_ADDRESS 0xA0000 + #define VBE_DISPI_BANK_SIZE_KB 64 + + #define VBE_DISPI_MAX_XRES 1024 + #define VBE_DISPI_MAX_YRES 768 + + #define VBE_DISPI_IOPORT_INDEX 0x01CE + #define VBE_DISPI_IOPORT_DATA 0x01CF + + #define VBE_DISPI_INDEX_ID 0x0 + #define VBE_DISPI_INDEX_XRES 0x1 + #define VBE_DISPI_INDEX_YRES 0x2 + #define VBE_DISPI_INDEX_BPP 0x3 + #define VBE_DISPI_INDEX_ENABLE 0x4 + #define VBE_DISPI_INDEX_BANK 0x5 + #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 + #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 + #define VBE_DISPI_INDEX_X_OFFSET 0x8 + #define VBE_DISPI_INDEX_Y_OFFSET 0x9 + + #define VBE_DISPI_ID0 0xB0C0 + #define VBE_DISPI_ID1 0xB0C1 + #define VBE_DISPI_ID2 0xB0C2 + #define VBE_DISPI_ID3 0xB0C3 + #define VBE_DISPI_ID4 0xB0C4 + + #define VBE_DISPI_DISABLED 0x00 + #define VBE_DISPI_ENABLED 0x01 + #define VBE_DISPI_VBE_ENABLED 0x40 + #define VBE_DISPI_NOCLEARMEM 0x80 + + #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 + +API +--- + The display api works by using a index (VBE_DISPI_IOPORT_INDEX) and + data (VBE_DISPI_IOPORT_DATA) ioport. One writes the index of the parameter to the index port. + Next, the parameter value can be read or written. + +[0xb0c0] + * VBE_DISPI_INDEX_ID : WORD {R,W} + This parameter can be used to detect the current display API (both bochs & vbebios). + The bios writes VBE_DISPI_ID0 to the dataport and reads it back again. + This way, the display code knows the vbebios 'ID' and the vbebios can check if the correct + display code is present. + As a result, a PANIC can be generated if an incompatible vbebios/display code combination is detected. + This panic can be generated from the bochs display code (NOT the bios, see Notes). + + Example values: VBE_DISPI_ID0 + + * VBE_DISPI_INDEX_XRES : WORD {R,W} + This parameter can be used to read/write the vbe display X resolution (in pixels). + It's illegal to set the XRES when the VBE is enabled (display code should generate PANIC). + + If the value written exceeds VBE_DISPI_MAX_XRES, the display code needs to generate a PANIC. + + Example values: 320,640,800,1024 + + * VBE_DISPI_INDEX_YRES : WORD {R,W} + This parameter can be used to read/write the vbe display Y resolution (in pixels). + It's illegal to set the YRES when the VBE is enabled (display code should generate PANIC). + + If the value written exceeds VBE_DISPI_MAX_YRES, the display code needs to generate a PANIC. + + Example values: 200,400,480,600,768 + + * VBE_DISPI_INDEX_BPP : WORD {R,W} + This parameter can be used to read/write the vbe display BPP. + It's illegal to set the BPP when the VBE is enabled (display code should generate PANIC). + + If the value written is an incompatible BPP, the display code needs to generate a PANIC. + + Example values: VBE_DISPI_BPP_8 + + * VBE_DISPI_INDEX_ENABLE : WORD {R,W} + This parameter can be used to read/write the vbe ENABLED state. + If the bios writes VBE_DISPI_ENABLED then the display code will setup a hostside display mode + with the current XRES, YRES and BPP settings. + If the bios write VBE_DISPI_DISABLED then the display code will switch back to normal vga mode behaviour. + + Example values: VBE_DISPI_ENABLED, VBE_DISPI_DISABLED + + * VBE_DISPI_INDEX_BANK : WORD {R,W} + This parameter can be used to read/write the current selected BANK (at 0xA0000). + This can be used for switching banks in banked mode. + +[0xb0c1] + * VBE_DISPI_INDEX_VIRT_WIDTH : WORD {R,W} + This parameter can be used to read/write the current virtual width. + Upon enabling a mode, this will be set to the current xres + Setting this field during enabled mode will result in the virtual width to be changed. + Value will be adjusted if current setting is not possible. + + * VBE_DISPI_INDEX_VIRT_HEIGHT : WORD {R} + This parameter can be read in order to obtain the current virtual height. + This setting will be adjusted after setting a virtual width in order to stay within limit of video memory. + + * VBE_DISPI_INDEX_X_OFFSET : WORD {R,W} + The current X offset (in pixels!) of the visible screen part. + Writing a new offset will also result in a complete screen refresh. + + * VBE_DISPI_INDEX_Y_OFFSET : WORD {R,W} + The current Y offset (in pixels!) of the visible screen part. + Writing a new offset will also result in a complete screen refresh. + + +[0xb0c2] + * VBE_DISPI_INDEX_BPP : WORD {R,W} + The value written is now the number of bits per pixel. A value of 0 is treated + the same as 8 for backward compatibilty. These values are supported: 8, 15, + 16, 24 and 32. The value of 4 is not yet handled in the VBE code. + * VBE_DISPI_INDEX_ENABLE : WORD {R,W} + The new flag VBE_DISPI_NOCLEARMEM allows to preserve the VBE video memory. + The new flag VBE_DISPI_LFB_ENABLED indicates the usage of the LFB. + +[0xb0c3] + * VBE_DISPI_INDEX_ENABLE : WORD {R,W} + If the new flag VBE_DISPI_GETCAPS is enabled, the xres, yres and bpp registers + return the gui capabilities. + The new flag VBE_DISPI_8BIT_DAC switches the DAC to 8 bit mode. + +[0xb0c4] + * VBE_DISPI_TOTAL_VIDEO_MEMORY_MB set to 8 (moved to auto-generated vbetables.h) + +Displaying GFX (banked mode) +-------------- + What happens is that the total screen is devided in banks of 'VBE_DISPI_BANK_SIZE_KB' KiloByte in size. + If you want to set a pixel you can calculate its bank by doing: + + offset = pixel_x + pixel_y * resolution_x; + bank = offset / 64 Kb (rounded 1.9999 -> 1) + + bank_pixel_pos = offset - bank * 64Kb + + Now you can set the current bank and put the pixel at VBE_DISPI_BANK_ADDRESS + bank_pixel_pos + +Displaying GFX (linear frame buffer mode) +-------------- + NOT WRITTEN YET + +Notes +----- + * Since the XRES/YRES/BPP may not be written when VBE is enabled, if you want to switch from one VBE mode + to another, you will need to disable VBE first. + + * Note when the bios doesn't find a valid DISPI_ID, it can disable the VBE functions. This allows people to + use the same bios for both vbe enabled and disabled bochs executables. diff --git a/src/VBox/Devices/Graphics/BIOS/vberom.asm b/src/VBox/Devices/Graphics/BIOS/vberom.asm new file mode 100644 index 00000000..374fe34c --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vberom.asm @@ -0,0 +1,951 @@ +;; ============================================================================================ +;; +;; Copyright (C) 2002 Jeroen Janssen +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; ============================================================================================ +;; +;; This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +;; You can NOT drive any physical vga card with it. +;; +;; ============================================================================================ +;; +;; This VBE Bios is based on information taken from : +;; - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +;; +;; ============================================================================================ + + +; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice +; other than GPL or LGPL is available it will apply instead, Oracle elects to use only +; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where +; a choice of LGPL license versions is made available with the language indicating +; that LGPLv2 or any later version may be used, or where a choice of which version +; of the LGPL is applied is otherwise unspecified. + +include vgadefs.inc +include commondefs.inc + +public _vga_compat_setup +public dispi_set_enable_ +public dispi_set_bank_ +public _dispi_set_bank_farcall +public _dispi_get_max_bpp +public _vbe_has_vbe_display + +public vbe_biosfn_return_current_mode +public vbe_biosfn_display_window_control +public vbe_biosfn_set_get_display_start +public vbe_biosfn_set_get_dac_palette_format +public vbe_biosfn_set_get_palette_data +public vbe_biosfn_return_protected_mode_interface + +VGAROM segment public 'CODE' + +SET_DEFAULT_CPU + +VBE_BYTEWISE_IO EQU 1 + +;; Bytewise in/out +ifdef VBE_BYTEWISE_IO + +public do_out_dx_ax +public do_in_ax_dx + +do_out_dx_ax: + xchg ah, al + out dx, al + xchg ah, al + out dx, al + ret + +do_in_ax_dx: + in al, dx + xchg ah, al + in al, dx + ret + + out_dx_ax EQU call do_out_dx_ax + in_ax_dx EQU call do_in_ax_dx +else + out_dx_ax EQU out dx, ax + in_ax_dx EQU in ax, dx +endif + +;; Vertical retrace waiting +wait_vsync: + push ax + push dx + mov dx, 03DAh ; @todo use a symbolic constant! +wv_loop: + in al, dx + test al, 8 + jz wv_loop + pop dx + pop ax + ret + +wait_not_vsync: + push ax + push dx + mov dx, 03DAh ; @todo use a symbolic constant! +wnv_loop: + in al, dx + test al, 8 + jnz wnv_loop + pop dx + pop ax + ret + + +; AL = bits per pixel / AH = bytes per pixel +dispi_get_bpp: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BPP + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + cmp al, 4 + jbe get_bpp_noinc + mov ah, al +if VBOX_BIOS_CPU gt 8086 + shr ah, 3 +else + shr ah, 1 + shr ah, 1 + shr ah, 1 +endif + test al, 07 + jz get_bpp_noinc + inc ah +get_bpp_noinc: + pop dx + ret + +; get display capabilities + +_dispi_get_max_bpp: + push dx + push bx + call dispi_get_enable + mov bx, ax + or ax, VBE_DISPI_GETCAPS + call dispi_set_enable_ + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BPP + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + push ax + mov ax, bx + call dispi_set_enable_ + pop ax + pop bx + pop dx + ret + +dispi_set_enable_: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_ENABLE + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + pop dx + ret + +dispi_get_enable: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_ENABLE + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + pop dx + ret + +dispi_set_bank_: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BANK + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + pop dx + ret + +dispi_get_bank: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BANK + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + pop dx + ret + +_dispi_set_bank_farcall: + cmp bx, 0100h + je dispi_set_bank_farcall_get + or bx,bx + jnz dispi_set_bank_farcall_error + mov ax, dx + push dx + push ax + mov ax, VBE_DISPI_INDEX_BANK + mov dx, VBE_DISPI_IOPORT_INDEX + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + in_ax_dx + pop dx + cmp dx,ax + jne dispi_set_bank_farcall_error + mov ax, 004Fh + retf +dispi_set_bank_farcall_get: + mov ax, VBE_DISPI_INDEX_BANK + mov dx, VBE_DISPI_IOPORT_INDEX + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + mov dx,ax + retf +dispi_set_bank_farcall_error: + mov ax, 014Fh + retf + +dispi_set_x_offset: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_X_OFFSET + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + pop dx + ret + +dispi_get_x_offset: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_X_OFFSET + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + pop dx + ret + +dispi_set_y_offset: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_Y_OFFSET + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + pop dx + ret + +dispi_get_y_offset: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_Y_OFFSET + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + pop dx + ret + +vga_set_virt_width: + push ax + push bx + push dx + mov bx, ax + call dispi_get_bpp + cmp al, 4 + ja set_width_svga + shr bx, 1 +set_width_svga: +if VBOX_BIOS_CPU gt 8086 + shr bx, 3 +else + shr bx, 1 + shr bx, 1 + shr bx, 1 +endif + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov ah, bl + mov al, 13h + out dx, ax + pop dx + pop bx + pop ax + ret + +_vga_compat_setup: + push ax + push dx + + ; set CRT X resolution + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_XRES + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + push ax + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov ax, 0011h + out dx, ax + pop ax + push ax +if VBOX_BIOS_CPU gt 8086 + shr ax, 3 +else + shr ax, 1 + shr ax, 1 + shr ax, 1 +endif + dec ax + mov ah, al + mov al, 01 + out dx, ax + pop ax + call vga_set_virt_width + + ; set CRT Y resolution + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_YRES + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + dec ax + push ax + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov ah, al + mov al, 12h + out dx, ax + pop ax + mov al, 07 + out dx, al + inc dx + in al, dx + and al, 0BDh + test ah, 01 + jz bit8_clear + or al, 02 +bit8_clear: + test ah, 02 + jz bit9_clear + or al, 40h +bit9_clear: + out dx, al + + ; other settings + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov ax, 0009 + out dx, al + mov dx, VGAREG_VGA_CRTC_DATA + in al, dx + and al, 60h ; clear double scan bit and cell height + out dx, al + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov al, 17h + out dx, al + mov dx, VGAREG_VGA_CRTC_DATA + in al, dx + or al, 03 + out dx, al + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 10h + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + or al, 01 + mov dx, VGAREG_ACTL_ADDRESS + out dx, al + mov al, 20h + out dx, al + mov dx, VGAREG_GRDC_ADDRESS + mov ax, 0506h + out dx, ax + mov dx, VGAREG_SEQU_ADDRESS + mov ax, 0F02h + out dx, ax + + ; settings for >= 8bpp + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BPP + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + cmp al, 08 + jb vga_compat_end + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov al, 14h + out dx, al + mov dx, VGAREG_VGA_CRTC_DATA + in al, dx + or al, 40h + out dx, al + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 10h + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + or al, 40h + mov dx, VGAREG_ACTL_ADDRESS + out dx, al + mov al, 20h + out dx, al + mov dx, VGAREG_SEQU_ADDRESS + mov al, 04 + out dx, al + mov dx, VGAREG_SEQU_DATA + in al, dx + or al, 08 + out dx, al + mov dx, VGAREG_GRDC_ADDRESS + mov al, 05 + out dx, al + mov dx, VGAREG_GRDC_DATA + in al, dx + and al, 9Fh + or al, 40h + out dx, al + +vga_compat_end: + pop dx + pop ax + + +; Has VBE display - Returns true if VBE display detected + +_vbe_has_vbe_display: + push ds + push bx + mov ax, BIOSMEM_SEG + mov ds, ax + mov bx, BIOSMEM_VBE_FLAG + mov al, [bx] + and al, 01 + xor ah, ah + pop bx + pop ds + ret + + +; Function 03h - Return Current VBE Mode +; +; Input: +; AX = 4F03h +; Output: +; AX = VBE Return Status +; BX = Current VBE Mode +; +; +vbe_biosfn_return_current_mode: + push ds + mov ax, BIOSMEM_SEG + mov ds, ax + call dispi_get_enable + and ax, VBE_DISPI_ENABLED + jz no_vbe_mode + mov bx, BIOSMEM_VBE_MODE + mov ax, [bx] + mov bx, ax + jnz vbe_03_ok +no_vbe_mode: + mov bx, BIOSMEM_CURRENT_MODE + mov al, [bx] + mov bl, al + xor bh, bh +vbe_03_ok: + mov ax, 004Fh + pop ds + ret + + +; Function 05h - Display Window Control +; +; Input: +; AX = 4F05h +; (16-bit) BH = 00h Set memory window +; = 01h Get memory window +; BL = Window number +; = 00h Window A +; = 01h Window B +; DX = Window number in video memory in window +; granularity units (Set Memory Window only) +; Note: +; If this function is called while in a linear frame buffer mode, +; this function must fail with completion code AH=03h +; +; Output: +; AX = VBE Return Status +; DX = Window number in window granularity units +; (Get Memory Window only) + +vbe_biosfn_display_window_control: + cmp bl, 0 + jne vbe_05_failed + cmp bh, 1 + je get_display_window + jb set_display_window + mov ax, 0100h + ret +set_display_window: + mov ax, dx + call dispi_set_bank_ + call dispi_get_bank + cmp ax, dx + jne vbe_05_failed + mov ax, 004Fh + ret +get_display_window: + call dispi_get_bank + mov dx, ax + mov ax, 004Fh + ret +vbe_05_failed: + mov ax, 014Fh + ret + + +; Function 07h - Set/Get Display Start +; +; Input(16-bit): +; AX = 4F07h +; BH = 00h Reserved and must be 00h +; BL = 00h Set Display Start +; = 01h Get Display Start +; = 02h Schedule Display Start (Alternate) +; = 03h Schedule Stereoscopic Display Start +; = 04h Get Scheduled Display Start Status +; = 05h Enable Stereoscopic Mode +; = 06h Disable Stereoscopic Mode +; = 80h Set Display Start during Vertical Retrace +; = 82h Set Display Start during Vertical Retrace (Alternate) +; = 83h Set Stereoscopic Display Start during Vertical Retrace +; ECX = If BL=02h/82h Display Start Address in bytes +; If BL=03h/83h Left Image Start Address in bytes +; EDX = If BL=03h/83h Right Image Start Address in bytes +; CX = If BL=00h/80h First Displayed Pixel In Scan Line +; DX = If BL=00h/80h First Displayed Scan Line +; +; Output: +; AX = VBE Return Status +; BH = If BL=01h Reserved and will be 0 +; CX = If BL=01h First Displayed Pixel In Scan Line +; If BL=04h 0 if flip has not occurred, not 0 if it has +; DX = If BL=01h First Displayed Scan Line +; +; Input(32-bit): +; BH = 00h Reserved and must be 00h +; BL = 00h Set Display Start +; = 80h Set Display Start during Vertical Retrace +; CX = Bits 0-15 of display start address +; DX = Bits 16-31 of display start address +; ES = Selector for memory mapped registers +; +vbe_biosfn_set_get_display_start: + cmp bl, 80h + je set_display_start_wait + cmp bl, 1 + je get_display_start + jb set_display_start + mov ax, 0100h + ret +set_display_start_wait: + call wait_not_vsync + call wait_vsync +set_display_start: + mov ax, cx + call dispi_set_x_offset + mov ax, dx + call dispi_set_y_offset + mov ax, 004Fh + ret +get_display_start: + call dispi_get_x_offset + mov cx, ax + call dispi_get_y_offset + mov dx, ax + xor bh, bh + mov ax, 004Fh + ret + + +; Function 08h - Set/Get Dac Palette Format +; +; Input: +; AX = 4F08h +; BL = 00h set DAC palette width +; = 01h get DAC palette width +; BH = If BL=00h: desired number of bits per primary color +; Output: +; AX = VBE Return Status +; BH = current number of bits per primary color (06h = standard VGA) +; +vbe_biosfn_set_get_dac_palette_format: + cmp bl, 1 + je get_dac_palette_format + jb set_dac_palette_format + mov ax, 0100h + ret +set_dac_palette_format: + call dispi_get_enable + cmp bh, 6 + je set_normal_dac + cmp bh, 8 + jne vbe_08_unsupported + or ax, VBE_DISPI_8BIT_DAC + jnz set_dac_mode +set_normal_dac: + and ax, NOT VBE_DISPI_8BIT_DAC +set_dac_mode: + call dispi_set_enable_ +get_dac_palette_format: + mov bh, 6 + call dispi_get_enable + and ax, VBE_DISPI_8BIT_DAC + jz vbe_08_ok + mov bh, 8 +vbe_08_ok: + mov ax, 004Fh + ret +vbe_08_unsupported: + mov ax, 014Fh + ret + + +; Function 09h - Set/Get Palette Data +; +; Input: +; AX = 4F09h +; (16-bit) BL = 00h Set palette data +; = 01h Get palette data +; = 02h Set secondary palette data +; = 03h Get secondary palette data +; = 80h Set palette data during VRetrace +; CX = Number of entries to update (<= 256) +; DX = First entry to update +; ES:DI = Table of palette values +; Output: +; AX = VBE Return Status +; +; Notes: +; Secondary palette support is a "future extension". +; Attempts to set/get it should return status 02h. +; +; In VBE 3.0, reading palette data is optional and +; subfunctions 01h and 03h may return failure. +; +; The format of palette entries is as follows: +; +; PaletteEntry struc +; Blue db ? ; Blue channel value (6 or 8 bits) +; Green db ? ; Green channel value (6 or 8 bits) +; Red db ? ; Red channel value (6 or 8 bits) +; Padding db ? ; DWORD alignment byte (unused) +; PaletteEntry ends +; +; Most applications use VGA DAC registers directly to +; set/get palette in VBE modes. However, subfn 4F09h is +; required for NonVGA controllers (eg. XGA). +; +vbe_biosfn_set_get_palette_data: + test bl, bl + jz set_palette_data + cmp bl, 01 + je get_palette_data + cmp bl, 03 + jbe vbe_09_nohw + cmp bl, 80h + jne vbe_09_unsupported +if 0 + ; this is where we could wait for vertical retrace +endif +set_palette_data: + DO_pushad + push ds + push es + pop ds + mov al, dl + mov dx, VGAREG_DAC_WRITE_ADDRESS + out dx, al + inc dx + mov si, di +set_pal_loop: +if VBOX_BIOS_CPU ge 80386 + lodsd + ror eax, 16 + out dx, al + rol eax, 8 + out dx, al + rol eax, 8 + out dx, al +else + lodsw + mov bx, ax + lodsw + out dx, al + mov al, bh + out dx, al + mov al, bl + out dx, al +endif + loop set_pal_loop + pop ds + DO_popad +vbe_09_ok: + mov ax, 004Fh + ret + +get_palette_data: + DO_pushad + mov al, dl + mov dx, VGAREG_DAC_READ_ADDRESS + out dx, al + add dl, 2 +if VBOX_BIOS_CPU ge 80386 +get_pal_loop: + xor eax, eax + in al, dx + shl eax, 8 + in al, dx + shl eax, 8 + in al, dx + stosd +else + xor bx, bx +get_pal_loop: + in al, dx + mov bl, al + in al, dx + mov ah, al + in al, dx + stosw + mov ax, bx + stosw +endif + loop get_pal_loop + DO_popad + jmp vbe_09_ok + +vbe_09_unsupported: + mov ax, 014Fh + ret +vbe_09_nohw: + mov ax, 024Fh + ret + + +; Function 0Ah - Return VBE Protected Mode Interface +; +; Input: AX = 4F0Ah VBE 2.0 Protected Mode Interface +; BL = 00h Return protected mode table +; Output: AX = Status +; ES = Real Mode Segment of Table +; DI = Offset of Table +; CX = Length of Table including protected mode code +; (for copying purposes) +; +vbe_biosfn_return_protected_mode_interface: + test bl, bl + jnz _fail + push cs + pop es + mov di, offset vesa_pm_start + mov cx, vesa_pm_end - vesa_pm_start + mov ax, 004Fh + ret +_fail: + mov ax, 014fh + ret + +VGAROM ends + +;; +;; 32-bit VBE interface +;; + +.386 + +public vesa_pm_start +public vesa_pm_end + +VBE32 segment public use32 'CODE' + + align 2 + +vesa_pm_start: + dw vesa_pm_set_window - vesa_pm_start + dw vesa_pm_set_display_start - vesa_pm_start + dw vesa_pm_unimplemented - vesa_pm_start + dw vesa_pm_io_ports_table - vesa_pm_start +vesa_pm_io_ports_table: + dw VBE_DISPI_IOPORT_INDEX + dw VBE_DISPI_IOPORT_INDEX + 1 + dw VBE_DISPI_IOPORT_DATA + dw VBE_DISPI_IOPORT_DATA + 1 + dw 3B6h + dw 3B7h + dw 0FFFFh + dw 0FFFFh + +vesa_pm_set_window: + cmp bx, 0 + je vesa_pm_set_display_window1 + mov ax, 0100h + ret +vesa_pm_set_display_window1: + mov ax, dx + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BANK + out dx, ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out dx, ax + in ax, dx + pop dx + cmp dx, ax + jne illegal_window + mov ax, 004Fh + ret +illegal_window: + mov ax, 014Fh + ret +vesa_pm_set_display_start: + cmp bl, 80h + je vesa_pm_set_display_start1_wait + cmp bl, 00 + je vesa_pm_set_display_start1 + mov ax, 0100h + ret +vesa_pm_set_display_start1_wait: + push edx + mov dx, 03DAh ; @todo: use symbolic constant +wnv_loop_32: + in al, dx + test al, 8 + jnz wnv_loop_32 +wv_loop_32: + in al, dx + test al, 8 + jz wv_loop_32 + pop edx +vesa_pm_set_display_start1: +; convert offset to (X, Y) coordinate +; (would be simpler to change Bochs VBE API...) + push eax + push ecx + push edx + push esi + push edi + shl edx, 16 + and ecx, 0FFFFh + or ecx, edx + shl ecx, 2 + mov eax, ecx + push eax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_VIRT_WIDTH + out dx, ax + mov dx, VBE_DISPI_IOPORT_DATA + in ax, dx + movzx ecx, ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BPP + out dx, ax + mov dx, VBE_DISPI_IOPORT_DATA + in ax, dx + movzx esi, ax + pop eax + + cmp esi, 4 + jz bpp4_mode + add esi, 7 + shr esi, 3 + imul ecx, esi + xor edx, edx + div ecx + mov edi, eax + mov eax, edx + xor edx, edx + div esi + jmp set_xy_regs + +bpp4_mode: + shr ecx, 1 + xor edx, edx + div ecx + mov edi, eax + mov eax, edx + shl eax, 1 + +set_xy_regs: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_X_OFFSET + out dx, ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out dx, ax + pop dx + + mov ax, di + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_Y_OFFSET + out dx, ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out dx, ax + pop dx + + pop edi + pop esi + pop edx + pop ecx + pop eax + mov ax, 004fh + ret + +vesa_pm_unimplemented: + mov ax, 014Fh + ret +vesa_pm_end: + +VBE32 ends + + end diff --git a/src/VBox/Devices/Graphics/BIOS/vbetables-gen.c b/src/VBox/Devices/Graphics/BIOS/vbetables-gen.c new file mode 100644 index 00000000..f572386a --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vbetables-gen.c @@ -0,0 +1,245 @@ +/* Generate the VGABIOS VBE Tables */ +#include +#include + +#define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 8 + +typedef struct { + int width; + int height; + int depth; + int mode; +} ModeInfo; + +ModeInfo modes[] = { + /* standard VESA modes */ +{ 640, 400, 8 , 0x100}, +{ 640, 480, 8 , 0x101}, +{ 800, 600, 4 , 0x102}, +{ 800, 600, 8 , 0x103}, +{ 1024, 768, 4 , 0x104}, +{ 1024, 768, 8 , 0x105}, +{ 1280, 1024, 4 , 0x106}, +{ 1280, 1024, 8 , 0x107}, +{ 320, 200, 15 , 0x10D}, +{ 320, 200, 16 , 0x10E}, +{ 320, 200, 24 , 0x10F}, +{ 640, 480, 15 , 0x110}, +{ 640, 480, 16 , 0x111}, +{ 640, 480, 24 , 0x112}, +{ 800, 600, 15 , 0x113}, +{ 800, 600, 16 , 0x114}, +{ 800, 600, 24 , 0x115}, +{ 1024, 768, 15 , 0x116}, +{ 1024, 768, 16 , 0x117}, +{ 1024, 768, 24 , 0x118}, +{ 1280, 1024, 15 , 0x119}, +{ 1280, 1024, 16 , 0x11A}, +{ 1280, 1024, 24 , 0x11B}, +#if 0 /* Ubuntu fails with this */ +{ 1600, 1200, 8 , 0x11C}, +{ 1600, 1200, 15 , 0x11D}, +{ 1600, 1200, 16 , 0x11E}, +{ 1600, 1200, 24 , 0x11F}, +#endif + + /* BOCHS/PLE, 86 'own' mode numbers */ +{ 320, 200, 32 , 0x140}, +{ 640, 400, 32 , 0x141}, +{ 640, 480, 32 , 0x142}, +{ 800, 600, 32 , 0x143}, +{ 1024, 768, 32 , 0x144}, +{ 1280, 1024, 32 , 0x145}, +{ 320, 200, 8 , 0x146}, +{ 1600, 1200, 32 , 0x147}, +{ 1152, 864, 8 , 0x148}, +{ 1152, 864, 15 , 0x149}, +{ 1152, 864, 16 , 0x14a}, +{ 1152, 864, 24 , 0x14b}, +{ 1152, 864, 32 , 0x14c}, +{ 0, }, +}; + +int main(int argc, char **argv) +{ + const ModeInfo *pm; + int pages, pitch; + int r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos; + const char *str; + long vram_size = VBE_DISPI_TOTAL_VIDEO_MEMORY_MB * 1024 * 1024; + + (void)argc; (void)argv; + + printf("/* THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n"); + printf("#define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB %d\n\n", VBE_DISPI_TOTAL_VIDEO_MEMORY_MB); + printf("static ModeInfoListItem mode_info_list[]=\n"); + printf("{\n"); + for (pm = modes; pm->mode != 0; pm++) { + if (pm->depth == 4) + pitch = (pm->width + 7) / 8; + else + pitch = pm->width * ((pm->depth + 7) / 8); + pages = vram_size / (pm->height * pitch); + if (pages > 0) { + printf("{ 0x%04x, /* %dx%dx%d */\n", + pm->mode, pm->width, pm->height, pm->depth); + if (pm->depth == 4) + printf("{ /*Bit16u ModeAttributes*/ %s,\n", + "VBE_MODE_ATTRIBUTE_SUPPORTED | " + "VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | " + "VBE_MODE_ATTRIBUTE_COLOR_MODE | " + "VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT | " + "VBE_MODE_ATTRIBUTE_GRAPHICS_MODE"); + else + printf("{ /*Bit16u ModeAttributes*/ %s,\n", + "VBE_MODE_ATTRIBUTE_SUPPORTED | " + "VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | " + "VBE_MODE_ATTRIBUTE_COLOR_MODE | " + "VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE | " + "VBE_MODE_ATTRIBUTE_GRAPHICS_MODE"); + printf("/*Bit8u WinAAttributes*/ %s,\n", + "VBE_WINDOW_ATTRIBUTE_RELOCATABLE | " + "VBE_WINDOW_ATTRIBUTE_READABLE | " + "VBE_WINDOW_ATTRIBUTE_WRITEABLE"); + + printf("/*Bit8u WinBAttributes*/ %d,\n", 0); + + printf("/*Bit16u WinGranularity*/ %s,\n", "VBE_DISPI_BANK_SIZE_KB"); + + printf("/*Bit16u WinSize*/ %s,\n", "VBE_DISPI_BANK_SIZE_KB"); + + printf("/*Bit16u WinASegment*/ %s,\n", "VGAMEM_GRAPH"); + + printf("/*Bit16u WinBSegment*/ 0x%04x,\n", 0); + + printf("/*Bit32u WinFuncPtr*/ %d,\n", 0); + + printf("/*Bit16u BytesPerScanLine*/ %d,\n", pitch); + + /* Mandatory information for VBE 1.2 and above */ + printf("/*Bit16u XResolution*/ %d,\n", pm->width); + printf("/*Bit16u YResolution*/ %d,\n", pm->height); + printf("/*Bit8u XCharSize*/ %d,\n", 8); + printf("/*Bit8u YCharSize*/ %d,\n", 16); + if (pm->depth == 4) { + printf("/*Bit8u NumberOfPlanes*/ %d,\n", 4); + } else { + printf("/*Bit8u NumberOfPlanes*/ %d,\n", 1); + } + printf("/*Bit8u BitsPerPixel*/ %d,\n", pm->depth); + printf("/*Bit8u NumberOfBanks*/ %d,\n", 1); /* This would only be non-zero for CGA/HGC modes! */ + + if (pm->depth == 4) + str = "VBE_MEMORYMODEL_PLANAR"; + else if (pm->depth == 8) + str = "VBE_MEMORYMODEL_PACKED_PIXEL"; + else + str = "VBE_MEMORYMODEL_DIRECT_COLOR"; + printf("/*Bit8u MemoryModel*/ %s,\n", str); + printf("/*Bit8u BankSize*/ %d,\n", 0); + if (pm->depth == 4) + printf("/*Bit8u NumberOfImagePages*/ %d,\n", (pages / 4) - 1); + else + printf("/*Bit8u NumberOfImagePages*/ %d,\n", pages - 1); + printf("/*Bit8u Reserved_page*/ %d,\n", 0); + + /* Direct Color fields (required for direct/6 and YUV/7 memory models) */ + switch(pm->depth) { + case 15: + r_size = 5; + r_pos = 10; + g_size = 5; + g_pos = 5; + b_size = 5; + b_pos = 0; + a_size = 1; + a_pos = 15; + break; + case 16: + r_size = 5; + r_pos = 11; + g_size = 6; + g_pos = 5; + b_size = 5; + b_pos = 0; + a_size = 0; + a_pos = 0; + break; + case 24: + r_size = 8; + r_pos = 16; + g_size = 8; + g_pos = 8; + b_size = 8; + b_pos = 0; + a_size = 0; + a_pos = 0; + break; + case 32: + r_size = 8; + r_pos = 16; + g_size = 8; + g_pos = 8; + b_size = 8; + b_pos = 0; + a_size = 8; + a_pos = 24; + break; + default: + r_size = 0; + r_pos = 0; + g_size = 0; + g_pos = 0; + b_size = 0; + b_pos = 0; + a_size = 0; + a_pos = 0; + break; + } + + printf("/*Bit8u RedMaskSize*/ %d,\n", r_size); + printf("/*Bit8u RedFieldPosition*/ %d,\n", r_pos); + printf("/*Bit8u GreenMaskSize*/ %d,\n", g_size); + printf("/*Bit8u GreenFieldPosition*/ %d,\n", g_pos); + printf("/*Bit8u BlueMaskSize*/ %d,\n", b_size); + printf("/*Bit8u BlueFieldPosition*/ %d,\n", b_pos); + printf("/*Bit8u RsvdMaskSize*/ %d,\n", a_size); + printf("/*Bit8u RsvdFieldPosition*/ %d,\n", a_pos); + if (pm->depth == 32) + printf("/*Bit8u DirectColorModeInfo*/ %s,\n", + "VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE"); + else + printf("/*Bit8u DirectColorModeInfo*/ %s,\n", "0"); + + /* Mandatory information for VBE 2.0 and above */ + if (pm->depth > 4) + printf("/*Bit32u PhysBasePtr*/ %s,\n", + "0xFFFF0000 /* Filled in at run-time; low word must be zero! */"); + else + printf("/*Bit32u PhysBasePtr*/ %s,\n", "0"); + printf("/*Bit32u OffScreenMemOffset*/ %d,\n", 0); + printf("/*Bit16u OffScreenMemSize*/ %d,\n", 0); + /* Mandatory information for VBE 3.0 and above */ + printf("/*Bit16u LinBytesPerScanLine*/ %d,\n", pitch); + printf("/*Bit8u BnkNumberOfPages*/ %d,\n", 0); + printf("/*Bit8u LinNumberOfPages*/ %d,\n", 0); + printf("/*Bit8u LinRedMaskSize*/ %d,\n", r_size); + printf("/*Bit8u LinRedFieldPosition*/ %d,\n", r_pos); + printf("/*Bit8u LinGreenMaskSize*/ %d,\n", g_size); + printf("/*Bit8u LinGreenFieldPosition*/ %d,\n", g_pos); + printf("/*Bit8u LinBlueMaskSize*/ %d,\n", b_size); + printf("/*Bit8u LinBlueFieldPosition*/ %d,\n", b_pos); + printf("/*Bit8u LinRsvdMaskSize*/ %d,\n", a_size); + printf("/*Bit8u LinRsvdFieldPosition*/ %d,\n", a_pos); + printf("/*Bit32u MaxPixelClock*/ %d,\n", 0); + printf("} },\n"); + } + } +#ifndef VBOX /* We'll add the terminator ourselves, thank you. */ + printf("{ VBE_VESA_MODE_END_OF_LIST,\n"); + printf("{ 0,\n"); + printf("} },\n"); +#endif + printf("};\n"); + return 0; +} diff --git a/src/VBox/Devices/Graphics/BIOS/vgabios.c b/src/VBox/Devices/Graphics/BIOS/vgabios.c new file mode 100644 index 00000000..7c415481 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vgabios.c @@ -0,0 +1,2805 @@ +// ============================================================================================ +/* + * vgabios.c + */ +// ============================================================================================ +// +// Copyright (C) 2001,2002 the LGPL VGABios developers Team +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// ============================================================================================ +// +// This VGA Bios is specific to the plex86/bochs Emulated VGA card. +// You can NOT drive any physical vga card with it. +// +// ============================================================================================ +// +// This file contains code ripped from : +// - rombios.c of plex86 +// +// This VGA Bios contains fonts from : +// - fntcol16.zip (c) by Joseph Gil avalable at : +// ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip +// These fonts are public domain +// +// This VGA Bios is based on information taken from : +// - Kevin Lawton's vga card emulation for bochs/plex86 +// - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html +// - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/ +// - Michael Abrash's Graphics Programming Black Book +// - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex +// - DOSEMU 1.0.1 source code for several tables values and formulas +// +// Thanks for patches, comments and ideas to : +// - techt@pikeonline.net +// +// ============================================================================================ + + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include +#include "vgabios.h" + +#ifdef VBE +#include "vbe.h" +#endif + +#include "inlines.h" + +/* Declares */ +extern void vgabios_int10_handler(void); +#pragma aux vgabios_int10_handler "*"; + +// Output +void __cdecl unimplemented(void); +void __cdecl unknown(void); + +static uint8_t find_vga_entry(); + +extern uint8_t readx_byte(uint16_t seg, uint16_t offset); + +#ifdef VBE +extern uint16_t __cdecl vbe_has_vbe_display(void); +extern void vbe_init(void); +#endif + +void set_int_vector(uint8_t int_vec, void __far *ptr) +{ + void __far * __far *ivt = 0; + + ivt[int_vec] = ptr; +} + +//@todo!! +#if 0 + +vgabios_name: +#ifdef VBOX +.ascii "VirtualBox VGA BIOS" +#else +.ascii "Plex86/Bochs VGABios" +#endif +.ascii " " +.byte 0x00 + +#ifndef VBOX +vgabios_version: +#ifndef VGABIOS_VERS +.ascii "current-cvs" +#else +.ascii VGABIOS_VERS +#endif +.ascii " " + +vgabios_date: +.ascii VGABIOS_DATE +.byte 0x0a,0x0d +.byte 0x00 +#endif + +#ifndef VBOX +char vgabios_copyright[] = "(C) 2003 the LGPL VGABios developers Team\r\n"; +char vgabios_license[] = "This VGA/VBE Bios is released under the GNU LGPL\r\n\r\n"; +char vgabios_website[] = "Please visit :\r\n" \ + " . http://www.plex86.org\r\n" \ + " . http://bochs.sourceforge.net\r\n" \ + " . http://www.nongnu.org/vgabios\r\n\r\n" +#endif + +#endif + +extern void set_mode(int mode); +#pragma aux set_mode = \ + "xor ah, ah" \ + "int 10h" \ + parm [ax]; + +char msg_vga_init[] = "Oracle VM VirtualBox Version " VBOX_VERSION_STRING " VGA BIOS\r\n"; + +/* + * Boot time harware inits + */ +void init_vga_card(void) +{ + /* Switch to color mode and enable CPU access 480 lines. */ + outb(0x3C2, 0xC3); + /* More than 64k 3C4/04. */ + /// @todo 16-bit write + outb(0x3C4, 0x04); + outb(0x3C5, 0x02); + +#ifdef DEBUG_VGA + printf(msg_vga_init); +#endif +} + +#include "vgatables.h" +#include "vgadefs.h" + +// -------------------------------------------------------------------------------------------- + +#pragma pack(0) + +/* Alphanumeric character set override. */ +typedef struct { + uint8_t c_height; /* Bytes/lines per character. */ + uint8_t cgen_bank; /* Character generator bank. */ + uint16_t char_num; /* Number of chars defined. */ + uint16_t char_1st; /* First char code in table. */ + uint16_t font_ofs; /* Font definition table offset. */ + uint16_t font_seg; /* Font definition table segment. */ + uint8_t n_rows; /* Number of text rows shown. */ + uint8_t modes[1]; /* Applicable modes list, 0xFF terminated. */ +} cso_txt; + +/* Graphics character set override. */ +typedef struct { + uint8_t c_height; /* Lines per character. */ + uint16_t c_len; /* Bytes per character. */ + uint16_t font_ofs; /* Font definition table offset. */ + uint16_t font_seg; /* Font definition table segment. */ + uint8_t modes[1]; /* Applicable modes list, 0xFF terminated. */ +} cso_grf; + +struct dcc { + uint8_t n_ent; + uint8_t version; + uint8_t max_code; + uint8_t reserved; + uint16_t dccs[16]; +} dcc_table = { + 16, + 1, + 7, + 0 +}; + +struct ssa { + uint16_t size; + void __far *dcc; + void __far *sacs; + void __far *pal; + void __far *resvd[3]; + +} secondary_save_area = { + sizeof(struct ssa), + &dcc_table +}; + +void __far *video_save_pointer_table[7] = { + &video_param_table, + 0, + 0, + 0, + &secondary_save_area +}; + +/* + * Boot time bios area inits + */ +void init_bios_area(void) +{ + uint8_t __far *bda; + + bda = 0x40 :> 0; + + /* Indicate 80x25 color was detected. */ + bda[BIOSMEM_INITIAL_MODE] = (bda[BIOSMEM_INITIAL_MODE] & 0xcf) | 0x20; + /* Just for the first int10 find its children. */ + + /* The default char height. */ + bda[BIOSMEM_CHAR_HEIGHT] = 16; + /* Clear the screen. */ + bda[BIOSMEM_VIDEO_CTL] = 0x60; + /* Set the basic screen we have. */ + bda[BIOSMEM_SWITCHES] = 0xf9; + /* Set the basic mode set options. */ + bda[BIOSMEM_MODESET_CTL] = 0x51; + /* Set the default MSR. */ + bda[BIOSMEM_CURRENT_MSR] = 0x09; + /* Initialize the default save area pointer. */ + *(void __far * __far *)&bda[BIOSMEM_VS_POINTER] = video_save_pointer_table; +} + +// ============================================================================================ +// +// Init Entry point +// +// ============================================================================================ +void __far __cdecl vgabios_init_func(void) +{ + init_vga_card(); + init_bios_area(); +#ifdef VBE + vbe_init(); +#endif + set_int_vector(0x10, vgabios_int10_handler); + set_int_vector(0x6D, vgabios_int10_handler); +#ifdef CIRRUS + cirrus_init(); +#endif + +#ifndef VBOX + display_splash_screen(); + + // init video mode and clear the screen + // @@AS: Do not remove this init, because it will break VESA graphics + set_mode(3); + + display_info(); + +#ifdef VBE + vbe_display_info(); +#endif + +#ifdef CIRRUS + cirrus_display_info(); +#endif + +#else /* VBOX */ + +//#ifdef DEBUG_bird + /* Init video mode and clear the screen */ + set_mode(3); +//#endif +#endif /* VBOX */ +} + +#include "vgafonts.h" + +#ifndef VBOX +// -------------------------------------------------------------------------------------------- +/* + * Boot time Splash screen + */ +static void display_splash_screen() +{ +} + +// -------------------------------------------------------------------------------------------- +/* + * Tell who we are + */ + +static void display_string(void) +{ + // Get length of string +ASM_START + mov ax,ds + mov es,ax + mov di,si + xor cx,cx + not cx + xor al,al + cld + repne + scasb + not cx + dec cx + push cx + + mov ax,#0x0300 + mov bx,#0x0000 + int #0x10 + + pop cx + mov ax,#0x1301 + mov bx,#0x000b + mov bp,si + int #0x10 +ASM_END +} + +static void display_info(void) +{ + display_string(vgabios_name); + display_string(vgabios_version); + display_string(vgabios_copyright); + display_string(vgabios_license); + display_string(vgabios_website); +} + +#endif + +// -------------------------------------------------------------------------------------------- +#ifdef VGA_DEBUG +void __cdecl int10_debugmsg(uint16_t DI, uint16_t SI, uint16_t BP, uint16_t SP, uint16_t BX, + uint16_t DX, uint16_t CX, uint16_t AX, uint16_t DS, uint16_t ES, uint16_t FLAGS) +{ + /* Function 0Eh is write char and would generate way too much output. */ + if (GET_AH() != 0x0E) + printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n", GET_AH(), GET_AL(), BX, CX, DX); +} +#endif + +static void vga_get_cursor_pos(uint8_t page, uint16_t STACK_BASED *scans, uint16_t STACK_BASED *loc) +{ + if (page > 7) { + *scans = 0; + *loc = 0; + } else { + // FIXME should handle VGA 14/16 lines + *scans = read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE); + *loc = read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS + page * 2); + } +} + +/* Look for a glyph bitmap in a given font. */ +static uint16_t vga_find_glyph(uint8_t __far *font, uint8_t STACK_BASED *glyph, uint8_t cp, uint16_t n_glyphs, uint8_t cheight) +{ + uint16_t codepoint = 0; /* Zero returned when glyph not found. */ + + while (n_glyphs--) { + if (!repe_cmpsb(font, glyph, cheight)) { + codepoint = cp | 0x8000; /* Found matching glyph! */ + break; + } + font += cheight; + ++cp; /* Increment code point number. */ + } + return codepoint; +} + +static void vga_read_glyph_planar(uint8_t __far *vptr, uint16_t stride, uint8_t STACK_BASED *glyph, uint8_t cheight) +{ + /* Set Mode Register (GR5) to Read Mode 1. Assuming default register + * state from our mode set, this does all the hard work for us such that + * reading a byte from video memory gives us a bit mask for all eight + * pixels, for both 16-color and monochrome modes. + */ + outw(VGAREG_GRDC_ADDRESS, 0x0805); + + while (cheight--) { + *glyph++ = ~*vptr; + vptr += stride; + } + + /* Put GR5 back to Read Mode 0. */ + outw(VGAREG_GRDC_ADDRESS, 0x0005); +} + +static uint16_t vga_char_ofs_planar(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols, uint8_t page, uint8_t cheight) +{ + uint16_t ofs; + + ofs = ycurs * nbcols * cheight + xcurs; + ofs += page * read_word(BIOSMEM_SEG, BIOSMEM_PAGE_SIZE); + + return ofs; +} + +static uint8_t vga_read_char_planar(uint16_t nbcols, uint16_t ofs, uint8_t cheight) +{ + uint8_t glyph[16]; /* NB: Don't try taller characters! */ + + vga_read_glyph_planar(0xA000 :> (uint8_t *)ofs, nbcols, &glyph, cheight); + + /* Look through font pointed to by INT 43h. */ + return vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 256, cheight); +} + +static uint16_t vga_char_ofs_linear(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols, uint8_t page, uint8_t cheight) +{ + uint16_t ofs; + + ofs = ycurs * nbcols * cheight + xcurs; + ofs *= 8; + return ofs; +} + +static void vga_read_glyph_linear(uint8_t __far *vptr, uint16_t stride, uint8_t STACK_BASED *glyph, uint8_t cheight) +{ + uint8_t bmap, cbit; + int i; + + /* Zero pixels are background, everything else foreground. */ + while (cheight--) { + bmap = 0; + cbit = 0x80; + for (i = 0; i < 8; ++i) { + if (vptr[i]) + bmap |= cbit; + cbit >>= 1; + } + *glyph++ = bmap; + vptr += stride; + } +} + +static uint8_t vga_read_char_linear(uint16_t nbcols, uint16_t ofs, uint8_t cheight) +{ + uint8_t glyph[16]; /* NB: Don't try taller characters! */ + + vga_read_glyph_linear(0xA000 :> (uint8_t *)ofs, nbcols * 8, &glyph, cheight); + + /* Look through font pointed to by INT 43h. */ + return vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 256, cheight); +} + +static uint8_t vga_read_2bpp_char(uint8_t __far *vptr) +{ + uint16_t mask, pixb; + uint8_t bmap, cbit; + int i; + + mask = 0xC000; /* Check two bits at a time to see if they're zero. */ + cbit = 0x80; /* Go from left to right. */ + bmap = 0; + pixb = swap_16(*((uint16_t __far *)vptr)); + /* Go through 8 lines/words. */ + for (i = 0; i < 8; ++i) { + if (pixb & mask) + bmap |= cbit; + cbit >>= 1; + mask >>= 2; + } + return bmap; +} + +static void vga_read_glyph_cga(uint16_t ofs, uint8_t STACK_BASED *glyph, uint8_t mode) +{ + int i; + uint8_t __far *vptr; + + /* The font size is fixed at 8x8. Stride is always 80 bytes because the + * mode is either 80 characters wide at 1bpp or 40 characters at 2bpp. + */ + if (mode != 6) { + /* Adjust offset for 2bpp. */ + vptr = 0xB800 :> (uint8_t *)(ofs * 2); + /* For 2bpp modes, we have to extract the bits by hand. */ + for (i = 0; i < 4; ++i) { + *glyph++ = vga_read_2bpp_char(vptr); + *glyph++ = vga_read_2bpp_char(vptr + 0x2000); + vptr += 80; + } + } else { + vptr = 0xB800 :> (uint8_t *)ofs; + for (i = 0; i < 4; ++i) { + *glyph++ = vptr[0]; + *glyph++ = vptr[0x2000]; + vptr += 80; + } + } +} + +static uint16_t vga_char_ofs_cga(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols) +{ + /* Multiply ony by 8 due to line interleaving. NB: Caller + * has to multiply the result for two for 2bpp mode. + */ + return ycurs * nbcols * 4 + xcurs; +} + +static uint8_t vga_read_char_cga(uint16_t ofs, uint8_t mode) +{ + uint8_t glyph[8]; /* Char height is hardcoded to 8. */ + uint16_t found; + + /* Segment would be B000h for mono modes; we don't do those. */ + vga_read_glyph_cga(ofs, &glyph, mode); + + /* Look through the first half of the font pointed to by INT 43h. */ + found = vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 128, 8); + /* If not found, look for the second half pointed to by INT 1Fh */ + if (!(found & 0x8000)) { + void __far *int1f; + + int1f = (void __far *)read_dword(0, 0x1f * 4); + if (int1f) /* If null pointer, skip. */ + found = vga_find_glyph(int1f, &glyph, 128, 128, 8); + } + return found; +} + +static void vga_read_char_attr(uint8_t page, uint16_t STACK_BASED *chr_atr) +{ + uint8_t xcurs, ycurs, mode, line, cheight; + uint16_t nbcols, nbrows, address; + uint16_t cursor, dummy, ofs; + + // Get the mode + mode = read_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE); + line = find_vga_entry(mode); + if (line == 0xFF) + return; + + // Get the cursor pos for the page + vga_get_cursor_pos(page, &dummy, &cursor); + xcurs = cursor & 0x00ff; + ycurs = (cursor & 0xff00) >> 8; + + // Get the dimensions + nbrows = read_byte(BIOSMEM_SEG, BIOSMEM_NB_ROWS) + 1; + nbcols = read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS); + + if (vga_modes[line].class == TEXT) { + // Compute the address + address = SCREEN_MEM_START(nbcols, nbrows, page) + (xcurs + ycurs * nbcols) * 2; + *chr_atr = read_word(vga_modes[line].sstart, address); + } else { + switch (vga_modes[line].memmodel) { + case CGA: + /* For CGA graphics, font size is hardcoded at 8x8. */ + ofs = vga_char_ofs_cga(xcurs, ycurs, nbcols); + *chr_atr = vga_read_char_cga(ofs, mode); + break; + case PLANAR1: + case PLANAR4: + cheight = read_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT); + ofs = vga_char_ofs_planar(xcurs, ycurs, nbcols, page, cheight); + *chr_atr = vga_read_char_planar(nbcols, ofs, cheight); + break; + case LINEAR8: + cheight = read_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT); + ofs = vga_char_ofs_linear(xcurs, ycurs, nbcols, page, cheight); + *chr_atr = vga_read_char_linear(nbcols, ofs, cheight); + break; + default: +#ifdef VGA_DEBUG + unimplemented(); +#endif + break; + } + } +} + +static void vga_get_font_info (uint16_t func, uint16_t STACK_BASED *u_seg, uint16_t STACK_BASED *u_ofs, + uint16_t STACK_BASED *c_height, uint16_t STACK_BASED *max_row) +{ + void __far *ptr; + + switch (func) { + case 0x00: + ptr = (void __far *)read_dword(0x00, 0x1f * 4); + break; + case 0x01: + ptr = (void __far *)read_dword(0x00, 0x43 * 4); + break; + case 0x02: + ptr = vgafont14; + break; + case 0x03: + ptr = vgafont8; + break; + case 0x04: + ptr = vgafont8 + 128 * 8; + break; + case 0x05: + ptr = vgafont14alt; + break; + case 0x06: + ptr = vgafont16; + break; + case 0x07: + ptr = vgafont16alt; + break; + default: +#ifdef VGA_DEBUG + printf("Get font info subfn(%02x) not implemented\n", func); +#endif + return; + } + /* Split the far pointer and write it back. */ + *u_ofs = (uint16_t)ptr; + *u_seg = (uint32_t)ptr >> 16; + + /* The character height (effectively bytes per glyph). */ + *c_height = read_byte(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT); + + /* The highest row number. */ + *max_row = read_byte(BIOSMEM_SEG, BIOSMEM_NB_ROWS); +} + +static void vga_read_pixel(uint8_t page, uint16_t col, uint16_t row, uint16_t STACK_BASED *pixel) +{ + uint8_t mode, line, mask, attr, data, i; + uint16_t addr; + + /* Determine current mode characteristics. */ + mode = read_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE); + line = find_vga_entry(mode); + if (line == 0xFF) + return; + if (vga_modes[line].class == TEXT) + return; + + /* Read data depending on memory model. */ + switch (vga_modes[line].memmodel) { + case PLANAR4: + case PLANAR1: + addr = col / 8 + row * read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS); + addr += read_word(BIOSMEM_SEG, BIOSMEM_PAGE_SIZE) * page; + mask = 0x80 >> (col & 0x07); + attr = 0x00; + for (i = 0; i < 4; i++) { + outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04); + data = read_byte(0xa000,addr) & mask; + if (data > 0) + attr |= (0x01 << i); + } + break; + case CGA: + addr = (col >> (4 - vga_modes[line].pixbits)) + (row >> 1) * 80; + if (row & 1) + addr += 0x2000; + data = read_byte(0xb800, addr); + if (vga_modes[line].pixbits == 2) + attr = (data >> ((3 - (col & 0x03)) * 2)) & 0x03; + else + attr = (data >> (7 - (col & 0x07))) & 0x01; + break; + case LINEAR8: + addr = col + row * (read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS) * 8); + attr = read_byte(0xa000, addr); + break; + default: +#ifdef VGA_DEBUG + unimplemented(); +#endif + attr = 0; + } + *(uint8_t STACK_BASED *)pixel = attr; +} + + + +// -------------------------------------------------------------------------------------------- +/*static*/ void biosfn_perform_gray_scale_summing(uint16_t start, uint16_t count) +{uint8_t r,g,b; + uint16_t i; + uint16_t index; + + inb(VGAREG_ACTL_RESET); + outb(VGAREG_ACTL_ADDRESS,0x00); + + for( index = 0; index < count; index++ ) + { + // set read address and switch to read mode + outb(VGAREG_DAC_READ_ADDRESS,start); + // get 6-bit wide RGB data values + r=inb( VGAREG_DAC_DATA ); + g=inb( VGAREG_DAC_DATA ); + b=inb( VGAREG_DAC_DATA ); + + // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue ) + i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8; + + if(i>0x3f)i=0x3f; + + // set write address and switch to write mode + outb(VGAREG_DAC_WRITE_ADDRESS,start); + // write new intensity value + outb( VGAREG_DAC_DATA, i&0xff ); + outb( VGAREG_DAC_DATA, i&0xff ); + outb( VGAREG_DAC_DATA, i&0xff ); + start++; + } + inb(VGAREG_ACTL_RESET); + outb(VGAREG_ACTL_ADDRESS,0x20); +#ifdef VBOX + inb(VGAREG_ACTL_RESET); +#endif /* VBOX */ +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_set_cursor_shape(uint8_t CH, uint8_t CL) +{ + uint16_t cheight, curs, crtc_addr; + int cga_emu; + + /* Unmodified input is stored in the BDA. */ + curs = (CH << 8) + CL; + write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_TYPE, curs); + + /* Check if VGA is active. If not, just write the input to the CRTC. */ + if (!(read_byte(BIOSMEM_SEG, BIOSMEM_VIDEO_CTL) & 8)) { + /* Trying to disable the cursor? */ + if ((CH & 0x60) == 0x20) { + /* Special IBM-compatible value to turn off cursor. */ + CH = 0x1E; + CL = 0; + } else { + cga_emu = !(read_byte(BIOSMEM_SEG, BIOSMEM_VIDEO_CTL) & 1); + + /* If CGA cursor emulation is on and this is a text mode, adjust. + * But if cursor star or end is bigger than 31, don't adjust. + */ + /// @todo Figure out if this is a text mode + if (cga_emu /* && text mode*/ && (CH < 32) && (CL < 32)) { + cheight = read_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT); + + /* Is the end lower than start? VGA does not wrap around.*/ + if (CL < CH) { + /* For zero CL (end), leave values unchanged. */ + if (CL) { + CH = 0; + CL = cheight - 1; + } + } else { + if (((CL | CH) >= cheight) || ((CL != cheight - 1) && (CH != cheight - 2))) { + /* If it's an overbar cursor, don't adjust. */ + if (CL > 3) { + if (CL <= CH + 2) { + /* It's it a normal underline style cursor. */ + CH = CH - CL + cheight - 1; + CL = cheight - 1; + if (cheight >= 14) { + /* Shift up one pixel for normal EGA/VGA fonts. */ + CL--; + CH--; + } + } else if (CH <= 2) { + /* It's a full block cursor. */ + CL = cheight - 1; + } else { + /* It's a half block cursor. */ + CH = cheight / 2; + CL = cheight - 1; + } + } + } + } + } + } + } + + // CTRC regs 0x0a and 0x0b + crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS); + outb(crtc_addr, 0x0a); + outb(crtc_addr + 1, CH); + outb(crtc_addr, 0x0b); + outb(crtc_addr + 1 ,CL); +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_set_cursor_pos (uint8_t page, uint16_t cursor) +{ + uint8_t xcurs,ycurs,current; + uint16_t nbcols,nbrows,address,crtc_addr; + + // Should not happen... + if(page>7)return; + + // Bios cursor pos + write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor); + + // Set the hardware cursor + current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + if(page==current) + { + // Get the dimensions + nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); + nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; + + xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; + + // Calculate the address knowing nbcols nbrows and page num + address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols; + + // CRTC regs 0x0e and 0x0f + crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); + outb(crtc_addr,0x0e); + outb(crtc_addr+1,(address&0xff00)>>8); + outb(crtc_addr,0x0f); + outb(crtc_addr+1,address&0x00ff); + } +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_set_active_page(uint8_t page) +{ + uint16_t cursor,dummy,crtc_addr; + uint16_t nbcols,nbrows,address; + uint8_t mode,line; + + if(page>7)return; + + // Get the mode + mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); + line=find_vga_entry(mode); + if(line==0xFF)return; + + // Get pos curs pos for the right page + vga_get_cursor_pos(page,&dummy,&cursor); + + if(vga_modes[line].class==TEXT) + { + // Get the dimensions + nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); + nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; + + // Calculate the address knowing nbcols nbrows and page num + address=SCREEN_MEM_START(nbcols,nbrows,page); + write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address); + + // Start address + address=SCREEN_IO_START(nbcols,nbrows,page); + } + else + { + address = page * video_param_table[line_to_vpti[line]].slength; + } + + // CRTC regs 0x0c and 0x0d + crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); + outb(crtc_addr,0x0c); + outb(crtc_addr+1,(address&0xff00)>>8); + outb(crtc_addr,0x0d); + outb(crtc_addr+1,address&0x00ff); + + // And change the BIOS page + write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page); + +#ifdef VGA_DEBUG + printf("Set active page %02x address %04x\n",page,address); +#endif + + // Display the cursor, now the page is active + biosfn_set_cursor_pos(page,cursor); +} + +/// Recursive BIOS invocation, uses vector 6Dh +extern void vga_font_set(uint8_t function, uint8_t data); +#pragma aux vga_font_set = \ + "mov ah, 11h" \ + "int 6Dh" \ + parm [al] [bl]; + +// ============================================================================================ +// +// BIOS functions +// +// ============================================================================================ + +/* CGA-compatible MSR (0x3D8) register values for first modes 0-7. */ +uint8_t cga_msr[8] = { + 0x2C, 0x28, 0x2D, 0x29, 0x2A, 0x2E, 0x1E, 0x29 +}; + +/* Convert index in vga_modes[] to index in video_param_table[] for 200-line (CGA) text modes. */ +static int8_t line_to_vpti_200[8] = { + 0x00, 0x01, 0x02, 0x03, -1, -1, -1, 0x07 +}; + +/* Same for 350-line (EGA) text modes. */ +static int8_t line_to_vpti_350[8] = { + 0x13, 0x14, 0x15, 0x16, -1, -1, -1, 0x07 +}; + +/* Same for 400-line (VGA) text modes. */ +static int8_t line_to_vpti_400[8] = { + 0x17, 0x17, 0x18, 0x18, -1, -1, -1, 0x19 +}; + +int find_vpti(uint8_t line) +{ + int idx; + uint8_t mctl; + + if (vga_modes[line].class == TEXT) { + mctl = read_byte(BIOSMEM_SEG, BIOSMEM_MODESET_CTL); + if (mctl & 0x10) + idx = line_to_vpti_400[line]; + else if (mctl & 0x80) + idx = line_to_vpti_200[line]; + else + idx = line_to_vpti_350[line]; + } else + idx = line_to_vpti[line]; + + return idx; +} + +static void biosfn_load_text_user_pat(uint8_t AL, uint16_t ES, uint16_t BP, uint16_t CX, uint16_t DX, uint8_t BL, uint8_t BH); +static void load_text_patch(uint16_t ES, uint16_t BP, uint8_t BL, uint8_t BH); + +void biosfn_set_video_mode(uint8_t mode) +{// mode: Bit 7 is 1 if no clear screen + + // Should we clear the screen ? + uint8_t noclearmem=mode&0x80; + uint8_t line,mmask,vpti; + uint8_t modeset_ctl; + uint8_t *palette; + uint16_t i; + uint16_t crtc_addr; + void __far * __far *save_area; + VideoParamTableEntry __far *vpt; + +#ifdef VBE + if (vbe_has_vbe_display()) { + // Force controller into VGA mode + outb(VGAREG_SEQU_ADDRESS,7); + outb(VGAREG_SEQU_DATA,0x00); + } +#endif // def VBE + + // The real mode + mode=mode&0x7f; + + // Display switching is not supported; mono monitors aren't really either, + // but requests to set mode 7 are honored. + + // find the entry in the video modes + line=find_vga_entry(mode); + +#ifdef VGA_DEBUG + printf("mode search %02x found line %02x\n",mode,line); +#endif + + if(line==0xFF) + return; + + // Read the save area pointer. + save_area = (void __far *)read_dword(BIOSMEM_SEG, BIOSMEM_VS_POINTER); + + vpti = find_vpti(line); + vpt = save_area[0]; + vpt += vpti; + +#if 0 // These are unused, but perhaps they shouldn't be? + // Read the bios vga control + video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL); + + // Read the bios vga switches + vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES); +#endif + + // Read the bios mode set control + modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); + + // Then we know the number of lines +// FIXME + + // if palette loading (bit 3 of modeset ctl = 0) + if((modeset_ctl&0x08)==0) + {// Set the PEL mask + outb(VGAREG_PEL_MASK,vga_modes[line].pelmask); + + // Set the whole dac always, from 0 + outb(VGAREG_DAC_WRITE_ADDRESS,0x00); + + // From which palette + switch(vga_modes[line].dacmodel) + {case 0: + palette=&palette0[0]; + break; + case 1: + palette=&palette1[0]; + break; + case 2: + palette=&palette2[0]; + break; + case 3: + palette=&palette3[0]; + break; + } + // Override for CGA text modes. + if(vga_modes[line].class==TEXT) + { + if(vpt->cheight == 8) // CGA + palette=&palette1[0]; + } + // Always 256*3 values + for(i=0;i<0x0100;i++) + {if(i<=dac_regs[vga_modes[line].dacmodel]) + {outb(VGAREG_DAC_DATA,palette[(i*3)+0]); + outb(VGAREG_DAC_DATA,palette[(i*3)+1]); + outb(VGAREG_DAC_DATA,palette[(i*3)+2]); + } + else + {outb(VGAREG_DAC_DATA,0); + outb(VGAREG_DAC_DATA,0); + outb(VGAREG_DAC_DATA,0); + } + } + if((modeset_ctl&0x02)==0x02) + { + biosfn_perform_gray_scale_summing(0x00, 0x100); + } + } + + // Reset Attribute Ctl flip-flop + inb(VGAREG_ACTL_RESET); + + // Set Attribute Ctl + for(i=0;i<=0x13;i++) + {outb(VGAREG_ACTL_ADDRESS,i); + outb(VGAREG_ACTL_WRITE_DATA,vpt->actl_regs[i]); + } + outb(VGAREG_ACTL_ADDRESS,0x14); + outb(VGAREG_ACTL_WRITE_DATA,0x00); + + // Save palette into the save area if it exists. + if(save_area[1]) + { + uint8_t __far *dyn_save; + + dyn_save = save_area[1]; + for (i = 0; i < 16; ++i) + dyn_save[i] = vpt->actl_regs[i]; + dyn_save[16] = vpt->actl_regs[17]; + } + + // Set Sequencer Ctl + outb(VGAREG_SEQU_ADDRESS,0); + outb(VGAREG_SEQU_DATA,0x03); + for(i=1;i<=4;i++) + {outb(VGAREG_SEQU_ADDRESS,i); + outb(VGAREG_SEQU_DATA,vpt->sequ_regs[i - 1]); + } + + // Set Grafx Ctl + for(i=0;i<=8;i++) + {outb(VGAREG_GRDC_ADDRESS,i); + outb(VGAREG_GRDC_DATA,vpt->grdc_regs[i]); + } + + // Set CRTC address VGA or MDA + crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS; + + // Set the misc register; may change CRTC base! + outb(VGAREG_WRITE_MISC_OUTPUT,vpt->miscreg); + + // Disable CRTC write protection + outw(crtc_addr,0x0011); + // Set CRTC regs + for(i=0;i<=0x18;i++) + {outb(crtc_addr,i); + outb(crtc_addr+1,vpt->crtc_regs[i]); + } + + // Enable video + outb(VGAREG_ACTL_ADDRESS,0x20); + inb(crtc_addr + VGAREG_ACTL_RESET - VGAREG_VGA_CRTC_ADDRESS); + + if(noclearmem==0x00) + { + if(vga_modes[line].class==TEXT) + { + memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k + } + else + { + if(mode<0x0d) + { + memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k + } + else + { + outb( VGAREG_SEQU_ADDRESS, 0x02 ); + mmask = inb( VGAREG_SEQU_DATA ); + outb( VGAREG_SEQU_DATA, 0x0f ); // all planes + memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k + outb( VGAREG_SEQU_DATA, mmask ); + } + } + } + + // Set the BIOS mem + write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode); + write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,vpt->twidth); + write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vpt->slength); + write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr); + write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,vpt->theightm1); + write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,vpt->cheight); + write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem)); + write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9); + + // FIXME We nearly have the good tables. to be reworked + write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now + + if (mode <= 7) + { + write_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_MSR, cga_msr[mode]); /* Like CGA reg. 0x3D8 */ + write_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_PAL, mode == 6 ? 0x3F : 0x30); /* Like CGA reg. 0x3D9*/ + } + + // Set cursor shape + if(vga_modes[line].class==TEXT) + { + biosfn_set_cursor_shape(0x06,0x07); + } + + /// @todo Could be optimized to a memset since only BDA needs updating. + // Set cursor pos for page 0..7 + for(i=0;i<8;i++) + biosfn_set_cursor_pos(i,0x0000); + + // Set active page 0 + biosfn_set_active_page(0x00); + + // Write the fonts in memory + if(vga_modes[line].class==TEXT) + { + cso_txt __far *ovr = save_area[2]; + + switch (vpt->cheight) { + case 8: + biosfn_load_text_user_pat(0, 0xC000, (uint16_t)vgafont8, 256, 0, 0, vpt->cheight); + break; + case 14: + biosfn_load_text_user_pat(0, 0xC000, (uint16_t)vgafont14, 256, 0, 0, vpt->cheight); + if (mode == 7) /* 350-line EGA modes are 640 wide, only mono EGA mode is 720 wide. */ + load_text_patch(0xC000, (uint16_t)vgafont14alt, 0, 14); + break; + default: + biosfn_load_text_user_pat(0, 0xC000, (uint16_t)vgafont16, 256, 0, 0, vpt->cheight); + load_text_patch(0xC000, (uint16_t)vgafont16alt, 0, 16); + } + if (ovr) + { +#ifdef VGA_DEBUG + printf("Charmap override found, font at %04x:%04x\n", ovr->font_seg, ovr->font_ofs); +#endif + i = 0; + // Does the override support current mode? + while (ovr->modes[i] != 0xff) + { + if (ovr->modes[i] == mode) + break; + ++i; + } + // If there is a valid font override, apply it. + if (ovr->modes[i] == mode) + { +#ifdef VGA_DEBUG + printf("Loading override, %04x chars, height %02x\n", ovr->char_num, ovr->c_height); +#endif + biosfn_load_text_user_pat(0x10, ovr->font_seg, ovr->font_ofs, ovr->char_num, + ovr->char_1st, ovr->cgen_bank, ovr->c_height); + } + } + vga_font_set(0x03, 0); /* Select font page mode 0. */ + } + + // Set the ints 0x1F and 0x43 + set_int_vector(0x1f, vgafont8+128*8); + + switch(vpt->cheight) + {case 8: + set_int_vector(0x43, vgafont8); + break; + case 14: + set_int_vector(0x43, vgafont14); + break; + case 16: + set_int_vector(0x43, vgafont16); + break; + } +} + +// -------------------------------------------------------------------------------------------- +static void vgamem_copy_pl4(uint8_t xstart, uint8_t ysrc, uint8_t ydest, + uint8_t cols, uint8_t nbcols, uint8_t cheight) +{ + uint16_t src,dest; + uint8_t i; + + src=ysrc*cheight*nbcols+xstart; + dest=ydest*cheight*nbcols+xstart; + outw(VGAREG_GRDC_ADDRESS, 0x0105); + for(i=0;i>1)+xstart; + dest=((ydest*cheight*nbcols)>>1)+xstart; + for(i=0;i>1)+xstart; + for(i=0;irlr)return; + if(cul>clr)return; + + // Get the mode + mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); + line=find_vga_entry(mode); + if(line==0xFF)return; + + // Get the dimensions + nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; + nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); + + // Get the current page + if(page==0xFF) + page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + + if(rlr>=nbrows)rlr=nbrows-1; + if(clr>=nbcols)clr=nbcols-1; + if(nblines>nbrows)nblines=0; + cols=clr-cul+1; + + if(vga_modes[line].class==TEXT) + { + // Compute the address + address=SCREEN_MEM_START(nbcols,nbrows,page); +#ifdef VGA_DEBUG + printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page); +#endif + + if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) + { + memsetw(vga_modes[line].sstart,address,(uint16_t)attr*0x100+' ',nbrows*nbcols); + } + else + {// if Scroll up + if(dir==SCROLL_UP) + {for(i=rul;i<=rlr;i++) + { + if((i+nblines>rlr)||(nblines==0)) + memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(uint16_t)attr*0x100+' ',cols); + else + memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols); + } + } + else + {for(i=rlr;i>=rul;i--) + { + if((irlr) break; + } + } + } + } + else + { + cheight=video_param_table[line_to_vpti[line]].cheight; + switch(vga_modes[line].memmodel) + { + case PLANAR4: + case PLANAR1: + if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) + { + outw(VGAREG_GRDC_ADDRESS, 0x0205); + memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight); + outw(VGAREG_GRDC_ADDRESS, 0x0005); + } + else + {// if Scroll up + if(dir==SCROLL_UP) + {for(i=rul;i<=rlr;i++) + { + if((i+nblines>rlr)||(nblines==0)) + vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr); + else + vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight); + } + } + else + {for(i=rlr;i>=rul;i--) + { + if((irlr) break; + } + } + } + break; + case CGA: + bpp=vga_modes[line].pixbits; + if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) + { + memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp); + } + else + { + if(bpp==2) + { + cul<<=1; + cols<<=1; + nbcols<<=1; + } + // if Scroll up + if(dir==SCROLL_UP) + {for(i=rul;i<=rlr;i++) + { + if((i+nblines>rlr)||(nblines==0)) + vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr); + else + vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight); + } + } + else + {for(i=rlr;i>=rul;i--) + { + if((irlr) break; + } + } + } + break; + case LINEAR8: + if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) + { + memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*8); + } + else + { + // if Scroll up + if(dir==SCROLL_UP) + {for(i=rul;i<=rlr;i++) + { + if((i+nblines>rlr)||(nblines==0)) + vgamem_fill_linear(cul,i,cols,nbcols,cheight,attr); + else + vgamem_copy_linear(cul,i+nblines,i,cols,nbcols,cheight); + } + } + else + {for(i=rlr;i>=rul;i--) + { + if((irlr) break; + } + } + } + break; +#ifdef VGA_DEBUG + default: + printf("Scroll in graphics mode "); + unimplemented(); +#endif + } + } +} + +// -------------------------------------------------------------------------------------------- +static void write_gfx_char_pl4(uint8_t car, uint8_t attr, uint8_t xcurs, + uint8_t ycurs, uint8_t nbcols, uint8_t cheight, uint8_t page) +{ + uint8_t i,j,mask; + uint8_t __far *fdata; + uint16_t addr,dest,src; + + fdata = (void __far *)read_dword(0x00, 0x43 * 4); + + addr=xcurs+ycurs*cheight*nbcols; + addr+=read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page; + src = car * cheight; + outw(VGAREG_SEQU_ADDRESS, 0x0f02); + outw(VGAREG_GRDC_ADDRESS, 0x0205); + if(attr&0x80) + { + outw(VGAREG_GRDC_ADDRESS, 0x1803); + } + else + { + outw(VGAREG_GRDC_ADDRESS, 0x0003); + } + for(i=0;i>j; + outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); + readx_byte(0xa000,dest); + if(fdata[src+i]&mask) + { + write_byte(0xa000,dest,attr&0x0f); + } + else + { + write_byte(0xa000,dest,0x00); + } + } + } + outw(VGAREG_GRDC_ADDRESS, 0xff08); + outw(VGAREG_GRDC_ADDRESS, 0x0005); + outw(VGAREG_GRDC_ADDRESS, 0x0003); +} + +// -------------------------------------------------------------------------------------------- +static void write_gfx_char_cga(uint8_t car, uint8_t attr, uint8_t xcurs, + uint8_t ycurs, uint8_t nbcols, uint8_t bpp) +{ + uint8_t i,j,mask,data; + uint8_t *fdata; + uint16_t addr,dest,src; + + fdata = &vgafont8; + addr=(xcurs*bpp)+ycurs*320; + src = car * 8; + for(i=0;i<8;i++) + { + dest=addr+(i>>1)*80; + if (i & 1) dest += 0x2000; + mask = 0x80; + /* NB: In 1bpp modes, the attribute is ignored, only the XOR flag has meaning. */ + if (bpp == 1) + { + if (attr & 0x80) + { + data = read_byte(0xb800,dest); + data ^= fdata[src+i]; + } + else + { + data = fdata[src+i]; + } + write_byte(0xb800,dest,data); + } + else + { + while (mask > 0) + { + if (attr & 0x80) + { + data = read_byte(0xb800,dest); + } + else + { + data = 0x00; + } + for(j=0;j<4;j++) + { + if (fdata[src+i] & mask) + { + if (attr & 0x80) + { + data ^= (attr & 0x03) << ((3-j)*2); + } + else + { + data |= (attr & 0x03) << ((3-j)*2); + } + } + mask >>= 1; + } + write_byte(0xb800,dest,data); + dest += 1; + } + } + } +} + +// -------------------------------------------------------------------------------------------- +static void write_gfx_char_lin(uint8_t car, uint8_t attr, uint8_t xcurs, + uint8_t ycurs, uint8_t nbcols) +{ + uint8_t i,j,mask,data; + uint8_t *fdata; + uint16_t addr,dest,src; + + fdata = &vgafont8; + addr=xcurs*8+ycurs*nbcols*64; + src = car * 8; + for(i=0;i<8;i++) + { + dest=addr+i*nbcols*8; + mask = 0x80; + for(j=0;j<8;j++) + { + data = 0x00; + if (fdata[src+i] & mask) + { + data = attr; + } + write_byte(0xa000,dest+j,data); + mask >>= 1; + } + } +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_write_char_attr(uint8_t car, uint8_t page, uint8_t attr, uint16_t count) +{ + uint8_t cheight,xcurs,ycurs,mode,line,bpp; + uint16_t nbcols,nbrows,address; + uint16_t cursor,dummy; + + // Get the mode + mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); + line=find_vga_entry(mode); + if(line==0xFF)return; + + // Get the cursor pos for the page + vga_get_cursor_pos(page,&dummy,&cursor); + xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; + + // Get the dimensions + nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; + nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); + + if(vga_modes[line].class==TEXT) + { + // Compute the address + address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; + + dummy=((uint16_t)attr<<8)+car; + memsetw(vga_modes[line].sstart,address,dummy,count); + } + else + { + // FIXME gfx mode not complete + cheight=video_param_table[line_to_vpti[line]].cheight; + bpp=vga_modes[line].pixbits; + while(count-->0) + { + switch(vga_modes[line].memmodel) + { + case PLANAR1: + attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */ + case PLANAR4: + write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page); + break; + case CGA: + write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); + break; + case LINEAR8: + write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); + break; +#ifdef VGA_DEBUG + default: + unimplemented(); +#endif + } + xcurs++; + } + } +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_write_char_only(uint8_t car, uint8_t page, uint8_t attr, uint16_t count) +{ + uint8_t cheight,xcurs,ycurs,mode,line,bpp; + uint16_t nbcols,nbrows,address; + uint16_t cursor,dummy; + + // Get the mode + mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); + line=find_vga_entry(mode); + if(line==0xFF)return; + + // Get the cursor pos for the page + vga_get_cursor_pos(page,&dummy,&cursor); + xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; + + // Get the dimensions + nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; + nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); + + if(vga_modes[line].class==TEXT) + { + // Compute the address + address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; + + while(count-->0) + {write_byte(vga_modes[line].sstart,address,car); + address+=2; + } + } + else + { + // FIXME gfx mode not complete + cheight=video_param_table[line_to_vpti[line]].cheight; + bpp=vga_modes[line].pixbits; + while(count-->0) + { + switch(vga_modes[line].memmodel) + { + case PLANAR1: + attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */ + case PLANAR4: + write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page); + break; + case CGA: + write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); + break; + case LINEAR8: + write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); + break; +#ifdef VGA_DEBUG + default: + unimplemented(); +#endif + } + xcurs++; + } + } +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_write_pixel(uint8_t BH, uint8_t AL, uint16_t CX, uint16_t DX) +{ + uint8_t mode,line,mask,attr,data; + uint16_t addr; + + // Get the mode + mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); + line=find_vga_entry(mode); + if(line==0xFF)return; + if(vga_modes[line].class==TEXT)return; + + switch(vga_modes[line].memmodel) + { + case PLANAR4: + case PLANAR1: + addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); + addr += read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE) * BH; + mask = 0x80 >> (CX & 0x07); + outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); + outw(VGAREG_GRDC_ADDRESS, 0x0205); + data = readx_byte(0xa000,addr); + if (AL & 0x80) + { + outw(VGAREG_GRDC_ADDRESS, 0x1803); + } + write_byte(0xa000,addr,AL); + outw(VGAREG_GRDC_ADDRESS, 0xff08); + outw(VGAREG_GRDC_ADDRESS, 0x0005); + outw(VGAREG_GRDC_ADDRESS, 0x0003); + break; + case CGA: + if(vga_modes[line].pixbits==2) + { + addr=(CX>>2)+(DX>>1)*80; + } + else + { + addr=(CX>>3)+(DX>>1)*80; + } + if (DX & 1) addr += 0x2000; + data = read_byte(0xb800,addr); + if(vga_modes[line].pixbits==2) + { + attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2); + mask = 0x03 << ((3 - (CX & 0x03)) * 2); + } + else + { + attr = (AL & 0x01) << (7 - (CX & 0x07)); + mask = 0x01 << (7 - (CX & 0x07)); + } + if (AL & 0x80) + { + data ^= attr; + } + else + { + data &= ~mask; + data |= attr; + } + write_byte(0xb800,addr,data); + break; + case LINEAR8: + addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); + write_byte(0xa000,addr,AL); + break; +#ifdef VGA_DEBUG + default: + unimplemented(); +#endif + } +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_write_teletype(uint8_t car, uint8_t page, uint8_t attr, uint8_t flag) +{// flag = WITH_ATTR / NO_ATTR + + uint8_t cheight,xcurs,ycurs,mode,line,bpp; + uint16_t nbcols,nbrows,address; + uint16_t cursor,dummy; + + // special case if page is 0xff, use current page + if(page==0xff) + page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + + // Get the mode + mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); + line=find_vga_entry(mode); + if(line==0xFF)return; + + // Get the cursor pos for the page + vga_get_cursor_pos(page,&dummy,&cursor); + xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; + + // Get the dimensions + nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; + nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); + + switch(car) + { + case '\a': // ASCII 0x07, BEL + //FIXME should beep + break; + + case '\b': // ASCII 0x08, BS + if(xcurs>0)xcurs--; + break; + + case '\n': // ASCII 0x0A, LF + ycurs++; + break; + + case '\r': // ASCII 0x0D, CR + xcurs=0; + break; + + default: + + if(vga_modes[line].class==TEXT) + { + // Compute the address + address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; + + // Write the char + write_byte(vga_modes[line].sstart,address,car); + + if(flag==WITH_ATTR) + write_byte(vga_modes[line].sstart,address+1,attr); + } + else + { + // FIXME gfx mode not complete + cheight=video_param_table[line_to_vpti[line]].cheight; + bpp=vga_modes[line].pixbits; + switch(vga_modes[line].memmodel) + { + case PLANAR1: + attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */ + case PLANAR4: + write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page); + break; + case CGA: + write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); + break; + case LINEAR8: + write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); + break; +#ifdef VGA_DEBUG + default: + unimplemented(); +#endif + } + } + xcurs++; + // Do we need to wrap ? + if(xcurs==nbcols) + {xcurs=0; + ycurs++; + } + } + + // Do we need to scroll ? + if(ycurs==nbrows) + { + if(vga_modes[line].class==TEXT) + { + address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2; + attr=read_byte(vga_modes[line].sstart,address+1); + biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP); + } + else + { + biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP); + } + ycurs-=1; + } + + // Set the cursor for the page + cursor=ycurs; cursor<<=8; cursor+=xcurs; + biosfn_set_cursor_pos(page,cursor); +} + +// -------------------------------------------------------------------------------------------- +static void get_font_access(void) +{ + outw(VGAREG_GRDC_ADDRESS, 0x0005); + outb(VGAREG_GRDC_ADDRESS, 0x06); + outw(VGAREG_GRDC_ADDRESS, (((0x04 | (inb(VGAREG_GRDC_DATA) & 0x01)) << 8) | 0x06)); + outw(VGAREG_SEQU_ADDRESS, 0x0402); + outw(VGAREG_SEQU_ADDRESS, 0x0604); +} + +static void release_font_access(void) +{ + outw(VGAREG_GRDC_ADDRESS, (((0x0a | ((inb(VGAREG_READ_MISC_OUTPUT) & 0x01) << 2)) << 8) | 0x06)); + outw(VGAREG_GRDC_ADDRESS, 0x1005); + outw(VGAREG_SEQU_ADDRESS, 0x0302); + outw(VGAREG_SEQU_ADDRESS, 0x0204); +} + +static void set_scan_lines(uint8_t lines) +{ + uint16_t crtc_addr,cols,vde; + uint8_t crtc_r9,ovl,rows; + + crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); + outb(crtc_addr, 0x09); + crtc_r9 = inb(crtc_addr+1); + crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1); + outb(crtc_addr+1, crtc_r9); + if(lines==8) + { + biosfn_set_cursor_shape(0x06,0x07); + } + else + { + biosfn_set_cursor_shape(lines-4,lines-3); + } + write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines); + outb(crtc_addr, 0x12); + vde = inb(crtc_addr+1); + outb(crtc_addr, 0x07); + ovl = inb(crtc_addr+1); + vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1); + rows = vde / lines; + write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1); + cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); + write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2); +} + +static void biosfn_set_font_block(uint8_t BL) +{ + outw(VGAREG_SEQU_ADDRESS, 0x0100); + outw(VGAREG_SEQU_ADDRESS, 0x0003 | (BL << 8)); + outw(VGAREG_SEQU_ADDRESS, 0x0300); +} + +static void load_text_patch(uint16_t ES, uint16_t BP, uint8_t BL, uint8_t BH) +{ + uint16_t blockaddr, dest, src; + uint8_t __far *pat; + + get_font_access(); + + blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); + pat = ES :> (uint8_t *)BP; + src = BP + 1; + while (*pat) { + dest = blockaddr + *pat * 32; + memcpyb(0xA000, dest, ES, src, BH); + src += BH + 1; + pat += BH + 1; + } + + release_font_access(); +} + +static void biosfn_load_text_user_pat(uint8_t AL, uint16_t ES, uint16_t BP, uint16_t CX, + uint16_t DX, uint8_t BL, uint8_t BH) +{ + uint16_t blockaddr,dest,i,src; + + get_font_access(); + blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); + for(i=0;i=0x10) + { + set_scan_lines(BH); + } +} + +static void biosfn_load_gfx_8_8_chars(uint16_t ES, uint16_t BP) +{ + set_int_vector(0x1F, ES:>BP); +} + +static void set_gfx_font(void _far *font, uint16_t cheight, uint8_t row_code, uint8_t rows) +{ + static uint8_t row_tbl[] = { 0, 14, 25, 43 }; + + set_int_vector(0x43, font); + if (row_code) { + if (row_code > 3) + row_code = 2; /* Default to 25 rows. */ + rows = row_tbl[row_code]; + } + /* Else 'rows' used as is. */ + + write_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT, cheight); + write_word(BIOSMEM_SEG, BIOSMEM_NB_ROWS, rows - 1); +} + +static void biosfn_load_gfx_user_chars(uint16_t ES, uint16_t BP, uint16_t CX, + uint8_t BL, uint8_t DL) +{ + set_gfx_font(ES:>BP, CX, BL, DL); +} + +/* Some references (RBIL) suggest that only BL is used; that is wrong, + * all of these subfunctions will use DL if BL is zero. + */ +static void biosfn_load_gfx_8_14_chars(uint8_t BL, uint8_t DL) +{ + set_gfx_font(vgafont14, 14, BL, DL); +} +static void biosfn_load_gfx_8_8_dd_chars(uint8_t BL, uint8_t DL) +{ + set_gfx_font(vgafont8, 8, BL, DL); +} +static void biosfn_load_gfx_8_16_chars(uint8_t BL, uint8_t DL) +{ + set_gfx_font(vgafont16, 16, BL, DL); +} +// -------------------------------------------------------------------------------------------- +static void biosfn_alternate_prtsc(void) +{ +#ifdef VGA_DEBUG + unimplemented(); +#endif +} +// -------------------------------------------------------------------------------------------- +static void biosfn_set_txt_lines(uint8_t AL) +{ + uint8_t mctl; + + /* Read byte at 40:89. */ + mctl = read_byte(BIOSMEM_SEG, BIOSMEM_MODESET_CTL); + mctl = mctl & 0x6F; /* Clear 400/200 line flags. */ + + switch (AL) /* AL was already validated to be in 0-2 range. */ + { + case 0: /* 200 lines. */ + mctl |= 0x80; + break; + case 2: /* 400 lines. */ + mctl |= 0x10; + break; + } + write_byte(BIOSMEM_SEG, BIOSMEM_MODESET_CTL, mctl); +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_switch_video_interface (AL,ES,DX) uint8_t AL;uint16_t ES;uint16_t DX; +{ +#ifdef VGA_DEBUG + unimplemented(); +#endif +} +static void biosfn_enable_video_refresh_control(uint8_t AL) +{ +#ifdef VGA_DEBUG + unimplemented(); +#endif +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_write_string(uint8_t flag, uint8_t page, uint8_t attr, uint16_t count, + uint8_t row, uint8_t col, uint16_t seg, uint16_t offset) +{ + uint16_t newcurs,oldcurs,dummy; + uint8_t car; + + // Read curs info for the page + vga_get_cursor_pos(page,&dummy,&oldcurs); + + // if row=0xff special case : use current cursor position + if(row==0xff) + {col=oldcurs&0x00ff; + row=(oldcurs&0xff00)>>8; + } + + newcurs=row; newcurs<<=8; newcurs+=col; + biosfn_set_cursor_pos(page,newcurs); + + while(count--!=0) + { + car=read_byte(seg,offset++); + if((flag&0x02)!=0) + attr=read_byte(seg,offset++); + + biosfn_write_teletype(car,page,attr,WITH_ATTR); + } + + // Set back curs pos + if((flag&0x01)==0) + biosfn_set_cursor_pos(page,oldcurs); +} + +// -------------------------------------------------------------------------------------------- +static void biosfn_read_state_info(uint16_t BX, uint16_t ES, uint16_t DI) +{ + uint16_t pg_sz; + uint16_t scans; + uint8_t mode; + uint8_t mctl; + uint8_t temp; + + mode = read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); + pg_sz = read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); + // Address of static functionality table + write_dword(ES,DI+0x00, (uint32_t)(void __far *)static_functionality); + + // A lot is a straight copy from the BDA. Note that the number + // of character rows in the BDA is zero-based but one-based in + // the dynamic state area + memcpyb(ES,DI+0x04,BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,30); + write_byte(ES,DI+0x22,read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1); + memcpyb(ES,DI+0x23,BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,2); + + write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX)); + write_byte(ES,DI+0x26,0); // Alternate display code + write_word(ES,DI+0x27,16); // Number of colors + write_byte(ES,DI+0x29,8); // Number of pages + write_byte(ES,DI+0x2a,2); // Vertical resolution specifier + write_byte(ES,DI+0x2b,0); // Primary font block + write_byte(ES,DI+0x2c,0); // Secondary font block + write_byte(ES,DI+0x2d,0x21); + write_byte(ES,DI+0x31,3); // 256K video RAM + write_byte(ES,DI+0x32,0); // Save pointer state information + + mctl = read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); + + /* Extract and write the vertical resolution specifier bits. */ + scans = ((mctl & 0x80) >> 6) | ((mctl & 0x10) >> 4); + switch (scans) { + case 0: temp = 1; break; /* 350 lines */ + case 1: temp = 2; break; /* 400 lines */ + default: + case 2: temp = 0; break; /* 200 lines */ + } + write_byte(ES,DI+0x2a,temp); + + /* Patch up the data for graphics modes. */ + if (mode >= 0x0E && mode <= 0x12) { + if (pg_sz) + write_byte(ES,DI+0x29,16384/(pg_sz >> 2)); + } else if (mode == 0x13) { + write_byte(ES,DI+0x29,1); /* Just one page due to chaining */ + write_word(ES,DI+0x27,256); /* But 256!! colors!!! */ + } else if (mode >= 4 && mode <= 6) { + /* CGA modes. */ + if (pg_sz) + write_byte(ES,DI+0x29,16384/pg_sz); + write_word(ES,DI+0x27,4); + } + if (mode == 6 || mode == 0x11) + write_word(ES,DI+0x27,2); /* 2-color modes. */ + + if ((mode >= 4) && (mode != 7)) { + write_byte(ES,DI+0x2d,0x01); + scans = (read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1) * read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); + switch (scans) { + case 200: temp = 0; break; + case 350: temp = 1; break; + case 400: temp = 2; break; + default: + case 480: temp = 3; break; + } + write_byte(ES,DI+0x2a,temp); + } + + memsetb(ES,DI+0x33,0,13); +} + +// -------------------------------------------------------------------------------------------- +uint16_t biosfn_read_video_state_size2(uint16_t state) +{ + uint16_t size; + + size = 0; + if (state & 1) + size += 0x46; + + if (state & 2) + size += (5 + 8 + 5) * 2 + 6; + + if (state & 4) + size += 3 + 256 * 3 + 1; + + return size; +} + +static void vga_get_video_state_size(uint16_t state, uint16_t STACK_BASED *size) +{ + /* The size is the number of 64-byte blocks required to save the state. */ + *size = (biosfn_read_video_state_size2(state) + 63) / 64; +} + +uint16_t biosfn_save_video_state(uint16_t CX, uint16_t ES, uint16_t BX) +{ + uint16_t i, crtc_addr, ar_index; + + crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS); + if (CX & 1) { + write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++; + write_byte(ES, BX, inb(crtc_addr)); BX++; + write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++; + inb(VGAREG_ACTL_RESET); + ar_index = inb(VGAREG_ACTL_ADDRESS); + write_byte(ES, BX, ar_index); BX++; + write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++; + + for(i=1;i<=4;i++){ + outb(VGAREG_SEQU_ADDRESS, i); + write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++; + } + outb(VGAREG_SEQU_ADDRESS, 0); + write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++; + + for(i=0;i<=0x18;i++) { + outb(crtc_addr,i); + write_byte(ES, BX, inb(crtc_addr+1)); BX++; + } + + for(i=0;i<=0x13;i++) { + inb(VGAREG_ACTL_RESET); /* Reads do not toggle flip-flop! */ + outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20)); + write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++; + } + inb(VGAREG_ACTL_RESET); + + for(i=0;i<=8;i++) { + outb(VGAREG_GRDC_ADDRESS,i); + write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++; + } + + write_word(ES, BX, crtc_addr); BX+= 2; + + /* XXX: read plane latches */ + write_byte(ES, BX, 0); BX++; + write_byte(ES, BX, 0); BX++; + write_byte(ES, BX, 0); BX++; + write_byte(ES, BX, 0); BX++; + } + if (CX & 2) { + write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++; + write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2; + write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2; + write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2; + write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++; + write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2; + write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++; + write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++; + write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++; + write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2; + for(i=0;i<8;i++) { + write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i)); + BX += 2; + } + write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2; + write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++; + /* current font */ + write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2; + write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2; + write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2; + write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2; + } + if (CX & 4) { + /* XXX: check this */ + write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */ + write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */ + write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++; + // Set the whole dac always, from 0 + outb(VGAREG_DAC_WRITE_ADDRESS,0x00); + for(i=0;i<256*3;i++) { + write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++; + } + write_byte(ES, BX, 0); BX++; /* color select register */ + } + return BX; +} + +uint16_t biosfn_restore_video_state(uint16_t CX, uint16_t ES, uint16_t BX) +{ + uint16_t i, crtc_addr, v, addr1, ar_index; + + if (CX & 1) { + // Reset Attribute Ctl flip-flop + inb(VGAREG_ACTL_RESET); + + crtc_addr = read_word(ES, BX + 0x40); + addr1 = BX; + BX += 5; + + for(i=1;i<=4;i++){ + outb(VGAREG_SEQU_ADDRESS, i); + outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++; + } + outb(VGAREG_SEQU_ADDRESS, 0); + outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++; + + // select crtc base address + v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01; + if (crtc_addr == 0x3d4) + v |= 0x01; + outb(VGAREG_WRITE_MISC_OUTPUT, v); + + // Disable CRTC write protection + outw(crtc_addr,0x0011); + // Set CRTC regs + for(i=0;i<=0x18;i++) { + if (i != 0x11) { + outb(crtc_addr,i); + outb(crtc_addr+1, read_byte(ES, BX)); + } + BX++; + } + // enable write protection if needed + outb(crtc_addr, 0x11); + outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11)); + + // Set Attribute Ctl + ar_index = read_byte(ES, addr1 + 0x03); + inb(VGAREG_ACTL_RESET); + for(i=0;i<=0x13;i++) { + outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20)); + outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++; + } + outb(VGAREG_ACTL_ADDRESS, ar_index); + inb(VGAREG_ACTL_RESET); + + for(i=0;i<=8;i++) { + outb(VGAREG_GRDC_ADDRESS,i); + outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++; + } + BX += 2; /* crtc_addr */ + BX += 4; /* plane latches */ + + outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++; + outb(crtc_addr, read_byte(ES, addr1)); addr1++; + outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++; + addr1++; + outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++; + } + if (CX & 2) { + write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++; + write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2; + write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2; + write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2; + write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++; + write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2; + write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++; + write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++; + write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++; + write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2; + for(i=0;i<8;i++) { + write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX)); + BX += 2; + } + write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2; + write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++; + /* current font */ + write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2; + write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2; + write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2; + write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2; + } + if (CX & 4) { + BX++; + v = read_byte(ES, BX); BX++; + outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++; + // Set the whole dac always, from 0 + outb(VGAREG_DAC_WRITE_ADDRESS,0x00); + for(i=0;i<256*3;i++) { + outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++; + } + BX++; + outb(VGAREG_DAC_WRITE_ADDRESS, v); + } + return BX; +} + +// ============================================================================================ +// +// Video Utils +// +// ============================================================================================ + +// -------------------------------------------------------------------------------------------- +static uint8_t find_vga_entry(uint8_t mode) +{ + uint8_t i,line=0xFF; + for(i=0;i<=MODE_MAX;i++) + if(vga_modes[i].svgamode==mode) + {line=i; + break; + } + return line; +} + +/* =========================================================== */ +/* + * Misc Utils +*/ +/* =========================================================== */ + +/* This function is used for planar VGA memory reads to defeat the + * optimizer. We must read exactly one byte, otherwise the screen + * may be corrupted. + */ +uint8_t readx_byte(uint16_t seg, uint16_t offset) +{ + return( *(seg:>(uint8_t *)offset) ); +} + +#ifdef VGA_DEBUG +void __cdecl unimplemented() +{ + printf("--> Unimplemented\n"); +} + +void __cdecl unknown() +{ + printf("--> Unknown int10\n"); +} + +#undef VBE_PRINTF_PORT +#define VBE_PRINTF_PORT 0x504 + +// -------------------------------------------------------------------------------------------- +void __cdecl printf(char *s, ...) +{ + char c; + Boolean in_format; + unsigned format_width, i; + uint16_t arg, digit, nibble; + uint16_t STACK_BASED *arg_ptr; + + arg_ptr = (uint16_t STACK_BASED *)&s; + + in_format = 0; + format_width = 0; + + while (c = *s) { + if (c == '%') { + in_format = 1; + format_width = 0; + } else if (in_format) { + if ((c >= '0') && (c <= '9')) { + format_width = (format_width * 10) + (c - '0'); + } else if (c == 'x') { + arg_ptr++; // increment to next arg + arg = *arg_ptr; + if (format_width == 0) + format_width = 4; + i = 0; + digit = format_width - 1; + for (i = 0; i < format_width; i++) { + nibble = (arg >> (4 * digit)) & 0x000f; + if (nibble <= 9) + outb(VBE_PRINTF_PORT, nibble + '0'); + else + outb(VBE_PRINTF_PORT, (nibble - 10) + 'A'); + digit--; + } + in_format = 0; + } + //else if (c == 'd') { + // in_format = 0; + // } + } else { + outb(VBE_PRINTF_PORT, c); + } + ++s; + } +} +#endif + +/// @todo rearrange, call only from VBE module? +extern void vbe_biosfn_return_controller_information(uint16_t STACK_BASED *AX, uint16_t ES, uint16_t DI); +extern void vbe_biosfn_return_mode_information(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t ES, uint16_t DI); +extern void vbe_biosfn_set_mode(uint16_t STACK_BASED *AX, uint16_t BX, uint16_t ES, uint16_t DI); +extern void vbe_biosfn_save_restore_state(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t DX, uint16_t ES, uint16_t STACK_BASED *BX); +extern void vbe_biosfn_get_set_scanline_length(uint16_t STACK_BASED *AX, uint16_t STACK_BASED *BX, uint16_t STACK_BASED *CX, uint16_t STACK_BASED *DX); +extern void private_biosfn_custom_mode(uint16_t STACK_BASED *AX, uint16_t STACK_BASED *BX, uint16_t STACK_BASED *CX, uint16_t STACK_BASED *DX); + + +// -------------------------------------------------------------------------------------------- +/* + * int10 main dispatcher + */ +void __cdecl int10_func(uint16_t DI, uint16_t SI, uint16_t BP, uint16_t SP, uint16_t BX, + uint16_t DX, uint16_t CX, uint16_t AX, uint16_t DS, uint16_t ES, uint16_t FLAGS) +{ + + // BIOS functions + switch(GET_AH()) + { + case 0x00: + biosfn_set_video_mode(GET_AL()); + switch(GET_AL()&0x7F) + {case 6: + SET_AL(0x3F); + break; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 7: + SET_AL(0x30); + break; + default: + SET_AL(0x20); + } + break; + case 0x01: + biosfn_set_cursor_shape(GET_CH(),GET_CL()); + break; + case 0x02: + biosfn_set_cursor_pos(GET_BH(),DX); + break; + case 0x03: + vga_get_cursor_pos(GET_BH(), &CX, &DX); + break; + case 0x04: + // Read light pen pos (unimplemented) +#ifdef VGA_DEBUG + unimplemented(); +#endif + AX=0x00; + BX=0x00; + CX=0x00; + DX=0x00; + break; + case 0x05: + biosfn_set_active_page(GET_AL()); + break; + case 0x06: + biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP); + break; + case 0x07: + biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN); + break; + case 0x08: + vga_read_char_attr(GET_BH(), &AX); + break; + case 0x09: + biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX); + break; + case 0x0A: + biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX); + break; + case 0x0C: + biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX); + break; + case 0x0D: + vga_read_pixel(GET_BH(), CX, DX, &AX); + break; + case 0x0E: + // Ralf Brown Interrupt list is WRONG on bh(page) + // We do output only on the current page ! +#ifdef VGA_DEBUG + printf("write_teletype %02x\n", GET_AL()); +#endif + + biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR); + break; + case 0x10: + // All other functions of group AH=0x10 rewritten in assembler + biosfn_perform_gray_scale_summing(BX,CX); + break; + case 0x11: + switch(GET_AL()) + { + case 0x00: + case 0x10: + biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH()); + break; + case 0x01: + case 0x11: + biosfn_load_text_user_pat(GET_AL(), 0xC000, (uint16_t)vgafont14, 256, 0, GET_BL(), 14); + break; + case 0x02: + case 0x12: + biosfn_load_text_user_pat(GET_AL(), 0xC000, (uint16_t)vgafont8, 256, 0, GET_BL(), 8); + break; + case 0x03: + biosfn_set_font_block(GET_BL()); + break; + case 0x04: + case 0x14: + biosfn_load_text_user_pat(GET_AL(), 0xC000, (uint16_t)vgafont16, 256, 0, GET_BL(), 16); + break; + case 0x20: + biosfn_load_gfx_8_8_chars(ES,BP); + break; + case 0x21: + biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL()); + break; + case 0x22: + biosfn_load_gfx_8_14_chars(GET_BL(),GET_DL()); + break; + case 0x23: + biosfn_load_gfx_8_8_dd_chars(GET_BL(),GET_DL()); + break; + case 0x24: + biosfn_load_gfx_8_16_chars(GET_BL(),GET_DL()); + break; + case 0x30: + vga_get_font_info(GET_BH(), &ES, &BP, &CX, &DX); + break; +#ifdef VGA_DEBUG + default: + unknown(); +#endif + } + + break; + case 0x12: + switch(GET_BL()) + { + case 0x20: + biosfn_alternate_prtsc(); + break; + case 0x30: + if (GET_AL() <= 2) { + biosfn_set_txt_lines(GET_AL()); + SET_AL(0x12); + } + break; + case 0x34: /* CGA text cursor emulation control. */ + if (GET_AL() < 2) { + write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, + (read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & ~1) | GET_AL()); + SET_AL(0x12); + } + else + SET_AL(0); /* Invalid argument. */ + break; + case 0x35: + biosfn_switch_video_interface(GET_AL(),ES,DX); + SET_AL(0x12); + break; + case 0x36: + biosfn_enable_video_refresh_control(GET_AL()); + SET_AL(0x12); + break; +#ifdef VGA_DEBUG + default: + unknown(); +#endif + } + break; + case 0x13: + biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP); + break; + case 0x1B: + biosfn_read_state_info(BX,ES,DI); + SET_AL(0x1B); + break; + case 0x1C: + switch(GET_AL()) + { + case 0x00: + vga_get_video_state_size(CX,&BX); + break; + case 0x01: + biosfn_save_video_state(CX,ES,BX); + break; + case 0x02: + biosfn_restore_video_state(CX,ES,BX); + break; +#ifdef VGA_DEBUG + default: + unknown(); +#endif + } + SET_AL(0x1C); + break; + +#ifdef VBE + case 0x4f: + if (vbe_has_vbe_display()) { + switch(GET_AL()) + { + case 0x00: + vbe_biosfn_return_controller_information(&AX,ES,DI); + break; + case 0x01: + vbe_biosfn_return_mode_information(&AX,CX,ES,DI); + break; + case 0x02: + vbe_biosfn_set_mode(&AX,BX,ES,DI); + break; + case 0x04: + vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX); + break; + case 0x06: + vbe_biosfn_get_set_scanline_length(&AX, &BX, &CX, &DX); + break; + case 0x09: + //FIXME +#ifdef VGA_DEBUG + unimplemented(); +#endif + // function failed + AX=0x100; + break; + case 0x0A: + //FIXME +#ifdef VGA_DEBUG + unimplemented(); +#endif + // function failed + AX=0x100; + break; + default: +#ifdef VGA_DEBUG + unknown(); +#endif + // function failed + AX=0x100; + } + } + else { + // No VBE display + AX=0x0100; + } + break; + case 0x56: + if (vbe_has_vbe_display()) { + switch(GET_AL()) + { + case 0x42: + private_biosfn_custom_mode(&AX,&BX,&CX,&DX); + break; + default: + AX=0x0100; + break; + } + } else { + // No VBE display + AX=0x0100; + } + break; +#endif + +#ifdef VGA_DEBUG + default: + unknown(); +#endif + } +} + +#ifdef VBE +//#include "vbe.c" +#endif + +#ifdef CIRRUS +#include "clext.c" +#endif + +// -------------------------------------------------------------------------------------------- + diff --git a/src/VBox/Devices/Graphics/BIOS/vgabios.h b/src/VBox/Devices/Graphics/BIOS/vgabios.h new file mode 100644 index 00000000..1c545710 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vgabios.h @@ -0,0 +1,68 @@ + +#ifndef VBOX_INCLUDED_SRC_Graphics_BIOS_vgabios_h +#define VBOX_INCLUDED_SRC_Graphics_BIOS_vgabios_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* Types */ +//typedef unsigned char Bit8u; +//typedef unsigned short Bit16u; +//typedef unsigned long Bit32u; +typedef unsigned short Boolean; + +/* Defines */ + +#define SET_AL(val8) AX = ((AX & 0xff00) | (val8)) +#define SET_BL(val8) BX = ((BX & 0xff00) | (val8)) +#define SET_CL(val8) CX = ((CX & 0xff00) | (val8)) +#define SET_DL(val8) DX = ((DX & 0xff00) | (val8)) +#define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8)) +#define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8)) +#define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8)) +#define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8)) + +#define GET_AL() ( AX & 0x00ff ) +#define GET_BL() ( BX & 0x00ff ) +#define GET_CL() ( CX & 0x00ff ) +#define GET_DL() ( DX & 0x00ff ) +#define GET_AH() ( AX >> 8 ) +#define GET_BH() ( BX >> 8 ) +#define GET_CH() ( CX >> 8 ) +#define GET_DH() ( DX >> 8 ) + +#define SET_CF() FLAGS |= 0x0001 +#define CLEAR_CF() FLAGS &= 0xfffe +#define GET_CF() (FLAGS & 0x0001) + +#define SET_ZF() FLAGS |= 0x0040 +#define CLEAR_ZF() FLAGS &= 0xffbf +#define GET_ZF() (FLAGS & 0x0040) + +#define SCROLL_DOWN 0 +#define SCROLL_UP 1 +#define NO_ATTR 2 +#define WITH_ATTR 3 + +#define SCREEN_SIZE(x,y) (((x*y*2)|0x00ff)+1) +#define SCREEN_MEM_START(x,y,p) ((((x*y*2)|0x00ff)+1)*p) +#define SCREEN_IO_START(x,y,p) ((((x*y)|0x00ff)+1)*p) + +/* Macro for stack-based pointers. */ +#define STACK_BASED _based(_segname("_STACK")) + +/* Output. */ +extern void __cdecl printf(char *s, ...); + +/* VGA BIOS routines called by VBE. */ +extern void biosfn_set_video_mode(uint8_t mode); +extern uint16_t biosfn_read_video_state_size2(uint16_t state); +extern uint16_t biosfn_save_video_state(uint16_t CX, uint16_t ES, uint16_t BX); +extern uint16_t biosfn_restore_video_state(uint16_t CX, uint16_t ES, uint16_t BX); + +/* Allow stand-alone compilation. */ +#ifndef VBOX_VERSION_STRING +#include +#endif + +#endif /* !VBOX_INCLUDED_SRC_Graphics_BIOS_vgabios_h */ diff --git a/src/VBox/Devices/Graphics/BIOS/vgadefs.h b/src/VBox/Devices/Graphics/BIOS/vgadefs.h new file mode 100644 index 00000000..5ae13ea4 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vgadefs.h @@ -0,0 +1,78 @@ + +#ifndef VBOX_INCLUDED_SRC_Graphics_BIOS_vgadefs_h +#define VBOX_INCLUDED_SRC_Graphics_BIOS_vgadefs_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* + * + * BIOS Memory + * + */ +#define BIOSMEM_SEG 0x40 + +#define BIOSMEM_INITIAL_MODE 0x10 +#define BIOSMEM_CURRENT_MODE 0x49 +#define BIOSMEM_NB_COLS 0x4A +#define BIOSMEM_PAGE_SIZE 0x4C +#define BIOSMEM_CURRENT_START 0x4E +#define BIOSMEM_CURSOR_POS 0x50 +#define BIOSMEM_CURSOR_TYPE 0x60 +#define BIOSMEM_CURRENT_PAGE 0x62 +#define BIOSMEM_CRTC_ADDRESS 0x63 +#define BIOSMEM_CURRENT_MSR 0x65 +#define BIOSMEM_CURRENT_PAL 0x66 +#define BIOSMEM_NB_ROWS 0x84 +#define BIOSMEM_CHAR_HEIGHT 0x85 +#define BIOSMEM_VIDEO_CTL 0x87 +#define BIOSMEM_SWITCHES 0x88 +#define BIOSMEM_MODESET_CTL 0x89 +#define BIOSMEM_DCC_INDEX 0x8A +#define BIOSMEM_VS_POINTER 0xA8 +#define BIOSMEM_VBE_FLAG 0xB9 +#define BIOSMEM_VBE_MODE 0xBA + + +/* + * + * VGA registers + * + */ +#define VGAREG_ACTL_ADDRESS 0x3c0 +#define VGAREG_ACTL_WRITE_DATA 0x3c0 +#define VGAREG_ACTL_READ_DATA 0x3c1 + +#define VGAREG_INPUT_STATUS 0x3c2 +#define VGAREG_WRITE_MISC_OUTPUT 0x3c2 +#define VGAREG_VIDEO_ENABLE 0x3c3 +#define VGAREG_SEQU_ADDRESS 0x3c4 +#define VGAREG_SEQU_DATA 0x3c5 + +#define VGAREG_PEL_MASK 0x3c6 +#define VGAREG_DAC_STATE 0x3c7 +#define VGAREG_DAC_READ_ADDRESS 0x3c7 +#define VGAREG_DAC_WRITE_ADDRESS 0x3c8 +#define VGAREG_DAC_DATA 0x3c9 + +#define VGAREG_READ_FEATURE_CTL 0x3ca +#define VGAREG_READ_MISC_OUTPUT 0x3cc + +#define VGAREG_GRDC_ADDRESS 0x3ce +#define VGAREG_GRDC_DATA 0x3cf + +#define VGAREG_MDA_CRTC_ADDRESS 0x3b4 +#define VGAREG_MDA_CRTC_DATA 0x3b5 +#define VGAREG_VGA_CRTC_ADDRESS 0x3d4 +#define VGAREG_VGA_CRTC_DATA 0x3d5 + +#define VGAREG_MDA_WRITE_FEATURE_CTL 0x3ba +#define VGAREG_VGA_WRITE_FEATURE_CTL 0x3da +#define VGAREG_ACTL_RESET 0x3da + +#define VGAREG_MDA_MODECTL 0x3b8 +#define VGAREG_CGA_MODECTL 0x3d8 +#define VGAREG_CGA_PALETTE 0x3d9 + +#endif /* !VBOX_INCLUDED_SRC_Graphics_BIOS_vgadefs_h */ + diff --git a/src/VBox/Devices/Graphics/BIOS/vgadefs.inc b/src/VBox/Devices/Graphics/BIOS/vgadefs.inc new file mode 100644 index 00000000..ef69fb5e --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vgadefs.inc @@ -0,0 +1,58 @@ +VGAREG_ACTL_ADDRESS EQU 3C0h +VGAREG_ACTL_WRITE_DATA EQU 3C0h +VGAREG_ACTL_READ_DATA EQU 3C1h +VGAREG_ACTL_RESET EQU 3DAh + +VGAREG_DAC_READ_ADDRESS EQU 3C7h +VGAREG_DAC_WRITE_ADDRESS EQU 3C8h +VGAREG_DAC_DATA EQU 3C9h + +VGAREG_PEL_MASK EQU 3C6h + +VGAREG_SEQU_ADDRESS EQU 3C4h +VGAREG_SEQU_DATA EQU 3C5h + +VGAREG_GRDC_ADDRESS EQU 3CEh +VGAREG_GRDC_DATA EQU 3CFh + +VGAREG_MDA_CRTC_ADDRESS EQU 3B4h +VGAREG_VGA_CRTC_ADDRESS EQU 3D4h +VGAREG_VGA_CRTC_DATA EQU 3D5h + + +VGAREG_READ_MISC_OUTPUT EQU 3CCh +VGAREG_WRITE_MISC_OUTPUT EQU 3C2h + +BIOSMEM_SEG EQU 40h +BIOSMEM_CURRENT_MODE EQU 49h +BIOSMEM_NB_COLS EQU 4Ah +BIOSMEM_CURRENT_PAGE EQU 62h +BIOSMEM_CRTC_ADDRESS EQU 63h +BIOSMEM_VIDEO_CTL EQU 87h +BIOSMEM_SWITCHES EQU 88h +BIOSMEM_MODESET_CTL EQU 89h +BIOSMEM_DCC_INDEX EQU 8Ah + +BIOSMEM_VBE_FLAG EQU 0B9h +BIOSMEM_VBE_MODE EQU 0BAh + +VBE_DISPI_IOPORT_INDEX EQU 1CEh +VBE_DISPI_IOPORT_DATA EQU 1CFh + +VBE_DISPI_INDEX_ID EQU 00h +VBE_DISPI_INDEX_XRES EQU 01h +VBE_DISPI_INDEX_YRES EQU 02h +VBE_DISPI_INDEX_BPP EQU 03h +VBE_DISPI_INDEX_ENABLE EQU 04h +VBE_DISPI_INDEX_BANK EQU 05h +VBE_DISPI_INDEX_VIRT_WIDTH EQU 06h +VBE_DISPI_INDEX_VIRT_HEIGHT EQU 07h +VBE_DISPI_INDEX_X_OFFSET EQU 08h +VBE_DISPI_INDEX_Y_OFFSET EQU 09h + +VBE_DISPI_ENABLED EQU 01h +VBE_DISPI_GETCAPS EQU 02h +VBE_DISPI_8BIT_DAC EQU 20h + +VBE_DISPI_ID0 EQU 0B0C0h +VBE_DISPI_ID4 EQU 0B0C4h diff --git a/src/VBox/Devices/Graphics/BIOS/vgafonts.h b/src/VBox/Devices/Graphics/BIOS/vgafonts.h new file mode 100644 index 00000000..0411a006 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vgafonts.h @@ -0,0 +1,878 @@ +/* + * These fonts come from ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip + * The package is (c) by Joseph Gil + * The individual fonts are public domain + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_BIOS_vgafonts_h +#define VBOX_INCLUDED_SRC_Graphics_BIOS_vgafonts_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +static uint8_t vgafont8[256*8]= +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, + 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, + 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, + 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, + 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, + 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, + 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, // 10 + 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, + 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, + 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, + 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, + 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, + 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, + 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, // 20 + 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, + 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, // 30 + 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, + 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, + 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, + 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, + 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, + 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, // 40 + 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, + 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, + 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, + 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, + 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, // 50 + 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, + 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, + 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, + 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, + 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, // 60 + 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, + 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, + 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, + 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, + 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, + 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, // 70 + 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, + 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, + 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, + 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, + 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, + 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, + 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, // 80 + 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, + 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, + 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, + 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, + 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, + 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, // 90 + 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, + 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, + 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, // 100 + 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, + 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, + 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, + 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, // 110 + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, + 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, + 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, + 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, + 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, + 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, // 120 + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, + 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, + 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 130 + 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, + 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, + 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, + 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, // 140 + 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, + 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, + 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, + 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, + 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, + 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 150 + 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, + 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, + 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, + 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, + 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, + 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 160 + 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, + 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, + 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, + 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, // 170 + 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, + 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, + 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, // 180 + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, // 190 + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, // 200 + 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, // 210 + 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, // 220 + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, + 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, + 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, + 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, + 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, // 230 + 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, + 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, + 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, + 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, + 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, + 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, // 240 + 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, + 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, + 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, // 250 + 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, + 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static uint8_t vgafont14[256*14]= +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, // 10 + 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, // 20 + 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, // 30 + 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, // 40 + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, // 50 + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, // 60 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, // 70 + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, // 80 + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, // 90 + 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, // 100 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, // 110 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, // 120 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, // 130 + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, // 140 + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, // 150 + 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, + 0x00, 0xc6, 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, // 160 + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, // 170 + 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, + 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 180 + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 190 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 200 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 210 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 220 + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0x40, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, // 230 + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, // 240 + 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 250 + 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static uint8_t vgafont16[256*16]= +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, // 10 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, // 20 + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 30 + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 40 + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, // 50 + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // 60 + 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, // 70 + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 80 + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 90 + 0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 100 + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 110 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00, // 120 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, // 130 + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // 140 + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, // 150 + 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, + 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, // 160 + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, // 170 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 180 + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 190 + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, // 200 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 210 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 220 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, // 230 + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, // 240 + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 250 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static uint8_t vgafont14alt[20*15+1]= +{ + 0x1d, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, + 0x00, 0x63, 0x63, 0x63, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x2d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4d, + 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, + 0x54, + 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x56, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x57, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, + 0x58, + 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, + 0x59, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x5a, + 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x61, 0xc3, 0xff, 0x00, 0x00, 0x00, + 0x6d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, + 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x77, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, + 0x91, + 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, + 0x9b, + 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x9d, + 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x9e, + 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, + 0xf1, + 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0xff, 0x00, 0x00, 0x00, + 0xf6, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00 +}; +static uint8_t vgafont16alt[19*17+1]= +{ + 0x1d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, + 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x4d, + 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x54, + 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x56, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x57, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x58, + 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x59, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x5a, + 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x6d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, + 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x77, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x91, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, + 0x9b, + 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x9d, + 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x9e, + 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, + 0xab, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, + 0xac, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, + 0x00 +}; + +#endif /* !VBOX_INCLUDED_SRC_Graphics_BIOS_vgafonts_h */ + diff --git a/src/VBox/Devices/Graphics/BIOS/vgarom.asm b/src/VBox/Devices/Graphics/BIOS/vgarom.asm new file mode 100644 index 00000000..f5bffcc4 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vgarom.asm @@ -0,0 +1,1102 @@ +;; ============================================================================================ +;; +;; Copyright (C) 2001,2002 the LGPL VGABios developers Team +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; ============================================================================================ +;; +;; This VGA Bios is specific to the plex86/bochs Emulated VGA card. +;; You can NOT drive any physical vga card with it. +;; +;; ============================================================================================ +;; + + +; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice +; other than GPL or LGPL is available it will apply instead, Oracle elects to use only +; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where +; a choice of LGPL license versions is made available with the language indicating +; that LGPLv2 or any later version may be used, or where a choice of which version +; of the LGPL is applied is otherwise unspecified. + +include vgadefs.inc +include commondefs.inc + +public vgabios_int10_handler + +VGAROM segment public 'CODE' + +; Implemented in C +extrn _int10_func:near +extrn _vgabios_init_func:near + +ifdef VBE +; Implemented in separate assembly module +extrn vbe_biosfn_return_current_mode:near +extrn vbe_biosfn_display_window_control:near +extrn vbe_biosfn_set_get_display_start:near +extrn vbe_biosfn_set_get_dac_palette_format:near +extrn vbe_biosfn_set_get_palette_data:near +extrn vbe_biosfn_return_protected_mode_interface:near +endif + +ifdef VGA_DEBUG +extrn _int10_debugmsg:near +extrn _printf:near +extrn _unimplemented:near +extrn _unknown:near +endif + +vgabios_start: + +db 055h, 0AAh ; ROM signature, required for expansion ROMs +db 40h ; ROM module length in units of 512 bytes */ + + +vgabios_entry_point: + + jmp vgabios_init + + org 1Eh + + db 'IBM',0 + +vgabios_init: +;; We have to set ds to access the right data segment + push cs + pop ds + cld + jmp _vgabios_init_func + +;; +;; int10 handled here +;; + +SET_DEFAULT_CPU_286 + +vgabios_int10_handler: + pushf +ifdef VGA_DEBUG + push es + push ds + DO_pusha + push cs + pop ds + cld + call _int10_debugmsg + DO_popa + pop ds + pop es +endif + cmp ah, 0Fh + jne int10_test_1A + call biosfn_get_video_mode + jmp int10_end +int10_test_1A: + cmp ah, 1Ah + jne int10_test_0B + call biosfn_group_1A + jmp int10_end +int10_test_0B: + cmp ah, 0Bh + jne int10_test_1103 + call biosfn_group_0B + jmp int10_end +int10_test_1103: + cmp ax, 1103h + jne int10_test_12 + call biosfn_set_text_block_specifier + jmp int10_end +int10_test_12: + cmp ah, 12h + jne int10_test_101B + cmp bl, 10h + jne int10_test_BL30 + call biosfn_get_ega_info + jmp int10_end +int10_test_BL30: + cmp bl, 30h + jne int10_test_BL31 + call biosfn_select_vert_res + jmp int10_end +int10_test_BL31: + cmp bl, 31h + jne int10_test_BL32 + call biosfn_enable_default_palette_loading + jmp int10_end +int10_test_BL32: + cmp bl, 32h + jne int10_test_BL33 + call biosfn_enable_video_addressing + jmp int10_end +int10_test_BL33: + cmp bl, 33h + jne int10_test_BL34 + call biosfn_enable_grayscale_summing + jmp int10_end +int10_test_BL34: + cmp bl, 34h + jne int10_normal + call biosfn_enable_cursor_emulation + jmp int10_end +int10_test_101B: + cmp ax, 101Bh + je int10_normal + cmp ah, 10h +ifndef VBE + jne int10_normal +else + jne int10_test_4F +endif + call biosfn_group_10 + jmp int10_end +ifdef VBE +int10_test_4F: + cmp ah, 4Fh + jne int10_normal + cmp al, 3 + jne int10_test_vbe_05 + call vbe_biosfn_return_current_mode + jmp int10_end +int10_test_vbe_05: + cmp al, 5 + jne int10_test_vbe_07 + call vbe_biosfn_display_window_control + jmp int10_end +int10_test_vbe_07: + cmp al, 7 + jne int10_test_vbe_08 + call vbe_biosfn_set_get_display_start + jmp int10_end +int10_test_vbe_08: + cmp al, 8 + jne int10_test_vbe_09 + call vbe_biosfn_set_get_dac_palette_format + jmp int10_end +int10_test_vbe_09: + cmp al, 9 + jne int10_test_vbe_0A + call vbe_biosfn_set_get_palette_data + jmp int10_end +int10_test_vbe_0A: + cmp al, 0Ah + jne int10_normal + call vbe_biosfn_return_protected_mode_interface + jmp int10_end +endif + +int10_normal: + push es + push ds + DO_pusha + +;; We have to set ds to access the right data segment + push cs + pop ds + cld + call _int10_func + + DO_popa + pop ds + pop es +int10_end: + popf + iret + +;;-------------------------------------------------------------------------------------------- + +biosfn_group_0B: + cmp bh, 0 + je biosfn_set_border_color + cmp bh, 1 + je biosfn_set_palette +ifdef VGA_DEBUG + call _unknown +endif + ret +biosfn_set_border_color: + push ax + push bx + push cx + push dx + push ds + mov dx, BIOSMEM_SEG + mov ds, dx + mov dx, VGAREG_ACTL_RESET + in al, dx + cmp byte ptr ds:[BIOSMEM_CURRENT_MODE], 3 + jbe set_border_done + mov dx, VGAREG_ACTL_ADDRESS + mov al, 00h + out dx, al + mov al, bl + and al, 0Fh + test al, 08h + jz set_low_border + add al, 08h +set_low_border: + out dx, al + mov cl, 1 + and bl, 10h +set_intensity_loop: + mov dx, VGAREG_ACTL_ADDRESS + mov al, cl + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + and al, 0EFh + or al, bl + mov dx, VGAREG_ACTL_ADDRESS + out dx, al + inc cl + cmp cl, 4 + jne set_intensity_loop +set_border_done: + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop ds + pop dx + pop cx + pop bx + pop ax + ret +biosfn_set_palette: + push ax + push bx + push cx + push dx + mov dx, VGAREG_ACTL_RESET + in al, dx + mov cl, 01 + and bl, 01 +set_cga_palette_loop: + mov dx, VGAREG_ACTL_ADDRESS + mov al, cl + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + and al, 0FEh + or al, bl + mov dx, VGAREG_ACTL_ADDRESS + out dx, al + inc cl + cmp cl, 4 + jne set_cga_palette_loop + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop dx + pop cx + pop bx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_get_video_mode: + push ds + mov ax, BIOSMEM_SEG + mov ds, ax + push bx + mov bx, BIOSMEM_CURRENT_PAGE + mov al, [bx] + pop bx + mov bh, al + push bx + mov bx, BIOSMEM_VIDEO_CTL + mov ah, [bx] + and ah, 80h + mov bx, BIOSMEM_CURRENT_MODE + mov al, [bx] + or al, ah + mov bx, BIOSMEM_NB_COLS + mov ah, [bx] + pop bx + pop ds + ret + +;-------------------------------------------------------------------------------------------- + +biosfn_group_10: + cmp al, 0 + jne int10_test_1001 + jmp biosfn_set_single_palette_reg +int10_test_1001: + cmp al, 1 + jne int10_test_1002 + jmp biosfn_set_overscan_border_color +int10_test_1002: + cmp al, 2 + jne int10_test_1003 + jmp biosfn_set_all_palette_reg +int10_test_1003: + cmp al, 3 + jne int10_test_1007 + jmp biosfn_toggle_intensity +int10_test_1007: + cmp al, 7 + jne int10_test_1008 + jmp biosfn_get_single_palette_reg +int10_test_1008: + cmp al, 8 + jne int10_test_1009 + jmp biosfn_read_overscan_border_color +int10_test_1009: + cmp al, 9 + jne int10_test_1010 + jmp biosfn_get_all_palette_reg +int10_test_1010: + cmp al, 10h + jne int10_test_1012 + jmp biosfn_set_single_dac_reg +int10_test_1012: + cmp al, 12h + jne int10_test_1013 + jmp biosfn_set_all_dac_reg +int10_test_1013: + cmp al, 13h + jne int10_test_1015 + jmp biosfn_select_video_dac_color_page +int10_test_1015: + cmp al, 15h + jne int10_test_1017 + jmp biosfn_read_single_dac_reg +int10_test_1017: + cmp al, 17h + jne int10_test_1018 + jmp biosfn_read_all_dac_reg +int10_test_1018: + cmp al, 18h + jne int10_test_1019 + jmp biosfn_set_pel_mask +int10_test_1019: + cmp al, 19h + jne int10_test_101A + jmp biosfn_read_pel_mask +int10_test_101A: + cmp al, 1Ah + jne int10_group_10_unknown + jmp biosfn_read_video_dac_state +int10_group_10_unknown: +ifdef VGA_DEBUG + call _unknown +endif + ret + +biosfn_set_single_palette_reg: + cmp bl, 14h + ja no_actl_reg1 + push ax + push dx + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, bl + out dx, al + mov al, bh + out dx, al + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop dx + pop ax +no_actl_reg1: + ret + +;-------------------------------------------------------------------------------------------- + +biosfn_set_overscan_border_color: + push bx + mov bl, 11h + call biosfn_set_single_palette_reg + pop bx + ret + +;-------------------------------------------------------------------------------------------- + +biosfn_set_all_palette_reg: + push ax + push bx + push cx + push dx + mov bx, dx + mov dx, VGAREG_ACTL_RESET + in al, dx + mov cl, 0 + mov dx, VGAREG_ACTL_ADDRESS +set_palette_loop: + mov al, cl + out dx, al + mov al, es:[bx] + out dx, al + inc bx + inc cl + cmp cl, 10h + jne set_palette_loop + mov al, 11h + out dx, al + mov al, es:[bx] + out dx, al + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop dx + pop cx + pop bx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_toggle_intensity: + push ax + push bx + push dx + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 10h + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + and al, 0F7h + and bl, 01 +if VBOX_BIOS_CPU gt 8086 + shl bl, 3 +else + shl bl, 1 + shl bl, 1 + shl bl, 1 +endif + or al, bl + mov dx, VGAREG_ACTL_ADDRESS + out dx, al + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop dx + pop bx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_get_single_palette_reg: + cmp bl, 14h + ja no_actl_reg2 + push ax + push dx + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, bl + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + mov bh, al + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop dx + pop ax +no_actl_reg2: + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_read_overscan_border_color: + push ax + push bx + mov bl, 11h + call biosfn_get_single_palette_reg + mov al, bh + pop bx + mov bh, al + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_get_all_palette_reg: + push ax + push bx + push cx + push dx + mov bx, dx + mov cl, 0 +get_palette_loop: + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, cl + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + mov es:[bx], al + inc bx + inc cl + cmp cl, 10h + jne get_palette_loop + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 11h + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + mov es:[bx], al + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop dx + pop cx + pop bx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_set_single_dac_reg: + push ax + push dx + mov dx, VGAREG_DAC_WRITE_ADDRESS + mov al, bl + out dx, al + mov dx, VGAREG_DAC_DATA + pop ax + push ax + mov al, ah + out dx, al + mov al, ch + out dx, al + mov al, cl + out dx, al + pop dx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_set_all_dac_reg: + push ax + push bx + push cx + push dx + mov dx, VGAREG_DAC_WRITE_ADDRESS + mov al, bl + out dx, al + pop dx + push dx + mov bx, dx + mov dx, VGAREG_DAC_DATA +set_dac_loop: + mov al, es:[bx] + out dx, al + inc bx + mov al, es:[bx] + out dx, al + inc bx + mov al, es:[bx] + out dx, al + inc bx + dec cx + jnz set_dac_loop + pop dx + pop cx + pop bx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_select_video_dac_color_page: + push ax + push bx + push dx + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 10h + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + and bl, 01 + jnz set_dac_page + and al, 07Fh +if VBOX_BIOS_CPU gt 8086 + shl bh, 7 +else + shl bh, 1 + shl bh, 1 + shl bh, 1 + shl bh, 1 + shl bh, 1 + shl bh, 1 + shl bh, 1 +endif + or al, bh + mov dx, VGAREG_ACTL_ADDRESS + out dx, al + jmp set_actl_normal +set_dac_page: + push ax + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 14h + out dx, al + pop ax + and al, 80h + jnz set_dac_16_page +if VBOX_BIOS_CPU gt 8086 + shl bh, 2 +else + shl bh, 1 + shl bh, 1 +endif +set_dac_16_page: + and bh, 0Fh + mov al, bh + out dx, al +set_actl_normal: + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop dx + pop bx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_read_single_dac_reg: + push ax + push dx + mov dx, VGAREG_DAC_READ_ADDRESS + mov al, bl + out dx, al + pop ax + mov ah, al + mov dx, VGAREG_DAC_DATA + in al, dx + xchg al, ah + push ax + in al, dx + mov ch, al + in al, dx + mov cl, al + pop dx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_read_all_dac_reg: + push ax + push bx + push cx + push dx + mov dx, VGAREG_DAC_READ_ADDRESS + mov al, bl + out dx, al + pop dx + push dx + mov bx, dx + mov dx, VGAREG_DAC_DATA +read_dac_loop: + in al, dx + mov es:[bx], al + inc bx + in al, dx + mov es:[bx], al + inc bx + in al, dx + mov es:[bx], al + inc bx + dec cx + jnz read_dac_loop + pop dx + pop cx + pop bx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_set_pel_mask: + push ax + push dx + mov dx, VGAREG_PEL_MASK + mov al, bl + out dx, al + pop dx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_read_pel_mask: + push ax + push dx + mov dx, VGAREG_PEL_MASK + in al, dx + mov bl, al + pop dx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_read_video_dac_state: + push ax + push dx + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 10h + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + mov bl, al +if VBOX_BIOS_CPU gt 8086 + shr bl, 7 +else + shr bl, 1 + shr bl, 1 + shr bl, 1 + shr bl, 1 + shr bl, 1 + shr bl, 1 + shr bl, 1 +endif + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 14h + out dx, al + mov dx, VGAREG_ACTL_READ_DATA + in al, dx + mov bh, al + and bh, 0Fh + test bl, 01 + jnz get_dac_16_page +if VBOX_BIOS_CPU gt 8086 + shr bh, 2 +else + shr bh, 1 + shr bh, 1 +endif +get_dac_16_page: + mov dx, VGAREG_ACTL_RESET + in al, dx + mov dx, VGAREG_ACTL_ADDRESS + mov al, 20h + out dx, al +ifdef VBOX + mov dx, VGAREG_ACTL_RESET + in al, dx +endif ; VBOX + pop dx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_set_text_block_specifier: + push ax + push dx + mov dx, VGAREG_SEQU_ADDRESS + mov ah, bl + mov al, 03 + out dx, ax + pop dx + pop ax + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_get_ega_info: + push ds + push ax + mov ax, BIOSMEM_SEG + mov ds, ax + xor ch, ch + mov bx, BIOSMEM_SWITCHES + mov cl, [bx] + and cl, 0Fh + mov bx, BIOSMEM_CRTC_ADDRESS + mov ax, [bx] + mov bx, 0003h + cmp ax, VGAREG_MDA_CRTC_ADDRESS + jne mode_ega_color + mov bh, 01 +mode_ega_color: + pop ax + pop ds + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_select_vert_res: + +; res : 00 200 lines, 01 350 lines, 02 400 lines + + push ds + push bx + push dx + mov dl, al + mov ax, BIOSMEM_SEG + mov ds, ax + mov bx, BIOSMEM_MODESET_CTL + mov al, [bx] + mov bx, BIOSMEM_SWITCHES + mov ah, [bx] + cmp dl, 1 + je vert_res_350 + jb vert_res_200 + cmp dl, 2 + je vert_res_400 +ifdef VGA_DEBUG + mov al, dl + xor ah, ah + push ax + mov bx, msg_vert_res + push bx + call _printf + add sp, 4 +endif + jmp set_retcode +vert_res_400: + + ; reset modeset ctl bit 7 and set bit 4 + ; set switches bit 3-0 to 09 + + and al, 07Fh + or al, 010h + and ah, 0F0h + or ah, 009h + jnz set_vert_res +vert_res_350: + + ; reset modeset ctl bit 7 and bit 4 + ; set switches bit 3-0 to 09 + + and al, 06Fh + and ah, 0F0h + or ah, 009h + jnz set_vert_res +vert_res_200: + + ; set modeset ctl bit 7 and reset bit 4 + ; set switches bit 3-0 to 08 + + and al, 0EFh + or al, 080h + and ah, 0F0h + or ah, 008h +set_vert_res: + mov bx, BIOSMEM_MODESET_CTL + mov [bx], al + mov bx, BIOSMEM_SWITCHES + mov [bx], ah +set_retcode: + mov ax, 1212h + pop dx + pop bx + pop ds + ret + +ifdef VGA_DEBUG +msg_vert_res: +db "Select vert res (%02x) was discarded", 13, 10, 0 +endif + + +biosfn_enable_default_palette_loading: + push ds + push bx + push dx + mov dl, al + and dl, 01 +if VBOX_BIOS_CPU gt 8086 + shl dl, 3 +else + shl dl, 1 + shl dl, 1 + shl dl, 1 +endif + mov ax, BIOSMEM_SEG + mov ds, ax + mov bx, BIOSMEM_MODESET_CTL + mov al, [bx] + and al, 0F7h + or al, dl + mov [bx], al + mov ax, 1212h + pop dx + pop bx + pop ds + ret + + +biosfn_enable_video_addressing: + push bx + push dx + mov bl, al + and bl, 01 + xor bl, 01 + shl bl, 1 + mov dx, VGAREG_READ_MISC_OUTPUT + in al, dx + and al, 0FDh + or al, bl + mov dx, VGAREG_WRITE_MISC_OUTPUT + out dx, al + mov ax, 1212h + pop dx + pop bx + ret + + +biosfn_enable_grayscale_summing: + push ds + push bx + push dx + mov dl, al + and dl, 01h + xor dl, 01h + shl dl, 1 + mov ax, BIOSMEM_SEG + mov ds, ax + mov bx, BIOSMEM_MODESET_CTL + mov al, [bx] + and al, 0FDh + or al, dl + mov [bx], al + mov ax, 1212h + pop dx + pop bx + pop ds + ret + + +biosfn_enable_cursor_emulation: + push ds + push bx + push dx + mov dl, al + and dl, 01 + xor dl, 01 + mov ax, BIOSMEM_SEG + mov ds, ax + mov bx, BIOSMEM_MODESET_CTL + mov al, [bx] + and al, 0FEh + or al, dl + mov [bx], al + mov ax, 1212h + pop dx + pop bx + pop ds + ret + +;;-------------------------------------------------------------------------------------------- + +biosfn_group_1A: + cmp al, 0 + je biosfn_read_display_code + cmp al, 1 + je biosfn_set_display_code +ifdef VGA_DEBUG + call _unknown +endif + ret +biosfn_read_display_code: + push ds + push ax + mov ax, BIOSMEM_SEG + mov ds, ax + mov bx, BIOSMEM_DCC_INDEX + mov al, [bx] + mov bl, al + xor bh, bh + pop ax + mov al, ah + pop ds + ret +biosfn_set_display_code: + push ds + push ax + push bx + mov ax, BIOSMEM_SEG + mov ds, ax + mov ax, bx + mov bx, BIOSMEM_DCC_INDEX + mov [bx], al +ifdef VGA_DEBUG + mov al, ah + xor ah, ah + push ax + mov bx, msg_alt_dcc + push bx + call _printf + add sp, 4 +endif + pop bx + pop ax + mov al, ah + pop ds + ret + +ifdef VGA_DEBUG +msg_alt_dcc: +db "Alternate Display code (%02x) was discarded", 13, 10, 0 +endif + +VGAROM ends + + end diff --git a/src/VBox/Devices/Graphics/BIOS/vgatables.h b/src/VBox/Devices/Graphics/BIOS/vgatables.h new file mode 100644 index 00000000..a5d8e8e6 --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vgatables.h @@ -0,0 +1,625 @@ + +#ifndef VBOX_INCLUDED_SRC_Graphics_BIOS_vgatables_h +#define VBOX_INCLUDED_SRC_Graphics_BIOS_vgatables_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* Video memory */ +#define VGAMEM_GRAPH 0xA000 +#define VGAMEM_CTEXT 0xB800 +#define VGAMEM_MTEXT 0xB000 + +/* + * + * Tables of default values for each mode + * + */ +#define MODE_MAX 15 +#define TEXT 0x00 +#define GRAPH 0x01 + +#define CTEXT 0x00 +#define MTEXT 0x01 +#define CGA 0x02 +#define PLANAR1 0x03 +#define PLANAR4 0x04 +#define LINEAR8 0x05 + +// for SVGA +#define LINEAR15 0x10 +#define LINEAR16 0x11 +#define LINEAR24 0x12 +#define LINEAR32 0x13 + +typedef struct +{uint8_t svgamode; + uint8_t class; /* TEXT, GRAPH */ + uint8_t memmodel; /* CTEXT,MTEXT,CGA,PL1,PL2,PL4,P8,P15,P16,P24,P32 */ + uint8_t pixbits; + uint16_t sstart; + uint8_t pelmask; + uint8_t dacmodel; /* 0 1 2 3 */ +} VGAMODES; + +static VGAMODES vga_modes[MODE_MAX+1]= +{//mode class model bits sstart pelm dac + {0x00, TEXT, CTEXT, 4, 0xB800, 0xFF, 0x02}, + {0x01, TEXT, CTEXT, 4, 0xB800, 0xFF, 0x02}, + {0x02, TEXT, CTEXT, 4, 0xB800, 0xFF, 0x02}, + {0x03, TEXT, CTEXT, 4, 0xB800, 0xFF, 0x02}, + {0x04, GRAPH, CGA, 2, 0xB800, 0xFF, 0x01}, + {0x05, GRAPH, CGA, 2, 0xB800, 0xFF, 0x01}, + {0x06, GRAPH, CGA, 1, 0xB800, 0xFF, 0x01}, + {0x07, TEXT, MTEXT, 4, 0xB000, 0xFF, 0x00}, + {0x0D, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x01}, + {0x0E, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x01}, + {0x0F, GRAPH, PLANAR1, 1, 0xA000, 0xFF, 0x00}, + {0x10, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x02}, + {0x11, GRAPH, PLANAR1, 1, 0xA000, 0xFF, 0x02}, + {0x12, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x02}, + {0x13, GRAPH, LINEAR8, 8, 0xA000, 0xFF, 0x03}, + {0x6A, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x02} +}; + +/* convert index in vga_modes[] to index in video_param_table[] */ +static uint8_t line_to_vpti[MODE_MAX+1]={ + 0x17, 0x17, 0x18, 0x18, 0x04, 0x05, 0x06, 0x07, + 0x0d, 0x0e, 0x11, 0x12, 0x1a, 0x1b, 0x1c, 0x1d, +}; + +/* Default Palette */ +#define DAC_MAX_MODEL 3 + +static uint8_t dac_regs[DAC_MAX_MODEL+1]= +{0x3f,0x3f,0x3f,0xff}; + +/* standard BIOS Video Parameter Table */ +#pragma pack(push, 1) +typedef struct { + uint8_t twidth; + uint8_t theightm1; + uint8_t cheight; + uint16_t slength; + uint8_t sequ_regs[4]; + uint8_t miscreg; + uint8_t crtc_regs[25]; + uint8_t actl_regs[20]; + uint8_t grdc_regs[9]; +} VideoParamTableEntry; +#pragma pack(pop) + +static VideoParamTableEntry video_param_table[30] = { +{ + /* index=0x00 cga mode 0/1 */ + 40, 24, 8, 0x0800, /* tw, th-1, ch, slength */ + 0x09, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x63, /* miscreg */ + 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f, + 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x08, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x01 cga mode 0/1 */ + 40, 24, 8, 0x0800, /* tw, th-1, ch, slength */ + 0x09, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x63, /* miscreg */ + 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f, + 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x08, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x02 cga mode 2/3 */ + 80, 24, 8, 0x1000, /* tw, th-1, ch, slength */ + 0x01, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x63, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x08, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x03 cga mode 2/3 */ + 80, 24, 8, 0x1000, /* tw, th-1, ch, slength */ + 0x01, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x63, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x08, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x04 vga mode 0x04 */ + 40, 24, 8, 0x4000, /* tw, th-1, ch, slength */ + 0x09, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x63, /* miscreg */ + 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2, + 0xff, /* crtc_regs */ + 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x01, 0x00, 0x03, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x05 vga mode 0x05 */ + 40, 24, 8, 0x4000, /* tw, th-1, ch, slength */ + 0x09, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x63, /* miscreg */ + 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2, + 0xff, /* crtc_regs */ + 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x01, 0x00, 0x03, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x06 vga mode 0x06 */ + 80, 24, 8, 0x4000, /* tw, th-1, ch, slength */ + 0x01, 0x01, 0x00, 0x06, /* sequ_regs */ + 0x63, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2, + 0xff, /* crtc_regs */ + 0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x01, 0x00, 0x01, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x07 ega mode 0x07 */ + 80, 24, 14, 0x1000, /* tw, th-1, ch, slength */ + 0x00, 0x03, 0x00, 0x03, /* sequ_regs */ + 0xA6, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x28, 0x0d, 0x63, 0xba, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x0e, 0x00, 0x0f, 0x08, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x08 no mode defined */ + 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}, +{ + /* index=0x09 no mode defined */ + 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}, +{ + /* index=0x0a no mode defined */ + 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}, +#if 0 +/* XENIX 2.2 uses mode entries Bh/Ch when loading EGA fonts. If they are + * all zeros, fonts can't be set. However, some versions (XENIX 2.2.3b) + * end up programming garbage into the fonts. We're better off with + * cut off VGA fonts than with complete garbage, so we leave these + * mode table entries zeroed. + */ +{ + /* index=0x0b EGA font load fake mode (color) */ + 80, 24, 8, 0x1000, /* tw, th-1, ch, slength */ + 0x01, 0x04, 0x00, 0x07, /* sequ_regs */ + 0x23, /* miscreg */ + 0x70, 0x4f, 0x5c, 0x2f, 0x5f, 0x07, 0x04, 0x11, + 0x00, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + 0xe1, 0x24, 0xc7, 0x28, 0x08, 0xe0, 0xf0, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x0c EGA font load fake mode (mono) */ + 80, 24, 14, 0x1000, /* tw, th-1, ch, slength */ + 0x01, 0x04, 0x00, 0x07, /* sequ_regs */ + 0xa6, /* miscreg */ + 0x60, 0x4f, 0x56, 0x3a, 0x51, 0x60, 0x70, 0x1f, + 0x00, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x5e, 0x2e, 0x5d, 0x28, 0x0d, 0x5e, 0x6e, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0x08, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xff, /* grdc_regs */ +}, +#else +{ + /* index=0x0b no mode defined */ + 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}, +{ + /* index=0x0c no mode defined */ + 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}, +#endif +{ + /* index=0x0d vga mode 0x0d */ + 40, 24, 8, 0x2000, /* tw, th-1, ch, slength */ + 0x09, 0x0f, 0x00, 0x06, /* sequ_regs */ + 0x63, /* miscreg */ + 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x0e vga mode 0x0e */ + 80, 24, 8, 0x4000, /* tw, th-1, ch, slength */ + 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ + 0x63, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x0f no mode defined */ + 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}, +{ + /* index=0x10 no mode defined */ + 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}, +{ + /* index=0x11 vga mode 0x0f */ + 80, 24, 14, 0x8000, /* tw, th-1, ch, slength */ + 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ + 0xa3, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3, + 0xff, /* crtc_regs */ + 0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x12 vga mode 0x10 */ + 80, 24, 14, 0x8000, /* tw, th-1, ch, slength */ + 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ + 0xa3, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x13 ega mode 0/1 */ + 40, 24, 14, 0x0800, /* tw, th-1, ch, slength */ + 0x09, 0x03, 0x00, 0x02, /* sequ_regs */ + 0xa3, /* miscreg */ + 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f, + 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x14, 0x1f, 0x63, 0xba, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x08, 0x00, 0x0f, 0x08, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x14 ega mode 0/1 */ + 40, 24, 14, 0x0800, /* tw, th-1, ch, slength */ + 0x09, 0x03, 0x00, 0x02, /* sequ_regs */ + 0xa3, /* miscreg */ + 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f, + 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x14, 0x1f, 0x63, 0xba, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x08, 0x00, 0x0f, 0x08, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x15 ega mode 2/3 */ + 80, 24, 14, 0x1000, /* tw, th-1, ch, slength */ + 0x01, 0x03, 0x00, 0x02, /* sequ_regs */ + 0xa3, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x28, 0x1f, 0x63, 0xba, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x08, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x16 ega mode 2/3 */ + 80, 24, 14, 0x1000, /* tw, th-1, ch, slength */ + 0x01, 0x03, 0x00, 0x02, /* sequ_regs */ + 0xa3, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x28, 0x1f, 0x63, 0xba, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x08, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, /* grdc_regs */ +}, +{ + /* index=0x17 vga mode 0x01 */ + 40, 24, 16, 0x0800, /* tw, th-1, ch, slength */ + 0x08, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x67, /* miscreg */ + 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x0c, 0x00, 0x0f, 0x08, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x18 vga mode 0x03 */ + 80, 24, 16, 0x1000, /* tw, th-1, ch, slength */ + 0x00, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x67, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x0c, 0x00, 0x0f, 0x08, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x19 vga mode 0x07 */ + 80, 24, 16, 0x1000, /* tw, th-1, ch, slength */ + 0x00, 0x03, 0x00, 0x02, /* sequ_regs */ + 0x66, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x0e, 0x00, 0x0f, 0x08, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x1a vga mode 0x11 */ + 80, 29, 16, 0xa000, /* tw, th-1, ch, slength */ + 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ + 0xe3, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xc3, + 0xff, /* crtc_regs */ + 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, + 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, + 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x1b vga mode 0x12 */ + 80, 29, 16, 0xa000, /* tw, th-1, ch, slength */ + 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ + 0xe3, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x1c vga mode 0x13 */ + 40, 24, 8, 0x2000, /* tw, th-1, ch, slength */ + 0x01, 0x0f, 0x00, 0x0e, /* sequ_regs */ + 0x63, /* miscreg */ + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, + 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x41, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, /* grdc_regs */ +}, +{ + /* index=0x1d vga mode 0x6a */ + 100, 36, 16, 0x0000, /* tw, th-1, ch, slength */ + 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ + 0xe3, /* miscreg */ + 0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x59, 0x8d, 0x57, 0x32, 0x00, 0x57, 0x73, 0xe3, + 0xff, /* crtc_regs */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ +}, +}; + +/* Mono */ +static uint8_t palette0[63+1][3]= +{ + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, + 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, + 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f +}; + +static uint8_t palette1[63+1][3]= +{ + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f +}; + +static uint8_t palette2[63+1][3]= +{ + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f, + 0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a, + 0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f, + 0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a, + 0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f, + 0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f +}; + +static uint8_t palette3[256][3]= +{ + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18, + 0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f, + 0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10, + 0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00, + 0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f, + 0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27, + + 0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f, + 0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f, + 0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31, + 0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d, + 0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f, + 0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07, + 0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00, + 0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c, + + 0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11, + 0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e, + 0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c, + 0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16, + 0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14, + 0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c, + 0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04, + 0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00, + + 0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10, + 0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a, + 0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08, + 0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10, + 0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c, + 0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b, + 0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 +}; + +static uint8_t static_functionality[0x10]= +{ + /* 0 */ 0xff, // All modes supported #1 + /* 1 */ 0xe0, // All modes supported #2 + /* 2 */ 0x0f, // All modes supported #3 + /* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved + /* 7 */ 0x07, // 200, 350, 400 scan lines + /* 8 */ 0x02, // maximum number of visible charsets in text mode + /* 9 */ 0x08, // total number of charset blocks in text mode + /* a */ 0xe7, // Change to add new functions + /* b */ 0x0c, // Change to add new functions + /* c */ 0x00, // reserved + /* d */ 0x00, // reserved + /* e */ 0x00, // Change to add new functions + /* f */ 0x00 // reserved +}; + +#endif /* !VBOX_INCLUDED_SRC_Graphics_BIOS_vgatables_h */ + diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA-cmd.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA-cmd.cpp new file mode 100644 index 00000000..cc4f0f1b --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA-cmd.cpp @@ -0,0 +1,7650 @@ +/* $Id: DevVGA-SVGA-cmd.cpp $ */ +/** @file + * VMware SVGA device - implementation of VMSVGA commands. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef IN_RING3 +# error "DevVGA-SVGA-cmd.cpp is only for ring-3 code" +#endif + + +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include +#include +#include + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +/* Should be included after DevVGA.h/DevVGA-SVGA.h to pick all defines. */ +#ifdef VBOX_WITH_VMSVGA3D +# include "DevVGA-SVGA3d.h" +#endif +#include "DevVGA-SVGA-internal.h" + +#include +#include + +#if defined(LOG_ENABLED) || defined(VBOX_STRICT) +# define SVGA_CASE_ID2STR(idx) case idx: return #idx + +static const char *vmsvgaFifo3dCmdToString(SVGAFifo3dCmdId enmCmdId) +{ + switch (enmCmdId) + { + SVGA_CASE_ID2STR(SVGA_3D_CMD_LEGACY_BASE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DEFINE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DESTROY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_COPY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_STRETCHBLT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DMA); + SVGA_CASE_ID2STR(SVGA_3D_CMD_CONTEXT_DEFINE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_CONTEXT_DESTROY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETTRANSFORM); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETZRANGE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETRENDERSTATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETRENDERTARGET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETTEXTURESTATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETMATERIAL); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETLIGHTDATA); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETLIGHTENABLED); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETVIEWPORT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETCLIPPLANE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_CLEAR); + SVGA_CASE_ID2STR(SVGA_3D_CMD_PRESENT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SHADER_DEFINE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SHADER_DESTROY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_SHADER_CONST); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW_PRIMITIVES); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SETSCISSORRECT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_BEGIN_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_END_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_WAIT_FOR_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_PRESENT_READBACK); + SVGA_CASE_ID2STR(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DEFINE_V2); + SVGA_CASE_ID2STR(SVGA_3D_CMD_GENERATE_MIPMAPS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD4); /* SVGA_3D_CMD_VIDEO_CREATE_DECODER */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD5); /* SVGA_3D_CMD_VIDEO_DESTROY_DECODER */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD6); /* SVGA_3D_CMD_VIDEO_CREATE_PROCESSOR */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD7); /* SVGA_3D_CMD_VIDEO_DESTROY_PROCESSOR */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD8); /* SVGA_3D_CMD_VIDEO_DECODE_START_FRAME */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD9); /* SVGA_3D_CMD_VIDEO_DECODE_RENDER */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD10); /* SVGA_3D_CMD_VIDEO_DECODE_END_FRAME */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD11); /* SVGA_3D_CMD_VIDEO_PROCESS_FRAME */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_ACTIVATE_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEACTIVATE_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SCREEN_DMA); + SVGA_CASE_ID2STR(SVGA_3D_CMD_VB_DX_CLEAR_RENDERTARGET_VIEW_REGION); /* SVGA_3D_CMD_DEAD1 */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD2); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD12); /* Old SVGA_3D_CMD_LOGICOPS_BITBLT */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD13); /* Old SVGA_3D_CMD_LOGICOPS_TRANSBLT */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD14); /* Old SVGA_3D_CMD_LOGICOPS_STRETCHBLT */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD15); /* Old SVGA_3D_CMD_LOGICOPS_COLORFILL */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD16); /* Old SVGA_3D_CMD_LOGICOPS_ALPHABLEND */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD17); /* Old SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND */ + SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_OTABLE_BASE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_OTABLE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_MOB); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_MOB); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD3); + SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_COND_BIND_GB_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_IMAGE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_IMAGE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_IMAGE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_OTABLE_BASE64); + SVGA_CASE_ID2STR(SVGA_3D_CMD_BEGIN_GB_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_END_GB_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_WAIT_FOR_GB_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_NOP); + SVGA_CASE_ID2STR(SVGA_3D_CMD_ENABLE_GART); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DISABLE_GART); + SVGA_CASE_ID2STR(SVGA_3D_CMD_MAP_MOB_INTO_GART); + SVGA_CASE_ID2STR(SVGA_3D_CMD_UNMAP_GART_RANGE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SCREENTARGET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL); + SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_GB_SCREEN_DMA); + SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH); + SVGA_CASE_ID2STR(SVGA_3D_CMD_GB_MOB_FENCE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE_V2); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_MOB64); + SVGA_CASE_ID2STR(SVGA_3D_CMD_REDEFINE_GB_MOB64); + SVGA_CASE_ID2STR(SVGA_3D_CMD_NOP_ERROR); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_STREAMS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_DECLS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_DIVISORS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW_INDEXED); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_INVALIDATE_CONTEXT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER_RESOURCES); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SAMPLERS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INSTANCED); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_AUTO); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_INPUT_LAYOUT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_INDEX_BUFFER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_TOPOLOGY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_RENDERTARGETS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_BLEND_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_RASTERIZER_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_QUERY_OFFSET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BEGIN_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_END_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_PREDICATION); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SOTARGETS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VIEWPORTS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SCISSORRECTS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_COPY_REGION); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_COPY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRESENTBLT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_GENMIPS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_SUBRESOURCE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_BLEND_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_BLEND_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_STREAMOUTPUT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_COTABLE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_COTABLE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BUFFER_COPY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MOVE_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_ALL_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_ALL_QUERY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MOB_FENCE_64); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_ALL_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_HINT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BUFFER_UPDATE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_HS_CONSTANT_BUFFER_OFFSET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_DS_CONSTANT_BUFFER_OFFSET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_CS_CONSTANT_BUFFER_OFFSET); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SCREEN_COPY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED1); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED2); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED3); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED4); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED5); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED6); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED7); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED8); + SVGA_CASE_ID2STR(SVGA_3D_CMD_GROW_OTABLE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_GROW_COTABLE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_INTRA_SURFACE_COPY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE_V3); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESOLVE_COPY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_RESOLVE_COPY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_CONVERT_REGION); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_CONVERT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_WHOLE_SURFACE_COPY); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_UA_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_UA_VIEW); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_UA_VIEWS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DISPATCH); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DISPATCH_INDIRECT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_WRITE_ZERO_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_HINT_ZERO_SURFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_TRANSFER_TO_BUFFER); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_STRUCTURE_COUNT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_BITBLT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_TRANSBLT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_STRETCHBLT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_COLORFILL); + SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_ALPHABLEND); + SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED2_1); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED2_2); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE_V4); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_CS_UA_VIEWS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_MIN_LOD); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED2_3); + SVGA_CASE_ID2STR(SVGA_3D_CMD_RESERVED2_4); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER_IFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_STREAMOUTPUT); + SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_STRETCHBLT_NON_MS_TO_MS); + SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_SHADER_IFACE); + SVGA_CASE_ID2STR(SVGA_3D_CMD_MAX); + SVGA_CASE_ID2STR(SVGA_3D_CMD_FUTURE_MAX); + } + return "UNKNOWN_3D"; +} + +/** + * FIFO command name lookup + * + * @returns FIFO command string or "UNKNOWN" + * @param u32Cmd FIFO command + */ +const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd) +{ + switch (u32Cmd) + { + SVGA_CASE_ID2STR(SVGA_CMD_INVALID_CMD); + SVGA_CASE_ID2STR(SVGA_CMD_UPDATE); + SVGA_CASE_ID2STR(SVGA_CMD_RECT_FILL); + SVGA_CASE_ID2STR(SVGA_CMD_RECT_COPY); + SVGA_CASE_ID2STR(SVGA_CMD_RECT_ROP_COPY); + SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_CURSOR); + SVGA_CASE_ID2STR(SVGA_CMD_DISPLAY_CURSOR); + SVGA_CASE_ID2STR(SVGA_CMD_MOVE_CURSOR); + SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_ALPHA_CURSOR); + SVGA_CASE_ID2STR(SVGA_CMD_UPDATE_VERBOSE); + SVGA_CASE_ID2STR(SVGA_CMD_FRONT_ROP_FILL); + SVGA_CASE_ID2STR(SVGA_CMD_FENCE); + SVGA_CASE_ID2STR(SVGA_CMD_ESCAPE); + SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_SCREEN); + SVGA_CASE_ID2STR(SVGA_CMD_DESTROY_SCREEN); + SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_GMRFB); + SVGA_CASE_ID2STR(SVGA_CMD_BLIT_GMRFB_TO_SCREEN); + SVGA_CASE_ID2STR(SVGA_CMD_BLIT_SCREEN_TO_GMRFB); + SVGA_CASE_ID2STR(SVGA_CMD_ANNOTATION_FILL); + SVGA_CASE_ID2STR(SVGA_CMD_ANNOTATION_COPY); + SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_GMR2); + SVGA_CASE_ID2STR(SVGA_CMD_REMAP_GMR2); + SVGA_CASE_ID2STR(SVGA_CMD_DEAD); + SVGA_CASE_ID2STR(SVGA_CMD_DEAD_2); + SVGA_CASE_ID2STR(SVGA_CMD_NOP); + SVGA_CASE_ID2STR(SVGA_CMD_NOP_ERROR); + SVGA_CASE_ID2STR(SVGA_CMD_MAX); + default: + if ( u32Cmd >= SVGA_3D_CMD_BASE + && u32Cmd < SVGA_3D_CMD_MAX) + return vmsvgaFifo3dCmdToString((SVGAFifo3dCmdId)u32Cmd); + } + return "UNKNOWN"; +} +# undef SVGA_CASE_ID2STR +#endif /* LOG_ENABLED || VBOX_STRICT */ + + +/* + * + * Guest-Backed Objects (GBO). + * + */ + +#ifdef VBOX_WITH_VMSVGA3D + +static int vmsvgaR3GboCreate(PVMSVGAR3STATE pSvgaR3State, SVGAMobFormat ptDepth, PPN64 baseAddress, uint32_t sizeInBytes, PVMSVGAGBO pGbo) +{ + ASSERT_GUEST_RETURN(sizeInBytes <= _128M, VERR_INVALID_PARAMETER); /** @todo Less than SVGA_REG_MOB_MAX_SIZE */ + + /* + * The 'baseAddress' is a page number and points to the 'root page' of the GBO. + * Content of the root page depends on the ptDepth value: + * SVGA3D_MOBFMT_PTDEPTH[64]_0 - the only data page; + * SVGA3D_MOBFMT_PTDEPTH[64]_1 - array of page numbers for data pages; + * SVGA3D_MOBFMT_PTDEPTH[64]_2 - array of page numbers for SVGA3D_MOBFMT_PTDEPTH[64]_1 pages. + * The code below extracts the page addresses of the GBO. + */ + + /* Verify and normalize the ptDepth value. */ + bool fGCPhys64; /* Whether the page table contains 64 bit page numbers. */ + if (RT_LIKELY( ptDepth == SVGA3D_MOBFMT_PTDEPTH64_0 + || ptDepth == SVGA3D_MOBFMT_PTDEPTH64_1 + || ptDepth == SVGA3D_MOBFMT_PTDEPTH64_2)) + fGCPhys64 = true; + else if ( ptDepth == SVGA3D_MOBFMT_PTDEPTH_0 + || ptDepth == SVGA3D_MOBFMT_PTDEPTH_1 + || ptDepth == SVGA3D_MOBFMT_PTDEPTH_2) + { + fGCPhys64 = false; + /* Shift ptDepth to the SVGA3D_MOBFMT_PTDEPTH64_x range. */ + ptDepth = (SVGAMobFormat)(ptDepth + SVGA3D_MOBFMT_PTDEPTH64_0 - SVGA3D_MOBFMT_PTDEPTH_0); + } + else if (ptDepth == SVGA3D_MOBFMT_RANGE) + fGCPhys64 = false; /* Does not matter, there is no page table. */ + else + ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER); + + uint32_t const cPPNsPerPage = X86_PAGE_SIZE / (fGCPhys64 ? sizeof(PPN64) : sizeof(PPN)); + + pGbo->cbTotal = sizeInBytes; + pGbo->cTotalPages = (sizeInBytes + X86_PAGE_SIZE - 1) >> X86_PAGE_SHIFT; + + /* Allocate the maximum amount possible (everything non-continuous) */ + PVMSVGAGBODESCRIPTOR paDescriptors = (PVMSVGAGBODESCRIPTOR)RTMemAlloc(pGbo->cTotalPages * sizeof(VMSVGAGBODESCRIPTOR)); + AssertReturn(paDescriptors, VERR_NO_MEMORY); + + int rc = VINF_SUCCESS; + if (ptDepth == SVGA3D_MOBFMT_PTDEPTH64_0) + { + ASSERT_GUEST_STMT_RETURN(pGbo->cTotalPages == 1, + RTMemFree(paDescriptors), + VERR_INVALID_PARAMETER); + + RTGCPHYS GCPhys = (RTGCPHYS)baseAddress << X86_PAGE_SHIFT; + GCPhys &= UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */ + paDescriptors[0].GCPhys = GCPhys; + paDescriptors[0].cPages = 1; + } + else if (ptDepth == SVGA3D_MOBFMT_PTDEPTH64_1) + { + ASSERT_GUEST_STMT_RETURN(pGbo->cTotalPages <= cPPNsPerPage, + RTMemFree(paDescriptors), + VERR_INVALID_PARAMETER); + + /* Read the root page. */ + uint8_t au8RootPage[X86_PAGE_SIZE]; + RTGCPHYS GCPhys = (RTGCPHYS)baseAddress << X86_PAGE_SHIFT; + rc = PDMDevHlpPCIPhysRead(pSvgaR3State->pDevIns, GCPhys, &au8RootPage, sizeof(au8RootPage)); + if (RT_SUCCESS(rc)) + { + PPN64 *paPPN64 = (PPN64 *)&au8RootPage[0]; + PPN *paPPN32 = (PPN *)&au8RootPage[0]; + for (uint32_t iPPN = 0; iPPN < pGbo->cTotalPages; ++iPPN) + { + GCPhys = (RTGCPHYS)(fGCPhys64 ? paPPN64[iPPN] : paPPN32[iPPN]) << X86_PAGE_SHIFT; + GCPhys &= UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */ + paDescriptors[iPPN].GCPhys = GCPhys; + paDescriptors[iPPN].cPages = 1; + } + } + } + else if (ptDepth == SVGA3D_MOBFMT_PTDEPTH64_2) + { + ASSERT_GUEST_STMT_RETURN(pGbo->cTotalPages <= cPPNsPerPage * cPPNsPerPage, + RTMemFree(paDescriptors), + VERR_INVALID_PARAMETER); + + /* Read the Level2 root page. */ + uint8_t au8RootPageLevel2[X86_PAGE_SIZE]; + RTGCPHYS GCPhys = (RTGCPHYS)baseAddress << X86_PAGE_SHIFT; + rc = PDMDevHlpPCIPhysRead(pSvgaR3State->pDevIns, GCPhys, &au8RootPageLevel2, sizeof(au8RootPageLevel2)); + if (RT_SUCCESS(rc)) + { + uint32_t cPagesLeft = pGbo->cTotalPages; + + PPN64 *paPPN64Level2 = (PPN64 *)&au8RootPageLevel2[0]; + PPN *paPPN32Level2 = (PPN *)&au8RootPageLevel2[0]; + + uint32_t const cPPNsLevel2 = (pGbo->cTotalPages + cPPNsPerPage - 1) / cPPNsPerPage; + for (uint32_t iPPNLevel2 = 0; iPPNLevel2 < cPPNsLevel2; ++iPPNLevel2) + { + /* Read the Level1 root page. */ + uint8_t au8RootPage[X86_PAGE_SIZE]; + RTGCPHYS GCPhysLevel1 = (RTGCPHYS)(fGCPhys64 ? paPPN64Level2[iPPNLevel2] : paPPN32Level2[iPPNLevel2]) << X86_PAGE_SHIFT; + GCPhys &= UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */ + rc = PDMDevHlpPCIPhysRead(pSvgaR3State->pDevIns, GCPhysLevel1, &au8RootPage, sizeof(au8RootPage)); + if (RT_SUCCESS(rc)) + { + PPN64 *paPPN64 = (PPN64 *)&au8RootPage[0]; + PPN *paPPN32 = (PPN *)&au8RootPage[0]; + + uint32_t const cPPNs = RT_MIN(cPagesLeft, cPPNsPerPage); + for (uint32_t iPPN = 0; iPPN < cPPNs; ++iPPN) + { + GCPhys = (RTGCPHYS)(fGCPhys64 ? paPPN64[iPPN] : paPPN32[iPPN]) << X86_PAGE_SHIFT; + GCPhys &= UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */ + paDescriptors[iPPN + iPPNLevel2 * cPPNsPerPage].GCPhys = GCPhys; + paDescriptors[iPPN + iPPNLevel2 * cPPNsPerPage].cPages = 1; + } + cPagesLeft -= cPPNs; + } + } + } + } + else if (ptDepth == SVGA3D_MOBFMT_RANGE) + { + RTGCPHYS GCPhys = (RTGCPHYS)baseAddress << X86_PAGE_SHIFT; + GCPhys &= UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */ + paDescriptors[0].GCPhys = GCPhys; + paDescriptors[0].cPages = pGbo->cTotalPages; + } + else + { + AssertFailed(); + return VERR_INTERNAL_ERROR; /* ptDepth should be already verified. */ + } + + /* Compress the descriptors. */ + if (ptDepth != SVGA3D_MOBFMT_RANGE) + { + uint32_t iDescriptor = 0; + for (uint32_t i = 1; i < pGbo->cTotalPages; ++i) + { + /* Continuous physical memory? */ + if (paDescriptors[i].GCPhys == paDescriptors[iDescriptor].GCPhys + paDescriptors[iDescriptor].cPages * X86_PAGE_SIZE) + { + Assert(paDescriptors[iDescriptor].cPages); + paDescriptors[iDescriptor].cPages++; + Log5Func(("Page %x GCPhys=%RGp successor\n", i, paDescriptors[i].GCPhys)); + } + else + { + iDescriptor++; + paDescriptors[iDescriptor].GCPhys = paDescriptors[i].GCPhys; + paDescriptors[iDescriptor].cPages = 1; + Log5Func(("Page %x GCPhys=%RGp\n", i, paDescriptors[iDescriptor].GCPhys)); + } + } + + pGbo->cDescriptors = iDescriptor + 1; + Log5Func(("Nr of descriptors %d\n", pGbo->cDescriptors)); + } + else + pGbo->cDescriptors = 1; + + if (RT_LIKELY(pGbo->cDescriptors < pGbo->cTotalPages)) + { + pGbo->paDescriptors = (PVMSVGAGBODESCRIPTOR)RTMemRealloc(paDescriptors, pGbo->cDescriptors * sizeof(VMSVGAGBODESCRIPTOR)); + AssertReturn(pGbo->paDescriptors, VERR_NO_MEMORY); + } + else + pGbo->paDescriptors = paDescriptors; + + pGbo->fGboFlags = 0; + pGbo->pvHost = NULL; + + return VINF_SUCCESS; +} + + +static void vmsvgaR3GboDestroy(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo) +{ + RT_NOREF(pSvgaR3State); + + if (RT_LIKELY(VMSVGA_IS_GBO_CREATED(pGbo))) + { + RTMemFree(pGbo->pvHost); + RTMemFree(pGbo->paDescriptors); + RT_ZERO(*pGbo); + } +} + +/** @todo static void vmsvgaR3GboWriteProtect(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo, bool fWriteProtect) */ + +typedef enum VMSVGAGboTransferDirection +{ + VMSVGAGboTransferDirection_Read, + VMSVGAGboTransferDirection_Write, +} VMSVGAGboTransferDirection; + +static int vmsvgaR3GboTransfer(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo, + uint32_t off, void *pvData, uint32_t cbData, + VMSVGAGboTransferDirection enmDirection) +{ + //DEBUG_BREAKPOINT_TEST(); + int rc = VINF_SUCCESS; + uint8_t *pu8CurrentHost = (uint8_t *)pvData; + + /* Find the right descriptor */ + PCVMSVGAGBODESCRIPTOR const paDescriptors = pGbo->paDescriptors; + uint32_t iDescriptor = 0; /* Index in the descriptor array. */ + uint32_t offDescriptor = 0; /* GMR offset of the current descriptor. */ + while (offDescriptor + paDescriptors[iDescriptor].cPages * X86_PAGE_SIZE <= off) + { + offDescriptor += paDescriptors[iDescriptor].cPages * X86_PAGE_SIZE; + AssertReturn(offDescriptor < pGbo->cbTotal, VERR_INTERNAL_ERROR); /* overflow protection */ + ++iDescriptor; + AssertReturn(iDescriptor < pGbo->cDescriptors, VERR_INTERNAL_ERROR); + } + + while (cbData) + { + uint32_t cbToCopy; + if (off + cbData <= offDescriptor + paDescriptors[iDescriptor].cPages * X86_PAGE_SIZE) + cbToCopy = cbData; + else + { + cbToCopy = (offDescriptor + paDescriptors[iDescriptor].cPages * X86_PAGE_SIZE - off); + AssertReturn(cbToCopy <= cbData, VERR_INVALID_PARAMETER); + } + + RTGCPHYS const GCPhys = paDescriptors[iDescriptor].GCPhys + off - offDescriptor; + Log5Func(("%s phys=%RGp\n", (enmDirection == VMSVGAGboTransferDirection_Read) ? "READ" : "WRITE", GCPhys)); + + /* + * We are deliberately using the non-PCI version of PDMDevHlpPCIPhys[Read|Write] as the + * guest-side VMSVGA driver seems to allocate non-DMA (regular physical) addresses, + * see @bugref{9654#c75}. + */ + if (enmDirection == VMSVGAGboTransferDirection_Read) + rc = PDMDevHlpPhysRead(pSvgaR3State->pDevIns, GCPhys, pu8CurrentHost, cbToCopy); + else + rc = PDMDevHlpPhysWrite(pSvgaR3State->pDevIns, GCPhys, pu8CurrentHost, cbToCopy); + AssertRCBreak(rc); + + cbData -= cbToCopy; + off += cbToCopy; + pu8CurrentHost += cbToCopy; + + /* Go to the next descriptor if there's anything left. */ + if (cbData) + { + offDescriptor += paDescriptors[iDescriptor].cPages * X86_PAGE_SIZE; + AssertReturn(offDescriptor < pGbo->cbTotal, VERR_INTERNAL_ERROR); + ++iDescriptor; + AssertReturn(iDescriptor < pGbo->cDescriptors, VERR_INTERNAL_ERROR); + } + } + return rc; +} + + +static int vmsvgaR3GboWrite(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo, + uint32_t off, void const *pvData, uint32_t cbData) +{ + return vmsvgaR3GboTransfer(pSvgaR3State, pGbo, + off, (void *)pvData, cbData, + VMSVGAGboTransferDirection_Write); +} + + +static int vmsvgaR3GboRead(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo, + uint32_t off, void *pvData, uint32_t cbData) +{ + return vmsvgaR3GboTransfer(pSvgaR3State, pGbo, + off, pvData, cbData, + VMSVGAGboTransferDirection_Read); +} + + +static int vmsvgaR3GboBackingStoreCreate(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo, uint32_t cbValid) +{ + int rc; + + /* Just reread the data if pvHost has been allocated already. */ + if (!(pGbo->fGboFlags & VMSVGAGBO_F_HOST_BACKED)) + pGbo->pvHost = RTMemAllocZ(pGbo->cbTotal); + + if (pGbo->pvHost) + { + cbValid = RT_MIN(cbValid, pGbo->cbTotal); + rc = vmsvgaR3GboRead(pSvgaR3State, pGbo, 0, pGbo->pvHost, cbValid); + } + else + rc = VERR_NO_MEMORY; + + if (RT_SUCCESS(rc)) + pGbo->fGboFlags |= VMSVGAGBO_F_HOST_BACKED; + else + { + RTMemFree(pGbo->pvHost); + pGbo->pvHost = NULL; + } + return rc; +} + + +static void vmsvgaR3GboBackingStoreDelete(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo) +{ + RT_NOREF(pSvgaR3State); + AssertReturnVoid(pGbo->fGboFlags & VMSVGAGBO_F_HOST_BACKED); + RTMemFree(pGbo->pvHost); + pGbo->pvHost = NULL; + pGbo->fGboFlags &= ~VMSVGAGBO_F_HOST_BACKED; +} + + +static int vmsvgaR3GboBackingStoreWriteToGuest(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo) +{ + AssertReturn(pGbo->fGboFlags & VMSVGAGBO_F_HOST_BACKED, VERR_INVALID_STATE); + return vmsvgaR3GboWrite(pSvgaR3State, pGbo, 0, pGbo->pvHost, pGbo->cbTotal); +} + + +static int vmsvgaR3GboBackingStoreReadFromGuest(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGbo) +{ + AssertReturn(pGbo->fGboFlags & VMSVGAGBO_F_HOST_BACKED, VERR_INVALID_STATE); + return vmsvgaR3GboRead(pSvgaR3State, pGbo, 0, pGbo->pvHost, pGbo->cbTotal); +} + +static int vmsvgaR3GboCopy(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGboDst, uint32_t offDst, + PVMSVGAGBO pGboSrc, uint32_t offSrc, uint32_t cbCopy) +{ + uint32_t const cbTmpBuf = GUEST_PAGE_SIZE; + void *pvTmpBuf = RTMemTmpAlloc(cbTmpBuf); + AssertPtrReturn(pvTmpBuf, VERR_NO_MEMORY); + + int rc = VINF_SUCCESS; + while (cbCopy > 0) + { + uint32_t const cbToCopy = RT_MIN(cbTmpBuf, cbCopy); + + rc = vmsvgaR3GboRead(pSvgaR3State, pGboSrc, offSrc, pvTmpBuf, cbToCopy); + AssertRCBreak(rc); + + rc = vmsvgaR3GboWrite(pSvgaR3State, pGboDst, offDst, pvTmpBuf, cbToCopy); + AssertRCBreak(rc); + + offSrc += cbToCopy; + offDst += cbToCopy; + cbCopy -= cbToCopy; + } + + RTMemTmpFree(pvTmpBuf); + return rc; +} + + +/* + * + * Object Tables. + * + */ + +static int vmsvgaR3OTableSetOrGrow(PVMSVGAR3STATE pSvgaR3State, SVGAOTableType type, PPN64 baseAddress, + uint32_t sizeInBytes, uint32 validSizeInBytes, SVGAMobFormat ptDepth, bool fGrow) +{ + ASSERT_GUEST_RETURN(type < RT_ELEMENTS(pSvgaR3State->aGboOTables), VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(sizeInBytes >= validSizeInBytes, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + ASSERT_GUEST_RETURN(pSvgaR3State->aGboOTables[type].cbTotal >= validSizeInBytes, VERR_INVALID_PARAMETER); + + if (sizeInBytes > 0) + { + /* Create a new guest backed object for the object table. */ + VMSVGAGBO gbo; + int rc = vmsvgaR3GboCreate(pSvgaR3State, ptDepth, baseAddress, sizeInBytes, &gbo); + AssertRCReturn(rc, rc); + + /* If the guest sets a new OTable (fGrow == false), then it has already copied the valid data to the new GBO. */ + if (fGrow && validSizeInBytes) + { + /* Copy data from old gbo to the new one. */ + rc = vmsvgaR3GboCopy(pSvgaR3State, &gbo, 0, &pSvgaR3State->aGboOTables[type], 0, validSizeInBytes); + AssertRCReturnStmt(rc, vmsvgaR3GboDestroy(pSvgaR3State, &gbo), rc); + } + + vmsvgaR3GboDestroy(pSvgaR3State, &pSvgaR3State->aGboOTables[type]); + pSvgaR3State->aGboOTables[type] = gbo; + + } + else + vmsvgaR3GboDestroy(pSvgaR3State, &pSvgaR3State->aGboOTables[type]); + + return VINF_SUCCESS; +} + + +static int vmsvgaR3OTableVerifyIndex(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGboOTable, + uint32_t idx, uint32_t cbEntry) +{ + RT_NOREF(pSvgaR3State); + + /* The table must exist and the index must be within the table. */ + ASSERT_GUEST_RETURN(VMSVGA_IS_GBO_CREATED(pGboOTable), VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(idx < pGboOTable->cbTotal / cbEntry, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + return VINF_SUCCESS; +} + + +static int vmsvgaR3OTableRead(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGboOTable, + uint32_t idx, uint32_t cbEntry, + void *pvData, uint32_t cbData) +{ + AssertReturn(cbData <= cbEntry, VERR_INVALID_PARAMETER); + + int rc = vmsvgaR3OTableVerifyIndex(pSvgaR3State, pGboOTable, idx, cbEntry); + if (RT_SUCCESS(rc)) + { + uint32_t const off = idx * cbEntry; + rc = vmsvgaR3GboRead(pSvgaR3State, pGboOTable, off, pvData, cbData); + } + return rc; +} + +static int vmsvgaR3OTableWrite(PVMSVGAR3STATE pSvgaR3State, PVMSVGAGBO pGboOTable, + uint32_t idx, uint32_t cbEntry, + void const *pvData, uint32_t cbData) +{ + AssertReturn(cbData <= cbEntry, VERR_INVALID_PARAMETER); + + int rc = vmsvgaR3OTableVerifyIndex(pSvgaR3State, pGboOTable, idx, cbEntry); + if (RT_SUCCESS(rc)) + { + uint32_t const off = idx * cbEntry; + rc = vmsvgaR3GboWrite(pSvgaR3State, pGboOTable, off, pvData, cbData); + } + return rc; +} + + +int vmsvgaR3OTableReadSurface(PVMSVGAR3STATE pSvgaR3State, uint32_t sid, SVGAOTableSurfaceEntry *pEntrySurface) +{ + return vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, pEntrySurface, sizeof(SVGAOTableSurfaceEntry)); +} + + +/* + * + * The guest's Memory OBjects (MOB). + * + */ + +static int vmsvgaR3MobCreate(PVMSVGAR3STATE pSvgaR3State, + SVGAMobFormat ptDepth, PPN64 baseAddress, uint32_t sizeInBytes, SVGAMobId mobid, + PVMSVGAMOB pMob) +{ + RT_ZERO(*pMob); + + /* Update the entry in the pSvgaR3State->pGboOTableMob. */ + SVGAOTableMobEntry entry; + entry.ptDepth = ptDepth; + entry.sizeInBytes = sizeInBytes; + entry.base = baseAddress; + int rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_MOB], + mobid, SVGA3D_OTABLE_MOB_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* Create the corresponding GBO. */ + rc = vmsvgaR3GboCreate(pSvgaR3State, ptDepth, baseAddress, sizeInBytes, &pMob->Gbo); + if (RT_SUCCESS(rc)) + { + /* If a mob with this id already exists, then delete it. */ + PVMSVGAMOB pOldMob = (PVMSVGAMOB)RTAvlU32Remove(&pSvgaR3State->MOBTree, mobid); + if (pOldMob) + { + /* This should not happen. */ + ASSERT_GUEST_FAILED(); + RTListNodeRemove(&pOldMob->nodeLRU); + vmsvgaR3GboDestroy(pSvgaR3State, &pOldMob->Gbo); + RTMemFree(pOldMob); + } + + /* Add to the tree of known MOBs and the LRU list. */ + pMob->Core.Key = mobid; + if (RTAvlU32Insert(&pSvgaR3State->MOBTree, &pMob->Core)) + { + RTListPrepend(&pSvgaR3State->MOBLRUList, &pMob->nodeLRU); + return VINF_SUCCESS; + } + + AssertFailedStmt(rc = VERR_INVALID_STATE); + vmsvgaR3GboDestroy(pSvgaR3State, &pMob->Gbo); + } + } + + return rc; +} + + +static void vmsvgaR3MobFree(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob) +{ + vmsvgaR3GboDestroy(pSvgaR3State, &pMob->Gbo); + RTMemFree(pMob); +} + + +static int vmsvgaR3MobDestroy(PVMSVGAR3STATE pSvgaR3State, SVGAMobId mobid) +{ + /* Update the entry in the pSvgaR3State->pGboOTableMob. */ + SVGAOTableMobEntry entry; + RT_ZERO(entry); + vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_MOB], + mobid, SVGA3D_OTABLE_MOB_ENTRY_SIZE, &entry, sizeof(entry)); + + PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Remove(&pSvgaR3State->MOBTree, mobid); + if (pMob) + { + RTListNodeRemove(&pMob->nodeLRU); + vmsvgaR3MobFree(pSvgaR3State, pMob); + return VINF_SUCCESS; + } + + return VERR_INVALID_PARAMETER; +} + + +PVMSVGAMOB vmsvgaR3MobGet(PVMSVGAR3STATE pSvgaR3State, SVGAMobId RT_UNTRUSTED_GUEST mobid) +{ + if (mobid == SVGA_ID_INVALID) + return NULL; + + PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Get(&pSvgaR3State->MOBTree, mobid); + if (pMob) + { + /* Move to the head of the LRU list. */ + RTListNodeRemove(&pMob->nodeLRU); + RTListPrepend(&pSvgaR3State->MOBLRUList, &pMob->nodeLRU); + } + else + ASSERT_GUEST_FAILED(); + + return pMob; +} + + +int vmsvgaR3MobWrite(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob, + uint32_t off, void const *pvData, uint32_t cbData) +{ + return vmsvgaR3GboWrite(pSvgaR3State, &pMob->Gbo, off, pvData, cbData); +} + + +int vmsvgaR3MobRead(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob, + uint32_t off, void *pvData, uint32_t cbData) +{ + return vmsvgaR3GboWrite(pSvgaR3State, &pMob->Gbo, off, pvData, cbData); +} + + +/** Create a host ring-3 pointer to the MOB data. + * Current approach is to allocate a host memory buffer and copy the guest MOB data if necessary. + * @param pSvgaR3State R3 device state. + * @param pMob The MOB. + * @param cbValid How many bytes of the guest backing memory contain valid data. + * @return VBox status. + */ +/** @todo uint32_t cbValid -> uint32_t offStart, uint32_t cbData */ +int vmsvgaR3MobBackingStoreCreate(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob, uint32_t cbValid) +{ + AssertReturn(pMob, VERR_INVALID_PARAMETER); + return vmsvgaR3GboBackingStoreCreate(pSvgaR3State, &pMob->Gbo, cbValid); +} + + +void vmsvgaR3MobBackingStoreDelete(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob) +{ + if (pMob) + vmsvgaR3GboBackingStoreDelete(pSvgaR3State, &pMob->Gbo); +} + + +int vmsvgaR3MobBackingStoreWriteToGuest(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob) +{ + if (pMob) + return vmsvgaR3GboBackingStoreWriteToGuest(pSvgaR3State, &pMob->Gbo); + return VERR_INVALID_PARAMETER; +} + + +int vmsvgaR3MobBackingStoreReadFromGuest(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob) +{ + if (pMob) + return vmsvgaR3GboBackingStoreReadFromGuest(pSvgaR3State, &pMob->Gbo); + return VERR_INVALID_PARAMETER; +} + + +void *vmsvgaR3MobBackingStorePtr(PVMSVGAMOB pMob, uint32_t off) +{ + if (pMob && (pMob->Gbo.fGboFlags & VMSVGAGBO_F_HOST_BACKED)) + { + if (off <= pMob->Gbo.cbTotal) + return (uint8_t *)pMob->Gbo.pvHost + off; + } + return NULL; +} + + +static DECLCALLBACK(int) vmsvgaR3MobFreeCb(PAVLU32NODECORE pNode, void *pvUser) +{ + PVMSVGAMOB pMob = (PVMSVGAMOB)pNode; + PVMSVGAR3STATE pSvgaR3State = (PVMSVGAR3STATE)pvUser; + vmsvgaR3MobFree(pSvgaR3State, pMob); + return 0; +} + + +#endif /* VBOX_WITH_VMSVGA3D */ + + + +void vmsvgaR3ResetSvgaState(PVGASTATE pThis, PVGASTATECC pThisCC) +{ +#ifdef VBOX_WITH_VMSVGA3D + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pThis); + + RTAvlU32Destroy(&pSvgaR3State->MOBTree, vmsvgaR3MobFreeCb, pSvgaR3State); + RTListInit(&pSvgaR3State->MOBLRUList); + + for (unsigned i = 0; i < RT_ELEMENTS(pSvgaR3State->aGboOTables); ++i) + vmsvgaR3GboDestroy(pSvgaR3State, &pSvgaR3State->aGboOTables[i]); +#else + RT_NOREF(pThis, pThisCC); +#endif +} + + +void vmsvgaR3TerminateSvgaState(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + vmsvgaR3ResetSvgaState(pThis, pThisCC); +} + + +/* + * Screen objects. + */ +VMSVGASCREENOBJECT *vmsvgaR3GetScreenObject(PVGASTATECC pThisCC, uint32_t idScreen) +{ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + if ( idScreen < (uint32_t)RT_ELEMENTS(pSVGAState->aScreens) + && pSVGAState + && pSVGAState->aScreens[idScreen].fDefined) + { + Assert(pSVGAState->aScreens[idScreen].idScreen == idScreen); + return &pSVGAState->aScreens[idScreen]; + } + return NULL; +} + + +int vmsvgaR3DestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + pScreen->fModified = true; + pScreen->fDefined = false; + + /* Notify frontend that the screen is about to be deleted. */ + vmsvgaR3ChangeMode(pThis, pThisCC); + +#ifdef VBOX_WITH_VMSVGA3D + if (RT_LIKELY(pThis->svga.f3DEnabled)) + vmsvga3dDestroyScreen(pThisCC, pScreen); +#endif + + RTMemFree(pScreen->pvScreenBitmap); + pScreen->pvScreenBitmap = NULL; + + return VINF_SUCCESS; +} + + +void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + for (uint32_t idScreen = 0; idScreen < (uint32_t)RT_ELEMENTS(pThisCC->svga.pSvgaR3State->aScreens); ++idScreen) + { + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen); + if (pScreen) + vmsvgaR3DestroyScreen(pThis, pThisCC, pScreen); + } +} + + +/** + * Copy a rectangle of pixels within guest VRAM. + */ +static void vmsvgaR3RectCopy(PVGASTATECC pThisCC, VMSVGASCREENOBJECT const *pScreen, uint32_t srcX, uint32_t srcY, + uint32_t dstX, uint32_t dstY, uint32_t width, uint32_t height, unsigned cbFrameBuffer) +{ + if (!width || !height) + return; /* Nothing to do, don't even bother. */ + + /* + * The guest VRAM (aka GFB) is considered to be a bitmap in the format + * corresponding to the current display mode. + */ + uint32_t const cbPixel = RT_ALIGN(pScreen->cBpp, 8) / 8; + uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch : width * cbPixel; + uint8_t const *pSrc; + uint8_t *pDst; + unsigned const cbRectWidth = width * cbPixel; + unsigned uMaxOffset; + + uMaxOffset = (RT_MAX(srcY, dstY) + height) * cbScanline + (RT_MAX(srcX, dstX) + width) * cbPixel; + if (uMaxOffset >= cbFrameBuffer) + { + Log(("Max offset (%u) too big for framebuffer (%u bytes), ignoring!\n", uMaxOffset, cbFrameBuffer)); + return; /* Just don't listen to a bad guest. */ + } + + pSrc = pDst = pThisCC->pbVRam; + pSrc += srcY * cbScanline + srcX * cbPixel; + pDst += dstY * cbScanline + dstX * cbPixel; + + if (srcY >= dstY) + { + /* Source below destination, copy top to bottom. */ + for (; height > 0; height--) + { + memmove(pDst, pSrc, cbRectWidth); + pSrc += cbScanline; + pDst += cbScanline; + } + } + else + { + /* Source above destination, copy bottom to top. */ + pSrc += cbScanline * (height - 1); + pDst += cbScanline * (height - 1); + for (; height > 0; height--) + { + memmove(pDst, pSrc, cbRectWidth); + pSrc -= cbScanline; + pDst -= cbScanline; + } + } +} + + +/** + * Common worker for changing the pointer shape. + * + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pSVGAState The VMSVGA ring-3 instance data. + * @param fAlpha Whether there is alpha or not. + * @param xHot Hotspot x coordinate. + * @param yHot Hotspot y coordinate. + * @param cx Width. + * @param cy Height. + * @param pbData Heap copy of the cursor data. Consumed. + * @param cbData The size of the data. + */ +static void vmsvgaR3InstallNewCursor(PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, bool fAlpha, + uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy, uint8_t *pbData, uint32_t cbData) +{ + LogRel2(("vmsvgaR3InstallNewCursor: cx=%d cy=%d xHot=%d yHot=%d fAlpha=%d cbData=%#x\n", cx, cy, xHot, yHot, fAlpha, cbData)); +#ifdef LOG_ENABLED + if (LogIs2Enabled()) + { + uint32_t cbAndLine = RT_ALIGN(cx, 8) / 8; + if (!fAlpha) + { + Log2(("VMSVGA Cursor AND mask (%d,%d):\n", cx, cy)); + for (uint32_t y = 0; y < cy; y++) + { + Log2(("%3u:", y)); + uint8_t const *pbLine = &pbData[y * cbAndLine]; + for (uint32_t x = 0; x < cx; x += 8) + { + uint8_t b = pbLine[x / 8]; + char szByte[12]; + szByte[0] = b & 0x80 ? '*' : ' '; /* most significant bit first */ + szByte[1] = b & 0x40 ? '*' : ' '; + szByte[2] = b & 0x20 ? '*' : ' '; + szByte[3] = b & 0x10 ? '*' : ' '; + szByte[4] = b & 0x08 ? '*' : ' '; + szByte[5] = b & 0x04 ? '*' : ' '; + szByte[6] = b & 0x02 ? '*' : ' '; + szByte[7] = b & 0x01 ? '*' : ' '; + szByte[8] = '\0'; + Log2(("%s", szByte)); + } + Log2(("\n")); + } + } + + Log2(("VMSVGA Cursor XOR mask (%d,%d):\n", cx, cy)); + uint32_t const *pu32Xor = (uint32_t const *)&pbData[RT_ALIGN_32(cbAndLine * cy, 4)]; + for (uint32_t y = 0; y < cy; y++) + { + Log2(("%3u:", y)); + uint32_t const *pu32Line = &pu32Xor[y * cx]; + for (uint32_t x = 0; x < cx; x++) + Log2((" %08x", pu32Line[x])); + Log2(("\n")); + } + } +#endif + + int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, fAlpha, xHot, yHot, cx, cy, pbData); + AssertRC(rc); + + if (pSVGAState->Cursor.fActive) + RTMemFreeZ(pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData); + + pSVGAState->Cursor.fActive = true; + pSVGAState->Cursor.xHotspot = xHot; + pSVGAState->Cursor.yHotspot = yHot; + pSVGAState->Cursor.width = cx; + pSVGAState->Cursor.height = cy; + pSVGAState->Cursor.cbData = cbData; + pSVGAState->Cursor.pData = pbData; +} + + +#ifdef VBOX_WITH_VMSVGA3D + +/* + * SVGA_3D_CMD_* handlers. + */ + + +/** SVGA_3D_CMD_SURFACE_DEFINE 1040, SVGA_3D_CMD_SURFACE_DEFINE_V2 1070 + * + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param pCmd The VMSVGA command. + * @param cMipLevelSizes Number of elements in the paMipLevelSizes array. + * @param paMipLevelSizes Arrays of surface sizes for each face and miplevel. + */ +static void vmsvga3dCmdDefineSurface(PVGASTATECC pThisCC, SVGA3dCmdDefineSurface_v2 const *pCmd, + uint32_t cMipLevelSizes, SVGA3dSize *paMipLevelSizes) +{ + ASSERT_GUEST_RETURN_VOID(pCmd->sid < SVGA3D_MAX_SURFACE_IDS); + ASSERT_GUEST_RETURN_VOID(cMipLevelSizes >= 1); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Number of faces (cFaces) is specified as the number of the first non-zero elements in the 'face' array. + * Since only plain surfaces (cFaces == 1) and cubemaps (cFaces == 6) are supported + * (see also SVGA3dCmdDefineSurface definition in svga3d_reg.h), we ignore anything else. + */ + uint32_t cRemainingMipLevels = cMipLevelSizes; + uint32_t cFaces = 0; + for (uint32_t i = 0; i < SVGA3D_MAX_SURFACE_FACES; ++i) + { + if (pCmd->face[i].numMipLevels == 0) + break; + + /* All SVGA3dSurfaceFace structures must have the same value of numMipLevels field */ + ASSERT_GUEST_RETURN_VOID(pCmd->face[i].numMipLevels == pCmd->face[0].numMipLevels); + + /* numMipLevels value can't be greater than the number of remaining elements in the paMipLevelSizes array. */ + ASSERT_GUEST_RETURN_VOID(pCmd->face[i].numMipLevels <= cRemainingMipLevels); + cRemainingMipLevels -= pCmd->face[i].numMipLevels; + + ++cFaces; + } + for (uint32_t i = cFaces; i < SVGA3D_MAX_SURFACE_FACES; ++i) + ASSERT_GUEST_RETURN_VOID(pCmd->face[i].numMipLevels == 0); + + /* cFaces must be 6 for a cubemap and 1 otherwise. */ + ASSERT_GUEST_RETURN_VOID(cFaces == (uint32_t)((pCmd->surfaceFlags & SVGA3D_SURFACE_CUBEMAP) ? 6 : 1)); + + /* Sum of face[i].numMipLevels must be equal to cMipLevels. */ + ASSERT_GUEST_RETURN_VOID(cRemainingMipLevels == 0); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Verify paMipLevelSizes */ + uint32_t cWidth = paMipLevelSizes[0].width; + uint32_t cHeight = paMipLevelSizes[0].height; + uint32_t cDepth = paMipLevelSizes[0].depth; + for (uint32_t i = 1; i < pCmd->face[0].numMipLevels; ++i) + { + cWidth >>= 1; + if (cWidth == 0) cWidth = 1; + cHeight >>= 1; + if (cHeight == 0) cHeight = 1; + cDepth >>= 1; + if (cDepth == 0) cDepth = 1; + for (uint32_t iFace = 0; iFace < cFaces; ++iFace) + { + uint32_t const iMipLevelSize = iFace * pCmd->face[0].numMipLevels + i; + ASSERT_GUEST_RETURN_VOID( cWidth == paMipLevelSizes[iMipLevelSize].width + && cHeight == paMipLevelSizes[iMipLevelSize].height + && cDepth == paMipLevelSizes[iMipLevelSize].depth); + } + } + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Create the surface. */ + vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, pCmd->surfaceFlags, pCmd->format, + pCmd->multisampleCount, pCmd->autogenFilter, + pCmd->face[0].numMipLevels, &paMipLevelSizes[0], /* arraySize = */ 0, /* fAllocMipLevels = */ true); +} + + +/* SVGA_3D_CMD_SET_OTABLE_BASE 1091 */ +static void vmsvga3dCmdSetOTableBase(PVGASTATECC pThisCC, SVGA3dCmdSetOTableBase const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + vmsvgaR3OTableSetOrGrow(pSvgaR3State, pCmd->type, pCmd->baseAddress, + pCmd->sizeInBytes, pCmd->validSizeInBytes, pCmd->ptDepth, /*fGrow*/ false); +} + + +/* SVGA_3D_CMD_DEFINE_GB_MOB 1093 */ +static void vmsvga3dCmdDefineGBMob(PVGASTATECC pThisCC, SVGA3dCmdDefineGBMob const *pCmd) +{ + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + ASSERT_GUEST_RETURN_VOID(pCmd->mobid != SVGA_ID_INVALID); /* The guest should not use this id. */ + + /* Maybe just update the OTable and create Gbo when the MOB is actually accessed? */ + /* Allocate a structure for the MOB. */ + PVMSVGAMOB pMob = (PVMSVGAMOB)RTMemAllocZ(sizeof(*pMob)); + AssertPtrReturnVoid(pMob); + + int rc = vmsvgaR3MobCreate(pSvgaR3State, pCmd->ptDepth, pCmd->base, pCmd->sizeInBytes, pCmd->mobid, pMob); + if (RT_SUCCESS(rc)) + { + return; + } + + AssertFailed(); + + RTMemFree(pMob); +} + + +/* SVGA_3D_CMD_DESTROY_GB_MOB 1094 */ +static void vmsvga3dCmdDestroyGBMob(PVGASTATECC pThisCC, SVGA3dCmdDestroyGBMob const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + ASSERT_GUEST_RETURN_VOID(pCmd->mobid != SVGA_ID_INVALID); /* The guest should not use this id. */ + + int rc = vmsvgaR3MobDestroy(pSvgaR3State, pCmd->mobid); + if (RT_SUCCESS(rc)) + { + return; + } + + AssertFailed(); +} + + +/* SVGA_3D_CMD_DEFINE_GB_SURFACE 1097 */ +static void vmsvga3dCmdDefineGBSurface(PVGASTATECC pThisCC, SVGA3dCmdDefineGBSurface const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Update the entry in the pSvgaR3State->pGboOTableSurface. */ + SVGAOTableSurfaceEntry entry; + RT_ZERO(entry); + entry.format = pCmd->format; + entry.surface1Flags = pCmd->surfaceFlags; + entry.numMipLevels = pCmd->numMipLevels; + entry.multisampleCount = pCmd->multisampleCount; + entry.autogenFilter = pCmd->autogenFilter; + entry.size = pCmd->size; + entry.mobid = SVGA_ID_INVALID; + // entry.arraySize = 0; + // entry.mobPitch = 0; + int rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* Create the host surface. */ + vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, pCmd->surfaceFlags, pCmd->format, + pCmd->multisampleCount, pCmd->autogenFilter, + pCmd->numMipLevels, &pCmd->size, /* arraySize = */ 0, /* fAllocMipLevels = */ false); + } +} + + +/* SVGA_3D_CMD_DESTROY_GB_SURFACE 1098 */ +static void vmsvga3dCmdDestroyGBSurface(PVGASTATECC pThisCC, SVGA3dCmdDestroyGBSurface const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Update the entry in the pSvgaR3State->pGboOTableSurface. */ + SVGAOTableSurfaceEntry entry; + RT_ZERO(entry); + entry.mobid = SVGA_ID_INVALID; + vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entry, sizeof(entry)); + + vmsvga3dSurfaceDestroy(pThisCC, pCmd->sid); +} + + +/* SVGA_3D_CMD_BIND_GB_SURFACE 1099 */ +static void vmsvga3dCmdBindGBSurface(PVGASTATECC pThisCC, SVGA3dCmdBindGBSurface const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Assign the mobid to the surface. */ + int rc = VINF_SUCCESS; + if (pCmd->mobid != SVGA_ID_INVALID) + rc = vmsvgaR3OTableVerifyIndex(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_MOB], + pCmd->mobid, SVGA3D_OTABLE_MOB_ENTRY_SIZE); + if (RT_SUCCESS(rc)) + { + SVGAOTableSurfaceEntry entry; + rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + entry.mobid = pCmd->mobid; + rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* */ + } + } + } +} + + +typedef union +{ + float f; + uint32_t u; +} Unsigned2Float; + +float float16ToFloat(uint16_t f16) +{ + /* Format specs from Wiki: [15] = sign, [14:10] = exponent, [9:0] = fraction */ + uint16_t const f = f16 & 0x3FF; + uint16_t const e = (f16 >> 10) & 0x1F; + uint16_t const s = (f16 >> 15) & 0x1; + Unsigned2Float u2f; + + if (e == 0) + { + if (f == 0) + { + /* zero, -0 */ + u2f.u = (s << 31) | (0 << 23) | 0; + return u2f.f; + } + + /* subnormal numbers: (-1)^signbit * 2^-14 * 0.significantbits */ + float const k = 1.0f / 16384.0f; /* 2^-14 */ + return (s ? -1.0f : 1.0f) * k * (float)f / 1024.0f; + } + + if (e == 31) + { + if (f == 0) + { + /* +-infinity */ + u2f.u = (s << 31) | (0xFF << 23) | 0; + return u2f.f; + } + + /* NaN */ + u2f.u = (s << 31) | (0xFF << 23) | 1; + return u2f.f; + } + + /* normalized value: (-1)^signbit * 2^(exponent - 15) * 1.significantbits */ + /* Build the float, adjusting for exponent bias (float32 bias is 127, float16 is 15) + * and number of bits in the fraction (float32 has 23, float16 has 10). */ + u2f.u = (s << 31) | ((e + 127 - 15) << 23) | (f << (23 - 10)); + return u2f.f; +} + + +static int vmsvga3dBmpWrite(const char *pszFilename, VMSVGA3D_MAPPED_SURFACE const *pMap) +{ + if ( pMap->cbBlock != 4 && pMap->cbBlock != 1 + && pMap->format != SVGA3D_R16G16B16A16_FLOAT + && pMap->format != SVGA3D_R32G32B32A32_FLOAT) + return VERR_NOT_SUPPORTED; + + int const w = pMap->cbRow / pMap->cbBlock; + int const h = pMap->cRows; + + const int cbBitmap = pMap->cbRow * pMap->cRows * 4; + + FILE *f = fopen(pszFilename, "wb"); + if (!f) + return VERR_FILE_NOT_FOUND; + +#ifdef RT_OS_WINDOWS + if (pMap->cbBlock == 4) + { + BMPFILEHDR fileHdr; + RT_ZERO(fileHdr); + fileHdr.uType = BMP_HDR_MAGIC; + fileHdr.cbFileSize = sizeof(fileHdr) + sizeof(BITMAPV4HEADER) + cbBitmap; + fileHdr.offBits = sizeof(fileHdr) + sizeof(BITMAPV4HEADER); + + BITMAPV4HEADER hdrV4; + RT_ZERO(hdrV4); + hdrV4.bV4Size = sizeof(hdrV4); + hdrV4.bV4Width = w; + hdrV4.bV4Height = -h; + hdrV4.bV4Planes = 1; + hdrV4.bV4BitCount = 32; + hdrV4.bV4V4Compression = BI_BITFIELDS; + hdrV4.bV4SizeImage = cbBitmap; + hdrV4.bV4XPelsPerMeter = 2835; + hdrV4.bV4YPelsPerMeter = 2835; + // hdrV4.bV4ClrUsed = 0; + // hdrV4.bV4ClrImportant = 0; + hdrV4.bV4RedMask = 0x00ff0000; + hdrV4.bV4GreenMask = 0x0000ff00; + hdrV4.bV4BlueMask = 0x000000ff; + hdrV4.bV4AlphaMask = 0xff000000; + hdrV4.bV4CSType = LCS_WINDOWS_COLOR_SPACE; + // hdrV4.bV4Endpoints = {0}; + // hdrV4.bV4GammaRed = 0; + // hdrV4.bV4GammaGreen = 0; + // hdrV4.bV4GammaBlue = 0; + + fwrite(&fileHdr, 1, sizeof(fileHdr), f); + fwrite(&hdrV4, 1, sizeof(hdrV4), f); + } + else +#endif + { + BMPFILEHDR fileHdr; + RT_ZERO(fileHdr); + fileHdr.uType = BMP_HDR_MAGIC; + fileHdr.cbFileSize = sizeof(BMPFILEHDR) + sizeof(BMPWIN3XINFOHDR) + cbBitmap; + fileHdr.offBits = sizeof(BMPFILEHDR) + sizeof(BMPWIN3XINFOHDR); + + BMPWIN3XINFOHDR coreHdr; + RT_ZERO(coreHdr); + coreHdr.cbSize = sizeof(coreHdr); + coreHdr.uWidth = w; + coreHdr.uHeight = -h; + coreHdr.cPlanes = 1; + coreHdr.cBits = 32; + coreHdr.cbSizeImage = cbBitmap; + + fwrite(&fileHdr, 1, sizeof(fileHdr), f); + fwrite(&coreHdr, 1, sizeof(coreHdr), f); + } + + if (pMap->format == SVGA3D_R16G16B16A16_FLOAT) + { + const uint8_t *s = (uint8_t *)pMap->pvData; + for (int32_t y = 0; y < h; ++y) + { + for (int32_t x = 0; x < w; ++x) + { + uint16_t const *pu16Pixel = (uint16_t *)(s + x * 8); + uint8_t r = (uint8_t)(255.0 * float16ToFloat(pu16Pixel[0])); + uint8_t g = (uint8_t)(255.0 * float16ToFloat(pu16Pixel[1])); + uint8_t b = (uint8_t)(255.0 * float16ToFloat(pu16Pixel[2])); + uint8_t a = (uint8_t)(255.0 * float16ToFloat(pu16Pixel[3])); + uint32_t u32Pixel = b + (g << 8) + (r << 16) + (a << 24); + fwrite(&u32Pixel, 1, 4, f); + } + + s += pMap->cbRowPitch; + } + } + else if (pMap->format == SVGA3D_R32G32B32A32_FLOAT) + { + const uint8_t *s = (uint8_t *)pMap->pvData; + for (int32_t y = 0; y < h; ++y) + { + for (int32_t x = 0; x < w; ++x) + { + float const *pPixel = (float *)(s + x * 8); + uint8_t r = (uint8_t)(255.0 * pPixel[0]); + uint8_t g = (uint8_t)(255.0 * pPixel[1]); + uint8_t b = (uint8_t)(255.0 * pPixel[2]); + uint8_t a = (uint8_t)(255.0 * pPixel[3]); + uint32_t u32Pixel = b + (g << 8) + (r << 16) + (a << 24); + fwrite(&u32Pixel, 1, 4, f); + } + + s += pMap->cbRowPitch; + } + } + else if (pMap->cbBlock == 4) + { + const uint8_t *s = (uint8_t *)pMap->pvData; + for (uint32_t iRow = 0; iRow < pMap->cRows; ++iRow) + { + fwrite(s, 1, pMap->cbRow, f); + + s += pMap->cbRowPitch; + } + } + else if (pMap->cbBlock == 1) + { + const uint8_t *s = (uint8_t *)pMap->pvData; + for (uint32_t iRow = 0; iRow < pMap->cRows; ++iRow) + { + for (int32_t x = 0; x < w; ++x) + { + uint32_t u32Pixel = s[x]; + fwrite(&u32Pixel, 1, 4, f); + } + + s += pMap->cbRowPitch; + } + } + + fclose(f); + + return VINF_SUCCESS; +} + + +void vmsvga3dMapWriteBmpFile(VMSVGA3D_MAPPED_SURFACE const *pMap, char const *pszPrefix) +{ + static int idxBitmap = 0; + char *pszFilename = RTStrAPrintf2("bmp\\%s%d.bmp", pszPrefix, idxBitmap++); + int rc = vmsvga3dBmpWrite(pszFilename, pMap); + Log(("WriteBmpFile %s format %d %Rrc\n", pszFilename, pMap->format, rc)); RT_NOREF(rc); + RTStrFree(pszFilename); +} + + +static int vmsvgaR3TransferSurfaceLevel(PVGASTATECC pThisCC, + PVMSVGAMOB pMob, + SVGA3dSurfaceImageId const *pImage, + SVGA3dBox const *pBox, + SVGA3dTransferType enmTransfer) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + VMSVGA3D_SURFACE_MAP enmMapType; + if (enmTransfer == SVGA3D_WRITE_HOST_VRAM) + enmMapType = pBox + ? VMSVGA3D_SURFACE_MAP_WRITE + : VMSVGA3D_SURFACE_MAP_WRITE_DISCARD; + else if (enmTransfer == SVGA3D_READ_HOST_VRAM) + enmMapType = VMSVGA3D_SURFACE_MAP_READ; + else + AssertFailedReturn(VERR_INVALID_PARAMETER); + + VMSVGA3D_MAPPED_SURFACE map; + int rc = vmsvga3dSurfaceMap(pThisCC, pImage, pBox, enmMapType, &map); + if (RT_SUCCESS(rc)) + { + /* Copy mapped surface <-> MOB. */ + VMSGA3D_BOX_DIMENSIONS dims; + rc = vmsvga3dGetBoxDimensions(pThisCC, pImage, pBox, &dims); + if (RT_SUCCESS(rc)) + { + for (uint32_t z = 0; z < map.box.d; ++z) + { + uint8_t *pu8Map = (uint8_t *)map.pvData + z * map.cbDepthPitch; + uint32_t offMob = dims.offSubresource + dims.offBox + z * dims.cbDepthPitch; + + for (uint32_t iRow = 0; iRow < map.cRows; ++iRow) + { + if (enmTransfer == SVGA3D_READ_HOST_VRAM) + rc = vmsvgaR3GboWrite(pSvgaR3State, &pMob->Gbo, offMob, pu8Map, dims.cbRow); + else + rc = vmsvgaR3GboRead(pSvgaR3State, &pMob->Gbo, offMob, pu8Map, dims.cbRow); + AssertRCBreak(rc); + + pu8Map += map.cbRowPitch; + offMob += dims.cbPitch; + } + } + } + + // vmsvga3dMapWriteBmpFile(&map, "Dynamic"); + + bool const fWritten = (enmTransfer == SVGA3D_WRITE_HOST_VRAM); + vmsvga3dSurfaceUnmap(pThisCC, pImage, &map, fWritten); + } + + return rc; +} + + +/* SVGA_3D_CMD_UPDATE_GB_IMAGE 1101 */ +static void vmsvga3dCmdUpdateGBImage(PVGASTATECC pThisCC, SVGA3dCmdUpdateGBImage const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + LogFlowFunc(("sid=%u @%u,%u,%u %ux%ux%u\n", + pCmd->image.sid, pCmd->box.x, pCmd->box.y, pCmd->box.z, pCmd->box.w, pCmd->box.h, pCmd->box.d)); + +/* + SVGA3dSurfaceFormat format; + SVGA3dSurface1Flags surface1Flags; + uint32 numMipLevels; + uint32 multisampleCount; + SVGA3dTextureFilter autogenFilter; + SVGA3dSize size; + SVGAMobId mobid; + uint32 arraySize; + uint32 mobPitch; + SVGA3dSurface2Flags surface2Flags; + uint8 multisamplePattern; + uint8 qualityLevel; + uint16 bufferByteStride; + float minLOD; +*/ + + /* "update a surface from its backing MOB." */ + SVGAOTableSurfaceEntry entrySurface; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->image.sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entrySurface, sizeof(entrySurface)); + if (RT_SUCCESS(rc)) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, entrySurface.mobid); + if (pMob) + { + rc = vmsvgaR3TransferSurfaceLevel(pThisCC, pMob, &pCmd->image, &pCmd->box, SVGA3D_WRITE_HOST_VRAM); + AssertRC(rc); + } + } +} + + +/* SVGA_3D_CMD_UPDATE_GB_SURFACE 1102 */ +static void vmsvga3dCmdUpdateGBSurface(PVGASTATECC pThisCC, SVGA3dCmdUpdateGBSurface const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + LogFlowFunc(("sid=%u\n", + pCmd->sid)); + + /* "update a surface from its backing MOB." */ + SVGAOTableSurfaceEntry entrySurface; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entrySurface, sizeof(entrySurface)); + if (RT_SUCCESS(rc)) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, entrySurface.mobid); + if (pMob) + { + uint32 const arraySize = vmsvga3dGetArrayElements(pThisCC, pCmd->sid); + for (uint32_t iArray = 0; iArray < arraySize; ++iArray) + { + for (uint32_t iMipmap = 0; iMipmap < entrySurface.numMipLevels; ++iMipmap) + { + SVGA3dSurfaceImageId image; + image.sid = pCmd->sid; + image.face = iArray; + image.mipmap = iMipmap; + + rc = vmsvgaR3TransferSurfaceLevel(pThisCC, pMob, &image, /* all pBox = */ NULL, SVGA3D_WRITE_HOST_VRAM); + AssertRCBreak(rc); + } + } + } + } +} + + +/* SVGA_3D_CMD_READBACK_GB_IMAGE 1103 */ +static void vmsvga3dCmdReadbackGBImage(PVGASTATECC pThisCC, SVGA3dCmdReadbackGBImage const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + LogFlowFunc(("sid=%u, face=%u, mipmap=%u\n", + pCmd->image.sid, pCmd->image.face, pCmd->image.mipmap)); + + /* Read a surface to its backing MOB. */ + SVGAOTableSurfaceEntry entrySurface; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->image.sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entrySurface, sizeof(entrySurface)); + if (RT_SUCCESS(rc)) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, entrySurface.mobid); + if (pMob) + { + rc = vmsvgaR3TransferSurfaceLevel(pThisCC, pMob, &pCmd->image, /* all pBox = */ NULL, SVGA3D_READ_HOST_VRAM); + AssertRC(rc); + } + } +} + + +/* SVGA_3D_CMD_READBACK_GB_SURFACE 1104 */ +static void vmsvga3dCmdReadbackGBSurface(PVGASTATECC pThisCC, SVGA3dCmdReadbackGBSurface const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + LogFlowFunc(("sid=%u\n", + pCmd->sid)); + + /* Read a surface to its backing MOB. */ + SVGAOTableSurfaceEntry entrySurface; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entrySurface, sizeof(entrySurface)); + if (RT_SUCCESS(rc)) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, entrySurface.mobid); + if (pMob) + { + uint32 const arraySize = vmsvga3dGetArrayElements(pThisCC, pCmd->sid); + for (uint32_t iArray = 0; iArray < arraySize; ++iArray) + { + for (uint32_t iMipmap = 0; iMipmap < entrySurface.numMipLevels; ++iMipmap) + { + SVGA3dSurfaceImageId image; + image.sid = pCmd->sid; + image.face = iArray; + image.mipmap = iMipmap; + + rc = vmsvgaR3TransferSurfaceLevel(pThisCC, pMob, &image, /* all pBox = */ NULL, SVGA3D_READ_HOST_VRAM); + AssertRCBreak(rc); + } + } + } + } +} + + +/* SVGA_3D_CMD_INVALIDATE_GB_IMAGE 1105 */ +static void vmsvga3dCmdInvalidateGBImage(PVGASTATECC pThisCC, SVGA3dCmdInvalidateGBImage const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + vmsvga3dSurfaceInvalidate(pThisCC, pCmd->image.sid, pCmd->image.face, pCmd->image.mipmap); +} + + +/* SVGA_3D_CMD_INVALIDATE_GB_SURFACE 1106 */ +static void vmsvga3dCmdInvalidateGBSurface(PVGASTATECC pThisCC, SVGA3dCmdInvalidateGBSurface const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + vmsvga3dSurfaceInvalidate(pThisCC, pCmd->sid, SVGA_ID_INVALID, SVGA_ID_INVALID); +} + + +/* SVGA_3D_CMD_SET_OTABLE_BASE64 1115 */ +static void vmsvga3dCmdSetOTableBase64(PVGASTATECC pThisCC, SVGA3dCmdSetOTableBase64 const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + vmsvgaR3OTableSetOrGrow(pSvgaR3State, pCmd->type, pCmd->baseAddress, + pCmd->sizeInBytes, pCmd->validSizeInBytes, pCmd->ptDepth, /*fGrow*/ false); +} + + +/* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET 1124 */ +static void vmsvga3dCmdDefineGBScreenTarget(PVGASTATE pThis, PVGASTATECC pThisCC, SVGA3dCmdDefineGBScreenTarget const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + ASSERT_GUEST_RETURN_VOID(pCmd->stid < RT_ELEMENTS(pSvgaR3State->aScreens)); + ASSERT_GUEST_RETURN_VOID(pCmd->width > 0 && pCmd->width <= pThis->svga.u32MaxWidth); /* SVGA_REG_SCREENTARGET_MAX_WIDTH */ + ASSERT_GUEST_RETURN_VOID(pCmd->height > 0 && pCmd->height <= pThis->svga.u32MaxHeight); /* SVGA_REG_SCREENTARGET_MAX_HEIGHT */ + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Update the entry in the pSvgaR3State->pGboOTableScreenTarget. */ + SVGAOTableScreenTargetEntry entry; + RT_ZERO(entry); + entry.image.sid = SVGA_ID_INVALID; + // entry.image.face = 0; + // entry.image.mipmap = 0; + entry.width = pCmd->width; + entry.height = pCmd->height; + entry.xRoot = pCmd->xRoot; + entry.yRoot = pCmd->yRoot; + entry.flags = pCmd->flags; + entry.dpi = pCmd->dpi; + + int rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SCREENTARGET], + pCmd->stid, SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* Screen objects and screen targets are similar, therefore we will use the same for both. */ + /** @todo Generic screen object/target interface. */ + VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[pCmd->stid]; + Assert(pScreen->idScreen == pCmd->stid); + pScreen->fDefined = true; + pScreen->fModified = true; + pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET + | (RT_BOOL(pCmd->flags & SVGA_STFLAG_PRIMARY) ? SVGA_SCREEN_IS_PRIMARY : 0); + + pScreen->xOrigin = pCmd->xRoot; + pScreen->yOrigin = pCmd->yRoot; + pScreen->cWidth = pCmd->width; + pScreen->cHeight = pCmd->height; + pScreen->offVRAM = 0; /* Not applicable for screen targets, they use either a separate memory buffer or a host window. */ + pScreen->cbPitch = pCmd->width * 4; + pScreen->cBpp = 32; + + if (RT_LIKELY(pThis->svga.f3DEnabled)) + vmsvga3dDefineScreen(pThis, pThisCC, pScreen); + + if (!pScreen->pHwScreen) + { + /* System memory buffer. */ + pScreen->pvScreenBitmap = RTMemAllocZ(pScreen->cHeight * pScreen->cbPitch); + } + + pThis->svga.fGFBRegisters = false; + vmsvgaR3ChangeMode(pThis, pThisCC); + } +} + + +/* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET 1125 */ +static void vmsvga3dCmdDestroyGBScreenTarget(PVGASTATE pThis, PVGASTATECC pThisCC, SVGA3dCmdDestroyGBScreenTarget const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + ASSERT_GUEST_RETURN_VOID(pCmd->stid < RT_ELEMENTS(pSvgaR3State->aScreens)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Update the entry in the pSvgaR3State->pGboOTableScreenTarget. */ + SVGAOTableScreenTargetEntry entry; + RT_ZERO(entry); + int rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SCREENTARGET], + pCmd->stid, SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* Screen objects and screen targets are similar, therefore we will use the same for both. */ + /** @todo Generic screen object/target interface. */ + VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[pCmd->stid]; + vmsvgaR3DestroyScreen(pThis, pThisCC, pScreen); + } +} + + +/* SVGA_3D_CMD_BIND_GB_SCREENTARGET 1126 */ +static void vmsvga3dCmdBindGBScreenTarget(PVGASTATECC pThisCC, SVGA3dCmdBindGBScreenTarget const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* "Binding a surface to a Screen Target the same as flipping" */ + + ASSERT_GUEST_RETURN_VOID(pCmd->stid < RT_ELEMENTS(pSvgaR3State->aScreens)); + ASSERT_GUEST_RETURN_VOID(pCmd->image.face == 0 && pCmd->image.mipmap == 0); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Assign the surface to the screen target. */ + int rc = VINF_SUCCESS; + if (pCmd->image.sid != SVGA_ID_INVALID) + rc = vmsvgaR3OTableVerifyIndex(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->image.sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE); + if (RT_SUCCESS(rc)) + { + SVGAOTableScreenTargetEntry entry; + rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SCREENTARGET], + pCmd->stid, SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + entry.image = pCmd->image; + rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SCREENTARGET], + pCmd->stid, SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[pCmd->stid]; + rc = pSvgaR3State->pFuncsGBO->pfnScreenTargetBind(pThisCC, pScreen, pCmd->image.sid); + AssertRC(rc); + } + } + } +} + + +/* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET 1127 */ +static void vmsvga3dCmdUpdateGBScreenTarget(PVGASTATECC pThisCC, SVGA3dCmdUpdateGBScreenTarget const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Update the screen target from its backing surface. */ + ASSERT_GUEST_RETURN_VOID(pCmd->stid < RT_ELEMENTS(pSvgaR3State->aScreens)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Get the screen target info. */ + SVGAOTableScreenTargetEntry entryScreenTarget; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SCREENTARGET], + pCmd->stid, SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE, &entryScreenTarget, sizeof(entryScreenTarget)); + if (RT_SUCCESS(rc)) + { + ASSERT_GUEST_RETURN_VOID(entryScreenTarget.image.face == 0 && entryScreenTarget.image.mipmap == 0); + RT_UNTRUSTED_VALIDATED_FENCE(); + + if (entryScreenTarget.image.sid != SVGA_ID_INVALID) + { + SVGAOTableSurfaceEntry entrySurface; + rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + entryScreenTarget.image.sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entrySurface, sizeof(entrySurface)); + if (RT_SUCCESS(rc)) + { + /* Copy entrySurface.mobid content to the screen target. */ + if (entrySurface.mobid != SVGA_ID_INVALID) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + SVGA3dRect targetRect = pCmd->rect; + + VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[pCmd->stid]; + if (pScreen->pHwScreen) + { + /* Copy the screen target surface to the backend's screen. */ + pSvgaR3State->pFuncsGBO->pfnScreenTargetUpdate(pThisCC, pScreen, &targetRect); + } + else + { + SVGASignedRect r; + r.left = pCmd->rect.x; + r.top = pCmd->rect.y; + r.right = pCmd->rect.x + pCmd->rect.w; + r.bottom = pCmd->rect.y + pCmd->rect.h; + vmsvga3dScreenUpdate(pThisCC, pCmd->stid, r, entryScreenTarget.image, r, 0, NULL); + } + } + } + } + } +} + + +/* SVGA_3D_CMD_DEFINE_GB_SURFACE_V2 1134 */ +static void vmsvga3dCmdDefineGBSurface_v2(PVGASTATECC pThisCC, SVGA3dCmdDefineGBSurface_v2 const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Update the entry in the pSvgaR3State->pGboOTableSurface. */ + SVGAOTableSurfaceEntry entry; + RT_ZERO(entry); + entry.format = pCmd->format; + entry.surface1Flags = pCmd->surfaceFlags; + entry.numMipLevels = pCmd->numMipLevels; + entry.multisampleCount = pCmd->multisampleCount; + entry.autogenFilter = pCmd->autogenFilter; + entry.size = pCmd->size; + entry.mobid = SVGA_ID_INVALID; + entry.arraySize = pCmd->arraySize; + // entry.mobPitch = 0; + // entry.mobPitch = 0; + // entry.surface2Flags = 0; + // entry.multisamplePattern = 0; + // entry.qualityLevel = 0; + // entry.bufferByteStride = 0; + // entry.minLOD = 0; + + int rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* Create the host surface. */ + /** @todo SVGAOTableSurfaceEntry as input parameter? */ + vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, pCmd->surfaceFlags, pCmd->format, + pCmd->multisampleCount, pCmd->autogenFilter, + pCmd->numMipLevels, &pCmd->size, pCmd->arraySize, /* fAllocMipLevels = */ false); + } +} + + +/* SVGA_3D_CMD_DEFINE_GB_MOB64 1135 */ +static void vmsvga3dCmdDefineGBMob64(PVGASTATECC pThisCC, SVGA3dCmdDefineGBMob64 const *pCmd) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + ASSERT_GUEST_RETURN_VOID(pCmd->mobid != SVGA_ID_INVALID); /* The guest should not use this id. */ + + /* Maybe just update the OTable and create Gbo when the MOB is actually accessed? */ + /* Allocate a structure for the MOB. */ + PVMSVGAMOB pMob = (PVMSVGAMOB)RTMemAllocZ(sizeof(*pMob)); + AssertPtrReturnVoid(pMob); + + int rc = vmsvgaR3MobCreate(pSvgaR3State, pCmd->ptDepth, pCmd->base, pCmd->sizeInBytes, pCmd->mobid, pMob); + if (RT_SUCCESS(rc)) + { + return; + } + + RTMemFree(pMob); +} + + +/* SVGA_3D_CMD_DX_DEFINE_CONTEXT 1143 */ +static int vmsvga3dCmdDXDefineContext(PVGASTATECC pThisCC, SVGA3dCmdDXDefineContext const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Update the entry in the pSvgaR3State->pGboOTable[SVGA_OTABLE_DXCONTEXT]. */ + SVGAOTableDXContextEntry entry; + RT_ZERO(entry); + entry.cid = pCmd->cid; + entry.mobid = SVGA_ID_INVALID; + int rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_DXCONTEXT], + pCmd->cid, sizeof(SVGAOTableDXContextEntry), &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* Create the host context. */ + rc = vmsvga3dDXDefineContext(pThisCC, pCmd->cid); + } + + return rc; +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_CONTEXT 1144 */ +static int vmsvga3dCmdDXDestroyContext(PVGASTATECC pThisCC, SVGA3dCmdDXDestroyContext const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Update the entry in the pSvgaR3State->pGboOTable[SVGA_OTABLE_DXCONTEXT]. */ + SVGAOTableDXContextEntry entry; + RT_ZERO(entry); + vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_DXCONTEXT], + pCmd->cid, sizeof(SVGAOTableDXContextEntry), &entry, sizeof(entry)); + + return vmsvga3dDXDestroyContext(pThisCC, pCmd->cid); +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BIND_CONTEXT 1145 */ +static int vmsvga3dCmdDXBindContext(PVGASTATECC pThisCC, SVGA3dCmdDXBindContext const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Assign a mobid to a cid. */ + int rc = VINF_SUCCESS; + if (pCmd->mobid != SVGA_ID_INVALID) + rc = vmsvgaR3OTableVerifyIndex(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_MOB], + pCmd->mobid, SVGA3D_OTABLE_MOB_ENTRY_SIZE); + if (RT_SUCCESS(rc)) + { + SVGAOTableDXContextEntry entry; + rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_DXCONTEXT], + pCmd->cid, sizeof(SVGAOTableDXContextEntry), &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + SVGADXContextMobFormat *pSvgaDXContext = NULL; + if (pCmd->mobid != entry.mobid && entry.mobid != SVGA_ID_INVALID) + { + /* Unbind notification to the DX backend. Copy the context data to the guest backing memory. */ + pSvgaDXContext = (SVGADXContextMobFormat *)RTMemAlloc(sizeof(SVGADXContextMobFormat)); + if (pSvgaDXContext) + { + rc = vmsvga3dDXUnbindContext(pThisCC, pCmd->cid, pSvgaDXContext); + if (RT_SUCCESS(rc)) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, entry.mobid); + if (pMob) + { + rc = vmsvgaR3GboWrite(pSvgaR3State, &pMob->Gbo, 0, pSvgaDXContext, sizeof(SVGADXContextMobFormat)); + } + } + + RTMemFree(pSvgaDXContext); + pSvgaDXContext = NULL; + } + } + + if (pCmd->mobid != SVGA_ID_INVALID) + { + /* Bind a new context. Copy existing data from the guest backing memory. */ + if (pCmd->validContents) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, pCmd->mobid); + if (pMob) + { + pSvgaDXContext = (SVGADXContextMobFormat *)RTMemAlloc(sizeof(SVGADXContextMobFormat)); + if (pSvgaDXContext) + { + rc = vmsvgaR3GboRead(pSvgaR3State, &pMob->Gbo, 0, pSvgaDXContext, sizeof(SVGADXContextMobFormat)); + if (RT_FAILURE(rc)) + { + RTMemFree(pSvgaDXContext); + pSvgaDXContext = NULL; + } + } + } + } + + rc = vmsvga3dDXBindContext(pThisCC, pCmd->cid, pSvgaDXContext); + + RTMemFree(pSvgaDXContext); + } + + /* Update the object table. */ + entry.mobid = pCmd->mobid; + rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_DXCONTEXT], + pCmd->cid, sizeof(SVGAOTableDXContextEntry), &entry, sizeof(entry)); + } + } + + return rc; +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_READBACK_CONTEXT 1146 */ +static int vmsvga3dCmdDXReadbackContext(PVGASTATECC pThisCC, SVGA3dCmdDXReadbackContext const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* "Request that the device flush the contents back into guest memory." */ + SVGAOTableDXContextEntry entry; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_DXCONTEXT], + pCmd->cid, sizeof(SVGAOTableDXContextEntry), &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + if (entry.mobid != SVGA_ID_INVALID) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, entry.mobid); + if (pMob) + { + /* Get the content. */ + SVGADXContextMobFormat *pSvgaDXContext = (SVGADXContextMobFormat *)RTMemAlloc(sizeof(SVGADXContextMobFormat)); + if (pSvgaDXContext) + { + rc = vmsvga3dDXReadbackContext(pThisCC, pCmd->cid, pSvgaDXContext); + if (RT_SUCCESS(rc)) + rc = vmsvgaR3GboWrite(pSvgaR3State, &pMob->Gbo, 0, pSvgaDXContext, sizeof(SVGADXContextMobFormat)); + + RTMemFree(pSvgaDXContext); + } + else + rc = VERR_NO_MEMORY; + } + } + } + + return rc; +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_INVALIDATE_CONTEXT 1147 */ +static int vmsvga3dCmdDXInvalidateContext(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXInvalidateContext const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXInvalidateContext(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER 1148 */ +static int vmsvga3dCmdDXSetSingleConstantBuffer(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetSingleConstantBuffer const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetSingleConstantBuffer(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_SHADER_RESOURCES 1149 */ +static int vmsvga3dCmdDXSetShaderResources(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetShaderResources const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dShaderResourceViewId const *paShaderResourceViewId = (SVGA3dShaderResourceViewId *)&pCmd[1]; + uint32_t const cShaderResourceViewId = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dShaderResourceViewId); + return vmsvga3dDXSetShaderResources(pThisCC, idDXContext, pCmd, cShaderResourceViewId, paShaderResourceViewId); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_SHADER 1150 */ +static int vmsvga3dCmdDXSetShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetShader const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetShader(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_SAMPLERS 1151 */ +static int vmsvga3dCmdDXSetSamplers(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetSamplers const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dSamplerId const *paSamplerId = (SVGA3dSamplerId *)&pCmd[1]; + uint32_t const cSamplerId = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dSamplerId); + return vmsvga3dDXSetSamplers(pThisCC, idDXContext, pCmd, cSamplerId, paSamplerId); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DRAW 1152 */ +static int vmsvga3dCmdDXDraw(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDraw const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDraw(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DRAW_INDEXED 1153 */ +static int vmsvga3dCmdDXDrawIndexed(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexed const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDrawIndexed(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DRAW_INSTANCED 1154 */ +static int vmsvga3dCmdDXDrawInstanced(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawInstanced const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDrawInstanced(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED 1155 */ +static int vmsvga3dCmdDXDrawIndexedInstanced(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexedInstanced const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDrawIndexedInstanced(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DRAW_AUTO 1156 */ +static int vmsvga3dCmdDXDrawAuto(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawAuto const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(pCmd, cbCmd); + return vmsvga3dDXDrawAuto(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_INPUT_LAYOUT 1157 */ +static int vmsvga3dCmdDXSetInputLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetInputLayout const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetInputLayout(pThisCC, idDXContext, pCmd->elementLayoutId); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS 1158 */ +static int vmsvga3dCmdDXSetVertexBuffers(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetVertexBuffers const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dVertexBuffer const *paVertexBuffer = (SVGA3dVertexBuffer *)&pCmd[1]; + uint32_t const cVertexBuffer = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dVertexBuffer); + return vmsvga3dDXSetVertexBuffers(pThisCC, idDXContext, pCmd->startBuffer, cVertexBuffer, paVertexBuffer); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_INDEX_BUFFER 1159 */ +static int vmsvga3dCmdDXSetIndexBuffer(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetIndexBuffer const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetIndexBuffer(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_TOPOLOGY 1160 */ +static int vmsvga3dCmdDXSetTopology(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetTopology const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetTopology(pThisCC, idDXContext, pCmd->topology); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_RENDERTARGETS 1161 */ +static int vmsvga3dCmdDXSetRenderTargets(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetRenderTargets const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dRenderTargetViewId const *paRenderTargetViewId = (SVGA3dRenderTargetViewId *)&pCmd[1]; + uint32_t const cRenderTargetViewId = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dRenderTargetViewId); + return vmsvga3dDXSetRenderTargets(pThisCC, idDXContext, pCmd->depthStencilViewId, cRenderTargetViewId, paRenderTargetViewId); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_BLEND_STATE 1162 */ +static int vmsvga3dCmdDXSetBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetBlendState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetBlendState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE 1163 */ +static int vmsvga3dCmdDXSetDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetDepthStencilState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetDepthStencilState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_RASTERIZER_STATE 1164 */ +static int vmsvga3dCmdDXSetRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetRasterizerState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetRasterizerState(pThisCC, idDXContext, pCmd->rasterizerId); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_QUERY 1165 */ +static int vmsvga3dCmdDXDefineQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineQuery(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_QUERY 1166 */ +static int vmsvga3dCmdDXDestroyQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyQuery(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BIND_QUERY 1167 */ +static int vmsvga3dCmdDXBindQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(cbCmd); + /* This returns NULL if mob does not exist. If the guest sends a wrong mob id, the current mob will be unbound. */ + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, pCmd->mobid); + return vmsvga3dDXBindQuery(pThisCC, idDXContext, pCmd, pMob); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_QUERY_OFFSET 1168 */ +static int vmsvga3dCmdDXSetQueryOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetQueryOffset const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetQueryOffset(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BEGIN_QUERY 1169 */ +static int vmsvga3dCmdDXBeginQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBeginQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXBeginQuery(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_END_QUERY 1170 */ +static int vmsvga3dCmdDXEndQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXEndQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXEndQuery(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_READBACK_QUERY 1171 */ +static int vmsvga3dCmdDXReadbackQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXReadbackQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXReadbackQuery(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_PREDICATION 1172 */ +static int vmsvga3dCmdDXSetPredication(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetPredication const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetPredication(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_SOTARGETS 1173 */ +static int vmsvga3dCmdDXSetSOTargets(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetSOTargets const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dSoTarget const *paSoTarget = (SVGA3dSoTarget *)&pCmd[1]; + uint32_t const cSoTarget = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dSoTarget); + return vmsvga3dDXSetSOTargets(pThisCC, idDXContext, cSoTarget, paSoTarget); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_VIEWPORTS 1174 */ +static int vmsvga3dCmdDXSetViewports(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetViewports const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dViewport const *paViewport = (SVGA3dViewport *)&pCmd[1]; + uint32_t const cViewport = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dViewport); + return vmsvga3dDXSetViewports(pThisCC, idDXContext, cViewport, paViewport); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_SCISSORRECTS 1175 */ +static int vmsvga3dCmdDXSetScissorRects(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetScissorRects const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGASignedRect const *paRect = (SVGASignedRect *)&pCmd[1]; + uint32_t const cRect = (cbCmd - sizeof(*pCmd)) / sizeof(SVGASignedRect); + return vmsvga3dDXSetScissorRects(pThisCC, idDXContext, cRect, paRect); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW 1176 */ +static int vmsvga3dCmdDXClearRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearRenderTargetView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXClearRenderTargetView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW 1177 */ +static int vmsvga3dCmdDXClearDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearDepthStencilView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXClearDepthStencilView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_PRED_COPY_REGION 1178 */ +static int vmsvga3dCmdDXPredCopyRegion(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredCopyRegion const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXPredCopyRegion(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_PRED_COPY 1179 */ +static int vmsvga3dCmdDXPredCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredCopy const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXPredCopy(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_PRESENTBLT 1180 */ +static int vmsvga3dCmdDXPresentBlt(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPresentBlt const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXPresentBlt(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_GENMIPS 1181 */ +static int vmsvga3dCmdDXGenMips(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXGenMips const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXGenMips(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE 1182 */ +static int vmsvga3dCmdDXUpdateSubResource(PVGASTATECC pThisCC, SVGA3dCmdDXUpdateSubResource const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(cbCmd); + + LogFlowFunc(("sid=%u, subResource=%u, box=%d,%d,%d %ux%ux%u\n", + pCmd->sid, pCmd->subResource, pCmd->box.x, pCmd->box.y, pCmd->box.z, pCmd->box.w, pCmd->box.h, pCmd->box.d)); + + /* "Inform the device that the guest-contents have been updated." */ + SVGAOTableSurfaceEntry entrySurface; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entrySurface, sizeof(entrySurface)); + if (RT_SUCCESS(rc)) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, entrySurface.mobid); + if (pMob) + { + uint32 const cSubresource = vmsvga3dGetSubresourceCount(pThisCC, pCmd->sid); + ASSERT_GUEST_RETURN(pCmd->subResource < cSubresource, VERR_INVALID_PARAMETER); + /* pCmd->box will be verified by the mapping function. */ + RT_UNTRUSTED_VALIDATED_FENCE(); + + /** @todo Mapping functions should use subresource index rather than SVGA3dSurfaceImageId? */ + SVGA3dSurfaceImageId image; + image.sid = pCmd->sid; + vmsvga3dCalcMipmapAndFace(entrySurface.numMipLevels, pCmd->subResource, &image.mipmap, &image.face); + + rc = vmsvgaR3TransferSurfaceLevel(pThisCC, pMob, &image, &pCmd->box, SVGA3D_WRITE_HOST_VRAM); + AssertRC(rc); + } + } + + return rc; +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_READBACK_SUBRESOURCE 1183 */ +static int vmsvga3dCmdDXReadbackSubResource(PVGASTATECC pThisCC, SVGA3dCmdDXReadbackSubResource const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(cbCmd); + + LogFlowFunc(("sid=%u, subResource=%u\n", + pCmd->sid, pCmd->subResource)); + + /* "Request the device to flush the dirty contents into the guest." */ + SVGAOTableSurfaceEntry entrySurface; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entrySurface, sizeof(entrySurface)); + if (RT_SUCCESS(rc)) + { + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, entrySurface.mobid); + if (pMob) + { + uint32 const cSubresource = vmsvga3dGetSubresourceCount(pThisCC, pCmd->sid); + ASSERT_GUEST_RETURN(pCmd->subResource < cSubresource, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /** @todo Mapping functions should use subresource index rather than SVGA3dSurfaceImageId? */ + SVGA3dSurfaceImageId image; + image.sid = pCmd->sid; + vmsvga3dCalcMipmapAndFace(entrySurface.numMipLevels, pCmd->subResource, &image.mipmap, &image.face); + + rc = vmsvgaR3TransferSurfaceLevel(pThisCC, pMob, &image, /* all pBox = */ NULL, SVGA3D_READ_HOST_VRAM); + AssertRC(rc); + } + } + + return rc; +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE 1184 */ +static int vmsvga3dCmdDXInvalidateSubResource(PVGASTATECC pThisCC, SVGA3dCmdDXInvalidateSubResource const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(cbCmd); + + LogFlowFunc(("sid=%u, subResource=%u\n", + pCmd->sid, pCmd->subResource)); + + /* "Notify the device that the contents can be lost." */ + SVGAOTableSurfaceEntry entrySurface; + int rc = vmsvgaR3OTableRead(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entrySurface, sizeof(entrySurface)); + if (RT_SUCCESS(rc)) + { + uint32_t iFace; + uint32_t iMipmap; + vmsvga3dCalcMipmapAndFace(entrySurface.numMipLevels, pCmd->subResource, &iMipmap, &iFace); + vmsvga3dSurfaceInvalidate(pThisCC, pCmd->sid, iFace, iMipmap); + } + + return rc; +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW 1185 */ +static int vmsvga3dCmdDXDefineShaderResourceView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineShaderResourceView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineShaderResourceView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW 1186 */ +static int vmsvga3dCmdDXDestroyShaderResourceView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyShaderResourceView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyShaderResourceView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW 1187 */ +static int vmsvga3dCmdDXDefineRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineRenderTargetView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineRenderTargetView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW 1188 */ +static int vmsvga3dCmdDXDestroyRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyRenderTargetView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyRenderTargetView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW 1189 */ +static int vmsvga3dCmdDXDefineDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineDepthStencilView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + SVGA3dCmdDXDefineDepthStencilView_v2 cmd; + cmd.depthStencilViewId = pCmd->depthStencilViewId; + cmd.sid = pCmd->sid; + cmd.format = pCmd->format; + cmd.resourceDimension = pCmd->resourceDimension; + cmd.mipSlice = pCmd->mipSlice; + cmd.firstArraySlice = pCmd->firstArraySlice; + cmd.arraySize = pCmd->arraySize; + cmd.flags = 0; + return vmsvga3dDXDefineDepthStencilView(pThisCC, idDXContext, &cmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW 1190 */ +static int vmsvga3dCmdDXDestroyDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyDepthStencilView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyDepthStencilView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT 1191 */ +static int vmsvga3dCmdDXDefineElementLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineElementLayout const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dInputElementDesc const *paDesc = (SVGA3dInputElementDesc *)&pCmd[1]; + uint32_t const cDesc = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dInputElementDesc); + return vmsvga3dDXDefineElementLayout(pThisCC, idDXContext, pCmd->elementLayoutId, cDesc, paDesc); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT 1192 */ +static int vmsvga3dCmdDXDestroyElementLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyElementLayout const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyElementLayout(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_BLEND_STATE 1193 */ +static int vmsvga3dCmdDXDefineBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineBlendState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineBlendState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_BLEND_STATE 1194 */ +static int vmsvga3dCmdDXDestroyBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyBlendState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyBlendState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE 1195 */ +static int vmsvga3dCmdDXDefineDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineDepthStencilState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineDepthStencilState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE 1196 */ +static int vmsvga3dCmdDXDestroyDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyDepthStencilState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyDepthStencilState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE 1197 */ +static int vmsvga3dCmdDXDefineRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineRasterizerState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineRasterizerState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE 1198 */ +static int vmsvga3dCmdDXDestroyRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyRasterizerState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyRasterizerState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE 1199 */ +static int vmsvga3dCmdDXDefineSamplerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineSamplerState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineSamplerState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE 1200 */ +static int vmsvga3dCmdDXDestroySamplerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroySamplerState const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroySamplerState(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_SHADER 1201 */ +static int vmsvga3dCmdDXDefineShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineShader const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineShader(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_SHADER 1202 */ +static int vmsvga3dCmdDXDestroyShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyShader const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyShader(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BIND_SHADER 1203 */ +static int vmsvga3dCmdDXBindShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindShader const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(idDXContext, cbCmd); + /* This returns NULL if mob does not exist. If the guest sends a wrong mob id, the current mob will be unbound. */ + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, pCmd->mobid); + return vmsvga3dDXBindShader(pThisCC, pCmd, pMob); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT 1204 */ +static int vmsvga3dCmdDXDefineStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineStreamOutput const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineStreamOutput(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT 1205 */ +static int vmsvga3dCmdDXDestroyStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyStreamOutput const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyStreamOutput(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_STREAMOUTPUT 1206 */ +static int vmsvga3dCmdDXSetStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetStreamOutput const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetStreamOutput(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_COTABLE 1207 */ +static int vmsvga3dCmdDXSetCOTable(PVGASTATECC pThisCC, SVGA3dCmdDXSetCOTable const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + /* This returns NULL if mob does not exist. If the guest sends a wrong mob id, the current mob will be unbound. */ + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, pCmd->mobid); + return vmsvga3dDXSetCOTable(pThisCC, pCmd, pMob); +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_READBACK_COTABLE 1208 */ +static int vmsvga3dCmdDXReadbackCOTable(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXReadbackCOTable const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(idDXContext, cbCmd); + return vmsvga3dDXReadbackCOTable(pThisCC, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BUFFER_COPY 1209 */ +static int vmsvga3dCmdDXBufferCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBufferCopy const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(idDXContext, cbCmd); + + int rc; + + /** @todo Backend should o the copy is both buffers have a hardware resource. */ + SVGA3dSurfaceImageId imageBufferSrc; + imageBufferSrc.sid = pCmd->src; + imageBufferSrc.face = 0; + imageBufferSrc.mipmap = 0; + + SVGA3dSurfaceImageId imageBufferDest; + imageBufferDest.sid = pCmd->dest; + imageBufferDest.face = 0; + imageBufferDest.mipmap = 0; + + /* + * Map the source buffer. + */ + VMSVGA3D_MAPPED_SURFACE mapBufferSrc; + rc = vmsvga3dSurfaceMap(pThisCC, &imageBufferSrc, NULL, VMSVGA3D_SURFACE_MAP_READ, &mapBufferSrc); + if (RT_SUCCESS(rc)) + { + /* + * Map the destination buffer. + */ + VMSVGA3D_MAPPED_SURFACE mapBufferDest; + rc = vmsvga3dSurfaceMap(pThisCC, &imageBufferDest, NULL, VMSVGA3D_SURFACE_MAP_WRITE, &mapBufferDest); + if (RT_SUCCESS(rc)) + { + /* + * Copy the source buffer to the destination. + */ + uint8_t const *pu8BufferSrc = (uint8_t *)mapBufferSrc.pvData; + uint32_t const cbBufferSrc = mapBufferSrc.cbRow; + + uint8_t *pu8BufferDest = (uint8_t *)mapBufferDest.pvData; + uint32_t const cbBufferDest = mapBufferDest.cbRow; + + if ( pCmd->srcX < cbBufferSrc + && pCmd->width <= cbBufferSrc- pCmd->srcX + && pCmd->destX < cbBufferDest + && pCmd->width <= cbBufferDest - pCmd->destX) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + + memcpy(&pu8BufferDest[pCmd->destX], &pu8BufferSrc[pCmd->srcX], pCmd->width); + } + else + ASSERT_GUEST_FAILED_STMT(rc = VERR_INVALID_PARAMETER); + + vmsvga3dSurfaceUnmap(pThisCC, &imageBufferDest, &mapBufferDest, true); + } + + vmsvga3dSurfaceUnmap(pThisCC, &imageBufferSrc, &mapBufferSrc, false); + } + + return rc; +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER 1210 */ +static int vmsvga3dCmdDXTransferFromBuffer(PVGASTATECC pThisCC, SVGA3dCmdDXTransferFromBuffer const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + + /* Plan: + * - map the buffer; + * - map the surface; + * - copy from buffer map to the surface map. + */ + + int rc; + + SVGA3dSurfaceImageId imageBuffer; + imageBuffer.sid = pCmd->srcSid; + imageBuffer.face = 0; + imageBuffer.mipmap = 0; + + SVGA3dSurfaceImageId imageSurface; + imageSurface.sid = pCmd->destSid; + rc = vmsvga3dCalcSurfaceMipmapAndFace(pThisCC, pCmd->destSid, pCmd->destSubResource, &imageSurface.mipmap, &imageSurface.face); + AssertRCReturn(rc, rc); + + /* + * Map the buffer. + */ + VMSVGA3D_MAPPED_SURFACE mapBuffer; + rc = vmsvga3dSurfaceMap(pThisCC, &imageBuffer, NULL, VMSVGA3D_SURFACE_MAP_READ, &mapBuffer); + if (RT_SUCCESS(rc)) + { + /* + * Map the surface. + */ + VMSVGA3D_MAPPED_SURFACE mapSurface; + rc = vmsvga3dSurfaceMap(pThisCC, &imageSurface, &pCmd->destBox, VMSVGA3D_SURFACE_MAP_WRITE, &mapSurface); + if (RT_SUCCESS(rc)) + { + /* + * Copy the mapped buffer to the surface. "Raw byte wise transfer" + */ + uint8_t const *pu8Buffer = (uint8_t *)mapBuffer.pvData; + uint32_t const cbBuffer = mapBuffer.cbRow; + + if (pCmd->srcOffset <= cbBuffer) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + uint8_t const *pu8BufferBegin = pu8Buffer; + uint8_t const *pu8BufferEnd = pu8Buffer + cbBuffer; + + pu8Buffer += pCmd->srcOffset; + + uint8_t *pu8Surface = (uint8_t *)mapSurface.pvData; + + uint32_t const cbRowCopy = RT_MIN(pCmd->srcPitch, mapSurface.cbRow); + for (uint32_t z = 0; z < mapSurface.box.d && RT_SUCCESS(rc); ++z) + { + uint8_t const *pu8BufferRow = pu8Buffer; + uint8_t *pu8SurfaceRow = pu8Surface; + for (uint32_t iRow = 0; iRow < mapSurface.cRows; ++iRow) + { + ASSERT_GUEST_STMT_BREAK( (uintptr_t)pu8BufferRow >= (uintptr_t)pu8BufferBegin + && (uintptr_t)pu8BufferRow < (uintptr_t)pu8BufferEnd + && (uintptr_t)pu8BufferRow < (uintptr_t)(pu8BufferRow + cbRowCopy) + && (uintptr_t)(pu8BufferRow + cbRowCopy) > (uintptr_t)pu8BufferBegin + && (uintptr_t)(pu8BufferRow + cbRowCopy) <= (uintptr_t)pu8BufferEnd, + rc = VERR_INVALID_PARAMETER); + + memcpy(pu8SurfaceRow, pu8BufferRow, cbRowCopy); + + pu8SurfaceRow += mapSurface.cbRowPitch; + pu8BufferRow += pCmd->srcPitch; + } + + pu8Buffer += pCmd->srcSlicePitch; + pu8Surface += mapSurface.cbDepthPitch; + } + } + else + ASSERT_GUEST_FAILED_STMT(rc = VERR_INVALID_PARAMETER); + + vmsvga3dSurfaceUnmap(pThisCC, &imageSurface, &mapSurface, true); + } + + vmsvga3dSurfaceUnmap(pThisCC, &imageBuffer, &mapBuffer, false); + } + + return rc; +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK 1211 */ +static int vmsvga3dCmdDXSurfaceCopyAndReadback(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSurfaceCopyAndReadback const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXSurfaceCopyAndReadback(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_MOVE_QUERY 1212 */ +static int vmsvga3dCmdDXMoveQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXMoveQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXMoveQuery(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BIND_ALL_QUERY 1213 */ +static int vmsvga3dCmdDXBindAllQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindAllQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXBindAllQuery(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_READBACK_ALL_QUERY 1214 */ +static int vmsvga3dCmdDXReadbackAllQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXReadbackAllQuery const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXReadbackAllQuery(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER 1215 */ +static int vmsvga3dCmdDXPredTransferFromBuffer(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredTransferFromBuffer const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(idDXContext, cbCmd); + + /* This command is executed in a context: "The context is implied from the command buffer header." + * However the device design allows to do the transfer without a context, so re-use context-less command handler. + */ + SVGA3dCmdDXTransferFromBuffer cmd; + cmd.srcSid = pCmd->srcSid; + cmd.srcOffset = pCmd->srcOffset; + cmd.srcPitch = pCmd->srcPitch; + cmd.srcSlicePitch = pCmd->srcSlicePitch; + cmd.destSid = pCmd->destSid; + cmd.destSubResource = pCmd->destSubResource; + cmd.destBox = pCmd->destBox; + return vmsvga3dCmdDXTransferFromBuffer(pThisCC, &cmd, sizeof(cmd)); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_MOB_FENCE_64 1216 */ +static int vmsvga3dCmdDXMobFence64(PVGASTATECC pThisCC, SVGA3dCmdDXMobFence64 const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(cbCmd); + + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, pCmd->mobId); + ASSERT_GUEST_RETURN(pMob, VERR_INVALID_PARAMETER); + + int rc = vmsvgaR3MobWrite(pSvgaR3State, pMob, pCmd->mobOffset, &pCmd->value, sizeof(pCmd->value)); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + return VINF_SUCCESS; +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BIND_ALL_SHADER 1217 */ +static int vmsvga3dCmdDXBindAllShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindAllShader const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXBindAllShader(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_HINT 1218 */ +static int vmsvga3dCmdDXHint(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXHint const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXHint(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BUFFER_UPDATE 1219 */ +static int vmsvga3dCmdDXBufferUpdate(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBufferUpdate const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXBufferUpdate(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET 1220 */ +static int vmsvga3dCmdDXSetVSConstantBufferOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetVSConstantBufferOffset const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetConstantBufferOffset(pThisCC, idDXContext, pCmd, SVGA3D_SHADERTYPE_VS); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET 1221 */ +static int vmsvga3dCmdDXSetPSConstantBufferOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetPSConstantBufferOffset const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetConstantBufferOffset(pThisCC, idDXContext, pCmd, SVGA3D_SHADERTYPE_PS); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET 1222 */ +static int vmsvga3dCmdDXSetGSConstantBufferOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetGSConstantBufferOffset const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetConstantBufferOffset(pThisCC, idDXContext, pCmd, SVGA3D_SHADERTYPE_GS); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_HS_CONSTANT_BUFFER_OFFSET 1223 */ +static int vmsvga3dCmdDXSetHSConstantBufferOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetHSConstantBufferOffset const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetConstantBufferOffset(pThisCC, idDXContext, pCmd, SVGA3D_SHADERTYPE_HS); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_DS_CONSTANT_BUFFER_OFFSET 1224 */ +static int vmsvga3dCmdDXSetDSConstantBufferOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetDSConstantBufferOffset const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetConstantBufferOffset(pThisCC, idDXContext, pCmd, SVGA3D_SHADERTYPE_DS); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_CS_CONSTANT_BUFFER_OFFSET 1225 */ +static int vmsvga3dCmdDXSetCSConstantBufferOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetCSConstantBufferOffset const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetConstantBufferOffset(pThisCC, idDXContext, pCmd, SVGA3D_SHADERTYPE_CS); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER 1226 */ +static int vmsvga3dCmdDXCondBindAllShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXCondBindAllShader const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXCondBindAllShader(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_SCREEN_COPY 1227 */ +static int vmsvga3dCmdScreenCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdScreenCopy const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dScreenCopy(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_GROW_OTABLE 1236 */ +static int vmsvga3dCmdGrowOTable(PVGASTATECC pThisCC, SVGA3dCmdGrowOTable const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(cbCmd); + return vmsvgaR3OTableSetOrGrow(pSvgaR3State, pCmd->type, pCmd->baseAddress, + pCmd->sizeInBytes, pCmd->validSizeInBytes, pCmd->ptDepth, /*fGrow*/ true); +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_GROW_COTABLE 1237 */ +static int vmsvga3dCmdDXGrowCOTable(PVGASTATECC pThisCC, SVGA3dCmdDXGrowCOTable const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXGrowCOTable(pThisCC, pCmd); +#else + RT_NOREF(pThisCC, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_INTRA_SURFACE_COPY 1238 */ +static int vmsvga3dCmdIntraSurfaceCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdIntraSurfaceCopy const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dIntraSurfaceCopy(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DEFINE_GB_SURFACE_V3 1239 */ +static int vmsvga3dCmdDefineGBSurface_v3(PVGASTATECC pThisCC, SVGA3dCmdDefineGBSurface_v3 const *pCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Update the entry in the pSvgaR3State->pGboOTableSurface. */ + SVGAOTableSurfaceEntry entry; + RT_ZERO(entry); + entry.format = pCmd->format; + entry.surface1Flags = (uint32_t)(pCmd->surfaceFlags); + entry.numMipLevels = pCmd->numMipLevels; + entry.multisampleCount = pCmd->multisampleCount; + entry.autogenFilter = pCmd->autogenFilter; + entry.size = pCmd->size; + entry.mobid = SVGA_ID_INVALID; + entry.arraySize = pCmd->arraySize; + // entry.mobPitch = 0; + // entry.mobPitch = 0; + entry.surface2Flags = (uint32_t)(pCmd->surfaceFlags >> UINT64_C(32)); + // entry.multisamplePattern = 0; + // entry.qualityLevel = 0; + // entry.bufferByteStride = 0; + // entry.minLOD = 0; + + int rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* Create the host surface. */ + /** @todo SVGAOTableSurfaceEntry as input parameter? */ + vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, pCmd->surfaceFlags, pCmd->format, + pCmd->multisampleCount, pCmd->autogenFilter, + pCmd->numMipLevels, &pCmd->size, pCmd->arraySize, /* fAllocMipLevels = */ false); + } + return rc; +#else + RT_NOREF(pThisCC, pCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_RESOLVE_COPY 1240 */ +static int vmsvga3dCmdDXResolveCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXResolveCopy const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXResolveCopy(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_PRED_RESOLVE_COPY 1241 */ +static int vmsvga3dCmdDXPredResolveCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredResolveCopy const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXPredResolveCopy(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_PRED_CONVERT_REGION 1242 */ +static int vmsvga3dCmdDXPredConvertRegion(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredConvertRegion const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXPredConvertRegion(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_PRED_CONVERT 1243 */ +static int vmsvga3dCmdDXPredConvert(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredConvert const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXPredConvert(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_WHOLE_SURFACE_COPY 1244 */ +static int vmsvga3dCmdWholeSurfaceCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdWholeSurfaceCopy const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dWholeSurfaceCopy(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_UA_VIEW 1245 */ +static int vmsvga3dCmdDXDefineUAView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineUAView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineUAView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DESTROY_UA_VIEW 1246 */ +static int vmsvga3dCmdDXDestroyUAView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyUAView const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDestroyUAView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT 1247 */ +static int vmsvga3dCmdDXClearUAViewUint(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearUAViewUint const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXClearUAViewUint(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT 1248 */ +static int vmsvga3dCmdDXClearUAViewFloat(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearUAViewFloat const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXClearUAViewFloat(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT 1249 */ +static int vmsvga3dCmdDXCopyStructureCount(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXCopyStructureCount const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXCopyStructureCount(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_UA_VIEWS 1250 */ +static int vmsvga3dCmdDXSetUAViews(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetUAViews const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dUAViewId const *paUAViewId = (SVGA3dUAViewId *)&pCmd[1]; + uint32_t const cUAViewId = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dUAViewId); + return vmsvga3dDXSetUAViews(pThisCC, idDXContext, pCmd, cUAViewId, paUAViewId); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT 1251 */ +static int vmsvga3dCmdDXDrawIndexedInstancedIndirect(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexedInstancedIndirect const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDrawIndexedInstancedIndirect(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT 1252 */ +static int vmsvga3dCmdDXDrawInstancedIndirect(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawInstancedIndirect const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDrawInstancedIndirect(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DISPATCH 1253 */ +static int vmsvga3dCmdDXDispatch(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDispatch const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDispatch(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DISPATCH_INDIRECT 1254 */ +static int vmsvga3dCmdDXDispatchIndirect(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDispatchIndirect const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXDispatchIndirect(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_WRITE_ZERO_SURFACE 1255 */ +static int vmsvga3dCmdWriteZeroSurface(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdWriteZeroSurface const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dWriteZeroSurface(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_HINT_ZERO_SURFACE 1256 */ +static int vmsvga3dCmdHintZeroSurface(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdHintZeroSurface const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dHintZeroSurface(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_TRANSFER_TO_BUFFER 1257 */ +static int vmsvga3dCmdDXTransferToBuffer(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXTransferToBuffer const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXTransferToBuffer(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_STRUCTURE_COUNT 1258 */ +static int vmsvga3dCmdDXSetStructureCount(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetStructureCount const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXSetStructureCount(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_LOGICOPS_BITBLT 1259 */ +static int vmsvga3dCmdLogicOpsBitBlt(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdLogicOpsBitBlt const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dLogicOpsBitBlt(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_LOGICOPS_TRANSBLT 1260 */ +static int vmsvga3dCmdLogicOpsTransBlt(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdLogicOpsTransBlt const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dLogicOpsTransBlt(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_LOGICOPS_STRETCHBLT 1261 */ +static int vmsvga3dCmdLogicOpsStretchBlt(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdLogicOpsStretchBlt const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dLogicOpsStretchBlt(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_LOGICOPS_COLORFILL 1262 */ +static int vmsvga3dCmdLogicOpsColorFill(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdLogicOpsColorFill const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dLogicOpsColorFill(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_LOGICOPS_ALPHABLEND 1263 */ +static int vmsvga3dCmdLogicOpsAlphaBlend(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdLogicOpsAlphaBlend const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dLogicOpsAlphaBlend(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND 1264 */ +static int vmsvga3dCmdLogicOpsClearTypeBlend(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdLogicOpsClearTypeBlend const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dLogicOpsClearTypeBlend(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DEFINE_GB_SURFACE_V4 1267 */ +static int vmsvga3dCmdDefineGBSurface_v4(PVGASTATECC pThisCC, SVGA3dCmdDefineGBSurface_v4 const *pCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* Update the entry in the pSvgaR3State->pGboOTableSurface. */ + SVGAOTableSurfaceEntry entry; + RT_ZERO(entry); + entry.format = pCmd->format; + entry.surface1Flags = (uint32_t)(pCmd->surfaceFlags); + entry.numMipLevels = pCmd->numMipLevels; + entry.multisampleCount = pCmd->multisampleCount; + entry.autogenFilter = pCmd->autogenFilter; + entry.size = pCmd->size; + entry.mobid = SVGA_ID_INVALID; + entry.arraySize = pCmd->arraySize; + // entry.mobPitch = 0; + // entry.mobPitch = 0; + entry.surface2Flags = (uint32_t)(pCmd->surfaceFlags >> UINT64_C(32)); + // entry.multisamplePattern = 0; + // entry.qualityLevel = 0; + entry.bufferByteStride = pCmd->bufferByteStride; + // entry.minLOD = 0; + + int rc = vmsvgaR3OTableWrite(pSvgaR3State, &pSvgaR3State->aGboOTables[SVGA_OTABLE_SURFACE], + pCmd->sid, SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, &entry, sizeof(entry)); + if (RT_SUCCESS(rc)) + { + /* Create the host surface. */ + /** @todo SVGAOTableSurfaceEntry as input parameter? */ + vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, pCmd->surfaceFlags, pCmd->format, + pCmd->multisampleCount, pCmd->autogenFilter, + pCmd->numMipLevels, &pCmd->size, pCmd->arraySize, /* fAllocMipLevels = */ false); + } + return rc; +#else + RT_NOREF(pThisCC, pCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_CS_UA_VIEWS 1268 */ +static int vmsvga3dCmdDXSetCSUAViews(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetCSUAViews const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGA3dUAViewId const *paUAViewId = (SVGA3dUAViewId *)&pCmd[1]; + uint32_t const cUAViewId = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dUAViewId); + return vmsvga3dDXSetCSUAViews(pThisCC, idDXContext, pCmd, cUAViewId, paUAViewId); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_MIN_LOD 1269 */ +static int vmsvga3dCmdDXSetMinLOD(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetMinLOD const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXSetMinLOD(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2 1272 */ +static int vmsvga3dCmdDXDefineDepthStencilView_v2(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineDepthStencilView_v2 const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineDepthStencilView(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB 1273 */ +static int vmsvga3dCmdDXDefineStreamOutputWithMob(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineStreamOutputWithMob const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXDefineStreamOutputWithMob(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_SET_SHADER_IFACE 1274 */ +static int vmsvga3dCmdDXSetShaderIface(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetShaderIface const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXSetShaderIface(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BIND_STREAMOUTPUT 1275 */ +static int vmsvga3dCmdDXBindStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindStreamOutput const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + RT_NOREF(cbCmd); + return vmsvga3dDXBindStreamOutput(pThisCC, idDXContext, pCmd); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_SURFACE_STRETCHBLT_NON_MS_TO_MS 1276 */ +static int vmsvga3dCmdSurfaceStretchBltNonMSToMS(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdSurfaceStretchBltNonMSToMS const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dSurfaceStretchBltNonMSToMS(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_DX_BIND_SHADER_IFACE 1277 */ +static int vmsvga3dCmdDXBindShaderIface(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindShaderIface const *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + RT_NOREF(pSvgaR3State, pCmd, cbCmd); + return vmsvga3dDXBindShaderIface(pThisCC, idDXContext); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/* SVGA_3D_CMD_VB_DX_CLEAR_RENDERTARGET_VIEW_REGION 1083 */ +static int vmsvga3dCmdVBDXClearRenderTargetViewRegion(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdVBDXClearRenderTargetViewRegion *pCmd, uint32_t cbCmd) +{ +#ifdef VMSVGA3D_DX + //DEBUG_BREAKPOINT_TEST(); + SVGASignedRect const *paRect = (SVGASignedRect *)&pCmd[1]; + uint32_t const cRect = (cbCmd - sizeof(*pCmd)) / sizeof(SVGASignedRect); + return vmsvga3dVBDXClearRenderTargetViewRegion(pThisCC, idDXContext, pCmd, cRect, paRect); +#else + RT_NOREF(pThisCC, idDXContext, pCmd, cbCmd); + return VERR_NOT_SUPPORTED; +#endif +} + + +/** @def VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK + * Check that the 3D command has at least a_cbMin of payload bytes after the + * header. Will break out of the switch if it doesn't. + */ +# define VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(a_cbMin) \ + if (1) { \ + AssertMsgBreak(cbCmd >= (a_cbMin), ("size=%#x a_cbMin=%#zx\n", cbCmd, (size_t)(a_cbMin))); \ + RT_UNTRUSTED_VALIDATED_FENCE(); \ + } else do {} while (0) + +# define VMSVGA_3D_CMD_NOTIMPL() \ + if (1) { \ + AssertMsgFailed(("Not implemented %d %s\n", enmCmdId, vmsvgaR3FifoCmdToString(enmCmdId))); \ + } else do {} while (0) + +/** SVGA_3D_CMD_* handler. + * This function parses the command and calls the corresponding command handler. + * + * @param pThis The shared VGA/VMSVGA state. + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param idDXContext VGPU10 DX context of the commands or SVGA3D_INVALID_ID if they are not for a specific context. + * @param enmCmdId SVGA_3D_CMD_* command identifier. + * @param cbCmd Size of the command in bytes. + * @param pvCmd Pointer to the command. + * @returns VBox status code if an error was detected parsing a command. + */ +int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t idDXContext, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd) +{ + if (enmCmdId > SVGA_3D_CMD_MAX) + { + LogRelMax(16, ("VMSVGA: unsupported 3D command %d\n", enmCmdId)); + ASSERT_GUEST_FAILED_RETURN(VERR_NOT_IMPLEMENTED); + } + + int rcParse = VINF_SUCCESS; + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + + switch (enmCmdId) + { + case SVGA_3D_CMD_SURFACE_DEFINE: + { + SVGA3dCmdDefineSurface *pCmd = (SVGA3dCmdDefineSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDefine); + + SVGA3dCmdDefineSurface_v2 cmd; + cmd.sid = pCmd->sid; + cmd.surfaceFlags = pCmd->surfaceFlags; + cmd.format = pCmd->format; + memcpy(cmd.face, pCmd->face, sizeof(cmd.face)); + cmd.multisampleCount = 0; + cmd.autogenFilter = SVGA3D_TEX_FILTER_NONE; + + uint32_t const cMipLevelSizes = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dSize); + vmsvga3dCmdDefineSurface(pThisCC, &cmd, cMipLevelSizes, (SVGA3dSize *)(pCmd + 1)); +# ifdef DEBUG_GMR_ACCESS + VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3ResetGmrHandlers, 1, pThis); +# endif + break; + } + + case SVGA_3D_CMD_SURFACE_DEFINE_V2: + { + SVGA3dCmdDefineSurface_v2 *pCmd = (SVGA3dCmdDefineSurface_v2 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDefineV2); + + uint32_t const cMipLevelSizes = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dSize); + vmsvga3dCmdDefineSurface(pThisCC, pCmd, cMipLevelSizes, (SVGA3dSize *)(pCmd + 1)); +# ifdef DEBUG_GMR_ACCESS + VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3ResetGmrHandlers, 1, pThis); +# endif + break; + } + + case SVGA_3D_CMD_SURFACE_DESTROY: + { + SVGA3dCmdDestroySurface *pCmd = (SVGA3dCmdDestroySurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDestroy); + + vmsvga3dSurfaceDestroy(pThisCC, pCmd->sid); + break; + } + + case SVGA_3D_CMD_SURFACE_COPY: + { + SVGA3dCmdSurfaceCopy *pCmd = (SVGA3dCmdSurfaceCopy *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceCopy); + + uint32_t const cCopyBoxes = (cbCmd - sizeof(pCmd)) / sizeof(SVGA3dCopyBox); + vmsvga3dSurfaceCopy(pThisCC, pCmd->dest, pCmd->src, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1)); + break; + } + + case SVGA_3D_CMD_SURFACE_STRETCHBLT: + { + SVGA3dCmdSurfaceStretchBlt *pCmd = (SVGA3dCmdSurfaceStretchBlt *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceStretchBlt); + + vmsvga3dSurfaceStretchBlt(pThis, pThisCC, &pCmd->dest, &pCmd->boxDest, + &pCmd->src, &pCmd->boxSrc, pCmd->mode); + break; + } + + case SVGA_3D_CMD_SURFACE_DMA: + { + SVGA3dCmdSurfaceDMA *pCmd = (SVGA3dCmdSurfaceDMA *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDma); + + uint64_t u64NanoTS = 0; + if (LogRelIs3Enabled()) + u64NanoTS = RTTimeNanoTS(); + uint32_t const cCopyBoxes = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dCopyBox); + STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dSurfaceDmaProf, a); + vmsvga3dSurfaceDMA(pThis, pThisCC, pCmd->guest, pCmd->host, pCmd->transfer, + cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1)); + STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dSurfaceDmaProf, a); + if (LogRelIs3Enabled()) + { + if (cCopyBoxes) + { + SVGA3dCopyBox *pFirstBox = (SVGA3dCopyBox *)(pCmd + 1); + LogRel3(("VMSVGA: SURFACE_DMA: %d us %d boxes %d,%d %dx%d%s\n", + (RTTimeNanoTS() - u64NanoTS) / 1000ULL, cCopyBoxes, + pFirstBox->x, pFirstBox->y, pFirstBox->w, pFirstBox->h, + pCmd->transfer == SVGA3D_READ_HOST_VRAM ? " readback!!!" : "")); + } + } + break; + } + + case SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN: + { + SVGA3dCmdBlitSurfaceToScreen *pCmd = (SVGA3dCmdBlitSurfaceToScreen *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceScreen); + + static uint64_t u64FrameStartNanoTS = 0; + static uint64_t u64ElapsedPerSecNano = 0; + static int cFrames = 0; + uint64_t u64NanoTS = 0; + if (LogRelIs3Enabled()) + u64NanoTS = RTTimeNanoTS(); + uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGASignedRect); + STAM_REL_PROFILE_START(&pSvgaR3State->StatR3Cmd3dBlitSurfaceToScreenProf, a); + vmsvga3dSurfaceBlitToScreen(pThis, pThisCC, pCmd->destScreenId, pCmd->destRect, pCmd->srcImage, + pCmd->srcRect, cRects, (SVGASignedRect *)(pCmd + 1)); + STAM_REL_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dBlitSurfaceToScreenProf, a); + if (LogRelIs3Enabled()) + { + uint64_t u64ElapsedNano = RTTimeNanoTS() - u64NanoTS; + u64ElapsedPerSecNano += u64ElapsedNano; + + SVGASignedRect *pFirstRect = cRects ? (SVGASignedRect *)(pCmd + 1) : &pCmd->destRect; + LogRel3(("VMSVGA: SURFACE_TO_SCREEN: %d us %d rects %d,%d %dx%d\n", + (u64ElapsedNano) / 1000ULL, cRects, + pFirstRect->left, pFirstRect->top, + pFirstRect->right - pFirstRect->left, pFirstRect->bottom - pFirstRect->top)); + + ++cFrames; + if (u64NanoTS - u64FrameStartNanoTS >= UINT64_C(1000000000)) + { + LogRel3(("VMSVGA: SURFACE_TO_SCREEN: FPS %d, elapsed %llu us\n", + cFrames, u64ElapsedPerSecNano / 1000ULL)); + u64FrameStartNanoTS = u64NanoTS; + cFrames = 0; + u64ElapsedPerSecNano = 0; + } + } + break; + } + + case SVGA_3D_CMD_CONTEXT_DEFINE: + { + SVGA3dCmdDefineContext *pCmd = (SVGA3dCmdDefineContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dContextDefine); + + vmsvga3dContextDefine(pThisCC, pCmd->cid); + break; + } + + case SVGA_3D_CMD_CONTEXT_DESTROY: + { + SVGA3dCmdDestroyContext *pCmd = (SVGA3dCmdDestroyContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dContextDestroy); + + vmsvga3dContextDestroy(pThisCC, pCmd->cid); + break; + } + + case SVGA_3D_CMD_SETTRANSFORM: + { + SVGA3dCmdSetTransform *pCmd = (SVGA3dCmdSetTransform *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetTransform); + + vmsvga3dSetTransform(pThisCC, pCmd->cid, pCmd->type, pCmd->matrix); + break; + } + + case SVGA_3D_CMD_SETZRANGE: + { + SVGA3dCmdSetZRange *pCmd = (SVGA3dCmdSetZRange *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetZRange); + + vmsvga3dSetZRange(pThisCC, pCmd->cid, pCmd->zRange); + break; + } + + case SVGA_3D_CMD_SETRENDERSTATE: + { + SVGA3dCmdSetRenderState *pCmd = (SVGA3dCmdSetRenderState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetRenderState); + + uint32_t const cRenderStates = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dRenderState); + vmsvga3dSetRenderState(pThisCC, pCmd->cid, cRenderStates, (SVGA3dRenderState *)(pCmd + 1)); + break; + } + + case SVGA_3D_CMD_SETRENDERTARGET: + { + SVGA3dCmdSetRenderTarget *pCmd = (SVGA3dCmdSetRenderTarget *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetRenderTarget); + + vmsvga3dSetRenderTarget(pThisCC, pCmd->cid, pCmd->type, pCmd->target); + break; + } + + case SVGA_3D_CMD_SETTEXTURESTATE: + { + SVGA3dCmdSetTextureState *pCmd = (SVGA3dCmdSetTextureState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetTextureState); + + uint32_t const cTextureStates = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dTextureState); + vmsvga3dSetTextureState(pThisCC, pCmd->cid, cTextureStates, (SVGA3dTextureState *)(pCmd + 1)); + break; + } + + case SVGA_3D_CMD_SETMATERIAL: + { + SVGA3dCmdSetMaterial *pCmd = (SVGA3dCmdSetMaterial *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetMaterial); + + vmsvga3dSetMaterial(pThisCC, pCmd->cid, pCmd->face, &pCmd->material); + break; + } + + case SVGA_3D_CMD_SETLIGHTDATA: + { + SVGA3dCmdSetLightData *pCmd = (SVGA3dCmdSetLightData *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetLightData); + + vmsvga3dSetLightData(pThisCC, pCmd->cid, pCmd->index, &pCmd->data); + break; + } + + case SVGA_3D_CMD_SETLIGHTENABLED: + { + SVGA3dCmdSetLightEnabled *pCmd = (SVGA3dCmdSetLightEnabled *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetLightEnable); + + vmsvga3dSetLightEnabled(pThisCC, pCmd->cid, pCmd->index, pCmd->enabled); + break; + } + + case SVGA_3D_CMD_SETVIEWPORT: + { + SVGA3dCmdSetViewport *pCmd = (SVGA3dCmdSetViewport *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetViewPort); + + vmsvga3dSetViewPort(pThisCC, pCmd->cid, &pCmd->rect); + break; + } + + case SVGA_3D_CMD_SETCLIPPLANE: + { + SVGA3dCmdSetClipPlane *pCmd = (SVGA3dCmdSetClipPlane *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetClipPlane); + + vmsvga3dSetClipPlane(pThisCC, pCmd->cid, pCmd->index, pCmd->plane); + break; + } + + case SVGA_3D_CMD_CLEAR: + { + SVGA3dCmdClear *pCmd = (SVGA3dCmdClear *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dClear); + + uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dRect); + vmsvga3dCommandClear(pThisCC, pCmd->cid, pCmd->clearFlag, pCmd->color, pCmd->depth, pCmd->stencil, cRects, (SVGA3dRect *)(pCmd + 1)); + break; + } + + case SVGA_3D_CMD_PRESENT: + case SVGA_3D_CMD_PRESENT_READBACK: /** @todo SVGA_3D_CMD_PRESENT_READBACK isn't quite the same as present... */ + { + SVGA3dCmdPresent *pCmd = (SVGA3dCmdPresent *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + if (enmCmdId == SVGA_3D_CMD_PRESENT) + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dPresent); + else + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dPresentReadBack); + + uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dCopyRect); + STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dPresentProf, a); + vmsvga3dCommandPresent(pThis, pThisCC, pCmd->sid, cRects, (SVGA3dCopyRect *)(pCmd + 1)); + STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dPresentProf, a); + break; + } + + case SVGA_3D_CMD_SHADER_DEFINE: + { + SVGA3dCmdDefineShader *pCmd = (SVGA3dCmdDefineShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dShaderDefine); + + uint32_t const cbData = (cbCmd - sizeof(*pCmd)); + vmsvga3dShaderDefine(pThisCC, pCmd->cid, pCmd->shid, pCmd->type, cbData, (uint32_t *)(pCmd + 1)); + break; + } + + case SVGA_3D_CMD_SHADER_DESTROY: + { + SVGA3dCmdDestroyShader *pCmd = (SVGA3dCmdDestroyShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dShaderDestroy); + + vmsvga3dShaderDestroy(pThisCC, pCmd->cid, pCmd->shid, pCmd->type); + break; + } + + case SVGA_3D_CMD_SET_SHADER: + { + SVGA3dCmdSetShader *pCmd = (SVGA3dCmdSetShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetShader); + + vmsvga3dShaderSet(pThisCC, NULL, pCmd->cid, pCmd->type, pCmd->shid); + break; + } + + case SVGA_3D_CMD_SET_SHADER_CONST: + { + SVGA3dCmdSetShaderConst *pCmd = (SVGA3dCmdSetShaderConst *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetShaderConst); + + uint32_t const cRegisters = (cbCmd - sizeof(*pCmd)) / sizeof(pCmd->values) + 1; + vmsvga3dShaderSetConst(pThisCC, pCmd->cid, pCmd->reg, pCmd->type, pCmd->ctype, cRegisters, pCmd->values); + break; + } + + case SVGA_3D_CMD_DRAW_PRIMITIVES: + { + SVGA3dCmdDrawPrimitives *pCmd = (SVGA3dCmdDrawPrimitives *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dDrawPrimitives); + + ASSERT_GUEST_STMT_BREAK(pCmd->numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES, rcParse = VERR_INVALID_PARAMETER); + ASSERT_GUEST_STMT_BREAK(pCmd->numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS, rcParse = VERR_INVALID_PARAMETER); + uint32_t const cbRangesAndVertexDecls = pCmd->numVertexDecls * sizeof(SVGA3dVertexDecl) + + pCmd->numRanges * sizeof(SVGA3dPrimitiveRange); + ASSERT_GUEST_STMT_BREAK(cbRangesAndVertexDecls <= cbCmd - sizeof(*pCmd), rcParse = VERR_INVALID_PARAMETER); + + uint32_t const cVertexDivisor = (cbCmd - sizeof(*pCmd) - cbRangesAndVertexDecls) / sizeof(uint32_t); + ASSERT_GUEST_STMT_BREAK(!cVertexDivisor || cVertexDivisor == pCmd->numVertexDecls, rcParse = VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGA3dVertexDecl *pVertexDecl = (SVGA3dVertexDecl *)(pCmd + 1); + SVGA3dPrimitiveRange *pNumRange = (SVGA3dPrimitiveRange *)&pVertexDecl[pCmd->numVertexDecls]; + SVGA3dVertexDivisor *pVertexDivisor = cVertexDivisor ? (SVGA3dVertexDivisor *)&pNumRange[pCmd->numRanges] : NULL; + + STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dDrawPrimitivesProf, a); + vmsvga3dDrawPrimitives(pThisCC, pCmd->cid, pCmd->numVertexDecls, pVertexDecl, pCmd->numRanges, + pNumRange, cVertexDivisor, pVertexDivisor); + STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dDrawPrimitivesProf, a); + break; + } + + case SVGA_3D_CMD_SETSCISSORRECT: + { + SVGA3dCmdSetScissorRect *pCmd = (SVGA3dCmdSetScissorRect *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetScissorRect); + + vmsvga3dSetScissorRect(pThisCC, pCmd->cid, &pCmd->rect); + break; + } + + case SVGA_3D_CMD_BEGIN_QUERY: + { + SVGA3dCmdBeginQuery *pCmd = (SVGA3dCmdBeginQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dBeginQuery); + + vmsvga3dQueryBegin(pThisCC, pCmd->cid, pCmd->type); + break; + } + + case SVGA_3D_CMD_END_QUERY: + { + SVGA3dCmdEndQuery *pCmd = (SVGA3dCmdEndQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dEndQuery); + + vmsvga3dQueryEnd(pThisCC, pCmd->cid, pCmd->type); + break; + } + + case SVGA_3D_CMD_WAIT_FOR_QUERY: + { + SVGA3dCmdWaitForQuery *pCmd = (SVGA3dCmdWaitForQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dWaitForQuery); + + vmsvga3dQueryWait(pThisCC, pCmd->cid, pCmd->type, pThis, &pCmd->guestResult); + break; + } + + case SVGA_3D_CMD_GENERATE_MIPMAPS: + { + SVGA3dCmdGenerateMipmaps *pCmd = (SVGA3dCmdGenerateMipmaps *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dGenerateMipmaps); + + vmsvga3dGenerateMipmaps(pThisCC, pCmd->sid, pCmd->filter); + break; + } + + case SVGA_3D_CMD_ACTIVATE_SURFACE: + /* context id + surface id? */ + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dActivateSurface); + break; + + case SVGA_3D_CMD_DEACTIVATE_SURFACE: + /* context id + surface id? */ + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dDeactivateSurface); + break; + + /* + * + * VPGU10: SVGA_CAP_GBOBJECTS+ commands. + * + */ + case SVGA_3D_CMD_SCREEN_DMA: + { + SVGA3dCmdScreenDMA *pCmd = (SVGA3dCmdScreenDMA *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + /* case SVGA_3D_CMD_DEAD1: New SVGA_3D_CMD_VB_DX_CLEAR_RENDERTARGET_VIEW_REGION */ + case SVGA_3D_CMD_DEAD2: + case SVGA_3D_CMD_DEAD12: /* Old SVGA_3D_CMD_LOGICOPS_BITBLT */ + case SVGA_3D_CMD_DEAD13: /* Old SVGA_3D_CMD_LOGICOPS_TRANSBLT */ + case SVGA_3D_CMD_DEAD14: /* Old SVGA_3D_CMD_LOGICOPS_STRETCHBLT */ + case SVGA_3D_CMD_DEAD15: /* Old SVGA_3D_CMD_LOGICOPS_COLORFILL */ + case SVGA_3D_CMD_DEAD16: /* Old SVGA_3D_CMD_LOGICOPS_ALPHABLEND */ + case SVGA_3D_CMD_DEAD17: /* Old SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND */ + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_SET_OTABLE_BASE: + { + SVGA3dCmdSetOTableBase *pCmd = (SVGA3dCmdSetOTableBase *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdSetOTableBase(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_READBACK_OTABLE: + { + SVGA3dCmdReadbackOTable *pCmd = (SVGA3dCmdReadbackOTable *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_MOB: + { + SVGA3dCmdDefineGBMob *pCmd = (SVGA3dCmdDefineGBMob *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdDefineGBMob(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_DESTROY_GB_MOB: + { + SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdDestroyGBMob(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_DEAD3: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING: + { + SVGA3dCmdUpdateGBMobMapping *pCmd = (SVGA3dCmdUpdateGBMobMapping *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_SURFACE: + { + SVGA3dCmdDefineGBSurface *pCmd = (SVGA3dCmdDefineGBSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdDefineGBSurface(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_DESTROY_GB_SURFACE: + { + SVGA3dCmdDestroyGBSurface *pCmd = (SVGA3dCmdDestroyGBSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdDestroyGBSurface(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_BIND_GB_SURFACE: + { + SVGA3dCmdBindGBSurface *pCmd = (SVGA3dCmdBindGBSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdBindGBSurface(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_COND_BIND_GB_SURFACE: + { + SVGA3dCmdCondBindGBSurface *pCmd = (SVGA3dCmdCondBindGBSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_UPDATE_GB_IMAGE: + { + SVGA3dCmdUpdateGBImage *pCmd = (SVGA3dCmdUpdateGBImage *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdUpdateGBImage(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_UPDATE_GB_SURFACE: + { + SVGA3dCmdUpdateGBSurface *pCmd = (SVGA3dCmdUpdateGBSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdUpdateGBSurface(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_READBACK_GB_IMAGE: + { + SVGA3dCmdReadbackGBImage *pCmd = (SVGA3dCmdReadbackGBImage *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdReadbackGBImage(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_READBACK_GB_SURFACE: + { + SVGA3dCmdReadbackGBSurface *pCmd = (SVGA3dCmdReadbackGBSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdReadbackGBSurface(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_INVALIDATE_GB_IMAGE: + { + SVGA3dCmdInvalidateGBImage *pCmd = (SVGA3dCmdInvalidateGBImage *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdInvalidateGBImage(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_INVALIDATE_GB_SURFACE: + { + SVGA3dCmdInvalidateGBSurface *pCmd = (SVGA3dCmdInvalidateGBSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdInvalidateGBSurface(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_CONTEXT: + { + SVGA3dCmdDefineGBContext *pCmd = (SVGA3dCmdDefineGBContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DESTROY_GB_CONTEXT: + { + SVGA3dCmdDestroyGBContext *pCmd = (SVGA3dCmdDestroyGBContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_BIND_GB_CONTEXT: + { + SVGA3dCmdBindGBContext *pCmd = (SVGA3dCmdBindGBContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_READBACK_GB_CONTEXT: + { + SVGA3dCmdReadbackGBContext *pCmd = (SVGA3dCmdReadbackGBContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_INVALIDATE_GB_CONTEXT: + { + SVGA3dCmdInvalidateGBContext *pCmd = (SVGA3dCmdInvalidateGBContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_SHADER: + { + SVGA3dCmdDefineGBShader *pCmd = (SVGA3dCmdDefineGBShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DESTROY_GB_SHADER: + { + SVGA3dCmdDestroyGBShader *pCmd = (SVGA3dCmdDestroyGBShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_BIND_GB_SHADER: + { + SVGA3dCmdBindGBShader *pCmd = (SVGA3dCmdBindGBShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_SET_OTABLE_BASE64: + { + SVGA3dCmdSetOTableBase64 *pCmd = (SVGA3dCmdSetOTableBase64 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdSetOTableBase64(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_BEGIN_GB_QUERY: + { + SVGA3dCmdBeginGBQuery *pCmd = (SVGA3dCmdBeginGBQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_END_GB_QUERY: + { + SVGA3dCmdEndGBQuery *pCmd = (SVGA3dCmdEndGBQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_WAIT_FOR_GB_QUERY: + { + SVGA3dCmdWaitForGBQuery *pCmd = (SVGA3dCmdWaitForGBQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_NOP: + { + /* Apparently there is nothing to do. */ + break; + } + + case SVGA_3D_CMD_ENABLE_GART: + { + SVGA3dCmdEnableGart *pCmd = (SVGA3dCmdEnableGart *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DISABLE_GART: + { + /* No corresponding SVGA3dCmd structure. */ + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_MAP_MOB_INTO_GART: + { + SVGA3dCmdMapMobIntoGart *pCmd = (SVGA3dCmdMapMobIntoGart *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_UNMAP_GART_RANGE: + { + SVGA3dCmdUnmapGartRange *pCmd = (SVGA3dCmdUnmapGartRange *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_SCREENTARGET: + { + SVGA3dCmdDefineGBScreenTarget *pCmd = (SVGA3dCmdDefineGBScreenTarget *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdDefineGBScreenTarget(pThis, pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_DESTROY_GB_SCREENTARGET: + { + SVGA3dCmdDestroyGBScreenTarget *pCmd = (SVGA3dCmdDestroyGBScreenTarget *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdDestroyGBScreenTarget(pThis, pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_BIND_GB_SCREENTARGET: + { + SVGA3dCmdBindGBScreenTarget *pCmd = (SVGA3dCmdBindGBScreenTarget *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdBindGBScreenTarget(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_UPDATE_GB_SCREENTARGET: + { + SVGA3dCmdUpdateGBScreenTarget *pCmd = (SVGA3dCmdUpdateGBScreenTarget *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdUpdateGBScreenTarget(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL: + { + SVGA3dCmdReadbackGBImagePartial *pCmd = (SVGA3dCmdReadbackGBImagePartial *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL: + { + SVGA3dCmdInvalidateGBImagePartial *pCmd = (SVGA3dCmdInvalidateGBImagePartial *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE: + { + SVGA3dCmdSetGBShaderConstInline *pCmd = (SVGA3dCmdSetGBShaderConstInline *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_GB_SCREEN_DMA: + { + SVGA3dCmdGBScreenDMA *pCmd = (SVGA3dCmdGBScreenDMA *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH: + { + SVGA3dCmdBindGBSurfaceWithPitch *pCmd = (SVGA3dCmdBindGBSurfaceWithPitch *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_GB_MOB_FENCE: + { + SVGA3dCmdGBMobFence *pCmd = (SVGA3dCmdGBMobFence *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_SURFACE_V2: + { + SVGA3dCmdDefineGBSurface_v2 *pCmd = (SVGA3dCmdDefineGBSurface_v2 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdDefineGBSurface_v2(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_MOB64: + { + SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + vmsvga3dCmdDefineGBMob64(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_REDEFINE_GB_MOB64: + { + SVGA3dCmdRedefineGBMob64 *pCmd = (SVGA3dCmdRedefineGBMob64 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_NOP_ERROR: + { + /* Apparently there is nothing to do. */ + break; + } + + case SVGA_3D_CMD_SET_VERTEX_STREAMS: + { + SVGA3dCmdSetVertexStreams *pCmd = (SVGA3dCmdSetVertexStreams *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_SET_VERTEX_DECLS: + { + SVGA3dCmdSetVertexDecls *pCmd = (SVGA3dCmdSetVertexDecls *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_SET_VERTEX_DIVISORS: + { + SVGA3dCmdSetVertexDivisors *pCmd = (SVGA3dCmdSetVertexDivisors *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd); + break; + } + + case SVGA_3D_CMD_DRAW: + { + /* No corresponding SVGA3dCmd structure. */ + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_DRAW_INDEXED: + { + /* No corresponding SVGA3dCmd structure. */ + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_CONTEXT: + { + SVGA3dCmdDXDefineContext *pCmd = (SVGA3dCmdDXDefineContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineContext(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_CONTEXT: + { + SVGA3dCmdDXDestroyContext *pCmd = (SVGA3dCmdDXDestroyContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyContext(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BIND_CONTEXT: + { + SVGA3dCmdDXBindContext *pCmd = (SVGA3dCmdDXBindContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBindContext(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_READBACK_CONTEXT: + { + SVGA3dCmdDXReadbackContext *pCmd = (SVGA3dCmdDXReadbackContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXReadbackContext(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_INVALIDATE_CONTEXT: + { + SVGA3dCmdDXInvalidateContext *pCmd = (SVGA3dCmdDXInvalidateContext *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXInvalidateContext(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER: + { + SVGA3dCmdDXSetSingleConstantBuffer *pCmd = (SVGA3dCmdDXSetSingleConstantBuffer *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetSingleConstantBuffer(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_SHADER_RESOURCES: + { + SVGA3dCmdDXSetShaderResources *pCmd = (SVGA3dCmdDXSetShaderResources *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetShaderResources(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_SHADER: + { + SVGA3dCmdDXSetShader *pCmd = (SVGA3dCmdDXSetShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetShader(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_SAMPLERS: + { + SVGA3dCmdDXSetSamplers *pCmd = (SVGA3dCmdDXSetSamplers *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetSamplers(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DRAW: + { + SVGA3dCmdDXDraw *pCmd = (SVGA3dCmdDXDraw *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDraw(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DRAW_INDEXED: + { + SVGA3dCmdDXDrawIndexed *pCmd = (SVGA3dCmdDXDrawIndexed *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDrawIndexed(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DRAW_INSTANCED: + { + SVGA3dCmdDXDrawInstanced *pCmd = (SVGA3dCmdDXDrawInstanced *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDrawInstanced(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED: + { + SVGA3dCmdDXDrawIndexedInstanced *pCmd = (SVGA3dCmdDXDrawIndexedInstanced *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDrawIndexedInstanced(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DRAW_AUTO: + { + SVGA3dCmdDXDrawAuto *pCmd = (SVGA3dCmdDXDrawAuto *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDrawAuto(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_INPUT_LAYOUT: + { + SVGA3dCmdDXSetInputLayout *pCmd = (SVGA3dCmdDXSetInputLayout *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetInputLayout(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS: + { + SVGA3dCmdDXSetVertexBuffers *pCmd = (SVGA3dCmdDXSetVertexBuffers *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetVertexBuffers(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_INDEX_BUFFER: + { + SVGA3dCmdDXSetIndexBuffer *pCmd = (SVGA3dCmdDXSetIndexBuffer *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetIndexBuffer(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_TOPOLOGY: + { + SVGA3dCmdDXSetTopology *pCmd = (SVGA3dCmdDXSetTopology *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetTopology(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_RENDERTARGETS: + { + SVGA3dCmdDXSetRenderTargets *pCmd = (SVGA3dCmdDXSetRenderTargets *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetRenderTargets(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_BLEND_STATE: + { + SVGA3dCmdDXSetBlendState *pCmd = (SVGA3dCmdDXSetBlendState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetBlendState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE: + { + SVGA3dCmdDXSetDepthStencilState *pCmd = (SVGA3dCmdDXSetDepthStencilState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetDepthStencilState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_RASTERIZER_STATE: + { + SVGA3dCmdDXSetRasterizerState *pCmd = (SVGA3dCmdDXSetRasterizerState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetRasterizerState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_QUERY: + { + SVGA3dCmdDXDefineQuery *pCmd = (SVGA3dCmdDXDefineQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_QUERY: + { + SVGA3dCmdDXDestroyQuery *pCmd = (SVGA3dCmdDXDestroyQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BIND_QUERY: + { + SVGA3dCmdDXBindQuery *pCmd = (SVGA3dCmdDXBindQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBindQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_QUERY_OFFSET: + { + SVGA3dCmdDXSetQueryOffset *pCmd = (SVGA3dCmdDXSetQueryOffset *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetQueryOffset(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BEGIN_QUERY: + { + SVGA3dCmdDXBeginQuery *pCmd = (SVGA3dCmdDXBeginQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBeginQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_END_QUERY: + { + SVGA3dCmdDXEndQuery *pCmd = (SVGA3dCmdDXEndQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXEndQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_READBACK_QUERY: + { + SVGA3dCmdDXReadbackQuery *pCmd = (SVGA3dCmdDXReadbackQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXReadbackQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_PREDICATION: + { + SVGA3dCmdDXSetPredication *pCmd = (SVGA3dCmdDXSetPredication *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetPredication(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_SOTARGETS: + { + SVGA3dCmdDXSetSOTargets *pCmd = (SVGA3dCmdDXSetSOTargets *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetSOTargets(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_VIEWPORTS: + { + SVGA3dCmdDXSetViewports *pCmd = (SVGA3dCmdDXSetViewports *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetViewports(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_SCISSORRECTS: + { + SVGA3dCmdDXSetScissorRects *pCmd = (SVGA3dCmdDXSetScissorRects *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetScissorRects(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW: + { + SVGA3dCmdDXClearRenderTargetView *pCmd = (SVGA3dCmdDXClearRenderTargetView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXClearRenderTargetView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW: + { + SVGA3dCmdDXClearDepthStencilView *pCmd = (SVGA3dCmdDXClearDepthStencilView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXClearDepthStencilView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_PRED_COPY_REGION: + { + SVGA3dCmdDXPredCopyRegion *pCmd = (SVGA3dCmdDXPredCopyRegion *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXPredCopyRegion(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_PRED_COPY: + { + SVGA3dCmdDXPredCopy *pCmd = (SVGA3dCmdDXPredCopy *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXPredCopy(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_PRESENTBLT: + { + SVGA3dCmdDXPresentBlt *pCmd = (SVGA3dCmdDXPresentBlt *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXPresentBlt(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_GENMIPS: + { + SVGA3dCmdDXGenMips *pCmd = (SVGA3dCmdDXGenMips *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXGenMips(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE: + { + SVGA3dCmdDXUpdateSubResource *pCmd = (SVGA3dCmdDXUpdateSubResource *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXUpdateSubResource(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_READBACK_SUBRESOURCE: + { + SVGA3dCmdDXReadbackSubResource *pCmd = (SVGA3dCmdDXReadbackSubResource *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXReadbackSubResource(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE: + { + SVGA3dCmdDXInvalidateSubResource *pCmd = (SVGA3dCmdDXInvalidateSubResource *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXInvalidateSubResource(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW: + { + SVGA3dCmdDXDefineShaderResourceView *pCmd = (SVGA3dCmdDXDefineShaderResourceView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineShaderResourceView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW: + { + SVGA3dCmdDXDestroyShaderResourceView *pCmd = (SVGA3dCmdDXDestroyShaderResourceView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyShaderResourceView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW: + { + SVGA3dCmdDXDefineRenderTargetView *pCmd = (SVGA3dCmdDXDefineRenderTargetView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineRenderTargetView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW: + { + SVGA3dCmdDXDestroyRenderTargetView *pCmd = (SVGA3dCmdDXDestroyRenderTargetView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyRenderTargetView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW: + { + SVGA3dCmdDXDefineDepthStencilView *pCmd = (SVGA3dCmdDXDefineDepthStencilView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineDepthStencilView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW: + { + SVGA3dCmdDXDestroyDepthStencilView *pCmd = (SVGA3dCmdDXDestroyDepthStencilView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyDepthStencilView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT: + { + SVGA3dCmdDXDefineElementLayout *pCmd = (SVGA3dCmdDXDefineElementLayout *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineElementLayout(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT: + { + SVGA3dCmdDXDestroyElementLayout *pCmd = (SVGA3dCmdDXDestroyElementLayout *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyElementLayout(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_BLEND_STATE: + { + SVGA3dCmdDXDefineBlendState *pCmd = (SVGA3dCmdDXDefineBlendState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineBlendState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_BLEND_STATE: + { + SVGA3dCmdDXDestroyBlendState *pCmd = (SVGA3dCmdDXDestroyBlendState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyBlendState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE: + { + SVGA3dCmdDXDefineDepthStencilState *pCmd = (SVGA3dCmdDXDefineDepthStencilState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineDepthStencilState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE: + { + SVGA3dCmdDXDestroyDepthStencilState *pCmd = (SVGA3dCmdDXDestroyDepthStencilState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyDepthStencilState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE: + { + SVGA3dCmdDXDefineRasterizerState *pCmd = (SVGA3dCmdDXDefineRasterizerState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineRasterizerState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE: + { + SVGA3dCmdDXDestroyRasterizerState *pCmd = (SVGA3dCmdDXDestroyRasterizerState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyRasterizerState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE: + { + SVGA3dCmdDXDefineSamplerState *pCmd = (SVGA3dCmdDXDefineSamplerState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineSamplerState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE: + { + SVGA3dCmdDXDestroySamplerState *pCmd = (SVGA3dCmdDXDestroySamplerState *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroySamplerState(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_SHADER: + { + SVGA3dCmdDXDefineShader *pCmd = (SVGA3dCmdDXDefineShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineShader(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_SHADER: + { + SVGA3dCmdDXDestroyShader *pCmd = (SVGA3dCmdDXDestroyShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyShader(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BIND_SHADER: + { + SVGA3dCmdDXBindShader *pCmd = (SVGA3dCmdDXBindShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBindShader(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT: + { + SVGA3dCmdDXDefineStreamOutput *pCmd = (SVGA3dCmdDXDefineStreamOutput *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineStreamOutput(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT: + { + SVGA3dCmdDXDestroyStreamOutput *pCmd = (SVGA3dCmdDXDestroyStreamOutput *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyStreamOutput(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_STREAMOUTPUT: + { + SVGA3dCmdDXSetStreamOutput *pCmd = (SVGA3dCmdDXSetStreamOutput *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetStreamOutput(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_COTABLE: + { + SVGA3dCmdDXSetCOTable *pCmd = (SVGA3dCmdDXSetCOTable *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetCOTable(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_READBACK_COTABLE: + { + SVGA3dCmdDXReadbackCOTable *pCmd = (SVGA3dCmdDXReadbackCOTable *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXReadbackCOTable(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BUFFER_COPY: + { + SVGA3dCmdDXBufferCopy *pCmd = (SVGA3dCmdDXBufferCopy *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBufferCopy(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER: + { + SVGA3dCmdDXTransferFromBuffer *pCmd = (SVGA3dCmdDXTransferFromBuffer *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXTransferFromBuffer(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK: + { + SVGA3dCmdDXSurfaceCopyAndReadback *pCmd = (SVGA3dCmdDXSurfaceCopyAndReadback *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSurfaceCopyAndReadback(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_MOVE_QUERY: + { + SVGA3dCmdDXMoveQuery *pCmd = (SVGA3dCmdDXMoveQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXMoveQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BIND_ALL_QUERY: + { + SVGA3dCmdDXBindAllQuery *pCmd = (SVGA3dCmdDXBindAllQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBindAllQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_READBACK_ALL_QUERY: + { + SVGA3dCmdDXReadbackAllQuery *pCmd = (SVGA3dCmdDXReadbackAllQuery *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXReadbackAllQuery(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER: + { + SVGA3dCmdDXPredTransferFromBuffer *pCmd = (SVGA3dCmdDXPredTransferFromBuffer *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXPredTransferFromBuffer(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_MOB_FENCE_64: + { + SVGA3dCmdDXMobFence64 *pCmd = (SVGA3dCmdDXMobFence64 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXMobFence64(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BIND_ALL_SHADER: + { + SVGA3dCmdDXBindAllShader *pCmd = (SVGA3dCmdDXBindAllShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBindAllShader(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_HINT: + { + SVGA3dCmdDXHint *pCmd = (SVGA3dCmdDXHint *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXHint(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BUFFER_UPDATE: + { + SVGA3dCmdDXBufferUpdate *pCmd = (SVGA3dCmdDXBufferUpdate *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBufferUpdate(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET: + { + SVGA3dCmdDXSetVSConstantBufferOffset *pCmd = (SVGA3dCmdDXSetVSConstantBufferOffset *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetVSConstantBufferOffset(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET: + { + SVGA3dCmdDXSetPSConstantBufferOffset *pCmd = (SVGA3dCmdDXSetPSConstantBufferOffset *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetPSConstantBufferOffset(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET: + { + SVGA3dCmdDXSetGSConstantBufferOffset *pCmd = (SVGA3dCmdDXSetGSConstantBufferOffset *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetGSConstantBufferOffset(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_HS_CONSTANT_BUFFER_OFFSET: + { + SVGA3dCmdDXSetHSConstantBufferOffset *pCmd = (SVGA3dCmdDXSetHSConstantBufferOffset *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetHSConstantBufferOffset(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_DS_CONSTANT_BUFFER_OFFSET: + { + SVGA3dCmdDXSetDSConstantBufferOffset *pCmd = (SVGA3dCmdDXSetDSConstantBufferOffset *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetDSConstantBufferOffset(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_CS_CONSTANT_BUFFER_OFFSET: + { + SVGA3dCmdDXSetCSConstantBufferOffset *pCmd = (SVGA3dCmdDXSetCSConstantBufferOffset *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetCSConstantBufferOffset(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER: + { + SVGA3dCmdDXCondBindAllShader *pCmd = (SVGA3dCmdDXCondBindAllShader *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXCondBindAllShader(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_SCREEN_COPY: + { + SVGA3dCmdScreenCopy *pCmd = (SVGA3dCmdScreenCopy *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdScreenCopy(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_RESERVED1: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED2: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED3: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED4: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED5: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED6: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED7: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED8: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_GROW_OTABLE: + { + SVGA3dCmdGrowOTable *pCmd = (SVGA3dCmdGrowOTable *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdGrowOTable(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_GROW_COTABLE: + { + SVGA3dCmdDXGrowCOTable *pCmd = (SVGA3dCmdDXGrowCOTable *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXGrowCOTable(pThisCC, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_INTRA_SURFACE_COPY: + { + SVGA3dCmdIntraSurfaceCopy *pCmd = (SVGA3dCmdIntraSurfaceCopy *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdIntraSurfaceCopy(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_SURFACE_V3: + { + SVGA3dCmdDefineGBSurface_v3 *pCmd = (SVGA3dCmdDefineGBSurface_v3 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDefineGBSurface_v3(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_DX_RESOLVE_COPY: + { + SVGA3dCmdDXResolveCopy *pCmd = (SVGA3dCmdDXResolveCopy *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXResolveCopy(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_PRED_RESOLVE_COPY: + { + SVGA3dCmdDXPredResolveCopy *pCmd = (SVGA3dCmdDXPredResolveCopy *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXPredResolveCopy(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_PRED_CONVERT_REGION: + { + SVGA3dCmdDXPredConvertRegion *pCmd = (SVGA3dCmdDXPredConvertRegion *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXPredConvertRegion(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_PRED_CONVERT: + { + SVGA3dCmdDXPredConvert *pCmd = (SVGA3dCmdDXPredConvert *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXPredConvert(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_WHOLE_SURFACE_COPY: + { + SVGA3dCmdWholeSurfaceCopy *pCmd = (SVGA3dCmdWholeSurfaceCopy *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdWholeSurfaceCopy(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_UA_VIEW: + { + SVGA3dCmdDXDefineUAView *pCmd = (SVGA3dCmdDXDefineUAView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineUAView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DESTROY_UA_VIEW: + { + SVGA3dCmdDXDestroyUAView *pCmd = (SVGA3dCmdDXDestroyUAView *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDestroyUAView(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT: + { + SVGA3dCmdDXClearUAViewUint *pCmd = (SVGA3dCmdDXClearUAViewUint *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXClearUAViewUint(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT: + { + SVGA3dCmdDXClearUAViewFloat *pCmd = (SVGA3dCmdDXClearUAViewFloat *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXClearUAViewFloat(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT: + { + SVGA3dCmdDXCopyStructureCount *pCmd = (SVGA3dCmdDXCopyStructureCount *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXCopyStructureCount(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_UA_VIEWS: + { + SVGA3dCmdDXSetUAViews *pCmd = (SVGA3dCmdDXSetUAViews *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetUAViews(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT: + { + SVGA3dCmdDXDrawIndexedInstancedIndirect *pCmd = (SVGA3dCmdDXDrawIndexedInstancedIndirect *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDrawIndexedInstancedIndirect(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT: + { + SVGA3dCmdDXDrawInstancedIndirect *pCmd = (SVGA3dCmdDXDrawInstancedIndirect *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDrawInstancedIndirect(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DISPATCH: + { + SVGA3dCmdDXDispatch *pCmd = (SVGA3dCmdDXDispatch *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDispatch(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DISPATCH_INDIRECT: + { + SVGA3dCmdDXDispatchIndirect *pCmd = (SVGA3dCmdDXDispatchIndirect *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDispatchIndirect(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_WRITE_ZERO_SURFACE: + { + SVGA3dCmdWriteZeroSurface *pCmd = (SVGA3dCmdWriteZeroSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdWriteZeroSurface(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_HINT_ZERO_SURFACE: + { + SVGA3dCmdHintZeroSurface *pCmd = (SVGA3dCmdHintZeroSurface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdHintZeroSurface(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_TRANSFER_TO_BUFFER: + { + SVGA3dCmdDXTransferToBuffer *pCmd = (SVGA3dCmdDXTransferToBuffer *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXTransferToBuffer(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_STRUCTURE_COUNT: + { + SVGA3dCmdDXSetStructureCount *pCmd = (SVGA3dCmdDXSetStructureCount *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetStructureCount(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_LOGICOPS_BITBLT: + { + SVGA3dCmdLogicOpsBitBlt *pCmd = (SVGA3dCmdLogicOpsBitBlt *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdLogicOpsBitBlt(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_LOGICOPS_TRANSBLT: + { + SVGA3dCmdLogicOpsTransBlt *pCmd = (SVGA3dCmdLogicOpsTransBlt *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdLogicOpsTransBlt(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_LOGICOPS_STRETCHBLT: + { + SVGA3dCmdLogicOpsStretchBlt *pCmd = (SVGA3dCmdLogicOpsStretchBlt *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdLogicOpsStretchBlt(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_LOGICOPS_COLORFILL: + { + SVGA3dCmdLogicOpsColorFill *pCmd = (SVGA3dCmdLogicOpsColorFill *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdLogicOpsColorFill(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_LOGICOPS_ALPHABLEND: + { + SVGA3dCmdLogicOpsAlphaBlend *pCmd = (SVGA3dCmdLogicOpsAlphaBlend *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdLogicOpsAlphaBlend(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND: + { + SVGA3dCmdLogicOpsClearTypeBlend *pCmd = (SVGA3dCmdLogicOpsClearTypeBlend *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdLogicOpsClearTypeBlend(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_RESERVED2_1: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED2_2: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_DEFINE_GB_SURFACE_V4: + { + SVGA3dCmdDefineGBSurface_v4 *pCmd = (SVGA3dCmdDefineGBSurface_v4 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDefineGBSurface_v4(pThisCC, pCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_CS_UA_VIEWS: + { + SVGA3dCmdDXSetCSUAViews *pCmd = (SVGA3dCmdDXSetCSUAViews *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetCSUAViews(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_MIN_LOD: + { + SVGA3dCmdDXSetMinLOD *pCmd = (SVGA3dCmdDXSetMinLOD *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetMinLOD(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_RESERVED2_3: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_RESERVED2_4: + { + VMSVGA_3D_CMD_NOTIMPL(); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2: + { + SVGA3dCmdDXDefineDepthStencilView_v2 *pCmd = (SVGA3dCmdDXDefineDepthStencilView_v2 *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineDepthStencilView_v2(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB: + { + SVGA3dCmdDXDefineStreamOutputWithMob *pCmd = (SVGA3dCmdDXDefineStreamOutputWithMob *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXDefineStreamOutputWithMob(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_SET_SHADER_IFACE: + { + SVGA3dCmdDXSetShaderIface *pCmd = (SVGA3dCmdDXSetShaderIface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXSetShaderIface(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BIND_STREAMOUTPUT: + { + SVGA3dCmdDXBindStreamOutput *pCmd = (SVGA3dCmdDXBindStreamOutput *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBindStreamOutput(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_SURFACE_STRETCHBLT_NON_MS_TO_MS: + { + SVGA3dCmdSurfaceStretchBltNonMSToMS *pCmd = (SVGA3dCmdSurfaceStretchBltNonMSToMS *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdSurfaceStretchBltNonMSToMS(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_DX_BIND_SHADER_IFACE: + { + SVGA3dCmdDXBindShaderIface *pCmd = (SVGA3dCmdDXBindShaderIface *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdDXBindShaderIface(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + case SVGA_3D_CMD_VB_DX_CLEAR_RENDERTARGET_VIEW_REGION: + { + SVGA3dCmdVBDXClearRenderTargetViewRegion *pCmd = (SVGA3dCmdVBDXClearRenderTargetViewRegion *)pvCmd; + VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd)); + rcParse = vmsvga3dCmdVBDXClearRenderTargetViewRegion(pThisCC, idDXContext, pCmd, cbCmd); + break; + } + + /* Unsupported commands. */ + case SVGA_3D_CMD_DEAD4: /* SVGA_3D_CMD_VIDEO_CREATE_DECODER */ + case SVGA_3D_CMD_DEAD5: /* SVGA_3D_CMD_VIDEO_DESTROY_DECODER */ + case SVGA_3D_CMD_DEAD6: /* SVGA_3D_CMD_VIDEO_CREATE_PROCESSOR */ + case SVGA_3D_CMD_DEAD7: /* SVGA_3D_CMD_VIDEO_DESTROY_PROCESSOR */ + case SVGA_3D_CMD_DEAD8: /* SVGA_3D_CMD_VIDEO_DECODE_START_FRAME */ + case SVGA_3D_CMD_DEAD9: /* SVGA_3D_CMD_VIDEO_DECODE_RENDER */ + case SVGA_3D_CMD_DEAD10: /* SVGA_3D_CMD_VIDEO_DECODE_END_FRAME */ + case SVGA_3D_CMD_DEAD11: /* SVGA_3D_CMD_VIDEO_PROCESS_FRAME */ + /* Prevent the compiler warning. */ + case SVGA_3D_CMD_LEGACY_BASE: + case SVGA_3D_CMD_MAX: + case SVGA_3D_CMD_FUTURE_MAX: + /* No 'default' case */ + STAM_REL_COUNTER_INC(&pSvgaR3State->StatFifoUnkCmds); + ASSERT_GUEST_MSG_FAILED(("enmCmdId=%d\n", enmCmdId)); + LogRelMax(16, ("VMSVGA: unsupported 3D command %d\n", enmCmdId)); + rcParse = VERR_NOT_IMPLEMENTED; + break; + } + + return VINF_SUCCESS; +// return rcParse; +} +# undef VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK +#endif /* VBOX_WITH_VMSVGA3D */ + + +/* + * + * Handlers for FIFO commands. + * + * Every handler takes the following parameters: + * + * pThis The shared VGA/VMSVGA state. + * pThisCC The VGA/VMSVGA state for ring-3. + * pCmd The command data. + */ + + +/* SVGA_CMD_UPDATE */ +void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd) +{ + RT_NOREF(pThis); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdUpdate); + Log(("SVGA_CMD_UPDATE %d,%d %dx%d\n", pCmd->x, pCmd->y, pCmd->width, pCmd->height)); + + /** @todo Multiple screens? */ + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0); + if (!pScreen) /* Can happen if screen is not defined (aScreens[idScreen].fDefined == false) yet. */ + return; + + vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->x, pCmd->y, pCmd->width, pCmd->height); +} + + +/* SVGA_CMD_UPDATE_VERBOSE */ +void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd) +{ + RT_NOREF(pThis); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdUpdateVerbose); + Log(("SVGA_CMD_UPDATE_VERBOSE %d,%d %dx%d reason %#x\n", pCmd->x, pCmd->y, pCmd->width, pCmd->height, pCmd->reason)); + + /** @todo Multiple screens? */ + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0); + if (!pScreen) /* Can happen if screen is not defined (aScreens[idScreen].fDefined == false) yet. */ + return; + + vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->x, pCmd->y, pCmd->width, pCmd->height); +} + + +/* SVGA_CMD_RECT_FILL */ +void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd) +{ + RT_NOREF(pThis, pCmd); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectFill); + Log(("SVGA_CMD_RECT_FILL %08X @ %d,%d (%dx%d)\n", pCmd->pixel, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height)); + LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_RECT_FILL command ignored.\n")); +} + + +/* SVGA_CMD_RECT_COPY */ +void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectCopy); + Log(("SVGA_CMD_RECT_COPY %d,%d -> %d,%d %dx%d\n", pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height)); + + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0); + AssertPtrReturnVoid(pScreen); + + /* Check that arguments aren't complete junk. A precise check is done in vmsvgaR3RectCopy(). */ + ASSERT_GUEST_RETURN_VOID(pCmd->srcX < pThis->svga.u32MaxWidth); + ASSERT_GUEST_RETURN_VOID(pCmd->destX < pThis->svga.u32MaxWidth); + ASSERT_GUEST_RETURN_VOID(pCmd->width < pThis->svga.u32MaxWidth); + ASSERT_GUEST_RETURN_VOID(pCmd->srcY < pThis->svga.u32MaxHeight); + ASSERT_GUEST_RETURN_VOID(pCmd->destY < pThis->svga.u32MaxHeight); + ASSERT_GUEST_RETURN_VOID(pCmd->height < pThis->svga.u32MaxHeight); + + vmsvgaR3RectCopy(pThisCC, pScreen, pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, + pCmd->width, pCmd->height, pThis->vram_size); + vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height); +} + + +/* SVGA_CMD_RECT_ROP_COPY */ +void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectRopCopy); + Log(("SVGA_CMD_RECT_ROP_COPY %d,%d -> %d,%d %dx%d ROP %#X\n", pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height, pCmd->rop)); + + if (pCmd->rop != SVGA_ROP_COPY) + { + /* We only support the plain copy ROP which makes SVGA_CMD_RECT_ROP_COPY exactly the same + * as SVGA_CMD_RECT_COPY. XFree86 4.1.0 and 4.2.0 drivers (driver version 10.4.0 and 10.7.0, + * respectively) issue SVGA_CMD_RECT_ROP_COPY when SVGA_CAP_RECT_COPY is present even when + * SVGA_CAP_RASTER_OP is not. However, the ROP will always be SVGA_ROP_COPY. + */ + LogRelMax(4, ("VMSVGA: SVGA_CMD_RECT_ROP_COPY %d,%d -> %d,%d (%dx%d) ROP %X unsupported\n", + pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height, pCmd->rop)); + return; + } + + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0); + AssertPtrReturnVoid(pScreen); + + /* Check that arguments aren't complete junk. A precise check is done in vmsvgaR3RectCopy(). */ + ASSERT_GUEST_RETURN_VOID(pCmd->srcX < pThis->svga.u32MaxWidth); + ASSERT_GUEST_RETURN_VOID(pCmd->destX < pThis->svga.u32MaxWidth); + ASSERT_GUEST_RETURN_VOID(pCmd->width < pThis->svga.u32MaxWidth); + ASSERT_GUEST_RETURN_VOID(pCmd->srcY < pThis->svga.u32MaxHeight); + ASSERT_GUEST_RETURN_VOID(pCmd->destY < pThis->svga.u32MaxHeight); + ASSERT_GUEST_RETURN_VOID(pCmd->height < pThis->svga.u32MaxHeight); + + vmsvgaR3RectCopy(pThisCC, pScreen, pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, + pCmd->width, pCmd->height, pThis->vram_size); + vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height); +} + + +/* SVGA_CMD_DISPLAY_CURSOR */ +void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd) +{ + RT_NOREF(pThis, pCmd); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDisplayCursor); + Log(("SVGA_CMD_DISPLAY_CURSOR id=%d state=%d\n", pCmd->id, pCmd->state)); + LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_DISPLAY_CURSOR command ignored.\n")); +} + + +/* SVGA_CMD_MOVE_CURSOR */ +void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd) +{ + RT_NOREF(pThis, pCmd); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdMoveCursor); + Log(("SVGA_CMD_MOVE_CURSOR to %d,%d\n", pCmd->pos.x, pCmd->pos.y)); + LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_MOVE_CURSOR command ignored.\n")); +} + + +/* SVGA_CMD_DEFINE_CURSOR */ +void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineCursor); + Log(("SVGA_CMD_DEFINE_CURSOR id=%d size (%dx%d) hotspot (%d,%d) andMaskDepth=%d xorMaskDepth=%d\n", + pCmd->id, pCmd->width, pCmd->height, pCmd->hotspotX, pCmd->hotspotY, pCmd->andMaskDepth, pCmd->xorMaskDepth)); + + ASSERT_GUEST_RETURN_VOID(pCmd->height < 2048 && pCmd->width < 2048); + ASSERT_GUEST_RETURN_VOID(pCmd->andMaskDepth <= 32); + ASSERT_GUEST_RETURN_VOID(pCmd->xorMaskDepth <= 32); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const cbSrcAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8; + uint32_t const cbSrcAndMask = cbSrcAndLine * pCmd->height; + uint32_t const cbSrcXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8; + + uint8_t const *pbSrcAndMask = (uint8_t const *)(pCmd + 1); + uint8_t const *pbSrcXorMask = (uint8_t const *)(pCmd + 1) + cbSrcAndMask; + + uint32_t const cx = pCmd->width; + uint32_t const cy = pCmd->height; + + /* + * Convert the input to 1-bit AND mask and a 32-bit BRGA XOR mask. + * The AND data uses 8-bit aligned scanlines. + * The XOR data must be starting on a 32-bit boundrary. + */ + uint32_t cbDstAndLine = RT_ALIGN_32(cx, 8) / 8; + uint32_t cbDstAndMask = cbDstAndLine * cy; + uint32_t cbDstXorMask = cx * sizeof(uint32_t) * cy; + uint32_t cbCopy = RT_ALIGN_32(cbDstAndMask, 4) + cbDstXorMask; + + uint8_t *pbCopy = (uint8_t *)RTMemAlloc(cbCopy); + AssertReturnVoid(pbCopy); + + /* Convert the AND mask. */ + uint8_t *pbDst = pbCopy; + uint8_t const *pbSrc = pbSrcAndMask; + switch (pCmd->andMaskDepth) + { + case 1: + if (cbSrcAndLine == cbDstAndLine) + memcpy(pbDst, pbSrc, cbSrcAndLine * cy); + else + { + Assert(cbSrcAndLine > cbDstAndLine); /* lines are dword alined in source, but only byte in destination. */ + for (uint32_t y = 0; y < cy; y++) + { + memcpy(pbDst, pbSrc, cbDstAndLine); + pbDst += cbDstAndLine; + pbSrc += cbSrcAndLine; + } + } + break; + /* Should take the XOR mask into account for the multi-bit AND mask. */ + case 8: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; ) + { + uint8_t bDst = 0; + uint8_t fBit = 0x80; + do + { + uintptr_t const idxPal = pbSrc[x] * 3; + if ((( pThis->last_palette[idxPal] + | (pThis->last_palette[idxPal] >> 8) + | (pThis->last_palette[idxPal] >> 16)) & 0xff) > 0xfc) + bDst |= fBit; + fBit >>= 1; + x++; + } while (x < cx && (x & 7)); + pbDst[(x - 1) / 8] = bDst; + } + pbDst += cbDstAndLine; + pbSrc += cbSrcAndLine; + } + break; + case 15: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; ) + { + uint8_t bDst = 0; + uint8_t fBit = 0x80; + do + { + if ((pbSrc[x * 2] | (pbSrc[x * 2 + 1] & 0x7f)) >= 0xfc) + bDst |= fBit; + fBit >>= 1; + x++; + } while (x < cx && (x & 7)); + pbDst[(x - 1) / 8] = bDst; + } + pbDst += cbDstAndLine; + pbSrc += cbSrcAndLine; + } + break; + case 16: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; ) + { + uint8_t bDst = 0; + uint8_t fBit = 0x80; + do + { + if ((pbSrc[x * 2] | pbSrc[x * 2 + 1]) >= 0xfc) + bDst |= fBit; + fBit >>= 1; + x++; + } while (x < cx && (x & 7)); + pbDst[(x - 1) / 8] = bDst; + } + pbDst += cbDstAndLine; + pbSrc += cbSrcAndLine; + } + break; + case 24: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; ) + { + uint8_t bDst = 0; + uint8_t fBit = 0x80; + do + { + if ((pbSrc[x * 3] | pbSrc[x * 3 + 1] | pbSrc[x * 3 + 2]) >= 0xfc) + bDst |= fBit; + fBit >>= 1; + x++; + } while (x < cx && (x & 7)); + pbDst[(x - 1) / 8] = bDst; + } + pbDst += cbDstAndLine; + pbSrc += cbSrcAndLine; + } + break; + case 32: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; ) + { + uint8_t bDst = 0; + uint8_t fBit = 0x80; + do + { + if ((pbSrc[x * 4] | pbSrc[x * 4 + 1] | pbSrc[x * 4 + 2] | pbSrc[x * 4 + 3]) >= 0xfc) + bDst |= fBit; + fBit >>= 1; + x++; + } while (x < cx && (x & 7)); + pbDst[(x - 1) / 8] = bDst; + } + pbDst += cbDstAndLine; + pbSrc += cbSrcAndLine; + } + break; + default: + RTMemFreeZ(pbCopy, cbCopy); + AssertFailedReturnVoid(); + } + + /* Convert the XOR mask. */ + uint32_t *pu32Dst = (uint32_t *)(pbCopy + RT_ALIGN_32(cbDstAndMask, 4)); + pbSrc = pbSrcXorMask; + switch (pCmd->xorMaskDepth) + { + case 1: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; ) + { + /* most significant bit is the left most one. */ + uint8_t bSrc = pbSrc[x / 8]; + do + { + *pu32Dst++ = bSrc & 0x80 ? UINT32_C(0x00ffffff) : 0; + bSrc <<= 1; + x++; + } while ((x & 7) && x < cx); + } + pbSrc += cbSrcXorLine; + } + break; + case 8: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; x++) + { + uint32_t u = pThis->last_palette[pbSrc[x]]; + *pu32Dst++ = u;//RT_MAKE_U32_FROM_U8(RT_BYTE1(u), RT_BYTE2(u), RT_BYTE3(u), 0); + } + pbSrc += cbSrcXorLine; + } + break; + case 15: /* Src: RGB-5-5-5 */ + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; x++) + { + uint32_t const uValue = RT_MAKE_U16(pbSrc[x * 2], pbSrc[x * 2 + 1]); + *pu32Dst++ = RT_MAKE_U32_FROM_U8(( uValue & 0x1f) << 3, + ((uValue >> 5) & 0x1f) << 3, + ((uValue >> 10) & 0x1f) << 3, 0); + } + pbSrc += cbSrcXorLine; + } + break; + case 16: /* Src: RGB-5-6-5 */ + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; x++) + { + uint32_t const uValue = RT_MAKE_U16(pbSrc[x * 2], pbSrc[x * 2 + 1]); + *pu32Dst++ = RT_MAKE_U32_FROM_U8(( uValue & 0x1f) << 3, + ((uValue >> 5) & 0x3f) << 2, + ((uValue >> 11) & 0x1f) << 3, 0); + } + pbSrc += cbSrcXorLine; + } + break; + case 24: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; x++) + *pu32Dst++ = RT_MAKE_U32_FROM_U8(pbSrc[x*3], pbSrc[x*3 + 1], pbSrc[x*3 + 2], 0); + pbSrc += cbSrcXorLine; + } + break; + case 32: + for (uint32_t y = 0; y < cy; y++) + { + for (uint32_t x = 0; x < cx; x++) + *pu32Dst++ = RT_MAKE_U32_FROM_U8(pbSrc[x*4], pbSrc[x*4 + 1], pbSrc[x*4 + 2], 0); + pbSrc += cbSrcXorLine; + } + break; + default: + RTMemFreeZ(pbCopy, cbCopy); + AssertFailedReturnVoid(); + } + + /* + * Pass it to the frontend/whatever. + */ + vmsvgaR3InstallNewCursor(pThisCC, pSvgaR3State, false /*fAlpha*/, pCmd->hotspotX, pCmd->hotspotY, + cx, cy, pbCopy, cbCopy); +} + + +/* SVGA_CMD_DEFINE_ALPHA_CURSOR */ +void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd) +{ + RT_NOREF(pThis); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineAlphaCursor); + Log(("VMSVGA cmd: SVGA_CMD_DEFINE_ALPHA_CURSOR id=%d size (%dx%d) hotspot (%d,%d)\n", pCmd->id, pCmd->width, pCmd->height, pCmd->hotspotX, pCmd->hotspotY)); + + /* Check against a reasonable upper limit to prevent integer overflows in the sanity checks below. */ + ASSERT_GUEST_RETURN_VOID(pCmd->height < 2048 && pCmd->width < 2048); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* The mouse pointer interface always expects an AND mask followed by the color data (XOR mask). */ + uint32_t cbAndMask = (pCmd->width + 7) / 8 * pCmd->height; /* size of the AND mask */ + cbAndMask = ((cbAndMask + 3) & ~3); /* + gap for alignment */ + uint32_t cbXorMask = pCmd->width * sizeof(uint32_t) * pCmd->height; /* + size of the XOR mask (32-bit BRGA format) */ + uint32_t cbCursorShape = cbAndMask + cbXorMask; + + uint8_t *pCursorCopy = (uint8_t *)RTMemAlloc(cbCursorShape); + AssertPtrReturnVoid(pCursorCopy); + + /* Transparency is defined by the alpha bytes, so make the whole bitmap visible. */ + memset(pCursorCopy, 0xff, cbAndMask); + /* Colour data */ + memcpy(pCursorCopy + cbAndMask, pCmd + 1, cbXorMask); + + vmsvgaR3InstallNewCursor(pThisCC, pSvgaR3State, true /*fAlpha*/, pCmd->hotspotX, pCmd->hotspotY, + pCmd->width, pCmd->height, pCursorCopy, cbCursorShape); +} + + +/* SVGA_CMD_ESCAPE */ +void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd) +{ + RT_NOREF(pThis); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdEscape); + + if (pCmd->nsid == SVGA_ESCAPE_NSID_VMWARE) + { + ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(uint32_t)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const cmd = *(uint32_t *)(pCmd + 1); + Log(("SVGA_CMD_ESCAPE (%#x %#x) VMWARE cmd=%#x\n", pCmd->nsid, pCmd->size, cmd)); + + switch (cmd) + { + case SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: + { + SVGAEscapeVideoSetRegs *pVideoCmd = (SVGAEscapeVideoSetRegs *)(pCmd + 1); + ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(pVideoCmd->header)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const cRegs = (pCmd->size - sizeof(pVideoCmd->header)) / sizeof(pVideoCmd->items[0]); + + Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: stream %#x\n", pVideoCmd->header.streamId)); + for (uint32_t iReg = 0; iReg < cRegs; iReg++) + Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: reg %#x val %#x\n", pVideoCmd->items[iReg].registerId, pVideoCmd->items[iReg].value)); + RT_NOREF_PV(pVideoCmd); + break; + } + + case SVGA_ESCAPE_VMWARE_VIDEO_FLUSH: + { + SVGAEscapeVideoFlush *pVideoCmd = (SVGAEscapeVideoFlush *)(pCmd + 1); + ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(*pVideoCmd)); + Log(("SVGA_ESCAPE_VMWARE_VIDEO_FLUSH: stream %#x\n", pVideoCmd->streamId)); + RT_NOREF_PV(pVideoCmd); + break; + } + + default: + Log(("SVGA_CMD_ESCAPE: Unknown vmware escape: %#x\n", cmd)); + break; + } + } + else + Log(("SVGA_CMD_ESCAPE %#x %#x\n", pCmd->nsid, pCmd->size)); +} + + +/* SVGA_CMD_DEFINE_SCREEN */ +void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineScreen); + Log(("SVGA_CMD_DEFINE_SCREEN id=%x flags=%x size=(%d,%d) root=(%d,%d) %d:0x%x 0x%x\n", + pCmd->screen.id, pCmd->screen.flags, pCmd->screen.size.width, pCmd->screen.size.height, pCmd->screen.root.x, pCmd->screen.root.y, + pCmd->screen.backingStore.ptr.gmrId, pCmd->screen.backingStore.ptr.offset, pCmd->screen.backingStore.pitch)); + + uint32_t const idScreen = pCmd->screen.id; + ASSERT_GUEST_RETURN_VOID(idScreen < RT_ELEMENTS(pSvgaR3State->aScreens)); + + uint32_t const uWidth = pCmd->screen.size.width; + ASSERT_GUEST_RETURN_VOID(uWidth <= pThis->svga.u32MaxWidth); + + uint32_t const uHeight = pCmd->screen.size.height; + ASSERT_GUEST_RETURN_VOID(uHeight <= pThis->svga.u32MaxHeight); + + uint32_t const cbWidth = uWidth * ((32 + 7) / 8); /** @todo 32? */ + uint32_t const cbPitch = pCmd->screen.backingStore.pitch ? pCmd->screen.backingStore.pitch : cbWidth; + ASSERT_GUEST_RETURN_VOID(cbWidth <= cbPitch); + + uint32_t const uScreenOffset = pCmd->screen.backingStore.ptr.offset; + ASSERT_GUEST_RETURN_VOID(uScreenOffset < pThis->vram_size); + + uint32_t const cbVram = pThis->vram_size - uScreenOffset; + /* If we have a not zero pitch, then height can't exceed the available VRAM. */ + ASSERT_GUEST_RETURN_VOID( (uHeight == 0 && cbPitch == 0) + || (cbPitch > 0 && uHeight <= cbVram / cbPitch)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[idScreen]; + Assert(pScreen->idScreen == idScreen); + pScreen->fDefined = true; + pScreen->fModified = true; + pScreen->fuScreen = pCmd->screen.flags; + if (!RT_BOOL(pCmd->screen.flags & (SVGA_SCREEN_DEACTIVATE | SVGA_SCREEN_BLANKING))) + { + /* Not blanked. */ + ASSERT_GUEST_RETURN_VOID(uWidth > 0 && uHeight > 0); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pScreen->xOrigin = pCmd->screen.root.x; + pScreen->yOrigin = pCmd->screen.root.y; + pScreen->cWidth = uWidth; + pScreen->cHeight = uHeight; + pScreen->offVRAM = uScreenOffset; + pScreen->cbPitch = cbPitch; + pScreen->cBpp = 32; + } + else + { + /* Screen blanked. Keep old values. */ + } + + pThis->svga.fGFBRegisters = false; + vmsvgaR3ChangeMode(pThis, pThisCC); + +#ifdef VBOX_WITH_VMSVGA3D + if (RT_LIKELY(pThis->svga.f3DEnabled)) + vmsvga3dDefineScreen(pThis, pThisCC, pScreen); +#endif +} + + +/* SVGA_CMD_DESTROY_SCREEN */ +void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDestroyScreen); + Log(("SVGA_CMD_DESTROY_SCREEN id=%x\n", pCmd->screenId)); + + uint32_t const idScreen = pCmd->screenId; + ASSERT_GUEST_RETURN_VOID(idScreen < RT_ELEMENTS(pSvgaR3State->aScreens)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[idScreen]; + Assert(pScreen->idScreen == idScreen); + vmsvgaR3DestroyScreen(pThis, pThisCC, pScreen); +} + + +/* SVGA_CMD_DEFINE_GMRFB */ +void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd) +{ + RT_NOREF(pThis); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmrFb); + Log(("SVGA_CMD_DEFINE_GMRFB gmr=%x offset=%x bytesPerLine=%x bpp=%d color depth=%d\n", + pCmd->ptr.gmrId, pCmd->ptr.offset, pCmd->bytesPerLine, pCmd->format.bitsPerPixel, pCmd->format.colorDepth)); + + pSvgaR3State->GMRFB.ptr = pCmd->ptr; + pSvgaR3State->GMRFB.bytesPerLine = pCmd->bytesPerLine; + pSvgaR3State->GMRFB.format = pCmd->format; +} + + +/* SVGA_CMD_BLIT_GMRFB_TO_SCREEN */ +void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdBlitGmrFbToScreen); + Log(("SVGA_CMD_BLIT_GMRFB_TO_SCREEN src=(%d,%d) dest id=%d (%d,%d)(%d,%d)\n", + pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->destScreenId, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right, pCmd->destRect.bottom)); + + ASSERT_GUEST_RETURN_VOID(pCmd->destScreenId < RT_ELEMENTS(pSvgaR3State->aScreens)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, pCmd->destScreenId); + AssertPtrReturnVoid(pScreen); + + /** @todo Support GMRFB.format.s.bitsPerPixel != pThis->svga.uBpp ? */ + AssertReturnVoid(pSvgaR3State->GMRFB.format.bitsPerPixel == pScreen->cBpp); + + /* Clip destRect to the screen dimensions. */ + SVGASignedRect screenRect; + screenRect.left = 0; + screenRect.top = 0; + screenRect.right = pScreen->cWidth; + screenRect.bottom = pScreen->cHeight; + SVGASignedRect clipRect = pCmd->destRect; + vmsvgaR3ClipRect(&screenRect, &clipRect); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const width = clipRect.right - clipRect.left; + uint32_t const height = clipRect.bottom - clipRect.top; + + if ( width == 0 + || height == 0) + return; /* Nothing to do. */ + + int32_t const srcx = pCmd->srcOrigin.x + (clipRect.left - pCmd->destRect.left); + int32_t const srcy = pCmd->srcOrigin.y + (clipRect.top - pCmd->destRect.top); + + /* Copy the defined by GMRFB image to the screen 0 VRAM area. + * Prepare parameters for vmsvgaR3GmrTransfer. + */ + AssertReturnVoid(pScreen->offVRAM < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */ + + /* Destination: host buffer which describes the screen 0 VRAM. + * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaR3GmrTransfer. + */ + uint8_t * const pbHstBuf = (uint8_t *)pThisCC->pbVRam + pScreen->offVRAM; + uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch : + width * (RT_ALIGN(pScreen->cBpp, 8) / 8); + uint32_t cbHstBuf = cbScanline * pScreen->cHeight; + if (cbHstBuf > pThis->vram_size - pScreen->offVRAM) + cbHstBuf = pThis->vram_size - pScreen->offVRAM; /* Paranoia. */ + uint32_t const offHst = (clipRect.left * RT_ALIGN(pScreen->cBpp, 8)) / 8 + + cbScanline * clipRect.top; + int32_t const cbHstPitch = cbScanline; + + /* Source: GMRFB. vmsvgaR3GmrTransfer ensures that no memory outside the GMR is read. */ + SVGAGuestPtr const gstPtr = pSvgaR3State->GMRFB.ptr; + uint32_t const offGst = (srcx * RT_ALIGN(pSvgaR3State->GMRFB.format.bitsPerPixel, 8)) / 8 + + pSvgaR3State->GMRFB.bytesPerLine * srcy; + int32_t const cbGstPitch = pSvgaR3State->GMRFB.bytesPerLine; + + int rc = vmsvgaR3GmrTransfer(pThis, pThisCC, SVGA3D_WRITE_HOST_VRAM, + pbHstBuf, cbHstBuf, offHst, cbHstPitch, + gstPtr, offGst, cbGstPitch, + (width * RT_ALIGN(pScreen->cBpp, 8)) / 8, height); + AssertRC(rc); + vmsvgaR3UpdateScreen(pThisCC, pScreen, clipRect.left, clipRect.top, width, height); +} + + +/* SVGA_CMD_BLIT_SCREEN_TO_GMRFB */ +void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdBlitScreentoGmrFb); + /* Note! This can fetch 3d render results as well!! */ + Log(("SVGA_CMD_BLIT_SCREEN_TO_GMRFB dest=(%d,%d) src id=%d (%d,%d)(%d,%d)\n", + pCmd->destOrigin.x, pCmd->destOrigin.y, pCmd->srcScreenId, pCmd->srcRect.left, pCmd->srcRect.top, pCmd->srcRect.right, pCmd->srcRect.bottom)); + + ASSERT_GUEST_RETURN_VOID(pCmd->srcScreenId < RT_ELEMENTS(pSvgaR3State->aScreens)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, pCmd->srcScreenId); + AssertPtrReturnVoid(pScreen); + + /** @todo Support GMRFB.format.bitsPerPixel != pThis->svga.uBpp ? */ + AssertReturnVoid(pSvgaR3State->GMRFB.format.bitsPerPixel == pScreen->cBpp); + + /* Clip destRect to the screen dimensions. */ + SVGASignedRect screenRect; + screenRect.left = 0; + screenRect.top = 0; + screenRect.right = pScreen->cWidth; + screenRect.bottom = pScreen->cHeight; + SVGASignedRect clipRect = pCmd->srcRect; + vmsvgaR3ClipRect(&screenRect, &clipRect); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const width = clipRect.right - clipRect.left; + uint32_t const height = clipRect.bottom - clipRect.top; + + if ( width == 0 + || height == 0) + return; /* Nothing to do. */ + + int32_t const dstx = pCmd->destOrigin.x + (clipRect.left - pCmd->srcRect.left); + int32_t const dsty = pCmd->destOrigin.y + (clipRect.top - pCmd->srcRect.top); + + /* Copy the defined by GMRFB image to the screen 0 VRAM area. + * Prepare parameters for vmsvgaR3GmrTransfer. + */ + AssertReturnVoid(pScreen->offVRAM < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */ + + /* Source: host buffer which describes the screen 0 VRAM. + * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaR3GmrTransfer. + */ + uint8_t * const pbHstBuf = (uint8_t *)pThisCC->pbVRam + pScreen->offVRAM; + uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch : + width * (RT_ALIGN(pScreen->cBpp, 8) / 8); + uint32_t cbHstBuf = cbScanline * pScreen->cHeight; + if (cbHstBuf > pThis->vram_size - pScreen->offVRAM) + cbHstBuf = pThis->vram_size - pScreen->offVRAM; /* Paranoia. */ + uint32_t const offHst = (clipRect.left * RT_ALIGN(pScreen->cBpp, 8)) / 8 + + cbScanline * clipRect.top; + int32_t const cbHstPitch = cbScanline; + + /* Destination: GMRFB. vmsvgaR3GmrTransfer ensures that no memory outside the GMR is read. */ + SVGAGuestPtr const gstPtr = pSvgaR3State->GMRFB.ptr; + uint32_t const offGst = (dstx * RT_ALIGN(pSvgaR3State->GMRFB.format.bitsPerPixel, 8)) / 8 + + pSvgaR3State->GMRFB.bytesPerLine * dsty; + int32_t const cbGstPitch = pSvgaR3State->GMRFB.bytesPerLine; + + int rc = vmsvgaR3GmrTransfer(pThis, pThisCC, SVGA3D_READ_HOST_VRAM, + pbHstBuf, cbHstBuf, offHst, cbHstPitch, + gstPtr, offGst, cbGstPitch, + (width * RT_ALIGN(pScreen->cBpp, 8)) / 8, height); + AssertRC(rc); +} + + +/* SVGA_CMD_ANNOTATION_FILL */ +void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd) +{ + RT_NOREF(pThis); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdAnnotationFill); + Log(("SVGA_CMD_ANNOTATION_FILL red=%x green=%x blue=%x\n", pCmd->color.r, pCmd->color.g, pCmd->color.b)); + + pSvgaR3State->colorAnnotation = pCmd->color; +} + + +/* SVGA_CMD_ANNOTATION_COPY */ +void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd) +{ + RT_NOREF(pThis, pCmd); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdAnnotationCopy); + Log(("SVGA_CMD_ANNOTATION_COPY srcOrigin %d,%d, srcScreenId %u\n", pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->srcScreenId)); + + AssertFailed(); +} + + +#ifdef VBOX_WITH_VMSVGA3D +/* SVGA_CMD_DEFINE_GMR2 */ +void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2); + Log(("SVGA_CMD_DEFINE_GMR2 id=%#x %#x pages\n", pCmd->gmrId, pCmd->numPages)); + + /* Validate current GMR id. */ + ASSERT_GUEST_RETURN_VOID(pCmd->gmrId < pThis->svga.cGMR); + ASSERT_GUEST_RETURN_VOID(pCmd->numPages <= VMSVGA_MAX_GMR_PAGES); + RT_UNTRUSTED_VALIDATED_FENCE(); + + if (!pCmd->numPages) + { + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2Free); + vmsvgaR3GmrFree(pThisCC, pCmd->gmrId); + } + else + { + PGMR pGMR = &pSvgaR3State->paGMR[pCmd->gmrId]; + if (pGMR->cMaxPages) + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2Modify); + + /* Not sure if we should always free the descriptor, but for simplicity + we do so if the new size is smaller than the current. */ + /** @todo always free the descriptor in SVGA_CMD_DEFINE_GMR2? */ + if (pGMR->cbTotal / X86_PAGE_SIZE > pCmd->numPages) + vmsvgaR3GmrFree(pThisCC, pCmd->gmrId); + + pGMR->cMaxPages = pCmd->numPages; + /* The rest is done by the REMAP_GMR2 command. */ + } +} + + +/* SVGA_CMD_REMAP_GMR2 */ +void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRemapGmr2); + Log(("SVGA_CMD_REMAP_GMR2 id=%#x flags=%#x offset=%#x npages=%#x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages)); + + /* Validate current GMR id and size. */ + ASSERT_GUEST_RETURN_VOID(pCmd->gmrId < pThis->svga.cGMR); + RT_UNTRUSTED_VALIDATED_FENCE(); + PGMR pGMR = &pSvgaR3State->paGMR[pCmd->gmrId]; + ASSERT_GUEST_RETURN_VOID( (uint64_t)pCmd->offsetPages + pCmd->numPages + <= RT_MIN(pGMR->cMaxPages, RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE))); + ASSERT_GUEST_RETURN_VOID(!pCmd->offsetPages || pGMR->paDesc); /** @todo */ + + if (pCmd->numPages == 0) + return; + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Calc new total page count so we can use it instead of cMaxPages for allocations below. */ + uint32_t const cNewTotalPages = RT_MAX(pGMR->cbTotal >> X86_PAGE_SHIFT, pCmd->offsetPages + pCmd->numPages); + + /* + * We flatten the existing descriptors into a page array, overwrite the + * pages specified in this command and then recompress the descriptor. + */ + /** @todo Optimize the GMR remap algorithm! */ + + /* Save the old page descriptors as an array of page frame numbers (address >> X86_PAGE_SHIFT) */ + uint64_t *paNewPage64 = NULL; + if (pGMR->paDesc) + { + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRemapGmr2Modify); + + paNewPage64 = (uint64_t *)RTMemAllocZ(cNewTotalPages * sizeof(uint64_t)); + AssertPtrReturnVoid(paNewPage64); + + uint32_t idxPage = 0; + for (uint32_t i = 0; i < pGMR->numDescriptors; i++) + for (uint32_t j = 0; j < pGMR->paDesc[i].numPages; j++) + paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * X86_PAGE_SIZE) >> X86_PAGE_SHIFT; + AssertReturnVoidStmt(idxPage == pGMR->cbTotal >> X86_PAGE_SHIFT, RTMemFree(paNewPage64)); + RT_UNTRUSTED_VALIDATED_FENCE(); + } + + /* Free the old GMR if present. */ + if (pGMR->paDesc) + RTMemFree(pGMR->paDesc); + + /* Allocate the maximum amount possible (everything non-continuous) */ + PVMSVGAGMRDESCRIPTOR paDescs; + pGMR->paDesc = paDescs = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cNewTotalPages * sizeof(VMSVGAGMRDESCRIPTOR)); + AssertReturnVoidStmt(paDescs, RTMemFree(paNewPage64)); + + if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR) + { + /** @todo */ + AssertFailed(); + pGMR->numDescriptors = 0; + } + else + { + uint32_t *paPages32 = (uint32_t *)(pCmd + 1); + uint64_t *paPages64 = (uint64_t *)(pCmd + 1); + bool fGCPhys64 = RT_BOOL(pCmd->flags & SVGA_REMAP_GMR2_PPN64); + + uint32_t cPages; + if (paNewPage64) + { + /* Overwrite the old page array with the new page values. */ + if (fGCPhys64) + for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++) + paNewPage64[i] = paPages64[i - pCmd->offsetPages]; + else + for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++) + paNewPage64[i] = paPages32[i - pCmd->offsetPages]; + + /* Use the updated page array instead of the command data. */ + fGCPhys64 = true; + paPages64 = paNewPage64; + cPages = cNewTotalPages; + } + else + cPages = pCmd->numPages; + + /* The first page. */ + /** @todo The 0x00000FFFFFFFFFFF mask limits to 44 bits and should not be + * applied to paNewPage64. */ + RTGCPHYS GCPhys; + if (fGCPhys64) + GCPhys = (paPages64[0] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */ + else + GCPhys = (RTGCPHYS)paPages32[0] << GUEST_PAGE_SHIFT; + paDescs[0].GCPhys = GCPhys; + paDescs[0].numPages = 1; + + /* Subsequent pages. */ + uint32_t iDescriptor = 0; + for (uint32_t i = 1; i < cPages; i++) + { + if (pCmd->flags & SVGA_REMAP_GMR2_PPN64) + GCPhys = (paPages64[i] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */ + else + GCPhys = (RTGCPHYS)paPages32[i] << X86_PAGE_SHIFT; + + /* Continuous physical memory? */ + if (GCPhys == paDescs[iDescriptor].GCPhys + paDescs[iDescriptor].numPages * X86_PAGE_SIZE) + { + Assert(paDescs[iDescriptor].numPages); + paDescs[iDescriptor].numPages++; + Log5Func(("Page %x GCPhys=%RGp successor\n", i, GCPhys)); + } + else + { + iDescriptor++; + paDescs[iDescriptor].GCPhys = GCPhys; + paDescs[iDescriptor].numPages = 1; + Log5Func(("Page %x GCPhys=%RGp\n", i, paDescs[iDescriptor].GCPhys)); + } + } + + pGMR->cbTotal = cNewTotalPages << X86_PAGE_SHIFT; + Log5Func(("Nr of descriptors %x; cbTotal=%#x\n", iDescriptor + 1, cNewTotalPages)); + pGMR->numDescriptors = iDescriptor + 1; + } + + if (paNewPage64) + RTMemFree(paNewPage64); +} + + +/** + * Free the specified GMR + * + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param idGMR GMR id + */ +void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR) +{ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + + /* Free the old descriptor if present. */ + PGMR pGMR = &pSVGAState->paGMR[idGMR]; + if ( pGMR->numDescriptors + || pGMR->paDesc /* needed till we implement SVGA_REMAP_GMR2_VIA_GMR */) + { +# ifdef DEBUG_GMR_ACCESS + VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThisCC->pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3DeregisterGmr, 2, pDevIns, idGMR); +# endif + + Assert(pGMR->paDesc); + RTMemFree(pGMR->paDesc); + pGMR->paDesc = NULL; + pGMR->numDescriptors = 0; + pGMR->cbTotal = 0; + pGMR->cMaxPages = 0; + } + Assert(!pGMR->cMaxPages); + Assert(!pGMR->cbTotal); +} +#endif /* VBOX_WITH_VMSVGA3D */ + + +/** + * Copy between a GMR and a host memory buffer. + * + * @returns VBox status code. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param enmTransferType Transfer type (read/write) + * @param pbHstBuf Host buffer pointer (valid) + * @param cbHstBuf Size of host buffer (valid) + * @param offHst Host buffer offset of the first scanline + * @param cbHstPitch Destination buffer pitch + * @param gstPtr GMR description + * @param offGst Guest buffer offset of the first scanline + * @param cbGstPitch Guest buffer pitch + * @param cbWidth Width in bytes to copy + * @param cHeight Number of scanllines to copy + */ +int vmsvgaR3GmrTransfer(PVGASTATE pThis, PVGASTATECC pThisCC, const SVGA3dTransferType enmTransferType, + uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch, + SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch, + uint32_t cbWidth, uint32_t cHeight) +{ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + PPDMDEVINS pDevIns = pThisCC->pDevIns; /* simpler */ + int rc; + + LogFunc(("%s host %p size=%d offset %d pitch=%d; guest gmr=%#x:%#x offset=%d pitch=%d cbWidth=%d cHeight=%d\n", + enmTransferType == SVGA3D_READ_HOST_VRAM ? "WRITE" : "READ", /* GMR op: READ host VRAM means WRITE GMR */ + pbHstBuf, cbHstBuf, offHst, cbHstPitch, + gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cbWidth, cHeight)); + AssertReturn(cbWidth && cHeight, VERR_INVALID_PARAMETER); + + PGMR pGMR; + uint32_t cbGmr; /* The GMR size in bytes. */ + if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER) + { + pGMR = NULL; + cbGmr = pThis->vram_size; + } + else + { + AssertReturn(gstPtr.gmrId < pThis->svga.cGMR, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + pGMR = &pSVGAState->paGMR[gstPtr.gmrId]; + cbGmr = pGMR->cbTotal; + } + + /* + * GMR + */ + /* Calculate GMR offset of the data to be copied. */ + AssertMsgReturn(gstPtr.offset < cbGmr, + ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n", + gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + AssertMsgReturn(offGst < cbGmr - gstPtr.offset, + ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n", + gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + uint32_t const offGmr = offGst + gstPtr.offset; /* Offset in the GMR, where the first scanline is located. */ + + /* Verify that cbWidth is less than scanline and fits into the GMR. */ + uint32_t const cbGmrScanline = cbGstPitch > 0 ? cbGstPitch : -cbGstPitch; + AssertMsgReturn(cbGmrScanline != 0, + ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n", + gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + AssertMsgReturn(cbWidth <= cbGmrScanline, + ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n", + gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr), + VERR_INVALID_PARAMETER); + AssertMsgReturn(cbWidth <= cbGmr - offGmr, + ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n", + gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* How many bytes are available for the data in the GMR. */ + uint32_t const cbGmrLeft = cbGstPitch > 0 ? cbGmr - offGmr : offGmr + cbWidth; + + /* How many scanlines would fit into the available data. */ + uint32_t cGmrScanlines = cbGmrLeft / cbGmrScanline; + uint32_t const cbGmrLastScanline = cbGmrLeft - cGmrScanlines * cbGmrScanline; /* Slack space. */ + if (cbWidth <= cbGmrLastScanline) + ++cGmrScanlines; + + if (cHeight > cGmrScanlines) + cHeight = cGmrScanlines; + + AssertMsgReturn(cHeight > 0, + ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n", + gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* + * Host buffer. + */ + AssertMsgReturn(offHst < cbHstBuf, + ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n", + pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth), + VERR_INVALID_PARAMETER); + + /* Verify that cbWidth is less than scanline and fits into the buffer. */ + uint32_t const cbHstScanline = cbHstPitch > 0 ? cbHstPitch : -cbHstPitch; + AssertMsgReturn(cbHstScanline != 0, + ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n", + pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth), + VERR_INVALID_PARAMETER); + AssertMsgReturn(cbWidth <= cbHstScanline, + ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n", + pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth), + VERR_INVALID_PARAMETER); + AssertMsgReturn(cbWidth <= cbHstBuf - offHst, + ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n", + pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth), + VERR_INVALID_PARAMETER); + + /* How many bytes are available for the data in the buffer. */ + uint32_t const cbHstLeft = cbHstPitch > 0 ? cbHstBuf - offHst : offHst + cbWidth; + + /* How many scanlines would fit into the available data. */ + uint32_t cHstScanlines = cbHstLeft / cbHstScanline; + uint32_t const cbHstLastScanline = cbHstLeft - cHstScanlines * cbHstScanline; /* Slack space. */ + if (cbWidth <= cbHstLastScanline) + ++cHstScanlines; + + if (cHeight > cHstScanlines) + cHeight = cHstScanlines; + + AssertMsgReturn(cHeight > 0, + ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n", + pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth), + VERR_INVALID_PARAMETER); + + uint8_t *pbHst = pbHstBuf + offHst; + + /* Shortcut for the framebuffer. */ + if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER) + { + uint8_t *pbGst = pThisCC->pbVRam + offGmr; + + uint8_t const *pbSrc; + int32_t cbSrcPitch; + uint8_t *pbDst; + int32_t cbDstPitch; + + if (enmTransferType == SVGA3D_READ_HOST_VRAM) + { + pbSrc = pbHst; + cbSrcPitch = cbHstPitch; + pbDst = pbGst; + cbDstPitch = cbGstPitch; + } + else + { + pbSrc = pbGst; + cbSrcPitch = cbGstPitch; + pbDst = pbHst; + cbDstPitch = cbHstPitch; + } + + if ( cbWidth == (uint32_t)cbGstPitch + && cbGstPitch == cbHstPitch) + { + /* Entire scanlines, positive pitch. */ + memcpy(pbDst, pbSrc, cbWidth * cHeight); + } + else + { + for (uint32_t i = 0; i < cHeight; ++i) + { + memcpy(pbDst, pbSrc, cbWidth); + + pbDst += cbDstPitch; + pbSrc += cbSrcPitch; + } + } + return VINF_SUCCESS; + } + + AssertPtrReturn(pGMR, VERR_INVALID_PARAMETER); + AssertReturn(pGMR->numDescriptors > 0, VERR_INVALID_PARAMETER); + + PVMSVGAGMRDESCRIPTOR const paDesc = pGMR->paDesc; /* Local copy of the pointer. */ + uint32_t iDesc = 0; /* Index in the descriptor array. */ + uint32_t offDesc = 0; /* GMR offset of the current descriptor. */ + uint32_t offGmrScanline = offGmr; /* GMR offset of the scanline which is being copied. */ + uint8_t *pbHstScanline = pbHst; /* Host address of the scanline which is being copied. */ + for (uint32_t i = 0; i < cHeight; ++i) + { + uint32_t cbCurrentWidth = cbWidth; + uint32_t offGmrCurrent = offGmrScanline; + uint8_t *pbCurrentHost = pbHstScanline; + + /* Find the right descriptor */ + while (offDesc + paDesc[iDesc].numPages * GUEST_PAGE_SIZE <= offGmrCurrent) + { + offDesc += paDesc[iDesc].numPages * GUEST_PAGE_SIZE; + AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR); /* overflow protection */ + ++iDesc; + AssertReturn(iDesc < pGMR->numDescriptors, VERR_INTERNAL_ERROR); + } + + while (cbCurrentWidth) + { + uint32_t cbToCopy; + + if (offGmrCurrent + cbCurrentWidth <= offDesc + paDesc[iDesc].numPages * GUEST_PAGE_SIZE) + cbToCopy = cbCurrentWidth; + else + { + cbToCopy = (offDesc + paDesc[iDesc].numPages * GUEST_PAGE_SIZE - offGmrCurrent); + AssertReturn(cbToCopy <= cbCurrentWidth, VERR_INVALID_PARAMETER); + } + + RTGCPHYS const GCPhys = paDesc[iDesc].GCPhys + offGmrCurrent - offDesc; + + Log5Func(("%s phys=%RGp\n", (enmTransferType == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", GCPhys)); + + /* + * We are deliberately using the non-PCI version of PDMDevHlpPCIPhys[Read|Write] as the + * guest-side VMSVGA driver seems to allocate non-DMA (physical memory) addresses, + * see @bugref{9654#c75}. + */ + if (enmTransferType == SVGA3D_WRITE_HOST_VRAM) + rc = PDMDevHlpPhysRead(pDevIns, GCPhys, pbCurrentHost, cbToCopy); + else + rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, pbCurrentHost, cbToCopy); + AssertRCBreak(rc); + + cbCurrentWidth -= cbToCopy; + offGmrCurrent += cbToCopy; + pbCurrentHost += cbToCopy; + + /* Go to the next descriptor if there's anything left. */ + if (cbCurrentWidth) + { + offDesc += paDesc[iDesc].numPages * GUEST_PAGE_SIZE; + AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR); + ++iDesc; + AssertReturn(iDesc < pGMR->numDescriptors, VERR_INTERNAL_ERROR); + } + } + + offGmrScanline += cbGstPitch; + pbHstScanline += cbHstPitch; + } + + return VINF_SUCCESS; +} + + +/** + * Unsigned coordinates in pBox. Clip to [0; pSizeSrc), [0; pSizeDest). + * + * @param pSizeSrc Source surface dimensions. + * @param pSizeDest Destination surface dimensions. + * @param pBox Coordinates to be clipped. + */ +void vmsvgaR3ClipCopyBox(const SVGA3dSize *pSizeSrc, const SVGA3dSize *pSizeDest, SVGA3dCopyBox *pBox) +{ + /* Src x, w */ + if (pBox->srcx > pSizeSrc->width) + pBox->srcx = pSizeSrc->width; + if (pBox->w > pSizeSrc->width - pBox->srcx) + pBox->w = pSizeSrc->width - pBox->srcx; + + /* Src y, h */ + if (pBox->srcy > pSizeSrc->height) + pBox->srcy = pSizeSrc->height; + if (pBox->h > pSizeSrc->height - pBox->srcy) + pBox->h = pSizeSrc->height - pBox->srcy; + + /* Src z, d */ + if (pBox->srcz > pSizeSrc->depth) + pBox->srcz = pSizeSrc->depth; + if (pBox->d > pSizeSrc->depth - pBox->srcz) + pBox->d = pSizeSrc->depth - pBox->srcz; + + /* Dest x, w */ + if (pBox->x > pSizeDest->width) + pBox->x = pSizeDest->width; + if (pBox->w > pSizeDest->width - pBox->x) + pBox->w = pSizeDest->width - pBox->x; + + /* Dest y, h */ + if (pBox->y > pSizeDest->height) + pBox->y = pSizeDest->height; + if (pBox->h > pSizeDest->height - pBox->y) + pBox->h = pSizeDest->height - pBox->y; + + /* Dest z, d */ + if (pBox->z > pSizeDest->depth) + pBox->z = pSizeDest->depth; + if (pBox->d > pSizeDest->depth - pBox->z) + pBox->d = pSizeDest->depth - pBox->z; +} + + +/** + * Unsigned coordinates in pBox. Clip to [0; pSize). + * + * @param pSize Source surface dimensions. + * @param pBox Coordinates to be clipped. + */ +void vmsvgaR3ClipBox(const SVGA3dSize *pSize, SVGA3dBox *pBox) +{ + /* x, w */ + if (pBox->x > pSize->width) + pBox->x = pSize->width; + if (pBox->w > pSize->width - pBox->x) + pBox->w = pSize->width - pBox->x; + + /* y, h */ + if (pBox->y > pSize->height) + pBox->y = pSize->height; + if (pBox->h > pSize->height - pBox->y) + pBox->h = pSize->height - pBox->y; + + /* z, d */ + if (pBox->z > pSize->depth) + pBox->z = pSize->depth; + if (pBox->d > pSize->depth - pBox->z) + pBox->d = pSize->depth - pBox->z; +} + + +/** + * Clip. + * + * @param pBound Bounding rectangle. + * @param pRect Rectangle to be clipped. + */ +void vmsvgaR3ClipRect(SVGASignedRect const *pBound, SVGASignedRect *pRect) +{ + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + + /* Right order. */ + Assert(pBound->left <= pBound->right && pBound->top <= pBound->bottom); + if (pRect->left < pRect->right) + { + left = pRect->left; + right = pRect->right; + } + else + { + left = pRect->right; + right = pRect->left; + } + if (pRect->top < pRect->bottom) + { + top = pRect->top; + bottom = pRect->bottom; + } + else + { + top = pRect->bottom; + bottom = pRect->top; + } + + if (left < pBound->left) + left = pBound->left; + if (right < pBound->left) + right = pBound->left; + + if (left > pBound->right) + left = pBound->right; + if (right > pBound->right) + right = pBound->right; + + if (top < pBound->top) + top = pBound->top; + if (bottom < pBound->top) + bottom = pBound->top; + + if (top > pBound->bottom) + top = pBound->bottom; + if (bottom > pBound->bottom) + bottom = pBound->bottom; + + pRect->left = left; + pRect->right = right; + pRect->top = top; + pRect->bottom = bottom; +} + + +/** + * Clip. + * + * @param pBound Bounding rectangle. + * @param pRect Rectangle to be clipped. + */ +void vmsvgaR3Clip3dRect(SVGA3dRect const *pBound, SVGA3dRect RT_UNTRUSTED_GUEST *pRect) +{ + uint32_t const leftBound = pBound->x; + uint32_t const rightBound = pBound->x + pBound->w; + uint32_t const topBound = pBound->y; + uint32_t const bottomBound = pBound->y + pBound->h; + + uint32_t x = pRect->x; + uint32_t y = pRect->y; + uint32_t w = pRect->w; + uint32_t h = pRect->h; + + /* Make sure that right and bottom coordinates can be safely computed. */ + if (x > rightBound) + x = rightBound; + if (w > rightBound - x) + w = rightBound - x; + if (y > bottomBound) + y = bottomBound; + if (h > bottomBound - y) + h = bottomBound - y; + + /* Switch from x, y, w, h to left, top, right, bottom. */ + uint32_t left = x; + uint32_t right = x + w; + uint32_t top = y; + uint32_t bottom = y + h; + + /* A standard left, right, bottom, top clipping. */ + if (left < leftBound) + left = leftBound; + if (right < leftBound) + right = leftBound; + + if (left > rightBound) + left = rightBound; + if (right > rightBound) + right = rightBound; + + if (top < topBound) + top = topBound; + if (bottom < topBound) + bottom = topBound; + + if (top > bottomBound) + top = bottomBound; + if (bottom > bottomBound) + bottom = bottomBound; + + /* Back to x, y, w, h representation. */ + pRect->x = left; + pRect->y = top; + pRect->w = right - left; + pRect->h = bottom - top; +} + diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA-internal.h b/src/VBox/Devices/Graphics/DevVGA-SVGA-internal.h new file mode 100644 index 00000000..0fb190d4 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA-internal.h @@ -0,0 +1,306 @@ +/* $Id: DevVGA-SVGA-internal.h $ */ +/** @file + * VMWare SVGA device - internal header for DevVGA-SVGA* source files. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_internal_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_internal_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* + * Assert sane compilation environment. + */ +#ifndef IN_RING3 +# error "DevVGA-SVGA-internal.h is only for ring-3 code" +#endif + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * 64-bit GMR descriptor. + */ +typedef struct +{ + RTGCPHYS GCPhys; + uint64_t numPages; +} VMSVGAGMRDESCRIPTOR, *PVMSVGAGMRDESCRIPTOR; + +/** + * GMR slot + */ +typedef struct +{ + uint32_t cMaxPages; + uint32_t cbTotal; + uint32_t numDescriptors; + PVMSVGAGMRDESCRIPTOR paDesc; +} GMR, *PGMR; + + +typedef struct VMSVGACMDBUF *PVMSVGACMDBUF; +typedef struct VMSVGACMDBUFCTX *PVMSVGACMDBUFCTX; + +/* Command buffer. */ +typedef struct VMSVGACMDBUF +{ + RTLISTNODE nodeBuffer; + /* Context of the buffer. */ + PVMSVGACMDBUFCTX pCmdBufCtx; + /* PA of the buffer. */ + RTGCPHYS GCPhysCB; + /* A copy of the buffer header. */ + SVGACBHeader hdr; + /* A copy of the commands. Size of the memory buffer is hdr.length */ + void *pvCommands; +} VMSVGACMDBUF; + +/* Command buffer context. */ +typedef struct VMSVGACMDBUFCTX +{ + /* Buffers submitted to processing for the FIFO thread. */ + RTLISTANCHOR listSubmitted; + /* How many buffers in the queue. */ + uint32_t cSubmitted; +} VMSVGACMDBUFCTX; + +/** + * Internal SVGA ring-3 only state. + */ +typedef struct VMSVGAR3STATE +{ + PPDMDEVINS pDevIns; /* Stored here to use with PDMDevHlp* */ + GMR *paGMR; // [VMSVGAState::cGMR] + struct + { + SVGAGuestPtr RT_UNTRUSTED_GUEST ptr; + uint32_t RT_UNTRUSTED_GUEST bytesPerLine; + SVGAGMRImageFormat RT_UNTRUSTED_GUEST format; + } GMRFB; + struct + { + bool fActive; + uint32_t xHotspot; + uint32_t yHotspot; + uint32_t width; + uint32_t height; + uint32_t cbData; + void *pData; + } Cursor; + SVGAColorBGRX colorAnnotation; + +# ifdef VMSVGA_USE_EMT_HALT_CODE + /** Number of EMTs in BusyDelayedEmts (quicker than scanning the set). */ + uint32_t volatile cBusyDelayedEmts; + /** Set of EMTs that are */ + VMCPUSET BusyDelayedEmts; +# else + /** Number of EMTs waiting on hBusyDelayedEmts. */ + uint32_t volatile cBusyDelayedEmts; + /** Semaphore that EMTs wait on when reading SVGA_REG_BUSY and the FIFO is + * busy (ugly). */ + RTSEMEVENTMULTI hBusyDelayedEmts; +# endif + + /** Information about screens. */ + VMSVGASCREENOBJECT aScreens[64]; + + /** Command buffer contexts. */ + PVMSVGACMDBUFCTX apCmdBufCtxs[SVGA_CB_CONTEXT_MAX]; + /** The special Device Context for synchronous commands. */ + VMSVGACMDBUFCTX CmdBufCtxDC; + /** Flag which indicates that there are buffers to be processed. */ + uint32_t volatile fCmdBuf; + /** Critical section for accessing the command buffer data. */ + RTCRITSECT CritSectCmdBuf; + + /** Object Tables: MOBs, etc. see SVGA_OTABLE_* */ + VMSVGAGBO aGboOTables[SVGA_OTABLE_MAX]; + + /** Tree of guest's Memory OBjects. Key is mobid. */ + AVLU32TREE MOBTree; + /** Least Recently Used list of MOBs. + * To unmap older MOBs when the guest exceeds SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB (SVGA_REG_GBOBJECT_MEM_SIZE_KB) value. */ + RTLISTANCHOR MOBLRUList; + +# ifdef VBOX_WITH_VMSVGA3D +# ifdef VMSVGA3D_DX + /** DX context of the currently processed command buffer */ + uint32_t idDXContextCurrent; + uint32_t u32Reserved; +# endif + VMSVGA3DBACKENDFUNCS3D *pFuncs3D; + VMSVGA3DBACKENDFUNCSVGPU9 *pFuncsVGPU9; + VMSVGA3DBACKENDFUNCSMAP *pFuncsMap; + VMSVGA3DBACKENDFUNCSGBO *pFuncsGBO; + VMSVGA3DBACKENDFUNCSDX *pFuncsDX; +# endif + + /** Tracks how much time we waste reading SVGA_REG_BUSY with a busy FIFO. */ + STAMPROFILE StatBusyDelayEmts; + + STAMPROFILE StatR3Cmd3dPresentProf; + STAMPROFILE StatR3Cmd3dDrawPrimitivesProf; + STAMPROFILE StatR3Cmd3dSurfaceDmaProf; + STAMPROFILE StatR3Cmd3dBlitSurfaceToScreenProf; + STAMCOUNTER StatR3CmdDefineGmr2; + STAMCOUNTER StatR3CmdDefineGmr2Free; + STAMCOUNTER StatR3CmdDefineGmr2Modify; + STAMCOUNTER StatR3CmdRemapGmr2; + STAMCOUNTER StatR3CmdRemapGmr2Modify; + STAMCOUNTER StatR3CmdInvalidCmd; + STAMCOUNTER StatR3CmdFence; + STAMCOUNTER StatR3CmdUpdate; + STAMCOUNTER StatR3CmdUpdateVerbose; + STAMCOUNTER StatR3CmdDefineCursor; + STAMCOUNTER StatR3CmdDefineAlphaCursor; + STAMCOUNTER StatR3CmdMoveCursor; + STAMCOUNTER StatR3CmdDisplayCursor; + STAMCOUNTER StatR3CmdRectFill; + STAMCOUNTER StatR3CmdRectCopy; + STAMCOUNTER StatR3CmdRectRopCopy; + STAMCOUNTER StatR3CmdEscape; + STAMCOUNTER StatR3CmdDefineScreen; + STAMCOUNTER StatR3CmdDestroyScreen; + STAMCOUNTER StatR3CmdDefineGmrFb; + STAMCOUNTER StatR3CmdBlitGmrFbToScreen; + STAMCOUNTER StatR3CmdBlitScreentoGmrFb; + STAMCOUNTER StatR3CmdAnnotationFill; + STAMCOUNTER StatR3CmdAnnotationCopy; + STAMCOUNTER StatR3Cmd3dSurfaceDefine; + STAMCOUNTER StatR3Cmd3dSurfaceDefineV2; + STAMCOUNTER StatR3Cmd3dSurfaceDestroy; + STAMCOUNTER StatR3Cmd3dSurfaceCopy; + STAMCOUNTER StatR3Cmd3dSurfaceStretchBlt; + STAMCOUNTER StatR3Cmd3dSurfaceDma; + STAMCOUNTER StatR3Cmd3dSurfaceScreen; + STAMCOUNTER StatR3Cmd3dContextDefine; + STAMCOUNTER StatR3Cmd3dContextDestroy; + STAMCOUNTER StatR3Cmd3dSetTransform; + STAMCOUNTER StatR3Cmd3dSetZRange; + STAMCOUNTER StatR3Cmd3dSetRenderState; + STAMCOUNTER StatR3Cmd3dSetRenderTarget; + STAMCOUNTER StatR3Cmd3dSetTextureState; + STAMCOUNTER StatR3Cmd3dSetMaterial; + STAMCOUNTER StatR3Cmd3dSetLightData; + STAMCOUNTER StatR3Cmd3dSetLightEnable; + STAMCOUNTER StatR3Cmd3dSetViewPort; + STAMCOUNTER StatR3Cmd3dSetClipPlane; + STAMCOUNTER StatR3Cmd3dClear; + STAMCOUNTER StatR3Cmd3dPresent; + STAMCOUNTER StatR3Cmd3dPresentReadBack; + STAMCOUNTER StatR3Cmd3dShaderDefine; + STAMCOUNTER StatR3Cmd3dShaderDestroy; + STAMCOUNTER StatR3Cmd3dSetShader; + STAMCOUNTER StatR3Cmd3dSetShaderConst; + STAMCOUNTER StatR3Cmd3dDrawPrimitives; + STAMCOUNTER StatR3Cmd3dSetScissorRect; + STAMCOUNTER StatR3Cmd3dBeginQuery; + STAMCOUNTER StatR3Cmd3dEndQuery; + STAMCOUNTER StatR3Cmd3dWaitForQuery; + STAMCOUNTER StatR3Cmd3dGenerateMipmaps; + STAMCOUNTER StatR3Cmd3dActivateSurface; + STAMCOUNTER StatR3Cmd3dDeactivateSurface; + + STAMCOUNTER StatR3RegConfigDoneWr; + STAMCOUNTER StatR3RegGmrDescriptorWr; + STAMCOUNTER StatR3RegGmrDescriptorWrErrors; + STAMCOUNTER StatR3RegGmrDescriptorWrFree; + + STAMCOUNTER StatFifoCommands; + STAMCOUNTER StatFifoErrors; + STAMCOUNTER StatFifoUnkCmds; + STAMCOUNTER StatFifoTodoTimeout; + STAMCOUNTER StatFifoTodoWoken; + STAMPROFILE StatFifoStalls; + STAMPROFILE StatFifoExtendedSleep; +# ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER + STAMCOUNTER StatFifoAccessHandler; +# endif + STAMCOUNTER StatFifoCursorFetchAgain; + STAMCOUNTER StatFifoCursorNoChange; + STAMCOUNTER StatFifoCursorPosition; + STAMCOUNTER StatFifoCursorVisiblity; + STAMCOUNTER StatFifoWatchdogWakeUps; +} VMSVGAR3STATE, *PVMSVGAR3STATE; + + +/********************************************************************************************************************************* +* Functions * +*********************************************************************************************************************************/ +#ifdef DEBUG_GMR_ACCESS +DECLCALLBACK(int) vmsvgaR3ResetGmrHandlers(PVGASTATE pThis); +DECLCALLBACK(int) vmsvgaR3DeregisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId); +#endif + +int vmsvgaR3DestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen); + +void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC); +void vmsvgaR3ResetSvgaState(PVGASTATE pThis, PVGASTATECC pThisCC); + +void vmsvgaR3TerminateSvgaState(PVGASTATE pThis, PVGASTATECC pThisCC); + +int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC); +int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h); + +int vmsvgaR3GmrTransfer(PVGASTATE pThis, PVGASTATECC pThisCC, const SVGA3dTransferType enmTransferType, + uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch, + SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch, + uint32_t cbWidth, uint32_t cHeight); +void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR); + +void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd); +void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd); +void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd); +void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd); +void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd); +void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd); +void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd); +void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd); +void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd); +void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd); +void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd); +void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd); +void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd); +void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd); +void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd); +void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd); +void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd); + +#ifdef VBOX_WITH_VMSVGA3D +void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd); +void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd); +int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t idDXContext, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd); +#endif + +#if defined(LOG_ENABLED) || defined(VBOX_STRICT) +const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd); +#endif + + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_internal_h */ diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp new file mode 100644 index 00000000..c199b618 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp @@ -0,0 +1,7149 @@ +/* $Id: DevVGA-SVGA.cpp $ */ +/** @file + * VMware SVGA device. + * + * Logging levels guidelines for this and related files: + * - Log() for normal bits. + * - LogFlow() for more info. + * - Log2 for hex dump of cursor data. + * - Log3 for hex dump of shader code. + * - Log4 for hex dumps of 3D data. + * - Log5 for info about GMR pages. + * - Log6 for DX shaders. + * - Log7 for SVGA command dump. + * - Log8 for content of constant and vertex buffers. + * - LogRel for the usual important stuff. + * - LogRel2 for cursor. + * - LogRel3 for 3D performance data. + * - LogRel4 for HW accelerated graphics output. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/** @page pg_dev_vmsvga VMSVGA - VMware SVGA II Device Emulation + * + * This device emulation was contributed by trivirt AG. It offers an + * alternative to our Bochs based VGA graphics and 3d emulations. This is + * valuable for Xorg based guests, as there is driver support shipping with Xorg + * since it forked from XFree86. + * + * + * @section sec_dev_vmsvga_sdk The VMware SDK + * + * This is officially deprecated now, however it's still quite useful, + * especially for getting the old features working: + * http://vmware-svga.sourceforge.net/ + * + * They currently point developers at the following resources. + * - http://cgit.freedesktop.org/xorg/driver/xf86-video-vmware/ + * - http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/svga/ + * - http://cgit.freedesktop.org/mesa/vmwgfx/ + * + * @subsection subsec_dev_vmsvga_sdk_results Test results + * + * Test results: + * - 2dmark.img: + * + todo + * - backdoor-tclo.img: + * + todo + * - blit-cube.img: + * + todo + * - bunnies.img: + * + todo + * - cube.img: + * + todo + * - cubemark.img: + * + todo + * - dynamic-vertex-stress.img: + * + todo + * - dynamic-vertex.img: + * + todo + * - fence-stress.img: + * + todo + * - gmr-test.img: + * + todo + * - half-float-test.img: + * + todo + * - noscreen-cursor.img: + * - The CURSOR I/O and FIFO registers are not implemented, so the mouse + * cursor doesn't show. (Hacking the GUI a little, would make the cursor + * visible though.) + * - Cursor animation via the palette doesn't work. + * - During debugging, it turns out that the framebuffer content seems to + * be halfways ignore or something (memset(fb, 0xcc, lots)). + * - Trouble with way to small FIFO and the 256x256 cursor fails. Need to + * grow it 0x10 fold (128KB -> 2MB like in WS10). + * - null.img: + * + todo + * - pong.img: + * + todo + * - presentReadback.img: + * + todo + * - resolution-set.img: + * + todo + * - rt-gamma-test.img: + * + todo + * - screen-annotation.img: + * + todo + * - screen-cursor.img: + * + todo + * - screen-dma-coalesce.img: + * + todo + * - screen-gmr-discontig.img: + * + todo + * - screen-gmr-remap.img: + * + todo + * - screen-multimon.img: + * + todo + * - screen-present-clip.img: + * + todo + * - screen-render-test.img: + * + todo + * - screen-simple.img: + * + todo + * - screen-text.img: + * + todo + * - simple-shaders.img: + * + todo + * - simple_blit.img: + * + todo + * - tiny-2d-updates.img: + * + todo + * - video-formats.img: + * + todo + * - video-sync.img: + * + todo + * + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef IN_RING3 +# include +# include +# ifdef VBOX_STRICT +# include +# endif +#endif + +#include +#include +#include +#include + +#ifdef LOG_ENABLED +#include "svgadump/svga_dump.h" +#endif + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +/* Should be included after DevVGA.h/DevVGA-SVGA.h to pick all defines. */ +#ifdef VBOX_WITH_VMSVGA3D +# include "DevVGA-SVGA3d.h" +# ifdef RT_OS_DARWIN +# include "DevVGA-SVGA3d-cocoa.h" +# endif +# ifdef RT_OS_LINUX +# ifdef IN_RING3 +# include "DevVGA-SVGA3d-glLdr.h" +# endif +# endif +#endif +#ifdef IN_RING3 +#include "DevVGA-SVGA-internal.h" +#endif + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/** + * Macro for checking if a fixed FIFO register is valid according to the + * current FIFO configuration. + * + * @returns true / false. + * @param a_iIndex The fifo register index (like SVGA_FIFO_CAPABILITIES). + * @param a_offFifoMin A valid SVGA_FIFO_MIN value. + */ +#define VMSVGA_IS_VALID_FIFO_REG(a_iIndex, a_offFifoMin) ( ((a_iIndex) + 1) * sizeof(uint32_t) <= (a_offFifoMin) ) + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ +#ifdef IN_RING3 +# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS) +static FNPGMPHYSHANDLER vmsvgaR3FifoAccessHandler; +# endif +# ifdef DEBUG_GMR_ACCESS +static FNPGMPHYSHANDLER vmsvgaR3GmrAccessHandler; +# endif +#endif + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#ifdef IN_RING3 + +/** + * SSM descriptor table for the VMSVGAGMRDESCRIPTOR structure. + */ +static SSMFIELD const g_aVMSVGAGMRDESCRIPTORFields[] = +{ + SSMFIELD_ENTRY_GCPHYS( VMSVGAGMRDESCRIPTOR, GCPhys), + SSMFIELD_ENTRY( VMSVGAGMRDESCRIPTOR, numPages), + SSMFIELD_ENTRY_TERM() +}; + +/** + * SSM descriptor table for the GMR structure. + */ +static SSMFIELD const g_aGMRFields[] = +{ + SSMFIELD_ENTRY( GMR, cMaxPages), + SSMFIELD_ENTRY( GMR, cbTotal), + SSMFIELD_ENTRY( GMR, numDescriptors), + SSMFIELD_ENTRY_IGN_HCPTR( GMR, paDesc), + SSMFIELD_ENTRY_TERM() +}; + +/** + * SSM descriptor table for the VMSVGASCREENOBJECT structure. + */ +static SSMFIELD const g_aVMSVGASCREENOBJECTFields[] = +{ + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fuScreen), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, idScreen), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, xOrigin), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, yOrigin), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cWidth), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cHeight), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, offVRAM), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cbPitch), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cBpp), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fDefined), + SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fModified), + SSMFIELD_ENTRY_VER( VMSVGASCREENOBJECT, cDpi, VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS), + SSMFIELD_ENTRY_TERM() +}; + +/** + * SSM descriptor table for the VMSVGAR3STATE structure. + */ +static SSMFIELD const g_aVMSVGAR3STATEFields[] = +{ + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, paGMR), + SSMFIELD_ENTRY( VMSVGAR3STATE, GMRFB), + SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.fActive), + SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.xHotspot), + SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.yHotspot), + SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.width), + SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.height), + SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.cbData), + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAR3STATE, Cursor.pData), + SSMFIELD_ENTRY( VMSVGAR3STATE, colorAnnotation), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, cBusyDelayedEmts), +#ifdef VMSVGA_USE_EMT_HALT_CODE + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, BusyDelayedEmts), +#else + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, hBusyDelayedEmts), +#endif + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatBusyDelayEmts), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresentProf), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDrawPrimitivesProf), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDmaProf), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dBlitSurfaceToScreenProf), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2Free), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2Modify), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRemapGmr2), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRemapGmr2Modify), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdInvalidCmd), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdFence), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdUpdate), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdUpdateVerbose), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineCursor), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineAlphaCursor), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdMoveCursor), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDisplayCursor), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectFill), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectCopy), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectRopCopy), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdEscape), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineScreen), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDestroyScreen), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmrFb), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdBlitGmrFbToScreen), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdBlitScreentoGmrFb), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdAnnotationFill), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdAnnotationCopy), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDefine), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDefineV2), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDestroy), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceCopy), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceStretchBlt), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDma), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceScreen), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dContextDefine), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dContextDestroy), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetTransform), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetZRange), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetRenderState), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetRenderTarget), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetTextureState), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetMaterial), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetLightData), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetLightEnable), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetViewPort), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetClipPlane), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dClear), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresent), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresentReadBack), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dShaderDefine), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dShaderDestroy), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetShader), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetShaderConst), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDrawPrimitives), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetScissorRect), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dBeginQuery), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dEndQuery), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dWaitForQuery), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dGenerateMipmaps), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dActivateSurface), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDeactivateSurface), + + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegConfigDoneWr), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWr), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWrErrors), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWrFree), + + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCommands), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoErrors), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoUnkCmds), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoTodoTimeout), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoTodoWoken), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoStalls), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoExtendedSleep), +# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS) + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoAccessHandler), +# endif + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorFetchAgain), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorNoChange), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorPosition), + SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorVisiblity), + + SSMFIELD_ENTRY_TERM() +}; + +/** + * SSM descriptor table for the VGAState.svga structure. + */ +static SSMFIELD const g_aVGAStateSVGAFields[] = +{ + SSMFIELD_ENTRY_IGN_GCPHYS( VMSVGAState, GCPhysFIFO), + SSMFIELD_ENTRY_IGNORE( VMSVGAState, cbFIFO), + SSMFIELD_ENTRY_IGNORE( VMSVGAState, cbFIFOConfig), + SSMFIELD_ENTRY( VMSVGAState, u32SVGAId), + SSMFIELD_ENTRY( VMSVGAState, fEnabled), + SSMFIELD_ENTRY( VMSVGAState, fConfigured), + SSMFIELD_ENTRY( VMSVGAState, fBusy), + SSMFIELD_ENTRY( VMSVGAState, fTraces), + SSMFIELD_ENTRY( VMSVGAState, u32GuestId), + SSMFIELD_ENTRY( VMSVGAState, cScratchRegion), + SSMFIELD_ENTRY( VMSVGAState, au32ScratchRegion), + SSMFIELD_ENTRY( VMSVGAState, u32IrqStatus), + SSMFIELD_ENTRY( VMSVGAState, u32IrqMask), + SSMFIELD_ENTRY( VMSVGAState, u32PitchLock), + SSMFIELD_ENTRY( VMSVGAState, u32CurrentGMRId), + SSMFIELD_ENTRY( VMSVGAState, u32DeviceCaps), + SSMFIELD_ENTRY_VER( VMSVGAState, u32DeviceCaps2, VGA_SAVEDSTATE_VERSION_VMSVGA_REG_CAP2), + SSMFIELD_ENTRY_VER( VMSVGAState, u32GuestDriverId, VGA_SAVEDSTATE_VERSION_VMSVGA_REG_CAP2), + SSMFIELD_ENTRY_VER( VMSVGAState, u32GuestDriverVer1, VGA_SAVEDSTATE_VERSION_VMSVGA_REG_CAP2), + SSMFIELD_ENTRY_VER( VMSVGAState, u32GuestDriverVer2, VGA_SAVEDSTATE_VERSION_VMSVGA_REG_CAP2), + SSMFIELD_ENTRY_VER( VMSVGAState, u32GuestDriverVer3, VGA_SAVEDSTATE_VERSION_VMSVGA_REG_CAP2), + SSMFIELD_ENTRY( VMSVGAState, u32IndexReg), + SSMFIELD_ENTRY_IGNORE( VMSVGAState, hFIFORequestSem), + SSMFIELD_ENTRY_IGNORE( VMSVGAState, uLastCursorUpdateCount), + SSMFIELD_ENTRY_IGNORE( VMSVGAState, fFIFOThreadSleeping), + SSMFIELD_ENTRY_VER( VMSVGAState, fGFBRegisters, VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS), + SSMFIELD_ENTRY( VMSVGAState, uWidth), + SSMFIELD_ENTRY( VMSVGAState, uHeight), + SSMFIELD_ENTRY( VMSVGAState, uBpp), + SSMFIELD_ENTRY( VMSVGAState, cbScanline), + SSMFIELD_ENTRY_VER( VMSVGAState, uScreenOffset, VGA_SAVEDSTATE_VERSION_VMSVGA), + SSMFIELD_ENTRY_VER( VMSVGAState, uCursorX, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR), + SSMFIELD_ENTRY_VER( VMSVGAState, uCursorY, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR), + SSMFIELD_ENTRY_VER( VMSVGAState, uCursorID, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR), + SSMFIELD_ENTRY_VER( VMSVGAState, uCursorOn, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR), + SSMFIELD_ENTRY( VMSVGAState, u32MaxWidth), + SSMFIELD_ENTRY( VMSVGAState, u32MaxHeight), + SSMFIELD_ENTRY( VMSVGAState, u32ActionFlags), + SSMFIELD_ENTRY( VMSVGAState, f3DEnabled), + SSMFIELD_ENTRY( VMSVGAState, fVRAMTracking), + SSMFIELD_ENTRY_IGNORE( VMSVGAState, u8FIFOExtCommand), + SSMFIELD_ENTRY_IGNORE( VMSVGAState, fFifoExtCommandWakeup), + SSMFIELD_ENTRY_IGNORE( VMSVGAState, cGMR), + SSMFIELD_ENTRY_VER( VMSVGAState, au32DevCaps, VGA_SAVEDSTATE_VERSION_VMSVGA_DX), + SSMFIELD_ENTRY_VER( VMSVGAState, u32DevCapIndex, VGA_SAVEDSTATE_VERSION_VMSVGA_DX), + SSMFIELD_ENTRY_VER( VMSVGAState, u32RegCommandLow, VGA_SAVEDSTATE_VERSION_VMSVGA_DX), + SSMFIELD_ENTRY_VER( VMSVGAState, u32RegCommandHigh, VGA_SAVEDSTATE_VERSION_VMSVGA_DX), + + SSMFIELD_ENTRY_TERM() +}; +#endif /* IN_RING3 */ + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ +#ifdef IN_RING3 +static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces); +static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, + uint32_t uVersion, uint32_t uPass); +static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM); +static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx); +static void vmsvgaR3PowerOnDevice(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, bool fLoadState); +#endif /* IN_RING3 */ + + +#define SVGA_CASE_ID2STR(idx) case idx: return #idx +#if defined(LOG_ENABLED) +/** + * Index register string name lookup + * + * @returns Index register string or "UNKNOWN" + * @param pThis The shared VGA/VMSVGA state. + * @param idxReg The index register. + */ +static const char *vmsvgaIndexToString(PVGASTATE pThis, uint32_t idxReg) +{ + AssertCompile(SVGA_REG_TOP == 77); /* Ensure that the correct headers are used. */ + switch (idxReg) + { + SVGA_CASE_ID2STR(SVGA_REG_ID); + SVGA_CASE_ID2STR(SVGA_REG_ENABLE); + SVGA_CASE_ID2STR(SVGA_REG_WIDTH); + SVGA_CASE_ID2STR(SVGA_REG_HEIGHT); + SVGA_CASE_ID2STR(SVGA_REG_MAX_WIDTH); + SVGA_CASE_ID2STR(SVGA_REG_MAX_HEIGHT); + SVGA_CASE_ID2STR(SVGA_REG_DEPTH); + SVGA_CASE_ID2STR(SVGA_REG_BITS_PER_PIXEL); /* Current bpp in the guest */ + SVGA_CASE_ID2STR(SVGA_REG_PSEUDOCOLOR); + SVGA_CASE_ID2STR(SVGA_REG_RED_MASK); + SVGA_CASE_ID2STR(SVGA_REG_GREEN_MASK); + SVGA_CASE_ID2STR(SVGA_REG_BLUE_MASK); + SVGA_CASE_ID2STR(SVGA_REG_BYTES_PER_LINE); + SVGA_CASE_ID2STR(SVGA_REG_FB_START); /* (Deprecated) */ + SVGA_CASE_ID2STR(SVGA_REG_FB_OFFSET); + SVGA_CASE_ID2STR(SVGA_REG_VRAM_SIZE); + SVGA_CASE_ID2STR(SVGA_REG_FB_SIZE); + + /* ID 0 implementation only had the above registers, then the palette */ + SVGA_CASE_ID2STR(SVGA_REG_CAPABILITIES); + SVGA_CASE_ID2STR(SVGA_REG_MEM_START); /* (Deprecated) */ + SVGA_CASE_ID2STR(SVGA_REG_MEM_SIZE); + SVGA_CASE_ID2STR(SVGA_REG_CONFIG_DONE); /* Set when memory area configured */ + SVGA_CASE_ID2STR(SVGA_REG_SYNC); /* See "FIFO Synchronization Registers" */ + SVGA_CASE_ID2STR(SVGA_REG_BUSY); /* See "FIFO Synchronization Registers" */ + SVGA_CASE_ID2STR(SVGA_REG_GUEST_ID); /* Set guest OS identifier */ + SVGA_CASE_ID2STR(SVGA_REG_DEAD); /* (Deprecated) SVGA_REG_CURSOR_ID. */ + SVGA_CASE_ID2STR(SVGA_REG_CURSOR_X); /* (Deprecated) */ + SVGA_CASE_ID2STR(SVGA_REG_CURSOR_Y); /* (Deprecated) */ + SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ON); /* (Deprecated) */ + SVGA_CASE_ID2STR(SVGA_REG_HOST_BITS_PER_PIXEL); /* (Deprecated) */ + SVGA_CASE_ID2STR(SVGA_REG_SCRATCH_SIZE); /* Number of scratch registers */ + SVGA_CASE_ID2STR(SVGA_REG_MEM_REGS); /* Number of FIFO registers */ + SVGA_CASE_ID2STR(SVGA_REG_NUM_DISPLAYS); /* (Deprecated) */ + SVGA_CASE_ID2STR(SVGA_REG_PITCHLOCK); /* Fixed pitch for all modes */ + SVGA_CASE_ID2STR(SVGA_REG_IRQMASK); /* Interrupt mask */ + + /* Legacy multi-monitor support */ + SVGA_CASE_ID2STR(SVGA_REG_NUM_GUEST_DISPLAYS); /* Number of guest displays in X/Y direction */ + SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_ID); /* Display ID for the following display attributes */ + SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_IS_PRIMARY); /* Whether this is a primary display */ + SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_X); /* The display position x */ + SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_Y); /* The display position y */ + SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_WIDTH); /* The display's width */ + SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_HEIGHT); /* The display's height */ + + SVGA_CASE_ID2STR(SVGA_REG_GMR_ID); + SVGA_CASE_ID2STR(SVGA_REG_GMR_DESCRIPTOR); + SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_IDS); + SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH); + + SVGA_CASE_ID2STR(SVGA_REG_TRACES); /* Enable trace-based updates even when FIFO is on */ + SVGA_CASE_ID2STR(SVGA_REG_GMRS_MAX_PAGES); /* Maximum number of 4KB pages for all GMRs */ + SVGA_CASE_ID2STR(SVGA_REG_MEMORY_SIZE); /* Total dedicated device memory excluding FIFO */ + SVGA_CASE_ID2STR(SVGA_REG_COMMAND_LOW); /* Lower 32 bits and submits commands */ + SVGA_CASE_ID2STR(SVGA_REG_COMMAND_HIGH); /* Upper 32 bits of command buffer PA */ + SVGA_CASE_ID2STR(SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM); /* Max primary memory */ + SVGA_CASE_ID2STR(SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB); /* Suggested limit on mob mem */ + SVGA_CASE_ID2STR(SVGA_REG_DEV_CAP); /* Write dev cap index, read value */ + SVGA_CASE_ID2STR(SVGA_REG_CMD_PREPEND_LOW); + SVGA_CASE_ID2STR(SVGA_REG_CMD_PREPEND_HIGH); + SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_WIDTH); + SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_HEIGHT); + SVGA_CASE_ID2STR(SVGA_REG_MOB_MAX_SIZE); + SVGA_CASE_ID2STR(SVGA_REG_BLANK_SCREEN_TARGETS); + SVGA_CASE_ID2STR(SVGA_REG_CAP2); + SVGA_CASE_ID2STR(SVGA_REG_DEVEL_CAP); + SVGA_CASE_ID2STR(SVGA_REG_GUEST_DRIVER_ID); + SVGA_CASE_ID2STR(SVGA_REG_GUEST_DRIVER_VERSION1); + SVGA_CASE_ID2STR(SVGA_REG_GUEST_DRIVER_VERSION2); + SVGA_CASE_ID2STR(SVGA_REG_GUEST_DRIVER_VERSION3); + SVGA_CASE_ID2STR(SVGA_REG_CURSOR_MOBID); + SVGA_CASE_ID2STR(SVGA_REG_CURSOR_MAX_BYTE_SIZE); + SVGA_CASE_ID2STR(SVGA_REG_CURSOR_MAX_DIMENSION); + SVGA_CASE_ID2STR(SVGA_REG_FIFO_CAPS); + SVGA_CASE_ID2STR(SVGA_REG_FENCE); + SVGA_CASE_ID2STR(SVGA_REG_RESERVED1); + SVGA_CASE_ID2STR(SVGA_REG_RESERVED2); + SVGA_CASE_ID2STR(SVGA_REG_RESERVED3); + SVGA_CASE_ID2STR(SVGA_REG_RESERVED4); + SVGA_CASE_ID2STR(SVGA_REG_RESERVED5); + SVGA_CASE_ID2STR(SVGA_REG_SCREENDMA); + SVGA_CASE_ID2STR(SVGA_REG_GBOBJECT_MEM_SIZE_KB); + SVGA_CASE_ID2STR(SVGA_REG_TOP); /* Must be 1 more than the last register */ + + default: + if (idxReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion) + return "SVGA_SCRATCH_BASE reg"; + if (idxReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS) + return "SVGA_PALETTE_BASE reg"; + return "UNKNOWN"; + } +} +#endif /* LOG_ENABLED */ + +#if defined(LOG_ENABLED) || (defined(IN_RING3) && defined(VBOX_WITH_VMSVGA3D)) +static const char *vmsvgaDevCapIndexToString(SVGA3dDevCapIndex idxDevCap) +{ + AssertCompile(SVGA3D_DEVCAP_MAX == 260); + switch (idxDevCap) + { + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_INVALID); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_3D); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_LIGHTS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURES); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_CLIP_PLANES); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_VERTEX_SHADER_VERSION); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_VERTEX_SHADER); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_FRAGMENT_SHADER); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_RENDER_TARGETS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_S23E8_TEXTURES); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_S10E5_TEXTURES); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_D16_BUFFER_FORMAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_QUERY_TYPES); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_POINT_SIZE); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_SHADER_TEXTURES); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VOLUME_EXTENT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VERTEX_INDEX); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_TEXTURE_OPS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_R5G6B5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ALPHA8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_D16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT1); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT2); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT3); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT4); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_CxV8U8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_R_S10E5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_R_S23E8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MISSING62); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_V16U16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_G16R16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_UYVY); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_YUY2); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD4); /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD5); /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD7); /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD6); /* SVGA3D_DEVCAP_SUPERSAMPLE */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_AUTOGENMIPMAPS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_NV12); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD10); /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_CONTEXT_IDS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_SURFACE_IDS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_DF16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_DF24); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ATI1); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ATI2); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD1); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD8); /* SVGA3D_DEVCAP_VIDEO_DECODE */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD9); /* SVGA3D_DEVCAP_VIDEO_PROCESS */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_LINE_AA); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_LINE_STIPPLE); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_LINE_WIDTH); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_YV12); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD3); /* Old SVGA3D_DEVCAP_LOGICOPS */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_TS_COLOR_KEY); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD2); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXCONTEXT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD11); /* SVGA3D_DEVCAP_MAX_TEXTURE_ARRAY_SIZE */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DX_MAX_VERTEXBUFFERS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DX_PROVOKING_VERTEX); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X8R8G8B8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A8R8G8B8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R5G6B5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X1R5G5B5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A1R5G5B5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A4R4G4B4); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D32); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D24S8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D15S1); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_LUMINANCE8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_LUMINANCE4_ALPHA4); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_LUMINANCE16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_LUMINANCE8_ALPHA8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT1); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT2); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT3); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT4); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BUMPU8V8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BUMPL6V5U5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BUMPX8L8V8U8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD1); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ARGB_S10E5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ARGB_S23E8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A2R10G10B10); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_V8U8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Q8W8V8U8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_CxV8U8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X8L8V8U8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A2W10V10U10); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ALPHA8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R_S10E5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R_S23E8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_RG_S10E5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_RG_S23E8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BUFFER); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D24X8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_V16U16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_G16R16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A16B16G16R16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_UYVY); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_YUY2); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_NV12); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD2); /* SVGA3D_DEVCAP_DXFMT_AYUV */ + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X32_G8X24_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_D32_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X24_G8_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_SNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_UINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_SNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_SINT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_P8); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_B8G8_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_G8R8_G8B8_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC1_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC1_UNORM_SRGB); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC2_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC2_UNORM_SRGB); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC3_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC3_UNORM_SRGB); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ATI1); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC4_SNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ATI2); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC5_SNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R10G10B10_XR_BIAS_A2_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_DF16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_DF24); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D24S8_INT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_YV12); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_SNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_SNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_FLOAT); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_D16_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A8_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC1_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC2_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC3_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC4_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC5_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SM41); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MULTISAMPLE_2X); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MULTISAMPLE_4X); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MS_FULL_QUALITY); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_LOGICOPS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_LOGIC_BLENDOPS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_RESERVED_1); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC6H_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC6H_UF16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC6H_SF16); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC7_TYPELESS); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC7_UNORM); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC7_UNORM_SRGB); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_RESERVED_2); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SM5); + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MULTISAMPLE_8X); + + SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX); + + default: + break; + } + return "UNKNOWN"; +} +#endif /* defined(LOG_ENABLED) || (defined(IN_RING3) && defined(VBOX_WITH_VMSVGA3D)) */ +#undef SVGA_CASE_ID2STR + + +#ifdef IN_RING3 + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnSetViewport} + */ +DECLCALLBACK(void) vmsvgaR3PortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE); + + Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", idScreen, x, y, cx, cy)); + VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport; + + /** @todo Test how it interacts with multiple screen objects. */ + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen); + uint32_t const uWidth = pScreen ? pScreen->cWidth : 0; + uint32_t const uHeight = pScreen ? pScreen->cHeight : 0; + + if (x < uWidth) + { + pThis->svga.viewport.x = x; + pThis->svga.viewport.cx = RT_MIN(cx, uWidth - x); + pThis->svga.viewport.xRight = x + pThis->svga.viewport.cx; + } + else + { + pThis->svga.viewport.x = uWidth; + pThis->svga.viewport.cx = 0; + pThis->svga.viewport.xRight = uWidth; + } + if (y < uHeight) + { + pThis->svga.viewport.y = y; + pThis->svga.viewport.cy = RT_MIN(cy, uHeight - y); + pThis->svga.viewport.yLowWC = uHeight - y - pThis->svga.viewport.cy; + pThis->svga.viewport.yHighWC = uHeight - y; + } + else + { + pThis->svga.viewport.y = uHeight; + pThis->svga.viewport.cy = 0; + pThis->svga.viewport.yLowWC = 0; + pThis->svga.viewport.yHighWC = 0; + } + +# ifdef VBOX_WITH_VMSVGA3D + /* + * Now inform the 3D backend. + */ + if (pThis->svga.f3DEnabled) + vmsvga3dUpdateHostScreenViewport(pThisCC, idScreen, &OldViewport); +# else + RT_NOREF(OldViewport); +# endif +} + + +/** + * Updating screen information in API + * + * @param pThis The The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + */ +void vmsvgaR3VBVAResize(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + int rc; + + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + + for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen) + { + VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[iScreen]; + if (!pScreen->fModified) + continue; + + pScreen->fModified = false; + + VBVAINFOVIEW view; + RT_ZERO(view); + view.u32ViewIndex = pScreen->idScreen; + // view.u32ViewOffset = 0; + view.u32ViewSize = pThis->vram_size; + view.u32MaxScreenSize = pThis->vram_size; + + VBVAINFOSCREEN screen; + RT_ZERO(screen); + screen.u32ViewIndex = pScreen->idScreen; + + if (pScreen->fDefined) + { + if ( pScreen->cWidth == VMSVGA_VAL_UNINITIALIZED + || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED + || pScreen->cBpp == VMSVGA_VAL_UNINITIALIZED) + { + Assert(pThis->svga.fGFBRegisters); + continue; + } + + screen.i32OriginX = pScreen->xOrigin; + screen.i32OriginY = pScreen->yOrigin; + screen.u32StartOffset = pScreen->offVRAM; + screen.u32LineSize = pScreen->cbPitch; + screen.u32Width = pScreen->cWidth; + screen.u32Height = pScreen->cHeight; + screen.u16BitsPerPixel = pScreen->cBpp; + if (!(pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE)) + screen.u16Flags = VBVA_SCREEN_F_ACTIVE; + if (pScreen->fuScreen & SVGA_SCREEN_BLANKING) + screen.u16Flags |= VBVA_SCREEN_F_BLANK2; + } + else + { + /* Screen is destroyed. */ + screen.u16Flags = VBVA_SCREEN_F_DISABLED; + } + + void *pvVRAM = pScreen->pvScreenBitmap ? pScreen->pvScreenBitmap : pThisCC->pbVRam; + rc = pThisCC->pDrv->pfnVBVAResize(pThisCC->pDrv, &view, &screen, pvVRAM, /*fResetInputMapping=*/ true); + AssertRC(rc); + } +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnReportMonitorPositions} + * + * Used to update screen offsets (positions) since appearently vmwgfx fails to + * pass correct offsets thru FIFO. + */ +DECLCALLBACK(void) vmsvgaR3PortReportMonitorPositions(PPDMIDISPLAYPORT pInterface, uint32_t cPositions, PCRTPOINT paPositions) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + + AssertReturnVoid(pSVGAState); + + /* We assume cPositions is the # of outputs Xserver reports and paPositions is (-1, -1) for disabled monitors. */ + cPositions = RT_MIN(cPositions, RT_ELEMENTS(pSVGAState->aScreens)); + for (uint32_t i = 0; i < cPositions; ++i) + { + if ( pSVGAState->aScreens[i].xOrigin == paPositions[i].x + && pSVGAState->aScreens[i].yOrigin == paPositions[i].y) + continue; + + if (paPositions[i].x == -1) + continue; + if (paPositions[i].y == -1) + continue; + + pSVGAState->aScreens[i].xOrigin = paPositions[i].x; + pSVGAState->aScreens[i].yOrigin = paPositions[i].y; + pSVGAState->aScreens[i].fModified = true; + } + + vmsvgaR3VBVAResize(pThis, pThisCC); +} + +#endif /* IN_RING3 */ + +/** + * Read port register + * + * @returns VBox status code. + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA state. + * @param pu32 Where to store the read value + */ +static int vmsvgaReadPort(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t *pu32) +{ +#ifdef IN_RING3 + PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); +#endif + int rc = VINF_SUCCESS; + *pu32 = 0; + + /* Rough index register validation. */ + uint32_t idxReg = pThis->svga.u32IndexReg; +#if !defined(IN_RING3) && defined(VBOX_STRICT) + ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg), + VINF_IOM_R3_IOPORT_READ); +#else + ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg), + STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd), + VINF_SUCCESS); +#endif + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */ + if ( idxReg >= SVGA_REG_ID_0_TOP + && pThis->svga.u32SVGAId == SVGA_ID_0) + { + idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP; + Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg)); + } + + switch (idxReg) + { + case SVGA_REG_ID: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd); + *pu32 = pThis->svga.u32SVGAId; + break; + + case SVGA_REG_ENABLE: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd); + *pu32 = pThis->svga.fEnabled; + break; + + case SVGA_REG_WIDTH: + { + STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd); + if ( pThis->svga.fEnabled + && pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED) + *pu32 = pThis->svga.uWidth; + else + { +#ifndef IN_RING3 + rc = VINF_IOM_R3_IOPORT_READ; +#else + *pu32 = pThisCC->pDrv->cx; +#endif + } + break; + } + + case SVGA_REG_HEIGHT: + { + STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd); + if ( pThis->svga.fEnabled + && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED) + *pu32 = pThis->svga.uHeight; + else + { +#ifndef IN_RING3 + rc = VINF_IOM_R3_IOPORT_READ; +#else + *pu32 = pThisCC->pDrv->cy; +#endif + } + break; + } + + case SVGA_REG_MAX_WIDTH: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd); + *pu32 = pThis->svga.u32MaxWidth; + break; + + case SVGA_REG_MAX_HEIGHT: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd); + *pu32 = pThis->svga.u32MaxHeight; + break; + + case SVGA_REG_DEPTH: + /* This returns the color depth of the current mode. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd); + switch (pThis->svga.uBpp) + { + case 15: + case 16: + case 24: + *pu32 = pThis->svga.uBpp; + break; + + default: + case 32: + *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */ + break; + } + break; + + case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd); + *pu32 = pThis->svga.uHostBpp; + break; + + case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd); + *pu32 = pThis->svga.uBpp; + break; + + case SVGA_REG_PSEUDOCOLOR: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd); + *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */ + break; + + case SVGA_REG_RED_MASK: + case SVGA_REG_GREEN_MASK: + case SVGA_REG_BLUE_MASK: + { + uint32_t uBpp; + + if (pThis->svga.fEnabled) + uBpp = pThis->svga.uBpp; + else + uBpp = pThis->svga.uHostBpp; + + uint32_t u32RedMask, u32GreenMask, u32BlueMask; + switch (uBpp) + { + case 8: + u32RedMask = 0x07; + u32GreenMask = 0x38; + u32BlueMask = 0xc0; + break; + + case 15: + u32RedMask = 0x0000001f; + u32GreenMask = 0x000003e0; + u32BlueMask = 0x00007c00; + break; + + case 16: + u32RedMask = 0x0000001f; + u32GreenMask = 0x000007e0; + u32BlueMask = 0x0000f800; + break; + + case 24: + case 32: + default: + u32RedMask = 0x00ff0000; + u32GreenMask = 0x0000ff00; + u32BlueMask = 0x000000ff; + break; + } + switch (idxReg) + { + case SVGA_REG_RED_MASK: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd); + *pu32 = u32RedMask; + break; + + case SVGA_REG_GREEN_MASK: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd); + *pu32 = u32GreenMask; + break; + + case SVGA_REG_BLUE_MASK: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd); + *pu32 = u32BlueMask; + break; + } + break; + } + + case SVGA_REG_BYTES_PER_LINE: + { + STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd); + if ( pThis->svga.fEnabled + && pThis->svga.cbScanline) + *pu32 = pThis->svga.cbScanline; + else + { +#ifndef IN_RING3 + rc = VINF_IOM_R3_IOPORT_READ; +#else + *pu32 = pThisCC->pDrv->cbScanline; +#endif + } + break; + } + + case SVGA_REG_VRAM_SIZE: /* VRAM size */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd); + *pu32 = pThis->vram_size; + break; + + case SVGA_REG_FB_START: /* Frame buffer physical address. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd); + Assert(pThis->GCPhysVRAM <= 0xffffffff); + *pu32 = pThis->GCPhysVRAM; + break; + + case SVGA_REG_FB_OFFSET: /* Offset of the frame buffer in VRAM */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd); + /* Always zero in our case. */ + *pu32 = 0; + break; + + case SVGA_REG_FB_SIZE: /* Frame buffer size */ + { +#ifndef IN_RING3 + rc = VINF_IOM_R3_IOPORT_READ; +#else + STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd); + + /* VMWare testcases want at least 4 MB in case the hardware is disabled. */ + if ( pThis->svga.fEnabled + && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED) + { + /* Hardware enabled; return real framebuffer size .*/ + *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline; + } + else + *pu32 = RT_MAX(0x100000, (uint32_t)pThisCC->pDrv->cy * pThisCC->pDrv->cbScanline); + + *pu32 = RT_MIN(pThis->vram_size, *pu32); + Log(("h=%d w=%d bpp=%d\n", pThisCC->pDrv->cy, pThisCC->pDrv->cx, pThisCC->pDrv->cBits)); +#endif + break; + } + + case SVGA_REG_CAPABILITIES: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd); + *pu32 = pThis->svga.u32DeviceCaps; + break; + + case SVGA_REG_MEM_START: /* FIFO start */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd); + Assert(pThis->svga.GCPhysFIFO <= 0xffffffff); + *pu32 = pThis->svga.GCPhysFIFO; + break; + + case SVGA_REG_MEM_SIZE: /* FIFO size */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd); + *pu32 = pThis->svga.cbFIFO; + break; + + case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd); + *pu32 = pThis->svga.fConfigured; + break; + + case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd); + *pu32 = 0; + break; + + case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd); + if (pThis->svga.fBusy) + { +#ifndef IN_RING3 + /* Go to ring-3 and halt the CPU. */ + rc = VINF_IOM_R3_IOPORT_READ; + RT_NOREF(pDevIns); + break; +#else /* IN_RING3 */ +# if defined(VMSVGA_USE_EMT_HALT_CODE) + /* The guest is basically doing a HLT via the device here, but with + a special wake up condition on FIFO completion. */ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay); + VMCPUID idCpu = PDMDevHlpGetCurrentCpuId(pDevIns); + VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu); + ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts); + if (pThis->svga.fBusy) + { + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */ + rc = PDMDevHlpVMWaitForDeviceReady(pDevIns, idCpu); + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + } + ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts); + VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu); +# else + + /* Delay the EMT a bit so the FIFO and others can get some work done. + This used to be a crude 50 ms sleep. The current code tries to be + more efficient, but the consept is still very crude. */ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay); + RTThreadYield(); + if (pThis->svga.fBusy) + { + uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts); + + if (pThis->svga.fBusy && cRefs == 1) + RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts); + if (pThis->svga.fBusy) + { + /** @todo If this code is going to stay, we need to call into the halt/wait + * code in VMEmt.cpp here, otherwise all kind of EMT interaction will + * suffer when the guest is polling on a busy FIFO. */ + uint64_t uIgnored1, uIgnored2; + uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pDevIns), &uIgnored1, &uIgnored2); + if (cNsMaxWait >= RT_NS_100US) + RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts, + RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME, + RT_MIN(cNsMaxWait, RT_NS_10MS)); + } + + ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts); + } + STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay); +# endif + *pu32 = pThis->svga.fBusy != 0; +#endif /* IN_RING3 */ + } + else + *pu32 = false; + break; + + case SVGA_REG_GUEST_ID: /* Set guest OS identifier */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd); + *pu32 = pThis->svga.u32GuestId; + break; + + case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd); + *pu32 = pThis->svga.cScratchRegion; + break; + + case SVGA_REG_MEM_REGS: /* Number of FIFO registers */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd); + *pu32 = SVGA_FIFO_NUM_REGS; + break; + + case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd); + *pu32 = pThis->svga.u32PitchLock; + break; + + case SVGA_REG_IRQMASK: /* Interrupt mask */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd); + *pu32 = pThis->svga.u32IrqMask; + break; + + /* See "Guest memory regions" below. */ + case SVGA_REG_GMR_ID: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd); + *pu32 = pThis->svga.u32CurrentGMRId; + break; + + case SVGA_REG_GMR_DESCRIPTOR: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd); + /* Write only */ + *pu32 = 0; + break; + + case SVGA_REG_GMR_MAX_IDS: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd); + *pu32 = pThis->svga.cGMR; + break; + + case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd); + *pu32 = VMSVGA_MAX_GMR_PAGES; + break; + + case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd); + *pu32 = pThis->svga.fTraces; + break; + + case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd); + *pu32 = VMSVGA_MAX_GMR_PAGES; + break; + + case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd); + *pu32 = VMSVGA_SURFACE_SIZE; + break; + + case SVGA_REG_TOP: /* Must be 1 more than the last register */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd); + break; + + /* Mouse cursor support. */ + case SVGA_REG_DEAD: /* SVGA_REG_CURSOR_ID */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdRd); + *pu32 = pThis->svga.uCursorID; + break; + + case SVGA_REG_CURSOR_X: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXRd); + *pu32 = pThis->svga.uCursorX; + break; + + case SVGA_REG_CURSOR_Y: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYRd); + *pu32 = pThis->svga.uCursorY; + break; + + case SVGA_REG_CURSOR_ON: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnRd); + *pu32 = pThis->svga.uCursorOn; + break; + + /* Legacy multi-monitor support */ + case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd); + *pu32 = 1; + break; + + case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd); + *pu32 = 0; + break; + + case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd); + *pu32 = 0; + break; + + case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd); + *pu32 = 0; + break; + + case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd); + *pu32 = 0; + break; + + case SVGA_REG_DISPLAY_WIDTH: /* The display's width */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd); + *pu32 = pThis->svga.uWidth; + break; + + case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd); + *pu32 = pThis->svga.uHeight; + break; + + case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd); + /* We must return something sensible here otherwise the Linux driver + will take a legacy code path without 3d support. This number also + limits how many screens Linux guests will allow. */ + *pu32 = pThis->cMonitors; + break; + + /* + * SVGA_CAP_GBOBJECTS+ registers. + */ + case SVGA_REG_COMMAND_LOW: + /* Lower 32 bits of command buffer physical address. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowRd); + *pu32 = pThis->svga.u32RegCommandLow; + break; + + case SVGA_REG_COMMAND_HIGH: + /* Upper 32 bits of command buffer PA. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighRd); + *pu32 = pThis->svga.u32RegCommandHigh; + break; + + case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM: + /* Max primary (screen) memory. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxPrimBBMemRd); + *pu32 = pThis->vram_size; /** @todo Maybe half VRAM? */ + break; + + case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB: + /* Suggested limit on mob mem (i.e. size of the guest mapped VRAM in KB) */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGBMemSizeRd); + *pu32 = pThis->vram_size / 1024; + break; + + case SVGA_REG_DEV_CAP: + /* Write dev cap index, read value */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapRd); + if (pThis->svga.u32DevCapIndex < RT_ELEMENTS(pThis->svga.au32DevCaps)) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + *pu32 = pThis->svga.au32DevCaps[pThis->svga.u32DevCapIndex]; + } + else + *pu32 = 0; + break; + + case SVGA_REG_CMD_PREPEND_LOW: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowRd); + *pu32 = 0; /* Not supported. */ + break; + + case SVGA_REG_CMD_PREPEND_HIGH: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighRd); + *pu32 = 0; /* Not supported. */ + break; + + case SVGA_REG_SCREENTARGET_MAX_WIDTH: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxWidthRd); + *pu32 = pThis->svga.u32MaxWidth; + break; + + case SVGA_REG_SCREENTARGET_MAX_HEIGHT: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxHeightRd); + *pu32 = pThis->svga.u32MaxHeight; + break; + + case SVGA_REG_MOB_MAX_SIZE: + /* Essentially the max texture size */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegMobMaxSizeRd); + *pu32 = _128M; /** @todo Some actual value. Probably the mapped VRAM size. */ + break; + + case SVGA_REG_BLANK_SCREEN_TARGETS: + /// @todo STAM_REL_COUNTER_INC(&pThis->svga.aStatRegRd[idxReg]); + *pu32 = 0; /* Not supported. */ + break; + + case SVGA_REG_CAP2: + *pu32 = pThis->svga.u32DeviceCaps2; + break; + + case SVGA_REG_DEVEL_CAP: + *pu32 = 0; /* Not supported. */ + break; + + /* + * SVGA_REG_GUEST_DRIVER_* registers require SVGA_CAP2_DX2. + */ + case SVGA_REG_GUEST_DRIVER_ID: + *pu32 = pThis->svga.u32GuestDriverId; + break; + + case SVGA_REG_GUEST_DRIVER_VERSION1: + *pu32 = pThis->svga.u32GuestDriverVer1; + break; + + case SVGA_REG_GUEST_DRIVER_VERSION2: + *pu32 = pThis->svga.u32GuestDriverVer2; + break; + + case SVGA_REG_GUEST_DRIVER_VERSION3: + *pu32 = pThis->svga.u32GuestDriverVer3; + break; + + /* + * SVGA_REG_CURSOR_ registers require SVGA_CAP2_CURSOR_MOB which the device does not support currently. + */ + case SVGA_REG_CURSOR_MOBID: + *pu32 = SVGA_ID_INVALID; + break; + + case SVGA_REG_CURSOR_MAX_BYTE_SIZE: + *pu32 = 0; + break; + + case SVGA_REG_CURSOR_MAX_DIMENSION: + *pu32 = 0; + break; + + case SVGA_REG_FIFO_CAPS: + case SVGA_REG_FENCE: /* Same as SVGA_FIFO_FENCE for PCI_ID_SVGA3. Our device is PCI_ID_SVGA2 so not supported. */ + case SVGA_REG_RESERVED1: /* SVGA_REG_RESERVED* correspond to SVGA_REG_CURSOR4_*. Require SVGA_CAP2_EXTRA_REGS. */ + case SVGA_REG_RESERVED2: + case SVGA_REG_RESERVED3: + case SVGA_REG_RESERVED4: + case SVGA_REG_RESERVED5: + case SVGA_REG_SCREENDMA: + *pu32 = 0; /* Not supported. */ + break; + + case SVGA_REG_GBOBJECT_MEM_SIZE_KB: + /** @todo "The maximum amount of guest-backed objects that the device can have resident at a time" */ + *pu32 = _1G / _1K; + break; + + default: + { + uint32_t offReg; + if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion) + { + STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd); + RT_UNTRUSTED_VALIDATED_FENCE(); + *pu32 = pThis->svga.au32ScratchRegion[offReg]; + } + else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS) + { + /* Note! Using last_palette rather than palette here to preserve the VGA one. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd); + RT_UNTRUSTED_VALIDATED_FENCE(); + uint32_t u32 = pThis->last_palette[offReg / 3]; + switch (offReg % 3) + { + case 0: *pu32 = (u32 >> 16) & 0xff; break; /* red */ + case 1: *pu32 = (u32 >> 8) & 0xff; break; /* green */ + case 2: *pu32 = u32 & 0xff; break; /* blue */ + } + } + else + { +#if !defined(IN_RING3) && defined(VBOX_STRICT) + rc = VINF_IOM_R3_IOPORT_READ; +#else + STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd); + + /* Do not assert. The guest might be reading all registers. */ + LogFunc(("Unknown reg=%#x\n", idxReg)); +#endif + } + break; + } + } + LogFlow(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc)); + return rc; +} + +#ifdef IN_RING3 +/** + * Apply the current resolution settings to change the video mode. + * + * @returns VBox status code. + * @param pThis The shared VGA state. + * @param pThisCC The ring-3 VGA state. + */ +int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + /* Always do changemode on FIFO thread. */ + Assert(RTThreadSelf() == pThisCC->svga.pFIFOIOThread->Thread); + + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + + pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, true); + + if (pThis->svga.fGFBRegisters) + { + /* "For backwards compatibility, when the GFB mode registers (WIDTH, + * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device + * deletes all screens other than screen #0, and redefines screen + * #0 according to the specified mode. Drivers that use + * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0." + */ + + VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0]; + Assert(pScreen->idScreen == 0); + pScreen->fDefined = true; + pScreen->fModified = true; + pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY; + pScreen->xOrigin = 0; + pScreen->yOrigin = 0; + pScreen->offVRAM = 0; + pScreen->cbPitch = pThis->svga.cbScanline; + pScreen->cWidth = pThis->svga.uWidth; + pScreen->cHeight = pThis->svga.uHeight; + pScreen->cBpp = pThis->svga.uBpp; + + for (unsigned iScreen = 1; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen) + { + /* Delete screen. */ + pScreen = &pSVGAState->aScreens[iScreen]; + if (pScreen->fDefined) + { + pScreen->fModified = true; + pScreen->fDefined = false; + } + } + } + else + { + /* "If Screen Objects are supported, they can be used to fully + * replace the functionality provided by the framebuffer registers + * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY." + */ + pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED; + pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED; + pThis->svga.uBpp = pThis->svga.uHostBpp; + } + + vmsvgaR3VBVAResize(pThis, pThisCC); + + /* Last stuff. For the VGA device screenshot. */ + pThis->last_bpp = pSVGAState->aScreens[0].cBpp; + pThis->last_scr_width = pSVGAState->aScreens[0].cWidth; + pThis->last_scr_height = pSVGAState->aScreens[0].cHeight; + pThis->last_width = pSVGAState->aScreens[0].cWidth; + pThis->last_height = pSVGAState->aScreens[0].cHeight; + + /* vmsvgaPortSetViewPort not called after state load; set sensible defaults. */ + if ( pThis->svga.viewport.cx == 0 + && pThis->svga.viewport.cy == 0) + { + pThis->svga.viewport.cx = pSVGAState->aScreens[0].cWidth; + pThis->svga.viewport.xRight = pSVGAState->aScreens[0].cWidth; + pThis->svga.viewport.cy = pSVGAState->aScreens[0].cHeight; + pThis->svga.viewport.yHighWC = pSVGAState->aScreens[0].cHeight; + pThis->svga.viewport.yLowWC = 0; + } + + return VINF_SUCCESS; +} + +int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h) +{ + ASSERT_GUEST_LOGREL_MSG_RETURN(w > 0 && h > 0, + ("vmsvgaR3UpdateScreen: screen %d (%d,%d) %dx%d: Invalid height and/or width supplied.\n", + pScreen->idScreen, x, y, w, h), + VERR_INVALID_PARAMETER); + + VBVACMDHDR cmd; + cmd.x = (int16_t)(pScreen->xOrigin + x); + cmd.y = (int16_t)(pScreen->yOrigin + y); + cmd.w = (uint16_t)w; + cmd.h = (uint16_t)h; + + pThisCC->pDrv->pfnVBVAUpdateBegin(pThisCC->pDrv, pScreen->idScreen); + pThisCC->pDrv->pfnVBVAUpdateProcess(pThisCC->pDrv, pScreen->idScreen, &cmd, sizeof(cmd)); + pThisCC->pDrv->pfnVBVAUpdateEnd(pThisCC->pDrv, pScreen->idScreen, + pScreen->xOrigin + x, pScreen->yOrigin + y, w, h); + + return VINF_SUCCESS; +} + +#endif /* IN_RING3 */ +#if defined(IN_RING0) || defined(IN_RING3) + +/** + * Safely updates the SVGA_FIFO_BUSY register (in shared memory). + * + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param fState The busy state. + */ +DECLINLINE(void) vmsvgaHCSafeFifoBusyRegUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, bool fState) +{ + ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState); + + if (RT_UNLIKELY(fState != (pThis->svga.fBusy != 0))) + { + /* Race / unfortunately scheduling. Highly unlikly. */ + uint32_t cLoops = 64; + do + { + ASMNopPause(); + fState = (pThis->svga.fBusy != 0); + ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState != 0); + } while (cLoops-- > 0 && fState != (pThis->svga.fBusy != 0)); + } +} + + +/** + * Update the scanline pitch in response to the guest changing mode + * width/bpp. + * + * @param pThis The shared VGA/VMSVGA state. + * @param pThisCC The VGA/VMSVGA state for the current context. + */ +DECLINLINE(void) vmsvgaHCUpdatePitch(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO; + uint32_t uFifoPitchLock = pFIFO[SVGA_FIFO_PITCHLOCK]; + uint32_t uRegPitchLock = pThis->svga.u32PitchLock; + uint32_t uFifoMin = pFIFO[SVGA_FIFO_MIN]; + + /* The SVGA_FIFO_PITCHLOCK register is only valid if SVGA_FIFO_MIN points past + * it. If SVGA_FIFO_MIN is small, there may well be data at the SVGA_FIFO_PITCHLOCK + * location but it has a different meaning. + */ + if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK) + uFifoPitchLock = 0; + + /* Sanitize values. */ + if ((uFifoPitchLock < 200) || (uFifoPitchLock > 32768)) + uFifoPitchLock = 0; + if ((uRegPitchLock < 200) || (uRegPitchLock > 32768)) + uRegPitchLock = 0; + + /* Prefer the register value to the FIFO value.*/ + if (uRegPitchLock) + pThis->svga.cbScanline = uRegPitchLock; + else if (uFifoPitchLock) + pThis->svga.cbScanline = uFifoPitchLock; + else + pThis->svga.cbScanline = (uint32_t)pThis->svga.uWidth * (RT_ALIGN(pThis->svga.uBpp, 8) / 8); + + if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK) + pThis->svga.u32PitchLock = pThis->svga.cbScanline; +} + +#endif /* IN_RING0 || IN_RING3 */ + +#ifdef IN_RING3 + +/** + * Sends cursor position and visibility information from legacy + * SVGA registers to the front-end. + */ +static void vmsvgaR3RegUpdateCursor(PVGASTATECC pThisCC, PVGASTATE pThis, uint32_t uCursorOn) +{ + /* + * Writing the X/Y/ID registers does not trigger changes; only writing the + * SVGA_REG_CURSOR_ON register does. That minimizes the overhead. + * We boldly assume that guests aren't stupid and aren't writing the CURSOR_ON + * register if they don't have to. + */ + uint32_t x, y, idScreen; + uint32_t fFlags = VBVA_CURSOR_VALID_DATA; + + x = pThis->svga.uCursorX; + y = pThis->svga.uCursorY; + idScreen = SVGA_ID_INVALID; /* The old register interface is single screen only. */ + + /* The original values for SVGA_REG_CURSOR_ON were off (0) and on (1); later, the values + * were extended as follows: + * + * SVGA_CURSOR_ON_HIDE 0 + * SVGA_CURSOR_ON_SHOW 1 + * SVGA_CURSOR_ON_REMOVE_FROM_FB 2 - cursor on but not in the framebuffer + * SVGA_CURSOR_ON_RESTORE_TO_FB 3 - cursor on, possibly in the framebuffer + * + * Since we never draw the cursor into the guest's framebuffer, we do not need to + * distinguish between the non-zero values but still remember them. + */ + if (RT_BOOL(pThis->svga.uCursorOn) != RT_BOOL(uCursorOn)) + { + LogRel2(("vmsvgaR3RegUpdateCursor: uCursorOn %d prev CursorOn %d (%d,%d)\n", uCursorOn, pThis->svga.uCursorOn, x, y)); + pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(uCursorOn), false, 0, 0, 0, 0, NULL); + } + pThis->svga.uCursorOn = uCursorOn; + pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y); +} + +#endif /* IN_RING3 */ + + +/** + * Write port register + * + * @returns Strict VBox status code. + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA state. + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param u32 Value to write + */ +static VBOXSTRICTRC vmsvgaWritePort(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32) +{ +#ifdef IN_RING3 + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; +#endif + VBOXSTRICTRC rc = VINF_SUCCESS; + RT_NOREF(pThisCC); + + /* Rough index register validation. */ + uint32_t idxReg = pThis->svga.u32IndexReg; +#if !defined(IN_RING3) && defined(VBOX_STRICT) + ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg), + VINF_IOM_R3_IOPORT_WRITE); +#else + ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg), + STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr), + VINF_SUCCESS); +#endif + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */ + if ( idxReg >= SVGA_REG_ID_0_TOP + && pThis->svga.u32SVGAId == SVGA_ID_0) + { + idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP; + Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg)); + } +#ifdef LOG_ENABLED + if (idxReg != SVGA_REG_DEV_CAP) + LogFlow(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32)); + else + LogFlow(("vmsvgaWritePort index=%s (%d) val=%s (%d)\n", vmsvgaIndexToString(pThis, idxReg), idxReg, vmsvgaDevCapIndexToString((SVGA3dDevCapIndex)u32), u32)); +#endif + /* Check if the guest uses legacy registers. See vmsvgaR3ChangeMode */ + switch (idxReg) + { + case SVGA_REG_WIDTH: + case SVGA_REG_HEIGHT: + case SVGA_REG_PITCHLOCK: + case SVGA_REG_BITS_PER_PIXEL: + pThis->svga.fGFBRegisters = true; + break; + default: + break; + } + + switch (idxReg) + { + case SVGA_REG_ID: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr); + if ( u32 == SVGA_ID_0 + || u32 == SVGA_ID_1 + || u32 == SVGA_ID_2) + pThis->svga.u32SVGAId = u32; + else + PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32); + break; + + case SVGA_REG_ENABLE: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr); +#ifdef IN_RING3 + if ( (u32 & SVGA_REG_ENABLE_ENABLE) + && pThis->svga.fEnabled == false) + { + /* Make a backup copy of the first 512kb in order to save font data etc. */ + /** @todo should probably swap here, rather than copy + zero */ + memcpy(pThisCC->svga.pbVgaFrameBufferR3, pThisCC->pbVRam, VMSVGA_VGA_FB_BACKUP_SIZE); + memset(pThisCC->pbVRam, 0, VMSVGA_VGA_FB_BACKUP_SIZE); + } + + pThis->svga.fEnabled = u32; + if (pThis->svga.fEnabled) + { + if ( pThis->svga.uWidth == VMSVGA_VAL_UNINITIALIZED + && pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED) + { + /* Keep the current mode. */ + pThis->svga.uWidth = pThisCC->pDrv->cx; + pThis->svga.uHeight = pThisCC->pDrv->cy; + pThis->svga.uBpp = (pThisCC->pDrv->cBits + 7) & ~7; + vmsvgaHCUpdatePitch(pThis, pThisCC); + } + + if ( pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED + && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED) + ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE); +# ifdef LOG_ENABLED + uint32_t *pFIFO = pThisCC->svga.pau32FIFO; + Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY])); + Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP])); +# endif + + /* Disable or enable dirty page tracking according to the current fTraces value. */ + vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces); + + /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */ + for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen) + pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, idScreen, NULL /*pHostFlags*/); + + /* Make the cursor visible again as needed. */ + if (pSVGAState->Cursor.fActive) + pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, false, 0, 0, 0, 0, NULL); + } + else + { + /* Make sure the cursor is off. */ + if (pSVGAState->Cursor.fActive) + pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, false /*fVisible*/, false, 0, 0, 0, 0, NULL); + + /* Restore the text mode backup. */ + memcpy(pThisCC->pbVRam, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE); + + pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, false); + + /* Enable dirty page tracking again when going into legacy mode. */ + vmsvgaR3SetTraces(pDevIns, pThis, true); + + /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */ + for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen) + pThisCC->pDrv->pfnVBVADisable(pThisCC->pDrv, idScreen); + + /* Clear the pitch lock. */ + pThis->svga.u32PitchLock = 0; + } +#else /* !IN_RING3 */ + rc = VINF_IOM_R3_IOPORT_WRITE; +#endif /* !IN_RING3 */ + break; + + case SVGA_REG_WIDTH: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr); + if (u32 != pThis->svga.uWidth) + { + if (u32 <= pThis->svga.u32MaxWidth) + { +#if defined(IN_RING3) || defined(IN_RING0) + pThis->svga.uWidth = u32; + vmsvgaHCUpdatePitch(pThis, pThisCC); + if (pThis->svga.fEnabled) + ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE); +#else + rc = VINF_IOM_R3_IOPORT_WRITE; +#endif + } + else + Log(("SVGA_REG_WIDTH: New value is out of bounds: %u, max %u\n", u32, pThis->svga.u32MaxWidth)); + } + /* else: nop */ + break; + + case SVGA_REG_HEIGHT: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr); + if (u32 != pThis->svga.uHeight) + { + if (u32 <= pThis->svga.u32MaxHeight) + { + pThis->svga.uHeight = u32; + if (pThis->svga.fEnabled) + ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE); + } + else + Log(("SVGA_REG_HEIGHT: New value is out of bounds: %u, max %u\n", u32, pThis->svga.u32MaxHeight)); + } + /* else: nop */ + break; + + case SVGA_REG_DEPTH: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr); + /** @todo read-only?? */ + break; + + case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr); + if (pThis->svga.uBpp != u32) + { + if (u32 <= 32) + { +#if defined(IN_RING3) || defined(IN_RING0) + pThis->svga.uBpp = u32; + vmsvgaHCUpdatePitch(pThis, pThisCC); + if (pThis->svga.fEnabled) + ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE); +#else + rc = VINF_IOM_R3_IOPORT_WRITE; +#endif + } + else + Log(("SVGA_REG_BITS_PER_PIXEL: New value is out of bounds: %u, max 32\n", u32)); + } + /* else: nop */ + break; + + case SVGA_REG_PSEUDOCOLOR: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr); + break; + + case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */ +#ifdef IN_RING3 + STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr); + pThis->svga.fConfigured = u32; + /* Disabling the FIFO enables tracing (dirty page detection) by default. */ + if (!pThis->svga.fConfigured) + pThis->svga.fTraces = true; + vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces); +#else + rc = VINF_IOM_R3_IOPORT_WRITE; +#endif + break; + + case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr); + if ( pThis->svga.fEnabled + && pThis->svga.fConfigured) + { +#if defined(IN_RING3) || defined(IN_RING0) + Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY])); + /* + * The VMSVGA_BUSY_F_EMT_FORCE flag makes sure we will check if the FIFO is empty + * at least once; VMSVGA_BUSY_F_FIFO alone does not ensure that. + */ + ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO); + if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThisCC->svga.pau32FIFO[SVGA_FIFO_MIN])) + vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, true); + + /* Kick the FIFO thread to start processing commands again. */ + PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem); +#else + rc = VINF_IOM_R3_IOPORT_WRITE; +#endif + } + /* else nothing to do. */ + else + Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured)); + + break; + + case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" (read-only) */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr); + break; + + case SVGA_REG_GUEST_ID: /* Set guest OS identifier */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr); + pThis->svga.u32GuestId = u32; + break; + + case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr); + pThis->svga.u32PitchLock = u32; + /* Should this also update the FIFO pitch lock? Unclear. */ + break; + + case SVGA_REG_IRQMASK: /* Interrupt mask */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr); + pThis->svga.u32IrqMask = u32; + + /* Irq pending after the above change? */ + if (pThis->svga.u32IrqStatus & u32) + { + Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus)); + PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 1); + } + else + PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0); + break; + + /* Mouse cursor support */ + case SVGA_REG_DEAD: /* SVGA_REG_CURSOR_ID */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdWr); + pThis->svga.uCursorID = u32; + break; + + case SVGA_REG_CURSOR_X: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXWr); + pThis->svga.uCursorX = u32; + break; + + case SVGA_REG_CURSOR_Y: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYWr); + pThis->svga.uCursorY = u32; + break; + + case SVGA_REG_CURSOR_ON: +#ifdef IN_RING3 + /* The cursor is only updated when SVGA_REG_CURSOR_ON is written. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnWr); + vmsvgaR3RegUpdateCursor(pThisCC, pThis, u32); +#else + rc = VINF_IOM_R3_IOPORT_WRITE; +#endif + break; + + /* Legacy multi-monitor support */ + case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr); + break; + case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr); + break; + case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr); + break; + case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr); + break; + case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr); + break; + case SVGA_REG_DISPLAY_WIDTH: /* The display's width */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr); + break; + case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr); + break; +#ifdef VBOX_WITH_VMSVGA3D + /* See "Guest memory regions" below. */ + case SVGA_REG_GMR_ID: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr); + pThis->svga.u32CurrentGMRId = u32; + break; + + case SVGA_REG_GMR_DESCRIPTOR: +# ifndef IN_RING3 + rc = VINF_IOM_R3_IOPORT_WRITE; + break; +# else /* IN_RING3 */ + { + STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr); + + /* Validate current GMR id. */ + uint32_t idGMR = pThis->svga.u32CurrentGMRId; + AssertBreak(idGMR < pThis->svga.cGMR); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Free the old GMR if present. */ + vmsvgaR3GmrFree(pThisCC, idGMR); + + /* Just undefine the GMR? */ + RTGCPHYS GCPhys = (RTGCPHYS)u32 << GUEST_PAGE_SHIFT; + if (GCPhys == 0) + { + STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree); + break; + } + + + /* Never cross a page boundary automatically. */ + const uint32_t cMaxPages = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE); + uint32_t cPagesTotal = 0; + uint32_t iDesc = 0; + PVMSVGAGMRDESCRIPTOR paDescs = NULL; + uint32_t cLoops = 0; + RTGCPHYS GCPhysBase = GCPhys; + while ((GCPhys >> GUEST_PAGE_SHIFT) == (GCPhysBase >> GUEST_PAGE_SHIFT)) + { + /* Read descriptor. */ + SVGAGuestMemDescriptor desc; + rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhys, &desc, sizeof(desc)); + AssertRCBreak(VBOXSTRICTRC_VAL(rc)); + + if (desc.numPages != 0) + { + AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE); + cPagesTotal += desc.numPages; + AssertBreakStmt(cPagesTotal <= cMaxPages, rc = VERR_OUT_OF_RANGE); + + if ((iDesc & 15) == 0) + { + void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR)); + AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY); + paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew; + } + + paDescs[iDesc].GCPhys = (RTGCPHYS)desc.ppn << GUEST_PAGE_SHIFT; + paDescs[iDesc++].numPages = desc.numPages; + + /* Continue with the next descriptor. */ + GCPhys += sizeof(desc); + } + else if (desc.ppn == 0) + break; /* terminator */ + else /* Pointer to the next physical page of descriptors. */ + GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << GUEST_PAGE_SHIFT; + + cLoops++; + AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE); + } + + AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE); + if (RT_SUCCESS(rc)) + { + /* Commit the GMR. */ + pSVGAState->paGMR[idGMR].paDesc = paDescs; + pSVGAState->paGMR[idGMR].numDescriptors = iDesc; + pSVGAState->paGMR[idGMR].cMaxPages = cPagesTotal; + pSVGAState->paGMR[idGMR].cbTotal = cPagesTotal * GUEST_PAGE_SIZE; + Assert((pSVGAState->paGMR[idGMR].cbTotal >> GUEST_PAGE_SHIFT) == cPagesTotal); + Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n", + idGMR, iDesc, pSVGAState->paGMR[idGMR].cbTotal, cPagesTotal)); + } + else + { + RTMemFree(paDescs); + STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors); + } + break; + } +# endif /* IN_RING3 */ +#endif // VBOX_WITH_VMSVGA3D + + case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr); + if (pThis->svga.fTraces == u32) + break; /* nothing to do */ + +#ifdef IN_RING3 + vmsvgaR3SetTraces(pDevIns, pThis, !!u32); +#else + rc = VINF_IOM_R3_IOPORT_WRITE; +#endif + break; + + case SVGA_REG_TOP: /* Must be 1 more than the last register */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr); + break; + + case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr); + Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32)); + break; + + /* + * SVGA_CAP_GBOBJECTS+ registers. + */ + case SVGA_REG_COMMAND_LOW: + { + /* Lower 32 bits of command buffer physical address and submit the command buffer. */ +#ifdef IN_RING3 + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowWr); + pThis->svga.u32RegCommandLow = u32; + + /* "lower 6 bits are used for the SVGACBContext" */ + RTGCPHYS GCPhysCB = pThis->svga.u32RegCommandHigh; + GCPhysCB <<= 32; + GCPhysCB |= pThis->svga.u32RegCommandLow & ~SVGA_CB_CONTEXT_MASK; + SVGACBContext const CBCtx = (SVGACBContext)(pThis->svga.u32RegCommandLow & SVGA_CB_CONTEXT_MASK); + vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, GCPhysCB, CBCtx); +#else + rc = VINF_IOM_R3_IOPORT_WRITE; +#endif + break; + } + + case SVGA_REG_COMMAND_HIGH: + /* Upper 32 bits of command buffer PA. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighWr); + pThis->svga.u32RegCommandHigh = u32; + break; + + case SVGA_REG_DEV_CAP: + /* Write dev cap index, read value */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapWr); + pThis->svga.u32DevCapIndex = u32; + break; + + case SVGA_REG_CMD_PREPEND_LOW: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowWr); + /* Not supported. */ + break; + + case SVGA_REG_CMD_PREPEND_HIGH: + STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighWr); + /* Not supported. */ + break; + + case SVGA_REG_GUEST_DRIVER_ID: + if (u32 != SVGA_REG_GUEST_DRIVER_ID_SUBMIT) + pThis->svga.u32GuestDriverId = u32; + break; + + case SVGA_REG_GUEST_DRIVER_VERSION1: + pThis->svga.u32GuestDriverVer1 = u32; + break; + + case SVGA_REG_GUEST_DRIVER_VERSION2: + pThis->svga.u32GuestDriverVer2 = u32; + break; + + case SVGA_REG_GUEST_DRIVER_VERSION3: + pThis->svga.u32GuestDriverVer3 = u32; + break; + + case SVGA_REG_CURSOR_MOBID: + /* Not supported, ignore. See correspondent comments in vmsvgaReadPort. */ + break; + + case SVGA_REG_FB_START: + case SVGA_REG_MEM_START: + case SVGA_REG_HOST_BITS_PER_PIXEL: + case SVGA_REG_MAX_WIDTH: + case SVGA_REG_MAX_HEIGHT: + case SVGA_REG_VRAM_SIZE: + case SVGA_REG_FB_SIZE: + case SVGA_REG_CAPABILITIES: + case SVGA_REG_MEM_SIZE: + case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */ + case SVGA_REG_MEM_REGS: /* Number of FIFO registers */ + case SVGA_REG_BYTES_PER_LINE: + case SVGA_REG_FB_OFFSET: + case SVGA_REG_RED_MASK: + case SVGA_REG_GREEN_MASK: + case SVGA_REG_BLUE_MASK: + case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */ + case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */ + case SVGA_REG_GMR_MAX_IDS: + case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH: + case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM: + case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB: + case SVGA_REG_SCREENTARGET_MAX_WIDTH: + case SVGA_REG_SCREENTARGET_MAX_HEIGHT: + case SVGA_REG_MOB_MAX_SIZE: + case SVGA_REG_BLANK_SCREEN_TARGETS: + case SVGA_REG_CAP2: + case SVGA_REG_DEVEL_CAP: + case SVGA_REG_CURSOR_MAX_BYTE_SIZE: + case SVGA_REG_CURSOR_MAX_DIMENSION: + case SVGA_REG_FIFO_CAPS: + case SVGA_REG_FENCE: + case SVGA_REG_RESERVED1: + case SVGA_REG_RESERVED2: + case SVGA_REG_RESERVED3: + case SVGA_REG_RESERVED4: + case SVGA_REG_RESERVED5: + case SVGA_REG_SCREENDMA: + case SVGA_REG_GBOBJECT_MEM_SIZE_KB: + /* Read only - ignore. */ + Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32)); + STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr); + break; + + default: + { + uint32_t offReg; + if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + pThis->svga.au32ScratchRegion[offReg] = u32; + STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr); + } + else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS) + { + /* Note! Using last_palette rather than palette here to preserve the VGA one. + Btw, see rgb_to_pixel32. */ + STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr); + u32 &= 0xff; + RT_UNTRUSTED_VALIDATED_FENCE(); + uint32_t uRgb = pThis->last_palette[offReg / 3]; + switch (offReg % 3) + { + case 0: uRgb = (uRgb & UINT32_C(0x0000ffff)) | (u32 << 16); break; /* red */ + case 1: uRgb = (uRgb & UINT32_C(0x00ff00ff)) | (u32 << 8); break; /* green */ + case 2: uRgb = (uRgb & UINT32_C(0x00ffff00)) | u32 ; break; /* blue */ + } + pThis->last_palette[offReg / 3] = uRgb; + } + else + { +#if !defined(IN_RING3) && defined(VBOX_STRICT) + rc = VINF_IOM_R3_IOPORT_WRITE; +#else + STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr); + AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32)); +#endif + } + break; + } + } + return rc; +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN} + */ +DECLCALLBACK(VBOXSTRICTRC) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + RT_NOREF_PV(pvUser); + + /* Only dword accesses. */ + if (cb == 4) + { + switch (offPort) + { + case SVGA_INDEX_PORT: + *pu32 = pThis->svga.u32IndexReg; + break; + + case SVGA_VALUE_PORT: + return vmsvgaReadPort(pDevIns, pThis, pu32); + + case SVGA_BIOS_PORT: + Log(("Ignoring BIOS port read\n")); + *pu32 = 0; + break; + + case SVGA_IRQSTATUS_PORT: + LogFlow(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus)); + *pu32 = pThis->svga.u32IrqStatus; + break; + + default: + ASSERT_GUEST_MSG_FAILED(("vmsvgaIORead: Unknown register %u was read from.\n", offPort)); + *pu32 = UINT32_MAX; + break; + } + } + else + { + Log(("Ignoring non-dword I/O port read at %x cb=%d\n", offPort, cb)); + *pu32 = UINT32_MAX; + } + return VINF_SUCCESS; +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT} + */ +DECLCALLBACK(VBOXSTRICTRC) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + RT_NOREF_PV(pvUser); + + /* Only dword accesses. */ + if (cb == 4) + switch (offPort) + { + case SVGA_INDEX_PORT: + pThis->svga.u32IndexReg = u32; + break; + + case SVGA_VALUE_PORT: + return vmsvgaWritePort(pDevIns, pThis, pThisCC, u32); + + case SVGA_BIOS_PORT: + Log(("Ignoring BIOS port write (val=%x)\n", u32)); + break; + + case SVGA_IRQSTATUS_PORT: + LogFlow(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32)); + ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32); + /* Clear the irq in case all events have been cleared. */ + if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask)) + { + Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT: clearing IRQ\n")); + PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0); + } + break; + + default: + ASSERT_GUEST_MSG_FAILED(("vmsvgaIOWrite: Unknown register %u was written to, value %#x LB %u.\n", offPort, u32, cb)); + break; + } + else + Log(("Ignoring non-dword write at %x val=%x cb=%d\n", offPort, u32, cb)); + + return VINF_SUCCESS; +} + +#ifdef IN_RING3 + +# ifdef DEBUG_FIFO_ACCESS +/** + * Handle FIFO memory access. + * @returns VBox status code. + * @param pVM VM handle. + * @param pThis The shared VGA/VMSVGA instance data. + * @param GCPhys The access physical address. + * @param fWriteAccess Read or write access + */ +static int vmsvgaR3DebugFifoAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess) +{ + RT_NOREF(pVM); + RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO; + uint32_t *pFIFO = pThisCC->svga.pau32FIFO; + + switch (GCPhysOffset >> 2) + { + case SVGA_FIFO_MIN: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MIN = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_MAX: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MAX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_NEXT_CMD: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_NEXT_CMD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_STOP: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_STOP = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_CAPABILITIES: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CAPABILITIES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_FLAGS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FLAGS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_FENCE: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_HWVERSION: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_PITCHLOCK: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_PITCHLOCK = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_CURSOR_ON: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_ON = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_CURSOR_X: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_X = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_CURSOR_Y: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_Y = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_CURSOR_COUNT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_CURSOR_LAST_UPDATED: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_LAST_UPDATED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_RESERVED: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_RESERVED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_CURSOR_SCREEN_ID: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_SCREEN_ID = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_DEAD: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_DEAD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_HWVERSION_REVISED: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION_REVISED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_3D: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_3D = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_LIGHTS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_LIGHTS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURES: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CLIP_PLANES: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CLIP_PLANES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_RENDER_TARGETS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S23E8_TEXTURES: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S23E8_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S10E5_TEXTURES: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S10E5_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D16_BUFFER_FORMAT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D16_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_QUERY_TYPES: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_QUERY_TYPES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_POINT_SIZE: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_POINT_SIZE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_INDEX: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_INDEX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_OPS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_OPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D16: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT1: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT2: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT3: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT3 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT4: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT5: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_V16U16: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_V16U16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_G16R16: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_UYVY: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_UYVY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_YUY2: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_YUY2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */ + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD4 (SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */ + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD5 (SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */ + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD7 (SVGA3D_DEVCAP_ALPHATOCOVERAGE) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */ + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD6 (SVGA3D_DEVCAP_SUPERSAMPLE) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_AUTOGENMIPMAPS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_AUTOGENMIPMAPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_NV12: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_NV12 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */ + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD10 (SVGA3D_DEVCAP_SURFACEFMT_AYUV) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CONTEXT_IDS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CONTEXT_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SURFACE_IDS: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SURFACE_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI1: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI2: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_3D_CAPS_LAST: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS_LAST = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_GUEST_3D_HWVERSION: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_GUEST_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_FENCE_GOAL: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE_GOAL = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + case SVGA_FIFO_BUSY: + Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_BUSY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2])); + break; + default: + Log(("vmsvgaFIFOAccess [0x%x]: %s access at offset %x = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", GCPhysOffset, pFIFO[GCPhysOffset >> 2])); + break; + } + + return VINF_EM_RAW_EMULATE_INSTR; +} +# endif /* DEBUG_FIFO_ACCESS */ + +# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS) +/** + * HC access handler for the FIFO. + * + * @returns VINF_SUCCESS if the handler have carried out the operation. + * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation. + * @param pVM VM Handle. + * @param pVCpu The cross context CPU structure for the calling EMT. + * @param GCPhys The physical address the guest is writing to. + * @param pvPhys The HC mapping of that address. + * @param pvBuf What the guest is reading/writing. + * @param cbBuf How much it's reading/writing. + * @param enmAccessType The access type. + * @param enmOrigin Who is making the access. + * @param pvUser User argument. + */ +static DECLCALLBACK(VBOXSTRICTRC) +vmsvgaR3FifoAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, + PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser) +{ + NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(enmAccessType); NOREF(GCPhys); + PVGASTATE pThis = (PVGASTATE)pvUser; + AssertPtr(pThis); + +# ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER + /* + * Wake up the FIFO thread as it might have work to do now. + */ + int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem); + AssertLogRelRC(rc); +# endif + +# ifdef DEBUG_FIFO_ACCESS + /* + * When in debug-fifo-access mode, we do not disable the access handler, + * but leave it on as we wish to catch all access. + */ + Assert(GCPhys >= pThis->svga.GCPhysFIFO); + rc = vmsvgaR3DebugFifoAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE); +# elif defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) + /* + * Temporarily disable the access handler now that we've kicked the FIFO thread. + */ + STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoAccessHandler); + rc = PGMHandlerPhysicalPageTempOff(pVM, pThis->svga.GCPhysFIFO, pThis->svga.GCPhysFIFO); +# endif + if (RT_SUCCESS(rc)) + return VINF_PGM_HANDLER_DO_DEFAULT; + AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc)); + return rc; +} +# endif /* VMSVGA_USE_FIFO_ACCESS_HANDLER || DEBUG_FIFO_ACCESS */ + +#endif /* IN_RING3 */ + +#ifdef DEBUG_GMR_ACCESS +# ifdef IN_RING3 + +/** + * HC access handler for GMRs. + * + * @returns VINF_SUCCESS if the handler have carried out the operation. + * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation. + * @param pVM VM Handle. + * @param pVCpu The cross context CPU structure for the calling EMT. + * @param GCPhys The physical address the guest is writing to. + * @param pvPhys The HC mapping of that address. + * @param pvBuf What the guest is reading/writing. + * @param cbBuf How much it's reading/writing. + * @param enmAccessType The access type. + * @param enmOrigin Who is making the access. + * @param pvUser User argument. + */ +static DECLCALLBACK(VBOXSTRICTRC) +vmsvgaR3GmrAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, + PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser) +{ + PVGASTATE pThis = (PVGASTATE)pvUser; + Assert(pThis); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType); NOREF(enmOrigin); + + Log(("vmsvgaR3GmrAccessHandler: GMR access to page %RGp\n", GCPhys)); + + for (uint32_t i = 0; i < pThis->svga.cGMR; ++i) + { + PGMR pGMR = &pSVGAState->paGMR[i]; + + if (pGMR->numDescriptors) + { + for (uint32_t j = 0; j < pGMR->numDescriptors; j++) + { + if ( GCPhys >= pGMR->paDesc[j].GCPhys + && GCPhys < pGMR->paDesc[j].GCPhys + pGMR->paDesc[j].numPages * GUEST_PAGE_SIZE) + { + /* + * Turn off the write handler for this particular page and make it R/W. + * Then return telling the caller to restart the guest instruction. + */ + int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys); + AssertRC(rc); + return VINF_PGM_HANDLER_DO_DEFAULT; + } + } + } + } + + return VINF_PGM_HANDLER_DO_DEFAULT; +} + +/** Callback handler for VMR3ReqCallWaitU */ +static DECLCALLBACK(int) vmsvgaR3RegisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + PGMR pGMR = &pSVGAState->paGMR[gmrId]; + int rc; + + for (uint32_t i = 0; i < pGMR->numDescriptors; i++) + { + rc = PDMDevHlpPGMHandlerPhysicalRegister(pDevIns, pGMR->paDesc[i].GCPhys, + pGMR->paDesc[i].GCPhys + pGMR->paDesc[i].numPages * GUEST_PAGE_SIZE - 1, + pThis->svga.hGmrAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR, "VMSVGA GMR"); + AssertRC(rc); + } + return VINF_SUCCESS; +} + +/** Callback handler for VMR3ReqCallWaitU */ +static DECLCALLBACK(int) vmsvgaR3DeregisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + PGMR pGMR = &pSVGAState->paGMR[gmrId]; + + for (uint32_t i = 0; i < pGMR->numDescriptors; i++) + { + int rc = PDMDevHlpPGMHandlerPhysicalDeregister(pDevIns, pGMR->paDesc[i].GCPhys); + AssertRC(rc); + } + return VINF_SUCCESS; +} + +/** Callback handler for VMR3ReqCallWaitU */ +static DECLCALLBACK(int) vmsvgaR3ResetGmrHandlers(PVGASTATE pThis) +{ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + + for (uint32_t i = 0; i < pThis->svga.cGMR; ++i) + { + PGMR pGMR = &pSVGAState->paGMR[i]; + + if (pGMR->numDescriptors) + { + for (uint32_t j = 0; j < pGMR->numDescriptors; j++) + { + int rc = PDMDevHlpPGMHandlerPhysicalReset(pDevIns, pGMR->paDesc[j].GCPhys); + AssertRC(rc); + } + } + } + return VINF_SUCCESS; +} + +# endif /* IN_RING3 */ +#endif /* DEBUG_GMR_ACCESS */ + +/* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */ + +#ifdef IN_RING3 + + +/* + * + * Command buffer submission. + * + * Guest submits a buffer by writing to SVGA_REG_COMMAND_LOW register. + * + * EMT thread appends a command buffer to the context queue (VMSVGACMDBUFCTX::listSubmitted) + * and wakes up the FIFO thread. + * + * FIFO thread fetches the command buffer from the queue, processes the commands and writes + * the buffer header back to the guest memory. + * + * If buffers are preempted, then the EMT thread removes all buffers from the context queue. + * + */ + + +/** Update a command buffer header 'status' and 'errorOffset' fields in the guest memory. + * + * @param pDevIns The device instance. + * @param GCPhysCB Guest physical address of the command buffer header. + * @param status Command buffer status (SVGA_CB_STATUS_*). + * @param errorOffset Offset to the first byte of the failing command for SVGA_CB_STATUS_COMMAND_ERROR. + * errorOffset is ignored if the status is not SVGA_CB_STATUS_COMMAND_ERROR. + * @thread FIFO or EMT. + */ +static void vmsvgaR3CmdBufWriteStatus(PPDMDEVINS pDevIns, RTGCPHYS GCPhysCB, SVGACBStatus status, uint32_t errorOffset) +{ + SVGACBHeader hdr; + hdr.status = status; + hdr.errorOffset = errorOffset; + AssertCompile( RT_OFFSETOF(SVGACBHeader, status) == 0 + && RT_OFFSETOF(SVGACBHeader, errorOffset) == 4 + && RT_OFFSETOF(SVGACBHeader, id) == 8); + size_t const cbWrite = status == SVGA_CB_STATUS_COMMAND_ERROR + ? RT_UOFFSET_AFTER(SVGACBHeader, errorOffset) /* Both 'status' and 'errorOffset' fields. */ + : RT_UOFFSET_AFTER(SVGACBHeader, status); /* Only 'status' field. */ + PDMDevHlpPCIPhysWrite(pDevIns, GCPhysCB, &hdr, cbWrite); +} + + +/** Raise an IRQ. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA state. + * @param u32IrqStatus SVGA_IRQFLAG_* bits. + * @thread FIFO or EMT. + */ +static void vmsvgaR3CmdBufRaiseIRQ(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t u32IrqStatus) +{ + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + + if (pThis->svga.u32IrqMask & u32IrqStatus) + { + LogFunc(("Trigger interrupt with status %#x\n", u32IrqStatus)); + ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus); + PDMDevHlpPCISetIrq(pDevIns, 0, 1); + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); +} + + +/** Allocate a command buffer structure. + * + * @param pCmdBufCtx The command buffer context which must allocate the buffer. + * @return Pointer to the allocated command buffer structure. + */ +static PVMSVGACMDBUF vmsvgaR3CmdBufAlloc(PVMSVGACMDBUFCTX pCmdBufCtx) +{ + if (!pCmdBufCtx) + return NULL; + + PVMSVGACMDBUF pCmdBuf = (PVMSVGACMDBUF)RTMemAllocZ(sizeof(*pCmdBuf)); + if (pCmdBuf) + { + // RT_ZERO(pCmdBuf->nodeBuffer); + pCmdBuf->pCmdBufCtx = pCmdBufCtx; + // pCmdBuf->GCPhysCB = 0; + // RT_ZERO(pCmdBuf->hdr); + // pCmdBuf->pvCommands = NULL; + } + + return pCmdBuf; +} + + +/** Free a command buffer structure. + * + * @param pCmdBuf The command buffer pointer. + */ +static void vmsvgaR3CmdBufFree(PVMSVGACMDBUF pCmdBuf) +{ + if (pCmdBuf) + RTMemFree(pCmdBuf->pvCommands); + RTMemFree(pCmdBuf); +} + + +/** Initialize a command buffer context. + * + * @param pCmdBufCtx The command buffer context. + */ +static void vmsvgaR3CmdBufCtxInit(PVMSVGACMDBUFCTX pCmdBufCtx) +{ + RTListInit(&pCmdBufCtx->listSubmitted); + pCmdBufCtx->cSubmitted = 0; +} + + +/** Destroy a command buffer context. + * + * @param pCmdBufCtx The command buffer context pointer. + */ +static void vmsvgaR3CmdBufCtxTerm(PVMSVGACMDBUFCTX pCmdBufCtx) +{ + if (!pCmdBufCtx) + return; + + if (pCmdBufCtx->listSubmitted.pNext) + { + /* If the list has been initialized. */ + PVMSVGACMDBUF pIter, pNext; + RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer) + { + RTListNodeRemove(&pIter->nodeBuffer); + --pCmdBufCtx->cSubmitted; + vmsvgaR3CmdBufFree(pIter); + } + } + Assert(pCmdBufCtx->cSubmitted == 0); + pCmdBufCtx->cSubmitted = 0; +} + + +/** Handles SVGA_DC_CMD_START_STOP_CONTEXT command. + * + * @param pSvgaR3State VMSVGA R3 state. + * @param pCmd The command data. + * @return SVGACBStatus code. + * @thread EMT + */ +static SVGACBStatus vmsvgaR3CmdBufDCStartStop(PVMSVGAR3STATE pSvgaR3State, SVGADCCmdStartStop const *pCmd) +{ + /* Create or destroy a regular command buffer context. */ + if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)) + return SVGA_CB_STATUS_COMMAND_ERROR; + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACBStatus CBStatus = SVGA_CB_STATUS_COMPLETED; + + int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf); + AssertRC(rc); + if (pCmd->enable) + { + pSvgaR3State->apCmdBufCtxs[pCmd->context] = (PVMSVGACMDBUFCTX)RTMemAlloc(sizeof(VMSVGACMDBUFCTX)); + if (pSvgaR3State->apCmdBufCtxs[pCmd->context]) + vmsvgaR3CmdBufCtxInit(pSvgaR3State->apCmdBufCtxs[pCmd->context]); + else + CBStatus = SVGA_CB_STATUS_QUEUE_FULL; + } + else + { + vmsvgaR3CmdBufCtxTerm(pSvgaR3State->apCmdBufCtxs[pCmd->context]); + RTMemFree(pSvgaR3State->apCmdBufCtxs[pCmd->context]); + pSvgaR3State->apCmdBufCtxs[pCmd->context] = NULL; + } + RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf); + + return CBStatus; +} + + +/** Handles SVGA_DC_CMD_PREEMPT command. + * + * @param pDevIns The device instance. + * @param pSvgaR3State VMSVGA R3 state. + * @param pCmd The command data. + * @return SVGACBStatus code. + * @thread EMT + */ +static SVGACBStatus vmsvgaR3CmdBufDCPreempt(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, SVGADCCmdPreempt const *pCmd) +{ + /* Remove buffers from the processing queue of the specified context. */ + if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)) + return SVGA_CB_STATUS_COMMAND_ERROR; + RT_UNTRUSTED_VALIDATED_FENCE(); + + PVMSVGACMDBUFCTX const pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[pCmd->context]; + RTLISTANCHOR listPreempted; + + int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf); + AssertRC(rc); + if (pCmd->ignoreIDZero) + { + RTListInit(&listPreempted); + + PVMSVGACMDBUF pIter, pNext; + RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer) + { + if (pIter->hdr.id == 0) + continue; + + RTListNodeRemove(&pIter->nodeBuffer); + --pCmdBufCtx->cSubmitted; + RTListAppend(&listPreempted, &pIter->nodeBuffer); + } + } + else + { + RTListMove(&listPreempted, &pCmdBufCtx->listSubmitted); + pCmdBufCtx->cSubmitted = 0; + } + RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf); + + PVMSVGACMDBUF pIter, pNext; + RTListForEachSafe(&listPreempted, pIter, pNext, VMSVGACMDBUF, nodeBuffer) + { + RTListNodeRemove(&pIter->nodeBuffer); + vmsvgaR3CmdBufWriteStatus(pDevIns, pIter->GCPhysCB, SVGA_CB_STATUS_PREEMPTED, 0); + LogFunc(("Preempted %RX64\n", pIter->GCPhysCB)); + vmsvgaR3CmdBufFree(pIter); + } + + return SVGA_CB_STATUS_COMPLETED; +} + + +/** @def VMSVGA_INC_CMD_SIZE_BREAK + * Increments the size of the command cbCmd by a_cbMore. + * Checks that the command buffer has at least cbCmd bytes. Will break out of the switch if it doesn't. + * Used by vmsvgaR3CmdBufProcessDC and vmsvgaR3CmdBufProcessCommands. + */ +#define VMSVGA_INC_CMD_SIZE_BREAK(a_cbMore) \ + if (1) { \ + cbCmd += (a_cbMore); \ + ASSERT_GUEST_MSG_STMT_BREAK(cbRemain >= cbCmd, ("size=%#x remain=%#zx\n", cbCmd, (size_t)cbRemain), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); \ + RT_UNTRUSTED_VALIDATED_FENCE(); \ + } else do {} while (0) + + +/** Processes Device Context command buffer. + * + * @param pDevIns The device instance. + * @param pSvgaR3State VMSVGA R3 state. + * @param pvCommands Pointer to the command buffer. + * @param cbCommands Size of the command buffer. + * @param poffNextCmd Where to store the offset of the first unprocessed command. + * @return SVGACBStatus code. + * @thread EMT + */ +static SVGACBStatus vmsvgaR3CmdBufProcessDC(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd) +{ + SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED; + + uint8_t const *pu8Cmd = (uint8_t *)pvCommands; + uint32_t cbRemain = cbCommands; + while (cbRemain) + { + /* Command identifier is a 32 bit value. */ + if (cbRemain < sizeof(uint32_t)) + { + CBstatus = SVGA_CB_STATUS_COMMAND_ERROR; + break; + } + + /* Fetch the command id. */ + uint32_t const cmdId = *(uint32_t *)pu8Cmd; + uint32_t cbCmd = sizeof(uint32_t); + switch (cmdId) + { + case SVGA_DC_CMD_NOP: + { + /* NOP */ + break; + } + + case SVGA_DC_CMD_START_STOP_CONTEXT: + { + SVGADCCmdStartStop *pCmd = (SVGADCCmdStartStop *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + CBstatus = vmsvgaR3CmdBufDCStartStop(pSvgaR3State, pCmd); + break; + } + + case SVGA_DC_CMD_PREEMPT: + { + SVGADCCmdPreempt *pCmd = (SVGADCCmdPreempt *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + CBstatus = vmsvgaR3CmdBufDCPreempt(pDevIns, pSvgaR3State, pCmd); + break; + } + + default: + { + /* Unsupported command. */ + CBstatus = SVGA_CB_STATUS_COMMAND_ERROR; + break; + } + } + + if (CBstatus != SVGA_CB_STATUS_COMPLETED) + break; + + pu8Cmd += cbCmd; + cbRemain -= cbCmd; + } + + Assert(cbRemain <= cbCommands); + *poffNextCmd = cbCommands - cbRemain; + return CBstatus; +} + + +/** Submits a device context command buffer for synchronous processing. + * + * @param pDevIns The device instance. + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param ppCmdBuf Pointer to the command buffer pointer. + * The function can set the command buffer pointer to NULL to prevent deallocation by the caller. + * @param poffNextCmd Where to store the offset of the first unprocessed command. + * @return SVGACBStatus code. + * @thread EMT + */ +static SVGACBStatus vmsvgaR3CmdBufSubmitDC(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf, uint32_t *poffNextCmd) +{ + /* Synchronously process the device context commands. */ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + return vmsvgaR3CmdBufProcessDC(pDevIns, pSvgaR3State, (*ppCmdBuf)->pvCommands, (*ppCmdBuf)->hdr.length, poffNextCmd); +} + +/** Submits a command buffer for asynchronous processing by the FIFO thread. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA state. + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param ppCmdBuf Pointer to the command buffer pointer. + * The function can set the command buffer pointer to NULL to prevent deallocation by the caller. + * @return SVGACBStatus code. + * @thread EMT + */ +static SVGACBStatus vmsvgaR3CmdBufSubmitCtx(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf) +{ + /* Command buffer submission. */ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE; + + PVMSVGACMDBUF const pCmdBuf = *ppCmdBuf; + PVMSVGACMDBUFCTX const pCmdBufCtx = pCmdBuf->pCmdBufCtx; + + int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf); + AssertRC(rc); + + if (RT_LIKELY(pCmdBufCtx->cSubmitted < SVGA_CB_MAX_QUEUED_PER_CONTEXT)) + { + RTListAppend(&pCmdBufCtx->listSubmitted, &pCmdBuf->nodeBuffer); + ++pCmdBufCtx->cSubmitted; + *ppCmdBuf = NULL; /* Consume the buffer. */ + ASMAtomicWriteU32(&pThisCC->svga.pSvgaR3State->fCmdBuf, 1); + } + else + CBstatus = SVGA_CB_STATUS_QUEUE_FULL; + + RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf); + + /* Inform the FIFO thread. */ + if (*ppCmdBuf == NULL) + PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem); + + return CBstatus; +} + + +/** SVGA_REG_COMMAND_LOW write handler. + * Submits a command buffer to the FIFO thread or processes a device context command. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA state. + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param GCPhysCB Guest physical address of the command buffer header. + * @param CBCtx Context the command buffer is submitted to. + * @thread EMT + */ +static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE; + uint32_t offNextCmd = 0; + uint32_t fIRQ = 0; + + /* Get the context if the device has the capability. */ + PVMSVGACMDBUFCTX pCmdBufCtx = NULL; + if (pThis->svga.u32DeviceCaps & SVGA_CAP_COMMAND_BUFFERS) + { + if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))) + pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[CBCtx]; + else if (CBCtx == SVGA_CB_CONTEXT_DEVICE) + pCmdBufCtx = &pSvgaR3State->CmdBufCtxDC; + RT_UNTRUSTED_VALIDATED_FENCE(); + } + + /* Allocate a new command buffer. */ + PVMSVGACMDBUF pCmdBuf = vmsvgaR3CmdBufAlloc(pCmdBufCtx); + if (RT_LIKELY(pCmdBuf)) + { + pCmdBuf->GCPhysCB = GCPhysCB; + + int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysCB, &pCmdBuf->hdr, sizeof(pCmdBuf->hdr)); + if (RT_SUCCESS(rc)) + { + LogFunc(("status %RX32 errorOffset %RX32 id %RX64 flags %RX32 length %RX32 ptr %RX64 offset %RX32 dxContext %RX32 (%RX32 %RX32 %RX32 %RX32 %RX32 %RX32)\n", + pCmdBuf->hdr.status, + pCmdBuf->hdr.errorOffset, + pCmdBuf->hdr.id, + pCmdBuf->hdr.flags, + pCmdBuf->hdr.length, + pCmdBuf->hdr.ptr.pa, + pCmdBuf->hdr.offset, + pCmdBuf->hdr.dxContext, + pCmdBuf->hdr.mustBeZero[0], + pCmdBuf->hdr.mustBeZero[1], + pCmdBuf->hdr.mustBeZero[2], + pCmdBuf->hdr.mustBeZero[3], + pCmdBuf->hdr.mustBeZero[4], + pCmdBuf->hdr.mustBeZero[5])); + + /* Verify the command buffer header. */ + if (RT_LIKELY( pCmdBuf->hdr.status == SVGA_CB_STATUS_NONE + && (pCmdBuf->hdr.flags & ~(SVGA_CB_FLAG_NO_IRQ | SVGA_CB_FLAG_DX_CONTEXT)) == 0 /* No unexpected flags. */ + && pCmdBuf->hdr.length <= SVGA_CB_MAX_SIZE)) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Read the command buffer content. */ + pCmdBuf->pvCommands = RTMemAlloc(pCmdBuf->hdr.length); + if (pCmdBuf->pvCommands) + { + RTGCPHYS const GCPhysCmd = (RTGCPHYS)pCmdBuf->hdr.ptr.pa; + rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysCmd, pCmdBuf->pvCommands, pCmdBuf->hdr.length); + if (RT_SUCCESS(rc)) + { + /* Submit the buffer. Device context buffers will be processed synchronously. */ + if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))) + /* This usually processes the CB async and sets pCmbBuf to NULL. */ + CBstatus = vmsvgaR3CmdBufSubmitCtx(pDevIns, pThis, pThisCC, &pCmdBuf); + else + CBstatus = vmsvgaR3CmdBufSubmitDC(pDevIns, pThisCC, &pCmdBuf, &offNextCmd); + } + else + { + ASSERT_GUEST_MSG_FAILED(("Failed to read commands at %RGp\n", GCPhysCmd)); + CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR; + fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER; + } + } + else + { + /* No memory for commands. */ + CBstatus = SVGA_CB_STATUS_QUEUE_FULL; + } + } + else + { + ASSERT_GUEST_MSG_FAILED(("Invalid buffer header\n")); + CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR; + fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER; + } + } + else + { + LogFunc(("Failed to read buffer header at %RGp\n", GCPhysCB)); + ASSERT_GUEST_FAILED(); + /* Do not attempt to write the status. */ + } + + /* Free the buffer if pfnCmdBufSubmit did not consume it. */ + vmsvgaR3CmdBufFree(pCmdBuf); + } + else + { + LogFunc(("Can't allocate buffer for context id %#x\n", CBCtx)); + AssertFailed(); + CBstatus = SVGA_CB_STATUS_QUEUE_FULL; + } + + if (CBstatus != SVGA_CB_STATUS_NONE) + { + LogFunc(("Write status %#x, offNextCmd %#x, fIRQ %#x\n", CBstatus, offNextCmd, fIRQ)); + vmsvgaR3CmdBufWriteStatus(pDevIns, GCPhysCB, CBstatus, offNextCmd); + if (fIRQ) + vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, fIRQ); + } +} + + +/** Checks if there are some buffers to be processed. + * + * @param pThisCC The VGA/VMSVGA state for the current context. + * @return true if buffers must be processed. + * @thread FIFO + */ +static bool vmsvgaR3CmdBufHasWork(PVGASTATECC pThisCC) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + return RT_BOOL(ASMAtomicReadU32(&pSvgaR3State->fCmdBuf)); +} + + +/** Processes a command buffer. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA state. + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param idDXContext VGPU10 DX context of the commands or SVGA3D_INVALID_ID if they are not for a specific context. + * @param pvCommands Pointer to the command buffer. + * @param cbCommands Size of the command buffer. + * @param poffNextCmd Where to store the offset of the first unprocessed command. + * @param pu32IrqStatus Where to store SVGA_IRQFLAG_ if the IRQ is generated by the last command in the buffer. + * @return SVGACBStatus code. + * @thread FIFO + */ +static SVGACBStatus vmsvgaR3CmdBufProcessCommands(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t idDXContext, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd, uint32_t *pu32IrqStatus) +{ +# ifndef VBOX_WITH_VMSVGA3D + RT_NOREF(idDXContext); +# endif + SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + +# ifdef VBOX_WITH_VMSVGA3D +# ifdef VMSVGA3D_DX + /* Commands submitted for the SVGA3D_INVALID_ID context do not affect pipeline. So ignore them. */ + if (idDXContext != SVGA3D_INVALID_ID) + { + if (pSvgaR3State->idDXContextCurrent != idDXContext) + { + LogFlow(("DXCTX: buffer %d->%d\n", pSvgaR3State->idDXContextCurrent, idDXContext)); + vmsvga3dDXSwitchContext(pThisCC, idDXContext); + pSvgaR3State->idDXContextCurrent = idDXContext; + } + } +# endif +# endif + + uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO; + + uint8_t const *pu8Cmd = (uint8_t *)pvCommands; + uint32_t cbRemain = cbCommands; + while (cbRemain) + { + /* Command identifier is a 32 bit value. */ + if (cbRemain < sizeof(uint32_t)) + { + CBstatus = SVGA_CB_STATUS_COMMAND_ERROR; + break; + } + + /* Fetch the command id. + * 'cmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler + * warning. Because we support some obsolete and deprecated commands, which are not included in + * the SVGAFifoCmdId enum in the VMSVGA headers anymore. + */ + uint32_t const cmdId = *(uint32_t *)pu8Cmd; + uint32_t cbCmd = sizeof(uint32_t); + + LogFunc(("[cid=%d] %s %d\n", (int32_t)idDXContext, vmsvgaR3FifoCmdToString(cmdId), cmdId)); +# ifdef LOG_ENABLED +# ifdef VBOX_WITH_VMSVGA3D + if (SVGA_3D_CMD_BASE <= cmdId && cmdId < SVGA_3D_CMD_MAX) + { + SVGA3dCmdHeader const *header = (SVGA3dCmdHeader *)pu8Cmd; + svga_dump_command(cmdId, (uint8_t *)&header[1], header->size); + } + else if (cmdId == SVGA_CMD_FENCE) + { + Log7(("\tSVGA_CMD_FENCE\n")); + Log7(("\t\t0x%08x\n", ((uint32_t *)pu8Cmd)[1])); + } +# endif +# endif + + /* At the end of the switch cbCmd is equal to the total length of the command including the cmdId. + * I.e. pu8Cmd + cbCmd must point to the next command. + * However if CBstatus is set to anything but SVGA_CB_STATUS_COMPLETED in the switch, then + * the cbCmd value is ignored (and pu8Cmd still points to the failed command). + */ + /** @todo This code is very similar to the FIFO loop command processing. Think about merging. */ + switch (cmdId) + { + case SVGA_CMD_INVALID_CMD: + { + /* Nothing to do. */ + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdInvalidCmd); + break; + } + + case SVGA_CMD_FENCE: + { + SVGAFifoCmdFence *pCmd = (SVGAFifoCmdFence *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdFence); + Log(("SVGA_CMD_FENCE %#x\n", pCmd->fence)); + + uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN]; + if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin)) + { + pFIFO[SVGA_FIFO_FENCE] = pCmd->fence; + + if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE) + { + Log(("any fence irq\n")); + *pu32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE; + } + else if ( VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin) + && (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL) + && pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmd->fence) + { + Log(("fence goal reached irq (fence=%#x)\n", pCmd->fence)); + *pu32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL; + } + } + else + Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin)); + break; + } + + case SVGA_CMD_UPDATE: + { + SVGAFifoCmdUpdate *pCmd = (SVGAFifoCmdUpdate *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_UPDATE_VERBOSE: + { + SVGAFifoCmdUpdateVerbose *pCmd = (SVGAFifoCmdUpdateVerbose *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DEFINE_CURSOR: + { + /* Followed by bitmap data. */ + SVGAFifoCmdDefineCursor *pCmd = (SVGAFifoCmdDefineCursor *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + + /* Figure out the size of the bitmap data. */ + ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); + ASSERT_GUEST_STMT_BREAK(pCmd->andMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); + ASSERT_GUEST_STMT_BREAK(pCmd->xorMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8; + uint32_t const cbAndMask = cbAndLine * pCmd->height; + uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8; + uint32_t const cbXorMask = cbXorLine * pCmd->height; + + VMSVGA_INC_CMD_SIZE_BREAK(cbAndMask + cbXorMask); + vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DEFINE_ALPHA_CURSOR: + { + /* Followed by bitmap data. */ + SVGAFifoCmdDefineAlphaCursor *pCmd = (SVGAFifoCmdDefineAlphaCursor *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + + /* Figure out the size of the bitmap data. */ + ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); + + VMSVGA_INC_CMD_SIZE_BREAK(pCmd->width * pCmd->height * sizeof(uint32_t)); /* 32-bit BRGA format */ + vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_MOVE_CURSOR: + { + /* Deprecated; there should be no driver which *requires* this command. However, if + * we do ecncounter this command, it might be useful to not get the FIFO completely out of + * alignment. + * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing. + */ + SVGAFifoCmdMoveCursor *pCmd = (SVGAFifoCmdMoveCursor *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DISPLAY_CURSOR: + { + /* Deprecated; there should be no driver which *requires* this command. However, if + * we do ecncounter this command, it might be useful to not get the FIFO completely out of + * alignment. + * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing. + */ + SVGAFifoCmdDisplayCursor *pCmd = (SVGAFifoCmdDisplayCursor *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_RECT_FILL: + { + SVGAFifoCmdRectFill *pCmd = (SVGAFifoCmdRectFill *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_RECT_COPY: + { + SVGAFifoCmdRectCopy *pCmd = (SVGAFifoCmdRectCopy *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_RECT_ROP_COPY: + { + SVGAFifoCmdRectRopCopy *pCmd = (SVGAFifoCmdRectRopCopy *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_ESCAPE: + { + /* Followed by 'size' bytes of data. */ + SVGAFifoCmdEscape *pCmd = (SVGAFifoCmdEscape *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + + ASSERT_GUEST_STMT_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); + RT_UNTRUSTED_VALIDATED_FENCE(); + + VMSVGA_INC_CMD_SIZE_BREAK(pCmd->size); + vmsvgaR3CmdEscape(pThis, pThisCC, pCmd); + break; + } +# ifdef VBOX_WITH_VMSVGA3D + case SVGA_CMD_DEFINE_GMR2: + { + SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_REMAP_GMR2: + { + /* Followed by page descriptors or guest ptr. */ + SVGAFifoCmdRemapGMR2 *pCmd = (SVGAFifoCmdRemapGMR2 *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + + /* Calculate the size of what comes after next and fetch it. */ + uint32_t cbMore = 0; + if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR) + cbMore = sizeof(SVGAGuestPtr); + else + { + uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t); + if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN) + { + cbMore = cbPageDesc; + pCmd->numPages = 1; + } + else + { + ASSERT_GUEST_STMT_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); + cbMore = cbPageDesc * pCmd->numPages; + } + } + VMSVGA_INC_CMD_SIZE_BREAK(cbMore); + vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd); +# ifdef DEBUG_GMR_ACCESS + VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId); +# endif + break; + } +# endif /* VBOX_WITH_VMSVGA3D */ + case SVGA_CMD_DEFINE_SCREEN: + { + /* The size of this command is specified by the guest and depends on capabilities. */ + SVGAFifoCmdDefineScreen *pCmd = (SVGAFifoCmdDefineScreen *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(pCmd->screen.structSize)); + ASSERT_GUEST_STMT_BREAK(pCmd->screen.structSize < pThis->svga.cbFIFO, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); + RT_UNTRUSTED_VALIDATED_FENCE(); + + VMSVGA_INC_CMD_SIZE_BREAK(RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize) - sizeof(pCmd->screen.structSize)); + vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DESTROY_SCREEN: + { + SVGAFifoCmdDestroyScreen *pCmd = (SVGAFifoCmdDestroyScreen *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DEFINE_GMRFB: + { + SVGAFifoCmdDefineGMRFB *pCmd = (SVGAFifoCmdDefineGMRFB *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_BLIT_GMRFB_TO_SCREEN: + { + SVGAFifoCmdBlitGMRFBToScreen *pCmd = (SVGAFifoCmdBlitGMRFBToScreen *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_BLIT_SCREEN_TO_GMRFB: + { + SVGAFifoCmdBlitScreenToGMRFB *pCmd = (SVGAFifoCmdBlitScreenToGMRFB *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_ANNOTATION_FILL: + { + SVGAFifoCmdAnnotationFill *pCmd = (SVGAFifoCmdAnnotationFill *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_ANNOTATION_COPY: + { + SVGAFifoCmdAnnotationCopy *pCmd = (SVGAFifoCmdAnnotationCopy *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd)); + vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd); + break; + } + + default: + { +# ifdef VBOX_WITH_VMSVGA3D + if ( cmdId >= SVGA_3D_CMD_BASE + && cmdId < SVGA_3D_CMD_MAX) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* All 3d commands start with a common header, which defines the identifier and the size + * of the command. The identifier has been already read. Fetch the size. + */ + uint32_t const *pcbMore = (uint32_t const *)&pu8Cmd[cbCmd]; + VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pcbMore)); + VMSVGA_INC_CMD_SIZE_BREAK(*pcbMore); + if (RT_LIKELY(pThis->svga.f3DEnabled)) + { /* likely */ } + else + { + LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", cmdId)); + break; + } + + /* Command data begins after the 32 bit command length. */ + int rc = vmsvgaR3Process3dCmd(pThis, pThisCC, idDXContext, (SVGAFifo3dCmdId)cmdId, *pcbMore, pcbMore + 1); + if (RT_SUCCESS(rc)) + { /* likely */ } + else + { + CBstatus = SVGA_CB_STATUS_COMMAND_ERROR; + break; + } + } + else +# endif /* VBOX_WITH_VMSVGA3D */ + { + /* Unsupported command. */ + STAM_REL_COUNTER_INC(&pSvgaR3State->StatFifoUnkCmds); + ASSERT_GUEST_MSG_FAILED(("cmdId=%d\n", cmdId)); + LogRelMax(16, ("VMSVGA: unsupported command %d\n", cmdId)); + CBstatus = SVGA_CB_STATUS_COMMAND_ERROR; + break; + } + } + } + + if (CBstatus != SVGA_CB_STATUS_COMPLETED) + break; + + pu8Cmd += cbCmd; + cbRemain -= cbCmd; + + /* If this is not the last command in the buffer, then generate IRQ, if required. + * This avoids a double call to vmsvgaR3CmdBufRaiseIRQ if FENCE is the last command + * in the buffer (usually the case). + */ + if (RT_LIKELY(!(cbRemain && *pu32IrqStatus))) + { /* likely */ } + else + { + vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, *pu32IrqStatus); + *pu32IrqStatus = 0; + } + } + + Assert(cbRemain <= cbCommands); + *poffNextCmd = cbCommands - cbRemain; + return CBstatus; +} + + +/** Process command buffers. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA state. + * @param pThisCC The VGA/VMSVGA state for the current context. + * @param pThread Handle of the FIFO thread. + * @thread FIFO + */ +static void vmsvgaR3CmdBufProcessBuffers(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PPDMTHREAD pThread) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + for (;;) + { + if (pThread->enmState != PDMTHREADSTATE_RUNNING) + break; + + /* See if there is a submitted buffer. */ + PVMSVGACMDBUF pCmdBuf = NULL; + + int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf); + AssertRC(rc); + + /* It seems that a higher queue index has a higher priority. + * See SVGACBContext in svga_reg.h from latest vmwgfx Linux driver. + */ + for (unsigned i = RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs); i > 0; --i) + { + PVMSVGACMDBUFCTX pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[i - 1]; + if (pCmdBufCtx) + { + pCmdBuf = RTListRemoveFirst(&pCmdBufCtx->listSubmitted, VMSVGACMDBUF, nodeBuffer); + if (pCmdBuf) + { + Assert(pCmdBufCtx->cSubmitted > 0); + --pCmdBufCtx->cSubmitted; + break; + } + } + } + + if (!pCmdBuf) + { + ASMAtomicWriteU32(&pSvgaR3State->fCmdBuf, 0); + RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf); + break; + } + + RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf); + + SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE; + uint32_t offNextCmd = 0; + uint32_t u32IrqStatus = 0; + uint32_t const idDXContext = RT_BOOL(pCmdBuf->hdr.flags & SVGA_CB_FLAG_DX_CONTEXT) + ? pCmdBuf->hdr.dxContext + : SVGA3D_INVALID_ID; + /* Process one buffer. */ + CBstatus = vmsvgaR3CmdBufProcessCommands(pDevIns, pThis, pThisCC, idDXContext, pCmdBuf->pvCommands, pCmdBuf->hdr.length, &offNextCmd, &u32IrqStatus); + + if (!RT_BOOL(pCmdBuf->hdr.flags & SVGA_CB_FLAG_NO_IRQ)) + u32IrqStatus |= SVGA_IRQFLAG_COMMAND_BUFFER; + if (CBstatus == SVGA_CB_STATUS_COMMAND_ERROR) + u32IrqStatus |= SVGA_IRQFLAG_ERROR; + + vmsvgaR3CmdBufWriteStatus(pDevIns, pCmdBuf->GCPhysCB, CBstatus, offNextCmd); + if (u32IrqStatus) + vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, u32IrqStatus); + + vmsvgaR3CmdBufFree(pCmdBuf); + } +} + + +/** + * Worker for vmsvgaR3FifoThread that handles an external command. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + */ +static void vmsvgaR3FifoHandleExtCmd(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + uint8_t uExtCmd = pThis->svga.u8FIFOExtCommand; + switch (pThis->svga.u8FIFOExtCommand) + { + case VMSVGA_FIFO_EXTCMD_RESET: + Log(("vmsvgaR3FifoLoop: reset the fifo thread.\n")); + Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL); + + vmsvgaR3ResetScreens(pThis, pThisCC); +# ifdef VBOX_WITH_VMSVGA3D + /* The 3d subsystem must be reset from the fifo thread. */ + if (pThis->svga.f3DEnabled) + vmsvga3dReset(pThisCC); +# endif + vmsvgaR3ResetSvgaState(pThis, pThisCC); + break; + + case VMSVGA_FIFO_EXTCMD_POWEROFF: + Log(("vmsvgaR3FifoLoop: power off.\n")); + Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL); + + /* The screens must be reset on the FIFO thread, because they may use 3D resources. */ + vmsvgaR3ResetScreens(pThis, pThisCC); + break; + + case VMSVGA_FIFO_EXTCMD_TERMINATE: + Log(("vmsvgaR3FifoLoop: terminate the fifo thread.\n")); + Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL); + +# ifdef VBOX_WITH_VMSVGA3D + /* The 3d subsystem must be shut down from the fifo thread. */ + if (pThis->svga.f3DEnabled) + vmsvga3dTerminate(pThisCC); +# endif + vmsvgaR3TerminateSvgaState(pThis, pThisCC); + break; + + case VMSVGA_FIFO_EXTCMD_SAVESTATE: + { + Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_SAVESTATE.\n")); + PSSMHANDLE pSSM = (PSSMHANDLE)pThisCC->svga.pvFIFOExtCmdParam; + AssertLogRelMsgBreak(RT_VALID_PTR(pSSM), ("pSSM=%p\n", pSSM)); + vmsvgaR3SaveExecFifo(pDevIns->pHlpR3, pThisCC, pSSM); +# ifdef VBOX_WITH_VMSVGA3D + if (pThis->svga.f3DEnabled) + { + if (vmsvga3dIsLegacyBackend(pThisCC)) + vmsvga3dSaveExec(pDevIns, pThisCC, pSSM); +# ifdef VMSVGA3D_DX + else + vmsvga3dDXSaveExec(pDevIns, pThisCC, pSSM); +# endif + } +# endif + break; + } + + case VMSVGA_FIFO_EXTCMD_LOADSTATE: + { + Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_LOADSTATE.\n")); + PVMSVGA_STATE_LOAD pLoadState = (PVMSVGA_STATE_LOAD)pThisCC->svga.pvFIFOExtCmdParam; + AssertLogRelMsgBreak(RT_VALID_PTR(pLoadState), ("pLoadState=%p\n", pLoadState)); + vmsvgaR3LoadExecFifo(pDevIns->pHlpR3, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass); +# ifdef VBOX_WITH_VMSVGA3D + if (pThis->svga.f3DEnabled) + { + /* The following RT_OS_DARWIN code was in vmsvga3dLoadExec and therefore must be executed before each vmsvga3dLoadExec invocation. */ +# ifndef RT_OS_DARWIN /** @todo r=bird: this is normally done on the EMT, so for DARWIN we do that when loading saved state too now. See DevVGA-SVGA.cpp */ + /* Must initialize now as the recreation calls below rely on an initialized 3d subsystem. */ + vmsvgaR3PowerOnDevice(pDevIns, pThis, pThisCC, /*fLoadState=*/ true); +# endif + + if (vmsvga3dIsLegacyBackend(pThisCC)) + vmsvga3dLoadExec(pDevIns, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass); +# ifdef VMSVGA3D_DX + else + vmsvga3dDXLoadExec(pDevIns, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass); +# endif + } +# endif + break; + } + + case VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS: + { +# ifdef VBOX_WITH_VMSVGA3D + uint32_t sid = (uint32_t)(uintptr_t)pThisCC->svga.pvFIFOExtCmdParam; + Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS sid=%#x\n", sid)); + vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, sid); +# endif + break; + } + + + default: + AssertLogRelMsgFailed(("uExtCmd=%#x pvFIFOExtCmdParam=%p\n", uExtCmd, pThisCC->svga.pvFIFOExtCmdParam)); + break; + } + + /* + * Signal the end of the external command. + */ + pThisCC->svga.pvFIFOExtCmdParam = NULL; + pThis->svga.u8FIFOExtCommand = VMSVGA_FIFO_EXTCMD_NONE; + ASMMemoryFence(); /* paranoia^2 */ + int rc = RTSemEventSignal(pThisCC->svga.hFIFOExtCmdSem); + AssertLogRelRC(rc); +} + +/** + * Worker for vmsvgaR3Destruct, vmsvgaR3Reset, vmsvgaR3Save and vmsvgaR3Load for + * doing a job on the FIFO thread (even when it's officially suspended). + * + * @returns VBox status code (fully asserted). + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param uExtCmd The command to execute on the FIFO thread. + * @param pvParam Pointer to command parameters. + * @param cMsWait The time to wait for the command, given in + * milliseconds. + */ +static int vmsvgaR3RunExtCmdOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + uint8_t uExtCmd, void *pvParam, RTMSINTERVAL cMsWait) +{ + Assert(cMsWait >= RT_MS_1SEC * 5); + AssertLogRelMsg(pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE, + ("old=%d new=%d\n", pThis->svga.u8FIFOExtCommand, uExtCmd)); + + int rc; + PPDMTHREAD pThread = pThisCC->svga.pFIFOIOThread; + PDMTHREADSTATE enmState = pThread->enmState; + if (enmState == PDMTHREADSTATE_SUSPENDED) + { + /* + * The thread is suspended, we have to temporarily wake it up so it can + * perform the task. + * (We ASSUME not racing code here, both wrt thread state and ext commands.) + */ + Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=SUSPENDED\n", uExtCmd)); + /* Post the request. */ + pThis->svga.fFifoExtCommandWakeup = true; + pThisCC->svga.pvFIFOExtCmdParam = pvParam; + pThis->svga.u8FIFOExtCommand = uExtCmd; + ASMMemoryFence(); /* paranoia^3 */ + + /* Resume the thread. */ + rc = PDMDevHlpThreadResume(pDevIns, pThread); + AssertLogRelRC(rc); + if (RT_SUCCESS(rc)) + { + /* Wait. Take care in case the semaphore was already posted (same as below). */ + rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait); + if ( rc == VINF_SUCCESS + && pThis->svga.u8FIFOExtCommand == uExtCmd) + rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait); + AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc), + ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc)); + + /* suspend the thread */ + pThis->svga.fFifoExtCommandWakeup = false; + int rc2 = PDMDevHlpThreadSuspend(pDevIns, pThread); + AssertLogRelRC(rc2); + if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) + rc = rc2; + } + pThis->svga.fFifoExtCommandWakeup = false; + pThisCC->svga.pvFIFOExtCmdParam = NULL; + } + else if (enmState == PDMTHREADSTATE_RUNNING) + { + /* + * The thread is running, should only happen during reset and vmsvga3dsfc. + * We ASSUME not racing code here, both wrt thread state and ext commands. + */ + Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=RUNNING\n", uExtCmd)); + Assert(uExtCmd == VMSVGA_FIFO_EXTCMD_RESET || uExtCmd == VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS || uExtCmd == VMSVGA_FIFO_EXTCMD_POWEROFF); + + /* Post the request. */ + pThisCC->svga.pvFIFOExtCmdParam = pvParam; + pThis->svga.u8FIFOExtCommand = uExtCmd; + ASMMemoryFence(); /* paranoia^2 */ + rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem); + AssertLogRelRC(rc); + + /* Wait. Take care in case the semaphore was already posted (same as above). */ + rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait); + if ( rc == VINF_SUCCESS + && pThis->svga.u8FIFOExtCommand == uExtCmd) + rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait); /* it was already posted, retry the wait. */ + AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc), + ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc)); + + pThisCC->svga.pvFIFOExtCmdParam = NULL; + } + else + { + /* + * Something is wrong with the thread! + */ + AssertLogRelMsgFailed(("uExtCmd=%d enmState=%d\n", uExtCmd, enmState)); + rc = VERR_INVALID_STATE; + } + return rc; +} + + +/** + * Marks the FIFO non-busy, notifying any waiting EMTs. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pSVGAState Pointer to the ring-3 only SVGA state data. + * @param offFifoMin The start byte offset of the command FIFO. + */ +static void vmsvgaR3FifoSetNotBusy(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, uint32_t offFifoMin) +{ + ASMAtomicAndU32(&pThis->svga.fBusy, ~(VMSVGA_BUSY_F_FIFO | VMSVGA_BUSY_F_EMT_FORCE)); + if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin)) + vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, pThis->svga.fBusy != 0); + + /* Wake up any waiting EMTs. */ + if (pSVGAState->cBusyDelayedEmts > 0) + { +# ifdef VMSVGA_USE_EMT_HALT_CODE + VMCPUID idCpu = VMCpuSetFindLastPresentInternal(&pSVGAState->BusyDelayedEmts); + if (idCpu != NIL_VMCPUID) + { + PDMDevHlpVMNotifyCpuDeviceReady(pDevIns, idCpu); + while (idCpu-- > 0) + if (VMCPUSET_IS_PRESENT(&pSVGAState->BusyDelayedEmts, idCpu)) + PDMDevHlpVMNotifyCpuDeviceReady(pDevIns, idCpu); + } +# else + int rc2 = RTSemEventMultiSignal(pSVGAState->hBusyDelayedEmts); + AssertRC(rc2); +# endif + } +} + +/** + * Reads (more) payload into the command buffer. + * + * @returns pbBounceBuf on success + * @retval (void *)1 if the thread was requested to stop. + * @retval NULL on FIFO error. + * + * @param cbPayloadReq The number of bytes of payload requested. + * @param pFIFO The FIFO. + * @param offCurrentCmd The FIFO byte offset of the current command. + * @param offFifoMin The start byte offset of the command FIFO. + * @param offFifoMax The end byte offset of the command FIFO. + * @param pbBounceBuf The bounch buffer. Same size as the entire FIFO, so + * always sufficient size. + * @param pcbAlreadyRead How much payload we've already read into the bounce + * buffer. (We will NEVER re-read anything.) + * @param pThread The calling PDM thread handle. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pSVGAState Pointer to the ring-3 only SVGA state data. For + * statistics collection. + * @param pDevIns The device instance. + */ +static void *vmsvgaR3FifoGetCmdPayload(uint32_t cbPayloadReq, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO, + uint32_t offCurrentCmd, uint32_t offFifoMin, uint32_t offFifoMax, + uint8_t *pbBounceBuf, uint32_t *pcbAlreadyRead, + PPDMTHREAD pThread, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, PPDMDEVINS pDevIns) +{ + Assert(pbBounceBuf); + Assert(pcbAlreadyRead); + Assert(offFifoMin < offFifoMax); + Assert(offCurrentCmd >= offFifoMin && offCurrentCmd < offFifoMax); + Assert(offFifoMax <= pThis->svga.cbFIFO); + + /* + * Check if the requested payload size has already been satisfied . + * . + * When called to read more, the caller is responsible for making sure the . + * new command size (cbRequsted) never is smaller than what has already . + * been read. + */ + uint32_t cbAlreadyRead = *pcbAlreadyRead; + if (cbPayloadReq <= cbAlreadyRead) + { + AssertLogRelReturn(cbPayloadReq == cbAlreadyRead, NULL); + return pbBounceBuf; + } + + /* + * Commands bigger than the fifo buffer are invalid. + */ + uint32_t const cbFifoCmd = offFifoMax - offFifoMin; + AssertMsgReturnStmt(cbPayloadReq <= cbFifoCmd, ("cbPayloadReq=%#x cbFifoCmd=%#x\n", cbPayloadReq, cbFifoCmd), + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors), + NULL); + + /* + * Move offCurrentCmd past the command dword. + */ + offCurrentCmd += sizeof(uint32_t); + if (offCurrentCmd >= offFifoMax) + offCurrentCmd = offFifoMin; + + /* + * Do we have sufficient payload data available already? + * The host should not read beyond [SVGA_FIFO_NEXT_CMD], therefore '>=' in the condition below. + */ + uint32_t cbAfter, cbBefore; + uint32_t offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD]; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + if (offNextCmd >= offCurrentCmd) + { + if (RT_LIKELY(offNextCmd < offFifoMax)) + cbAfter = offNextCmd - offCurrentCmd; + else + { + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors); + LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n", + offNextCmd, offFifoMin, offFifoMax)); + cbAfter = offFifoMax - offCurrentCmd; + } + cbBefore = 0; + } + else + { + cbAfter = offFifoMax - offCurrentCmd; + if (offNextCmd >= offFifoMin) + cbBefore = offNextCmd - offFifoMin; + else + { + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors); + LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n", + offNextCmd, offFifoMin, offFifoMax)); + cbBefore = 0; + } + } + if (cbAfter + cbBefore < cbPayloadReq) + { + /* + * Insufficient, must wait for it to arrive. + */ +/** @todo Should clear the busy flag here to maybe encourage the guest to wake us up. */ + STAM_REL_PROFILE_START(&pSVGAState->StatFifoStalls, Stall); + for (uint32_t i = 0;; i++) + { + if (pThread->enmState != PDMTHREADSTATE_RUNNING) + { + STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall); + return (void *)(uintptr_t)1; + } + Log(("Guest still copying (%x vs %x) current %x next %x stop %x loop %u; sleep a bit\n", + cbPayloadReq, cbAfter + cbBefore, offCurrentCmd, offNextCmd, pFIFO[SVGA_FIFO_STOP], i)); + + PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, i < 16 ? 1 : 2); + + offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD]; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + if (offNextCmd >= offCurrentCmd) + { + cbAfter = RT_MIN(offNextCmd, offFifoMax) - offCurrentCmd; + cbBefore = 0; + } + else + { + cbAfter = offFifoMax - offCurrentCmd; + cbBefore = RT_MAX(offNextCmd, offFifoMin) - offFifoMin; + } + + if (cbAfter + cbBefore >= cbPayloadReq) + break; + } + STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall); + } + + /* + * Copy out the memory and update what pcbAlreadyRead points to. + */ + if (cbAfter >= cbPayloadReq) + memcpy(pbBounceBuf + cbAlreadyRead, + (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead, + cbPayloadReq - cbAlreadyRead); + else + { + LogFlow(("Split data buffer at %x (%u-%u)\n", offCurrentCmd, cbAfter, cbBefore)); + if (cbAlreadyRead < cbAfter) + { + memcpy(pbBounceBuf + cbAlreadyRead, + (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead, + cbAfter - cbAlreadyRead); + cbAlreadyRead = cbAfter; + } + memcpy(pbBounceBuf + cbAlreadyRead, + (uint8_t *)pFIFO + offFifoMin + cbAlreadyRead - cbAfter, + cbPayloadReq - cbAlreadyRead); + } + *pcbAlreadyRead = cbPayloadReq; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + return pbBounceBuf; +} + + +/** + * Sends cursor position and visibility information from the FIFO to the front-end. + * @returns SVGA_FIFO_CURSOR_COUNT value used. + */ +static uint32_t +vmsvgaR3FifoUpdateCursor(PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO, + uint32_t offFifoMin, uint32_t uCursorUpdateCount, + uint32_t *pxLast, uint32_t *pyLast, uint32_t *pfLastVisible) +{ + /* + * Check if the cursor update counter has changed and try get a stable + * set of values if it has. This is race-prone, especially consindering + * the screen ID, but little we can do about that. + */ + uint32_t x, y, fVisible, idScreen; + for (uint32_t i = 0; ; i++) + { + x = pFIFO[SVGA_FIFO_CURSOR_X]; + y = pFIFO[SVGA_FIFO_CURSOR_Y]; + fVisible = pFIFO[SVGA_FIFO_CURSOR_ON]; + idScreen = VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_SCREEN_ID, offFifoMin) + ? pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID] : SVGA_ID_INVALID; + if ( uCursorUpdateCount == pFIFO[SVGA_FIFO_CURSOR_COUNT] + || i > 3) + break; + if (i == 0) + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorFetchAgain); + ASMNopPause(); + uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT]; + } + + /* + * Check if anything has changed, as calling into pDrv is not light-weight. + */ + if ( *pxLast == x + && *pyLast == y + && (idScreen != SVGA_ID_INVALID || *pfLastVisible == fVisible)) + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorNoChange); + else + { + /* + * Detected changes. + * + * We handle global, not per-screen visibility information by sending + * pfnVBVAMousePointerShape without shape data. + */ + *pxLast = x; + *pyLast = y; + uint32_t fFlags = VBVA_CURSOR_VALID_DATA; + if (idScreen != SVGA_ID_INVALID) + fFlags |= VBVA_CURSOR_SCREEN_RELATIVE; + else if (*pfLastVisible != fVisible) + { + LogRel2(("vmsvgaR3FifoUpdateCursor: fVisible %d fLastVisible %d (%d,%d)\n", fVisible, *pfLastVisible, x, y)); + *pfLastVisible = fVisible; + pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(fVisible), false, 0, 0, 0, 0, NULL); + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorVisiblity); + } + pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y); + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorPosition); + } + + /* + * Update done. Signal this to the guest. + */ + pFIFO[SVGA_FIFO_CURSOR_LAST_UPDATED] = uCursorUpdateCount; + + return uCursorUpdateCount; +} + + +/** + * Checks if there is work to be done, either cursor updating or FIFO commands. + * + * @returns true if pending work, false if not. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param uLastCursorCount The last cursor update counter value. + */ +DECLINLINE(bool) vmsvgaR3FifoHasWork(PVGASTATECC pThisCC, uint32_t uLastCursorCount) +{ + /* If FIFO does not exist than there is nothing to do. Command buffers also require the enabled FIFO. */ + uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO; + AssertReturn(pFIFO, false); + + if (vmsvgaR3CmdBufHasWork(pThisCC)) + return true; + + if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP]) + return true; + + if ( uLastCursorCount != pFIFO[SVGA_FIFO_CURSOR_COUNT] + && VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, pFIFO[SVGA_FIFO_MIN])) + return true; + + return false; +} + + +/** + * Called by the VGA refresh timer to wake up the FIFO thread when needed. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + */ +void vmsvgaR3FifoWatchdogTimer(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + /* Caller already checked pThis->svga.fFIFOThreadSleeping, so we only have + to recheck it before doing the signalling. */ + if ( vmsvgaR3FifoHasWork(pThisCC, ASMAtomicReadU32(&pThis->svga.uLastCursorUpdateCount)) + && pThis->svga.fFIFOThreadSleeping + && !ASMAtomicReadBool(&pThis->svga.fBadGuest)) + { + int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem); + AssertRC(rc); + STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoWatchdogWakeUps); + } +} + + +/** + * Called by the FIFO thread to process pending actions. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + */ +void vmsvgaR3FifoPendingActions(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + RT_NOREF(pDevIns); + + /* Currently just mode changes. */ + if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT)) + { + vmsvgaR3ChangeMode(pThis, pThisCC); +# ifdef VBOX_WITH_VMSVGA3D + if (pThisCC->svga.p3dState != NULL) + vmsvga3dChangeMode(pThisCC); +# endif + } +} + + +/* + * These two macros are put outside vmsvgaR3FifoLoop because doxygen gets confused, + * even the latest version, and thinks we're documenting vmsvgaR3FifoLoop. Sigh. + */ +/** @def VMSVGAFIFO_GET_CMD_BUFFER_BREAK + * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload. + * + * Will break out of the switch on failure. + * Will restart and quit the loop if the thread was requested to stop. + * + * @param a_PtrVar Request variable pointer. + * @param a_Type Request typedef (not pointer) for casting. + * @param a_cbPayloadReq How much payload to fetch. + * @remarks Accesses a bunch of variables in the current scope! + */ +# define VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \ + if (1) { \ + (a_PtrVar) = (a_Type *)vmsvgaR3FifoGetCmdPayload((a_cbPayloadReq), pFIFO, offCurrentCmd, offFifoMin, offFifoMax, \ + pbBounceBuf, &cbPayload, pThread, pThis, pSVGAState, pDevIns); \ + if (RT_UNLIKELY((uintptr_t)(a_PtrVar) < 2)) { if ((uintptr_t)(a_PtrVar) == 1) continue; break; } \ + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \ + } else do {} while (0) +/* @def VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK + * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload for refetching the + * buffer after figuring out the actual command size. + * + * Will break out of the switch on failure. + * + * @param a_PtrVar Request variable pointer. + * @param a_Type Request typedef (not pointer) for casting. + * @param a_cbPayloadReq How much payload to fetch. + * @remarks Accesses a bunch of variables in the current scope! + */ +# define VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \ + if (1) { \ + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq); \ + } else do {} while (0) + +/** + * @callback_method_impl{PFNPDMTHREADDEV, The async FIFO handling thread.} + */ +static DECLCALLBACK(int) vmsvgaR3FifoLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + int rc; + + if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) + return VINF_SUCCESS; + + /* + * Special mode where we only execute an external command and the go back + * to being suspended. Currently, all ext cmds ends up here, with the reset + * one also being eligble for runtime execution further down as well. + */ + if (pThis->svga.fFifoExtCommandWakeup) + { + vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC); + while (pThread->enmState == PDMTHREADSTATE_RUNNING) + if (pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE) + PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, RT_MS_1MIN); + else + vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC); + return VINF_SUCCESS; + } + + + /* + * Signal the semaphore to make sure we don't wait for 250ms after a + * suspend & resume scenario (see vmsvgaR3FifoGetCmdPayload). + */ + PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem); + + /* + * Allocate a bounce buffer for command we get from the FIFO. + * (All code must return via the end of the function to free this buffer.) + */ + uint8_t *pbBounceBuf = (uint8_t *)RTMemAllocZ(pThis->svga.cbFIFO); + AssertReturn(pbBounceBuf, VERR_NO_MEMORY); + + /* + * Polling/sleep interval config. + * + * We wait for an a short interval if the guest has recently given us work + * to do, but the interval increases the longer we're kept idle. Once we've + * reached the refresh timer interval, we'll switch to extended waits, + * depending on it or the guest to kick us into action when needed. + * + * Should the refresh time go fishing, we'll just continue increasing the + * sleep length till we reaches the 250 ms max after about 16 seconds. + */ + RTMSINTERVAL const cMsMinSleep = 16; + RTMSINTERVAL const cMsIncSleep = 2; + RTMSINTERVAL const cMsMaxSleep = 250; + RTMSINTERVAL const cMsExtendedSleep = 15 * RT_MS_1SEC; /* Regular paranoia dictates that this cannot be indefinite. */ + RTMSINTERVAL cMsSleep = cMsMaxSleep; + + /* + * Cursor update state (SVGA_FIFO_CAP_CURSOR_BYPASS_3). + * + * Initialize with values that will detect an update from the guest. + * Make sure that if the guest never updates the cursor position, then the device does not report it. + * The guest has to change the value of uLastCursorUpdateCount, when the cursor position is actually updated. + * xLastCursor, yLastCursor and fLastCursorVisible are set to report the first update. + */ + uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO; + pThis->svga.uLastCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT]; + uint32_t xLastCursor = ~pFIFO[SVGA_FIFO_CURSOR_X]; + uint32_t yLastCursor = ~pFIFO[SVGA_FIFO_CURSOR_Y]; + uint32_t fLastCursorVisible = ~pFIFO[SVGA_FIFO_CURSOR_ON]; + + /* + * The FIFO loop. + */ + LogFlow(("vmsvgaR3FifoLoop: started loop\n")); + bool fBadOrDisabledFifo = ASMAtomicReadBool(&pThis->svga.fBadGuest); + while (pThread->enmState == PDMTHREADSTATE_RUNNING) + { +# if defined(RT_OS_DARWIN) && defined(VBOX_WITH_VMSVGA3D) + /* + * Should service the run loop every so often. + */ + if (pThis->svga.f3DEnabled) + vmsvga3dCocoaServiceRunLoop(); +# endif + + /* First check any pending actions. */ + vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC); + + /* + * Unless there's already work pending, go to sleep for a short while. + * (See polling/sleep interval config above.) + */ + if ( fBadOrDisabledFifo + || !vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount)) + { + ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, true); + Assert(pThis->cMilliesRefreshInterval > 0); + if (cMsSleep < pThis->cMilliesRefreshInterval) + rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsSleep); + else + { +# ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER + int rc2 = PDMDevHlpPGMHandlerPhysicalReset(pDevIns, pThis->svga.GCPhysFIFO); + AssertRC(rc2); /* No break. Racing EMTs unmapping and remapping the region. */ +# endif + if ( !fBadOrDisabledFifo + && vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount)) + rc = VINF_SUCCESS; + else + { + STAM_REL_PROFILE_START(&pSVGAState->StatFifoExtendedSleep, Acc); + rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsExtendedSleep); + STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoExtendedSleep, Acc); + } + } + ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, false); + AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED); + if (pThread->enmState != PDMTHREADSTATE_RUNNING) + { + LogFlow(("vmsvgaR3FifoLoop: thread state %x\n", pThread->enmState)); + break; + } + } + else + rc = VINF_SUCCESS; + fBadOrDisabledFifo = ASMAtomicReadBool(&pThis->svga.fBadGuest); + if (rc == VERR_TIMEOUT) + { + if (!vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount)) + { + cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep); + continue; + } + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoTimeout); + + Log(("vmsvgaR3FifoLoop: timeout\n")); + } + else if (vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount)) + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken); + cMsSleep = cMsMinSleep; + + Log(("vmsvgaR3FifoLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY])); + Log(("vmsvgaR3FifoLoop: min %x max %x\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX])); + Log(("vmsvgaR3FifoLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP])); + + /* + * Handle external commands (currently only reset). + */ + if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE) + { + vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC); + continue; + } + + /* + * If guest misbehaves, then do nothing. + */ + if (ASMAtomicReadBool(&pThis->svga.fBadGuest)) + { + vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, pFIFO[SVGA_FIFO_MIN]); + cMsSleep = cMsExtendedSleep; + LogRelMax(1, ("VMSVGA: FIFO processing stopped because of the guest misbehavior\n")); + continue; + } + + /* + * The device must be enabled and configured. + */ + if ( !pThis->svga.fEnabled + || !pThis->svga.fConfigured) + { + vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, pFIFO[SVGA_FIFO_MIN]); + fBadOrDisabledFifo = true; + cMsSleep = cMsMaxSleep; /* cheat */ + continue; + } + + /* + * Get and check the min/max values. We ASSUME that they will remain + * unchanged while we process requests. A further ASSUMPTION is that + * the guest won't mess with SVGA_FIFO_NEXT_CMD while we're busy, so + * we don't read it back while in the loop. + */ + uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN]; + uint32_t const offFifoMax = pFIFO[SVGA_FIFO_MAX]; + uint32_t offCurrentCmd = pFIFO[SVGA_FIFO_STOP]; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + if (RT_UNLIKELY( !VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_STOP, offFifoMin) + || offFifoMax <= offFifoMin + || offFifoMax > pThis->svga.cbFIFO + || (offFifoMax & 3) != 0 + || (offFifoMin & 3) != 0 + || offCurrentCmd < offFifoMin + || offCurrentCmd > offFifoMax)) + { + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors); + LogRelMax(8, ("vmsvgaR3FifoLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax)); + vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin); + fBadOrDisabledFifo = true; + continue; + } + RT_UNTRUSTED_VALIDATED_FENCE(); + if (RT_UNLIKELY(offCurrentCmd & 3)) + { + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors); + LogRelMax(8, ("vmsvgaR3FifoLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd)); + offCurrentCmd &= ~UINT32_C(3); + } + + /* + * Update the cursor position before we start on the FIFO commands. + */ + /** @todo do we need to check whether the guest disabled the SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability here? */ + if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, offFifoMin)) + { + uint32_t const uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT]; + if (uCursorUpdateCount == pThis->svga.uLastCursorUpdateCount) + { /* halfways likely */ } + else + { + uint32_t const uNewCount = vmsvgaR3FifoUpdateCursor(pThisCC, pSVGAState, pFIFO, offFifoMin, uCursorUpdateCount, + &xLastCursor, &yLastCursor, &fLastCursorVisible); + ASMAtomicWriteU32(&pThis->svga.uLastCursorUpdateCount, uNewCount); + } + } + + /* + * Mark the FIFO as busy. + */ + ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO); // Clears VMSVGA_BUSY_F_EMT_FORCE! + if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin)) + ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_BUSY], true); + + /* + * Process all submitted command buffers. + */ + vmsvgaR3CmdBufProcessBuffers(pDevIns, pThis, pThisCC, pThread); + + /* + * Execute all queued FIFO commands. + * Quit if pending external command or changes in the thread state. + */ + bool fDone = false; + while ( !(fDone = (pFIFO[SVGA_FIFO_NEXT_CMD] == offCurrentCmd)) + && pThread->enmState == PDMTHREADSTATE_RUNNING) + { + uint32_t cbPayload = 0; + uint32_t u32IrqStatus = 0; + + Assert(offCurrentCmd < offFifoMax && offCurrentCmd >= offFifoMin); + + /* First check any pending actions. */ + vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC); + + /* Check for pending external commands (reset). */ + if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE) + break; + + /* + * Process the command. + */ + /* 'enmCmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler + * warning. Because we implement some obsolete and deprecated commands, which are not included in + * the SVGAFifoCmdId enum in the VMSVGA headers anymore. + */ + uint32_t const enmCmdId = pFIFO[offCurrentCmd / sizeof(uint32_t)]; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + LogFlow(("vmsvgaR3FifoLoop: FIFO command (iCmd=0x%x) %s %d\n", + offCurrentCmd / sizeof(uint32_t), vmsvgaR3FifoCmdToString(enmCmdId), enmCmdId)); + switch (enmCmdId) + { + case SVGA_CMD_INVALID_CMD: + /* Nothing to do. */ + STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdInvalidCmd); + break; + + case SVGA_CMD_FENCE: + { + SVGAFifoCmdFence *pCmdFence; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmdFence, SVGAFifoCmdFence, sizeof(*pCmdFence)); + STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdFence); + if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin)) + { + Log(("vmsvgaR3FifoLoop: SVGA_CMD_FENCE %#x\n", pCmdFence->fence)); + pFIFO[SVGA_FIFO_FENCE] = pCmdFence->fence; + + if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE) + { + Log(("vmsvgaR3FifoLoop: any fence irq\n")); + u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE; + } + else + if ( VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin) + && (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL) + && pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmdFence->fence) + { + Log(("vmsvgaR3FifoLoop: fence goal reached irq (fence=%#x)\n", pCmdFence->fence)); + u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL; + } + } + else + Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin)); + break; + } + + case SVGA_CMD_UPDATE: + { + SVGAFifoCmdUpdate *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdate, sizeof(*pCmd)); + vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_UPDATE_VERBOSE: + { + SVGAFifoCmdUpdateVerbose *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdateVerbose, sizeof(*pCmd)); + vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DEFINE_CURSOR: + { + /* Followed by bitmap data. */ + SVGAFifoCmdDefineCursor *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, sizeof(*pCmd)); + + /* Figure out the size of the bitmap data. */ + ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048); + ASSERT_GUEST_BREAK(pCmd->andMaskDepth <= 32); + ASSERT_GUEST_BREAK(pCmd->xorMaskDepth <= 32); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8; + uint32_t const cbAndMask = cbAndLine * pCmd->height; + uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8; + uint32_t const cbXorMask = cbXorLine * pCmd->height; + + uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineCursor) + cbAndMask + cbXorMask; + VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, cbCmd); + vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DEFINE_ALPHA_CURSOR: + { + /* Followed by bitmap data. */ + SVGAFifoCmdDefineAlphaCursor *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, sizeof(*pCmd)); + + /* Figure out the size of the bitmap data. */ + ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048); + + uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineAlphaCursor) + pCmd->width * pCmd->height * sizeof(uint32_t) /* 32-bit BRGA format */; + VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, cbCmd); + vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_MOVE_CURSOR: + { + /* Deprecated; there should be no driver which *requires* this command. However, if + * we do ecncounter this command, it might be useful to not get the FIFO completely out of + * alignment. + * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing. + */ + SVGAFifoCmdMoveCursor *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdMoveCursor, sizeof(*pCmd)); + vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DISPLAY_CURSOR: + { + /* Deprecated; there should be no driver which *requires* this command. However, if + * we do ecncounter this command, it might be useful to not get the FIFO completely out of + * alignment. + * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing. + */ + SVGAFifoCmdDisplayCursor *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDisplayCursor, sizeof(*pCmd)); + vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_RECT_FILL: + { + SVGAFifoCmdRectFill *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectFill, sizeof(*pCmd)); + vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_RECT_COPY: + { + SVGAFifoCmdRectCopy *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectCopy, sizeof(*pCmd)); + vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_RECT_ROP_COPY: + { + SVGAFifoCmdRectRopCopy *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectRopCopy, sizeof(*pCmd)); + vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_ESCAPE: + { + /* Followed by 'size' bytes of data. */ + SVGAFifoCmdEscape *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, sizeof(*pCmd)); + + ASSERT_GUEST_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape)); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const cbCmd = sizeof(SVGAFifoCmdEscape) + pCmd->size; + VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, cbCmd); + vmsvgaR3CmdEscape(pThis, pThisCC, pCmd); + break; + } +# ifdef VBOX_WITH_VMSVGA3D + case SVGA_CMD_DEFINE_GMR2: + { + SVGAFifoCmdDefineGMR2 *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMR2, sizeof(*pCmd)); + vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_REMAP_GMR2: + { + /* Followed by page descriptors or guest ptr. */ + SVGAFifoCmdRemapGMR2 *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, sizeof(*pCmd)); + + /* Calculate the size of what comes after next and fetch it. */ + uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2); + if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR) + cbCmd += sizeof(SVGAGuestPtr); + else + { + uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t); + if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN) + { + cbCmd += cbPageDesc; + pCmd->numPages = 1; + } + else + { + ASSERT_GUEST_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc); + cbCmd += cbPageDesc * pCmd->numPages; + } + } + VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd); + vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd); +# ifdef DEBUG_GMR_ACCESS + VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId); +# endif + break; + } +# endif // VBOX_WITH_VMSVGA3D + case SVGA_CMD_DEFINE_SCREEN: + { + /* The size of this command is specified by the guest and depends on capabilities. */ + Assert(pFIFO[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT_2); + + SVGAFifoCmdDefineScreen *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize)); + AssertBreak(pCmd->screen.structSize < pThis->svga.cbFIFO); + RT_UNTRUSTED_VALIDATED_FENCE(); + + RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.id)); + VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize)); + vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DESTROY_SCREEN: + { + SVGAFifoCmdDestroyScreen *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDestroyScreen, sizeof(*pCmd)); + vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_DEFINE_GMRFB: + { + SVGAFifoCmdDefineGMRFB *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMRFB, sizeof(*pCmd)); + vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_BLIT_GMRFB_TO_SCREEN: + { + SVGAFifoCmdBlitGMRFBToScreen *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitGMRFBToScreen, sizeof(*pCmd)); + vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_BLIT_SCREEN_TO_GMRFB: + { + SVGAFifoCmdBlitScreenToGMRFB *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitScreenToGMRFB, sizeof(*pCmd)); + vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_ANNOTATION_FILL: + { + SVGAFifoCmdAnnotationFill *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationFill, sizeof(*pCmd)); + vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd); + break; + } + + case SVGA_CMD_ANNOTATION_COPY: + { + SVGAFifoCmdAnnotationCopy *pCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationCopy, sizeof(*pCmd)); + vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd); + break; + } + + default: +# ifdef VBOX_WITH_VMSVGA3D + if ( (int)enmCmdId >= SVGA_3D_CMD_BASE + && (int)enmCmdId < SVGA_3D_CMD_MAX) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* All 3d commands start with a common header, which defines the identifier and the size + * of the command. The identifier has been already read from FIFO. Fetch the size. + */ + uint32_t *pcbCmd; + VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pcbCmd, uint32_t, sizeof(*pcbCmd)); + uint32_t const cbCmd = *pcbCmd; + AssertBreak(cbCmd < pThis->svga.cbFIFO); + uint32_t *pu32Cmd; + VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pu32Cmd, uint32_t, sizeof(*pcbCmd) + cbCmd); + pu32Cmd++; /* Skip the command size. */ + + if (RT_LIKELY(pThis->svga.f3DEnabled)) + { /* likely */ } + else + { + LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", enmCmdId)); + break; + } + + vmsvgaR3Process3dCmd(pThis, pThisCC, SVGA3D_INVALID_ID, (SVGAFifo3dCmdId)enmCmdId, cbCmd, pu32Cmd); + } + else +# endif // VBOX_WITH_VMSVGA3D + { + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds); + AssertMsgFailed(("enmCmdId=%d\n", enmCmdId)); + LogRelMax(16, ("VMSVGA: unsupported command %d\n", enmCmdId)); + } + } + + /* Go to the next slot */ + Assert(cbPayload + sizeof(uint32_t) <= offFifoMax - offFifoMin); + offCurrentCmd += RT_ALIGN_32(cbPayload + sizeof(uint32_t), sizeof(uint32_t)); + if (offCurrentCmd >= offFifoMax) + { + offCurrentCmd -= offFifoMax - offFifoMin; + Assert(offCurrentCmd >= offFifoMin); + Assert(offCurrentCmd < offFifoMax); + } + ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], offCurrentCmd); + STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCommands); + + /* + * Raise IRQ if required. Must enter the critical section here + * before making final decisions here, otherwise cubebench and + * others may end up waiting forever. + */ + if ( u32IrqStatus + || (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)) + { + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + + /* FIFO progress might trigger an interrupt. */ + if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS) + { + Log(("vmsvgaR3FifoLoop: fifo progress irq\n")); + u32IrqStatus |= SVGA_IRQFLAG_FIFO_PROGRESS; + } + + /* Unmasked IRQ pending? */ + if (pThis->svga.u32IrqMask & u32IrqStatus) + { + Log(("vmsvgaR3FifoLoop: Trigger interrupt with status %x\n", u32IrqStatus)); + ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus); + PDMDevHlpPCISetIrq(pDevIns, 0, 1); + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + } + } + + /* If really done, clear the busy flag. */ + if (fDone) + { + Log(("vmsvgaR3FifoLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], offCurrentCmd)); + vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin); + } + } + + /* + * Free the bounce buffer. (There are no returns above!) + */ + RTMemFree(pbBounceBuf); + + return VINF_SUCCESS; +} + +#undef VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK +#undef VMSVGAFIFO_GET_CMD_BUFFER_BREAK + +/** + * @callback_method_impl{PFNPDMTHREADWAKEUPDEV, + * Unblock the FIFO I/O thread so it can respond to a state change.} + */ +static DECLCALLBACK(int) vmsvgaR3FifoLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread) +{ + RT_NOREF(pDevIns); + PVGASTATE pThis = (PVGASTATE)pThread->pvUser; + Log(("vmsvgaR3FifoLoopWakeUp\n")); + return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem); +} + +/** + * Enables or disables dirty page tracking for the framebuffer + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA instance data. + * @param fTraces Enable/disable traces + */ +static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces) +{ + if ( (!pThis->svga.fConfigured || !pThis->svga.fEnabled) + && !fTraces) + { + //Assert(pThis->svga.fTraces); + Log(("vmsvgaR3SetTraces: *not* allowed to disable dirty page tracking when the device is in legacy mode.\n")); + return; + } + + pThis->svga.fTraces = fTraces; + if (pThis->svga.fTraces) + { + unsigned cbFrameBuffer = pThis->vram_size; + + Log(("vmsvgaR3SetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0)); + /** @todo How does this work with screens? */ + if (pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED) + { +# ifndef DEBUG_bird /* BB-10.3.1 triggers this as it initializes everything to zero. Better just ignore it. */ + Assert(pThis->svga.cbScanline); +# endif + /* Hardware enabled; return real framebuffer size .*/ + cbFrameBuffer = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline; + cbFrameBuffer = RT_ALIGN(cbFrameBuffer, GUEST_PAGE_SIZE); + } + + if (!pThis->svga.fVRAMTracking) + { + Log(("vmsvgaR3SetTraces: enable frame buffer dirty page tracking. (%x bytes; vram %x)\n", cbFrameBuffer, pThis->vram_size)); + vgaR3RegisterVRAMHandler(pDevIns, pThis, cbFrameBuffer); + pThis->svga.fVRAMTracking = true; + } + } + else + { + if (pThis->svga.fVRAMTracking) + { + Log(("vmsvgaR3SetTraces: disable frame buffer dirty page tracking\n")); + vgaR3UnregisterVRAMHandler(pDevIns, pThis); + pThis->svga.fVRAMTracking = false; + } + } +} + +/** + * @callback_method_impl{FNPCIIOREGIONMAP} + */ +DECLCALLBACK(int) vmsvgaR3PciIORegionFifoMapUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, + RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + int rc; + RT_NOREF(pPciDev); + Assert(pPciDev == pDevIns->apPciDevs[0]); + + Log(("vmsvgaR3PciIORegionFifoMapUnmap: iRegion=%d GCPhysAddress=%RGp cb=%RGp enmType=%d\n", iRegion, GCPhysAddress, cb, enmType)); + AssertReturn( iRegion == pThis->pciRegions.iFIFO + && ( enmType == PCI_ADDRESS_SPACE_MEM + || (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH /* got wrong in 6.1.0RC1 */ && pThis->fStateLoaded)) + , VERR_INTERNAL_ERROR); + if (GCPhysAddress != NIL_RTGCPHYS) + { + /* + * Mapping the FIFO RAM. + */ + AssertLogRelMsg(cb == pThis->svga.cbFIFO, ("cb=%#RGp cbFIFO=%#x\n", cb, pThis->svga.cbFIFO)); + rc = PDMDevHlpMmio2Map(pDevIns, pThis->hMmio2VmSvgaFifo, GCPhysAddress); + AssertRC(rc); + +# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS) + if (RT_SUCCESS(rc)) + { + rc = PDMDevHlpPGMHandlerPhysicalRegister(pDevIns, GCPhysAddress, +# ifdef DEBUG_FIFO_ACCESS + GCPhysAddress + (pThis->svga.cbFIFO - 1), +# else + GCPhysAddress + GUEST_PAGE_SIZE - 1, +# endif + pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR, + "VMSVGA FIFO"); + AssertRC(rc); + } +# endif + if (RT_SUCCESS(rc)) + { + pThis->svga.GCPhysFIFO = GCPhysAddress; + Log(("vmsvgaR3IORegionMap: GCPhysFIFO=%RGp cbFIFO=%#x\n", GCPhysAddress, pThis->svga.cbFIFO)); + } + rc = VINF_PCI_MAPPING_DONE; /* caller only cares about this status, so it is okay that we overwrite errors here. */ + } + else + { + Assert(pThis->svga.GCPhysFIFO); +# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS) + rc = PDMDevHlpPGMHandlerPhysicalDeregister(pDevIns, pThis->svga.GCPhysFIFO); + AssertRC(rc); +# else + rc = VINF_SUCCESS; +# endif + pThis->svga.GCPhysFIFO = 0; + } + return rc; +} + +# ifdef VBOX_WITH_VMSVGA3D + +/** + * Used by vmsvga3dInfoSurfaceWorker to make the FIFO thread to save one or all + * surfaces to VMSVGA3DMIPMAPLEVEL::pSurfaceData heap buffers. + * + * @param pDevIns The device instance. + * @param pThis The The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param sid Either UINT32_MAX or the ID of a specific surface. If + * UINT32_MAX is used, all surfaces are processed. + */ +void vmsvgaR33dSurfaceUpdateHeapBuffersOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid) +{ + vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS, (void *)(uintptr_t)sid, + sid == UINT32_MAX ? 10 * RT_MS_1SEC : RT_MS_1MIN); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsfc"} + */ +DECLCALLBACK(void) vmsvgaR3Info3dSurface(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + /* There might be a specific surface ID at the start of the + arguments, if not show all surfaces. */ + uint32_t sid = UINT32_MAX; + if (pszArgs) + pszArgs = RTStrStripL(pszArgs); + if (pszArgs && RT_C_IS_DIGIT(*pszArgs)) + sid = RTStrToUInt32(pszArgs); + + /* Verbose or terse display, we default to verbose. */ + bool fVerbose = true; + if (RTStrIStr(pszArgs, "terse")) + fVerbose = false; + + /* The size of the ascii art (x direction, y is 3/4 of x). */ + uint32_t cxAscii = 80; + if (RTStrIStr(pszArgs, "gigantic")) + cxAscii = 300; + else if (RTStrIStr(pszArgs, "huge")) + cxAscii = 180; + else if (RTStrIStr(pszArgs, "big")) + cxAscii = 132; + else if (RTStrIStr(pszArgs, "normal")) + cxAscii = 80; + else if (RTStrIStr(pszArgs, "medium")) + cxAscii = 64; + else if (RTStrIStr(pszArgs, "small")) + cxAscii = 48; + else if (RTStrIStr(pszArgs, "tiny")) + cxAscii = 24; + + /* Y invert the image when producing the ASCII art. */ + bool fInvY = false; + if (RTStrIStr(pszArgs, "invy")) + fInvY = true; + + vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), + pHlp, sid, fVerbose, cxAscii, fInvY, NULL); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsurf"} + */ +DECLCALLBACK(void) vmsvgaR3Info3dSurfaceBmp(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + /* pszArg = "sid[>dir]" + * Writes %dir%/info-S-sidI.bmp, where S - sequential bitmap number, I - decimal surface id. + */ + char *pszBitmapPath = NULL; + uint32_t sid = UINT32_MAX; + if (pszArgs) + pszArgs = RTStrStripL(pszArgs); + if (pszArgs && RT_C_IS_DIGIT(*pszArgs)) + RTStrToUInt32Ex(pszArgs, &pszBitmapPath, 0, &sid); + if ( pszBitmapPath + && *pszBitmapPath == '>') + ++pszBitmapPath; + + const bool fVerbose = true; + const uint32_t cxAscii = 0; /* No ASCII */ + const bool fInvY = false; /* Do not invert. */ + vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), + pHlp, sid, fVerbose, cxAscii, fInvY, pszBitmapPath); +} + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dctx"} + */ +DECLCALLBACK(void) vmsvgaR3Info3dContext(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + /* There might be a specific surface ID at the start of the + arguments, if not show all contexts. */ + uint32_t sid = UINT32_MAX; + if (pszArgs) + pszArgs = RTStrStripL(pszArgs); + if (pszArgs && RT_C_IS_DIGIT(*pszArgs)) + sid = RTStrToUInt32(pszArgs); + + /* Verbose or terse display, we default to verbose. */ + bool fVerbose = true; + if (RTStrIStr(pszArgs, "terse")) + fVerbose = false; + + vmsvga3dInfoContextWorker(PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), pHlp, sid, fVerbose); +} +# endif /* VBOX_WITH_VMSVGA3D */ + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga"} + */ +static DECLCALLBACK(void) vmsvgaR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO; + RT_NOREF(pszArgs); + + pHlp->pfnPrintf(pHlp, "Extension enabled: %RTbool\n", pThis->svga.fEnabled); + pHlp->pfnPrintf(pHlp, "Configured: %RTbool\n", pThis->svga.fConfigured); + pHlp->pfnPrintf(pHlp, "Base I/O port: %#x\n", + pThis->hIoPortVmSvga != NIL_IOMIOPORTHANDLE + ? PDMDevHlpIoPortGetMappingAddress(pDevIns, pThis->hIoPortVmSvga) : UINT32_MAX); + pHlp->pfnPrintf(pHlp, "FIFO address: %RGp\n", pThis->svga.GCPhysFIFO); + pHlp->pfnPrintf(pHlp, "FIFO size: %u (%#x)\n", pThis->svga.cbFIFO, pThis->svga.cbFIFO); + pHlp->pfnPrintf(pHlp, "FIFO external cmd: %#x\n", pThis->svga.u8FIFOExtCommand); + pHlp->pfnPrintf(pHlp, "FIFO extcmd wakeup: %u\n", pThis->svga.fFifoExtCommandWakeup); + pHlp->pfnPrintf(pHlp, "FIFO min/max: %u/%u\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]); + pHlp->pfnPrintf(pHlp, "Busy: %#x\n", pThis->svga.fBusy); + pHlp->pfnPrintf(pHlp, "Traces: %RTbool (effective: %RTbool)\n", pThis->svga.fTraces, pThis->svga.fVRAMTracking); + pHlp->pfnPrintf(pHlp, "Guest ID: %#x (%d)\n", pThis->svga.u32GuestId, pThis->svga.u32GuestId); + pHlp->pfnPrintf(pHlp, "IRQ status: %#x\n", pThis->svga.u32IrqStatus); + pHlp->pfnPrintf(pHlp, "IRQ mask: %#x\n", pThis->svga.u32IrqMask); + pHlp->pfnPrintf(pHlp, "Pitch lock: %#x (FIFO:%#x)\n", pThis->svga.u32PitchLock, pFIFO[SVGA_FIFO_PITCHLOCK]); + pHlp->pfnPrintf(pHlp, "Current GMR ID: %#x\n", pThis->svga.u32CurrentGMRId); + pHlp->pfnPrintf(pHlp, "Device Capabilites: %#x\n", pThis->svga.u32DeviceCaps); + pHlp->pfnPrintf(pHlp, "Device Cap2: %#x\n", pThis->svga.u32DeviceCaps2); + pHlp->pfnPrintf(pHlp, "Guest driver id: %#x\n", pThis->svga.u32GuestDriverId); + pHlp->pfnPrintf(pHlp, "Guest driver ver1: %#x\n", pThis->svga.u32GuestDriverVer1); + pHlp->pfnPrintf(pHlp, "Guest driver ver2: %#x\n", pThis->svga.u32GuestDriverVer2); + pHlp->pfnPrintf(pHlp, "Guest driver ver3: %#x\n", pThis->svga.u32GuestDriverVer3); + pHlp->pfnPrintf(pHlp, "Index reg: %#x\n", pThis->svga.u32IndexReg); + pHlp->pfnPrintf(pHlp, "Action flags: %#x\n", pThis->svga.u32ActionFlags); + pHlp->pfnPrintf(pHlp, "Max display size: %ux%u\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight); + pHlp->pfnPrintf(pHlp, "Display size: %ux%u %ubpp\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp); + pHlp->pfnPrintf(pHlp, "Scanline: %u (%#x)\n", pThis->svga.cbScanline, pThis->svga.cbScanline); + pHlp->pfnPrintf(pHlp, "Viewport position: %ux%u\n", pThis->svga.viewport.x, pThis->svga.viewport.y); + pHlp->pfnPrintf(pHlp, "Viewport size: %ux%u\n", pThis->svga.viewport.cx, pThis->svga.viewport.cy); + + pHlp->pfnPrintf(pHlp, "Cursor active: %RTbool\n", pSVGAState->Cursor.fActive); + pHlp->pfnPrintf(pHlp, "Cursor hotspot: %ux%u\n", pSVGAState->Cursor.xHotspot, pSVGAState->Cursor.yHotspot); + pHlp->pfnPrintf(pHlp, "Cursor size: %ux%u\n", pSVGAState->Cursor.width, pSVGAState->Cursor.height); + pHlp->pfnPrintf(pHlp, "Cursor byte size: %u (%#x)\n", pSVGAState->Cursor.cbData, pSVGAState->Cursor.cbData); + + pHlp->pfnPrintf(pHlp, "FIFO cursor: state %u, screen %d\n", pFIFO[SVGA_FIFO_CURSOR_ON], pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID]); + pHlp->pfnPrintf(pHlp, "FIFO cursor at: %u,%u\n", pFIFO[SVGA_FIFO_CURSOR_X], pFIFO[SVGA_FIFO_CURSOR_Y]); + + pHlp->pfnPrintf(pHlp, "Legacy cursor: ID %u, state %u\n", pThis->svga.uCursorID, pThis->svga.uCursorOn); + pHlp->pfnPrintf(pHlp, "Legacy cursor at: %u,%u\n", pThis->svga.uCursorX, pThis->svga.uCursorY); + +# ifdef VBOX_WITH_VMSVGA3D + pHlp->pfnPrintf(pHlp, "3D enabled: %RTbool\n", pThis->svga.f3DEnabled); +# endif + if (pThisCC->pDrv) + { + pHlp->pfnPrintf(pHlp, "Driver mode: %ux%u %ubpp\n", pThisCC->pDrv->cx, pThisCC->pDrv->cy, pThisCC->pDrv->cBits); + pHlp->pfnPrintf(pHlp, "Driver pitch: %u (%#x)\n", pThisCC->pDrv->cbScanline, pThisCC->pDrv->cbScanline); + } + + /* Dump screen information. */ + for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen) + { + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, iScreen); + if (pScreen) + { + pHlp->pfnPrintf(pHlp, "Screen %u defined (ID %u):\n", iScreen, pScreen->idScreen); + pHlp->pfnPrintf(pHlp, " %u x %u x %ubpp @ %u, %u\n", pScreen->cWidth, pScreen->cHeight, + pScreen->cBpp, pScreen->xOrigin, pScreen->yOrigin); + pHlp->pfnPrintf(pHlp, " Pitch %u bytes, VRAM offset %X\n", pScreen->cbPitch, pScreen->offVRAM); + pHlp->pfnPrintf(pHlp, " Flags %X", pScreen->fuScreen); + if (pScreen->fuScreen != SVGA_SCREEN_MUST_BE_SET) + { + pHlp->pfnPrintf(pHlp, " ("); + if (pScreen->fuScreen & SVGA_SCREEN_IS_PRIMARY) + pHlp->pfnPrintf(pHlp, " IS_PRIMARY"); + if (pScreen->fuScreen & SVGA_SCREEN_FULLSCREEN_HINT) + pHlp->pfnPrintf(pHlp, " FULLSCREEN_HINT"); + if (pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE) + pHlp->pfnPrintf(pHlp, " DEACTIVATE"); + if (pScreen->fuScreen & SVGA_SCREEN_BLANKING) + pHlp->pfnPrintf(pHlp, " BLANKING"); + pHlp->pfnPrintf(pHlp, " )"); + } + pHlp->pfnPrintf(pHlp, ", %smodified\n", pScreen->fModified ? "" : "not "); + } + } + +} + +static int vmsvgaR3LoadBufCtx(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGACMDBUFCTX pBufCtx, SVGACBContext CBCtx) +{ + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + + uint32_t cSubmitted; + int rc = pHlp->pfnSSMGetU32(pSSM, &cSubmitted); + AssertLogRelRCReturn(rc, rc); + + for (uint32_t i = 0; i < cSubmitted; ++i) + { + PVMSVGACMDBUF pCmdBuf = vmsvgaR3CmdBufAlloc(pBufCtx); + AssertPtrReturn(pCmdBuf, VERR_NO_MEMORY); + + pHlp->pfnSSMGetGCPhys(pSSM, &pCmdBuf->GCPhysCB); + + uint32_t u32; + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertRCReturn(rc, rc); + AssertReturn(u32 == sizeof(SVGACBHeader), VERR_INVALID_STATE); + pHlp->pfnSSMGetMem(pSSM, &pCmdBuf->hdr, sizeof(SVGACBHeader)); + + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertRCReturn(rc, rc); + AssertReturn(u32 == pCmdBuf->hdr.length, VERR_INVALID_STATE); + + if (pCmdBuf->hdr.length) + { + pCmdBuf->pvCommands = RTMemAlloc(pCmdBuf->hdr.length); + AssertPtrReturn(pCmdBuf->pvCommands, VERR_NO_MEMORY); + + rc = pHlp->pfnSSMGetMem(pSSM, pCmdBuf->pvCommands, pCmdBuf->hdr.length); + AssertRCReturn(rc, rc); + } + + if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))) + { + vmsvgaR3CmdBufSubmitCtx(pDevIns, pThis, pThisCC, &pCmdBuf); + } + else + { + uint32_t offNextCmd = 0; + vmsvgaR3CmdBufSubmitDC(pDevIns, pThisCC, &pCmdBuf, &offNextCmd); + } + + /* Free the buffer if CmdBufSubmit* did not consume it. */ + vmsvgaR3CmdBufFree(pCmdBuf); + } + return rc; +} + +static int vmsvgaR3LoadCommandBuffers(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM) +{ + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + + bool f; + uint32_t u32; + + /* Device context command buffers. */ + int rc = vmsvgaR3LoadBufCtx(pDevIns, pThis, pThisCC, pSSM, &pSvgaR3State->CmdBufCtxDC, SVGA_CB_CONTEXT_MAX); + AssertLogRelRCReturn(rc, rc); + + /* DX contexts command buffers. */ + uint32_t cBufCtx; + rc = pHlp->pfnSSMGetU32(pSSM, &cBufCtx); + AssertLogRelRCReturn(rc, rc); + AssertReturn(cBufCtx == RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs), VERR_INVALID_STATE); + for (uint32_t j = 0; j < cBufCtx; ++j) + { + rc = pHlp->pfnSSMGetBool(pSSM, &f); + AssertLogRelRCReturn(rc, rc); + if (f) + { + pSvgaR3State->apCmdBufCtxs[j] = (PVMSVGACMDBUFCTX)RTMemAlloc(sizeof(VMSVGACMDBUFCTX)); + AssertPtrReturn(pSvgaR3State->apCmdBufCtxs[j], VERR_NO_MEMORY); + vmsvgaR3CmdBufCtxInit(pSvgaR3State->apCmdBufCtxs[j]); + + rc = vmsvgaR3LoadBufCtx(pDevIns, pThis, pThisCC, pSSM, pSvgaR3State->apCmdBufCtxs[j], (SVGACBContext)j); + AssertLogRelRCReturn(rc, rc); + } + } + + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + pSvgaR3State->fCmdBuf = u32; + return rc; +} + +static int vmsvgaR3LoadGbo(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, VMSVGAGBO *pGbo) +{ + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + + int rc; + pHlp->pfnSSMGetU32(pSSM, &pGbo->fGboFlags); + pHlp->pfnSSMGetU32(pSSM, &pGbo->cTotalPages); + pHlp->pfnSSMGetU32(pSSM, &pGbo->cbTotal); + rc = pHlp->pfnSSMGetU32(pSSM, &pGbo->cDescriptors); + AssertRCReturn(rc, rc); + + if (pGbo->cDescriptors) + { + pGbo->paDescriptors = (PVMSVGAGBODESCRIPTOR)RTMemAllocZ(pGbo->cDescriptors * sizeof(VMSVGAGBODESCRIPTOR)); + AssertPtrReturn(pGbo->paDescriptors, VERR_NO_MEMORY); + } + + for (uint32_t iDesc = 0; iDesc < pGbo->cDescriptors; ++iDesc) + { + PVMSVGAGBODESCRIPTOR pDesc = &pGbo->paDescriptors[iDesc]; + pHlp->pfnSSMGetGCPhys(pSSM, &pDesc->GCPhys); + rc = pHlp->pfnSSMGetU64(pSSM, &pDesc->cPages); + } + + if (pGbo->fGboFlags & VMSVGAGBO_F_HOST_BACKED) + { + pGbo->pvHost = RTMemAlloc(pGbo->cbTotal); + AssertPtrReturn(pGbo->pvHost, VERR_NO_MEMORY); + rc = pHlp->pfnSSMGetMem(pSSM, pGbo->pvHost, pGbo->cbTotal); + } + + return rc; +} + +/** + * Portion of VMSVGA state which must be loaded oin the FIFO thread. + */ +static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, + PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) +{ + RT_NOREF(uPass); + + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + int rc; + + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS) + { + uint32_t cScreens = 0; + rc = pHlp->pfnSSMGetU32(pSSM, &cScreens); + AssertRCReturn(rc, rc); + AssertLogRelMsgReturn(cScreens <= _64K, /* big enough */ + ("cScreens=%#x\n", cScreens), + VERR_SSM_DATA_UNIT_FORMAT_CHANGED); + + for (uint32_t i = 0; i < cScreens; ++i) + { + VMSVGASCREENOBJECT screen; + RT_ZERO(screen); + + rc = pHlp->pfnSSMGetStructEx(pSSM, &screen, sizeof(screen), 0, g_aVMSVGASCREENOBJECTFields, NULL); + AssertLogRelRCReturn(rc, rc); + + if (screen.idScreen < RT_ELEMENTS(pSVGAState->aScreens)) + { + VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[screen.idScreen]; + *pScreen = screen; + pScreen->fModified = true; + + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_DX) + { + uint32_t u32; + pHlp->pfnSSMGetU32(pSSM, &u32); /* Size of screen bitmap. */ + AssertLogRelRCReturn(rc, rc); + if (u32) + { + pScreen->pvScreenBitmap = RTMemAlloc(u32); + AssertPtrReturn(pScreen->pvScreenBitmap, VERR_NO_MEMORY); + + pHlp->pfnSSMGetMem(pSSM, pScreen->pvScreenBitmap, u32); + } + } + } + else + { + LogRel(("VGA: ignored screen object %d\n", screen.idScreen)); + } + } + } + else + { + /* Try to setup at least the first screen. */ + VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0]; + Assert(pScreen->idScreen == 0); + pScreen->fDefined = true; + pScreen->fModified = true; + pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY; + pScreen->xOrigin = 0; + pScreen->yOrigin = 0; + pScreen->offVRAM = pThis->svga.uScreenOffset; + pScreen->cbPitch = pThis->svga.cbScanline; + pScreen->cWidth = pThis->svga.uWidth; + pScreen->cHeight = pThis->svga.uHeight; + pScreen->cBpp = pThis->svga.uBpp; + } + + return VINF_SUCCESS; +} + +/** + * @copydoc FNSSMDEVLOADEXEC + */ +int vmsvgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) +{ + RT_NOREF(uPass); + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc; + + /* Load our part of the VGAState */ + rc = pHlp->pfnSSMGetStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL); + AssertRCReturn(rc, rc); + + /* Load the VGA framebuffer. */ + AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE >= _32K); + uint32_t cbVgaFramebuffer = _32K; + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX) + { + rc = pHlp->pfnSSMGetU32(pSSM, &cbVgaFramebuffer); + AssertRCReturn(rc, rc); + AssertLogRelMsgReturn(cbVgaFramebuffer <= _4M && cbVgaFramebuffer >= _32K && RT_IS_POWER_OF_TWO(cbVgaFramebuffer), + ("cbVgaFramebuffer=%#x - expected 32KB..4MB, power of two\n", cbVgaFramebuffer), + VERR_SSM_DATA_UNIT_FORMAT_CHANGED); + AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE <= _4M); + AssertCompile(RT_IS_POWER_OF_TWO(VMSVGA_VGA_FB_BACKUP_SIZE)); + } + rc = pHlp->pfnSSMGetMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, RT_MIN(cbVgaFramebuffer, VMSVGA_VGA_FB_BACKUP_SIZE)); + AssertRCReturn(rc, rc); + if (cbVgaFramebuffer > VMSVGA_VGA_FB_BACKUP_SIZE) + pHlp->pfnSSMSkip(pSSM, cbVgaFramebuffer - VMSVGA_VGA_FB_BACKUP_SIZE); + else if (cbVgaFramebuffer < VMSVGA_VGA_FB_BACKUP_SIZE) + RT_BZERO(&pThisCC->svga.pbVgaFrameBufferR3[cbVgaFramebuffer], VMSVGA_VGA_FB_BACKUP_SIZE - cbVgaFramebuffer); + + /* Load the VMSVGA state. */ + rc = pHlp->pfnSSMGetStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL); + AssertRCReturn(rc, rc); + + /* Load the active cursor bitmaps. */ + if (pSVGAState->Cursor.fActive) + { + pSVGAState->Cursor.pData = RTMemAlloc(pSVGAState->Cursor.cbData); + AssertReturn(pSVGAState->Cursor.pData, VERR_NO_MEMORY); + + rc = pHlp->pfnSSMGetMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData); + AssertRCReturn(rc, rc); + } + + /* Load the GMR state. */ + uint32_t cGMR = 256; /* Hardcoded in previous saved state versions. */ + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_GMR_COUNT) + { + rc = pHlp->pfnSSMGetU32(pSSM, &cGMR); + AssertRCReturn(rc, rc); + /* Numbers of GMRs was never less than 256. 1MB is a large arbitrary limit. */ + AssertLogRelMsgReturn(cGMR <= _1M && cGMR >= 256, + ("cGMR=%#x - expected 256B..1MB\n", cGMR), + VERR_SSM_DATA_UNIT_FORMAT_CHANGED); + } + + if (pThis->svga.cGMR != cGMR) + { + /* Reallocate GMR array. */ + Assert(pSVGAState->paGMR != NULL); + RTMemFree(pSVGAState->paGMR); + pSVGAState->paGMR = (PGMR)RTMemAllocZ(cGMR * sizeof(GMR)); + AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY); + pThis->svga.cGMR = cGMR; + } + + for (uint32_t i = 0; i < cGMR; ++i) + { + PGMR pGMR = &pSVGAState->paGMR[i]; + + rc = pHlp->pfnSSMGetStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL); + AssertRCReturn(rc, rc); + + if (pGMR->numDescriptors) + { + Assert(pGMR->cMaxPages || pGMR->cbTotal); + pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->numDescriptors * sizeof(VMSVGAGMRDESCRIPTOR)); + AssertReturn(pGMR->paDesc, VERR_NO_MEMORY); + + for (uint32_t j = 0; j < pGMR->numDescriptors; ++j) + { + rc = pHlp->pfnSSMGetStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL); + AssertRCReturn(rc, rc); + } + } + } + + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_DX) + { + bool f; + uint32_t u32; + + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_DX_CMDBUF) + { + /* Command buffers are saved independently from VGPU10. */ + rc = pHlp->pfnSSMGetBool(pSSM, &f); + AssertLogRelRCReturn(rc, rc); + if (f) + { + rc = vmsvgaR3LoadCommandBuffers(pDevIns, pThis, pThisCC, pSSM); + AssertLogRelRCReturn(rc, rc); + } + } + + rc = pHlp->pfnSSMGetBool(pSSM, &f); + AssertLogRelRCReturn(rc, rc); + pThis->fVMSVGA10 = f; + + if (pThis->fVMSVGA10) + { + if (uVersion < VGA_SAVEDSTATE_VERSION_VMSVGA_DX_CMDBUF) + { + rc = vmsvgaR3LoadCommandBuffers(pDevIns, pThis, pThisCC, pSSM); + AssertLogRelRCReturn(rc, rc); + } + + /* + * OTables GBOs. + */ + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertLogRelRCReturn(rc, rc); + AssertReturn(u32 == SVGA_OTABLE_MAX, VERR_INVALID_STATE); + for (int i = 0; i < SVGA_OTABLE_MAX; ++i) + { + VMSVGAGBO *pGbo = &pSVGAState->aGboOTables[i]; + rc = vmsvgaR3LoadGbo(pDevIns, pSSM, pGbo); + AssertRCReturn(rc, rc); + } + + /* + * MOBs. + */ + for (;;) + { + rc = pHlp->pfnSSMGetU32(pSSM, &u32); /* MOB id. */ + AssertRCReturn(rc, rc); + if (u32 == SVGA_ID_INVALID) + break; + + PVMSVGAMOB pMob = (PVMSVGAMOB)RTMemAllocZ(sizeof(*pMob)); + AssertPtrReturn(pMob, VERR_NO_MEMORY); + + rc = vmsvgaR3LoadGbo(pDevIns, pSSM, &pMob->Gbo); + AssertRCReturn(rc, rc); + + pMob->Core.Key = u32; + if (RTAvlU32Insert(&pSVGAState->MOBTree, &pMob->Core)) + RTListPrepend(&pSVGAState->MOBLRUList, &pMob->nodeLRU); + else + AssertFailedReturn(VERR_NO_MEMORY); + } + +# ifdef VMSVGA3D_DX + if (pThis->svga.f3DEnabled) + { + pHlp->pfnSSMGetU32(pSSM, &pSVGAState->idDXContextCurrent); + } +# endif + } + } + +# ifdef RT_OS_DARWIN /** @todo r=bird: this is normally done on the EMT, so for DARWIN we do that when loading saved state too now. See DevVGA-SVGA3d-shared.h. */ + vmsvgaR3PowerOnDevice(pDevIns, pThis, pThisCC, /*fLoadState=*/ true); +# endif + + VMSVGA_STATE_LOAD LoadState; + LoadState.pSSM = pSSM; + LoadState.uVersion = uVersion; + LoadState.uPass = uPass; + rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_LOADSTATE, &LoadState, RT_INDEFINITE_WAIT); + AssertLogRelRCReturn(rc, rc); + + return VINF_SUCCESS; +} + +/** + * Reinit the video mode after the state has been loaded. + */ +int vmsvgaR3LoadDone(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + + /* VMSVGA is working via VBVA interface, therefore it needs to be + * enabled on saved state restore. See @bugref{10071#c7}. */ + if (pThis->svga.fEnabled) + { + for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen) + pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, idScreen, NULL /*pHostFlags*/); + } + + /* Set the active cursor. */ + if (pSVGAState->Cursor.fActive) + { + /* We don't store the alpha flag, but we can take a guess that if + * the old register interface was used, the cursor was B&W. + */ + bool fAlpha = pThis->svga.uCursorOn ? false : true; + + int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, + true /*fVisible*/, + fAlpha, + pSVGAState->Cursor.xHotspot, + pSVGAState->Cursor.yHotspot, + pSVGAState->Cursor.width, + pSVGAState->Cursor.height, + pSVGAState->Cursor.pData); + AssertRC(rc); + + if (pThis->svga.uCursorOn) + pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, VBVA_CURSOR_VALID_DATA, SVGA_ID_INVALID, pThis->svga.uCursorX, pThis->svga.uCursorY); + } + + /* If the VRAM handler should not be registered, we have to explicitly + * unregister it here! + */ + if (!pThis->svga.fVRAMTracking) + { + vgaR3UnregisterVRAMHandler(pDevIns, pThis); + } + + /* Let the FIFO thread deal with changing the mode. */ + ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE); + + return VINF_SUCCESS; +} + +static int vmsvgaR3SaveBufCtx(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PVMSVGACMDBUFCTX pBufCtx) +{ + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + + int rc = pHlp->pfnSSMPutU32(pSSM, pBufCtx->cSubmitted); + AssertLogRelRCReturn(rc, rc); + if (pBufCtx->cSubmitted) + { + PVMSVGACMDBUF pIter; + RTListForEach(&pBufCtx->listSubmitted, pIter, VMSVGACMDBUF, nodeBuffer) + { + pHlp->pfnSSMPutGCPhys(pSSM, pIter->GCPhysCB); + pHlp->pfnSSMPutU32(pSSM, sizeof(SVGACBHeader)); + pHlp->pfnSSMPutMem(pSSM, &pIter->hdr, sizeof(SVGACBHeader)); + pHlp->pfnSSMPutU32(pSSM, pIter->hdr.length); + if (pIter->hdr.length) + rc = pHlp->pfnSSMPutMem(pSSM, pIter->pvCommands, pIter->hdr.length); + AssertLogRelRCReturn(rc, rc); + } + } + return rc; +} + +static int vmsvgaR3SaveGbo(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, VMSVGAGBO *pGbo) +{ + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + + int rc; + pHlp->pfnSSMPutU32(pSSM, pGbo->fGboFlags); + pHlp->pfnSSMPutU32(pSSM, pGbo->cTotalPages); + pHlp->pfnSSMPutU32(pSSM, pGbo->cbTotal); + rc = pHlp->pfnSSMPutU32(pSSM, pGbo->cDescriptors); + for (uint32_t iDesc = 0; iDesc < pGbo->cDescriptors; ++iDesc) + { + PVMSVGAGBODESCRIPTOR pDesc = &pGbo->paDescriptors[iDesc]; + pHlp->pfnSSMPutGCPhys(pSSM, pDesc->GCPhys); + rc = pHlp->pfnSSMPutU64(pSSM, pDesc->cPages); + } + if (pGbo->fGboFlags & VMSVGAGBO_F_HOST_BACKED) + rc = pHlp->pfnSSMPutMem(pSSM, pGbo->pvHost, pGbo->cbTotal); + return rc; +} + +/** + * Portion of SVGA state which must be saved in the FIFO thread. + */ +static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM) +{ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + int rc; + + /* Save the screen objects. */ + /* Count defined screen object. */ + uint32_t cScreens = 0; + for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i) + { + if (pSVGAState->aScreens[i].fDefined) + ++cScreens; + } + + rc = pHlp->pfnSSMPutU32(pSSM, cScreens); + AssertLogRelRCReturn(rc, rc); + + for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i) + { + VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[i]; + if (!pScreen->fDefined) + continue; + + rc = pHlp->pfnSSMPutStructEx(pSSM, pScreen, sizeof(*pScreen), 0, g_aVMSVGASCREENOBJECTFields, NULL); + AssertLogRelRCReturn(rc, rc); + + /* + * VGA_SAVEDSTATE_VERSION_VMSVGA_DX + */ + if (pScreen->pvScreenBitmap) + { + uint32_t const cbScreenBitmap = pScreen->cHeight * pScreen->cbPitch; + pHlp->pfnSSMPutU32(pSSM, cbScreenBitmap); + pHlp->pfnSSMPutMem(pSSM, pScreen->pvScreenBitmap, cbScreenBitmap); + } + else + pHlp->pfnSSMPutU32(pSSM, 0); + } + return VINF_SUCCESS; +} + +/** + * @copydoc FNSSMDEVSAVEEXEC + */ +int vmsvgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc; + + /* Save our part of the VGAState */ + rc = pHlp->pfnSSMPutStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL); + AssertLogRelRCReturn(rc, rc); + + /* Save the framebuffer backup. */ + rc = pHlp->pfnSSMPutU32(pSSM, VMSVGA_VGA_FB_BACKUP_SIZE); + rc = pHlp->pfnSSMPutMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE); + AssertLogRelRCReturn(rc, rc); + + /* Save the VMSVGA state. */ + rc = pHlp->pfnSSMPutStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL); + AssertLogRelRCReturn(rc, rc); + + /* Save the active cursor bitmaps. */ + if (pSVGAState->Cursor.fActive) + { + rc = pHlp->pfnSSMPutMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData); + AssertLogRelRCReturn(rc, rc); + } + + /* Save the GMR state */ + rc = pHlp->pfnSSMPutU32(pSSM, pThis->svga.cGMR); + AssertLogRelRCReturn(rc, rc); + for (uint32_t i = 0; i < pThis->svga.cGMR; ++i) + { + PGMR pGMR = &pSVGAState->paGMR[i]; + + rc = pHlp->pfnSSMPutStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL); + AssertLogRelRCReturn(rc, rc); + + for (uint32_t j = 0; j < pGMR->numDescriptors; ++j) + { + rc = pHlp->pfnSSMPutStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL); + AssertLogRelRCReturn(rc, rc); + } + } + + /* + * VGA_SAVEDSTATE_VERSION_VMSVGA_DX+ + */ + if (pThis->svga.u32DeviceCaps & SVGA_CAP_COMMAND_BUFFERS) + { + rc = pHlp->pfnSSMPutBool(pSSM, true); + AssertLogRelRCReturn(rc, rc); + + /* Device context command buffers. */ + rc = vmsvgaR3SaveBufCtx(pDevIns, pSSM, &pSVGAState->CmdBufCtxDC); + AssertRCReturn(rc, rc); + + /* DX contexts command buffers. */ + rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pSVGAState->apCmdBufCtxs)); + AssertLogRelRCReturn(rc, rc); + for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->apCmdBufCtxs); ++i) + { + if (pSVGAState->apCmdBufCtxs[i]) + { + pHlp->pfnSSMPutBool(pSSM, true); + rc = vmsvgaR3SaveBufCtx(pDevIns, pSSM, pSVGAState->apCmdBufCtxs[i]); + AssertRCReturn(rc, rc); + } + else + pHlp->pfnSSMPutBool(pSSM, false); + } + + rc = pHlp->pfnSSMPutU32(pSSM, pSVGAState->fCmdBuf); + AssertRCReturn(rc, rc); + } + else + { + rc = pHlp->pfnSSMPutBool(pSSM, false); + AssertLogRelRCReturn(rc, rc); + } + + rc = pHlp->pfnSSMPutBool(pSSM, pThis->fVMSVGA10); + AssertLogRelRCReturn(rc, rc); + + if (pThis->fVMSVGA10) + { + /* + * OTables GBOs. + */ + pHlp->pfnSSMPutU32(pSSM, SVGA_OTABLE_MAX); + for (int i = 0; i < SVGA_OTABLE_MAX; ++i) + { + VMSVGAGBO *pGbo = &pSVGAState->aGboOTables[i]; + rc = vmsvgaR3SaveGbo(pDevIns, pSSM, pGbo); + AssertRCReturn(rc, rc); + } + + /* + * MOBs. + */ + PVMSVGAMOB pIter; + RTListForEach(&pSVGAState->MOBLRUList, pIter, VMSVGAMOB, nodeLRU) + { + pHlp->pfnSSMPutU32(pSSM, pIter->Core.Key); /* MOB id. */ + rc = vmsvgaR3SaveGbo(pDevIns, pSSM, &pIter->Gbo); + AssertRCReturn(rc, rc); + } + + pHlp->pfnSSMPutU32(pSSM, SVGA_ID_INVALID); /* End marker. */ + +# ifdef VMSVGA3D_DX + if (pThis->svga.f3DEnabled) + { + pHlp->pfnSSMPutU32(pSSM, pSVGAState->idDXContextCurrent); + } +# endif + } + + /* + * Must save some state (3D in particular) in the FIFO thread. + */ + rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_SAVESTATE, pSSM, RT_INDEFINITE_WAIT); + AssertLogRelRCReturn(rc, rc); + + return VINF_SUCCESS; +} + +/** + * Destructor for PVMSVGAR3STATE structure. The structure is not deallocated. + * + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The device context. + */ +static void vmsvgaR3StateTerm(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + +# ifndef VMSVGA_USE_EMT_HALT_CODE + if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI) + { + RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts); + pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT; + } +# endif + + if (pSVGAState->Cursor.fActive) + { + RTMemFreeZ(pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData); + pSVGAState->Cursor.pData = NULL; + pSVGAState->Cursor.fActive = false; + } + + if (pSVGAState->paGMR) + { + for (unsigned i = 0; i < pThis->svga.cGMR; ++i) + if (pSVGAState->paGMR[i].paDesc) + RTMemFree(pSVGAState->paGMR[i].paDesc); + + RTMemFree(pSVGAState->paGMR); + pSVGAState->paGMR = NULL; + } + + if (RTCritSectIsInitialized(&pSVGAState->CritSectCmdBuf)) + { + RTCritSectEnter(&pSVGAState->CritSectCmdBuf); + for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->apCmdBufCtxs); ++i) + { + vmsvgaR3CmdBufCtxTerm(pSVGAState->apCmdBufCtxs[i]); + RTMemFree(pSVGAState->apCmdBufCtxs[i]); + pSVGAState->apCmdBufCtxs[i] = NULL; + } + vmsvgaR3CmdBufCtxTerm(&pSVGAState->CmdBufCtxDC); + RTCritSectLeave(&pSVGAState->CritSectCmdBuf); + RTCritSectDelete(&pSVGAState->CritSectCmdBuf); + } +} + +/** + * Constructor for PVMSVGAR3STATE structure. + * + * @returns VBox status code. + * @param pDevIns The PDM device instance. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pSVGAState Pointer to the structure. It is already allocated. + */ +static int vmsvgaR3StateInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState) +{ + int rc = VINF_SUCCESS; + + pSVGAState->pDevIns = pDevIns; + + pSVGAState->paGMR = (PGMR)RTMemAllocZ(pThis->svga.cGMR * sizeof(GMR)); + AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY); + +# ifndef VMSVGA_USE_EMT_HALT_CODE + /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */ + rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts); + AssertRCReturn(rc, rc); +# endif + + rc = RTCritSectInit(&pSVGAState->CritSectCmdBuf); + AssertRCReturn(rc, rc); + + /* Init screen ids which are constant and allow to use a pointer to aScreens element and know its index. */ + for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i) + pSVGAState->aScreens[i].idScreen = i; + + vmsvgaR3CmdBufCtxInit(&pSVGAState->CmdBufCtxDC); + + RTListInit(&pSVGAState->MOBLRUList); +# ifdef VBOX_WITH_VMSVGA3D +# ifdef VMSVGA3D_DX + pSVGAState->idDXContextCurrent = SVGA3D_INVALID_ID; +# endif +# endif + return rc; +} + +# ifdef VBOX_WITH_VMSVGA3D +static void vmsvga3dR3Free3dInterfaces(PVGASTATECC pThisCC) +{ + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + + RTMemFree(pSVGAState->pFuncsMap); + pSVGAState->pFuncsMap = NULL; + RTMemFree(pSVGAState->pFuncsGBO); + pSVGAState->pFuncsGBO = NULL; + RTMemFree(pSVGAState->pFuncsDX); + pSVGAState->pFuncsDX = NULL; + RTMemFree(pSVGAState->pFuncsVGPU9); + pSVGAState->pFuncsVGPU9 = NULL; + RTMemFree(pSVGAState->pFuncs3D); + pSVGAState->pFuncs3D = NULL; +} + +/* This structure is used only by vmsvgaR3Init3dInterfaces */ +typedef struct VMSVGA3DINTERFACE +{ + char const *pcszName; + uint32_t cbFuncs; + void **ppvFuncs; +} VMSVGA3DINTERFACE; + +extern VMSVGA3DBACKENDDESC const g_BackendLegacy; +#if defined(VMSVGA3D_DX_BACKEND) +extern VMSVGA3DBACKENDDESC const g_BackendDX; +#endif + +/** + * Initializes the optional host 3D backend interfaces. + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + */ +static int vmsvgaR3Init3dInterfaces(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ +#ifndef VMSVGA3D_DX + RT_NOREF(pThis); +#endif + + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + +#define ENTRY_3D_INTERFACE(a_Name, a_Field) { VMSVGA3D_BACKEND_INTERFACE_NAME_##a_Name, sizeof(VMSVGA3DBACKENDFUNCS##a_Name), (void **)&pSVGAState->a_Field } + VMSVGA3DINTERFACE a3dInterface[] = + { + ENTRY_3D_INTERFACE(3D, pFuncs3D), + ENTRY_3D_INTERFACE(VGPU9, pFuncsVGPU9), + ENTRY_3D_INTERFACE(DX, pFuncsDX), + ENTRY_3D_INTERFACE(MAP, pFuncsMap), + ENTRY_3D_INTERFACE(GBO, pFuncsGBO), + }; +#undef ENTRY_3D_INTERFACE + + VMSVGA3DBACKENDDESC const *pBackend = NULL; +#if defined(VMSVGA3D_DX_BACKEND) + if (pThis->fVMSVGA10) + pBackend = &g_BackendDX; + else +#endif + pBackend = &g_BackendLegacy; + + int rc = VINF_SUCCESS; + for (uint32_t i = 0; i < RT_ELEMENTS(a3dInterface); ++i) + { + VMSVGA3DINTERFACE *p = &a3dInterface[i]; + + int rc2 = pBackend->pfnQueryInterface(pThisCC, p->pcszName, NULL, p->cbFuncs); + if (RT_SUCCESS(rc2)) + { + *p->ppvFuncs = RTMemAllocZ(p->cbFuncs); + AssertBreakStmt(*p->ppvFuncs, rc = VERR_NO_MEMORY); + + pBackend->pfnQueryInterface(pThisCC, p->pcszName, *p->ppvFuncs, p->cbFuncs); + } + } + + if (RT_SUCCESS(rc)) + { + rc = vmsvga3dInit(pDevIns, pThis, pThisCC); + if (RT_SUCCESS(rc)) + return VINF_SUCCESS; + } + + vmsvga3dR3Free3dInterfaces(pThisCC); + return rc; +} +# endif /* VBOX_WITH_VMSVGA3D */ + +/** + * Compute the host capabilities: device and FIFO. + * + * Depends on 3D backend initialization. + * + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pu32DeviceCaps Device capabilities (SVGA_CAP_*). + * @param pu32DeviceCaps2 Device capabilities (SVGA_CAP2_*). + * @param pu32FIFOCaps FIFO capabilities (SVGA_FIFO_CAPS_*). + */ +static void vmsvgaR3GetCaps(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t *pu32DeviceCaps, uint32_t *pu32DeviceCaps2, uint32_t *pu32FIFOCaps) +{ +#ifndef VBOX_WITH_VMSVGA3D + RT_NOREF(pThisCC); +#endif + + /* Device caps. */ + *pu32DeviceCaps = SVGA_CAP_GMR + | SVGA_CAP_GMR2 + | SVGA_CAP_CURSOR + | SVGA_CAP_CURSOR_BYPASS + | SVGA_CAP_CURSOR_BYPASS_2 + | SVGA_CAP_EXTENDED_FIFO + | SVGA_CAP_IRQMASK + | SVGA_CAP_PITCHLOCK + | SVGA_CAP_RECT_COPY + | SVGA_CAP_TRACES + | SVGA_CAP_SCREEN_OBJECT_2 + | SVGA_CAP_ALPHA_CURSOR; + + *pu32DeviceCaps |= SVGA_CAP_COMMAND_BUFFERS /* Enable register based command buffer submission. */ + ; + + *pu32DeviceCaps2 = SVGA_CAP2_NONE; + + /* VGPU10 capabilities. */ + if (pThis->fVMSVGA10) + { +# ifdef VBOX_WITH_VMSVGA3D + if (pThisCC->svga.pSvgaR3State->pFuncsGBO) + *pu32DeviceCaps |= SVGA_CAP_GBOBJECTS; /* Enable guest-backed objects and surfaces. */ + if (pThisCC->svga.pSvgaR3State->pFuncsDX) + { + *pu32DeviceCaps |= SVGA_CAP_DX /* DX commands, and command buffers in a mob. */ + | SVGA_CAP_CAP2_REGISTER /* Extended capabilities. */ + ; + + if (*pu32DeviceCaps & SVGA_CAP_CAP2_REGISTER) + *pu32DeviceCaps2 |= SVGA_CAP2_GROW_OTABLE /* "Allow the GrowOTable/DXGrowCOTable commands" */ + | SVGA_CAP2_INTRA_SURFACE_COPY /* "IntraSurfaceCopy command" */ + | SVGA_CAP2_DX2 /* Shader Model 4.1. + * "Allow the DefineGBSurface_v3, WholeSurfaceCopy, WriteZeroSurface, and + * HintZeroSurface commands, and the SVGA_REG_GUEST_DRIVER_ID register." + */ + | SVGA_CAP2_GB_MEMSIZE_2 /* "Allow the SVGA_REG_GBOBJECT_MEM_SIZE_KB register" */ + | SVGA_CAP2_OTABLE_PTDEPTH_2 + | SVGA_CAP2_DX3 /* Shader Model 5. + * DefineGBSurface_v4, etc + */ + ; + } +# endif + } + +# ifdef VBOX_WITH_VMSVGA3D + if (pThisCC->svga.pSvgaR3State->pFuncs3D) + *pu32DeviceCaps |= SVGA_CAP_3D; +# endif + + /* FIFO capabilities. */ + *pu32FIFOCaps = SVGA_FIFO_CAP_FENCE + | SVGA_FIFO_CAP_PITCHLOCK + | SVGA_FIFO_CAP_CURSOR_BYPASS_3 + | SVGA_FIFO_CAP_RESERVE + | SVGA_FIFO_CAP_GMR2 + | SVGA_FIFO_CAP_3D_HWVERSION_REVISED + | SVGA_FIFO_CAP_SCREEN_OBJECT_2; +} + +/** Initialize the FIFO on power on and reset. + * + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + */ +static void vmsvgaR3InitFIFO(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + RT_BZERO(pThisCC->svga.pau32FIFO, pThis->svga.cbFIFO); + + /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */ + pThisCC->svga.pau32FIFO[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID; +} + +# ifdef VBOX_WITH_VMSVGA3D +/** + * Initializes the host 3D capabilities and writes them to FIFO memory. + * + * @returns VBox status code. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + */ +static void vmsvgaR3InitFifo3DCaps(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + /* Query the capabilities and store them in the pThis->svga.au32DevCaps array. */ + bool const fSavedBuffering = RTLogRelSetBuffering(true); + + for (unsigned i = 0; i < RT_ELEMENTS(pThis->svga.au32DevCaps); ++i) + { + uint32_t val = 0; + int rc = vmsvga3dQueryCaps(pThisCC, (SVGA3dDevCapIndex)i, &val); + if (RT_SUCCESS(rc)) + pThis->svga.au32DevCaps[i] = val; + else + pThis->svga.au32DevCaps[i] = 0; + + /* LogRel the capability value. */ + if (i < SVGA3D_DEVCAP_MAX) + { + char const *pszDevCapName = &vmsvgaDevCapIndexToString((SVGA3dDevCapIndex)i)[sizeof("SVGA3D_DEVCAP")]; + if (RT_SUCCESS(rc)) + { + if ( i == SVGA3D_DEVCAP_MAX_POINT_SIZE + || i == SVGA3D_DEVCAP_MAX_LINE_WIDTH + || i == SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH) + { + float const fval = *(float *)&val; + LogRel(("VMSVGA3d: cap[%u]=" FLOAT_FMT_STR " {%s}\n", i, FLOAT_FMT_ARGS(fval), pszDevCapName)); + } + else + LogRel(("VMSVGA3d: cap[%u]=%#010x {%s}\n", i, val, pszDevCapName)); + } + else + LogRel(("VMSVGA3d: cap[%u]=failed rc=%Rrc {%s}\n", i, rc, pszDevCapName)); + } + else + LogRel(("VMSVGA3d: new cap[%u]=%#010x rc=%Rrc\n", i, val, rc)); + } + + RTLogRelSetBuffering(fSavedBuffering); + + /* 3d hardware version; latest and greatest */ + pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION_REVISED] = SVGA3D_HWVERSION_CURRENT; + pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION] = SVGA3D_HWVERSION_CURRENT; + + /* Fill out 3d capabilities up to SVGA3D_DEVCAP_SURFACEFMT_ATI2 in the FIFO memory. + * SVGA3D_DEVCAP_SURFACEFMT_ATI2 is the last capabiltiy for pre-SVGA_CAP_GBOBJECTS hardware. + * If the VMSVGA device supports SVGA_CAP_GBOBJECTS capability, then the guest has to use SVGA_REG_DEV_CAP + * register to query the devcaps. Older guests will still try to read the devcaps from FIFO. + */ + SVGA3dCapsRecord *pCaps; + SVGA3dCapPair *pData; + + pCaps = (SVGA3dCapsRecord *)&pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_CAPS]; + pCaps->header.type = SVGA3DCAPS_RECORD_DEVCAPS; + pData = (SVGA3dCapPair *)&pCaps->data; + + AssertCompile(SVGA3D_DEVCAP_DEAD1 == SVGA3D_DEVCAP_SURFACEFMT_ATI2 + 1); + for (unsigned i = 0; i < SVGA3D_DEVCAP_DEAD1; ++i) + { + pData[i][0] = i; + pData[i][1] = pThis->svga.au32DevCaps[i]; + } + pCaps->header.length = (sizeof(pCaps->header) + SVGA3D_DEVCAP_DEAD1 * sizeof(SVGA3dCapPair)) / sizeof(uint32_t); + pCaps = (SVGA3dCapsRecord *)((uint32_t *)pCaps + pCaps->header.length); + + /* Mark end of record array (a zero word). */ + pCaps->header.length = 0; +} + +# endif + +/** + * Resets the SVGA hardware state + * + * @returns VBox status code. + * @param pDevIns The device instance. + */ +int vmsvgaR3Reset(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + + /* Reset before init? */ + if (!pSVGAState) + return VINF_SUCCESS; + + Log(("vmsvgaR3Reset\n")); + + /* Reset the FIFO processing as well as the 3d state (if we have one). */ + pThisCC->svga.pau32FIFO[SVGA_FIFO_NEXT_CMD] = pThisCC->svga.pau32FIFO[SVGA_FIFO_STOP] = 0; /** @todo should probably let the FIFO thread do this ... */ + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* Hack around lock order issue. FIFO thread might take the lock. */ + + int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_RESET, NULL /*pvParam*/, 60000 /*ms*/); + AssertLogRelRC(rc); + + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + + /* Reset other stuff. */ + pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE; + RT_ZERO(pThis->svga.au32ScratchRegion); + + ASMAtomicWriteBool(&pThis->svga.fBadGuest, false); + + vmsvgaR3StateTerm(pThis, pThisCC); + vmsvgaR3StateInit(pDevIns, pThis, pThisCC->svga.pSvgaR3State); + + RT_BZERO(pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE); + + vmsvgaR3InitFIFO(pThis, pThisCC); + + /* Initialize FIFO and register capabilities. */ + vmsvgaR3GetCaps(pThis, pThisCC, &pThis->svga.u32DeviceCaps, &pThis->svga.u32DeviceCaps2, &pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES]); + +# ifdef VBOX_WITH_VMSVGA3D + if (pThis->svga.f3DEnabled) + vmsvgaR3InitFifo3DCaps(pThis, pThisCC); +# endif + + /* VRAM tracking is enabled by default during bootup. */ + pThis->svga.fVRAMTracking = true; + pThis->svga.fEnabled = false; + + /* Invalidate current settings. */ + pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED; + pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED; + pThis->svga.uBpp = pThis->svga.uHostBpp; + pThis->svga.cbScanline = 0; + pThis->svga.u32PitchLock = 0; + + return rc; +} + +/** + * Cleans up the SVGA hardware state + * + * @returns VBox status code. + * @param pDevIns The device instance. + */ +int vmsvgaR3Destruct(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + + /* + * Ask the FIFO thread to terminate the 3d state and then terminate it. + */ + if (pThisCC->svga.pFIFOIOThread) + { + int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_TERMINATE, + NULL /*pvParam*/, 30000 /*ms*/); + AssertLogRelRC(rc); + + rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->svga.pFIFOIOThread, NULL); + AssertLogRelRC(rc); + pThisCC->svga.pFIFOIOThread = NULL; + } + + /* + * Destroy the special SVGA state. + */ + if (pThisCC->svga.pSvgaR3State) + { + vmsvgaR3StateTerm(pThis, pThisCC); + +# ifdef VBOX_WITH_VMSVGA3D + vmsvga3dR3Free3dInterfaces(pThisCC); +# endif + + RTMemFree(pThisCC->svga.pSvgaR3State); + pThisCC->svga.pSvgaR3State = NULL; + } + + /* + * Free our resources residing in the VGA state. + */ + if (pThisCC->svga.pbVgaFrameBufferR3) + { + RTMemFree(pThisCC->svga.pbVgaFrameBufferR3); + pThisCC->svga.pbVgaFrameBufferR3 = NULL; + } + if (pThisCC->svga.hFIFOExtCmdSem != NIL_RTSEMEVENT) + { + RTSemEventDestroy(pThisCC->svga.hFIFOExtCmdSem); + pThisCC->svga.hFIFOExtCmdSem = NIL_RTSEMEVENT; + } + if (pThis->svga.hFIFORequestSem != NIL_SUPSEMEVENT) + { + PDMDevHlpSUPSemEventClose(pDevIns, pThis->svga.hFIFORequestSem); + pThis->svga.hFIFORequestSem = NIL_SUPSEMEVENT; + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(size_t) vmsvga3dFloatFormat(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, + const char *pszType, void const *pvValue, + int cchWidth, int cchPrecision, unsigned fFlags, void *pvUser) +{ + RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser); + double const v = *(double *)&pvValue; + return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, FLOAT_FMT_STR, FLOAT_FMT_ARGS(v)); +} + +/** + * Initialize the SVGA hardware state + * + * @returns VBox status code. + * @param pDevIns The device instance. + */ +int vmsvgaR3Init(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PVMSVGAR3STATE pSVGAState; + int rc; + + rc = RTStrFormatTypeRegister("float", vmsvga3dFloatFormat, NULL); + AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc); + + pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE; + memset(pThis->svga.au32ScratchRegion, 0, sizeof(pThis->svga.au32ScratchRegion)); + + pThis->svga.cGMR = VMSVGA_MAX_GMR_IDS; + + /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */ + pThisCC->svga.pbVgaFrameBufferR3 = (uint8_t *)RTMemAllocZ(VMSVGA_VGA_FB_BACKUP_SIZE); + AssertReturn(pThisCC->svga.pbVgaFrameBufferR3, VERR_NO_MEMORY); + + /* Create event semaphore. */ + rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->svga.hFIFORequestSem); + AssertRCReturn(rc, rc); + + /* Create event semaphore. */ + rc = RTSemEventCreate(&pThisCC->svga.hFIFOExtCmdSem); + AssertRCReturn(rc, rc); + + pThisCC->svga.pSvgaR3State = (PVMSVGAR3STATE)RTMemAllocZ(sizeof(VMSVGAR3STATE)); + AssertReturn(pThisCC->svga.pSvgaR3State, VERR_NO_MEMORY); + + rc = vmsvgaR3StateInit(pDevIns, pThis, pThisCC->svga.pSvgaR3State); + AssertMsgRCReturn(rc, ("Failed to create pSvgaR3State.\n"), rc); + + pSVGAState = pThisCC->svga.pSvgaR3State; + + /* VRAM tracking is enabled by default during bootup. */ + pThis->svga.fVRAMTracking = true; + + /* Set up the host bpp. This value is as a default for the programmable + * bpp value. On old implementations, SVGA_REG_HOST_BITS_PER_PIXEL did not + * exist and SVGA_REG_BITS_PER_PIXEL was read-only, returning what was later + * separated as SVGA_REG_HOST_BITS_PER_PIXEL. + * + * NB: The driver cBits value is currently constant for the lifetime of the + * VM. If that changes, the host bpp logic might need revisiting. + */ + pThis->svga.uHostBpp = (pThisCC->pDrv->cBits + 7) & ~7; + + /* Invalidate current settings. */ + pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED; + pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED; + pThis->svga.uBpp = pThis->svga.uHostBpp; + pThis->svga.cbScanline = 0; + + pThis->svga.u32MaxWidth = VBE_DISPI_MAX_XRES; + pThis->svga.u32MaxHeight = VBE_DISPI_MAX_YRES; + while (pThis->svga.u32MaxWidth * pThis->svga.u32MaxHeight * 4 /* 32 bpp */ > pThis->vram_size) + { + pThis->svga.u32MaxWidth -= 256; + pThis->svga.u32MaxHeight -= 256; + } + Log(("VMSVGA: Maximum size (%d,%d)\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight)); + +# ifdef DEBUG_GMR_ACCESS + /* Register the GMR access handler type. */ + rc = PDMDevHlpPGMHandlerPhysicalTypeRegister(pDevIns, PGMPHYSHANDLERKIND_WRITE, vmsvgaR3GmrAccessHandler, + "VMSVGA GMR", &pThis->svga.hGmrAccessHandlerType); + AssertRCReturn(rc, rc); +# endif + +# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS) + /* Register the FIFO access handler type. In addition to debugging FIFO + access, this is also used to facilitate extended fifo thread sleeps. */ + rc = PDMDevHlpPGMHandlerPhysicalTypeRegister(pDevIns, +# ifdef DEBUG_FIFO_ACCESS + PGMPHYSHANDLERKIND_ALL, +# else + PGMPHYSHANDLERKIND_WRITE, +# endif + vmsvgaR3FifoAccessHandler, + "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType); + AssertRCReturn(rc, rc); +# endif + + /* Create the async IO thread. */ + rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->svga.pFIFOIOThread, pThis, vmsvgaR3FifoLoop, vmsvgaR3FifoLoopWakeUp, 0, + RTTHREADTYPE_IO, "VMSVGA FIFO"); + if (RT_FAILURE(rc)) + { + AssertMsgFailed(("%s: Async IO Thread creation for FIFO handling failed rc=%d\n", __FUNCTION__, rc)); + return rc; + } + + /* + * Statistics. + */ +# define REG_CNT(a_pvSample, a_pszName, a_pszDesc) \ + PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_COUNTER, a_pszName, STAMUNIT_OCCURENCES, a_pszDesc) +# define REG_PRF(a_pvSample, a_pszName, a_pszDesc) \ + PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_PROFILE, a_pszName, STAMUNIT_TICKS_PER_CALL, a_pszDesc) +# ifdef VBOX_WITH_STATISTICS + REG_PRF(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, "VMSVGA/Cmd/3dDrawPrimitivesProf", "Profiling of SVGA_3D_CMD_DRAW_PRIMITIVES."); + REG_PRF(&pSVGAState->StatR3Cmd3dPresentProf, "VMSVGA/Cmd/3dPresentProfBoth", "Profiling of SVGA_3D_CMD_PRESENT and SVGA_3D_CMD_PRESENT_READBACK."); + REG_PRF(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, "VMSVGA/Cmd/3dSurfaceDmaProf", "Profiling of SVGA_3D_CMD_SURFACE_DMA."); +# endif + REG_PRF(&pSVGAState->StatR3Cmd3dBlitSurfaceToScreenProf, "VMSVGA/Cmd/3dBlitSurfaceToScreenProf", "Profiling of SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN."); + REG_CNT(&pSVGAState->StatR3Cmd3dActivateSurface, "VMSVGA/Cmd/3dActivateSurface", "SVGA_3D_CMD_ACTIVATE_SURFACE"); + REG_CNT(&pSVGAState->StatR3Cmd3dBeginQuery, "VMSVGA/Cmd/3dBeginQuery", "SVGA_3D_CMD_BEGIN_QUERY"); + REG_CNT(&pSVGAState->StatR3Cmd3dClear, "VMSVGA/Cmd/3dClear", "SVGA_3D_CMD_CLEAR"); + REG_CNT(&pSVGAState->StatR3Cmd3dContextDefine, "VMSVGA/Cmd/3dContextDefine", "SVGA_3D_CMD_CONTEXT_DEFINE"); + REG_CNT(&pSVGAState->StatR3Cmd3dContextDestroy, "VMSVGA/Cmd/3dContextDestroy", "SVGA_3D_CMD_CONTEXT_DESTROY"); + REG_CNT(&pSVGAState->StatR3Cmd3dDeactivateSurface, "VMSVGA/Cmd/3dDeactivateSurface", "SVGA_3D_CMD_DEACTIVATE_SURFACE"); + REG_CNT(&pSVGAState->StatR3Cmd3dDrawPrimitives, "VMSVGA/Cmd/3dDrawPrimitives", "SVGA_3D_CMD_DRAW_PRIMITIVES"); + REG_CNT(&pSVGAState->StatR3Cmd3dEndQuery, "VMSVGA/Cmd/3dEndQuery", "SVGA_3D_CMD_END_QUERY"); + REG_CNT(&pSVGAState->StatR3Cmd3dGenerateMipmaps, "VMSVGA/Cmd/3dGenerateMipmaps", "SVGA_3D_CMD_GENERATE_MIPMAPS"); + REG_CNT(&pSVGAState->StatR3Cmd3dPresent, "VMSVGA/Cmd/3dPresent", "SVGA_3D_CMD_PRESENT"); + REG_CNT(&pSVGAState->StatR3Cmd3dPresentReadBack, "VMSVGA/Cmd/3dPresentReadBack", "SVGA_3D_CMD_PRESENT_READBACK"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetClipPlane, "VMSVGA/Cmd/3dSetClipPlane", "SVGA_3D_CMD_SETCLIPPLANE"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetLightData, "VMSVGA/Cmd/3dSetLightData", "SVGA_3D_CMD_SETLIGHTDATA"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetLightEnable, "VMSVGA/Cmd/3dSetLightEnable", "SVGA_3D_CMD_SETLIGHTENABLE"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetMaterial, "VMSVGA/Cmd/3dSetMaterial", "SVGA_3D_CMD_SETMATERIAL"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderState, "VMSVGA/Cmd/3dSetRenderState", "SVGA_3D_CMD_SETRENDERSTATE"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderTarget, "VMSVGA/Cmd/3dSetRenderTarget", "SVGA_3D_CMD_SETRENDERTARGET"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetScissorRect, "VMSVGA/Cmd/3dSetScissorRect", "SVGA_3D_CMD_SETSCISSORRECT"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetShader, "VMSVGA/Cmd/3dSetShader", "SVGA_3D_CMD_SET_SHADER"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetShaderConst, "VMSVGA/Cmd/3dSetShaderConst", "SVGA_3D_CMD_SET_SHADER_CONST"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetTextureState, "VMSVGA/Cmd/3dSetTextureState", "SVGA_3D_CMD_SETTEXTURESTATE"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetTransform, "VMSVGA/Cmd/3dSetTransform", "SVGA_3D_CMD_SETTRANSFORM"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetViewPort, "VMSVGA/Cmd/3dSetViewPort", "SVGA_3D_CMD_SETVIEWPORT"); + REG_CNT(&pSVGAState->StatR3Cmd3dSetZRange, "VMSVGA/Cmd/3dSetZRange", "SVGA_3D_CMD_SETZRANGE"); + REG_CNT(&pSVGAState->StatR3Cmd3dShaderDefine, "VMSVGA/Cmd/3dShaderDefine", "SVGA_3D_CMD_SHADER_DEFINE"); + REG_CNT(&pSVGAState->StatR3Cmd3dShaderDestroy, "VMSVGA/Cmd/3dShaderDestroy", "SVGA_3D_CMD_SHADER_DESTROY"); + REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceCopy, "VMSVGA/Cmd/3dSurfaceCopy", "SVGA_3D_CMD_SURFACE_COPY"); + REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefine, "VMSVGA/Cmd/3dSurfaceDefine", "SVGA_3D_CMD_SURFACE_DEFINE"); + REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefineV2, "VMSVGA/Cmd/3dSurfaceDefineV2", "SVGA_3D_CMD_SURFACE_DEFINE_V2"); + REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDestroy, "VMSVGA/Cmd/3dSurfaceDestroy", "SVGA_3D_CMD_SURFACE_DESTROY"); + REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDma, "VMSVGA/Cmd/3dSurfaceDma", "SVGA_3D_CMD_SURFACE_DMA"); + REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceScreen, "VMSVGA/Cmd/3dSurfaceScreen", "SVGA_3D_CMD_SURFACE_SCREEN"); + REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceStretchBlt, "VMSVGA/Cmd/3dSurfaceStretchBlt", "SVGA_3D_CMD_SURFACE_STRETCHBLT"); + REG_CNT(&pSVGAState->StatR3Cmd3dWaitForQuery, "VMSVGA/Cmd/3dWaitForQuery", "SVGA_3D_CMD_WAIT_FOR_QUERY"); + REG_CNT(&pSVGAState->StatR3CmdAnnotationCopy, "VMSVGA/Cmd/AnnotationCopy", "SVGA_CMD_ANNOTATION_COPY"); + REG_CNT(&pSVGAState->StatR3CmdAnnotationFill, "VMSVGA/Cmd/AnnotationFill", "SVGA_CMD_ANNOTATION_FILL"); + REG_CNT(&pSVGAState->StatR3CmdBlitGmrFbToScreen, "VMSVGA/Cmd/BlitGmrFbToScreen", "SVGA_CMD_BLIT_GMRFB_TO_SCREEN"); + REG_CNT(&pSVGAState->StatR3CmdBlitScreentoGmrFb, "VMSVGA/Cmd/BlitScreentoGmrFb", "SVGA_CMD_BLIT_SCREEN_TO_GMRFB"); + REG_CNT(&pSVGAState->StatR3CmdDefineAlphaCursor, "VMSVGA/Cmd/DefineAlphaCursor", "SVGA_CMD_DEFINE_ALPHA_CURSOR"); + REG_CNT(&pSVGAState->StatR3CmdDefineCursor, "VMSVGA/Cmd/DefineCursor", "SVGA_CMD_DEFINE_CURSOR"); + REG_CNT(&pSVGAState->StatR3CmdMoveCursor, "VMSVGA/Cmd/MoveCursor", "SVGA_CMD_MOVE_CURSOR"); + REG_CNT(&pSVGAState->StatR3CmdDisplayCursor, "VMSVGA/Cmd/DisplayCursor", "SVGA_CMD_DISPLAY_CURSOR"); + REG_CNT(&pSVGAState->StatR3CmdRectFill, "VMSVGA/Cmd/RectFill", "SVGA_CMD_RECT_FILL"); + REG_CNT(&pSVGAState->StatR3CmdRectCopy, "VMSVGA/Cmd/RectCopy", "SVGA_CMD_RECT_COPY"); + REG_CNT(&pSVGAState->StatR3CmdRectRopCopy, "VMSVGA/Cmd/RectRopCopy", "SVGA_CMD_RECT_ROP_COPY"); + REG_CNT(&pSVGAState->StatR3CmdDefineGmr2, "VMSVGA/Cmd/DefineGmr2", "SVGA_CMD_DEFINE_GMR2"); + REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Free, "VMSVGA/Cmd/DefineGmr2/Free", "Number of SVGA_CMD_DEFINE_GMR2 commands that only frees."); + REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Modify, "VMSVGA/Cmd/DefineGmr2/Modify", "Number of SVGA_CMD_DEFINE_GMR2 commands that redefines a non-free GMR."); + REG_CNT(&pSVGAState->StatR3CmdDefineGmrFb, "VMSVGA/Cmd/DefineGmrFb", "SVGA_CMD_DEFINE_GMRFB"); + REG_CNT(&pSVGAState->StatR3CmdDefineScreen, "VMSVGA/Cmd/DefineScreen", "SVGA_CMD_DEFINE_SCREEN"); + REG_CNT(&pSVGAState->StatR3CmdDestroyScreen, "VMSVGA/Cmd/DestroyScreen", "SVGA_CMD_DESTROY_SCREEN"); + REG_CNT(&pSVGAState->StatR3CmdEscape, "VMSVGA/Cmd/Escape", "SVGA_CMD_ESCAPE"); + REG_CNT(&pSVGAState->StatR3CmdFence, "VMSVGA/Cmd/Fence", "SVGA_CMD_FENCE"); + REG_CNT(&pSVGAState->StatR3CmdInvalidCmd, "VMSVGA/Cmd/InvalidCmd", "SVGA_CMD_INVALID_CMD"); + REG_CNT(&pSVGAState->StatR3CmdRemapGmr2, "VMSVGA/Cmd/RemapGmr2", "SVGA_CMD_REMAP_GMR2"); + REG_CNT(&pSVGAState->StatR3CmdRemapGmr2Modify, "VMSVGA/Cmd/RemapGmr2/Modify", "Number of SVGA_CMD_REMAP_GMR2 commands that modifies rather than complete the definition of a GMR."); + REG_CNT(&pSVGAState->StatR3CmdUpdate, "VMSVGA/Cmd/Update", "SVGA_CMD_UPDATE"); + REG_CNT(&pSVGAState->StatR3CmdUpdateVerbose, "VMSVGA/Cmd/UpdateVerbose", "SVGA_CMD_UPDATE_VERBOSE"); + + REG_CNT(&pSVGAState->StatR3RegConfigDoneWr, "VMSVGA/Reg/ConfigDoneWrite", "SVGA_REG_CONFIG_DONE writes"); + REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWr, "VMSVGA/Reg/GmrDescriptorWrite", "SVGA_REG_GMR_DESCRIPTOR writes"); + REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrErrors, "VMSVGA/Reg/GmrDescriptorWrite/Errors", "Number of erroneous SVGA_REG_GMR_DESCRIPTOR commands."); + REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrFree, "VMSVGA/Reg/GmrDescriptorWrite/Free", "Number of SVGA_REG_GMR_DESCRIPTOR commands only freeing the GMR."); + REG_CNT(&pThis->svga.StatRegBitsPerPixelWr, "VMSVGA/Reg/BitsPerPixelWrite", "SVGA_REG_BITS_PER_PIXEL writes."); + REG_CNT(&pThis->svga.StatRegBusyWr, "VMSVGA/Reg/BusyWrite", "SVGA_REG_BUSY writes."); + REG_CNT(&pThis->svga.StatRegCursorXWr, "VMSVGA/Reg/CursorXWrite", "SVGA_REG_CURSOR_X writes."); + REG_CNT(&pThis->svga.StatRegCursorYWr, "VMSVGA/Reg/CursorYWrite", "SVGA_REG_CURSOR_Y writes."); + REG_CNT(&pThis->svga.StatRegCursorIdWr, "VMSVGA/Reg/CursorIdWrite", "SVGA_REG_DEAD (SVGA_REG_CURSOR_ID) writes."); + REG_CNT(&pThis->svga.StatRegCursorOnWr, "VMSVGA/Reg/CursorOnWrite", "SVGA_REG_CURSOR_ON writes."); + REG_CNT(&pThis->svga.StatRegDepthWr, "VMSVGA/Reg/DepthWrite", "SVGA_REG_DEPTH writes."); + REG_CNT(&pThis->svga.StatRegDisplayHeightWr, "VMSVGA/Reg/DisplayHeightWrite", "SVGA_REG_DISPLAY_HEIGHT writes."); + REG_CNT(&pThis->svga.StatRegDisplayIdWr, "VMSVGA/Reg/DisplayIdWrite", "SVGA_REG_DISPLAY_ID writes."); + REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryWr, "VMSVGA/Reg/DisplayIsPrimaryWrite", "SVGA_REG_DISPLAY_IS_PRIMARY writes."); + REG_CNT(&pThis->svga.StatRegDisplayPositionXWr, "VMSVGA/Reg/DisplayPositionXWrite", "SVGA_REG_DISPLAY_POSITION_X writes."); + REG_CNT(&pThis->svga.StatRegDisplayPositionYWr, "VMSVGA/Reg/DisplayPositionYWrite", "SVGA_REG_DISPLAY_POSITION_Y writes."); + REG_CNT(&pThis->svga.StatRegDisplayWidthWr, "VMSVGA/Reg/DisplayWidthWrite", "SVGA_REG_DISPLAY_WIDTH writes."); + REG_CNT(&pThis->svga.StatRegEnableWr, "VMSVGA/Reg/EnableWrite", "SVGA_REG_ENABLE writes."); + REG_CNT(&pThis->svga.StatRegGmrIdWr, "VMSVGA/Reg/GmrIdWrite", "SVGA_REG_GMR_ID writes."); + REG_CNT(&pThis->svga.StatRegGuestIdWr, "VMSVGA/Reg/GuestIdWrite", "SVGA_REG_GUEST_ID writes."); + REG_CNT(&pThis->svga.StatRegHeightWr, "VMSVGA/Reg/HeightWrite", "SVGA_REG_HEIGHT writes."); + REG_CNT(&pThis->svga.StatRegIdWr, "VMSVGA/Reg/IdWrite", "SVGA_REG_ID writes."); + REG_CNT(&pThis->svga.StatRegIrqMaskWr, "VMSVGA/Reg/IrqMaskWrite", "SVGA_REG_IRQMASK writes."); + REG_CNT(&pThis->svga.StatRegNumDisplaysWr, "VMSVGA/Reg/NumDisplaysWrite", "SVGA_REG_NUM_DISPLAYS writes."); + REG_CNT(&pThis->svga.StatRegNumGuestDisplaysWr, "VMSVGA/Reg/NumGuestDisplaysWrite", "SVGA_REG_NUM_GUEST_DISPLAYS writes."); + REG_CNT(&pThis->svga.StatRegPaletteWr, "VMSVGA/Reg/PaletteWrite", "SVGA_PALETTE_XXXX writes."); + REG_CNT(&pThis->svga.StatRegPitchLockWr, "VMSVGA/Reg/PitchLockWrite", "SVGA_REG_PITCHLOCK writes."); + REG_CNT(&pThis->svga.StatRegPseudoColorWr, "VMSVGA/Reg/PseudoColorWrite", "SVGA_REG_PSEUDOCOLOR writes."); + REG_CNT(&pThis->svga.StatRegReadOnlyWr, "VMSVGA/Reg/ReadOnlyWrite", "Read-only SVGA_REG_XXXX writes."); + REG_CNT(&pThis->svga.StatRegScratchWr, "VMSVGA/Reg/ScratchWrite", "SVGA_REG_SCRATCH_XXXX writes."); + REG_CNT(&pThis->svga.StatRegSyncWr, "VMSVGA/Reg/SyncWrite", "SVGA_REG_SYNC writes."); + REG_CNT(&pThis->svga.StatRegTopWr, "VMSVGA/Reg/TopWrite", "SVGA_REG_TOP writes."); + REG_CNT(&pThis->svga.StatRegTracesWr, "VMSVGA/Reg/TracesWrite", "SVGA_REG_TRACES writes."); + REG_CNT(&pThis->svga.StatRegUnknownWr, "VMSVGA/Reg/UnknownWrite", "Writes to unknown register."); + REG_CNT(&pThis->svga.StatRegWidthWr, "VMSVGA/Reg/WidthWrite", "SVGA_REG_WIDTH writes."); + REG_CNT(&pThis->svga.StatRegCommandLowWr, "VMSVGA/Reg/CommandLowWrite", "SVGA_REG_COMMAND_LOW writes."); + REG_CNT(&pThis->svga.StatRegCommandHighWr, "VMSVGA/Reg/CommandHighWrite", "SVGA_REG_COMMAND_HIGH writes."); + REG_CNT(&pThis->svga.StatRegDevCapWr, "VMSVGA/Reg/DevCapWrite", "SVGA_REG_DEV_CAP writes."); + REG_CNT(&pThis->svga.StatRegCmdPrependLowWr, "VMSVGA/Reg/CmdPrependLowWrite", "SVGA_REG_CMD_PREPEND_LOW writes."); + REG_CNT(&pThis->svga.StatRegCmdPrependHighWr, "VMSVGA/Reg/CmdPrependHighWrite", "SVGA_REG_CMD_PREPEND_HIGH writes."); + + REG_CNT(&pThis->svga.StatRegBitsPerPixelRd, "VMSVGA/Reg/BitsPerPixelRead", "SVGA_REG_BITS_PER_PIXEL reads."); + REG_CNT(&pThis->svga.StatRegBlueMaskRd, "VMSVGA/Reg/BlueMaskRead", "SVGA_REG_BLUE_MASK reads."); + REG_CNT(&pThis->svga.StatRegBusyRd, "VMSVGA/Reg/BusyRead", "SVGA_REG_BUSY reads."); + REG_CNT(&pThis->svga.StatRegBytesPerLineRd, "VMSVGA/Reg/BytesPerLineRead", "SVGA_REG_BYTES_PER_LINE reads."); + REG_CNT(&pThis->svga.StatRegCapabilitesRd, "VMSVGA/Reg/CapabilitesRead", "SVGA_REG_CAPABILITIES reads."); + REG_CNT(&pThis->svga.StatRegConfigDoneRd, "VMSVGA/Reg/ConfigDoneRead", "SVGA_REG_CONFIG_DONE reads."); + REG_CNT(&pThis->svga.StatRegCursorXRd, "VMSVGA/Reg/CursorXRead", "SVGA_REG_CURSOR_X reads."); + REG_CNT(&pThis->svga.StatRegCursorYRd, "VMSVGA/Reg/CursorYRead", "SVGA_REG_CURSOR_Y reads."); + REG_CNT(&pThis->svga.StatRegCursorIdRd, "VMSVGA/Reg/CursorIdRead", "SVGA_REG_DEAD (SVGA_REG_CURSOR_ID) reads."); + REG_CNT(&pThis->svga.StatRegCursorOnRd, "VMSVGA/Reg/CursorOnRead", "SVGA_REG_CURSOR_ON reads."); + REG_CNT(&pThis->svga.StatRegDepthRd, "VMSVGA/Reg/DepthRead", "SVGA_REG_DEPTH reads."); + REG_CNT(&pThis->svga.StatRegDisplayHeightRd, "VMSVGA/Reg/DisplayHeightRead", "SVGA_REG_DISPLAY_HEIGHT reads."); + REG_CNT(&pThis->svga.StatRegDisplayIdRd, "VMSVGA/Reg/DisplayIdRead", "SVGA_REG_DISPLAY_ID reads."); + REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryRd, "VMSVGA/Reg/DisplayIsPrimaryRead", "SVGA_REG_DISPLAY_IS_PRIMARY reads."); + REG_CNT(&pThis->svga.StatRegDisplayPositionXRd, "VMSVGA/Reg/DisplayPositionXRead", "SVGA_REG_DISPLAY_POSITION_X reads."); + REG_CNT(&pThis->svga.StatRegDisplayPositionYRd, "VMSVGA/Reg/DisplayPositionYRead", "SVGA_REG_DISPLAY_POSITION_Y reads."); + REG_CNT(&pThis->svga.StatRegDisplayWidthRd, "VMSVGA/Reg/DisplayWidthRead", "SVGA_REG_DISPLAY_WIDTH reads."); + REG_CNT(&pThis->svga.StatRegEnableRd, "VMSVGA/Reg/EnableRead", "SVGA_REG_ENABLE reads."); + REG_CNT(&pThis->svga.StatRegFbOffsetRd, "VMSVGA/Reg/FbOffsetRead", "SVGA_REG_FB_OFFSET reads."); + REG_CNT(&pThis->svga.StatRegFbSizeRd, "VMSVGA/Reg/FbSizeRead", "SVGA_REG_FB_SIZE reads."); + REG_CNT(&pThis->svga.StatRegFbStartRd, "VMSVGA/Reg/FbStartRead", "SVGA_REG_FB_START reads."); + REG_CNT(&pThis->svga.StatRegGmrIdRd, "VMSVGA/Reg/GmrIdRead", "SVGA_REG_GMR_ID reads."); + REG_CNT(&pThis->svga.StatRegGmrMaxDescriptorLengthRd, "VMSVGA/Reg/GmrMaxDescriptorLengthRead", "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH reads."); + REG_CNT(&pThis->svga.StatRegGmrMaxIdsRd, "VMSVGA/Reg/GmrMaxIdsRead", "SVGA_REG_GMR_MAX_IDS reads."); + REG_CNT(&pThis->svga.StatRegGmrsMaxPagesRd, "VMSVGA/Reg/GmrsMaxPagesRead", "SVGA_REG_GMRS_MAX_PAGES reads."); + REG_CNT(&pThis->svga.StatRegGreenMaskRd, "VMSVGA/Reg/GreenMaskRead", "SVGA_REG_GREEN_MASK reads."); + REG_CNT(&pThis->svga.StatRegGuestIdRd, "VMSVGA/Reg/GuestIdRead", "SVGA_REG_GUEST_ID reads."); + REG_CNT(&pThis->svga.StatRegHeightRd, "VMSVGA/Reg/HeightRead", "SVGA_REG_HEIGHT reads."); + REG_CNT(&pThis->svga.StatRegHostBitsPerPixelRd, "VMSVGA/Reg/HostBitsPerPixelRead", "SVGA_REG_HOST_BITS_PER_PIXEL reads."); + REG_CNT(&pThis->svga.StatRegIdRd, "VMSVGA/Reg/IdRead", "SVGA_REG_ID reads."); + REG_CNT(&pThis->svga.StatRegIrqMaskRd, "VMSVGA/Reg/IrqMaskRead", "SVGA_REG_IRQ_MASK reads."); + REG_CNT(&pThis->svga.StatRegMaxHeightRd, "VMSVGA/Reg/MaxHeightRead", "SVGA_REG_MAX_HEIGHT reads."); + REG_CNT(&pThis->svga.StatRegMaxWidthRd, "VMSVGA/Reg/MaxWidthRead", "SVGA_REG_MAX_WIDTH reads."); + REG_CNT(&pThis->svga.StatRegMemorySizeRd, "VMSVGA/Reg/MemorySizeRead", "SVGA_REG_MEMORY_SIZE reads."); + REG_CNT(&pThis->svga.StatRegMemRegsRd, "VMSVGA/Reg/MemRegsRead", "SVGA_REG_MEM_REGS reads."); + REG_CNT(&pThis->svga.StatRegMemSizeRd, "VMSVGA/Reg/MemSizeRead", "SVGA_REG_MEM_SIZE reads."); + REG_CNT(&pThis->svga.StatRegMemStartRd, "VMSVGA/Reg/MemStartRead", "SVGA_REG_MEM_START reads."); + REG_CNT(&pThis->svga.StatRegNumDisplaysRd, "VMSVGA/Reg/NumDisplaysRead", "SVGA_REG_NUM_DISPLAYS reads."); + REG_CNT(&pThis->svga.StatRegNumGuestDisplaysRd, "VMSVGA/Reg/NumGuestDisplaysRead", "SVGA_REG_NUM_GUEST_DISPLAYS reads."); + REG_CNT(&pThis->svga.StatRegPaletteRd, "VMSVGA/Reg/PaletteRead", "SVGA_REG_PLAETTE_XXXX reads."); + REG_CNT(&pThis->svga.StatRegPitchLockRd, "VMSVGA/Reg/PitchLockRead", "SVGA_REG_PITCHLOCK reads."); + REG_CNT(&pThis->svga.StatRegPsuedoColorRd, "VMSVGA/Reg/PsuedoColorRead", "SVGA_REG_PSEUDOCOLOR reads."); + REG_CNT(&pThis->svga.StatRegRedMaskRd, "VMSVGA/Reg/RedMaskRead", "SVGA_REG_RED_MASK reads."); + REG_CNT(&pThis->svga.StatRegScratchRd, "VMSVGA/Reg/ScratchRead", "SVGA_REG_SCRATCH reads."); + REG_CNT(&pThis->svga.StatRegScratchSizeRd, "VMSVGA/Reg/ScratchSizeRead", "SVGA_REG_SCRATCH_SIZE reads."); + REG_CNT(&pThis->svga.StatRegSyncRd, "VMSVGA/Reg/SyncRead", "SVGA_REG_SYNC reads."); + REG_CNT(&pThis->svga.StatRegTopRd, "VMSVGA/Reg/TopRead", "SVGA_REG_TOP reads."); + REG_CNT(&pThis->svga.StatRegTracesRd, "VMSVGA/Reg/TracesRead", "SVGA_REG_TRACES reads."); + REG_CNT(&pThis->svga.StatRegUnknownRd, "VMSVGA/Reg/UnknownRead", "SVGA_REG_UNKNOWN reads."); + REG_CNT(&pThis->svga.StatRegVramSizeRd, "VMSVGA/Reg/VramSizeRead", "SVGA_REG_VRAM_SIZE reads."); + REG_CNT(&pThis->svga.StatRegWidthRd, "VMSVGA/Reg/WidthRead", "SVGA_REG_WIDTH reads."); + REG_CNT(&pThis->svga.StatRegWriteOnlyRd, "VMSVGA/Reg/WriteOnlyRead", "Write-only SVGA_REG_XXXX reads."); + REG_CNT(&pThis->svga.StatRegCommandLowRd, "VMSVGA/Reg/CommandLowRead", "SVGA_REG_COMMAND_LOW reads."); + REG_CNT(&pThis->svga.StatRegCommandHighRd, "VMSVGA/Reg/CommandHighRead", "SVGA_REG_COMMAND_HIGH reads."); + REG_CNT(&pThis->svga.StatRegMaxPrimBBMemRd, "VMSVGA/Reg/MaxPrimBBMemRead", "SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM reads."); + REG_CNT(&pThis->svga.StatRegGBMemSizeRd, "VMSVGA/Reg/GBMemSizeRead", "SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB reads."); + REG_CNT(&pThis->svga.StatRegDevCapRd, "VMSVGA/Reg/DevCapRead", "SVGA_REG_DEV_CAP reads."); + REG_CNT(&pThis->svga.StatRegCmdPrependLowRd, "VMSVGA/Reg/CmdPrependLowRead", "SVGA_REG_CMD_PREPEND_LOW reads."); + REG_CNT(&pThis->svga.StatRegCmdPrependHighRd, "VMSVGA/Reg/CmdPrependHighRead", "SVGA_REG_CMD_PREPEND_HIGH reads."); + REG_CNT(&pThis->svga.StatRegScrnTgtMaxWidthRd, "VMSVGA/Reg/ScrnTgtMaxWidthRead", "SVGA_REG_SCREENTARGET_MAX_WIDTH reads."); + REG_CNT(&pThis->svga.StatRegScrnTgtMaxHeightRd, "VMSVGA/Reg/ScrnTgtMaxHeightRead", "SVGA_REG_SCREENTARGET_MAX_HEIGHT reads."); + REG_CNT(&pThis->svga.StatRegMobMaxSizeRd, "VMSVGA/Reg/MobMaxSizeRead", "SVGA_REG_MOB_MAX_SIZE reads."); + + REG_PRF(&pSVGAState->StatBusyDelayEmts, "VMSVGA/EmtDelayOnBusyFifo", "Time we've delayed EMTs because of busy FIFO thread."); + REG_CNT(&pSVGAState->StatFifoCommands, "VMSVGA/FifoCommands", "FIFO command counter."); + REG_CNT(&pSVGAState->StatFifoErrors, "VMSVGA/FifoErrors", "FIFO error counter."); + REG_CNT(&pSVGAState->StatFifoUnkCmds, "VMSVGA/FifoUnknownCommands", "FIFO unknown command counter."); + REG_CNT(&pSVGAState->StatFifoTodoTimeout, "VMSVGA/FifoTodoTimeout", "Number of times we discovered pending work after a wait timeout."); + REG_CNT(&pSVGAState->StatFifoTodoWoken, "VMSVGA/FifoTodoWoken", "Number of times we discovered pending work after being woken up."); + REG_PRF(&pSVGAState->StatFifoStalls, "VMSVGA/FifoStalls", "Profiling of FIFO stalls (waiting for guest to finish copying data)."); + REG_PRF(&pSVGAState->StatFifoExtendedSleep, "VMSVGA/FifoExtendedSleep", "Profiling FIFO sleeps relying on the refresh timer and/or access handler."); +# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS) + REG_CNT(&pSVGAState->StatFifoAccessHandler, "VMSVGA/FifoAccessHandler", "Number of times the FIFO access handler triggered."); +# endif + REG_CNT(&pSVGAState->StatFifoCursorFetchAgain, "VMSVGA/FifoCursorFetchAgain", "Times the cursor update counter changed while reading."); + REG_CNT(&pSVGAState->StatFifoCursorNoChange, "VMSVGA/FifoCursorNoChange", "No cursor position change event though the update counter was modified."); + REG_CNT(&pSVGAState->StatFifoCursorPosition, "VMSVGA/FifoCursorPosition", "Cursor position and visibility changes."); + REG_CNT(&pSVGAState->StatFifoCursorVisiblity, "VMSVGA/FifoCursorVisiblity", "Cursor visibility changes."); + REG_CNT(&pSVGAState->StatFifoWatchdogWakeUps, "VMSVGA/FifoWatchdogWakeUps", "Number of times the FIFO refresh poller/watchdog woke up the FIFO thread."); + +# undef REG_CNT +# undef REG_PRF + + /* + * Info handlers. + */ + PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga", "Basic VMSVGA device state details", vmsvgaR3Info); +# ifdef VBOX_WITH_VMSVGA3D + PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dctx", "VMSVGA 3d context details. Accepts 'terse'.", vmsvgaR3Info3dContext); + PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsfc", + "VMSVGA 3d surface details. " + "Accepts 'terse', 'invy', and one of 'tiny', 'medium', 'normal', 'big', 'huge', or 'gigantic'.", + vmsvgaR3Info3dSurface); + PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsurf", + "VMSVGA 3d surface details and bitmap: " + "sid[>dir]", + vmsvgaR3Info3dSurfaceBmp); +# endif + + return VINF_SUCCESS; +} + +/* Initialize 3D backend, set device capabilities and call pfnPowerOn callback of 3D backend. + * + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param fLoadState Whether saved state is being loaded. + */ +static void vmsvgaR3PowerOnDevice(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, bool fLoadState) +{ +# ifdef VBOX_WITH_VMSVGA3D + if (pThis->svga.f3DEnabled) + { + /* Load a 3D backend. */ + int rc = vmsvgaR3Init3dInterfaces(pDevIns, pThis, pThisCC); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dInit -> %Rrc)\n", rc)); + pThis->svga.f3DEnabled = false; + } + } +# endif + +# if defined(VBOX_WITH_VMSVGA3D) && defined(RT_OS_LINUX) + if (pThis->svga.f3DEnabled) + { + /* The FIFO thread may use X API for accelerated screen output. */ + /* This must be done after backend initialization by vmsvgaR3Init3dInterfaces, + * because it dynamically resolves XInitThreads. + */ + XInitThreads(); + } +# endif + + if (!fLoadState) + { + vmsvgaR3InitFIFO(pThis, pThisCC); + vmsvgaR3GetCaps(pThis, pThisCC, &pThis->svga.u32DeviceCaps, &pThis->svga.u32DeviceCaps2, &pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES]); + } +# ifdef DEBUG + else + { + /* If saved state is being loaded then FIFO and caps are already restored. */ + uint32_t u32DeviceCaps = 0; + uint32_t u32DeviceCaps2 = 0; + uint32_t u32FIFOCaps = 0; + vmsvgaR3GetCaps(pThis, pThisCC, &u32DeviceCaps, &u32DeviceCaps2, &u32FIFOCaps); + + /* Capabilities should not change normally. + * However the saved state might have a subset of currently implemented caps. + */ + Assert( (pThis->svga.u32DeviceCaps & u32DeviceCaps) == pThis->svga.u32DeviceCaps + && (pThis->svga.u32DeviceCaps2 & u32DeviceCaps2) == pThis->svga.u32DeviceCaps2 + && (pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES] & u32FIFOCaps) == pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES]); + } +#endif + +# ifdef VBOX_WITH_VMSVGA3D + if (pThis->svga.f3DEnabled) + { + PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; + int rc = pSVGAState->pFuncs3D->pfnPowerOn(pDevIns, pThis, pThisCC); + if (RT_SUCCESS(rc)) + { + /* Initialize FIFO 3D capabilities. */ + vmsvgaR3InitFifo3DCaps(pThis, pThisCC); + } + else + { + LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dPowerOn -> %Rrc)\n", rc)); + pThis->svga.f3DEnabled = false; + } + } +# else /* !VBOX_WITH_VMSVGA3D */ + RT_NOREF(pDevIns); +# endif /* !VBOX_WITH_VMSVGA3D */ +} + + +/** + * Power On notification. + * + * @param pDevIns The device instance data. + * + * @remarks Caller enters the device critical section. + */ +DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + + vmsvgaR3PowerOnDevice(pDevIns, pThis, pThisCC, /*fLoadState=*/ false); +} + +/** + * Power Off notification. + * + * @param pDevIns The device instance data. + * + * @remarks Caller enters the device critical section. + */ +DECLCALLBACK(void) vmsvgaR3PowerOff(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + + /* + * Notify the FIFO thread. + */ + if (pThisCC->svga.pFIFOIOThread) + { + /* Hack around a deadlock: + * - the caller holds the device critsect; + * - FIFO thread may attempt to enter the critsect too (when raising an IRQ). + */ + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + + int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_POWEROFF, + NULL /*pvParam*/, 30000 /*ms*/); + AssertLogRelRC(rc); + + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + } +} + +#endif /* IN_RING3 */ diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA.h b/src/VBox/Devices/Graphics/DevVGA-SVGA.h new file mode 100644 index 00000000..c73c7e72 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA.h @@ -0,0 +1,674 @@ +/* $Id: DevVGA-SVGA.h $ */ +/** @file + * VMware SVGA device + */ +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifndef VBOX_WITH_VMSVGA +# error "VBOX_WITH_VMSVGA is not defined" +#endif + +#define VMSVGA_USE_EMT_HALT_CODE + +#include +#include +#include +#include +#ifdef VMSVGA_USE_EMT_HALT_CODE +# include +# include +#endif + +#include +#include + + +/* + * PCI device IDs. + */ +#ifndef PCI_VENDOR_ID_VMWARE +# define PCI_VENDOR_ID_VMWARE 0x15AD +#endif +#ifndef PCI_DEVICE_ID_VMWARE_SVGA2 +# define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 +#endif + +/* For "svga_overlay.h" */ +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +/* VMSVGA headers. */ +#include "vmsvga_headers_begin.h" +#pragma pack(1) /* VMSVGA structures are '__packed'. */ +#include +#include +#include +#include +#include +#pragma pack() +#include "vmsvga_headers_end.h" + +/**@def FLOAT_FMT_STR + * Format string bits to go with FLOAT_FMT_ARGS. */ +#define FLOAT_FMT_STR "%s%u.%06u" +/** @def FLOAT_FMT_ARGS + * Format arguments for a float value, corresponding to FLOAT_FMT_STR. + * @param r The floating point value to format. */ +#define FLOAT_FMT_ARGS(r) (r) >= 0.0f ? "" : "-", (unsigned)RT_ABS(r) \ + , (unsigned)(RT_ABS((r) - (float)(unsigned)(r)) * 1000000.0f) + +/* Deprecated commands. They are not included in the VMSVGA headers anymore. */ +#define SVGA_CMD_RECT_FILL 2 +#define SVGA_CMD_DISPLAY_CURSOR 20 +#define SVGA_CMD_MOVE_CURSOR 21 + +/* + * SVGA_CMD_RECT_FILL -- + * + * Fill a rectangular area in the the GFB, and copy the result + * to any screens which intersect it. + * + * Deprecated? + * + * Availability: + * SVGA_CAP_RECT_FILL + */ + +typedef +struct { + uint32_t pixel; + uint32_t destX; + uint32_t destY; + uint32_t width; + uint32_t height; +} SVGAFifoCmdRectFill; + +/* + * SVGA_CMD_DISPLAY_CURSOR -- + * + * Turn the cursor on or off. + * + * Deprecated. + * + * Availability: + * SVGA_CAP_CURSOR? + */ + +typedef +struct { + uint32_t id; // Reserved, must be zero. + uint32_t state; // 0=off +} SVGAFifoCmdDisplayCursor; + +/* + * SVGA_CMD_MOVE_CURSOR -- + * + * Set the cursor position. + * + * Deprecated. + * + * Availability: + * SVGA_CAP_CURSOR? + */ + +typedef +struct { + SVGASignedPoint pos; +} SVGAFifoCmdMoveCursor; + + +/** Default FIFO size. */ +#define VMSVGA_FIFO_SIZE _2M +/** The old FIFO size. */ +#define VMSVGA_FIFO_SIZE_OLD _128K + +/** Default scratch region size. */ +#define VMSVGA_SCRATCH_SIZE 0x100 +/** Surface memory available to the guest. */ +#define VMSVGA_SURFACE_SIZE (512*1024*1024) +/** Maximum GMR pages. */ +#define VMSVGA_MAX_GMR_PAGES 0x100000 +/** Maximum nr of GMR ids. */ +#define VMSVGA_MAX_GMR_IDS _8K +/** Maximum number of GMR descriptors. */ +#define VMSVGA_MAX_GMR_DESC_LOOP_COUNT VMSVGA_MAX_GMR_PAGES + +#define VMSVGA_VAL_UNINITIALIZED (unsigned)-1 + +/** For validating X and width values. + * The code assumes it's at least an order of magnitude less than UINT32_MAX. */ +#define VMSVGA_MAX_X _1M +/** For validating Y and height values. + * The code assumes it's at least an order of magnitude less than UINT32_MAX. */ +#define VMSVGA_MAX_Y _1M + +/* u32ActionFlags */ +#define VMSVGA_ACTION_CHANGEMODE_BIT 0 +#define VMSVGA_ACTION_CHANGEMODE RT_BIT(VMSVGA_ACTION_CHANGEMODE_BIT) + + +#ifdef DEBUG +/* Enable to log FIFO register accesses. */ +//# define DEBUG_FIFO_ACCESS +/* Enable to log GMR page accesses. */ +//# define DEBUG_GMR_ACCESS +#endif + +#define VMSVGA_FIFO_EXTCMD_NONE 0 +#define VMSVGA_FIFO_EXTCMD_TERMINATE 1 +#define VMSVGA_FIFO_EXTCMD_SAVESTATE 2 +#define VMSVGA_FIFO_EXTCMD_LOADSTATE 3 +#define VMSVGA_FIFO_EXTCMD_RESET 4 +#define VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS 5 +#define VMSVGA_FIFO_EXTCMD_POWEROFF 6 + +/** Size of the region to backup when switching into svga mode. */ +#define VMSVGA_VGA_FB_BACKUP_SIZE _512K + +/** @def VMSVGA_WITH_VGA_FB_BACKUP + * Enables correct VGA MMIO read/write handling when VMSVGA is enabled. It + * is SLOW and probably not entirely right, but it helps with getting 3dmark + * output and other stuff. */ +#define VMSVGA_WITH_VGA_FB_BACKUP 1 + +/** @def VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 + * defined(VMSVGA_WITH_VGA_FB_BACKUP) && defined(IN_RING3) */ +#if (defined(VMSVGA_WITH_VGA_FB_BACKUP) && defined(IN_RING3)) || defined(DOXYGEN_RUNNING) +# define VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 1 +#else +# undef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 +#endif + +/** @def VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ + * defined(VMSVGA_WITH_VGA_FB_BACKUP) && !defined(IN_RING3) */ +#if (defined(VMSVGA_WITH_VGA_FB_BACKUP) && !defined(IN_RING3)) || defined(DOXYGEN_RUNNING) +# define VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ 1 +#else +# undef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ +#endif + + +typedef struct +{ + PSSMHANDLE pSSM; + uint32_t uVersion; + uint32_t uPass; +} VMSVGA_STATE_LOAD; +typedef VMSVGA_STATE_LOAD *PVMSVGA_STATE_LOAD; + +/** Host screen viewport. + * (4th quadrant with negated Y values - usual Windows and X11 world view.) */ +typedef struct VMSVGAVIEWPORT +{ + uint32_t x; /**< x coordinate (left). */ + uint32_t y; /**< y coordinate (top). */ + uint32_t cx; /**< width. */ + uint32_t cy; /**< height. */ + /** Right side coordinate (exclusive). Same as x + cx. */ + uint32_t xRight; + /** First quadrant low y coordinate. + * Same as y + cy - 1 in window coordinates. */ + uint32_t yLowWC; + /** First quadrant high y coordinate (exclusive) - yLowWC + cy. + * Same as y - 1 in window coordinates. */ + uint32_t yHighWC; + /** Alignment padding. */ + uint32_t uAlignment; +} VMSVGAVIEWPORT; + +#ifdef VBOX_WITH_VMSVGA3D +typedef struct VMSVGAHWSCREEN *PVMSVGAHWSCREEN; +#endif + +/** + * Screen object state. + */ +typedef struct VMSVGASCREENOBJECT +{ + /** SVGA_SCREEN_* flags. */ + uint32_t fuScreen; + /** The screen object id. */ + uint32_t idScreen; + /** The screen dimensions. */ + int32_t xOrigin; + int32_t yOrigin; + uint32_t cWidth; + uint32_t cHeight; + /** Offset of the screen buffer in the guest VRAM. */ + uint32_t offVRAM; + /** Scanline pitch. */ + uint32_t cbPitch; + /** Bits per pixel. */ + uint32_t cBpp; + /** The physical DPI that the guest expects for this screen. Zero, if the guest is not DPI aware. */ + uint32_t cDpi; + bool fDefined; + bool fModified; + void *pvScreenBitmap; +#ifdef VBOX_WITH_VMSVGA3D + /** Pointer to the HW accelerated (3D) screen data. */ + R3PTRTYPE(PVMSVGAHWSCREEN) pHwScreen; +#endif +} VMSVGASCREENOBJECT; + +/** Pointer to the private VMSVGA ring-3 state structure. + * @todo Still not entirely satisfired with the type name, but better than + * the previous lower/upper case only distinction. */ +typedef struct VMSVGAR3STATE *PVMSVGAR3STATE; +/** Pointer to the private (implementation specific) VMSVGA3d state. */ +typedef struct VMSVGA3DSTATE *PVMSVGA3DSTATE; + + +/** + * The VMSVGA device state. + * + * This instantatiated as VGASTATE::svga. + */ +typedef struct VMSVGAState +{ + /** Guest physical address of the FIFO memory range. */ + RTGCPHYS GCPhysFIFO; + /** Size in bytes of the FIFO memory range. + * This may be smaller than cbFIFOConfig after restoring an old VM state. */ + uint32_t cbFIFO; + /** The configured FIFO size. */ + uint32_t cbFIFOConfig; + /** SVGA id. */ + uint32_t u32SVGAId; + /** SVGA extensions enabled or not. */ + uint32_t fEnabled; + /** SVGA memory area configured status. */ + uint32_t fConfigured; + /** Device is busy handling FIFO requests (VMSVGA_BUSY_F_FIFO, + * VMSVGA_BUSY_F_EMT_FORCE). */ + uint32_t volatile fBusy; +#define VMSVGA_BUSY_F_FIFO RT_BIT_32(0) /**< The normal true/false busy FIFO bit. */ +#define VMSVGA_BUSY_F_EMT_FORCE RT_BIT_32(1) /**< Bit preventing race status flickering when EMT kicks the FIFO thread. */ + /** Traces (dirty page detection) enabled or not. */ + uint32_t fTraces; + /** Guest OS identifier. */ + uint32_t u32GuestId; + /** Scratch region size (VMSVGAState::au32ScratchRegion). */ + uint32_t cScratchRegion; + /** Irq status. */ + uint32_t u32IrqStatus; + /** Irq mask. */ + uint32_t u32IrqMask; + /** Pitch lock. */ + uint32_t u32PitchLock; + /** Current GMR id. (SVGA_REG_GMR_ID) */ + uint32_t u32CurrentGMRId; + /** SVGA device capabilities. */ + uint32_t u32DeviceCaps; + uint32_t u32DeviceCaps2; /* Used to be I/O port base address and Padding0. */ + /** Guest driver information (SVGA_REG_GUEST_DRIVER_*). */ + uint32_t u32GuestDriverId; + uint32_t u32GuestDriverVer1; + uint32_t u32GuestDriverVer2; + uint32_t u32GuestDriverVer3; + /** Port io index register. */ + uint32_t u32IndexReg; + /** FIFO request semaphore. */ + SUPSEMEVENT hFIFORequestSem; + /** The last seen SVGA_FIFO_CURSOR_COUNT value. + * Used by the FIFO thread and its watchdog. */ + uint32_t uLastCursorUpdateCount; + /** Indicates that the FIFO thread is sleeping and might need waking up. */ + bool volatile fFIFOThreadSleeping; + /** The legacy GFB mode registers. If used, they correspond to screen 0. */ + /** True when the guest modifies the GFB mode registers. */ + bool fGFBRegisters; + /** SVGA 3D overlay enabled or not. */ + bool f3DOverlayEnabled; + /** Indicates that the guest behaves incorrectly. */ + bool volatile fBadGuest; + bool afPadding[4]; + uint32_t uWidth; + uint32_t uHeight; + uint32_t uBpp; + uint32_t cbScanline; + uint32_t uHostBpp; + /** Maximum width supported. */ + uint32_t u32MaxWidth; + /** Maximum height supported. */ + uint32_t u32MaxHeight; + /** Viewport rectangle, i.e. what's currently visible of the target host + * window. This is usually (0,0)(uWidth,uHeight), but if the window is + * shrunk and scrolling applied, both the origin and size may differ. */ + VMSVGAVIEWPORT viewport; + /** Action flags */ + uint32_t u32ActionFlags; + /** SVGA 3d extensions enabled or not. */ + bool f3DEnabled; + /** VRAM page monitoring enabled or not. */ + bool fVRAMTracking; + /** External command to be executed in the FIFO thread. */ + uint8_t volatile u8FIFOExtCommand; + /** Set by vmsvgaR3RunExtCmdOnFifoThread when it temporarily resumes the FIFO + * thread and does not want it do anything but the command. */ + bool volatile fFifoExtCommandWakeup; +#ifdef DEBUG_GMR_ACCESS + /** GMR debug access handler type handle. */ + PGMPHYSHANDLERTYPE hGmrAccessHandlerType; +#endif +#if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS) + /** FIFO debug access handler type handle. */ + PGMPHYSHANDLERTYPE hFifoAccessHandlerType; +#endif + /** Number of GMRs (VMSVGA_MAX_GMR_IDS, count of elements in VMSVGAR3STATE::paGMR array). */ + uint32_t cGMR; + uint32_t uScreenOffset; /* Used only for loading older saved states. */ + + /** Legacy cursor state. */ + uint32_t uCursorX; + uint32_t uCursorY; + uint32_t uCursorID; + uint32_t uCursorOn; + + /** Scratch array. + * Putting this at the end since it's big it probably not . */ + uint32_t au32ScratchRegion[VMSVGA_SCRATCH_SIZE]; + + /** Array of SVGA3D_DEVCAP values, which are accessed via SVGA_REG_DEV_CAP. */ + uint32_t au32DevCaps[SVGA3D_DEVCAP_MAX]; + /** Index written to the SVGA_REG_DEV_CAP register. */ + uint32_t u32DevCapIndex; + /** Low 32 bit of a command buffer address written to the SVGA_REG_COMMAND_LOW register. */ + uint32_t u32RegCommandLow; + /** High 32 bit of a command buffer address written to the SVGA_REG_COMMAND_HIGH register. */ + uint32_t u32RegCommandHigh; + + STAMCOUNTER StatRegBitsPerPixelWr; + STAMCOUNTER StatRegBusyWr; + STAMCOUNTER StatRegCursorXWr; + STAMCOUNTER StatRegCursorYWr; + STAMCOUNTER StatRegCursorIdWr; + STAMCOUNTER StatRegCursorOnWr; + STAMCOUNTER StatRegDepthWr; + STAMCOUNTER StatRegDisplayHeightWr; + STAMCOUNTER StatRegDisplayIdWr; + STAMCOUNTER StatRegDisplayIsPrimaryWr; + STAMCOUNTER StatRegDisplayPositionXWr; + STAMCOUNTER StatRegDisplayPositionYWr; + STAMCOUNTER StatRegDisplayWidthWr; + STAMCOUNTER StatRegEnableWr; + STAMCOUNTER StatRegGmrIdWr; + STAMCOUNTER StatRegGuestIdWr; + STAMCOUNTER StatRegHeightWr; + STAMCOUNTER StatRegIdWr; + STAMCOUNTER StatRegIrqMaskWr; + STAMCOUNTER StatRegNumDisplaysWr; + STAMCOUNTER StatRegNumGuestDisplaysWr; + STAMCOUNTER StatRegPaletteWr; + STAMCOUNTER StatRegPitchLockWr; + STAMCOUNTER StatRegPseudoColorWr; + STAMCOUNTER StatRegReadOnlyWr; + STAMCOUNTER StatRegScratchWr; + STAMCOUNTER StatRegSyncWr; + STAMCOUNTER StatRegTopWr; + STAMCOUNTER StatRegTracesWr; + STAMCOUNTER StatRegUnknownWr; + STAMCOUNTER StatRegWidthWr; + STAMCOUNTER StatRegCommandLowWr; + STAMCOUNTER StatRegCommandHighWr; + STAMCOUNTER StatRegDevCapWr; + STAMCOUNTER StatRegCmdPrependLowWr; + STAMCOUNTER StatRegCmdPrependHighWr; + + STAMCOUNTER StatRegBitsPerPixelRd; + STAMCOUNTER StatRegBlueMaskRd; + STAMCOUNTER StatRegBusyRd; + STAMCOUNTER StatRegBytesPerLineRd; + STAMCOUNTER StatRegCapabilitesRd; + STAMCOUNTER StatRegConfigDoneRd; + STAMCOUNTER StatRegCursorXRd; + STAMCOUNTER StatRegCursorYRd; + STAMCOUNTER StatRegCursorIdRd; + STAMCOUNTER StatRegCursorOnRd; + STAMCOUNTER StatRegDepthRd; + STAMCOUNTER StatRegDisplayHeightRd; + STAMCOUNTER StatRegDisplayIdRd; + STAMCOUNTER StatRegDisplayIsPrimaryRd; + STAMCOUNTER StatRegDisplayPositionXRd; + STAMCOUNTER StatRegDisplayPositionYRd; + STAMCOUNTER StatRegDisplayWidthRd; + STAMCOUNTER StatRegEnableRd; + STAMCOUNTER StatRegFbOffsetRd; + STAMCOUNTER StatRegFbSizeRd; + STAMCOUNTER StatRegFbStartRd; + STAMCOUNTER StatRegGmrIdRd; + STAMCOUNTER StatRegGmrMaxDescriptorLengthRd; + STAMCOUNTER StatRegGmrMaxIdsRd; + STAMCOUNTER StatRegGmrsMaxPagesRd; + STAMCOUNTER StatRegGreenMaskRd; + STAMCOUNTER StatRegGuestIdRd; + STAMCOUNTER StatRegHeightRd; + STAMCOUNTER StatRegHostBitsPerPixelRd; + STAMCOUNTER StatRegIdRd; + STAMCOUNTER StatRegIrqMaskRd; + STAMCOUNTER StatRegMaxHeightRd; + STAMCOUNTER StatRegMaxWidthRd; + STAMCOUNTER StatRegMemorySizeRd; + STAMCOUNTER StatRegMemRegsRd; + STAMCOUNTER StatRegMemSizeRd; + STAMCOUNTER StatRegMemStartRd; + STAMCOUNTER StatRegNumDisplaysRd; + STAMCOUNTER StatRegNumGuestDisplaysRd; + STAMCOUNTER StatRegPaletteRd; + STAMCOUNTER StatRegPitchLockRd; + STAMCOUNTER StatRegPsuedoColorRd; + STAMCOUNTER StatRegRedMaskRd; + STAMCOUNTER StatRegScratchRd; + STAMCOUNTER StatRegScratchSizeRd; + STAMCOUNTER StatRegSyncRd; + STAMCOUNTER StatRegTopRd; + STAMCOUNTER StatRegTracesRd; + STAMCOUNTER StatRegUnknownRd; + STAMCOUNTER StatRegVramSizeRd; + STAMCOUNTER StatRegWidthRd; + STAMCOUNTER StatRegWriteOnlyRd; + STAMCOUNTER StatRegCommandLowRd; + STAMCOUNTER StatRegCommandHighRd; + STAMCOUNTER StatRegMaxPrimBBMemRd; + STAMCOUNTER StatRegGBMemSizeRd; + STAMCOUNTER StatRegDevCapRd; + STAMCOUNTER StatRegCmdPrependLowRd; + STAMCOUNTER StatRegCmdPrependHighRd; + STAMCOUNTER StatRegScrnTgtMaxWidthRd; + STAMCOUNTER StatRegScrnTgtMaxHeightRd; + STAMCOUNTER StatRegMobMaxSizeRd; +} VMSVGAState, VMSVGASTATE; + + +/** + * The VMSVGA device state for ring-3 + * + * This instantatiated as VGASTATER3::svga. + */ +typedef struct VMSVGASTATER3 +{ + /** The R3 FIFO pointer. */ + R3PTRTYPE(uint32_t *) pau32FIFO; + /** R3 Opaque pointer to svga state. */ + R3PTRTYPE(PVMSVGAR3STATE) pSvgaR3State; + /** R3 Opaque pointer to 3d state. */ + R3PTRTYPE(PVMSVGA3DSTATE) p3dState; + /** The separate VGA frame buffer in svga mode. + * Unlike the the boch-based VGA device implementation, VMSVGA seems to have a + * separate frame buffer for VGA and allows concurrent use of both. The SVGA + * SDK is making use of this to do VGA text output while testing other things in + * SVGA mode, displaying the result by switching back to VGA text mode. So, + * when entering SVGA mode we copy the first part of the frame buffer here and + * direct VGA accesses here instead. It is copied back when leaving SVGA mode. */ + R3PTRTYPE(uint8_t *) pbVgaFrameBufferR3; + /** R3 Opaque pointer to an external fifo cmd parameter. */ + R3PTRTYPE(void * volatile) pvFIFOExtCmdParam; + + /** FIFO external command semaphore. */ + R3PTRTYPE(RTSEMEVENT) hFIFOExtCmdSem; + /** FIFO IO Thread. */ + R3PTRTYPE(PPDMTHREAD) pFIFOIOThread; +} VMSVGASTATER3; + + +/** + * The VMSVGA device state for ring-0 + * + * This instantatiated as VGASTATER0::svga. + */ +typedef struct VMSVGASTATER0 +{ + /** The R0 FIFO pointer. + * @note This only points to the _first_ _page_ of the FIFO! */ + R0PTRTYPE(uint32_t *) pau32FIFO; +} VMSVGASTATER0; + + +typedef struct VGAState *PVGASTATE; +typedef struct VGASTATER3 *PVGASTATER3; +typedef struct VGASTATER0 *PVGASTATER0; +typedef struct VGASTATERC *PVGASTATERC; +typedef CTX_SUFF(PVGASTATE) PVGASTATECC; + +DECLCALLBACK(int) vmsvgaR3PciIORegionFifoMapUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, + RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType); +DECLCALLBACK(VBOXSTRICTRC) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb); +DECLCALLBACK(VBOXSTRICTRC) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb); + +DECLCALLBACK(void) vmsvgaR3PortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t uScreenId, + uint32_t x, uint32_t y, uint32_t cx, uint32_t cy); +DECLCALLBACK(void) vmsvgaR3PortReportMonitorPositions(PPDMIDISPLAYPORT pInterface, uint32_t cPositions, PCRTPOINT paPositions); + +int vmsvgaR3Init(PPDMDEVINS pDevIns); +int vmsvgaR3Reset(PPDMDEVINS pDevIns); +int vmsvgaR3Destruct(PPDMDEVINS pDevIns); +int vmsvgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); +int vmsvgaR3LoadDone(PPDMDEVINS pDevIns); +int vmsvgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM); +DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns); +DECLCALLBACK(void) vmsvgaR3PowerOff(PPDMDEVINS pDevIns); +void vmsvgaR3FifoWatchdogTimer(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC); + +#ifdef IN_RING3 +VMSVGASCREENOBJECT *vmsvgaR3GetScreenObject(PVGASTATECC pThisCC, uint32_t idScreen); +int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h); +#endif + +int vmsvgaR3GmrTransfer(PVGASTATE pThis, PVGASTATECC pThisCC, const SVGA3dTransferType enmTransferType, + uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch, + SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch, + uint32_t cbWidth, uint32_t cHeight); + +void vmsvgaR3ClipCopyBox(const SVGA3dSize *pSizeSrc, const SVGA3dSize *pSizeDest, SVGA3dCopyBox *pBox); +void vmsvgaR3ClipBox(const SVGA3dSize *pSize, SVGA3dBox *pBox); +void vmsvgaR3ClipRect(SVGASignedRect const *pBound, SVGASignedRect *pRect); +void vmsvgaR3Clip3dRect(SVGA3dRect const *pBound, SVGA3dRect RT_UNTRUSTED_GUEST *pRect); + +/* + * GBO (Guest Backed Object). + * A GBO is a list of the guest pages. GBOs are used for VMSVGA MOBs (Memory OBjects) + * and Object Tables which the guest shares with the host. + * + * A GBO is similar to a GMR. Nevertheless I'll create a new code for GBOs in order + * to avoid tweaking and possibly breaking existing code. Moreover it will be probably possible to + * map the guest pages into the host R3 memory and access them directly. + */ + +/* GBO descriptor. */ +typedef struct VMSVGAGBODESCRIPTOR +{ + RTGCPHYS GCPhys; + uint64_t cPages; +} VMSVGAGBODESCRIPTOR, *PVMSVGAGBODESCRIPTOR; +typedef VMSVGAGBODESCRIPTOR const *PCVMSVGAGBODESCRIPTOR; + +/* GBO. + */ +typedef struct VMSVGAGBO +{ + uint32_t fGboFlags; + uint32_t cTotalPages; + uint32_t cbTotal; + uint32_t cDescriptors; + PVMSVGAGBODESCRIPTOR paDescriptors; + void *pvHost; /* Pointer to cbTotal bytes on the host if VMSVGAGBO_F_HOST_BACKED is set. */ +} VMSVGAGBO, *PVMSVGAGBO; +typedef VMSVGAGBO const *PCVMSVGAGBO; + +#define VMSVGAGBO_F_OBSOLETE_0x1 0x1 +#define VMSVGAGBO_F_HOST_BACKED 0x2 + +#define VMSVGA_IS_GBO_CREATED(a_Gbo) ((a_Gbo)->paDescriptors != NULL) + +int vmsvgaR3OTableReadSurface(PVMSVGAR3STATE pSvgaR3State, uint32_t sid, SVGAOTableSurfaceEntry *pEntrySurface); + +/* MOB is also a GBO. + */ +typedef struct VMSVGAMOB +{ + AVLU32NODECORE Core; /* Key is the mobid. */ + RTLISTNODE nodeLRU; + VMSVGAGBO Gbo; +} VMSVGAMOB, *PVMSVGAMOB; +typedef VMSVGAMOB const *PCVMSVGAMOB; + +PVMSVGAMOB vmsvgaR3MobGet(PVMSVGAR3STATE pSvgaR3State, SVGAMobId RT_UNTRUSTED_GUEST mobid); +int vmsvgaR3MobWrite(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob, uint32_t off, void const *pvData, uint32_t cbData); +int vmsvgaR3MobRead(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob, uint32_t off, void *pvData, uint32_t cbData); +int vmsvgaR3MobBackingStoreCreate(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob, uint32_t cbValid); +void vmsvgaR3MobBackingStoreDelete(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob); +int vmsvgaR3MobBackingStoreWriteToGuest(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob); +int vmsvgaR3MobBackingStoreReadFromGuest(PVMSVGAR3STATE pSvgaR3State, PVMSVGAMOB pMob); +void *vmsvgaR3MobBackingStorePtr(PVMSVGAMOB pMob, uint32_t off); + +DECLINLINE(uint32_t) vmsvgaR3MobSize(PVMSVGAMOB pMob) +{ + if (pMob) + return pMob->Gbo.cbTotal; + return 0; +} + +DECLINLINE(uint32_t) vmsvgaR3MobId(PVMSVGAMOB pMob) +{ + if (pMob) + return pMob->Core.Key; + return SVGA_ID_INVALID; +} + +#ifdef DEBUG_sunlover +#define DEBUG_BREAKPOINT_TEST() do { ASMBreakpoint(); } while (0) +#else +#define DEBUG_BREAKPOINT_TEST() do { } while (0) +#endif + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_h */ diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.h b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.h new file mode 100644 index 00000000..73c8ce5d --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.h @@ -0,0 +1,67 @@ +/* $Id: DevVGA-SVGA3d-cocoa.h $ */ +/** @file + * VirtualBox OpenGL Cocoa Window System Helper Implementation. + */ + +/* + * Copyright (C) 2014-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_cocoa_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_cocoa_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include +#include + +RT_C_DECLS_BEGIN + +#ifndef ___renderspu_cocoa_helper_h +ADD_COCOA_NATIVE_REF(NSView); +ADD_COCOA_NATIVE_REF(NSOpenGLContext); +#endif + +#ifdef IN_VMSVGA3DCOCOA +# define VMSVGA3DCOCOA_DECL(type) DECLEXPORT(type) +#else +# define VMSVGA3DCOCOA_DECL(type) DECLIMPORT(type) +#endif + +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaServiceRunLoop(void); +VMSVGA3DCOCOA_DECL(bool) vmsvga3dCocoaCreateViewAndContext(NativeNSViewRef *ppView, NativeNSOpenGLContextRef *ppCtx, + NativeNSViewRef pParentView, uint32_t cx, uint32_t cy, + NativeNSOpenGLContextRef pSharedCtx, bool fOtherProfile); +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaDestroyViewAndContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx); +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewInfo(PCDBGFINFOHLP pHlp, NativeNSViewRef pView); +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewSetPosition(NativeNSViewRef pView, NativeNSViewRef pParentView, int x, int y); +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewSetSize(NativeNSViewRef pView, int w, int h); +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewUpdateViewport(NativeNSViewRef pView); +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx); +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaSwapBuffers(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx); + +int ExplicitlyLoadVBoxSVGA3DObjC(bool fResolveAllImports, PRTERRINFO pErrInfo); + +RT_C_DECLS_END + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_cocoa_h */ + diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m new file mode 100644 index 00000000..b4750703 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m @@ -0,0 +1,947 @@ +/* $Id: DevVGA-SVGA3d-cocoa.m $ */ +/** @file + * VirtualBox OpenGL Cocoa Window System Helper Implementation. + * + * @remarks Inspired by HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m. + */ + +/* + * Copyright (C) 2009-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include "DevVGA-SVGA3d-cocoa.h" +#import +#undef PVM /* Stupid namespace pollution from outdated sys/param.h header file. */ +#import + +#include +#include +#include +#include +#include + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/** @def USE_NSOPENGLVIEW + * Define this to experiment with using NSOpenGLView instead + * of NSView. There are transparency issues with the former, + * so for the time being we're using the latter. */ +#if 0 || DOXYGEN_RUNNING +# define USE_NSOPENGLVIEW +#endif + +/**@def FLOAT_FMT_STR + * Format string bits to go with FLOAT_FMT_ARGS. */ +#define FLOAT_FMT_STR "%d.%06u" +/** @def FLOAT_FMT_ARGS + * Format arguments for a float value, corresponding to FLOAT_FMT_STR. + * @param r The floating point value to format. */ +#define FLOAT_FMT_ARGS(r) (int)(r), ((unsigned)(RT_ABS(r) * 1000000) % 1000000U) + + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * Argument package for doing this on the main thread. + */ +@interface VMSVGA3DCreateViewAndContext : NSObject +{ +@public + /* in */ + NativeNSViewRef pParentView; + uint32_t cx; + uint32_t cy; + NativeNSOpenGLContextRef pSharedCtx; + bool fOtherProfile; + + /* out */ + NativeNSViewRef pView; + NativeNSOpenGLContextRef pCtx; +} +@end + + +/** + * The overlay view. + */ +@interface VMSVGA3DOverlayView +#ifdef USE_NSOPENGLVIEW + : NSOpenGLView +#else + : NSView +#endif +{ +@private + /** This points to the parent view, if there is one. If there isn't a parent + * the view will be hidden and never used for displaying stuff. We only have + * one visible context per guest screen that is visible to the user and + * subject to buffer swapping. */ + NSView *m_pParentView; + /** Indicates that buffers (back+front) needs clearing before use because + * the view changed size. There are two buffers, so this is set to two + * each time when the view area increases. */ + uint32_t m_cClears; + /** Set if the OpenGL context needs updating after a resize. */ + bool m_fUpdateCtx; + +#ifndef USE_NSOPENGLVIEW + /** The OpenGL context associated with this view. */ + NSOpenGLContext *m_pCtx; + /** Number of times we've tried to set the view (shut up noisy NSLog). */ + uint32_t m_cSetViewAttempts; +#endif + + /** The desired view position relative to super. */ + NSPoint m_Pos; + /** The desired view size. */ + NSSize m_Size; +} ++ (void)createViewAndContext:(VMSVGA3DCreateViewAndContext *)pParams; +- (id)initWithFrameAndFormat:(NSRect)frame parentView:(NSView*)pparentView pixelFormat:(NSOpenGLPixelFormat *)pFmt; +- (void)vboxSetPos:(NSPoint)pos; +- (void)vboxSetSize:(NSSize)size; +- (void)vboxScheduleCtxUpdate; +- (void)vboxReshapePerform; +- (void)vboxReshape; +- (void)vboxBoundsDidChange:(NSNotification *)pNotification; +- (void)vboxFrameDidChange:(NSNotification *)pNotification; +- (void)vboxFrameDidChangeGlobal:(NSNotification *)pNotification; +- (BOOL)postsFrameChangedNotifications; +- (void)vboxRemoveFromSuperviewAndHide; +- (void)vboxUpdateCtxIfNecessary; +- (void)vboxClearBackBufferIfNecessary; +- (NSOpenGLContext *)makeCurrentGLContext; +- (void)restoreSavedGLContext:(NSOpenGLContext *)pSavedCtx; + +#ifndef USE_NSOPENGLVIEW +/* NSOpenGLView fakes: */ +- (void)setOpenGLContext:(NSOpenGLContext *)pCtx; +- (NSOpenGLContext *)openGLContext; +- (void)prepareOpenGL; + +#endif +/* Overridden: */ +- (void)viewDidMoveToWindow; +- (void)viewDidMoveToSuperview; +- (void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize; +- (void)drawRect:(NSRect)rect; + +@end + + +/******************************************************************************** +* +* VMSVGA3DOverlayView class implementation +* +********************************************************************************/ +@implementation VMSVGA3DOverlayView + + ++ (void)createViewAndContext:(VMSVGA3DCreateViewAndContext *)pParams +{ + LogFlow(("OvlView createViewAndContext:\n")); + + /* + * Create a pixel format. + */ + NSOpenGLPixelFormat *pFmt = nil; + + // Consider to remove it and check if it's harmless. + NSOpenGLPixelFormatAttribute attribs[] = + { + NSOpenGLPFAOpenGLProfile, (NSOpenGLPixelFormatAttribute)0, + //NSOpenGLPFAWindow, - obsolete/deprecated, try work without it... + NSOpenGLPFAAccelerated, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFABackingStore, + NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24, + NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute)8, + NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24, + 0 + }; + attribs[1] = pParams->fOtherProfile ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy; + pFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; + if (pFmt) + { + /* + * Create a new view. + */ + NSRect Frame; + Frame.origin.x = 0; + Frame.origin.y = 0; + Frame.size.width = pParams->cx < _1M && pParams->cx > 0 ? pParams->cx : 1; /* 'invalid drawable' if 0,0 size? */ + Frame.size.height = pParams->cy < _1M && pParams->cy > 0 ? pParams->cy : 1; + VMSVGA3DOverlayView *pView = [[VMSVGA3DOverlayView alloc] initWithFrameAndFormat:Frame + parentView:pParams->pParentView + pixelFormat:pFmt]; + if (pView) + { + /* + * If we have no shared GL context, we use the one that NSOpenGLView create. Otherwise, + * we replace it. (If we don't call openGLContext, it won't yet have been instantiated, + * so there is no unecessary contexts created here when pSharedCtx != NULL.) + */ + NSOpenGLContext *pCtx; +#ifdef USE_NSOPENGLVIEW + if (!pParams->pSharedCtx) + pCtx = [pView openGLContext]; + else +#endif + { + pCtx = [[NSOpenGLContext alloc] initWithFormat:pFmt shareContext: pParams->pSharedCtx]; + if (pCtx) + { + [pView setOpenGLContext:pCtx]; + [pCtx setView:pView]; +#ifdef USE_NSOPENGLVIEW + Assert([pCtx view] == pView); +#endif + } + } + if (pCtx) + { + /* + * Attach the view to the parent if we have one. Otherwise make sure its invisible. + */ + if (pParams->pParentView) + [pParams->pParentView addSubview:pView]; + else + [pView setHidden:YES]; + + /* + * Resize and return. + */ + //[pView vboxSetSize:Frame.size]; + + NSOpenGLContext *pSavedCtx = [pView makeCurrentGLContext]; + + [pView prepareOpenGL]; + GLint x; + //x = 0; [pCtx setValues:&x forParameter:NSOpenGLCPSwapInterval]; + //x = 1; [pCtx setValues:&x forParameter:NSOpenGLCPSurfaceOrder]; + x = 0; [pCtx setValues:&x forParameter:NSOpenGLCPSurfaceOpacity]; + + if (pParams->pParentView) + [pView setHidden:NO]; + else + [pView setHidden:YES]; + + [pView restoreSavedGLContext:pSavedCtx]; + + pParams->pView = pView; + pParams->pCtx = pCtx; + [pCtx retain]; //?? + + [pFmt release]; + + LogFlow(("OvlView createViewAndContext: returns successfully\n")); + return; + } + [pView release]; + } + [pFmt release]; + } + else + AssertFailed(); + + LogFlow(("OvlView createViewAndContext: returns failure\n")); + return; +} + +- (id)initWithFrameAndFormat:(NSRect) frame parentView:(NSView *)pParentView pixelFormat:(NSOpenGLPixelFormat *)pFmt +{ + LogFlow(("OvlView(%p) initWithFrameAndFormat:\n", (void *)self)); + + m_pParentView = pParentView; + /* Make some reasonable defaults */ + m_Pos = NSZeroPoint; + m_Size = frame.size; + m_cClears = 2; + m_fUpdateCtx = true; + +#ifdef USE_NSOPENGLVIEW + self = [super initWithFrame:frame pixelFormat:pFmt]; +#else + RT_NOREF(pFmt); + m_cSetViewAttempts = 0; + m_pCtx = NULL; + self = [super initWithFrame:frame]; +#endif + if (self) + { + //self.autoresizingMask = NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin; + self.autoresizingMask = NSViewNotSizable; + + /* + * Get notifications when we're moved or resized and when we're moved + * to a different screen or GPU or when the GL context simply needs updating. + */ + if (pParentView) + { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(vboxBoundsDidChange:) + name:NSViewBoundsDidChangeNotification + object:self]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(vboxFrameDidChange:) + name:NSViewFrameDidChangeNotification + object:self]; + //[[NSNotificationCenter defaultCenter] addObserver:self + // selector:@selector(vboxFrameDidChange:) + // name:NSViewDidUpdateTrackingAreasNotification + // object:self]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(vboxFrameDidChangeGlobal:) + name:NSViewGlobalFrameDidChangeNotification + object:self]; + } + } + LogFlow(("OvlView(%p) initWithFrameAndFormat: returns %p\n", (void *)self, (void *)self)); + return self; +} + +- (void)dealloc +{ + LogFlow(("OvlView(%p) dealloc:\n", (void *)self)); + +#ifdef USE_NSOPENGLVIEW + [[self openGLContext] clearDrawable]; +#else + if (m_pCtx) + { + [m_pCtx clearDrawable]; + [m_pCtx release]; + m_pCtx = nil; + } +#endif + + [super dealloc]; + + LogFlow(("OvlView(%p) dealloc: returns\n", (void *)self)); +} + + +- (void)vboxSetPos:(NSPoint)pos +{ + Log(("OvlView(%p) vboxSetPos: (%d,%d)\n", (void *)self, (int)pos.x, (int)pos.y)); + + m_Pos = pos; + [self vboxReshape]; + + LogFlow(("OvlView(%p) vboxSetPos: returns\n", (void *)self)); +} + + +- (void)vboxSetSize:(NSSize)size +{ + Log(("OvlView(%p) vboxSetSize: (%d,%d):\n", (void *)self, (int)size.width, (int)size.height)); + m_Size = size; + [self vboxReshape]; + LogFlow(("OvlView(%p) vboxSetSize: returns\n", (void *)self)); +} + +- (void)vboxScheduleCtxUpdate +{ + m_fUpdateCtx = true; +} + +- (void)vboxUpdateCtxIfNecessary +{ + if (m_fUpdateCtx) + { + Log(("OvlView(%p) vboxUpdateCtxIfNecessary: m_fUpdateCtx\n", (void *)self)); + /* This must be done on the main thread or it will crash with an error. */ + [[self openGLContext] performSelectorOnMainThread:@selector(update) withObject:nil waitUntilDone:YES]; + m_fUpdateCtx = false; + } +} + + +- (void)vboxClearBackBufferIfNecessary +{ +#if 1 /* experiment */ + if (m_cClears > 0) + { + Assert(![NSThread isMainThread]); + Assert([self openGLContext] == [NSOpenGLContext currentContext]); + Log(("OvlView(%p) vboxClearBackBufferIfNecessary: m_cClears=%d\n", (void *)self, m_cClears)); + m_cClears--; + + /* Clear errors. */ + GLenum rc; + while ((rc = glGetError()) != GL_NO_ERROR) + continue; + + /* Save the old buffer setting and make it GL_BACK (shall be GL_BACK already actually). */ + GLint iOldDrawBuf = GL_BACK; + glGetIntegerv(GL_DRAW_BUFFER, &iOldDrawBuf); + if (iOldDrawBuf != GL_BACK) + glDrawBuffer(GL_BACK); + while ((rc = glGetError()) != GL_NO_ERROR) + AssertMsgFailed(("rc=%x\n", rc)); + + /* Clear the current GL_BACK. */ + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT /*|GL_DEPTH_BUFFER_BIT*/ ); + while ((rc = glGetError()) != GL_NO_ERROR) + AssertMsgFailed(("rc=%x\n", rc)); + + /* We're back to the orignal back buffer now. Just restore GL_DRAW_BUFFER. */ + if (iOldDrawBuf != GL_BACK) + glDrawBuffer(iOldDrawBuf); + + while ((rc = glGetError()) != GL_NO_ERROR) + AssertMsgFailed(("rc=%x\n", rc)); + } +#endif +} + + + +- (void)vboxReshapePerform +{ + /* + * Change the size and position if necessary. + */ + NSRect CurFrameRect = [self frame]; + /** @todo conversions? */ + if ( m_Pos.x != CurFrameRect.origin.x + || m_Pos.y != CurFrameRect.origin.y) + { + LogFlow(("OvlView(%p) vboxReshapePerform: moving (%d,%d) -> (%d,%d)\n", + (void *)self, CurFrameRect.origin.x, CurFrameRect.origin.y, m_Pos.x, m_Pos.y)); + [self setFrameOrigin:m_Pos]; + } + + if ( CurFrameRect.size.width != m_Size.width + || CurFrameRect.size.height != m_Size.height) + { + LogFlow(("OvlView(%p) vboxReshapePerform: resizing (%d,%d) -> (%d,%d)\n", + (void *)self, CurFrameRect.size.width, CurFrameRect.size.height, m_Size.width, m_Size.height)); + [self setFrameSize:m_Size]; + + /* + * Schedule two clears and a context update for now. + * Really though, we should just clear any new surface area. + */ + m_cClears = 2; + } + m_fUpdateCtx = true; + LogFlow(("OvlView(%p) vboxReshapePerform: returns\n", self)); +} + + +- (void)vboxReshape +{ + LogFlow(("OvlView(%p) vboxReshape:\n", (void *)self)); + + /* + * Resize the view. + */ + if ([NSThread isMainThread]) + [self vboxReshapePerform]; + else + { + [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO]; + vmsvga3dCocoaServiceRunLoop(); + + /* + * Try update the opengl context. + */ + [[self openGLContext] update]; + } + + LogFlow(("OvlView(%p) vboxReshape: returns\n", (void *)self)); +} + +/** + * This is called when the bounds change. + * + * We indicate that the FIFO thread must update the GL context. + */ +- (void)vboxBoundsDidChange:(NSNotification *)pNotification +{ + RT_NOREF(pNotification); + LogFlow(("OvlView(%p) vboxBoundsDidChange:\n", (void *)self)); + self->m_fUpdateCtx = true; +} + +/** + * This is called when the frame changes size or position. + * + * We indicate that the FIFO thread must update the GL context. + */ +- (void)vboxFrameDidChange:(NSNotification *)pNotification +{ + RT_NOREF(pNotification); + LogFlow(("OvlView(%p) vboxFrameDidChange:\n", (void *)self)); + self->m_fUpdateCtx = true; +} + +/** + * This is called when moved to different screen/GPU or/and when the GL context + * needs updating. + * + * We indicate that the FIFO thread must update the GL context. + */ +- (void)vboxFrameDidChangeGlobal:(NSNotification *)pNotification +{ + RT_NOREF(pNotification); + LogFlow(("OvlView(%p) vboxFrameDidChangeGlobal:\n", (void *)self)); + self->m_fUpdateCtx = true; +} + +/** This enables the vboxFrameDidChange notification. */ +- (BOOL)postsFrameChangedNotifications +{ + LogFlow(("OvlView(%p) postsFrameChangedNotifications:\n", (void *)self)); + return YES; +} + +/** + * Removes the view from the parent, if it has one, and makes sure it's hidden. + * + * This is callbed before destroying it. + */ +- (void)vboxRemoveFromSuperviewAndHide +{ + LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide:\n", (void *)self)); + if (m_pParentView) + { + /* + * The removeFromSuperview has been frequently seen to deadlock thing like this: + * #0 0x00007fff8db440fa in __psynch_cvwait () + * #1 0x00007fff8d0acfb9 in _pthread_cond_wait () + * #2 0x00007fff8a1bc8f0 in -[NSViewHierarchyLock _lockForWriting:handler:] () + * #3 0x00007fff8a1bc171 in -[NSView removeFromSuperview] () + * #4 0x000000010cffb2bb in -[VMSVGA3DOverlayView vboxRemoveFromSuperviewAndHide] (self=0x10a1da550, _cmd=0x10cffd734) at DevVGA-SVGA3d-cocoa.m:467 + * #5 0x000000010cffbed3 in vmsvga3dCocoaDestroyViewAndContext (pView=0x10a1da550, pCtx=0x10a1da630) at DevVGA-SVGA3d-cocoa.m:662 + * (This is from OS X 10.8.5.) + */ + if ([NSThread isMainThread]) + { + LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide: calling removeFromSuperview\n", (void *)self)); + [self removeFromSuperview]; + LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide: calling setHidden\n", (void *)self)); + [self setHidden:YES]; + LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide: calling setHidden\n", (void *)self)); + [[NSNotificationCenter defaultCenter] removeObserver:self]; + } + else + { + LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide: defering to main thread\n", (void *)self)); + vmsvga3dCocoaServiceRunLoop(); + [self performSelectorOnMainThread:@selector(vboxRemoveFromSuperviewAndHide) withObject:nil waitUntilDone:YES]; + vmsvga3dCocoaServiceRunLoop(); + LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide: main thread done\n", (void *)self)); + } + } +} + + +/** + * Changes to the OpenGL context associated with the view. + * @returns Previous OpenGL context. + */ +- (NSOpenGLContext *)makeCurrentGLContext +{ + NSOpenGLContext *pSavedCtx = [NSOpenGLContext currentContext]; + + /* Always flush before changing. glXMakeCurrent and wglMakeCurrent does this + implicitly, seemingly NSOpenGLContext::makeCurrentContext doesn't. */ + if (pSavedCtx != nil) + glFlush(); + + [[self openGLContext] makeCurrentContext]; + return pSavedCtx; +} + + +/** + * Restores the previous OpenGL context after + * makeCurrentGLContext. + * + * @param pSavedCtx The makeCurrentGLContext return value. + */ +- (void)restoreSavedGLContext:(NSOpenGLContext *)pSavedCtx +{ + /* Always flush before changing. glXMakeCurrent and wglMakeCurrent does this + implicitly, seemingly NSOpenGLContext::makeCurrentContext doesn't. */ + glFlush(); + + if (pSavedCtx) + [pSavedCtx makeCurrentContext]; + else + [NSOpenGLContext clearCurrentContext]; +} + +#ifndef USE_NSOPENGLVIEW +/* + * Faking NSOpenGLView interface. + */ +- (void)setOpenGLContext:(NSOpenGLContext *)pCtx +{ + if (pCtx != m_pCtx) + { + if (pCtx) + { + [pCtx retain]; + [pCtx setView:self]; + /*Assert([pCtx view] == self); - setView fails early on, works later... */ + } + + if (m_pCtx) + [m_pCtx release]; + + m_pCtx = pCtx; + + if (pCtx) + [pCtx update]; + } +} + +- (NSOpenGLContext *)openGLContext +{ + /* Stupid hacks to work around setView failing early. This can get kind of + noisy on some OS versions, so shut it up a little bit. */ + /** @todo use NSOpenGLView for the non-visible contexts. */ + if (m_pCtx && [m_pCtx view] != self) + { + m_cSetViewAttempts++; + if ( m_pParentView + || m_cSetViewAttempts < 64 + || (m_cSetViewAttempts & (m_cSetViewAttempts < _64K ? 0xfff : 0x7fff)) == 0 ) + [m_pCtx setView:self]; + } + return m_pCtx; +} + +- (void)prepareOpenGL +{ + //[m_pCtx prepareOpenGL]; +} +#endif /* USE_NSOPENGLVIEW */ + +/* + * Overridden NSOpenGLView / NSView methods: + */ + +/** @todo do we need this? */ +-(void)viewDidMoveToWindow +{ + LogFlow(("OvlView(%p) viewDidMoveToWindow: new win: %p\n", (void *)self, (void *)[self window])); + [super viewDidMoveToWindow]; + [self vboxReshape]; +} + +-(void)viewDidMoveToSuperview +{ + LogFlow(("OvlView(%p) viewDidMoveToSuperview: new view: %p\n", (void *)self, (void *)[self superview])); + [super viewDidMoveToSuperview]; + [self vboxReshape]; +} + +-(void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize +{ + LogFlow(("OvlView(%p) resizeWithOldSuperviewSize: %d,%d -> %d,%d\n", (void *)self, + (int)oldBoundsSize.width, (int)oldBoundsSize.height, (int)[self bounds].size.width, (int)[self bounds].size.height)); + [super resizeWithOldSuperviewSize:oldBoundsSize]; + [self vboxReshape]; +} + +- (void)drawRect:(NSRect)rect +{ + RT_NOREF(rect); +// if (m_fClear) +// { +// m_fClear = false; +// [self vboxClearBuffers]; +// } +} + +@end /* VMSVGA3DOverlayView */ + +@implementation VMSVGA3DCreateViewAndContext +@end + + +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaServiceRunLoop(void) +{ + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + NSRunLoop *pRunLoop = [NSRunLoop currentRunLoop]; + + if ([NSRunLoop mainRunLoop] != pRunLoop) + { + [pRunLoop runUntilDate:[NSDate distantPast]]; + } + + [pPool release]; +} + + +/** + * Document me later. + * + * @param ppView + * @param ppCtx + * @param pParentView The parent view if this is a context we'll be + * presenting to. + * @param cx + * @param cy + * @param pSharedCtx + * @param fOtherProfile + */ +VMSVGA3DCOCOA_DECL(bool) vmsvga3dCocoaCreateViewAndContext(NativeNSViewRef *ppView, NativeNSOpenGLContextRef *ppCtx, + NativeNSViewRef pParentView, uint32_t cx, uint32_t cy, + NativeNSOpenGLContextRef pSharedCtx, bool fOtherProfile) +{ + LogFlow(("vmsvga3dCocoaCreateViewAndContext: pParentView=%d size=%d,%d pSharedCtx=%p fOtherProfile=%RTbool\n", + (void *)pParentView, cx, cy, (void *)pSharedCtx, fOtherProfile)); + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + vmsvga3dCocoaServiceRunLoop(); + + + VMSVGA3DCreateViewAndContext *pParams = [VMSVGA3DCreateViewAndContext alloc]; + pParams->pParentView = pParentView; + pParams->cx = cx; + pParams->cy = cy; + pParams->pSharedCtx = pSharedCtx; + pParams->fOtherProfile = fOtherProfile; + pParams->pView = NULL; + pParams->pCtx = NULL; + + [VMSVGA3DOverlayView performSelectorOnMainThread:@selector(createViewAndContext:) + withObject:pParams + waitUntilDone:YES]; + + vmsvga3dCocoaServiceRunLoop(); + + *ppCtx = pParams->pCtx; + *ppView = pParams->pView; + bool fRet = *ppCtx != NULL && *ppView != NULL; + + [pParams release]; + + [pPool release]; + LogFlow(("vmsvga3dCocoaDestroyContext: returns %RTbool\n", fRet)); + return fRet; +} + + +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaDestroyViewAndContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx) +{ + LogFlow(("vmsvga3dCocoaDestroyViewAndContext: pView=%p pCtx=%p\n", (void *)pView, (void *)pCtx)); + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + + /* The view */ + VMSVGA3DOverlayView *pOvlView = (VMSVGA3DOverlayView *)pView; + [pOvlView vboxRemoveFromSuperviewAndHide]; + + Log(("vmsvga3dCocoaDestroyViewAndContext: view %p ref count=%d\n", (void *)pOvlView, [pOvlView retainCount])); + [pOvlView release]; + + /* The OpenGL context. */ + Log(("vmsvga3dCocoaDestroyViewAndContext: ctx %p ref count=%d\n", (void *)pCtx, [pCtx retainCount])); + [pCtx release]; + + [pPool release]; + LogFlow(("vmsvga3dCocoaDestroyViewAndContext: returns\n")); +} + + +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewInfo(PCDBGFINFOHLP pHlp, NativeNSViewRef pView) +{ + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + if (pView != nil) + { + VMSVGA3DOverlayView *pOvlView = (VMSVGA3DOverlayView *)pView; + + NSRect FrameRect = [pOvlView frame]; + pHlp->pfnPrintf(pHlp, " Frame rect: x=" FLOAT_FMT_STR ", y=" FLOAT_FMT_STR " cx=" FLOAT_FMT_STR ", cy=" FLOAT_FMT_STR "\n", + FLOAT_FMT_ARGS(FrameRect.origin.x), FLOAT_FMT_ARGS(FrameRect.origin.y), + FLOAT_FMT_ARGS(FrameRect.size.width), FLOAT_FMT_ARGS(FrameRect.size.height)); + NSRect BoundsRect = [pOvlView bounds]; + pHlp->pfnPrintf(pHlp, " Bounds rect: x=" FLOAT_FMT_STR ", y=" FLOAT_FMT_STR " cx=" FLOAT_FMT_STR ", cy=" FLOAT_FMT_STR "\n", + FLOAT_FMT_ARGS(BoundsRect.origin.x), FLOAT_FMT_ARGS(BoundsRect.origin.y), + FLOAT_FMT_ARGS(BoundsRect.size.width), FLOAT_FMT_ARGS(BoundsRect.size.height)); + NSRect VisibleRect = [pOvlView visibleRect]; + pHlp->pfnPrintf(pHlp, " Visible rect: x=" FLOAT_FMT_STR ", y=" FLOAT_FMT_STR " cx=" FLOAT_FMT_STR ", cy=" FLOAT_FMT_STR "\n", + FLOAT_FMT_ARGS(VisibleRect.origin.x), FLOAT_FMT_ARGS(VisibleRect.origin.y), + FLOAT_FMT_ARGS(VisibleRect.size.width), FLOAT_FMT_ARGS(VisibleRect.size.height)); + pHlp->pfnPrintf(pHlp, " isHidden: %RTbool\n", [pOvlView isHidden] != NO); + pHlp->pfnPrintf(pHlp, " canDraw: %RTbool\n", [pOvlView canDraw] != NO); + pHlp->pfnPrintf(pHlp, " wantsDefaultClipping: %RTbool\n", [pOvlView wantsDefaultClipping] != NO); + pHlp->pfnPrintf(pHlp, " wantsLayer: %RTbool\n", [pOvlView wantsLayer] != NO); + if ([pOvlView layer] != nil) + pHlp->pfnPrintf(pHlp, " Layer: %p\n", [pOvlView layer] != nil); + pHlp->pfnPrintf(pHlp, " isOpaque: %RTbool\n", [pOvlView isOpaque] != NO); + pHlp->pfnPrintf(pHlp, " autoresizingMask: %#x\n", [pOvlView autoresizingMask]); + pHlp->pfnPrintf(pHlp, " isRotatedOrScaledFromBase: %RTbool\n", [pOvlView isRotatedOrScaledFromBase] != NO); + + NSView *pEnclosingScrollView = [pOvlView enclosingScrollView]; + NSView *pCurView = [pOvlView superview]; + uint32_t iLevel; + for (iLevel = 1; pCurView && iLevel < 7; iLevel++) + { + NSView *pNextView = [pCurView superview]; + pHlp->pfnPrintf(pHlp, " Superview#%u: %p, super=%p\n", iLevel, pCurView, pNextView); + FrameRect = [pCurView frame]; + pHlp->pfnPrintf(pHlp, " Superview#%u frame: x=" FLOAT_FMT_STR ", y=" FLOAT_FMT_STR " cx=" FLOAT_FMT_STR ", cy=" FLOAT_FMT_STR "\n", + iLevel, + FLOAT_FMT_ARGS(FrameRect.origin.x), FLOAT_FMT_ARGS(FrameRect.origin.y), + FLOAT_FMT_ARGS(FrameRect.size.width), FLOAT_FMT_ARGS(FrameRect.size.height)); + BoundsRect = [pCurView bounds]; + pHlp->pfnPrintf(pHlp, " Superview#%u bounds: x=" FLOAT_FMT_STR ", y=" FLOAT_FMT_STR " cx=" FLOAT_FMT_STR ", cy=" FLOAT_FMT_STR "\n", + iLevel, + FLOAT_FMT_ARGS(BoundsRect.origin.x), FLOAT_FMT_ARGS(BoundsRect.origin.y), + FLOAT_FMT_ARGS(BoundsRect.size.width), FLOAT_FMT_ARGS(BoundsRect.size.height)); + if (pEnclosingScrollView == pCurView) + pHlp->pfnPrintf(pHlp, " Superview#%u is enclosing scroll view\n", iLevel); + if ([pCurView enclosingScrollView]) + pHlp->pfnPrintf(pHlp, " Superview#%u has an enclosing scroll view: %p\n", [pCurView enclosingScrollView]); + pCurView = pNextView; + } + if (pCurView) + pHlp->pfnPrintf(pHlp, " (There are more super views)\n"); + + NSWindow *pWindow = [pOvlView window]; + if (pWindow != nil) + { + pHlp->pfnPrintf(pHlp, " Window: %p\n", pWindow); + FrameRect = [pWindow frame]; + pHlp->pfnPrintf(pHlp, " Window frame: x=" FLOAT_FMT_STR ", y=" FLOAT_FMT_STR " cx=" FLOAT_FMT_STR ", cy=" FLOAT_FMT_STR "\n", + FLOAT_FMT_ARGS(FrameRect.origin.x), FLOAT_FMT_ARGS(FrameRect.origin.y), + FLOAT_FMT_ARGS(FrameRect.size.width), FLOAT_FMT_ARGS(FrameRect.size.height)); + CGFloat rFactor = [pWindow backingScaleFactor]; + pHlp->pfnPrintf(pHlp, " W.backingScaleFactor: " FLOAT_FMT_STR "\n", FLOAT_FMT_ARGS(rFactor)); + } + + } + [pPool release]; +} + + +/** @note Not currently used. */ +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewSetPosition(NativeNSViewRef pView, NativeNSViewRef pParentView, int x, int y) +{ + RT_NOREF(pParentView); + LogFlow(("vmsvga3dCocoaViewSetPosition: pView=%p pParentView=%p (%d,%d)\n", (void *)pView, (void *)pParentView, x, y)); + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + + [(VMSVGA3DOverlayView *)pView vboxSetPos:NSMakePoint(x, y)]; + + [pPool release]; + LogFlow(("vmsvga3dCocoaViewSetPosition: returns\n")); +} + + +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewUpdateViewport(NativeNSViewRef pView) +{ + LogFlow(("vmsvga3dCocoaViewSetSize: pView=%p\n", (void *)pView)); + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + VMSVGA3DOverlayView *pOverlayView = (VMSVGA3DOverlayView *)pView; + + /* Possible that we don't actually need to do this (i.e. this API), but right now I'm + leaving it to be sure things actually work right when scrolling. */ + [pOverlayView vboxScheduleCtxUpdate]; + + [pPool release]; + LogFlow(("vmsvga3dCocoaViewSetSize: returns\n")); +} + + +VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewSetSize(NativeNSViewRef pView, int cx, int cy) +{ + LogFlow(("vmsvga3dCocoaViewSetSize: pView=%p (%d,%d)\n", (void *)pView, cx, cy)); + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + VMSVGA3DOverlayView *pOverlayView = (VMSVGA3DOverlayView *)pView; + + [pOverlayView vboxSetSize:NSMakeSize(cx, cy)]; + + [pPool release]; + LogFlow(("vmsvga3dCocoaViewSetSize: returns\n")); +} + + +void vmsvga3dCocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx) +{ + LogFlow(("vmsvga3dCocoaViewMakeCurrentContext: pView=%p, pCtx=%p\n", (void*)pView, (void*)pCtx)); + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + VMSVGA3DOverlayView *pOverlayView = (VMSVGA3DOverlayView *)pView; + + /* Always flush before flush. glXMakeCurrent and wglMakeCurrent does this + implicitly, seemingly NSOpenGLContext::makeCurrentContext doesn't. */ + if ([NSOpenGLContext currentContext] != 0) + glFlush(); + + if (pOverlayView) + { + /* This must be a release assertion as we depend on the setView + sideeffect of the openGLContext method call. (hack alert!) */ + AssertRelease([pOverlayView openGLContext] == pCtx); + [pCtx makeCurrentContext]; + [pOverlayView vboxUpdateCtxIfNecessary]; + } + else + [NSOpenGLContext clearCurrentContext]; + + [pPool release]; + LogFlow(("vmsvga3dCocoaViewMakeCurrentContext: returns\n")); +} + + +void vmsvga3dCocoaSwapBuffers(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx) +{ + LogFlow(("vmsvga3dCocoaSwapBuffers: pView=%p, pCtx=%p\n", (void*)pView, (void*)pCtx)); + NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init]; + VMSVGA3DOverlayView *pMyView = (VMSVGA3DOverlayView *)pView; + +#ifndef USE_NSOPENGLVIEW + /* Hack alert! setView fails early on so call openGLContext to try again. */ + if ([pCtx view] == NULL) + [pMyView openGLContext]; +#endif + + Assert(pCtx == [NSOpenGLContext currentContext]); + Assert(pCtx == [pMyView openGLContext]); + AssertMsg([pCtx view] == pMyView, ("%p != %p\n", (void *)[pCtx view], (void *)pMyView)); + + [pCtx flushBuffer]; + //[pView setNeedsDisplay:YES]; + vmsvga3dCocoaServiceRunLoop(); + + /* If buffer clearing or/and context updates are pending, execute that now. */ + [pMyView vboxUpdateCtxIfNecessary]; + [pMyView vboxClearBackBufferIfNecessary]; + + [pPool release]; + LogFlow(("vmsvga3dCocoaSwapBuffers: returns\n")); +} + diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp new file mode 100644 index 00000000..9802b570 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp @@ -0,0 +1,10277 @@ +/* $Id: DevVGA-SVGA3d-dx-dx11.cpp $ */ +/** @file + * DevVMWare - VMWare SVGA device + */ + +/* + * Copyright (C) 2020-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include +#include + +#include +#include +#include +#include + +#include /* required by DevVGA.h */ +#include + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#include "DevVGA-SVGA3d-internal.h" +#include "DevVGA-SVGA3d-dx-shader.h" + +/* d3d11_1.h has a structure field named 'Status' but Status is defined as int on Linux host */ +#if defined(Status) +#undef Status +#endif +#include + + +#ifdef RT_OS_WINDOWS +# define VBOX_D3D11_LIBRARY_NAME "d3d11" +#else +# define VBOX_D3D11_LIBRARY_NAME "VBoxDxVk" +#endif + +/* One ID3D11Device object is used for all VMSVGA contexts. */ +/** @todo This should be the only option because VGPU freely uses surfaces from different VMSVGA contexts + * and synchronization of access to shared surfaces kills performance. + */ +#define DX_FORCE_SINGLE_DEVICE +/* A single staging ID3D11Buffer is used for uploading data to other buffers. */ +#define DX_COMMON_STAGING_BUFFER +/* Always flush after submitting a draw call for debugging. */ +//#define DX_FLUSH_AFTER_DRAW + +/* This is not available on non Windows hosts. */ +#ifndef D3D_RELEASE +# define D3D_RELEASE(a_Ptr) do { if ((a_Ptr)) (a_Ptr)->Release(); (a_Ptr) = NULL; } while (0) +#endif + +/** Fake ID for the backend DX context. The context creates all shared textures. */ +#define DX_CID_BACKEND UINT32_C(0xfffffffe) + +#define D3D_RELEASE_ARRAY(a_Count, a_papArray) do { \ + for (uint32_t i = 0; i < (a_Count); ++i) \ + D3D_RELEASE((a_papArray)[i]); \ +} while (0) + +typedef struct D3D11BLITTER +{ + ID3D11Device1 *pDevice; + ID3D11DeviceContext1 *pImmediateContext; + + ID3D11VertexShader *pVertexShader; + ID3D11PixelShader *pPixelShader; + ID3D11SamplerState *pSamplerState; + ID3D11RasterizerState1 *pRasterizerState; + ID3D11BlendState1 *pBlendState; +} D3D11BLITTER; + +typedef struct DXDEVICE +{ + ID3D11Device1 *pDevice; /* Device. */ + ID3D11DeviceContext1 *pImmediateContext; /* Corresponding context. */ + IDXGIFactory *pDxgiFactory; /* DXGI Factory. */ + D3D_FEATURE_LEVEL FeatureLevel; + +#ifdef DX_COMMON_STAGING_BUFFER + /* Staging buffer for transfer to surface buffers. */ + ID3D11Buffer *pStagingBuffer; /* The staging buffer resource. */ + uint32_t cbStagingBuffer; /* Current size of the staging buffer resource. */ +#endif + + D3D11BLITTER Blitter; /* Blits one texture to another. */ +} DXDEVICE; + +/* Kind of a texture view. */ +typedef enum VMSVGA3DBACKVIEWTYPE +{ + VMSVGA3D_VIEWTYPE_NONE = 0, + VMSVGA3D_VIEWTYPE_RENDERTARGET = 1, + VMSVGA3D_VIEWTYPE_DEPTHSTENCIL = 2, + VMSVGA3D_VIEWTYPE_SHADERRESOURCE = 3, + VMSVGA3D_VIEWTYPE_UNORDEREDACCESS = 4 +} VMSVGA3DBACKVIEWTYPE; + +/* Information about a texture view to track all created views:. + * when a surface is invalidated, then all views must deleted; + * when a view is deleted, then the view must be unlinked from the surface. + */ +typedef struct DXVIEWINFO +{ + uint32_t sid; /* Surface which the view was created for. */ + uint32_t cid; /* DX context which created the view. */ + uint32_t viewId; /* View id assigned by the guest. */ + VMSVGA3DBACKVIEWTYPE enmViewType; +} DXVIEWINFO; + +/* Context Object Table element for a texture view. */ +typedef struct DXVIEW +{ + uint32_t cid; /* DX context which created the view. */ + uint32_t sid; /* Surface which the view was created for. */ + uint32_t viewId; /* View id assigned by the guest. */ + VMSVGA3DBACKVIEWTYPE enmViewType; + + union + { + ID3D11View *pView; /* The view object. */ + ID3D11RenderTargetView *pRenderTargetView; + ID3D11DepthStencilView *pDepthStencilView; + ID3D11ShaderResourceView *pShaderResourceView; + ID3D11UnorderedAccessView *pUnorderedAccessView; + } u; + + RTLISTNODE nodeSurfaceView; /* Views are linked to the surface. */ +} DXVIEW; + +/* What kind of resource has been created for the VMSVGA3D surface. */ +typedef enum VMSVGA3DBACKRESTYPE +{ + VMSVGA3D_RESTYPE_NONE = 0, + VMSVGA3D_RESTYPE_TEXTURE_1D = 1, + VMSVGA3D_RESTYPE_TEXTURE_2D = 2, + VMSVGA3D_RESTYPE_TEXTURE_CUBE = 3, + VMSVGA3D_RESTYPE_TEXTURE_3D = 4, + VMSVGA3D_RESTYPE_BUFFER = 5, +} VMSVGA3DBACKRESTYPE; + +typedef struct VMSVGA3DBACKENDSURFACE +{ + VMSVGA3DBACKRESTYPE enmResType; + DXGI_FORMAT enmDxgiFormat; + union + { + ID3D11Resource *pResource; + ID3D11Texture1D *pTexture1D; + ID3D11Texture2D *pTexture2D; + ID3D11Texture3D *pTexture3D; + ID3D11Buffer *pBuffer; + } u; + + /* For updates from memory. */ + union /** @todo One per format. */ + { + ID3D11Resource *pResource; + ID3D11Texture1D *pTexture1D; + ID3D11Texture2D *pTexture2D; + ID3D11Texture3D *pTexture3D; +#ifndef DX_COMMON_STAGING_BUFFER + ID3D11Buffer *pBuffer; +#endif + } dynamic; + + /* For reading the texture content. */ + union /** @todo One per format. */ + { + ID3D11Resource *pResource; + ID3D11Texture1D *pTexture1D; + ID3D11Texture2D *pTexture2D; + ID3D11Texture3D *pTexture3D; +#ifndef DX_COMMON_STAGING_BUFFER + ID3D11Buffer *pBuffer; +#endif + } staging; + + /* Screen targets are created as shared surfaces. */ + HANDLE SharedHandle; /* The shared handle of this structure. */ + + /* DX context which last rendered to the texture. + * This is only for render targets and screen targets, which can be shared between contexts. + * The backend context (cid == DX_CID_BACKEND) can also be a drawing context. + */ + uint32_t cidDrawing; + + /** AVL tree containing DXSHAREDTEXTURE structures. */ + AVLU32TREE SharedTextureTree; + + /* Render target views, depth stencil views and shader resource views created for this texture or buffer. */ + RTLISTANCHOR listView; /* DXVIEW */ + +} VMSVGA3DBACKENDSURFACE; + +/* "The only resources that can be shared are 2D non-mipmapped textures." */ +typedef struct DXSHAREDTEXTURE +{ + AVLU32NODECORE Core; /* Key is context id which opened this texture. */ + ID3D11Texture2D *pTexture; /* The opened shared texture. */ + uint32_t sid; /* Surface id. */ +} DXSHAREDTEXTURE; + + +typedef struct VMSVGAHWSCREEN +{ + ID3D11Texture2D *pTexture; /* Shared texture for the screen content. Only used as CopyResource target. */ + IDXGIResource *pDxgiResource; /* Interface of the texture. */ + IDXGIKeyedMutex *pDXGIKeyedMutex; /* Synchronization interface for the render device. */ + HANDLE SharedHandle; /* The shared handle of this structure. */ + uint32_t sidScreenTarget; /* The source surface for this screen. */ +} VMSVGAHWSCREEN; + + +typedef struct DXELEMENTLAYOUT +{ + ID3D11InputLayout *pElementLayout; + uint32_t cElementDesc; + D3D11_INPUT_ELEMENT_DESC aElementDesc[32]; +} DXELEMENTLAYOUT; + +typedef struct DXSHADER +{ + SVGA3dShaderType enmShaderType; + union + { + ID3D11DeviceChild *pShader; /* All. */ + ID3D11VertexShader *pVertexShader; /* SVGA3D_SHADERTYPE_VS */ + ID3D11PixelShader *pPixelShader; /* SVGA3D_SHADERTYPE_PS */ + ID3D11GeometryShader *pGeometryShader; /* SVGA3D_SHADERTYPE_GS */ + ID3D11HullShader *pHullShader; /* SVGA3D_SHADERTYPE_HS */ + ID3D11DomainShader *pDomainShader; /* SVGA3D_SHADERTYPE_DS */ + ID3D11ComputeShader *pComputeShader; /* SVGA3D_SHADERTYPE_CS */ + }; + void *pvDXBC; + uint32_t cbDXBC; + + uint32_t soid; /* Stream output declarations for geometry shaders. */ + + DXShaderInfo shaderInfo; +} DXSHADER; + +typedef struct DXQUERY +{ + union + { + ID3D11Query *pQuery; + ID3D11Predicate *pPredicate; + }; +} DXQUERY; + +typedef struct DXSTREAMOUTPUT +{ + UINT cDeclarationEntry; + D3D11_SO_DECLARATION_ENTRY aDeclarationEntry[SVGA3D_MAX_STREAMOUT_DECLS]; +} DXSTREAMOUTPUT; + +typedef struct DXBOUNDVERTEXBUFFER +{ + ID3D11Buffer *pBuffer; + uint32_t stride; + uint32_t offset; +} DXBOUNDVERTEXBUFFER; + +typedef struct DXBOUNDINDEXBUFFER +{ + ID3D11Buffer *pBuffer; + DXGI_FORMAT indexBufferFormat; + uint32_t indexBufferOffset; +} DXBOUNDINDEXBUFFER; + +typedef struct DXBOUNDRESOURCES /* Currently bound resources. Mirror SVGADXContextMobFormat structure. */ +{ + struct + { + DXBOUNDVERTEXBUFFER vertexBuffers[SVGA3D_DX_MAX_VERTEXBUFFERS]; + DXBOUNDINDEXBUFFER indexBuffer; + } inputAssembly; + struct + { + ID3D11Buffer *constantBuffers[SVGA3D_DX_MAX_CONSTBUFFERS]; + } shaderState[SVGA3D_NUM_SHADERTYPE]; +} DXBOUNDRESOURCES; + + +typedef struct VMSVGA3DBACKENDDXCONTEXT +{ + DXDEVICE dxDevice; /* DX device interfaces for this context operations. */ + + /* Arrays for Context-Object Tables. Number of entries depends on COTable size. */ + uint32_t cBlendState; /* Number of entries in the papBlendState array. */ + uint32_t cDepthStencilState; /* papDepthStencilState */ + uint32_t cSamplerState; /* papSamplerState */ + uint32_t cRasterizerState; /* papRasterizerState */ + uint32_t cElementLayout; /* paElementLayout */ + uint32_t cRenderTargetView; /* paRenderTargetView */ + uint32_t cDepthStencilView; /* paDepthStencilView */ + uint32_t cShaderResourceView; /* paShaderResourceView */ + uint32_t cQuery; /* paQuery */ + uint32_t cShader; /* paShader */ + uint32_t cStreamOutput; /* paStreamOutput */ + uint32_t cUnorderedAccessView; /* paUnorderedAccessView */ + ID3D11BlendState1 **papBlendState; + ID3D11DepthStencilState **papDepthStencilState; + ID3D11SamplerState **papSamplerState; + ID3D11RasterizerState1 **papRasterizerState; + DXELEMENTLAYOUT *paElementLayout; + DXVIEW *paRenderTargetView; + DXVIEW *paDepthStencilView; + DXVIEW *paShaderResourceView; + DXQUERY *paQuery; + DXSHADER *paShader; + DXSTREAMOUTPUT *paStreamOutput; + DXVIEW *paUnorderedAccessView; + + uint32_t cSOTarget; /* How many SO targets are currently set (SetSOTargets) */ + + DXBOUNDRESOURCES resources; +} VMSVGA3DBACKENDDXCONTEXT; + +/* Shader disassembler function. Optional. */ +typedef HRESULT FN_D3D_DISASSEMBLE(LPCVOID pSrcData, SIZE_T SrcDataSize, UINT Flags, LPCSTR szComments, ID3D10Blob **ppDisassembly); +typedef FN_D3D_DISASSEMBLE *PFN_D3D_DISASSEMBLE; + +typedef struct VMSVGA3DBACKEND +{ + RTLDRMOD hD3D11; + PFN_D3D11_CREATE_DEVICE pfnD3D11CreateDevice; + + RTLDRMOD hD3DCompiler; + PFN_D3D_DISASSEMBLE pfnD3DDisassemble; + + DXDEVICE dxDevice; /* Device for the VMSVGA3D context independent operation. */ + + DXBOUNDRESOURCES resources; /* What is currently applied to the pipeline. */ + + bool fSingleDevice; /* Whether to use one DX device for all guest contexts. */ + + /** @todo Here a set of functions which do different job in single and multiple device modes. */ +} VMSVGA3DBACKEND; + + +/* Static function prototypes. */ +static int dxDeviceFlush(DXDEVICE *pDevice); +static int dxDefineShaderResourceView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId, SVGACOTableDXSRViewEntry const *pEntry); +static int dxDefineUnorderedAccessView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, SVGACOTableDXUAViewEntry const *pEntry); +static int dxDefineRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGACOTableDXRTViewEntry const *pEntry); +static int dxDefineDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, SVGACOTableDXDSViewEntry const *pEntry); +static int dxSetRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext); +static int dxSetCSUnorderedAccessViews(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext); +static DECLCALLBACK(void) vmsvga3dBackSurfaceDestroy(PVGASTATECC pThisCC, bool fClearCOTableEntry, PVMSVGA3DSURFACE pSurface); +static int dxDestroyShader(DXSHADER *pDXShader); +static int dxDestroyQuery(DXQUERY *pDXQuery); +static int dxReadBuffer(DXDEVICE *pDevice, ID3D11Buffer *pBuffer, UINT Offset, UINT Bytes, void **ppvData, uint32_t *pcbData); + +static HRESULT BlitInit(D3D11BLITTER *pBlitter, ID3D11Device1 *pDevice, ID3D11DeviceContext1 *pImmediateContext); +static void BlitRelease(D3D11BLITTER *pBlitter); + + +/* This is not available with the DXVK headers for some reason. */ +#ifndef RT_OS_WINDOWS +typedef enum D3D11_TEXTURECUBE_FACE { + D3D11_TEXTURECUBE_FACE_POSITIVE_X, + D3D11_TEXTURECUBE_FACE_NEGATIVE_X, + D3D11_TEXTURECUBE_FACE_POSITIVE_Y, + D3D11_TEXTURECUBE_FACE_NEGATIVE_Y, + D3D11_TEXTURECUBE_FACE_POSITIVE_Z, + D3D11_TEXTURECUBE_FACE_NEGATIVE_Z +} D3D11_TEXTURECUBE_FACE; +#endif + + +DECLINLINE(D3D11_TEXTURECUBE_FACE) vmsvga3dCubemapFaceFromIndex(uint32_t iFace) +{ + D3D11_TEXTURECUBE_FACE Face; + switch (iFace) + { + case 0: Face = D3D11_TEXTURECUBE_FACE_POSITIVE_X; break; + case 1: Face = D3D11_TEXTURECUBE_FACE_NEGATIVE_X; break; + case 2: Face = D3D11_TEXTURECUBE_FACE_POSITIVE_Y; break; + case 3: Face = D3D11_TEXTURECUBE_FACE_NEGATIVE_Y; break; + case 4: Face = D3D11_TEXTURECUBE_FACE_POSITIVE_Z; break; + default: + case 5: Face = D3D11_TEXTURECUBE_FACE_NEGATIVE_Z; break; + } + return Face; +} + +/* This is to workaround issues with X8 formats, because they can't be used in some operations. */ +#define DX_REPLACE_X8_WITH_A8 +static DXGI_FORMAT vmsvgaDXSurfaceFormat2Dxgi(SVGA3dSurfaceFormat format) +{ + /* Ensure that correct headers are used. + * SVGA3D_AYUV was equal to 45, then replaced with SVGA3D_FORMAT_DEAD2 = 45, and redefined as SVGA3D_AYUV = 152. + */ + AssertCompile(SVGA3D_AYUV == 152); + +#define DXGI_FORMAT_ DXGI_FORMAT_UNKNOWN + /** @todo More formats. */ + switch (format) + { +#ifdef DX_REPLACE_X8_WITH_A8 + case SVGA3D_X8R8G8B8: return DXGI_FORMAT_B8G8R8A8_UNORM; +#else + case SVGA3D_X8R8G8B8: return DXGI_FORMAT_B8G8R8X8_UNORM; +#endif + case SVGA3D_A8R8G8B8: return DXGI_FORMAT_B8G8R8A8_UNORM; + case SVGA3D_R5G6B5: return DXGI_FORMAT_B5G6R5_UNORM; + case SVGA3D_X1R5G5B5: return DXGI_FORMAT_B5G5R5A1_UNORM; + case SVGA3D_A1R5G5B5: return DXGI_FORMAT_B5G5R5A1_UNORM; + case SVGA3D_A4R4G4B4: break; // 11.1 return DXGI_FORMAT_B4G4R4A4_UNORM; + case SVGA3D_Z_D32: break; + case SVGA3D_Z_D16: return DXGI_FORMAT_D16_UNORM; + case SVGA3D_Z_D24S8: return DXGI_FORMAT_D24_UNORM_S8_UINT; + case SVGA3D_Z_D15S1: break; + case SVGA3D_LUMINANCE8: return DXGI_FORMAT_; + case SVGA3D_LUMINANCE4_ALPHA4: return DXGI_FORMAT_; + case SVGA3D_LUMINANCE16: return DXGI_FORMAT_; + case SVGA3D_LUMINANCE8_ALPHA8: return DXGI_FORMAT_; + case SVGA3D_DXT1: return DXGI_FORMAT_; + case SVGA3D_DXT2: return DXGI_FORMAT_; + case SVGA3D_DXT3: return DXGI_FORMAT_; + case SVGA3D_DXT4: return DXGI_FORMAT_; + case SVGA3D_DXT5: return DXGI_FORMAT_; + case SVGA3D_BUMPU8V8: return DXGI_FORMAT_; + case SVGA3D_BUMPL6V5U5: return DXGI_FORMAT_; + case SVGA3D_BUMPX8L8V8U8: return DXGI_FORMAT_; + case SVGA3D_FORMAT_DEAD1: break; + case SVGA3D_ARGB_S10E5: return DXGI_FORMAT_; + case SVGA3D_ARGB_S23E8: return DXGI_FORMAT_; + case SVGA3D_A2R10G10B10: return DXGI_FORMAT_; + case SVGA3D_V8U8: return DXGI_FORMAT_; + case SVGA3D_Q8W8V8U8: return DXGI_FORMAT_; + case SVGA3D_CxV8U8: return DXGI_FORMAT_; + case SVGA3D_X8L8V8U8: return DXGI_FORMAT_; + case SVGA3D_A2W10V10U10: return DXGI_FORMAT_; + case SVGA3D_ALPHA8: return DXGI_FORMAT_; + case SVGA3D_R_S10E5: return DXGI_FORMAT_; + case SVGA3D_R_S23E8: return DXGI_FORMAT_; + case SVGA3D_RG_S10E5: return DXGI_FORMAT_; + case SVGA3D_RG_S23E8: return DXGI_FORMAT_; + case SVGA3D_BUFFER: return DXGI_FORMAT_; + case SVGA3D_Z_D24X8: return DXGI_FORMAT_; + case SVGA3D_V16U16: return DXGI_FORMAT_; + case SVGA3D_G16R16: return DXGI_FORMAT_; + case SVGA3D_A16B16G16R16: return DXGI_FORMAT_; + case SVGA3D_UYVY: return DXGI_FORMAT_; + case SVGA3D_YUY2: return DXGI_FORMAT_; + case SVGA3D_NV12: return DXGI_FORMAT_; + case SVGA3D_FORMAT_DEAD2: break; /* Old SVGA3D_AYUV */ + case SVGA3D_R32G32B32A32_TYPELESS: return DXGI_FORMAT_R32G32B32A32_TYPELESS; + case SVGA3D_R32G32B32A32_UINT: return DXGI_FORMAT_R32G32B32A32_UINT; + case SVGA3D_R32G32B32A32_SINT: return DXGI_FORMAT_R32G32B32A32_SINT; + case SVGA3D_R32G32B32_TYPELESS: return DXGI_FORMAT_R32G32B32_TYPELESS; + case SVGA3D_R32G32B32_FLOAT: return DXGI_FORMAT_R32G32B32_FLOAT; + case SVGA3D_R32G32B32_UINT: return DXGI_FORMAT_R32G32B32_UINT; + case SVGA3D_R32G32B32_SINT: return DXGI_FORMAT_R32G32B32_SINT; + case SVGA3D_R16G16B16A16_TYPELESS: return DXGI_FORMAT_R16G16B16A16_TYPELESS; + case SVGA3D_R16G16B16A16_UINT: return DXGI_FORMAT_R16G16B16A16_UINT; + case SVGA3D_R16G16B16A16_SNORM: return DXGI_FORMAT_R16G16B16A16_SNORM; + case SVGA3D_R16G16B16A16_SINT: return DXGI_FORMAT_R16G16B16A16_SINT; + case SVGA3D_R32G32_TYPELESS: return DXGI_FORMAT_R32G32_TYPELESS; + case SVGA3D_R32G32_UINT: return DXGI_FORMAT_R32G32_UINT; + case SVGA3D_R32G32_SINT: return DXGI_FORMAT_R32G32_SINT; + case SVGA3D_R32G8X24_TYPELESS: return DXGI_FORMAT_R32G8X24_TYPELESS; + case SVGA3D_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + case SVGA3D_R32_FLOAT_X8X24: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + case SVGA3D_X32_G8X24_UINT: return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT; + case SVGA3D_R10G10B10A2_TYPELESS: return DXGI_FORMAT_R10G10B10A2_TYPELESS; + case SVGA3D_R10G10B10A2_UINT: return DXGI_FORMAT_R10G10B10A2_UINT; + case SVGA3D_R11G11B10_FLOAT: return DXGI_FORMAT_R11G11B10_FLOAT; + case SVGA3D_R8G8B8A8_TYPELESS: return DXGI_FORMAT_R8G8B8A8_TYPELESS; + case SVGA3D_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case SVGA3D_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + case SVGA3D_R8G8B8A8_UINT: return DXGI_FORMAT_R8G8B8A8_UINT; + case SVGA3D_R8G8B8A8_SINT: return DXGI_FORMAT_R8G8B8A8_SINT; + case SVGA3D_R16G16_TYPELESS: return DXGI_FORMAT_R16G16_TYPELESS; + case SVGA3D_R16G16_UINT: return DXGI_FORMAT_R16G16_UINT; + case SVGA3D_R16G16_SINT: return DXGI_FORMAT_R16G16_SINT; + case SVGA3D_R32_TYPELESS: return DXGI_FORMAT_R32_TYPELESS; + case SVGA3D_D32_FLOAT: return DXGI_FORMAT_D32_FLOAT; + case SVGA3D_R32_UINT: return DXGI_FORMAT_R32_UINT; + case SVGA3D_R32_SINT: return DXGI_FORMAT_R32_SINT; + case SVGA3D_R24G8_TYPELESS: return DXGI_FORMAT_R24G8_TYPELESS; + case SVGA3D_D24_UNORM_S8_UINT: return DXGI_FORMAT_D24_UNORM_S8_UINT; + case SVGA3D_R24_UNORM_X8: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + case SVGA3D_X24_G8_UINT: return DXGI_FORMAT_X24_TYPELESS_G8_UINT; + case SVGA3D_R8G8_TYPELESS: return DXGI_FORMAT_R8G8_TYPELESS; + case SVGA3D_R8G8_UNORM: return DXGI_FORMAT_R8G8_UNORM; + case SVGA3D_R8G8_UINT: return DXGI_FORMAT_R8G8_UINT; + case SVGA3D_R8G8_SINT: return DXGI_FORMAT_R8G8_SINT; + case SVGA3D_R16_TYPELESS: return DXGI_FORMAT_R16_TYPELESS; + case SVGA3D_R16_UNORM: return DXGI_FORMAT_R16_UNORM; + case SVGA3D_R16_UINT: return DXGI_FORMAT_R16_UINT; + case SVGA3D_R16_SNORM: return DXGI_FORMAT_R16_SNORM; + case SVGA3D_R16_SINT: return DXGI_FORMAT_R16_SINT; + case SVGA3D_R8_TYPELESS: return DXGI_FORMAT_R8_TYPELESS; + case SVGA3D_R8_UNORM: return DXGI_FORMAT_R8_UNORM; + case SVGA3D_R8_UINT: return DXGI_FORMAT_R8_UINT; + case SVGA3D_R8_SNORM: return DXGI_FORMAT_R8_SNORM; + case SVGA3D_R8_SINT: return DXGI_FORMAT_R8_SINT; + case SVGA3D_P8: break; + case SVGA3D_R9G9B9E5_SHAREDEXP: return DXGI_FORMAT_R9G9B9E5_SHAREDEXP; + case SVGA3D_R8G8_B8G8_UNORM: return DXGI_FORMAT_R8G8_B8G8_UNORM; + case SVGA3D_G8R8_G8B8_UNORM: return DXGI_FORMAT_G8R8_G8B8_UNORM; + case SVGA3D_BC1_TYPELESS: return DXGI_FORMAT_BC1_TYPELESS; + case SVGA3D_BC1_UNORM_SRGB: return DXGI_FORMAT_BC1_UNORM_SRGB; + case SVGA3D_BC2_TYPELESS: return DXGI_FORMAT_BC2_TYPELESS; + case SVGA3D_BC2_UNORM_SRGB: return DXGI_FORMAT_BC2_UNORM_SRGB; + case SVGA3D_BC3_TYPELESS: return DXGI_FORMAT_BC3_TYPELESS; + case SVGA3D_BC3_UNORM_SRGB: return DXGI_FORMAT_BC3_UNORM_SRGB; + case SVGA3D_BC4_TYPELESS: return DXGI_FORMAT_BC4_TYPELESS; + case SVGA3D_ATI1: break; + case SVGA3D_BC4_SNORM: return DXGI_FORMAT_BC4_SNORM; + case SVGA3D_BC5_TYPELESS: return DXGI_FORMAT_BC5_TYPELESS; + case SVGA3D_ATI2: break; + case SVGA3D_BC5_SNORM: return DXGI_FORMAT_BC5_SNORM; + case SVGA3D_R10G10B10_XR_BIAS_A2_UNORM: return DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM; + case SVGA3D_B8G8R8A8_TYPELESS: return DXGI_FORMAT_B8G8R8A8_TYPELESS; + case SVGA3D_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; +#ifdef DX_REPLACE_X8_WITH_A8 + case SVGA3D_B8G8R8X8_TYPELESS: return DXGI_FORMAT_B8G8R8A8_TYPELESS; + case SVGA3D_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; +#else + case SVGA3D_B8G8R8X8_TYPELESS: return DXGI_FORMAT_B8G8R8X8_TYPELESS; + case SVGA3D_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; +#endif + case SVGA3D_Z_DF16: break; + case SVGA3D_Z_DF24: break; + case SVGA3D_Z_D24S8_INT: return DXGI_FORMAT_D24_UNORM_S8_UINT; + case SVGA3D_YV12: break; + case SVGA3D_R32G32B32A32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case SVGA3D_R16G16B16A16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; + case SVGA3D_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; + case SVGA3D_R32G32_FLOAT: return DXGI_FORMAT_R32G32_FLOAT; + case SVGA3D_R10G10B10A2_UNORM: return DXGI_FORMAT_R10G10B10A2_UNORM; + case SVGA3D_R8G8B8A8_SNORM: return DXGI_FORMAT_R8G8B8A8_SNORM; + case SVGA3D_R16G16_FLOAT: return DXGI_FORMAT_R16G16_FLOAT; + case SVGA3D_R16G16_UNORM: return DXGI_FORMAT_R16G16_UNORM; + case SVGA3D_R16G16_SNORM: return DXGI_FORMAT_R16G16_SNORM; + case SVGA3D_R32_FLOAT: return DXGI_FORMAT_R32_FLOAT; + case SVGA3D_R8G8_SNORM: return DXGI_FORMAT_R8G8_SNORM; + case SVGA3D_R16_FLOAT: return DXGI_FORMAT_R16_FLOAT; + case SVGA3D_D16_UNORM: return DXGI_FORMAT_D16_UNORM; + case SVGA3D_A8_UNORM: return DXGI_FORMAT_A8_UNORM; + case SVGA3D_BC1_UNORM: return DXGI_FORMAT_BC1_UNORM; + case SVGA3D_BC2_UNORM: return DXGI_FORMAT_BC2_UNORM; + case SVGA3D_BC3_UNORM: return DXGI_FORMAT_BC3_UNORM; + case SVGA3D_B5G6R5_UNORM: return DXGI_FORMAT_B5G6R5_UNORM; + case SVGA3D_B5G5R5A1_UNORM: return DXGI_FORMAT_B5G5R5A1_UNORM; + case SVGA3D_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM; +#ifdef DX_REPLACE_X8_WITH_A8 + case SVGA3D_B8G8R8X8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM; +#else + case SVGA3D_B8G8R8X8_UNORM: return DXGI_FORMAT_B8G8R8X8_UNORM; +#endif + case SVGA3D_BC4_UNORM: return DXGI_FORMAT_BC4_UNORM; + case SVGA3D_BC5_UNORM: return DXGI_FORMAT_BC5_UNORM; + + case SVGA3D_B4G4R4A4_UNORM: return DXGI_FORMAT_; + case SVGA3D_BC6H_TYPELESS: return DXGI_FORMAT_BC6H_TYPELESS; + case SVGA3D_BC6H_UF16: return DXGI_FORMAT_BC6H_UF16; + case SVGA3D_BC6H_SF16: return DXGI_FORMAT_BC6H_SF16; + case SVGA3D_BC7_TYPELESS: return DXGI_FORMAT_BC7_TYPELESS; + case SVGA3D_BC7_UNORM: return DXGI_FORMAT_BC7_UNORM; + case SVGA3D_BC7_UNORM_SRGB: return DXGI_FORMAT_BC7_UNORM_SRGB; + case SVGA3D_AYUV: return DXGI_FORMAT_; + + case SVGA3D_FORMAT_INVALID: + case SVGA3D_FORMAT_MAX: break; + } + // AssertFailed(); + return DXGI_FORMAT_UNKNOWN; +#undef DXGI_FORMAT_ +} + + +static SVGA3dSurfaceFormat vmsvgaDXDevCapSurfaceFmt2Format(SVGA3dDevCapIndex enmDevCap) +{ + switch (enmDevCap) + { + case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: return SVGA3D_X8R8G8B8; + case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: return SVGA3D_A8R8G8B8; + case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: return SVGA3D_A2R10G10B10; + case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: return SVGA3D_X1R5G5B5; + case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: return SVGA3D_A1R5G5B5; + case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: return SVGA3D_A4R4G4B4; + case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: return SVGA3D_R5G6B5; + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: return SVGA3D_LUMINANCE16; + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: return SVGA3D_LUMINANCE8_ALPHA8; + case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: return SVGA3D_ALPHA8; + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: return SVGA3D_LUMINANCE8; + case SVGA3D_DEVCAP_SURFACEFMT_Z_D16: return SVGA3D_Z_D16; + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: return SVGA3D_Z_D24S8; + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: return SVGA3D_Z_D24X8; + case SVGA3D_DEVCAP_SURFACEFMT_DXT1: return SVGA3D_DXT1; + case SVGA3D_DEVCAP_SURFACEFMT_DXT2: return SVGA3D_DXT2; + case SVGA3D_DEVCAP_SURFACEFMT_DXT3: return SVGA3D_DXT3; + case SVGA3D_DEVCAP_SURFACEFMT_DXT4: return SVGA3D_DXT4; + case SVGA3D_DEVCAP_SURFACEFMT_DXT5: return SVGA3D_DXT5; + case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: return SVGA3D_BUMPX8L8V8U8; + case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: return SVGA3D_A2W10V10U10; + case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: return SVGA3D_BUMPU8V8; + case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: return SVGA3D_Q8W8V8U8; + case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: return SVGA3D_CxV8U8; + case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: return SVGA3D_R_S10E5; + case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: return SVGA3D_R_S23E8; + case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: return SVGA3D_RG_S10E5; + case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: return SVGA3D_RG_S23E8; + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: return SVGA3D_ARGB_S10E5; + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: return SVGA3D_ARGB_S23E8; + case SVGA3D_DEVCAP_SURFACEFMT_V16U16: return SVGA3D_V16U16; + case SVGA3D_DEVCAP_SURFACEFMT_G16R16: return SVGA3D_G16R16; + case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: return SVGA3D_A16B16G16R16; + case SVGA3D_DEVCAP_SURFACEFMT_UYVY: return SVGA3D_UYVY; + case SVGA3D_DEVCAP_SURFACEFMT_YUY2: return SVGA3D_YUY2; + case SVGA3D_DEVCAP_SURFACEFMT_NV12: return SVGA3D_NV12; + case SVGA3D_DEVCAP_DEAD10: return SVGA3D_FORMAT_DEAD2; /* SVGA3D_DEVCAP_SURFACEFMT_AYUV -> SVGA3D_AYUV */ + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: return SVGA3D_Z_DF16; + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: return SVGA3D_Z_DF24; + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: return SVGA3D_Z_D24S8_INT; + case SVGA3D_DEVCAP_SURFACEFMT_ATI1: return SVGA3D_ATI1; + case SVGA3D_DEVCAP_SURFACEFMT_ATI2: return SVGA3D_ATI2; + case SVGA3D_DEVCAP_SURFACEFMT_YV12: return SVGA3D_YV12; + default: + AssertFailed(); + break; + } + return SVGA3D_FORMAT_INVALID; +} + + +static SVGA3dSurfaceFormat vmsvgaDXDevCapDxfmt2Format(SVGA3dDevCapIndex enmDevCap) +{ + switch (enmDevCap) + { + case SVGA3D_DEVCAP_DXFMT_X8R8G8B8: return SVGA3D_X8R8G8B8; + case SVGA3D_DEVCAP_DXFMT_A8R8G8B8: return SVGA3D_A8R8G8B8; + case SVGA3D_DEVCAP_DXFMT_R5G6B5: return SVGA3D_R5G6B5; + case SVGA3D_DEVCAP_DXFMT_X1R5G5B5: return SVGA3D_X1R5G5B5; + case SVGA3D_DEVCAP_DXFMT_A1R5G5B5: return SVGA3D_A1R5G5B5; + case SVGA3D_DEVCAP_DXFMT_A4R4G4B4: return SVGA3D_A4R4G4B4; + case SVGA3D_DEVCAP_DXFMT_Z_D32: return SVGA3D_Z_D32; + case SVGA3D_DEVCAP_DXFMT_Z_D16: return SVGA3D_Z_D16; + case SVGA3D_DEVCAP_DXFMT_Z_D24S8: return SVGA3D_Z_D24S8; + case SVGA3D_DEVCAP_DXFMT_Z_D15S1: return SVGA3D_Z_D15S1; + case SVGA3D_DEVCAP_DXFMT_LUMINANCE8: return SVGA3D_LUMINANCE8; + case SVGA3D_DEVCAP_DXFMT_LUMINANCE4_ALPHA4: return SVGA3D_LUMINANCE4_ALPHA4; + case SVGA3D_DEVCAP_DXFMT_LUMINANCE16: return SVGA3D_LUMINANCE16; + case SVGA3D_DEVCAP_DXFMT_LUMINANCE8_ALPHA8: return SVGA3D_LUMINANCE8_ALPHA8; + case SVGA3D_DEVCAP_DXFMT_DXT1: return SVGA3D_DXT1; + case SVGA3D_DEVCAP_DXFMT_DXT2: return SVGA3D_DXT2; + case SVGA3D_DEVCAP_DXFMT_DXT3: return SVGA3D_DXT3; + case SVGA3D_DEVCAP_DXFMT_DXT4: return SVGA3D_DXT4; + case SVGA3D_DEVCAP_DXFMT_DXT5: return SVGA3D_DXT5; + case SVGA3D_DEVCAP_DXFMT_BUMPU8V8: return SVGA3D_BUMPU8V8; + case SVGA3D_DEVCAP_DXFMT_BUMPL6V5U5: return SVGA3D_BUMPL6V5U5; + case SVGA3D_DEVCAP_DXFMT_BUMPX8L8V8U8: return SVGA3D_BUMPX8L8V8U8; + case SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD1: return SVGA3D_FORMAT_DEAD1; + case SVGA3D_DEVCAP_DXFMT_ARGB_S10E5: return SVGA3D_ARGB_S10E5; + case SVGA3D_DEVCAP_DXFMT_ARGB_S23E8: return SVGA3D_ARGB_S23E8; + case SVGA3D_DEVCAP_DXFMT_A2R10G10B10: return SVGA3D_A2R10G10B10; + case SVGA3D_DEVCAP_DXFMT_V8U8: return SVGA3D_V8U8; + case SVGA3D_DEVCAP_DXFMT_Q8W8V8U8: return SVGA3D_Q8W8V8U8; + case SVGA3D_DEVCAP_DXFMT_CxV8U8: return SVGA3D_CxV8U8; + case SVGA3D_DEVCAP_DXFMT_X8L8V8U8: return SVGA3D_X8L8V8U8; + case SVGA3D_DEVCAP_DXFMT_A2W10V10U10: return SVGA3D_A2W10V10U10; + case SVGA3D_DEVCAP_DXFMT_ALPHA8: return SVGA3D_ALPHA8; + case SVGA3D_DEVCAP_DXFMT_R_S10E5: return SVGA3D_R_S10E5; + case SVGA3D_DEVCAP_DXFMT_R_S23E8: return SVGA3D_R_S23E8; + case SVGA3D_DEVCAP_DXFMT_RG_S10E5: return SVGA3D_RG_S10E5; + case SVGA3D_DEVCAP_DXFMT_RG_S23E8: return SVGA3D_RG_S23E8; + case SVGA3D_DEVCAP_DXFMT_BUFFER: return SVGA3D_BUFFER; + case SVGA3D_DEVCAP_DXFMT_Z_D24X8: return SVGA3D_Z_D24X8; + case SVGA3D_DEVCAP_DXFMT_V16U16: return SVGA3D_V16U16; + case SVGA3D_DEVCAP_DXFMT_G16R16: return SVGA3D_G16R16; + case SVGA3D_DEVCAP_DXFMT_A16B16G16R16: return SVGA3D_A16B16G16R16; + case SVGA3D_DEVCAP_DXFMT_UYVY: return SVGA3D_UYVY; + case SVGA3D_DEVCAP_DXFMT_YUY2: return SVGA3D_YUY2; + case SVGA3D_DEVCAP_DXFMT_NV12: return SVGA3D_NV12; + case SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD2: return SVGA3D_FORMAT_DEAD2; /* SVGA3D_DEVCAP_DXFMT_AYUV -> SVGA3D_AYUV */ + case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS: return SVGA3D_R32G32B32A32_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT: return SVGA3D_R32G32B32A32_UINT; + case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT: return SVGA3D_R32G32B32A32_SINT; + case SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS: return SVGA3D_R32G32B32_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT: return SVGA3D_R32G32B32_FLOAT; + case SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT: return SVGA3D_R32G32B32_UINT; + case SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT: return SVGA3D_R32G32B32_SINT; + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS: return SVGA3D_R16G16B16A16_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT: return SVGA3D_R16G16B16A16_UINT; + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM: return SVGA3D_R16G16B16A16_SNORM; + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT: return SVGA3D_R16G16B16A16_SINT; + case SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS: return SVGA3D_R32G32_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R32G32_UINT: return SVGA3D_R32G32_UINT; + case SVGA3D_DEVCAP_DXFMT_R32G32_SINT: return SVGA3D_R32G32_SINT; + case SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS: return SVGA3D_R32G8X24_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT: return SVGA3D_D32_FLOAT_S8X24_UINT; + case SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24: return SVGA3D_R32_FLOAT_X8X24; + case SVGA3D_DEVCAP_DXFMT_X32_G8X24_UINT: return SVGA3D_X32_G8X24_UINT; + case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS: return SVGA3D_R10G10B10A2_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT: return SVGA3D_R10G10B10A2_UINT; + case SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT: return SVGA3D_R11G11B10_FLOAT; + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS: return SVGA3D_R8G8B8A8_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM: return SVGA3D_R8G8B8A8_UNORM; + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB: return SVGA3D_R8G8B8A8_UNORM_SRGB; + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT: return SVGA3D_R8G8B8A8_UINT; + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT: return SVGA3D_R8G8B8A8_SINT; + case SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS: return SVGA3D_R16G16_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R16G16_UINT: return SVGA3D_R16G16_UINT; + case SVGA3D_DEVCAP_DXFMT_R16G16_SINT: return SVGA3D_R16G16_SINT; + case SVGA3D_DEVCAP_DXFMT_R32_TYPELESS: return SVGA3D_R32_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_D32_FLOAT: return SVGA3D_D32_FLOAT; + case SVGA3D_DEVCAP_DXFMT_R32_UINT: return SVGA3D_R32_UINT; + case SVGA3D_DEVCAP_DXFMT_R32_SINT: return SVGA3D_R32_SINT; + case SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS: return SVGA3D_R24G8_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT: return SVGA3D_D24_UNORM_S8_UINT; + case SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8: return SVGA3D_R24_UNORM_X8; + case SVGA3D_DEVCAP_DXFMT_X24_G8_UINT: return SVGA3D_X24_G8_UINT; + case SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS: return SVGA3D_R8G8_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R8G8_UNORM: return SVGA3D_R8G8_UNORM; + case SVGA3D_DEVCAP_DXFMT_R8G8_UINT: return SVGA3D_R8G8_UINT; + case SVGA3D_DEVCAP_DXFMT_R8G8_SINT: return SVGA3D_R8G8_SINT; + case SVGA3D_DEVCAP_DXFMT_R16_TYPELESS: return SVGA3D_R16_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R16_UNORM: return SVGA3D_R16_UNORM; + case SVGA3D_DEVCAP_DXFMT_R16_UINT: return SVGA3D_R16_UINT; + case SVGA3D_DEVCAP_DXFMT_R16_SNORM: return SVGA3D_R16_SNORM; + case SVGA3D_DEVCAP_DXFMT_R16_SINT: return SVGA3D_R16_SINT; + case SVGA3D_DEVCAP_DXFMT_R8_TYPELESS: return SVGA3D_R8_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_R8_UNORM: return SVGA3D_R8_UNORM; + case SVGA3D_DEVCAP_DXFMT_R8_UINT: return SVGA3D_R8_UINT; + case SVGA3D_DEVCAP_DXFMT_R8_SNORM: return SVGA3D_R8_SNORM; + case SVGA3D_DEVCAP_DXFMT_R8_SINT: return SVGA3D_R8_SINT; + case SVGA3D_DEVCAP_DXFMT_P8: return SVGA3D_P8; + case SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP: return SVGA3D_R9G9B9E5_SHAREDEXP; + case SVGA3D_DEVCAP_DXFMT_R8G8_B8G8_UNORM: return SVGA3D_R8G8_B8G8_UNORM; + case SVGA3D_DEVCAP_DXFMT_G8R8_G8B8_UNORM: return SVGA3D_G8R8_G8B8_UNORM; + case SVGA3D_DEVCAP_DXFMT_BC1_TYPELESS: return SVGA3D_BC1_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_BC1_UNORM_SRGB: return SVGA3D_BC1_UNORM_SRGB; + case SVGA3D_DEVCAP_DXFMT_BC2_TYPELESS: return SVGA3D_BC2_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_BC2_UNORM_SRGB: return SVGA3D_BC2_UNORM_SRGB; + case SVGA3D_DEVCAP_DXFMT_BC3_TYPELESS: return SVGA3D_BC3_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_BC3_UNORM_SRGB: return SVGA3D_BC3_UNORM_SRGB; + case SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS: return SVGA3D_BC4_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_ATI1: return SVGA3D_ATI1; + case SVGA3D_DEVCAP_DXFMT_BC4_SNORM: return SVGA3D_BC4_SNORM; + case SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS: return SVGA3D_BC5_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_ATI2: return SVGA3D_ATI2; + case SVGA3D_DEVCAP_DXFMT_BC5_SNORM: return SVGA3D_BC5_SNORM; + case SVGA3D_DEVCAP_DXFMT_R10G10B10_XR_BIAS_A2_UNORM: return SVGA3D_R10G10B10_XR_BIAS_A2_UNORM; + case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS: return SVGA3D_B8G8R8A8_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB: return SVGA3D_B8G8R8A8_UNORM_SRGB; + case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS: return SVGA3D_B8G8R8X8_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB: return SVGA3D_B8G8R8X8_UNORM_SRGB; + case SVGA3D_DEVCAP_DXFMT_Z_DF16: return SVGA3D_Z_DF16; + case SVGA3D_DEVCAP_DXFMT_Z_DF24: return SVGA3D_Z_DF24; + case SVGA3D_DEVCAP_DXFMT_Z_D24S8_INT: return SVGA3D_Z_D24S8_INT; + case SVGA3D_DEVCAP_DXFMT_YV12: return SVGA3D_YV12; + case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT: return SVGA3D_R32G32B32A32_FLOAT; + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT: return SVGA3D_R16G16B16A16_FLOAT; + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM: return SVGA3D_R16G16B16A16_UNORM; + case SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT: return SVGA3D_R32G32_FLOAT; + case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM: return SVGA3D_R10G10B10A2_UNORM; + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM: return SVGA3D_R8G8B8A8_SNORM; + case SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT: return SVGA3D_R16G16_FLOAT; + case SVGA3D_DEVCAP_DXFMT_R16G16_UNORM: return SVGA3D_R16G16_UNORM; + case SVGA3D_DEVCAP_DXFMT_R16G16_SNORM: return SVGA3D_R16G16_SNORM; + case SVGA3D_DEVCAP_DXFMT_R32_FLOAT: return SVGA3D_R32_FLOAT; + case SVGA3D_DEVCAP_DXFMT_R8G8_SNORM: return SVGA3D_R8G8_SNORM; + case SVGA3D_DEVCAP_DXFMT_R16_FLOAT: return SVGA3D_R16_FLOAT; + case SVGA3D_DEVCAP_DXFMT_D16_UNORM: return SVGA3D_D16_UNORM; + case SVGA3D_DEVCAP_DXFMT_A8_UNORM: return SVGA3D_A8_UNORM; + case SVGA3D_DEVCAP_DXFMT_BC1_UNORM: return SVGA3D_BC1_UNORM; + case SVGA3D_DEVCAP_DXFMT_BC2_UNORM: return SVGA3D_BC2_UNORM; + case SVGA3D_DEVCAP_DXFMT_BC3_UNORM: return SVGA3D_BC3_UNORM; + case SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM: return SVGA3D_B5G6R5_UNORM; + case SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM: return SVGA3D_B5G5R5A1_UNORM; + case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM: return SVGA3D_B8G8R8A8_UNORM; + case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM: return SVGA3D_B8G8R8X8_UNORM; + case SVGA3D_DEVCAP_DXFMT_BC4_UNORM: return SVGA3D_BC4_UNORM; + case SVGA3D_DEVCAP_DXFMT_BC5_UNORM: return SVGA3D_BC5_UNORM; + case SVGA3D_DEVCAP_DXFMT_BC6H_TYPELESS: return SVGA3D_BC6H_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_BC6H_UF16: return SVGA3D_BC6H_UF16; + case SVGA3D_DEVCAP_DXFMT_BC6H_SF16: return SVGA3D_BC6H_SF16; + case SVGA3D_DEVCAP_DXFMT_BC7_TYPELESS: return SVGA3D_BC7_TYPELESS; + case SVGA3D_DEVCAP_DXFMT_BC7_UNORM: return SVGA3D_BC7_UNORM; + case SVGA3D_DEVCAP_DXFMT_BC7_UNORM_SRGB: return SVGA3D_BC7_UNORM_SRGB; + default: + AssertFailed(); + break; + } + return SVGA3D_FORMAT_INVALID; +} + + +static int vmsvgaDXCheckFormatSupportPreDX(PVMSVGA3DSTATE pState, SVGA3dSurfaceFormat enmFormat, uint32_t *pu32DevCap) +{ + int rc = VINF_SUCCESS; + + *pu32DevCap = 0; + + DXGI_FORMAT const dxgiFormat = vmsvgaDXSurfaceFormat2Dxgi(enmFormat); + if (dxgiFormat != DXGI_FORMAT_UNKNOWN) + { + RT_NOREF(pState); + /** @todo Implement */ + } + else + rc = VERR_NOT_SUPPORTED; + return rc; +} + +static int vmsvgaDXCheckFormatSupport(PVMSVGA3DSTATE pState, SVGA3dSurfaceFormat enmFormat, uint32_t *pu32DevCap) +{ + int rc = VINF_SUCCESS; + + *pu32DevCap = 0; + + DXGI_FORMAT const dxgiFormat = vmsvgaDXSurfaceFormat2Dxgi(enmFormat); + if (dxgiFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *pDevice = pState->pBackend->dxDevice.pDevice; + UINT FormatSupport = 0; + HRESULT hr = pDevice->CheckFormatSupport(dxgiFormat, &FormatSupport); + if (SUCCEEDED(hr)) + { + *pu32DevCap |= SVGA3D_DXFMT_SUPPORTED; + + if (FormatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) + *pu32DevCap |= SVGA3D_DXFMT_SHADER_SAMPLE; + + if (FormatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET) + *pu32DevCap |= SVGA3D_DXFMT_COLOR_RENDERTARGET; + + if (FormatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) + *pu32DevCap |= SVGA3D_DXFMT_DEPTH_RENDERTARGET; + + if (FormatSupport & D3D11_FORMAT_SUPPORT_BLENDABLE) + *pu32DevCap |= SVGA3D_DXFMT_BLENDABLE; + + if (FormatSupport & D3D11_FORMAT_SUPPORT_MIP) + *pu32DevCap |= SVGA3D_DXFMT_MIPS; + + if (FormatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) + *pu32DevCap |= SVGA3D_DXFMT_ARRAY; + + if (FormatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) + *pu32DevCap |= SVGA3D_DXFMT_VOLUME; + + if (FormatSupport & D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER) + *pu32DevCap |= SVGA3D_DXFMT_DX_VERTEX_BUFFER; + + UINT NumQualityLevels; + hr = pDevice->CheckMultisampleQualityLevels(dxgiFormat, 2, &NumQualityLevels); + if (SUCCEEDED(hr) && NumQualityLevels != 0) + *pu32DevCap |= SVGA3D_DXFMT_MULTISAMPLE; + } + else + { + LogFunc(("CheckFormatSupport failed for 0x%08x, hr = 0x%08x\n", dxgiFormat, hr)); + rc = VERR_NOT_SUPPORTED; + } + } + else + rc = VERR_NOT_SUPPORTED; + return rc; +} + + +static int dxDeviceCreate(PVMSVGA3DBACKEND pBackend, DXDEVICE *pDXDevice) +{ + int rc = VINF_SUCCESS; + + if (pBackend->fSingleDevice && pBackend->dxDevice.pDevice) + { + pDXDevice->pDevice = pBackend->dxDevice.pDevice; + pDXDevice->pDevice->AddRef(); + + pDXDevice->pImmediateContext = pBackend->dxDevice.pImmediateContext; + pDXDevice->pImmediateContext->AddRef(); + + pDXDevice->pDxgiFactory = pBackend->dxDevice.pDxgiFactory; + pDXDevice->pDxgiFactory->AddRef(); + + pDXDevice->FeatureLevel = pBackend->dxDevice.FeatureLevel; + +#ifdef DX_COMMON_STAGING_BUFFER + pDXDevice->pStagingBuffer = 0; + pDXDevice->cbStagingBuffer = 0; +#endif + + BlitInit(&pDXDevice->Blitter, pDXDevice->pDevice, pDXDevice->pImmediateContext); + return rc; + } + + IDXGIAdapter *pAdapter = NULL; /* Default adapter. */ + static D3D_FEATURE_LEVEL const s_aFeatureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0 + }; + UINT Flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; +#ifdef DEBUG + Flags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + ID3D11Device *pDevice = 0; + ID3D11DeviceContext *pImmediateContext = 0; + HRESULT hr = pBackend->pfnD3D11CreateDevice(pAdapter, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + Flags, + s_aFeatureLevels, + RT_ELEMENTS(s_aFeatureLevels), + D3D11_SDK_VERSION, + &pDevice, + &pDXDevice->FeatureLevel, + &pImmediateContext); +#ifdef DEBUG + if (FAILED(hr)) + { + /* Device creation may fail because _DEBUG flag requires "D3D11 SDK Layers for Windows 10" ("Graphics Tools"): + * Settings/System/Apps/Optional features/Add a feature/Graphics Tools + * Retry without the flag. + */ + Flags &= ~D3D11_CREATE_DEVICE_DEBUG; + hr = pBackend->pfnD3D11CreateDevice(pAdapter, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + Flags, + s_aFeatureLevels, + RT_ELEMENTS(s_aFeatureLevels), + D3D11_SDK_VERSION, + &pDevice, + &pDXDevice->FeatureLevel, + &pImmediateContext); + } +#endif + + if (SUCCEEDED(hr)) + { + LogRel(("VMSVGA: Feature level %#x\n", pDXDevice->FeatureLevel)); + + hr = pDevice->QueryInterface(__uuidof(ID3D11Device1), (void**)&pDXDevice->pDevice); + AssertReturnStmt(SUCCEEDED(hr), + D3D_RELEASE(pImmediateContext); D3D_RELEASE(pDevice), + VERR_NOT_SUPPORTED); + + hr = pImmediateContext->QueryInterface(__uuidof(ID3D11DeviceContext1), (void**)&pDXDevice->pImmediateContext); + AssertReturnStmt(SUCCEEDED(hr), + D3D_RELEASE(pImmediateContext); D3D_RELEASE(pDXDevice->pDevice); D3D_RELEASE(pDevice), + VERR_NOT_SUPPORTED); + +#ifdef DEBUG + /* Break into debugger when DX runtime detects anything unusual. */ + HRESULT hr2; + ID3D11Debug *pDebug = 0; + hr2 = pDXDevice->pDevice->QueryInterface(__uuidof(ID3D11Debug), (void**)&pDebug); + if (SUCCEEDED(hr2)) + { + ID3D11InfoQueue *pInfoQueue = 0; + hr2 = pDebug->QueryInterface(__uuidof(ID3D11InfoQueue), (void**)&pInfoQueue); + if (SUCCEEDED(hr2)) + { + pInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); +// pInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +// pInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, true); + + /* No breakpoints for the following messages. */ + D3D11_MESSAGE_ID saIgnoredMessageIds[] = + { + /* Message ID: Caused by: */ + D3D11_MESSAGE_ID_CREATEINPUTLAYOUT_TYPE_MISMATCH, /* Autogenerated input signatures. */ + D3D11_MESSAGE_ID_LIVE_DEVICE, /* Live object report. Does not seem to prevent a breakpoint. */ + (D3D11_MESSAGE_ID)3146081 /*DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET*/, /* U. */ + D3D11_MESSAGE_ID_DEVICE_DRAW_SAMPLER_NOT_SET, /* U. */ + D3D11_MESSAGE_ID_DEVICE_DRAW_SAMPLER_MISMATCH, /* U. */ + D3D11_MESSAGE_ID_CREATEINPUTLAYOUT_EMPTY_LAYOUT, /* P. */ + D3D11_MESSAGE_ID_DEVICE_SHADER_LINKAGE_REGISTERMASK, /* S. */ + }; + + D3D11_INFO_QUEUE_FILTER filter; + RT_ZERO(filter); + filter.DenyList.NumIDs = RT_ELEMENTS(saIgnoredMessageIds); + filter.DenyList.pIDList = saIgnoredMessageIds; + pInfoQueue->AddStorageFilterEntries(&filter); + + D3D_RELEASE(pInfoQueue); + } + D3D_RELEASE(pDebug); + } +#endif + + IDXGIDevice *pDxgiDevice = 0; + hr = pDXDevice->pDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDxgiDevice); + if (SUCCEEDED(hr)) + { + IDXGIAdapter *pDxgiAdapter = 0; + hr = pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&pDxgiAdapter); + if (SUCCEEDED(hr)) + { + hr = pDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&pDXDevice->pDxgiFactory); + D3D_RELEASE(pDxgiAdapter); + } + + D3D_RELEASE(pDxgiDevice); + } + } + + if (SUCCEEDED(hr)) + BlitInit(&pDXDevice->Blitter, pDXDevice->pDevice, pDXDevice->pImmediateContext); + else + rc = VERR_NOT_SUPPORTED; + + return rc; +} + + +static void dxDeviceDestroy(PVMSVGA3DBACKEND pBackend, DXDEVICE *pDevice) +{ + RT_NOREF(pBackend); + + BlitRelease(&pDevice->Blitter); + +#ifdef DX_COMMON_STAGING_BUFFER + D3D_RELEASE(pDevice->pStagingBuffer); +#endif + + D3D_RELEASE(pDevice->pDxgiFactory); + D3D_RELEASE(pDevice->pImmediateContext); + +#ifdef DEBUG + HRESULT hr2; + ID3D11Debug *pDebug = 0; + hr2 = pDevice->pDevice->QueryInterface(__uuidof(ID3D11Debug), (void**)&pDebug); + if (SUCCEEDED(hr2)) + { + /// @todo Use this to see whether all resources have been properly released. + //DEBUG_BREAKPOINT_TEST(); + //pDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL | (D3D11_RLDO_FLAGS)0x4 /*D3D11_RLDO_IGNORE_INTERNAL*/); + D3D_RELEASE(pDebug); + } +#endif + + D3D_RELEASE(pDevice->pDevice); + RT_ZERO(*pDevice); +} + + +static void dxViewAddToList(PVGASTATECC pThisCC, DXVIEW *pDXView) +{ + LogFunc(("cid = %u, sid = %u, viewId = %u, type = %u\n", + pDXView->cid, pDXView->sid, pDXView->viewId, pDXView->enmViewType)); + + Assert(pDXView->u.pView); /* Only already created views should be added. Guard against mis-use by callers. */ + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pDXView->sid, &pSurface); + AssertRCReturnVoid(rc); + + RTListAppend(&pSurface->pBackendSurface->listView, &pDXView->nodeSurfaceView); +} + + +static void dxViewRemoveFromList(DXVIEW *pDXView) +{ + LogFunc(("cid = %u, sid = %u, viewId = %u, type = %u\n", + pDXView->cid, pDXView->sid, pDXView->viewId, pDXView->enmViewType)); + /* pView can be NULL, if COT entry is already empty. */ + if (pDXView->u.pView) + { + Assert(pDXView->nodeSurfaceView.pNext && pDXView->nodeSurfaceView.pPrev); + RTListNodeRemove(&pDXView->nodeSurfaceView); + } +} + + +static int dxViewDestroy(DXVIEW *pDXView) +{ + LogFunc(("cid = %u, sid = %u, viewId = %u, type = %u\n", + pDXView->cid, pDXView->sid, pDXView->viewId, pDXView->enmViewType)); + if (pDXView->u.pView) + { + D3D_RELEASE(pDXView->u.pView); + RTListNodeRemove(&pDXView->nodeSurfaceView); + RT_ZERO(*pDXView); + } + + return VINF_SUCCESS; +} + + +static int dxViewInit(DXVIEW *pDXView, PVMSVGA3DSURFACE pSurface, VMSVGA3DDXCONTEXT *pDXContext, uint32_t viewId, VMSVGA3DBACKVIEWTYPE enmViewType, ID3D11View *pView) +{ + pDXView->cid = pDXContext->cid; + pDXView->sid = pSurface->id; + pDXView->viewId = viewId; + pDXView->enmViewType = enmViewType; + pDXView->u.pView = pView; + RTListAppend(&pSurface->pBackendSurface->listView, &pDXView->nodeSurfaceView); + + LogFunc(("cid = %u, sid = %u, viewId = %u, type = %u\n", + pDXView->cid, pDXView->sid, pDXView->viewId, pDXView->enmViewType)); + +DXVIEW *pIter, *pNext; +RTListForEachSafe(&pSurface->pBackendSurface->listView, pIter, pNext, DXVIEW, nodeSurfaceView) +{ + AssertPtr(pNext); + LogFunc(("pIter=%p, pNext=%p\n", pIter, pNext)); +} + + return VINF_SUCCESS; +} + + +DECLINLINE(bool) dxIsSurfaceShareable(PVMSVGA3DSURFACE pSurface) +{ + /* It is not expected that volume textures will be shared between contexts. */ + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_VOLUME) + return false; + + return (pSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) + || (pSurface->f.surfaceFlags & SVGA3D_SURFACE_BIND_RENDER_TARGET); +} + + +static DXDEVICE *dxDeviceFromCid(uint32_t cid, PVMSVGA3DSTATE pState) +{ + if (cid != DX_CID_BACKEND) + { + if (pState->pBackend->fSingleDevice) + return &pState->pBackend->dxDevice; + + VMSVGA3DDXCONTEXT *pDXContext; + int rc = vmsvga3dDXContextFromCid(pState, cid, &pDXContext); + if (RT_SUCCESS(rc)) + return &pDXContext->pBackendDXContext->dxDevice; + } + else + return &pState->pBackend->dxDevice; + + AssertFailed(); + return NULL; +} + + +static DXDEVICE *dxDeviceFromContext(PVMSVGA3DSTATE p3dState, VMSVGA3DDXCONTEXT *pDXContext) +{ + if (pDXContext && !p3dState->pBackend->fSingleDevice) + return &pDXContext->pBackendDXContext->dxDevice; + + return &p3dState->pBackend->dxDevice; +} + + +static int dxDeviceFlush(DXDEVICE *pDevice) +{ + /** @todo Should the flush follow the query submission? */ + pDevice->pImmediateContext->Flush(); + + ID3D11Query *pQuery = 0; + D3D11_QUERY_DESC qd; + RT_ZERO(qd); + qd.Query = D3D11_QUERY_EVENT; + + HRESULT hr = pDevice->pDevice->CreateQuery(&qd, &pQuery); + Assert(hr == S_OK); RT_NOREF(hr); + pDevice->pImmediateContext->End(pQuery); + + BOOL queryData; + while (pDevice->pImmediateContext->GetData(pQuery, &queryData, sizeof(queryData), 0) != S_OK) + RTThreadYield(); + + D3D_RELEASE(pQuery); + + return VINF_SUCCESS; +} + + +static int dxContextWait(uint32_t cidDrawing, PVMSVGA3DSTATE pState) +{ + if (pState->pBackend->fSingleDevice) + return VINF_SUCCESS; + + /* Flush cidDrawing context and issue a query. */ + DXDEVICE *pDXDevice = dxDeviceFromCid(cidDrawing, pState); + if (pDXDevice) + return dxDeviceFlush(pDXDevice); + /* cidDrawing does not exist anymore. */ + return VINF_SUCCESS; +} + + +static int dxSurfaceWait(PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, uint32_t cidRequesting) +{ + if (pState->pBackend->fSingleDevice) + return VINF_SUCCESS; + + VMSVGA3DBACKENDSURFACE *pBackendSurface = pSurface->pBackendSurface; + if (!pBackendSurface) + AssertFailedReturn(VERR_INVALID_STATE); + + int rc = VINF_SUCCESS; + if (pBackendSurface->cidDrawing != SVGA_ID_INVALID) + { + if (pBackendSurface->cidDrawing != cidRequesting) + { + LogFunc(("sid = %u, assoc cid = %u, drawing cid = %u, req cid = %u\n", + pSurface->id, pSurface->idAssociatedContext, pBackendSurface->cidDrawing, cidRequesting)); + Assert(dxIsSurfaceShareable(pSurface)); + rc = dxContextWait(pBackendSurface->cidDrawing, pState); + pBackendSurface->cidDrawing = SVGA_ID_INVALID; + } + } + return rc; +} + + +static ID3D11Resource *dxResource(PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, VMSVGA3DDXCONTEXT *pDXContext) +{ + VMSVGA3DBACKENDSURFACE *pBackendSurface = pSurface->pBackendSurface; + if (!pBackendSurface) + AssertFailedReturn(NULL); + + ID3D11Resource *pResource; + + uint32_t const cidRequesting = pDXContext ? pDXContext->cid : DX_CID_BACKEND; + if (cidRequesting == pSurface->idAssociatedContext || pState->pBackend->fSingleDevice) + pResource = pBackendSurface->u.pResource; + else + { + /* + * Context, which as not created the surface, is requesting. + */ + AssertReturn(pDXContext, NULL); + + Assert(dxIsSurfaceShareable(pSurface)); + Assert(pSurface->idAssociatedContext == DX_CID_BACKEND); + + DXSHAREDTEXTURE *pSharedTexture = (DXSHAREDTEXTURE *)RTAvlU32Get(&pBackendSurface->SharedTextureTree, pDXContext->cid); + if (!pSharedTexture) + { + DXDEVICE *pDevice = dxDeviceFromContext(pState, pDXContext); + AssertReturn(pDevice->pDevice, NULL); + + AssertReturn(pBackendSurface->SharedHandle, NULL); + + /* This context has not yet opened the texture. */ + pSharedTexture = (DXSHAREDTEXTURE *)RTMemAllocZ(sizeof(DXSHAREDTEXTURE)); + AssertReturn(pSharedTexture, NULL); + + pSharedTexture->Core.Key = pDXContext->cid; + bool const fSuccess = RTAvlU32Insert(&pBackendSurface->SharedTextureTree, &pSharedTexture->Core); + AssertReturn(fSuccess, NULL); + + HRESULT hr = pDevice->pDevice->OpenSharedResource(pBackendSurface->SharedHandle, __uuidof(ID3D11Texture2D), (void**)&pSharedTexture->pTexture); + Assert(SUCCEEDED(hr)); + if (SUCCEEDED(hr)) + pSharedTexture->sid = pSurface->id; + else + { + RTAvlU32Remove(&pBackendSurface->SharedTextureTree, pDXContext->cid); + RTMemFree(pSharedTexture); + return NULL; + } + } + + pResource = pSharedTexture->pTexture; + } + + /* Wait for drawing to finish. */ + dxSurfaceWait(pState, pSurface, cidRequesting); + + return pResource; +} + + +static uint32_t dxGetRenderTargetViewSid(PVMSVGA3DDXCONTEXT pDXContext, uint32_t renderTargetViewId) +{ + ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->cot.cRTView, SVGA_ID_INVALID); + + SVGACOTableDXRTViewEntry const *pRTViewEntry = &pDXContext->cot.paRTView[renderTargetViewId]; + return pRTViewEntry->sid; +} + + +static SVGACOTableDXSRViewEntry const *dxGetShaderResourceViewEntry(PVMSVGA3DDXCONTEXT pDXContext, uint32_t shaderResourceViewId) +{ + ASSERT_GUEST_RETURN(shaderResourceViewId < pDXContext->cot.cSRView, NULL); + + SVGACOTableDXSRViewEntry const *pSRViewEntry = &pDXContext->cot.paSRView[shaderResourceViewId]; + return pSRViewEntry; +} + + +static SVGACOTableDXUAViewEntry const *dxGetUnorderedAccessViewEntry(PVMSVGA3DDXCONTEXT pDXContext, uint32_t uaViewId) +{ + ASSERT_GUEST_RETURN(uaViewId < pDXContext->cot.cUAView, NULL); + + SVGACOTableDXUAViewEntry const *pUAViewEntry = &pDXContext->cot.paUAView[uaViewId]; + return pUAViewEntry; +} + + +static SVGACOTableDXDSViewEntry const *dxGetDepthStencilViewEntry(PVMSVGA3DDXCONTEXT pDXContext, uint32_t depthStencilViewId) +{ + ASSERT_GUEST_RETURN(depthStencilViewId < pDXContext->cot.cDSView, NULL); + + SVGACOTableDXDSViewEntry const *pDSViewEntry = &pDXContext->cot.paDSView[depthStencilViewId]; + return pDSViewEntry; +} + + +static SVGACOTableDXRTViewEntry const *dxGetRenderTargetViewEntry(PVMSVGA3DDXCONTEXT pDXContext, uint32_t renderTargetViewId) +{ + ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->cot.cRTView, NULL); + + SVGACOTableDXRTViewEntry const *pRTViewEntry = &pDXContext->cot.paRTView[renderTargetViewId]; + return pRTViewEntry; +} + + +static int dxTrackRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + for (unsigned long i = 0; i < RT_ELEMENTS(pDXContext->svgaDXContext.renderState.renderTargetViewIds); ++i) + { + uint32_t const renderTargetViewId = pDXContext->svgaDXContext.renderState.renderTargetViewIds[i]; + if (renderTargetViewId == SVGA_ID_INVALID) + continue; + + uint32_t const sid = dxGetRenderTargetViewSid(pDXContext, renderTargetViewId); + LogFunc(("[%u] sid = %u, drawing cid = %u\n", i, sid, pDXContext->cid)); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + if (RT_SUCCESS(rc)) + { + AssertContinue(pSurface->pBackendSurface); + pSurface->pBackendSurface->cidDrawing = pDXContext->cid; + } + } + return VINF_SUCCESS; +} + + +static int dxDefineStreamOutput(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid, SVGACOTableDXStreamOutputEntry const *pEntry, DXSHADER *pDXShader) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; + + /* Make D3D11_SO_DECLARATION_ENTRY array from SVGA3dStreamOutputDeclarationEntry. */ + SVGA3dStreamOutputDeclarationEntry const *paDecls; + PVMSVGAMOB pMob = NULL; + if (pEntry->usesMob) + { + pMob = vmsvgaR3MobGet(pSvgaR3State, pEntry->mobid); + ASSERT_GUEST_RETURN(pMob, VERR_INVALID_PARAMETER); + + /* Create a memory pointer for the MOB, which is accessible by host. */ + int rc = vmsvgaR3MobBackingStoreCreate(pSvgaR3State, pMob, vmsvgaR3MobSize(pMob)); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + /* Get pointer to the shader bytecode. This will also verify the offset. */ + paDecls = (SVGA3dStreamOutputDeclarationEntry const *)vmsvgaR3MobBackingStorePtr(pMob, pEntry->offsetInBytes); + AssertReturnStmt(paDecls, vmsvgaR3MobBackingStoreDelete(pSvgaR3State, pMob), VERR_INTERNAL_ERROR); + } + else + paDecls = &pEntry->decl[0]; + + pDXStreamOutput->cDeclarationEntry = pEntry->numOutputStreamEntries; + for (uint32_t i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) + { + D3D11_SO_DECLARATION_ENTRY *pDst = &pDXStreamOutput->aDeclarationEntry[i]; + SVGA3dStreamOutputDeclarationEntry const *pSrc = &paDecls[i]; + + uint32_t const registerMask = pSrc->registerMask & 0xF; + unsigned const iFirstBit = ASMBitFirstSetU32(registerMask); + unsigned const iLastBit = ASMBitLastSetU32(registerMask); + + pDst->Stream = pSrc->stream; + pDst->SemanticName = NULL; /* Semantic name and index will be taken from the shader output declaration. */ + pDst->SemanticIndex = 0; + pDst->StartComponent = iFirstBit > 0 ? iFirstBit - 1 : 0; + pDst->ComponentCount = iFirstBit > 0 ? iLastBit - (iFirstBit - 1) : 0; + pDst->OutputSlot = pSrc->outputSlot; + } + + uint32_t MaxSemanticIndex = 0; + for (uint32_t i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) + { + D3D11_SO_DECLARATION_ENTRY *pDeclarationEntry = &pDXStreamOutput->aDeclarationEntry[i]; + SVGA3dStreamOutputDeclarationEntry const *decl = &paDecls[i]; + + /* Find the corresponding register and mask in the GS shader output. */ + int idxFound = -1; + for (uint32_t iOutputEntry = 0; iOutputEntry < pDXShader->shaderInfo.cOutputSignature; ++iOutputEntry) + { + SVGA3dDXSignatureEntry const *pOutputEntry = &pDXShader->shaderInfo.aOutputSignature[iOutputEntry]; + if ( pOutputEntry->registerIndex == decl->registerIndex + && (decl->registerMask & ~pOutputEntry->mask) == 0) /* SO decl mask is a subset of shader output mask. */ + { + idxFound = iOutputEntry; + break; + } + } + + if (idxFound >= 0) + { + DXShaderAttributeSemantic const *pOutputSemantic = &pDXShader->shaderInfo.aOutputSemantic[idxFound]; + pDeclarationEntry->SemanticName = pOutputSemantic->pcszSemanticName; + pDeclarationEntry->SemanticIndex = pOutputSemantic->SemanticIndex; + MaxSemanticIndex = RT_MAX(MaxSemanticIndex, pOutputSemantic->SemanticIndex); + } + else + AssertFailed(); + } + + /* A geometry shader may return components of the same register as different attributes: + * + * Output signature + * Name Index Mask Register + * ATTRIB 2 xy 2 + * ATTRIB 3 z 2 + * + * For ATTRIB 3 the stream output declaration expects StartComponent = 0 and ComponentCount = 1 + * (not StartComponent = 2 and ComponentCount = 1): + * + * Stream output declaration + * SemanticName SemanticIndex StartComponent ComponentCount + * ATTRIB 2 0 2 + * ATTRIB 3 0 1 + * + * Stream output declaration can have multiple entries for the same attribute. + * In this case StartComponent is the offset within the attribute. + * + * Output signature + * Name Index Mask Register + * ATTRIB 0 xyzw 0 + * + * Stream output declaration + * SemanticName SemanticIndex StartComponent ComponentCount + * ATTRIB 0 0 1 + * ATTRIB 0 1 1 + * + * StartComponent has been computed as the component offset in a register: + * 'StartComponent = iFirstBit > 0 ? iFirstBit - 1 : 0;'. + * + * StartComponent must be the offset in an attribute. + */ + for (uint32_t SemanticIndex = 0; SemanticIndex <= MaxSemanticIndex; ++SemanticIndex) + { + /* Find minimum StartComponent value for this attribute. */ + uint32_t MinStartComponent = UINT32_MAX; + for (uint32_t i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) + { + D3D11_SO_DECLARATION_ENTRY *pDeclarationEntry = &pDXStreamOutput->aDeclarationEntry[i]; + if (pDeclarationEntry->SemanticIndex == SemanticIndex) + MinStartComponent = RT_MIN(MinStartComponent, pDeclarationEntry->StartComponent); + } + + AssertContinue(MinStartComponent != UINT32_MAX); + + /* Adjust the StartComponent to start from 0 for this attribute. */ + for (uint32_t i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) + { + D3D11_SO_DECLARATION_ENTRY *pDeclarationEntry = &pDXStreamOutput->aDeclarationEntry[i]; + if (pDeclarationEntry->SemanticIndex == SemanticIndex) + pDeclarationEntry->StartComponent -= MinStartComponent; + } + } + + if (pMob) + vmsvgaR3MobBackingStoreDelete(pSvgaR3State, pMob); + + return VINF_SUCCESS; +} + +static void dxDestroyStreamOutput(DXSTREAMOUTPUT *pDXStreamOutput) +{ + RT_ZERO(*pDXStreamOutput); +} + +static D3D11_BLEND dxBlendFactorAlpha(uint8_t svgaBlend) +{ + /* "Blend options that end in _COLOR are not allowed." but the guest sometimes sends them. */ + switch (svgaBlend) + { + case SVGA3D_BLENDOP_ZERO: return D3D11_BLEND_ZERO; + case SVGA3D_BLENDOP_ONE: return D3D11_BLEND_ONE; + case SVGA3D_BLENDOP_SRCCOLOR: return D3D11_BLEND_SRC_ALPHA; + case SVGA3D_BLENDOP_INVSRCCOLOR: return D3D11_BLEND_INV_SRC_ALPHA; + case SVGA3D_BLENDOP_SRCALPHA: return D3D11_BLEND_SRC_ALPHA; + case SVGA3D_BLENDOP_INVSRCALPHA: return D3D11_BLEND_INV_SRC_ALPHA; + case SVGA3D_BLENDOP_DESTALPHA: return D3D11_BLEND_DEST_ALPHA; + case SVGA3D_BLENDOP_INVDESTALPHA: return D3D11_BLEND_INV_DEST_ALPHA; + case SVGA3D_BLENDOP_DESTCOLOR: return D3D11_BLEND_DEST_ALPHA; + case SVGA3D_BLENDOP_INVDESTCOLOR: return D3D11_BLEND_INV_DEST_ALPHA; + case SVGA3D_BLENDOP_SRCALPHASAT: return D3D11_BLEND_SRC_ALPHA_SAT; + case SVGA3D_BLENDOP_BLENDFACTOR: return D3D11_BLEND_BLEND_FACTOR; + case SVGA3D_BLENDOP_INVBLENDFACTOR: return D3D11_BLEND_INV_BLEND_FACTOR; + case SVGA3D_BLENDOP_SRC1COLOR: return D3D11_BLEND_SRC1_ALPHA; + case SVGA3D_BLENDOP_INVSRC1COLOR: return D3D11_BLEND_INV_SRC1_ALPHA; + case SVGA3D_BLENDOP_SRC1ALPHA: return D3D11_BLEND_SRC1_ALPHA; + case SVGA3D_BLENDOP_INVSRC1ALPHA: return D3D11_BLEND_INV_SRC1_ALPHA; + case SVGA3D_BLENDOP_BLENDFACTORALPHA: return D3D11_BLEND_BLEND_FACTOR; + case SVGA3D_BLENDOP_INVBLENDFACTORALPHA: return D3D11_BLEND_INV_BLEND_FACTOR; + default: + break; + } + return D3D11_BLEND_ZERO; +} + + +static D3D11_BLEND dxBlendFactorColor(uint8_t svgaBlend) +{ + switch (svgaBlend) + { + case SVGA3D_BLENDOP_ZERO: return D3D11_BLEND_ZERO; + case SVGA3D_BLENDOP_ONE: return D3D11_BLEND_ONE; + case SVGA3D_BLENDOP_SRCCOLOR: return D3D11_BLEND_SRC_COLOR; + case SVGA3D_BLENDOP_INVSRCCOLOR: return D3D11_BLEND_INV_SRC_COLOR; + case SVGA3D_BLENDOP_SRCALPHA: return D3D11_BLEND_SRC_ALPHA; + case SVGA3D_BLENDOP_INVSRCALPHA: return D3D11_BLEND_INV_SRC_ALPHA; + case SVGA3D_BLENDOP_DESTALPHA: return D3D11_BLEND_DEST_ALPHA; + case SVGA3D_BLENDOP_INVDESTALPHA: return D3D11_BLEND_INV_DEST_ALPHA; + case SVGA3D_BLENDOP_DESTCOLOR: return D3D11_BLEND_DEST_COLOR; + case SVGA3D_BLENDOP_INVDESTCOLOR: return D3D11_BLEND_INV_DEST_COLOR; + case SVGA3D_BLENDOP_SRCALPHASAT: return D3D11_BLEND_SRC_ALPHA_SAT; + case SVGA3D_BLENDOP_BLENDFACTOR: return D3D11_BLEND_BLEND_FACTOR; + case SVGA3D_BLENDOP_INVBLENDFACTOR: return D3D11_BLEND_INV_BLEND_FACTOR; + case SVGA3D_BLENDOP_SRC1COLOR: return D3D11_BLEND_SRC1_COLOR; + case SVGA3D_BLENDOP_INVSRC1COLOR: return D3D11_BLEND_INV_SRC1_COLOR; + case SVGA3D_BLENDOP_SRC1ALPHA: return D3D11_BLEND_SRC1_ALPHA; + case SVGA3D_BLENDOP_INVSRC1ALPHA: return D3D11_BLEND_INV_SRC1_ALPHA; + case SVGA3D_BLENDOP_BLENDFACTORALPHA: return D3D11_BLEND_BLEND_FACTOR; + case SVGA3D_BLENDOP_INVBLENDFACTORALPHA: return D3D11_BLEND_INV_BLEND_FACTOR; + default: + break; + } + return D3D11_BLEND_ZERO; +} + + +static D3D11_BLEND_OP dxBlendOp(uint8_t svgaBlendEq) +{ + return (D3D11_BLEND_OP)svgaBlendEq; +} + + +static D3D11_LOGIC_OP dxLogicOp(uint8_t svgaLogicEq) +{ + return (D3D11_LOGIC_OP)svgaLogicEq; +} + + +/** @todo AssertCompile for types like D3D11_COMPARISON_FUNC and SVGA3dComparisonFunc */ +static HRESULT dxBlendStateCreate(DXDEVICE *pDevice, SVGACOTableDXBlendStateEntry const *pEntry, ID3D11BlendState1 **pp) +{ + D3D11_BLEND_DESC1 BlendDesc; + BlendDesc.AlphaToCoverageEnable = RT_BOOL(pEntry->alphaToCoverageEnable); + BlendDesc.IndependentBlendEnable = RT_BOOL(pEntry->independentBlendEnable); + for (int i = 0; i < SVGA3D_MAX_RENDER_TARGETS; ++i) + { + BlendDesc.RenderTarget[i].BlendEnable = RT_BOOL(pEntry->perRT[i].blendEnable); + BlendDesc.RenderTarget[i].LogicOpEnable = RT_BOOL(pEntry->perRT[i].logicOpEnable); + BlendDesc.RenderTarget[i].SrcBlend = dxBlendFactorColor(pEntry->perRT[i].srcBlend); + BlendDesc.RenderTarget[i].DestBlend = dxBlendFactorColor(pEntry->perRT[i].destBlend); + BlendDesc.RenderTarget[i].BlendOp = dxBlendOp (pEntry->perRT[i].blendOp); + BlendDesc.RenderTarget[i].SrcBlendAlpha = dxBlendFactorAlpha(pEntry->perRT[i].srcBlendAlpha); + BlendDesc.RenderTarget[i].DestBlendAlpha = dxBlendFactorAlpha(pEntry->perRT[i].destBlendAlpha); + BlendDesc.RenderTarget[i].BlendOpAlpha = dxBlendOp (pEntry->perRT[i].blendOpAlpha); + BlendDesc.RenderTarget[i].LogicOp = dxLogicOp (pEntry->perRT[i].logicOp); + BlendDesc.RenderTarget[i].RenderTargetWriteMask = pEntry->perRT[i].renderTargetWriteMask; + } + + HRESULT hr = pDevice->pDevice->CreateBlendState1(&BlendDesc, pp); + Assert(SUCCEEDED(hr)); + return hr; +} + + +static HRESULT dxDepthStencilStateCreate(DXDEVICE *pDevice, SVGACOTableDXDepthStencilEntry const *pEntry, ID3D11DepthStencilState **pp) +{ + D3D11_DEPTH_STENCIL_DESC desc; + desc.DepthEnable = pEntry->depthEnable; + desc.DepthWriteMask = (D3D11_DEPTH_WRITE_MASK)pEntry->depthWriteMask; + desc.DepthFunc = (D3D11_COMPARISON_FUNC)pEntry->depthFunc; + desc.StencilEnable = pEntry->stencilEnable; + desc.StencilReadMask = pEntry->stencilReadMask; + desc.StencilWriteMask = pEntry->stencilWriteMask; + desc.FrontFace.StencilFailOp = (D3D11_STENCIL_OP)pEntry->frontStencilFailOp; + desc.FrontFace.StencilDepthFailOp = (D3D11_STENCIL_OP)pEntry->frontStencilDepthFailOp; + desc.FrontFace.StencilPassOp = (D3D11_STENCIL_OP)pEntry->frontStencilPassOp; + desc.FrontFace.StencilFunc = (D3D11_COMPARISON_FUNC)pEntry->frontStencilFunc; + desc.BackFace.StencilFailOp = (D3D11_STENCIL_OP)pEntry->backStencilFailOp; + desc.BackFace.StencilDepthFailOp = (D3D11_STENCIL_OP)pEntry->backStencilDepthFailOp; + desc.BackFace.StencilPassOp = (D3D11_STENCIL_OP)pEntry->backStencilPassOp; + desc.BackFace.StencilFunc = (D3D11_COMPARISON_FUNC)pEntry->backStencilFunc; + /** @todo frontEnable, backEnable */ + + HRESULT hr = pDevice->pDevice->CreateDepthStencilState(&desc, pp); + Assert(SUCCEEDED(hr)); + return hr; +} + + +static HRESULT dxSamplerStateCreate(DXDEVICE *pDevice, SVGACOTableDXSamplerEntry const *pEntry, ID3D11SamplerState **pp) +{ + D3D11_SAMPLER_DESC desc; + /* Guest sometimes sends inconsistent (from D3D11 point of view) set of filter flags. */ + if (pEntry->filter & SVGA3D_FILTER_ANISOTROPIC) + desc.Filter = (pEntry->filter & SVGA3D_FILTER_COMPARE) + ? D3D11_FILTER_COMPARISON_ANISOTROPIC + : D3D11_FILTER_ANISOTROPIC; + else + desc.Filter = (D3D11_FILTER)pEntry->filter; + desc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)pEntry->addressU; + desc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)pEntry->addressV; + desc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)pEntry->addressW; + desc.MipLODBias = pEntry->mipLODBias; + desc.MaxAnisotropy = RT_CLAMP(pEntry->maxAnisotropy, 1, 16); /* "Valid values are between 1 and 16" */ + desc.ComparisonFunc = (D3D11_COMPARISON_FUNC)pEntry->comparisonFunc; + desc.BorderColor[0] = pEntry->borderColor.value[0]; + desc.BorderColor[1] = pEntry->borderColor.value[1]; + desc.BorderColor[2] = pEntry->borderColor.value[2]; + desc.BorderColor[3] = pEntry->borderColor.value[3]; + desc.MinLOD = pEntry->minLOD; + desc.MaxLOD = pEntry->maxLOD; + + HRESULT hr = pDevice->pDevice->CreateSamplerState(&desc, pp); + Assert(SUCCEEDED(hr)); + return hr; +} + + +static D3D11_FILL_MODE dxFillMode(uint8_t svgaFillMode) +{ + if (svgaFillMode == SVGA3D_FILLMODE_POINT) + return D3D11_FILL_WIREFRAME; + return (D3D11_FILL_MODE)svgaFillMode; +} + + +static D3D11_CULL_MODE dxCullMode(uint8_t svgaCullMode) +{ + return (D3D11_CULL_MODE)svgaCullMode; +} + + +static HRESULT dxRasterizerStateCreate(DXDEVICE *pDevice, SVGACOTableDXRasterizerStateEntry const *pEntry, ID3D11RasterizerState1 **pp) +{ + D3D11_RASTERIZER_DESC1 desc; + desc.FillMode = dxFillMode(pEntry->fillMode); + desc.CullMode = dxCullMode(pEntry->cullMode); + desc.FrontCounterClockwise = pEntry->frontCounterClockwise; + /** @todo provokingVertexLast */ + desc.DepthBias = pEntry->depthBias; + desc.DepthBiasClamp = pEntry->depthBiasClamp; + desc.SlopeScaledDepthBias = pEntry->slopeScaledDepthBias; + desc.DepthClipEnable = pEntry->depthClipEnable; + desc.ScissorEnable = pEntry->scissorEnable; + desc.MultisampleEnable = pEntry->multisampleEnable; + desc.AntialiasedLineEnable = pEntry->antialiasedLineEnable; + desc.ForcedSampleCount = pEntry->forcedSampleCount; + /** @todo lineWidth lineStippleEnable lineStippleFactor lineStipplePattern */ + + HRESULT hr = pDevice->pDevice->CreateRasterizerState1(&desc, pp); + Assert(SUCCEEDED(hr)); + return hr; +} + + +static HRESULT dxRenderTargetViewCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableDXRTViewEntry const *pEntry, VMSVGA3DSURFACE *pSurface, ID3D11RenderTargetView **pp) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + + ID3D11Resource *pResource = dxResource(pThisCC->svga.p3dState, pSurface, pDXContext); + + D3D11_RENDER_TARGET_VIEW_DESC desc; + RT_ZERO(desc); + desc.Format = vmsvgaDXSurfaceFormat2Dxgi(pEntry->format); + AssertReturn(desc.Format != DXGI_FORMAT_UNKNOWN || pEntry->format == SVGA3D_BUFFER, E_FAIL); + switch (pEntry->resourceDimension) + { + case SVGA3D_RESOURCE_BUFFER: + desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = pEntry->desc.buffer.firstElement; + desc.Buffer.NumElements = pEntry->desc.buffer.numElements; + break; + case SVGA3D_RESOURCE_TEXTURE1D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + { + desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D; + desc.Texture1D.MipSlice = pEntry->desc.tex.mipSlice; + } + else + { + desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY; + desc.Texture1DArray.MipSlice = pEntry->desc.tex.mipSlice; + desc.Texture1DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; + desc.Texture1DArray.ArraySize = pEntry->desc.tex.arraySize; + } + break; + case SVGA3D_RESOURCE_TEXTURE2D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + { + desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = pEntry->desc.tex.mipSlice; + } + else + { + desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MipSlice = pEntry->desc.tex.mipSlice; + desc.Texture2DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; + desc.Texture2DArray.ArraySize = pEntry->desc.tex.arraySize; + } + break; + case SVGA3D_RESOURCE_TEXTURE3D: + desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + desc.Texture3D.MipSlice = pEntry->desc.tex3D.mipSlice; + desc.Texture3D.FirstWSlice = pEntry->desc.tex3D.firstW; + desc.Texture3D.WSize = pEntry->desc.tex3D.wSize; + break; + case SVGA3D_RESOURCE_TEXTURECUBE: + desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MipSlice = pEntry->desc.tex.mipSlice; + desc.Texture2DArray.FirstArraySlice = 0; + desc.Texture2DArray.ArraySize = 6; + break; + case SVGA3D_RESOURCE_BUFFEREX: + AssertFailed(); /** @todo test. Probably not applicable to a render target view. */ + desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = pEntry->desc.buffer.firstElement; + desc.Buffer.NumElements = pEntry->desc.buffer.numElements; + break; + default: + ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); + } + + HRESULT hr = pDevice->pDevice->CreateRenderTargetView(pResource, &desc, pp); + Assert(SUCCEEDED(hr)); + return hr; +} + + +static HRESULT dxShaderResourceViewCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableDXSRViewEntry const *pEntry, VMSVGA3DSURFACE *pSurface, ID3D11ShaderResourceView **pp) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + + ID3D11Resource *pResource = dxResource(pThisCC->svga.p3dState, pSurface, pDXContext); + + D3D11_SHADER_RESOURCE_VIEW_DESC desc; + RT_ZERO(desc); + desc.Format = vmsvgaDXSurfaceFormat2Dxgi(pEntry->format); + AssertReturn(desc.Format != DXGI_FORMAT_UNKNOWN || pEntry->format == SVGA3D_BUFFER, E_FAIL); + + switch (pEntry->resourceDimension) + { + case SVGA3D_RESOURCE_BUFFER: + desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = pEntry->desc.buffer.firstElement; + desc.Buffer.NumElements = pEntry->desc.buffer.numElements; + break; + case SVGA3D_RESOURCE_TEXTURE1D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + { + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + desc.Texture1D.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; + desc.Texture1D.MipLevels = pEntry->desc.tex.mipLevels; + } + else + { + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + desc.Texture1DArray.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; + desc.Texture1DArray.MipLevels = pEntry->desc.tex.mipLevels; + desc.Texture1DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; + desc.Texture1DArray.ArraySize = pEntry->desc.tex.arraySize; + } + break; + case SVGA3D_RESOURCE_TEXTURE2D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + { + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; + desc.Texture2D.MipLevels = pEntry->desc.tex.mipLevels; + } + else + { + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; + desc.Texture2DArray.MipLevels = pEntry->desc.tex.mipLevels; + desc.Texture2DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; + desc.Texture2DArray.ArraySize = pEntry->desc.tex.arraySize; + } + break; + case SVGA3D_RESOURCE_TEXTURE3D: + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + desc.Texture3D.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; + desc.Texture3D.MipLevels = pEntry->desc.tex.mipLevels; + break; + case SVGA3D_RESOURCE_TEXTURECUBE: + if (pSurface->surfaceDesc.numArrayElements <= 6) + { + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + desc.TextureCube.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; + desc.TextureCube.MipLevels = pEntry->desc.tex.mipLevels; + } + else + { + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY; + desc.TextureCubeArray.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; + desc.TextureCubeArray.MipLevels = pEntry->desc.tex.mipLevels; + desc.TextureCubeArray.First2DArrayFace = pEntry->desc.tex.firstArraySlice; + desc.TextureCubeArray.NumCubes = pEntry->desc.tex.arraySize / 6; + } + break; + case SVGA3D_RESOURCE_BUFFEREX: + AssertFailed(); /** @todo test. */ + desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; + desc.BufferEx.FirstElement = pEntry->desc.bufferex.firstElement; + desc.BufferEx.NumElements = pEntry->desc.bufferex.numElements; + desc.BufferEx.Flags = pEntry->desc.bufferex.flags; + break; + default: + ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); + } + + HRESULT hr = pDevice->pDevice->CreateShaderResourceView(pResource, &desc, pp); + Assert(SUCCEEDED(hr)); + return hr; +} + + +static HRESULT dxUnorderedAccessViewCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableDXUAViewEntry const *pEntry, VMSVGA3DSURFACE *pSurface, ID3D11UnorderedAccessView **pp) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + + ID3D11Resource *pResource = dxResource(pThisCC->svga.p3dState, pSurface, pDXContext); + + D3D11_UNORDERED_ACCESS_VIEW_DESC desc; + RT_ZERO(desc); + desc.Format = vmsvgaDXSurfaceFormat2Dxgi(pEntry->format); + AssertReturn(desc.Format != DXGI_FORMAT_UNKNOWN || pEntry->format == SVGA3D_BUFFER, E_FAIL); + + switch (pEntry->resourceDimension) + { + case SVGA3D_RESOURCE_BUFFER: + desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = pEntry->desc.buffer.firstElement; + desc.Buffer.NumElements = pEntry->desc.buffer.numElements; + desc.Buffer.Flags = pEntry->desc.buffer.flags; + break; + case SVGA3D_RESOURCE_TEXTURE1D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + { + desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D; + desc.Texture1D.MipSlice = pEntry->desc.tex.mipSlice; + } + else + { + desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY; + desc.Texture1DArray.MipSlice = pEntry->desc.tex.mipSlice; + desc.Texture1DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; + desc.Texture1DArray.ArraySize = pEntry->desc.tex.arraySize; + } + break; + case SVGA3D_RESOURCE_TEXTURE2D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + { + desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = pEntry->desc.tex.mipSlice; + } + else + { + desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MipSlice = pEntry->desc.tex.mipSlice; + desc.Texture2DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; + desc.Texture2DArray.ArraySize = pEntry->desc.tex.arraySize; + } + break; + case SVGA3D_RESOURCE_TEXTURE3D: + desc.Texture3D.MipSlice = pEntry->desc.tex3D.mipSlice; + desc.Texture3D.FirstWSlice = pEntry->desc.tex3D.firstW; + desc.Texture3D.WSize = pEntry->desc.tex3D.wSize; + break; + default: + ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); + } + + HRESULT hr = pDevice->pDevice->CreateUnorderedAccessView(pResource, &desc, pp); + Assert(SUCCEEDED(hr)); + return hr; +} + + +static HRESULT dxDepthStencilViewCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableDXDSViewEntry const *pEntry, VMSVGA3DSURFACE *pSurface, ID3D11DepthStencilView **pp) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + + ID3D11Resource *pResource = dxResource(pThisCC->svga.p3dState, pSurface, pDXContext); + + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + RT_ZERO(desc); + desc.Format = vmsvgaDXSurfaceFormat2Dxgi(pEntry->format); + AssertReturn(desc.Format != DXGI_FORMAT_UNKNOWN || pEntry->format == SVGA3D_BUFFER, E_FAIL); + desc.Flags = pEntry->flags; + switch (pEntry->resourceDimension) + { + case SVGA3D_RESOURCE_TEXTURE1D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + { + desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D; + desc.Texture1D.MipSlice = pEntry->mipSlice; + } + else + { + desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY; + desc.Texture1DArray.MipSlice = pEntry->mipSlice; + desc.Texture1DArray.FirstArraySlice = pEntry->firstArraySlice; + desc.Texture1DArray.ArraySize = pEntry->arraySize; + } + break; + case SVGA3D_RESOURCE_TEXTURE2D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + { + desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = pEntry->mipSlice; + } + else + { + desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MipSlice = pEntry->mipSlice; + desc.Texture2DArray.FirstArraySlice = pEntry->firstArraySlice; + desc.Texture2DArray.ArraySize = pEntry->arraySize; + } + break; + default: + ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); + } + + HRESULT hr = pDevice->pDevice->CreateDepthStencilView(pResource, &desc, pp); + Assert(SUCCEEDED(hr)); + return hr; +} + + +static HRESULT dxShaderCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, DXSHADER *pDXShader) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + + HRESULT hr = S_OK; + + switch (pDXShader->enmShaderType) + { + case SVGA3D_SHADERTYPE_VS: + hr = pDevice->pDevice->CreateVertexShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pVertexShader); + Assert(SUCCEEDED(hr)); + break; + case SVGA3D_SHADERTYPE_PS: + hr = pDevice->pDevice->CreatePixelShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pPixelShader); + Assert(SUCCEEDED(hr)); + break; + case SVGA3D_SHADERTYPE_GS: + { + SVGA3dStreamOutputId const soid = pDXContext->svgaDXContext.streamOut.soid; + if (soid == SVGA_ID_INVALID) + { + hr = pDevice->pDevice->CreateGeometryShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pGeometryShader); + Assert(SUCCEEDED(hr)); + } + else + { + ASSERT_GUEST_RETURN(soid < pDXContext->pBackendDXContext->cStreamOutput, E_INVALIDARG); + + SVGACOTableDXStreamOutputEntry const *pEntry = &pDXContext->cot.paStreamOutput[soid]; + DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; + + hr = pDevice->pDevice->CreateGeometryShaderWithStreamOutput(pDXShader->pvDXBC, pDXShader->cbDXBC, + pDXStreamOutput->aDeclarationEntry, pDXStreamOutput->cDeclarationEntry, + pEntry->numOutputStreamStrides ? pEntry->streamOutputStrideInBytes : NULL, pEntry->numOutputStreamStrides, + pEntry->rasterizedStream, + /*pClassLinkage=*/ NULL, &pDXShader->pGeometryShader); + AssertBreak(SUCCEEDED(hr)); + + pDXShader->soid = soid; + } + break; + } + case SVGA3D_SHADERTYPE_HS: + hr = pDevice->pDevice->CreateHullShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pHullShader); + Assert(SUCCEEDED(hr)); + break; + case SVGA3D_SHADERTYPE_DS: + hr = pDevice->pDevice->CreateDomainShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pDomainShader); + Assert(SUCCEEDED(hr)); + break; + case SVGA3D_SHADERTYPE_CS: + hr = pDevice->pDevice->CreateComputeShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pComputeShader); + Assert(SUCCEEDED(hr)); + break; + default: + ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); + } + + return hr; +} + + +static void dxShaderSet(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderType type, DXSHADER *pDXShader) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + + switch (type) + { + case SVGA3D_SHADERTYPE_VS: + pDevice->pImmediateContext->VSSetShader(pDXShader ? pDXShader->pVertexShader : NULL, NULL, 0); + break; + case SVGA3D_SHADERTYPE_PS: + pDevice->pImmediateContext->PSSetShader(pDXShader ? pDXShader->pPixelShader : NULL, NULL, 0); + break; + case SVGA3D_SHADERTYPE_GS: + { + Assert(!pDXShader || (pDXShader->soid == pDXContext->svgaDXContext.streamOut.soid)); + pDevice->pImmediateContext->GSSetShader(pDXShader ? pDXShader->pGeometryShader : NULL, NULL, 0); + } break; + case SVGA3D_SHADERTYPE_HS: + pDevice->pImmediateContext->HSSetShader(pDXShader ? pDXShader->pHullShader : NULL, NULL, 0); + break; + case SVGA3D_SHADERTYPE_DS: + pDevice->pImmediateContext->DSSetShader(pDXShader ? pDXShader->pDomainShader : NULL, NULL, 0); + break; + case SVGA3D_SHADERTYPE_CS: + pDevice->pImmediateContext->CSSetShader(pDXShader ? pDXShader->pComputeShader : NULL, NULL, 0); + break; + default: + ASSERT_GUEST_FAILED_RETURN_VOID(); + } +} + + +static void dxConstantBufferSet(DXDEVICE *pDevice, uint32_t slot, SVGA3dShaderType type, ID3D11Buffer *pConstantBuffer) +{ + switch (type) + { + case SVGA3D_SHADERTYPE_VS: + pDevice->pImmediateContext->VSSetConstantBuffers(slot, 1, &pConstantBuffer); + break; + case SVGA3D_SHADERTYPE_PS: + pDevice->pImmediateContext->PSSetConstantBuffers(slot, 1, &pConstantBuffer); + break; + case SVGA3D_SHADERTYPE_GS: + pDevice->pImmediateContext->GSSetConstantBuffers(slot, 1, &pConstantBuffer); + break; + case SVGA3D_SHADERTYPE_HS: + pDevice->pImmediateContext->HSSetConstantBuffers(slot, 1, &pConstantBuffer); + break; + case SVGA3D_SHADERTYPE_DS: + pDevice->pImmediateContext->DSSetConstantBuffers(slot, 1, &pConstantBuffer); + break; + case SVGA3D_SHADERTYPE_CS: + pDevice->pImmediateContext->CSSetConstantBuffers(slot, 1, &pConstantBuffer); + break; + default: + ASSERT_GUEST_FAILED_RETURN_VOID(); + } +} + + +static void dxSamplerSet(DXDEVICE *pDevice, SVGA3dShaderType type, uint32_t startSampler, uint32_t cSampler, ID3D11SamplerState * const *papSampler) +{ + switch (type) + { + case SVGA3D_SHADERTYPE_VS: + pDevice->pImmediateContext->VSSetSamplers(startSampler, cSampler, papSampler); + break; + case SVGA3D_SHADERTYPE_PS: + pDevice->pImmediateContext->PSSetSamplers(startSampler, cSampler, papSampler); + break; + case SVGA3D_SHADERTYPE_GS: + pDevice->pImmediateContext->GSSetSamplers(startSampler, cSampler, papSampler); + break; + case SVGA3D_SHADERTYPE_HS: + pDevice->pImmediateContext->HSSetSamplers(startSampler, cSampler, papSampler); + break; + case SVGA3D_SHADERTYPE_DS: + pDevice->pImmediateContext->DSSetSamplers(startSampler, cSampler, papSampler); + break; + case SVGA3D_SHADERTYPE_CS: + pDevice->pImmediateContext->CSSetSamplers(startSampler, cSampler, papSampler); + break; + default: + ASSERT_GUEST_FAILED_RETURN_VOID(); + } +} + + +static void dxShaderResourceViewSet(DXDEVICE *pDevice, SVGA3dShaderType type, uint32_t startView, uint32_t cShaderResourceView, ID3D11ShaderResourceView * const *papShaderResourceView) +{ + switch (type) + { + case SVGA3D_SHADERTYPE_VS: + pDevice->pImmediateContext->VSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); + break; + case SVGA3D_SHADERTYPE_PS: + pDevice->pImmediateContext->PSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); + break; + case SVGA3D_SHADERTYPE_GS: + pDevice->pImmediateContext->GSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); + break; + case SVGA3D_SHADERTYPE_HS: + pDevice->pImmediateContext->HSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); + break; + case SVGA3D_SHADERTYPE_DS: + pDevice->pImmediateContext->DSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); + break; + case SVGA3D_SHADERTYPE_CS: + pDevice->pImmediateContext->CSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); + break; + default: + ASSERT_GUEST_FAILED_RETURN_VOID(); + } +} + + +static void dxCSUnorderedAccessViewSet(DXDEVICE *pDevice, uint32_t startView, uint32_t cView, ID3D11UnorderedAccessView * const *papUnorderedAccessView, UINT *pUAVInitialCounts) +{ + pDevice->pImmediateContext->CSSetUnorderedAccessViews(startView, cView, papUnorderedAccessView, pUAVInitialCounts); +} + + +static int dxBackendSurfaceAlloc(PVMSVGA3DBACKENDSURFACE *ppBackendSurface) +{ + PVMSVGA3DBACKENDSURFACE pBackendSurface = (PVMSVGA3DBACKENDSURFACE)RTMemAllocZ(sizeof(VMSVGA3DBACKENDSURFACE)); + AssertPtrReturn(pBackendSurface, VERR_NO_MEMORY); + pBackendSurface->cidDrawing = SVGA_ID_INVALID; + RTListInit(&pBackendSurface->listView); + *ppBackendSurface = pBackendSurface; + return VINF_SUCCESS; +} + + +static HRESULT dxInitSharedHandle(PVMSVGA3DBACKEND pBackend, PVMSVGA3DBACKENDSURFACE pBackendSurface) +{ + if (pBackend->fSingleDevice) + return S_OK; + + /* Get the shared handle. */ + IDXGIResource *pDxgiResource = NULL; + HRESULT hr = pBackendSurface->u.pResource->QueryInterface(__uuidof(IDXGIResource), (void**)&pDxgiResource); + Assert(SUCCEEDED(hr)); + if (SUCCEEDED(hr)) + { + hr = pDxgiResource->GetSharedHandle(&pBackendSurface->SharedHandle); + Assert(SUCCEEDED(hr)); + D3D_RELEASE(pDxgiResource); + } + + return hr; +} + + +static UINT dxBindFlags(SVGA3dSurfaceAllFlags surfaceFlags) +{ + /* Catch unimplemented flags. */ + Assert(!RT_BOOL(surfaceFlags & (SVGA3D_SURFACE_BIND_LOGICOPS | SVGA3D_SURFACE_BIND_RAW_VIEWS))); + + UINT BindFlags = 0; + + if (surfaceFlags & (SVGA3D_SURFACE_BIND_VERTEX_BUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER)) + BindFlags |= D3D11_BIND_VERTEX_BUFFER; + if (surfaceFlags & (SVGA3D_SURFACE_BIND_INDEX_BUFFER | SVGA3D_SURFACE_HINT_INDEXBUFFER)) + BindFlags |= D3D11_BIND_INDEX_BUFFER; + if (surfaceFlags & SVGA3D_SURFACE_BIND_CONSTANT_BUFFER) BindFlags |= D3D11_BIND_CONSTANT_BUFFER; + if (surfaceFlags & SVGA3D_SURFACE_BIND_SHADER_RESOURCE) BindFlags |= D3D11_BIND_SHADER_RESOURCE; + if (surfaceFlags & SVGA3D_SURFACE_BIND_RENDER_TARGET) BindFlags |= D3D11_BIND_RENDER_TARGET; + if (surfaceFlags & SVGA3D_SURFACE_BIND_DEPTH_STENCIL) BindFlags |= D3D11_BIND_DEPTH_STENCIL; + if (surfaceFlags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) BindFlags |= D3D11_BIND_STREAM_OUTPUT; + if (surfaceFlags & SVGA3D_SURFACE_BIND_UAVIEW) BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + + return BindFlags; +} + + +static DXDEVICE *dxSurfaceDevice(PVMSVGA3DSTATE p3dState, PVMSVGA3DSURFACE pSurface, PVMSVGA3DDXCONTEXT pDXContext, UINT *pMiscFlags) +{ + if (p3dState->pBackend->fSingleDevice) + { + *pMiscFlags = 0; + return &p3dState->pBackend->dxDevice; + } + + if (!pDXContext || dxIsSurfaceShareable(pSurface)) + { + *pMiscFlags = D3D11_RESOURCE_MISC_SHARED; + return &p3dState->pBackend->dxDevice; + } + + *pMiscFlags = 0; + return &pDXContext->pBackendDXContext->dxDevice; +} + + +static DXGI_FORMAT dxGetDxgiTypelessFormat(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return DXGI_FORMAT_R32G32B32A32_TYPELESS; /* 1 */ + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return DXGI_FORMAT_R32G32B32_TYPELESS; /* 5 */ + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + return DXGI_FORMAT_R16G16B16A16_TYPELESS; /* 9 */ + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + return DXGI_FORMAT_R32G32_TYPELESS; /* 15 */ + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return DXGI_FORMAT_R32G8X24_TYPELESS; /* 19 */ + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + return DXGI_FORMAT_R10G10B10A2_TYPELESS; /* 23 */ + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + return DXGI_FORMAT_R8G8B8A8_TYPELESS; /* 27 */ + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + return DXGI_FORMAT_R16G16_TYPELESS; /* 33 */ + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + return DXGI_FORMAT_R32_TYPELESS; /* 39 */ + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return DXGI_FORMAT_R24G8_TYPELESS; /* 44 */ + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + return DXGI_FORMAT_R8G8_TYPELESS; /* 48*/ + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + return DXGI_FORMAT_R16_TYPELESS; /* 53 */ + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + return DXGI_FORMAT_R8_TYPELESS; /* 60*/ + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + return DXGI_FORMAT_BC1_TYPELESS; /* 70 */ + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + return DXGI_FORMAT_BC2_TYPELESS; /* 73 */ + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + return DXGI_FORMAT_BC3_TYPELESS; /* 76 */ + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return DXGI_FORMAT_BC4_TYPELESS; /* 79 */ + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + return DXGI_FORMAT_BC5_TYPELESS; /* 82 */ + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8A8_TYPELESS; /* 90 */ + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8X8_TYPELESS; /* 92 */ + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + return DXGI_FORMAT_BC6H_TYPELESS; /* 94 */ + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return DXGI_FORMAT_BC7_TYPELESS; /* 97 */ + default: + break; + } + + return dxgiFormat; +} + + +static bool dxIsDepthStencilFormat(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_D16_UNORM: + return true; + default: + break; + } + + return false; +} + + +static int vmsvga3dBackSurfaceCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface) +{ + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = p3dState->pBackend; + AssertReturn(pBackend, VERR_INVALID_STATE); + + UINT MiscFlags; + DXDEVICE *pDXDevice = dxSurfaceDevice(p3dState, pSurface, pDXContext, &MiscFlags); + AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); + + if (pSurface->pBackendSurface != NULL) + { + AssertFailed(); /** @todo Should the function not be used like that? */ + vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); + } + + PVMSVGA3DBACKENDSURFACE pBackendSurface; + int rc = dxBackendSurfaceAlloc(&pBackendSurface); + AssertRCReturn(rc, rc); + + uint32_t const cWidth = pSurface->paMipmapLevels[0].cBlocksX * pSurface->cxBlock; + uint32_t const cHeight = pSurface->paMipmapLevels[0].cBlocksY * pSurface->cyBlock; + uint32_t const cDepth = pSurface->paMipmapLevels[0].mipmapSize.depth; + uint32_t const numMipLevels = pSurface->cLevels; + + DXGI_FORMAT dxgiFormat = vmsvgaDXSurfaceFormat2Dxgi(pSurface->format); + AssertReturn(dxgiFormat != DXGI_FORMAT_UNKNOWN, E_FAIL); + + /* Create typeless textures, unless it is a depth/stencil resource, + * because D3D11_BIND_DEPTH_STENCIL requires a depth/stencil format. + * Always use typeless format for staging/dynamic resources. + */ + DXGI_FORMAT const dxgiFormatTypeless = dxGetDxgiTypelessFormat(dxgiFormat); + if (!dxIsDepthStencilFormat(dxgiFormat)) + dxgiFormat = dxgiFormatTypeless; + + /* Format for staging resource is always the typeless one. */ + DXGI_FORMAT const dxgiFormatStaging = dxgiFormatTypeless; + + DXGI_FORMAT dxgiFormatDynamic; + /* Some drivers do not allow to use depth typeless formats for dynamic resources. + * Create a placeholder texture (it does not work with CopySubresource). + */ + /** @todo Implement upload from such textures. */ + if (dxgiFormatTypeless == DXGI_FORMAT_R24G8_TYPELESS) + dxgiFormatDynamic = DXGI_FORMAT_R32_UINT; + else if (dxgiFormatTypeless == DXGI_FORMAT_R32G8X24_TYPELESS) + dxgiFormatDynamic = DXGI_FORMAT_R32G32_UINT; + else + dxgiFormatDynamic = dxgiFormatTypeless; + + /* + * Create D3D11 texture object. + */ + D3D11_SUBRESOURCE_DATA *paInitialData = NULL; + if (pSurface->paMipmapLevels[0].pSurfaceData) + { + /* Can happen for a non GBO surface or if GBO texture was updated prior to creation of the hardware resource. */ + uint32_t const cSubresource = numMipLevels * pSurface->surfaceDesc.numArrayElements; + paInitialData = (D3D11_SUBRESOURCE_DATA *)RTMemAlloc(cSubresource * sizeof(D3D11_SUBRESOURCE_DATA)); + AssertPtrReturn(paInitialData, VERR_NO_MEMORY); + + for (uint32_t i = 0; i < cSubresource; ++i) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i]; + D3D11_SUBRESOURCE_DATA *p = &paInitialData[i]; + p->pSysMem = pMipmapLevel->pSurfaceData; + p->SysMemPitch = pMipmapLevel->cbSurfacePitch; + p->SysMemSlicePitch = pMipmapLevel->cbSurfacePlane; + } + } + + HRESULT hr = S_OK; + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_CUBEMAP) + { + Assert(pSurface->cFaces == 6); + Assert(cWidth == cHeight); + Assert(cDepth == 1); +//DEBUG_BREAKPOINT_TEST(); + + D3D11_TEXTURE2D_DESC td; + RT_ZERO(td); + td.Width = cWidth; + td.Height = cHeight; + td.MipLevels = numMipLevels; + td.ArraySize = pSurface->surfaceDesc.numArrayElements; /* This is 6 * numCubes */ + td.Format = dxgiFormat; + td.SampleDesc.Count = 1; + td.SampleDesc.Quality = 0; + td.Usage = D3D11_USAGE_DEFAULT; + td.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); + td.CPUAccessFlags = 0; /** @todo */ + td.MiscFlags = MiscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE; /** @todo */ + if ( numMipLevels > 1 + && (td.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) == (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) + td.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; /* Required for GenMips. */ + + hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->u.pTexture2D); + Assert(SUCCEEDED(hr)); + if (SUCCEEDED(hr)) + { + /* Map-able texture. */ + td.Format = dxgiFormatDynamic; + td.MipLevels = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ + td.ArraySize = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ + td.Usage = D3D11_USAGE_DYNAMIC; + td.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ + td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + td.MiscFlags = 0; + hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->dynamic.pTexture2D); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + { + /* Staging texture. */ + td.Format = dxgiFormatStaging; + td.Usage = D3D11_USAGE_STAGING; + td.BindFlags = 0; /* No flags allowed. */ + td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + td.MiscFlags = 0; + hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->staging.pTexture2D); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + hr = dxInitSharedHandle(pBackend, pBackendSurface); + + if (SUCCEEDED(hr)) + { + pBackendSurface->enmResType = VMSVGA3D_RESTYPE_TEXTURE_CUBE; + } + } + else if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_1D) + { + /* + * 1D texture. + */ + Assert(pSurface->cFaces == 1); + + D3D11_TEXTURE1D_DESC td; + RT_ZERO(td); + td.Width = cWidth; + td.MipLevels = numMipLevels; + td.ArraySize = pSurface->surfaceDesc.numArrayElements; + td.Format = dxgiFormat; + td.Usage = D3D11_USAGE_DEFAULT; + td.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); + td.CPUAccessFlags = 0; + td.MiscFlags = MiscFlags; /** @todo */ + if ( numMipLevels > 1 + && (td.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) == (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) + td.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; /* Required for GenMips. */ + + hr = pDXDevice->pDevice->CreateTexture1D(&td, paInitialData, &pBackendSurface->u.pTexture1D); + Assert(SUCCEEDED(hr)); + if (SUCCEEDED(hr)) + { + /* Map-able texture. */ + td.Format = dxgiFormatDynamic; + td.MipLevels = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ + td.ArraySize = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ + td.Usage = D3D11_USAGE_DYNAMIC; + td.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ + td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + td.MiscFlags = 0; + hr = pDXDevice->pDevice->CreateTexture1D(&td, paInitialData, &pBackendSurface->dynamic.pTexture1D); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + { + /* Staging texture. */ + td.Format = dxgiFormatStaging; + td.Usage = D3D11_USAGE_STAGING; + td.BindFlags = 0; /* No flags allowed. */ + td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + td.MiscFlags = 0; + hr = pDXDevice->pDevice->CreateTexture1D(&td, paInitialData, &pBackendSurface->staging.pTexture1D); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + hr = dxInitSharedHandle(pBackend, pBackendSurface); + + if (SUCCEEDED(hr)) + { + pBackendSurface->enmResType = VMSVGA3D_RESTYPE_TEXTURE_1D; + } + } + else + { + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_VOLUME) + { + /* + * Volume texture. + */ + Assert(pSurface->cFaces == 1); + Assert(pSurface->surfaceDesc.numArrayElements == 1); + + D3D11_TEXTURE3D_DESC td; + RT_ZERO(td); + td.Width = cWidth; + td.Height = cHeight; + td.Depth = cDepth; + td.MipLevels = numMipLevels; + td.Format = dxgiFormat; + td.Usage = D3D11_USAGE_DEFAULT; + td.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); + td.CPUAccessFlags = 0; /** @todo */ + td.MiscFlags = MiscFlags; /** @todo */ + if ( numMipLevels > 1 + && (td.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) == (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) + td.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; /* Required for GenMips. */ + + hr = pDXDevice->pDevice->CreateTexture3D(&td, paInitialData, &pBackendSurface->u.pTexture3D); + Assert(SUCCEEDED(hr)); + if (SUCCEEDED(hr)) + { + /* Map-able texture. */ + td.Format = dxgiFormatDynamic; + td.MipLevels = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ + td.Usage = D3D11_USAGE_DYNAMIC; + td.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ + td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + td.MiscFlags = 0; + hr = pDXDevice->pDevice->CreateTexture3D(&td, paInitialData, &pBackendSurface->dynamic.pTexture3D); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + { + /* Staging texture. */ + td.Format = dxgiFormatStaging; + td.Usage = D3D11_USAGE_STAGING; + td.BindFlags = 0; /* No flags allowed. */ + td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + td.MiscFlags = 0; + hr = pDXDevice->pDevice->CreateTexture3D(&td, paInitialData, &pBackendSurface->staging.pTexture3D); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + hr = dxInitSharedHandle(pBackend, pBackendSurface); + + if (SUCCEEDED(hr)) + { + pBackendSurface->enmResType = VMSVGA3D_RESTYPE_TEXTURE_3D; + } + } + else + { + /* + * 2D texture. + */ + Assert(cDepth == 1); + Assert(pSurface->cFaces == 1); + + D3D11_TEXTURE2D_DESC td; + RT_ZERO(td); + td.Width = cWidth; + td.Height = cHeight; + td.MipLevels = numMipLevels; + td.ArraySize = pSurface->surfaceDesc.numArrayElements; + td.Format = dxgiFormat; + td.SampleDesc.Count = 1; + td.SampleDesc.Quality = 0; + td.Usage = D3D11_USAGE_DEFAULT; + td.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); + td.CPUAccessFlags = 0; /** @todo */ + td.MiscFlags = MiscFlags; /** @todo */ + if ( numMipLevels > 1 + && (td.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) == (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) + td.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; /* Required for GenMips. */ + + hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->u.pTexture2D); + Assert(SUCCEEDED(hr)); + if (SUCCEEDED(hr)) + { + /* Map-able texture. */ + td.Format = dxgiFormatDynamic; + td.MipLevels = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ + td.ArraySize = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ + td.Usage = D3D11_USAGE_DYNAMIC; + td.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ + td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + td.MiscFlags = 0; + hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->dynamic.pTexture2D); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + { + /* Staging texture. */ + td.Format = dxgiFormatStaging; + td.Usage = D3D11_USAGE_STAGING; + td.BindFlags = 0; /* No flags allowed. */ + td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + td.MiscFlags = 0; + hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->staging.pTexture2D); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + hr = dxInitSharedHandle(pBackend, pBackendSurface); + + if (SUCCEEDED(hr)) + { + pBackendSurface->enmResType = VMSVGA3D_RESTYPE_TEXTURE_2D; + } + } + } + + if (hr == DXGI_ERROR_DEVICE_REMOVED) + { + DEBUG_BREAKPOINT_TEST(); + hr = pDXDevice->pDevice->GetDeviceRemovedReason(); + } + + Assert(hr == S_OK); + + RTMemFree(paInitialData); + + if (pSurface->autogenFilter != SVGA3D_TEX_FILTER_NONE) + { + } + + if (SUCCEEDED(hr)) + { + /* + * Success. + */ + LogFunc(("sid = %u\n", pSurface->id)); + pBackendSurface->enmDxgiFormat = dxgiFormat; + pSurface->pBackendSurface = pBackendSurface; + if (p3dState->pBackend->fSingleDevice || RT_BOOL(MiscFlags & D3D11_RESOURCE_MISC_SHARED)) + pSurface->idAssociatedContext = DX_CID_BACKEND; + else + pSurface->idAssociatedContext = pDXContext->cid; + return VINF_SUCCESS; + } + + D3D_RELEASE(pBackendSurface->staging.pResource); + D3D_RELEASE(pBackendSurface->dynamic.pResource); + D3D_RELEASE(pBackendSurface->u.pResource); + RTMemFree(pBackendSurface); + return VERR_NO_MEMORY; +} + + +static int vmsvga3dBackSurfaceCreateBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* Buffers should be created as such. */ + AssertReturn(RT_BOOL(pSurface->f.surfaceFlags & ( SVGA3D_SURFACE_HINT_INDEXBUFFER + | SVGA3D_SURFACE_HINT_VERTEXBUFFER + | SVGA3D_SURFACE_BIND_VERTEX_BUFFER + | SVGA3D_SURFACE_BIND_INDEX_BUFFER + )), VERR_INVALID_PARAMETER); + + if (pSurface->pBackendSurface != NULL) + { + AssertFailed(); /** @todo Should the function not be used like that? */ + vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); + } + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + int rc = vmsvga3dMipmapLevel(pSurface, 0, 0, &pMipLevel); + AssertRCReturn(rc, rc); + + PVMSVGA3DBACKENDSURFACE pBackendSurface; + rc = dxBackendSurfaceAlloc(&pBackendSurface); + AssertRCReturn(rc, rc); + + LogFunc(("sid = %u, size = %u\n", pSurface->id, pMipLevel->cbSurface)); + + /* Upload the current data, if any. */ + D3D11_SUBRESOURCE_DATA *pInitialData = NULL; + D3D11_SUBRESOURCE_DATA initialData; + if (pMipLevel->pSurfaceData) + { + initialData.pSysMem = pMipLevel->pSurfaceData; + initialData.SysMemPitch = pMipLevel->cbSurface; + initialData.SysMemSlicePitch = pMipLevel->cbSurface; + + pInitialData = &initialData; + } + + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = pMipLevel->cbSurface; + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); + + HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->u.pBuffer); + Assert(SUCCEEDED(hr)); +#ifndef DX_COMMON_STAGING_BUFFER + if (SUCCEEDED(hr)) + { + /* Map-able Buffer. */ + bd.Usage = D3D11_USAGE_DYNAMIC; + bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->dynamic.pBuffer); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + { + /* Staging texture. */ + bd.Usage = D3D11_USAGE_STAGING; + bd.BindFlags = 0; /* No flags allowed. */ + bd.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->staging.pBuffer); + Assert(SUCCEEDED(hr)); + } +#endif + + if (SUCCEEDED(hr)) + { + /* + * Success. + */ + pBackendSurface->enmResType = VMSVGA3D_RESTYPE_BUFFER; + pBackendSurface->enmDxgiFormat = DXGI_FORMAT_UNKNOWN; + pSurface->pBackendSurface = pBackendSurface; + pSurface->idAssociatedContext = pDXContext->cid; + return VINF_SUCCESS; + } + + /* Failure. */ + D3D_RELEASE(pBackendSurface->u.pBuffer); +#ifndef DX_COMMON_STAGING_BUFFER + D3D_RELEASE(pBackendSurface->dynamic.pBuffer); + D3D_RELEASE(pBackendSurface->staging.pBuffer); +#endif + RTMemFree(pBackendSurface); + return VERR_NO_MEMORY; +} + + +static int vmsvga3dBackSurfaceCreateSoBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* Buffers should be created as such. */ + AssertReturn(RT_BOOL(pSurface->f.surfaceFlags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT), VERR_INVALID_PARAMETER); + + if (pSurface->pBackendSurface != NULL) + { + AssertFailed(); /** @todo Should the function not be used like that? */ + vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); + } + + PVMSVGA3DBACKENDSURFACE pBackendSurface; + int rc = dxBackendSurfaceAlloc(&pBackendSurface); + AssertRCReturn(rc, rc); + + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = pSurface->paMipmapLevels[0].cbSurface; + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); + bd.CPUAccessFlags = 0; /// @todo ? D3D11_CPU_ACCESS_READ; + bd.MiscFlags = 0; + bd.StructureByteStride = 0; + + HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, 0, &pBackendSurface->u.pBuffer); +#ifndef DX_COMMON_STAGING_BUFFER + if (SUCCEEDED(hr)) + { + /* Map-able Buffer. */ + bd.Usage = D3D11_USAGE_DYNAMIC; + bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + hr = pDevice->pDevice->CreateBuffer(&bd, 0, &pBackendSurface->dynamic.pBuffer); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + { + /* Staging texture. */ + bd.Usage = D3D11_USAGE_STAGING; + bd.BindFlags = 0; /* No flags allowed. */ + bd.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + hr = pDevice->pDevice->CreateBuffer(&bd, 0, &pBackendSurface->staging.pBuffer); + Assert(SUCCEEDED(hr)); + } +#endif + + if (SUCCEEDED(hr)) + { + /* + * Success. + */ + pBackendSurface->enmResType = VMSVGA3D_RESTYPE_BUFFER; + pBackendSurface->enmDxgiFormat = DXGI_FORMAT_UNKNOWN; + pSurface->pBackendSurface = pBackendSurface; + pSurface->idAssociatedContext = pDXContext->cid; + return VINF_SUCCESS; + } + + /* Failure. */ + D3D_RELEASE(pBackendSurface->u.pBuffer); +#ifndef DX_COMMON_STAGING_BUFFER + D3D_RELEASE(pBackendSurface->dynamic.pBuffer); + D3D_RELEASE(pBackendSurface->staging.pBuffer); +#endif + RTMemFree(pBackendSurface); + return VERR_NO_MEMORY; +} + +#if 0 +static int vmsvga3dBackSurfaceCreateConstantBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface, uint32_t offsetInBytes, uint32_t sizeInBytes) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* Buffers should be created as such. */ + AssertReturn(RT_BOOL(pSurface->f.surfaceFlags & ( SVGA3D_SURFACE_BIND_CONSTANT_BUFFER)), VERR_INVALID_PARAMETER); + + if (pSurface->pBackendSurface != NULL) + { + AssertFailed(); /** @todo Should the function not be used like that? */ + vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); + } + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + int rc = vmsvga3dMipmapLevel(pSurface, 0, 0, &pMipLevel); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN( offsetInBytes < pMipLevel->cbSurface + && sizeInBytes <= pMipLevel->cbSurface - offsetInBytes, VERR_INVALID_PARAMETER); + + PVMSVGA3DBACKENDSURFACE pBackendSurface; + rc = dxBackendSurfaceAlloc(&pBackendSurface); + AssertRCReturn(rc, rc); + + /* Upload the current data, if any. */ + D3D11_SUBRESOURCE_DATA *pInitialData = NULL; + D3D11_SUBRESOURCE_DATA initialData; + if (pMipLevel->pSurfaceData) + { + initialData.pSysMem = (uint8_t *)pMipLevel->pSurfaceData + offsetInBytes; + initialData.SysMemPitch = pMipLevel->cbSurface; + initialData.SysMemSlicePitch = pMipLevel->cbSurface; + + pInitialData = &initialData; + + // Log(("%.*Rhxd\n", sizeInBytes, initialData.pSysMem)); + } + + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = sizeInBytes; + bd.Usage = D3D11_USAGE_DYNAMIC; + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bd.MiscFlags = 0; + bd.StructureByteStride = 0; + + HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->u.pBuffer); + if (SUCCEEDED(hr)) + { + /* + * Success. + */ + pBackendSurface->enmResType = VMSVGA3D_RESTYPE_BUFFER; + pBackendSurface->enmDxgiFormat = DXGI_FORMAT_UNKNOWN; + pSurface->pBackendSurface = pBackendSurface; + pSurface->idAssociatedContext = pDXContext->cid; + return VINF_SUCCESS; + } + + /* Failure. */ + D3D_RELEASE(pBackendSurface->u.pBuffer); + RTMemFree(pBackendSurface); + return VERR_NO_MEMORY; +} +#endif + +static int vmsvga3dBackSurfaceCreateResource(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + if (pSurface->pBackendSurface != NULL) + { + AssertFailed(); /** @todo Should the function not be used like that? */ + vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); + } + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + int rc = vmsvga3dMipmapLevel(pSurface, 0, 0, &pMipLevel); + AssertRCReturn(rc, rc); + + PVMSVGA3DBACKENDSURFACE pBackendSurface; + rc = dxBackendSurfaceAlloc(&pBackendSurface); + AssertRCReturn(rc, rc); + + HRESULT hr; + + /* + * Figure out the type of the surface. + */ + if (pSurface->format == SVGA3D_BUFFER) + { + /* Upload the current data, if any. */ + D3D11_SUBRESOURCE_DATA *pInitialData = NULL; + D3D11_SUBRESOURCE_DATA initialData; + if (pMipLevel->pSurfaceData) + { + initialData.pSysMem = pMipLevel->pSurfaceData; + initialData.SysMemPitch = pMipLevel->cbSurface; + initialData.SysMemSlicePitch = pMipLevel->cbSurface; + + pInitialData = &initialData; + } + + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = pMipLevel->cbSurface; + + if (pSurface->f.surfaceFlags & (SVGA3D_SURFACE_STAGING_UPLOAD | SVGA3D_SURFACE_STAGING_DOWNLOAD)) + bd.Usage = D3D11_USAGE_STAGING; + else if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_DYNAMIC) + bd.Usage = D3D11_USAGE_DYNAMIC; + else if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_STATIC) + bd.Usage = pInitialData ? D3D11_USAGE_IMMUTABLE : D3D11_USAGE_DEFAULT; /* Guest will update later. */ + else if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_INDIRECT_UPDATE) + bd.Usage = D3D11_USAGE_DEFAULT; + + bd.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); + + if (bd.Usage == D3D11_USAGE_STAGING) + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; + else if (bd.Usage == D3D11_USAGE_DYNAMIC) + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_DRAWINDIRECT_ARGS) + bd.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_BIND_RAW_VIEWS) + bd.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_BUFFER_STRUCTURED) + bd.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_RESOURCE_CLAMP) + bd.MiscFlags |= D3D11_RESOURCE_MISC_RESOURCE_CLAMP; + + if (bd.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) + { + SVGAOTableSurfaceEntry entrySurface; + rc = vmsvgaR3OTableReadSurface(pThisCC->svga.pSvgaR3State, pSurface->id, &entrySurface); + AssertRCReturn(rc, rc); + + bd.StructureByteStride = entrySurface.bufferByteStride; + } + + hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->u.pBuffer); + Assert(SUCCEEDED(hr)); +#ifndef DX_COMMON_STAGING_BUFFER + if (SUCCEEDED(hr)) + { + /* Map-able Buffer. */ + bd.Usage = D3D11_USAGE_DYNAMIC; + bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->dynamic.pBuffer); + Assert(SUCCEEDED(hr)); + } + + if (SUCCEEDED(hr)) + { + /* Staging texture. */ + bd.Usage = D3D11_USAGE_STAGING; + bd.BindFlags = 0; /* No flags allowed. */ + bd.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->staging.pBuffer); + Assert(SUCCEEDED(hr)); + } +#endif + if (SUCCEEDED(hr)) + { + pBackendSurface->enmResType = VMSVGA3D_RESTYPE_BUFFER; + pBackendSurface->enmDxgiFormat = DXGI_FORMAT_UNKNOWN; + } + } + else + { + /** @todo Texture. Currently vmsvga3dBackSurfaceCreateTexture is called for textures. */ + AssertFailed(); + hr = E_FAIL; + } + + if (SUCCEEDED(hr)) + { + /* + * Success. + */ + pSurface->pBackendSurface = pBackendSurface; + pSurface->idAssociatedContext = pDXContext->cid; + return VINF_SUCCESS; + } + + /* Failure. */ + D3D_RELEASE(pBackendSurface->u.pResource); + D3D_RELEASE(pBackendSurface->dynamic.pResource); + D3D_RELEASE(pBackendSurface->staging.pResource); + RTMemFree(pBackendSurface); + return VERR_NO_MEMORY; +} + + +#ifdef DX_COMMON_STAGING_BUFFER +static int dxStagingBufferRealloc(DXDEVICE *pDXDevice, uint32_t cbRequiredSize) +{ + AssertReturn(cbRequiredSize < SVGA3D_MAX_SURFACE_MEM_SIZE, VERR_INVALID_PARAMETER); + + if (RT_LIKELY(cbRequiredSize <= pDXDevice->cbStagingBuffer)) + return VINF_SUCCESS; + + D3D_RELEASE(pDXDevice->pStagingBuffer); + + uint32_t const cbAlloc = RT_ALIGN_32(cbRequiredSize, _64K); + + D3D11_SUBRESOURCE_DATA *pInitialData = NULL; + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = cbAlloc; + bd.Usage = D3D11_USAGE_STAGING; + //bd.BindFlags = 0; /* No bind flags are allowed for staging resources. */ + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; + + int rc = VINF_SUCCESS; + ID3D11Buffer *pBuffer; + HRESULT hr = pDXDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBuffer); + if (SUCCEEDED(hr)) + { + pDXDevice->pStagingBuffer = pBuffer; + pDXDevice->cbStagingBuffer = cbAlloc; + } + else + { + pDXDevice->cbStagingBuffer = 0; + rc = VERR_NO_MEMORY; + } + + return rc; +} +#endif + + +static DECLCALLBACK(int) vmsvga3dBackInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + RT_NOREF(pDevIns, pThis); + + int rc; +#ifdef RT_OS_LINUX /** @todo Remove, this is currently needed for loading the X11 library in order to call XInitThreads(). */ + rc = glLdrInit(pDevIns); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: Error loading OpenGL library and resolving necessary functions: %Rrc\n", rc)); + return rc; + } +#endif + + PVMSVGA3DBACKEND pBackend = (PVMSVGA3DBACKEND)RTMemAllocZ(sizeof(VMSVGA3DBACKEND)); + AssertReturn(pBackend, VERR_NO_MEMORY); + pThisCC->svga.p3dState->pBackend = pBackend; + + rc = RTLdrLoadSystem(VBOX_D3D11_LIBRARY_NAME, /* fNoUnload = */ true, &pBackend->hD3D11); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + rc = RTLdrGetSymbol(pBackend->hD3D11, "D3D11CreateDevice", (void **)&pBackend->pfnD3D11CreateDevice); + AssertRC(rc); + } + + if (RT_SUCCESS(rc)) + { + /* Failure to load the shader disassembler is ignored. */ + int rc2 = RTLdrLoadSystem("D3DCompiler_47", /* fNoUnload = */ true, &pBackend->hD3DCompiler); + if (RT_SUCCESS(rc2)) + rc2 = RTLdrGetSymbol(pBackend->hD3DCompiler, "D3DDisassemble", (void **)&pBackend->pfnD3DDisassemble); + Log6Func(("Load D3DDisassemble: %Rrc\n", rc2)); + } + +#if !defined(RT_OS_WINDOWS) || defined(DX_FORCE_SINGLE_DEVICE) + pBackend->fSingleDevice = true; +#endif + + LogRelMax(1, ("VMSVGA: Single DX device mode: %s\n", pBackend->fSingleDevice ? "enabled" : "disabled")); + +//DEBUG_BREAKPOINT_TEST(); + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackPowerOn(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + RT_NOREF(pDevIns, pThis); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = pState->pBackend; + AssertReturn(pBackend, VERR_INVALID_STATE); + + int rc = dxDeviceCreate(pBackend, &pBackend->dxDevice); + if (RT_SUCCESS(rc)) + { + IDXGIAdapter *pAdapter = NULL; + HRESULT hr = pBackend->dxDevice.pDxgiFactory->EnumAdapters(0, &pAdapter); + if (SUCCEEDED(hr)) + { + DXGI_ADAPTER_DESC desc; + hr = pAdapter->GetDesc(&desc); + if (SUCCEEDED(hr)) + { + char sz[RT_ELEMENTS(desc.Description)]; + for (unsigned i = 0; i < RT_ELEMENTS(desc.Description); ++i) + sz[i] = (char)desc.Description[i]; + LogRelMax(1, ("VMSVGA: Adapter [%s]\n", sz)); + } + + pAdapter->Release(); + } + } + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackReset(PVGASTATECC pThisCC) +{ + RT_NOREF(pThisCC); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackTerminate(PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + if (pState->pBackend) + dxDeviceDestroy(pState->pBackend, &pState->pBackend->dxDevice); + + return VINF_SUCCESS; +} + + +/** @todo Such structures must be in VBoxVideo3D.h */ +typedef struct VBOX3DNOTIFYDEFINESCREEN +{ + VBOX3DNOTIFY Core; + uint32_t cWidth; + uint32_t cHeight; + int32_t xRoot; + int32_t yRoot; + uint32_t fPrimary; + uint32_t cDpi; +} VBOX3DNOTIFYDEFINESCREEN; + + +static int vmsvga3dDrvNotifyDefineScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + VBOX3DNOTIFYDEFINESCREEN n; + n.Core.enmNotification = VBOX3D_NOTIFY_TYPE_HW_SCREEN_CREATED; + n.Core.iDisplay = pScreen->idScreen; + n.Core.u32Reserved = 0; + n.Core.cbData = sizeof(n) - RT_UOFFSETOF(VBOX3DNOTIFY, au8Data); + RT_ZERO(n.Core.au8Data); + n.cWidth = pScreen->cWidth; + n.cHeight = pScreen->cHeight; + n.xRoot = pScreen->xOrigin; + n.yRoot = pScreen->yOrigin; + n.fPrimary = RT_BOOL(pScreen->fuScreen & SVGA_SCREEN_IS_PRIMARY); + n.cDpi = pScreen->cDpi; + + return pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, &n.Core); +} + + +static int vmsvga3dDrvNotifyDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + VBOX3DNOTIFY n; + n.enmNotification = VBOX3D_NOTIFY_TYPE_HW_SCREEN_DESTROYED; + n.iDisplay = pScreen->idScreen; + n.u32Reserved = 0; + n.cbData = sizeof(n) - RT_UOFFSETOF(VBOX3DNOTIFY, au8Data); + RT_ZERO(n.au8Data); + + return pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, &n); +} + + +static int vmsvga3dDrvNotifyBindSurface(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, HANDLE hSharedSurface) +{ + VBOX3DNOTIFY n; + n.enmNotification = VBOX3D_NOTIFY_TYPE_HW_SCREEN_BIND_SURFACE; + n.iDisplay = pScreen->idScreen; + n.u32Reserved = 0; + n.cbData = sizeof(n) - RT_UOFFSETOF(VBOX3DNOTIFY, au8Data); + *(uint64_t *)&n.au8Data[0] = (uint64_t)hSharedSurface; + + return pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, &n); +} + + +typedef struct VBOX3DNOTIFYUPDATE +{ + VBOX3DNOTIFY Core; + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; +} VBOX3DNOTIFYUPDATE; + + +static int vmsvga3dDrvNotifyUpdate(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, + uint32_t x, uint32_t y, uint32_t w, uint32_t h) +{ + VBOX3DNOTIFYUPDATE n; + n.Core.enmNotification = VBOX3D_NOTIFY_TYPE_HW_SCREEN_UPDATE_END; + n.Core.iDisplay = pScreen->idScreen; + n.Core.u32Reserved = 0; + n.Core.cbData = sizeof(n) - RT_UOFFSETOF(VBOX3DNOTIFY, au8Data); + RT_ZERO(n.Core.au8Data); + n.x = x; + n.y = y; + n.w = w; + n.h = h; + + return pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, &n.Core); +} + +static int vmsvga3dHwScreenCreate(PVMSVGA3DSTATE pState, uint32_t cWidth, uint32_t cHeight, VMSVGAHWSCREEN *p) +{ + PVMSVGA3DBACKEND pBackend = pState->pBackend; + + DXDEVICE *pDXDevice = &pBackend->dxDevice; + AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); + + D3D11_TEXTURE2D_DESC td; + RT_ZERO(td); + td.Width = cWidth; + td.Height = cHeight; + td.MipLevels = 1; + td.ArraySize = 1; + td.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + td.SampleDesc.Count = 1; + td.SampleDesc.Quality = 0; + td.Usage = D3D11_USAGE_DEFAULT; + td.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + td.CPUAccessFlags = 0; + td.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; + + HRESULT hr = pDXDevice->pDevice->CreateTexture2D(&td, 0, &p->pTexture); + if (SUCCEEDED(hr)) + { + /* Get the shared handle. */ + hr = p->pTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&p->pDxgiResource); + if (SUCCEEDED(hr)) + { + hr = p->pDxgiResource->GetSharedHandle(&p->SharedHandle); + if (SUCCEEDED(hr)) + hr = p->pTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&p->pDXGIKeyedMutex); + } + } + + if (SUCCEEDED(hr)) + return VINF_SUCCESS; + + AssertFailed(); + return VERR_NOT_SUPPORTED; +} + + +static void vmsvga3dHwScreenDestroy(PVMSVGA3DSTATE pState, VMSVGAHWSCREEN *p) +{ + RT_NOREF(pState); + D3D_RELEASE(p->pDXGIKeyedMutex); + D3D_RELEASE(p->pDxgiResource); + D3D_RELEASE(p->pTexture); + p->SharedHandle = 0; + p->sidScreenTarget = SVGA_ID_INVALID; +} + + +static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + RT_NOREF(pThis, pThisCC, pScreen); + + LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: screen %u\n", pScreen->idScreen)); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = pState->pBackend; + AssertReturn(pBackend, VERR_INVALID_STATE); + + Assert(pScreen->pHwScreen == NULL); + + VMSVGAHWSCREEN *p = (VMSVGAHWSCREEN *)RTMemAllocZ(sizeof(VMSVGAHWSCREEN)); + AssertPtrReturn(p, VERR_NO_MEMORY); + + p->sidScreenTarget = SVGA_ID_INVALID; + + int rc = vmsvga3dDrvNotifyDefineScreen(pThisCC, pScreen); + if (RT_SUCCESS(rc)) + { + /* The frontend supports the screen. Create the actual resource. */ + rc = vmsvga3dHwScreenCreate(pState, pScreen->cWidth, pScreen->cHeight, p); + if (RT_SUCCESS(rc)) + LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: created\n")); + } + + if (RT_SUCCESS(rc)) + { + LogRel(("VMSVGA: Using HW accelerated screen %u\n", pScreen->idScreen)); + pScreen->pHwScreen = p; + } + else + { + LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: %Rrc\n", rc)); + vmsvga3dHwScreenDestroy(pState, p); + RTMemFree(p); + } + + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + vmsvga3dDrvNotifyDestroyScreen(pThisCC, pScreen); + + if (pScreen->pHwScreen) + { + vmsvga3dHwScreenDestroy(pState, pScreen->pHwScreen); + RTMemFree(pScreen->pHwScreen); + pScreen->pHwScreen = NULL; + } + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, + SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage, + SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects) +{ + RT_NOREF(pThisCC, pScreen, destRect, srcImage, srcRect, cRects, paRects); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = pState->pBackend; + AssertReturn(pBackend, VERR_INVALID_STATE); + + VMSVGAHWSCREEN *p = pScreen->pHwScreen; + AssertReturn(p, VERR_NOT_SUPPORTED); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, srcImage.sid, &pSurface); + AssertRCReturn(rc, rc); + + /** @todo Implement. */ + AssertFailed(); + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackSurfaceMap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox, + VMSVGA3D_SURFACE_MAP enmMapType, VMSVGA3D_MAPPED_SURFACE *pMap) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = pState->pBackend; + AssertReturn(pBackend, VERR_INVALID_STATE); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, pImage->sid, &pSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; + AssertPtrReturn(pBackendSurface, VERR_INVALID_STATE); + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + /* A surface is always mapped by the DX context which has created the surface. */ + DXDEVICE *pDevice = dxDeviceFromCid(pSurface->idAssociatedContext, pState); + AssertReturn(pDevice && pDevice->pDevice, VERR_INVALID_STATE); + + SVGA3dBox clipBox; + if (pBox) + { + clipBox = *pBox; + vmsvgaR3ClipBox(&pMipLevel->mipmapSize, &clipBox); + ASSERT_GUEST_RETURN(clipBox.w && clipBox.h && clipBox.d, VERR_INVALID_PARAMETER); + } + else + { + clipBox.x = 0; + clipBox.y = 0; + clipBox.z = 0; + clipBox.w = pMipLevel->mipmapSize.width; + clipBox.h = pMipLevel->mipmapSize.height; + clipBox.d = pMipLevel->mipmapSize.depth; + } + + D3D11_MAP d3d11MapType; + switch (enmMapType) + { + case VMSVGA3D_SURFACE_MAP_READ: d3d11MapType = D3D11_MAP_READ; break; + case VMSVGA3D_SURFACE_MAP_WRITE: d3d11MapType = D3D11_MAP_WRITE; break; + case VMSVGA3D_SURFACE_MAP_READ_WRITE: d3d11MapType = D3D11_MAP_READ_WRITE; break; + case VMSVGA3D_SURFACE_MAP_WRITE_DISCARD: d3d11MapType = D3D11_MAP_WRITE_DISCARD; break; + default: + AssertFailed(); + return VERR_INVALID_PARAMETER; + } + + D3D11_MAPPED_SUBRESOURCE mappedResource; + RT_ZERO(mappedResource); + + if ( pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_1D + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_CUBE + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) + { + dxSurfaceWait(pState, pSurface, pSurface->idAssociatedContext); + + ID3D11Resource *pMappedResource; + if (enmMapType == VMSVGA3D_SURFACE_MAP_READ) + { + pMappedResource = pBackendSurface->staging.pResource; + + /* Copy the texture content to the staging texture. + * The requested miplevel of the texture is copied to the miplevel 0 of the staging texture, + * because the staging (and dynamic) structures do not have miplevels. + * Always copy entire miplevel so all Dst are zero and pSrcBox is NULL, as D3D11 requires. + */ + ID3D11Resource *pDstResource = pMappedResource; + UINT DstSubresource = 0; + UINT DstX = 0; + UINT DstY = 0; + UINT DstZ = 0; + ID3D11Resource *pSrcResource = pBackendSurface->u.pResource; + UINT SrcSubresource = D3D11CalcSubresource(pImage->mipmap, pImage->face, pSurface->cLevels); + D3D11_BOX *pSrcBox = NULL; + //D3D11_BOX SrcBox; + //SrcBox.left = 0; + //SrcBox.top = 0; + //SrcBox.front = 0; + //SrcBox.right = pMipLevel->mipmapSize.width; + //SrcBox.bottom = pMipLevel->mipmapSize.height; + //SrcBox.back = pMipLevel->mipmapSize.depth; + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, pSrcBox); + } + else if (enmMapType == VMSVGA3D_SURFACE_MAP_WRITE) + pMappedResource = pBackendSurface->staging.pResource; + else + pMappedResource = pBackendSurface->dynamic.pResource; + + UINT const Subresource = 0; /* Dynamic or staging textures have one subresource. */ + HRESULT hr = pDevice->pImmediateContext->Map(pMappedResource, Subresource, + d3d11MapType, /* MapFlags = */ 0, &mappedResource); + if (SUCCEEDED(hr)) + vmsvga3dSurfaceMapInit(pMap, enmMapType, &clipBox, pSurface, + mappedResource.pData, mappedResource.RowPitch, mappedResource.DepthPitch); + else + AssertFailedStmt(rc = VERR_NOT_SUPPORTED); + } + else if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_BUFFER) + { +#ifdef DX_COMMON_STAGING_BUFFER + /* Map the staging buffer. */ + rc = dxStagingBufferRealloc(pDevice, pMipLevel->cbSurface); + if (RT_SUCCESS(rc)) + { + /* The staging buffer does not allow D3D11_MAP_WRITE_DISCARD, so replace it. */ + if (d3d11MapType == D3D11_MAP_WRITE_DISCARD) + d3d11MapType = D3D11_MAP_WRITE; + + if (enmMapType == VMSVGA3D_SURFACE_MAP_READ) + { + /* Copy from the buffer to the staging buffer. */ + ID3D11Resource *pDstResource = pDevice->pStagingBuffer; + UINT DstSubresource = 0; + UINT DstX = clipBox.x; + UINT DstY = clipBox.y; + UINT DstZ = clipBox.z; + ID3D11Resource *pSrcResource = pBackendSurface->u.pResource; + UINT SrcSubresource = 0; + D3D11_BOX SrcBox; + SrcBox.left = clipBox.x; + SrcBox.top = clipBox.y; + SrcBox.front = clipBox.z; + SrcBox.right = clipBox.w; + SrcBox.bottom = clipBox.h; + SrcBox.back = clipBox.d; + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox); + } + + UINT const Subresource = 0; /* Buffers have only one subresource. */ + HRESULT hr = pDevice->pImmediateContext->Map(pDevice->pStagingBuffer, Subresource, + d3d11MapType, /* MapFlags = */ 0, &mappedResource); + if (SUCCEEDED(hr)) + vmsvga3dSurfaceMapInit(pMap, enmMapType, &clipBox, pSurface, + mappedResource.pData, mappedResource.RowPitch, mappedResource.DepthPitch); + else + AssertFailedStmt(rc = VERR_NOT_SUPPORTED); + } +#else + ID3D11Resource *pMappedResource; + if (enmMapType == VMSVGA3D_SURFACE_MAP_READ) + { + pMappedResource = pBackendSurface->staging.pResource; + + /* Copy the resource content to the staging resource. */ + ID3D11Resource *pDstResource = pMappedResource; + UINT DstSubresource = 0; + UINT DstX = clipBox.x; + UINT DstY = clipBox.y; + UINT DstZ = clipBox.z; + ID3D11Resource *pSrcResource = pBackendSurface->u.pResource; + UINT SrcSubresource = 0; + D3D11_BOX SrcBox; + SrcBox.left = clipBox.x; + SrcBox.top = clipBox.y; + SrcBox.front = clipBox.z; + SrcBox.right = clipBox.w; + SrcBox.bottom = clipBox.h; + SrcBox.back = clipBox.d; + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox); + } + else if (enmMapType == VMSVGA3D_SURFACE_MAP_WRITE) + pMappedResource = pBackendSurface->staging.pResource; + else + pMappedResource = pBackendSurface->dynamic.pResource; + + UINT const Subresource = 0; /* Dynamic or staging textures have one subresource. */ + HRESULT hr = pDevice->pImmediateContext->Map(pMappedResource, Subresource, + d3d11MapType, /* MapFlags = */ 0, &mappedResource); + if (SUCCEEDED(hr)) + vmsvga3dSurfaceMapInit(pMap, enmMapType, &clipBox, pSurface, + mappedResource.pData, mappedResource.RowPitch, mappedResource.DepthPitch); + else + AssertFailedStmt(rc = VERR_NOT_SUPPORTED); +#endif + } + else + { + // UINT D3D11CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT MipLevels); + /** @todo Implement. */ + AssertFailed(); + rc = VERR_NOT_IMPLEMENTED; + } + + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackSurfaceUnmap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, VMSVGA3D_MAPPED_SURFACE *pMap, bool fWritten) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = pState->pBackend; + AssertReturn(pBackend, VERR_INVALID_STATE); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, pImage->sid, &pSurface); + AssertRCReturn(rc, rc); + + /* The called should not use the function for system memory surfaces. */ + PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; + AssertReturn(pBackendSurface, VERR_INVALID_PARAMETER); + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + /* A surface is always mapped by the DX context which has created the surface. */ + DXDEVICE *pDevice = dxDeviceFromCid(pSurface->idAssociatedContext, pState); + AssertReturn(pDevice && pDevice->pDevice, VERR_INVALID_STATE); + + if ( pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_1D + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_CUBE + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) + { + ID3D11Resource *pMappedResource; + if (pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ) + pMappedResource = pBackendSurface->staging.pResource; + else if (pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE) + pMappedResource = pBackendSurface->staging.pResource; + else + pMappedResource = pBackendSurface->dynamic.pResource; + + UINT const Subresource = 0; /* Staging or dynamic textures have one subresource. */ + pDevice->pImmediateContext->Unmap(pMappedResource, Subresource); + + if ( fWritten + && ( pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE + || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ_WRITE + || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD)) + { + /* If entire resource must be copied then use pSrcBox = NULL and dst point (0,0,0) + * Because DX11 insists on this for some resource types, for example DEPTH_STENCIL resources. + */ + uint32_t const cWidth0 = pSurface->paMipmapLevels[0].mipmapSize.width; + uint32_t const cHeight0 = pSurface->paMipmapLevels[0].mipmapSize.height; + uint32_t const cDepth0 = pSurface->paMipmapLevels[0].mipmapSize.depth; + /** @todo Entire subresource is always mapped. So find a way to copy it back, important for DEPTH_STENCIL mipmaps. */ + bool const fEntireResource = pMap->box.x == 0 && pMap->box.y == 0 && pMap->box.z == 0 + && pMap->box.w == cWidth0 && pMap->box.h == cHeight0 && pMap->box.d == cDepth0; + + ID3D11Resource *pDstResource = pBackendSurface->u.pResource; + UINT DstSubresource = D3D11CalcSubresource(pImage->mipmap, pImage->face, pSurface->cLevels); + UINT DstX = (pMap->box.x / pSurface->cxBlock) * pSurface->cxBlock; + UINT DstY = (pMap->box.y / pSurface->cyBlock) * pSurface->cyBlock; + UINT DstZ = pMap->box.z; + ID3D11Resource *pSrcResource = pMappedResource; + UINT SrcSubresource = Subresource; + D3D11_BOX *pSrcBox; + D3D11_BOX SrcBox; + if (fEntireResource) + pSrcBox = NULL; + else + { + uint32_t const cxBlocks = (pMap->box.w + pSurface->cxBlock - 1) / pSurface->cxBlock; + uint32_t const cyBlocks = (pMap->box.h + pSurface->cyBlock - 1) / pSurface->cyBlock; + + SrcBox.left = DstX; + SrcBox.top = DstY; + SrcBox.front = DstZ; + SrcBox.right = DstX + cxBlocks * pSurface->cxBlock; + SrcBox.bottom = DstY + cyBlocks * pSurface->cyBlock; + SrcBox.back = DstZ + pMap->box.d; + pSrcBox = &SrcBox; + } + + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, pSrcBox); + + pBackendSurface->cidDrawing = pSurface->idAssociatedContext; + } + } + else if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_BUFFER) + { + Log4(("Unmap buffer sid = %u:\n%.*Rhxd\n", pSurface->id, pMap->cbRow, pMap->pvData)); + +#ifdef DX_COMMON_STAGING_BUFFER + /* Unmap the staging buffer. */ + UINT const Subresource = 0; /* Buffers have only one subresource. */ + pDevice->pImmediateContext->Unmap(pDevice->pStagingBuffer, Subresource); + + /* Copy from the staging buffer to the actual buffer */ + if ( fWritten + && ( pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE + || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ_WRITE + || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD)) + { + ID3D11Resource *pDstResource = pBackendSurface->u.pResource; + UINT DstSubresource = 0; + UINT DstX = (pMap->box.x / pSurface->cxBlock) * pSurface->cxBlock; + UINT DstY = (pMap->box.y / pSurface->cyBlock) * pSurface->cyBlock; + UINT DstZ = pMap->box.z; + ID3D11Resource *pSrcResource = pDevice->pStagingBuffer; + UINT SrcSubresource = 0; + D3D11_BOX SrcBox; + + uint32_t const cxBlocks = (pMap->box.w + pSurface->cxBlock - 1) / pSurface->cxBlock; + uint32_t const cyBlocks = (pMap->box.h + pSurface->cyBlock - 1) / pSurface->cyBlock; + + SrcBox.left = DstX; + SrcBox.top = DstY; + SrcBox.front = DstZ; + SrcBox.right = DstX + cxBlocks * pSurface->cxBlock; + SrcBox.bottom = DstY + cyBlocks * pSurface->cyBlock; + SrcBox.back = DstZ + pMap->box.d; + + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox); + } +#else + ID3D11Resource *pMappedResource; + if (pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ) + pMappedResource = pBackendSurface->staging.pResource; + else if (pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE) + pMappedResource = pBackendSurface->staging.pResource; + else + pMappedResource = pBackendSurface->dynamic.pResource; + + UINT const Subresource = 0; /* Staging or dynamic textures have one subresource. */ + pDevice->pImmediateContext->Unmap(pMappedResource, Subresource); + + if ( fWritten + && ( pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE + || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ_WRITE + || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD)) + { + ID3D11Resource *pDstResource = pBackendSurface->u.pResource; + UINT DstSubresource = 0; + UINT DstX = pMap->box.x; + UINT DstY = pMap->box.y; + UINT DstZ = pMap->box.z; + ID3D11Resource *pSrcResource = pMappedResource; + UINT SrcSubresource = 0; + D3D11_BOX SrcBox; + SrcBox.left = DstX; + SrcBox.top = DstY; + SrcBox.front = DstZ; + SrcBox.right = DstX + pMap->box.w; + SrcBox.bottom = DstY + pMap->box.h; + SrcBox.back = DstZ + pMap->box.d; + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox); + + pBackendSurface->cidDrawing = pSurface->idAssociatedContext; + } +#endif + } + else + { + AssertFailed(); + rc = VERR_NOT_IMPLEMENTED; + } + + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dScreenTargetBind(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, uint32_t sid) +{ + int rc = VINF_SUCCESS; + + PVMSVGA3DSURFACE pSurface; + if (sid != SVGA_ID_INVALID) + { + /* Create the surface if does not yet exist. */ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + /* Create the actual texture. */ + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, NULL, pSurface); + AssertRCReturn(rc, rc); + } + } + else + pSurface = NULL; + + /* Notify the HW accelerated screen if it is used. */ + VMSVGAHWSCREEN *pHwScreen = pScreen->pHwScreen; + if (!pHwScreen) + return VINF_SUCCESS; + + /* Same surface -> do nothing. */ + if (pHwScreen->sidScreenTarget == sid) + return VINF_SUCCESS; + + if (sid != SVGA_ID_INVALID) + { + AssertReturn( pSurface->pBackendSurface + && pSurface->pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D + && RT_BOOL(pSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET), VERR_INVALID_PARAMETER); + + HANDLE const hSharedSurface = pHwScreen->SharedHandle; + rc = vmsvga3dDrvNotifyBindSurface(pThisCC, pScreen, hSharedSurface); + } + + if (RT_SUCCESS(rc)) + { + pHwScreen->sidScreenTarget = sid; + } + + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dScreenTargetUpdate(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, SVGA3dRect const *pRect) +{ + VMSVGAHWSCREEN *pHwScreen = pScreen->pHwScreen; + AssertReturn(pHwScreen, VERR_NOT_SUPPORTED); + + if (pHwScreen->sidScreenTarget == SVGA_ID_INVALID) + return VINF_SUCCESS; /* No surface bound. */ + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = pState->pBackend; + AssertReturn(pBackend, VERR_INVALID_STATE); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, pHwScreen->sidScreenTarget, &pSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; + AssertReturn( pBackendSurface + && pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D + && RT_BOOL(pSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET), + VERR_INVALID_PARAMETER); + + SVGA3dRect boundRect; + boundRect.x = 0; + boundRect.y = 0; + boundRect.w = pSurface->paMipmapLevels[0].mipmapSize.width; + boundRect.h = pSurface->paMipmapLevels[0].mipmapSize.height; + SVGA3dRect clipRect = *pRect; + vmsvgaR3Clip3dRect(&boundRect, &clipRect); + ASSERT_GUEST_RETURN(clipRect.w && clipRect.h, VERR_INVALID_PARAMETER); + + /* Wait for the surface to finish drawing. */ + dxSurfaceWait(pState, pSurface, DX_CID_BACKEND); + + /* Copy the screen texture to the shared surface. */ + DWORD result = pHwScreen->pDXGIKeyedMutex->AcquireSync(0, 10000); + if (result == S_OK) + { + pBackend->dxDevice.pImmediateContext->CopyResource(pHwScreen->pTexture, pBackendSurface->u.pTexture2D); + + dxDeviceFlush(&pBackend->dxDevice); + + result = pHwScreen->pDXGIKeyedMutex->ReleaseSync(1); + } + else + AssertFailed(); + + rc = vmsvga3dDrvNotifyUpdate(pThisCC, pScreen, pRect->x, pRect->y, pRect->w, pRect->h); + return rc; +} + + +/* + * + * 3D interface. + * + */ + +static DECLCALLBACK(int) vmsvga3dBackQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + int rc = VINF_SUCCESS; + + *pu32Val = 0; + + if (idx3dCaps > SVGA3D_DEVCAP_MAX) + { + LogRelMax(16, ("VMSVGA: unsupported SVGA3D_DEVCAP %d\n", idx3dCaps)); + return VERR_NOT_SUPPORTED; + } + + D3D_FEATURE_LEVEL const FeatureLevel = pState->pBackend->dxDevice.FeatureLevel; + + /* Most values are taken from: + * https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-intro + * + * Shader values are from + * https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-models + */ + + switch (idx3dCaps) + { + case SVGA3D_DEVCAP_3D: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_MAX_LIGHTS: + *pu32Val = SVGA3D_NUM_LIGHTS; /* VGPU9. Not applicable to DX11. */ + break; + + case SVGA3D_DEVCAP_MAX_TEXTURES: + *pu32Val = SVGA3D_NUM_TEXTURE_UNITS; /* VGPU9. Not applicable to DX11. */ + break; + + case SVGA3D_DEVCAP_MAX_CLIP_PLANES: + *pu32Val = SVGA3D_NUM_CLIPPLANES; + break; + + case SVGA3D_DEVCAP_VERTEX_SHADER_VERSION: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = SVGA3DVSVERSION_40; + else + *pu32Val = SVGA3DVSVERSION_30; + break; + + case SVGA3D_DEVCAP_VERTEX_SHADER: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = SVGA3DPSVERSION_40; + else + *pu32Val = SVGA3DPSVERSION_30; + break; + + case SVGA3D_DEVCAP_FRAGMENT_SHADER: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_MAX_RENDER_TARGETS: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = 8; + else + *pu32Val = 4; + break; + + case SVGA3D_DEVCAP_S23E8_TEXTURES: + case SVGA3D_DEVCAP_S10E5_TEXTURES: + /* Must be obsolete by now; surface format caps specify the same thing. */ + break; + + case SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND: + /* Obsolete */ + break; + + /* + * 2. The BUFFER_FORMAT capabilities are deprecated, and they always + * return TRUE. Even on physical hardware that does not support + * these formats natively, the SVGA3D device will provide an emulation + * which should be invisible to the guest OS. + */ + case SVGA3D_DEVCAP_D16_BUFFER_FORMAT: + case SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT: + case SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_QUERY_TYPES: + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING: + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_MAX_POINT_SIZE: + AssertCompile(sizeof(uint32_t) == sizeof(float)); + *(float *)pu32Val = 256.0f; /* VGPU9. Not applicable to DX11. */ + break; + + case SVGA3D_DEVCAP_MAX_SHADER_TEXTURES: + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH: + case SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT: + if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0) + *pu32Val = 16384; + else if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = 8192; + else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_3) + *pu32Val = 4096; + else + *pu32Val = 2048; + break; + + case SVGA3D_DEVCAP_MAX_VOLUME_EXTENT: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = 2048; + else + *pu32Val = 256; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT: + if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0) + *pu32Val = 16384; + else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_3) + *pu32Val = 8192; + else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_2) + *pu32Val = 2048; + else + *pu32Val = 128; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO: + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY: + if (FeatureLevel >= D3D_FEATURE_LEVEL_9_2) + *pu32Val = D3D11_REQ_MAXANISOTROPY; + else + *pu32Val = 2; // D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + break; + + case SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = UINT32_MAX; + else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_2) + *pu32Val = 1048575; // D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + else + *pu32Val = 65535; // D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_INDEX: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = UINT32_MAX; + else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_2) + *pu32Val = 1048575; + else + *pu32Val = 65534; + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = UINT32_MAX; + else + *pu32Val = 512; + break; + + case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = UINT32_MAX; + else + *pu32Val = 512; + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = 4096; + else + *pu32Val = 32; + break; + + case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = 4096; + else + *pu32Val = 32; + break; + + case SVGA3D_DEVCAP_TEXTURE_OPS: + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: + case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: + case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: + case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D16: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: + case SVGA3D_DEVCAP_SURFACEFMT_DXT1: + case SVGA3D_DEVCAP_SURFACEFMT_DXT2: + case SVGA3D_DEVCAP_SURFACEFMT_DXT3: + case SVGA3D_DEVCAP_SURFACEFMT_DXT4: + case SVGA3D_DEVCAP_SURFACEFMT_DXT5: + case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: + case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: + case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: + case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: + case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: + case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: + case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: + case SVGA3D_DEVCAP_SURFACEFMT_V16U16: + case SVGA3D_DEVCAP_SURFACEFMT_G16R16: + case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: + case SVGA3D_DEVCAP_SURFACEFMT_UYVY: + case SVGA3D_DEVCAP_SURFACEFMT_YUY2: + case SVGA3D_DEVCAP_SURFACEFMT_NV12: + case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */ + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: + case SVGA3D_DEVCAP_SURFACEFMT_ATI1: + case SVGA3D_DEVCAP_SURFACEFMT_ATI2: + case SVGA3D_DEVCAP_SURFACEFMT_YV12: + { + SVGA3dSurfaceFormat const enmFormat = vmsvgaDXDevCapSurfaceFmt2Format(idx3dCaps); + rc = vmsvgaDXCheckFormatSupportPreDX(pState, enmFormat, pu32Val); + break; + } + + case SVGA3D_DEVCAP_MISSING62: + /* Unused */ + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES: + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS: + if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) + *pu32Val = 8; + else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_3) + *pu32Val = 4; // D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT + else + *pu32Val = 1; // D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT + break; + + case SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */ + case SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */ + *pu32Val = (1 << (2-1)) | (1 << (4-1)) | (1 << (8-1)); /* 2x, 4x, 8x */ + break; + + case SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */ + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */ + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_AUTOGENMIPMAPS: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_MAX_CONTEXT_IDS: + *pu32Val = SVGA3D_MAX_CONTEXT_IDS; + break; + + case SVGA3D_DEVCAP_MAX_SURFACE_IDS: + *pu32Val = SVGA3D_MAX_SURFACE_IDS; + break; + + case SVGA3D_DEVCAP_DEAD1: + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_DEAD8: /* SVGA3D_DEVCAP_VIDEO_DECODE */ + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_DEAD9: /* SVGA3D_DEVCAP_VIDEO_PROCESS */ + /* Obsolete */ + break; + + case SVGA3D_DEVCAP_LINE_AA: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_LINE_STIPPLE: + *pu32Val = 0; /* DX11 does not seem to support this directly. */ + break; + + case SVGA3D_DEVCAP_MAX_LINE_WIDTH: + AssertCompile(sizeof(uint32_t) == sizeof(float)); + *(float *)pu32Val = 1.0f; + break; + + case SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH: + AssertCompile(sizeof(uint32_t) == sizeof(float)); + *(float *)pu32Val = 1.0f; + break; + + case SVGA3D_DEVCAP_DEAD3: /* Old SVGA3D_DEVCAP_LOGICOPS */ + /* Deprecated. */ + AssertCompile(SVGA3D_DEVCAP_DEAD3 == 92); /* Newer SVGA headers redefine this. */ + break; + + case SVGA3D_DEVCAP_TS_COLOR_KEY: + *pu32Val = 0; /* DX11 does not seem to support this directly. */ + break; + + case SVGA3D_DEVCAP_DEAD2: + break; + + case SVGA3D_DEVCAP_DXCONTEXT: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_DEAD11: /* SVGA3D_DEVCAP_MAX_TEXTURE_ARRAY_SIZE */ + *pu32Val = D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + break; + + case SVGA3D_DEVCAP_DX_MAX_VERTEXBUFFERS: + *pu32Val = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; + break; + + case SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS: + *pu32Val = D3D11_COMMONSHADER_CONSTANT_BUFFER_HW_SLOT_COUNT; + break; + + case SVGA3D_DEVCAP_DX_PROVOKING_VERTEX: + *pu32Val = 0; /* boolean */ + break; + + case SVGA3D_DEVCAP_DXFMT_X8R8G8B8: + case SVGA3D_DEVCAP_DXFMT_A8R8G8B8: + case SVGA3D_DEVCAP_DXFMT_R5G6B5: + case SVGA3D_DEVCAP_DXFMT_X1R5G5B5: + case SVGA3D_DEVCAP_DXFMT_A1R5G5B5: + case SVGA3D_DEVCAP_DXFMT_A4R4G4B4: + case SVGA3D_DEVCAP_DXFMT_Z_D32: + case SVGA3D_DEVCAP_DXFMT_Z_D16: + case SVGA3D_DEVCAP_DXFMT_Z_D24S8: + case SVGA3D_DEVCAP_DXFMT_Z_D15S1: + case SVGA3D_DEVCAP_DXFMT_LUMINANCE8: + case SVGA3D_DEVCAP_DXFMT_LUMINANCE4_ALPHA4: + case SVGA3D_DEVCAP_DXFMT_LUMINANCE16: + case SVGA3D_DEVCAP_DXFMT_LUMINANCE8_ALPHA8: + case SVGA3D_DEVCAP_DXFMT_DXT1: + case SVGA3D_DEVCAP_DXFMT_DXT2: + case SVGA3D_DEVCAP_DXFMT_DXT3: + case SVGA3D_DEVCAP_DXFMT_DXT4: + case SVGA3D_DEVCAP_DXFMT_DXT5: + case SVGA3D_DEVCAP_DXFMT_BUMPU8V8: + case SVGA3D_DEVCAP_DXFMT_BUMPL6V5U5: + case SVGA3D_DEVCAP_DXFMT_BUMPX8L8V8U8: + case SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD1: + case SVGA3D_DEVCAP_DXFMT_ARGB_S10E5: + case SVGA3D_DEVCAP_DXFMT_ARGB_S23E8: + case SVGA3D_DEVCAP_DXFMT_A2R10G10B10: + case SVGA3D_DEVCAP_DXFMT_V8U8: + case SVGA3D_DEVCAP_DXFMT_Q8W8V8U8: + case SVGA3D_DEVCAP_DXFMT_CxV8U8: + case SVGA3D_DEVCAP_DXFMT_X8L8V8U8: + case SVGA3D_DEVCAP_DXFMT_A2W10V10U10: + case SVGA3D_DEVCAP_DXFMT_ALPHA8: + case SVGA3D_DEVCAP_DXFMT_R_S10E5: + case SVGA3D_DEVCAP_DXFMT_R_S23E8: + case SVGA3D_DEVCAP_DXFMT_RG_S10E5: + case SVGA3D_DEVCAP_DXFMT_RG_S23E8: + case SVGA3D_DEVCAP_DXFMT_BUFFER: + case SVGA3D_DEVCAP_DXFMT_Z_D24X8: + case SVGA3D_DEVCAP_DXFMT_V16U16: + case SVGA3D_DEVCAP_DXFMT_G16R16: + case SVGA3D_DEVCAP_DXFMT_A16B16G16R16: + case SVGA3D_DEVCAP_DXFMT_UYVY: + case SVGA3D_DEVCAP_DXFMT_YUY2: + case SVGA3D_DEVCAP_DXFMT_NV12: + case SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD2: /* SVGA3D_DEVCAP_DXFMT_AYUV */ + case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT: + case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT: + case SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT: + case SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT: + case SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT: + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT: + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM: + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT: + case SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R32G32_UINT: + case SVGA3D_DEVCAP_DXFMT_R32G32_SINT: + case SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT: + case SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24: + case SVGA3D_DEVCAP_DXFMT_X32_G8X24_UINT: + case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT: + case SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT: + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM: + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB: + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT: + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT: + case SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R16G16_UINT: + case SVGA3D_DEVCAP_DXFMT_R16G16_SINT: + case SVGA3D_DEVCAP_DXFMT_R32_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_D32_FLOAT: + case SVGA3D_DEVCAP_DXFMT_R32_UINT: + case SVGA3D_DEVCAP_DXFMT_R32_SINT: + case SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT: + case SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8: + case SVGA3D_DEVCAP_DXFMT_X24_G8_UINT: + case SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R8G8_UNORM: + case SVGA3D_DEVCAP_DXFMT_R8G8_UINT: + case SVGA3D_DEVCAP_DXFMT_R8G8_SINT: + case SVGA3D_DEVCAP_DXFMT_R16_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R16_UNORM: + case SVGA3D_DEVCAP_DXFMT_R16_UINT: + case SVGA3D_DEVCAP_DXFMT_R16_SNORM: + case SVGA3D_DEVCAP_DXFMT_R16_SINT: + case SVGA3D_DEVCAP_DXFMT_R8_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_R8_UNORM: + case SVGA3D_DEVCAP_DXFMT_R8_UINT: + case SVGA3D_DEVCAP_DXFMT_R8_SNORM: + case SVGA3D_DEVCAP_DXFMT_R8_SINT: + case SVGA3D_DEVCAP_DXFMT_P8: + case SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP: + case SVGA3D_DEVCAP_DXFMT_R8G8_B8G8_UNORM: + case SVGA3D_DEVCAP_DXFMT_G8R8_G8B8_UNORM: + case SVGA3D_DEVCAP_DXFMT_BC1_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_BC1_UNORM_SRGB: + case SVGA3D_DEVCAP_DXFMT_BC2_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_BC2_UNORM_SRGB: + case SVGA3D_DEVCAP_DXFMT_BC3_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_BC3_UNORM_SRGB: + case SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_ATI1: + case SVGA3D_DEVCAP_DXFMT_BC4_SNORM: + case SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_ATI2: + case SVGA3D_DEVCAP_DXFMT_BC5_SNORM: + case SVGA3D_DEVCAP_DXFMT_R10G10B10_XR_BIAS_A2_UNORM: + case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB: + case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB: + case SVGA3D_DEVCAP_DXFMT_Z_DF16: + case SVGA3D_DEVCAP_DXFMT_Z_DF24: + case SVGA3D_DEVCAP_DXFMT_Z_D24S8_INT: + case SVGA3D_DEVCAP_DXFMT_YV12: + case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT: + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT: + case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM: + case SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT: + case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM: + case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM: + case SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT: + case SVGA3D_DEVCAP_DXFMT_R16G16_UNORM: + case SVGA3D_DEVCAP_DXFMT_R16G16_SNORM: + case SVGA3D_DEVCAP_DXFMT_R32_FLOAT: + case SVGA3D_DEVCAP_DXFMT_R8G8_SNORM: + case SVGA3D_DEVCAP_DXFMT_R16_FLOAT: + case SVGA3D_DEVCAP_DXFMT_D16_UNORM: + case SVGA3D_DEVCAP_DXFMT_A8_UNORM: + case SVGA3D_DEVCAP_DXFMT_BC1_UNORM: + case SVGA3D_DEVCAP_DXFMT_BC2_UNORM: + case SVGA3D_DEVCAP_DXFMT_BC3_UNORM: + case SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM: + case SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM: + case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM: + case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM: + case SVGA3D_DEVCAP_DXFMT_BC4_UNORM: + case SVGA3D_DEVCAP_DXFMT_BC5_UNORM: + case SVGA3D_DEVCAP_DXFMT_BC6H_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_BC6H_UF16: + case SVGA3D_DEVCAP_DXFMT_BC6H_SF16: + case SVGA3D_DEVCAP_DXFMT_BC7_TYPELESS: + case SVGA3D_DEVCAP_DXFMT_BC7_UNORM: + case SVGA3D_DEVCAP_DXFMT_BC7_UNORM_SRGB: + { + SVGA3dSurfaceFormat const enmFormat = vmsvgaDXDevCapDxfmt2Format(idx3dCaps); + rc = vmsvgaDXCheckFormatSupport(pState, enmFormat, pu32Val); + break; + } + + case SVGA3D_DEVCAP_SM41: + *pu32Val = 1; /* boolean */ + break; + + case SVGA3D_DEVCAP_MULTISAMPLE_2X: + *pu32Val = 0; /* boolean */ + break; + + case SVGA3D_DEVCAP_MULTISAMPLE_4X: + *pu32Val = 0; /* boolean */ + break; + + case SVGA3D_DEVCAP_MS_FULL_QUALITY: + *pu32Val = 0; /* boolean */ + break; + + case SVGA3D_DEVCAP_LOGICOPS: + AssertCompile(SVGA3D_DEVCAP_LOGICOPS == 248); + *pu32Val = 0; /* boolean */ + break; + + case SVGA3D_DEVCAP_LOGIC_BLENDOPS: + *pu32Val = 0; /* boolean */ + break; + + case SVGA3D_DEVCAP_RESERVED_1: + break; + + case SVGA3D_DEVCAP_RESERVED_2: + break; + + case SVGA3D_DEVCAP_SM5: + *pu32Val = 1; /* boolean */ + break; + + case SVGA3D_DEVCAP_MULTISAMPLE_8X: + *pu32Val = 0; /* boolean */ + break; + + case SVGA3D_DEVCAP_MAX: + case SVGA3D_DEVCAP_INVALID: + rc = VERR_NOT_SUPPORTED; + break; + } + + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackChangeMode(PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src, + uint32_t cCopyBoxes, SVGA3dCopyBox *pBox) +{ + RT_NOREF(cCopyBoxes, pBox); + + LogFunc(("src sid %d -> dst sid %d\n", src.sid, dest.sid)); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = pState->pBackend; + + PVMSVGA3DSURFACE pSrcSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, src.sid, &pSrcSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DSURFACE pDstSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, dest.sid, &pDstSurface); + AssertRCReturn(rc, rc); + + LogFunc(("src%s cid %d -> dst%s cid %d\n", + pSrcSurface->pBackendSurface ? "" : " sysmem", + pSrcSurface ? pSrcSurface->idAssociatedContext : SVGA_ID_INVALID, + pDstSurface->pBackendSurface ? "" : " sysmem", + pDstSurface ? pDstSurface->idAssociatedContext : SVGA_ID_INVALID)); + + //DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + //AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + if (pSrcSurface->pBackendSurface) + { + if (pDstSurface->pBackendSurface == NULL) + { + /* Create the target if it can be used as a device context shared resource (render or screen target). */ + if (pBackend->fSingleDevice || dxIsSurfaceShareable(pDstSurface)) + { + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, NULL, pDstSurface); + AssertRCReturn(rc, rc); + } + } + + if (pDstSurface->pBackendSurface) + { + /* Surface -> Surface. */ + /* Expect both of them to be shared surfaces created by the backend context. */ + Assert(pSrcSurface->idAssociatedContext == DX_CID_BACKEND && pDstSurface->idAssociatedContext == DX_CID_BACKEND); + + /* Wait for the source surface to finish drawing. */ + dxSurfaceWait(pState, pSrcSurface, DX_CID_BACKEND); + + DXDEVICE *pDXDevice = &pBackend->dxDevice; + + /* Clip the box. */ + PVMSVGA3DMIPMAPLEVEL pSrcMipLevel; + rc = vmsvga3dMipmapLevel(pSrcSurface, src.face, src.mipmap, &pSrcMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + PVMSVGA3DMIPMAPLEVEL pDstMipLevel; + rc = vmsvga3dMipmapLevel(pDstSurface, dest.face, dest.mipmap, &pDstMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + SVGA3dCopyBox clipBox = *pBox; + vmsvgaR3ClipCopyBox(&pSrcMipLevel->mipmapSize, &pDstMipLevel->mipmapSize, &clipBox); + + UINT DstSubresource = vmsvga3dCalcSubresource(dest.mipmap, dest.face, pDstSurface->cLevels); + UINT DstX = clipBox.x; + UINT DstY = clipBox.y; + UINT DstZ = clipBox.z; + + UINT SrcSubresource = vmsvga3dCalcSubresource(src.mipmap, src.face, pSrcSurface->cLevels); + D3D11_BOX SrcBox; + SrcBox.left = clipBox.srcx; + SrcBox.top = clipBox.srcy; + SrcBox.front = clipBox.srcz; + SrcBox.right = clipBox.srcx + clipBox.w; + SrcBox.bottom = clipBox.srcy + clipBox.h; + SrcBox.back = clipBox.srcz + clipBox.d; + + Assert(cCopyBoxes == 1); /** @todo */ + + ID3D11Resource *pDstResource; + ID3D11Resource *pSrcResource; + pDstResource = dxResource(pState, pDstSurface, NULL); + pSrcResource = dxResource(pState, pSrcSurface, NULL); + + pDXDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox); + + pDstSurface->pBackendSurface->cidDrawing = DX_CID_BACKEND; + } + else + { + /* Surface -> Memory. */ + AssertFailed(); /** @todo implement */ + } + } + else + { + /* Memory -> Surface. */ + AssertFailed(); /** @todo implement */ + } + + return rc; +} + + +static DECLCALLBACK(void) vmsvga3dBackUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport) +{ + RT_NOREF(pThisCC, idScreen, pOldViewport); + /** @todo Scroll the screen content without requiring the guest to redraw. */ +} + + +static DECLCALLBACK(int) vmsvga3dBackSurfaceUpdateHeapBuffers(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface) +{ + /** @todo */ + RT_NOREF(pThisCC, pSurface); + return VERR_NOT_IMPLEMENTED; +} + + +/* + * + * VGPU9 callbacks. Not implemented. + * + */ +/** @todo later */ + +/** + * Create a new 3d context + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param cid Context id + */ +static DECLCALLBACK(int) vmsvga3dBackContextDefine(PVGASTATECC pThisCC, uint32_t cid) +{ + RT_NOREF(cid); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VERR_NOT_IMPLEMENTED; +} + + +/** + * Destroy an existing 3d context + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param cid Context id + */ +static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid) +{ + RT_NOREF(cid); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16]) +{ + RT_NOREF(cid, type, matrix); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange) +{ + RT_NOREF(cid, zRange); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState) +{ + RT_NOREF(cid, cRenderStates, pRenderState); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target) +{ + RT_NOREF(cid, type, target); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState) +{ + RT_NOREF(cid, cTextureStates, pTextureState); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial) +{ + RT_NOREF(cid, face, pMaterial); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData) +{ + RT_NOREF(cid, index, pData); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled) +{ + RT_NOREF(cid, index, enabled); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) +{ + RT_NOREF(cid, pRect); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]) +{ + RT_NOREF(cid, index, plane); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, + uint32_t stencil, uint32_t cRects, SVGA3dRect *pRect) +{ + /* From SVGA3D_BeginClear comments: + * + * Clear is not affected by clipping, depth test, or other + * render state which affects the fragment pipeline. + * + * Therefore this code must ignore the current scissor rect. + */ + + RT_NOREF(cid, clearFlag, color, depth, stencil, cRects, pRect); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, + uint32_t numRanges, SVGA3dPrimitiveRange *pRange, + uint32_t cVertexDivisor, SVGA3dVertexDivisor *pVertexDivisor) +{ + RT_NOREF(cid, numVertexDecls, pVertexDecl, numRanges, pRange, cVertexDivisor, pVertexDivisor); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) +{ + RT_NOREF(cid, pRect); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter) +{ + RT_NOREF(sid, filter); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, + uint32_t cbData, uint32_t *pShaderData) +{ + RT_NOREF(cid, shid, type, cbData, pShaderData); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type) +{ + RT_NOREF(cid, shid, type); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackShaderSet(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid) +{ + RT_NOREF(pContext, cid, type, shid); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, + SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues) +{ + RT_NOREF(cid, reg, type, ctype, cRegisters, pValues); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryCreate(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThisCC, pContext); + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThisCC, pContext); + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryBegin(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThisCC, pContext); + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryEnd(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThisCC, pContext); + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryGetData(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t *pu32Pixels) +{ + RT_NOREF(pThisCC, pContext, pu32Pixels); + DEBUG_BREAKPOINT_TEST(); + return VINF_SUCCESS; +} + + +/** + * Destroy backend specific surface bits (part of SVGA_3D_CMD_SURFACE_DESTROY). + * + * @param pThisCC The device context. + * @param fClearCOTableEntry Whether to clear the corresponding COTable entry. + * @param pSurface The surface being destroyed. + */ +static DECLCALLBACK(void) vmsvga3dBackSurfaceDestroy(PVGASTATECC pThisCC, bool fClearCOTableEntry, PVMSVGA3DSURFACE pSurface) +{ + RT_NOREF(pThisCC); + + /* The caller should not use the function for system memory surfaces. */ + PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; + if (!pBackendSurface) + return; + pSurface->pBackendSurface = NULL; + + LogFunc(("sid=%u\n", pSurface->id)); + + /* If any views have been created for this resource, then also release them. */ + DXVIEW *pIter, *pNext; + RTListForEachSafe(&pBackendSurface->listView, pIter, pNext, DXVIEW, nodeSurfaceView) + { + LogFunc(("pIter=%p, pNext=%p\n", pIter, pNext)); + + /** @todo The common DX code should track the views and clean COTable on a surface destruction. */ + if (fClearCOTableEntry) + { + PVMSVGA3DDXCONTEXT pDXContext; + int rc = vmsvga3dDXContextFromCid(pThisCC->svga.p3dState, pIter->cid, &pDXContext); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + switch (pIter->enmViewType) + { + case VMSVGA3D_VIEWTYPE_RENDERTARGET: + { + SVGACOTableDXRTViewEntry *pEntry = &pDXContext->cot.paRTView[pIter->viewId]; + RT_ZERO(*pEntry); + break; + } + case VMSVGA3D_VIEWTYPE_DEPTHSTENCIL: + { + SVGACOTableDXDSViewEntry *pEntry = &pDXContext->cot.paDSView[pIter->viewId]; + RT_ZERO(*pEntry); + break; + } + case VMSVGA3D_VIEWTYPE_SHADERRESOURCE: + { + SVGACOTableDXSRViewEntry *pEntry = &pDXContext->cot.paSRView[pIter->viewId]; + RT_ZERO(*pEntry); + break; + } + case VMSVGA3D_VIEWTYPE_UNORDEREDACCESS: + { + SVGACOTableDXUAViewEntry *pEntry = &pDXContext->cot.paUAView[pIter->viewId]; + RT_ZERO(*pEntry); + break; + } + default: + AssertFailed(); + } + } + } + + dxViewDestroy(pIter); + } + + if ( pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_1D + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_CUBE + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) + { + D3D_RELEASE(pBackendSurface->staging.pResource); + D3D_RELEASE(pBackendSurface->dynamic.pResource); + D3D_RELEASE(pBackendSurface->u.pResource); + } + else if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_BUFFER) + { +#ifndef DX_COMMON_STAGING_BUFFER + D3D_RELEASE(pBackendSurface->staging.pBuffer); + D3D_RELEASE(pBackendSurface->dynamic.pBuffer); +#endif + D3D_RELEASE(pBackendSurface->u.pBuffer); + } + else + { + AssertFailed(); + } + + RTMemFree(pBackendSurface); + + /* No context has created the surface, because the surface does not exist anymore. */ + pSurface->idAssociatedContext = SVGA_ID_INVALID; +} + + +static DECLCALLBACK(void) vmsvga3dBackSurfaceInvalidateImage(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface, uint32_t uFace, uint32_t uMipmap) +{ + RT_NOREF(pThisCC, uFace, uMipmap); + + /* The caller should not use the function for system memory surfaces. */ + PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; + if (!pBackendSurface) + return; + + LogFunc(("sid=%u\n", pSurface->id)); + + /* The guest uses this to invalidate a buffer. */ + if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_BUFFER) + { + Assert(uFace == 0 && uMipmap == 0); /* The caller ensures this. */ + /** @todo This causes flickering when a buffer is invalidated and re-created right before a draw call. */ + //vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); + } + else + { + /** @todo Delete views that have been created for this mipmap. + * For now just delete all views, they will be recte=reated if necessary. + */ + ASSERT_GUEST_FAILED(); + DXVIEW *pIter, *pNext; + RTListForEachSafe(&pBackendSurface->listView, pIter, pNext, DXVIEW, nodeSurfaceView) + { + dxViewDestroy(pIter); + } + } +} + + +/** + * Backend worker for implementing SVGA_3D_CMD_SURFACE_STRETCHBLT. + * + * @returns VBox status code. + * @param pThis The VGA device instance. + * @param pState The VMSVGA3d state. + * @param pDstSurface The destination host surface. + * @param uDstFace The destination face (valid). + * @param uDstMipmap The destination mipmap level (valid). + * @param pDstBox The destination box. + * @param pSrcSurface The source host surface. + * @param uSrcFace The destination face (valid). + * @param uSrcMipmap The source mimap level (valid). + * @param pSrcBox The source box. + * @param enmMode The strecht blt mode . + * @param pContext The VMSVGA3d context (already current for OGL). + */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceStretchBlt(PVGASTATE pThis, PVMSVGA3DSTATE pState, + PVMSVGA3DSURFACE pDstSurface, uint32_t uDstFace, uint32_t uDstMipmap, SVGA3dBox const *pDstBox, + PVMSVGA3DSURFACE pSrcSurface, uint32_t uSrcFace, uint32_t uSrcMipmap, SVGA3dBox const *pSrcBox, + SVGA3dStretchBltMode enmMode, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThis, pState, pDstSurface, uDstFace, uDstMipmap, pDstBox, + pSrcSurface, uSrcFace, uSrcMipmap, pSrcBox, enmMode, pContext); + + AssertFailed(); + return VINF_SUCCESS; +} + + +/** + * Backend worker for implementing SVGA_3D_CMD_SURFACE_DMA that copies one box. + * + * @returns Failure status code or @a rc. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pState The VMSVGA3d state. + * @param pSurface The host surface. + * @param pMipLevel Mipmap level. The caller knows it already. + * @param uHostFace The host face (valid). + * @param uHostMipmap The host mipmap level (valid). + * @param GuestPtr The guest pointer. + * @param cbGuestPitch The guest pitch. + * @param transfer The transfer direction. + * @param pBox The box to copy (clipped, valid, except for guest's srcx, srcy, srcz). + * @param pContext The context (for OpenGL). + * @param rc The current rc for all boxes. + * @param iBox The current box number (for Direct 3D). + */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, + PVMSVGA3DMIPMAPLEVEL pMipLevel, uint32_t uHostFace, uint32_t uHostMipmap, + SVGAGuestPtr GuestPtr, uint32_t cbGuestPitch, SVGA3dTransferType transfer, + SVGA3dCopyBox const *pBox, PVMSVGA3DCONTEXT pContext, int rc, int iBox) +{ + RT_NOREF(pState, pMipLevel, pContext, iBox); + + /* The called should not use the function for system memory surfaces. */ + PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; + AssertReturn(pBackendSurface, VERR_INVALID_PARAMETER); + + if ( pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_1D + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_CUBE + || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) + { + /** @todo This is generic code and should be in DevVGA-SVGA3d.cpp for backends which support Map/Unmap. */ + uint32_t const u32GuestBlockX = pBox->srcx / pSurface->cxBlock; + uint32_t const u32GuestBlockY = pBox->srcy / pSurface->cyBlock; + Assert(u32GuestBlockX * pSurface->cxBlock == pBox->srcx); + Assert(u32GuestBlockY * pSurface->cyBlock == pBox->srcy); + uint32_t const cBlocksX = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock; + uint32_t const cBlocksY = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock; + AssertMsgReturn(cBlocksX && cBlocksY && pBox->d, ("Empty box %dx%dx%d\n", pBox->w, pBox->h, pBox->d), VERR_INTERNAL_ERROR); + + /* vmsvgaR3GmrTransfer verifies uGuestOffset. + * srcx(u32GuestBlockX) and srcy(u32GuestBlockY) have been verified in vmsvga3dSurfaceDMA + * to not cause 32 bit overflow when multiplied by cbBlock and cbGuestPitch. + */ + uint64_t uGuestOffset = u32GuestBlockX * pSurface->cbBlock + u32GuestBlockY * cbGuestPitch; + AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER); + + /* 3D texture needs additional processing. */ + ASSERT_GUEST_RETURN( pBox->z < D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + && pBox->d <= D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + && pBox->d <= D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION - pBox->z, + VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN( pBox->srcz < D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + && pBox->d <= D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + && pBox->d <= D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION - pBox->srcz, + VERR_INVALID_PARAMETER); + + uGuestOffset += pBox->srcz * pMipLevel->cbSurfacePlane; + + SVGA3dSurfaceImageId image; + image.sid = pSurface->id; + image.face = uHostFace; + image.mipmap = uHostMipmap; + + SVGA3dBox box; + box.x = pBox->x; + box.y = pBox->y; + box.z = pBox->z; + box.w = pBox->w; + box.h = pBox->h; + box.d = pBox->d; + + VMSVGA3D_SURFACE_MAP const enmMap = transfer == SVGA3D_WRITE_HOST_VRAM + ? VMSVGA3D_SURFACE_MAP_WRITE + : VMSVGA3D_SURFACE_MAP_READ; + + VMSVGA3D_MAPPED_SURFACE map; + rc = vmsvga3dBackSurfaceMap(pThisCC, &image, &box, enmMap, &map); + if (RT_SUCCESS(rc)) + { +#if 0 + if (box.w == 250 && box.h == 250 && box.d == 1 && enmMap == VMSVGA3D_SURFACE_MAP_READ) + { + DEBUG_BREAKPOINT_TEST(); + vmsvga3dMapWriteBmpFile(&map, "P"); + } +#endif + /* Prepare parameters for vmsvgaR3GmrTransfer, which needs the host buffer address, size + * and offset of the first scanline. + */ + uint32_t cbLockedBuf = map.cbRowPitch * cBlocksY; + if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) + cbLockedBuf += map.cbDepthPitch * (pBox->d - 1); /// @todo why map does not compute this for 2D textures + uint8_t *pu8LockedBuf = (uint8_t *)map.pvData; + uint32_t offLockedBuf = 0; + + for (uint32_t iPlane = 0; iPlane < pBox->d; ++iPlane) + { + AssertBreak(uGuestOffset < UINT32_MAX); + + rc = vmsvgaR3GmrTransfer(pThis, + pThisCC, + transfer, + pu8LockedBuf, + cbLockedBuf, + offLockedBuf, + map.cbRowPitch, + GuestPtr, + (uint32_t)uGuestOffset, + cbGuestPitch, + cBlocksX * pSurface->cbBlock, + cBlocksY); + AssertRC(rc); + + uGuestOffset += pMipLevel->cbSurfacePlane; + offLockedBuf += map.cbDepthPitch; + } + + bool const fWritten = (transfer == SVGA3D_WRITE_HOST_VRAM); + vmsvga3dBackSurfaceUnmap(pThisCC, &image, &map, fWritten); + } + } + else + { + AssertMsgFailed(("Unsupported surface type %d\n", pBackendSurface->enmResType)); + rc = VERR_NOT_IMPLEMENTED; + } + + return rc; +} + + +/** + * Create D3D/OpenGL texture object for the specified surface. + * + * Surfaces are created when needed. + * + * @param pThisCC The device context. + * @param pContext The context. + * @param idAssociatedContext Probably the same as pContext->id. + * @param pSurface The surface to create the texture for. + */ +static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, + PVMSVGA3DSURFACE pSurface) + +{ + RT_NOREF(pThisCC, pContext, idAssociatedContext, pSurface); + + AssertFailed(); + return VINF_SUCCESS; +} + + +/* + * DX callbacks. + */ + +static DECLCALLBACK(int) vmsvga3dBackDXDefineContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + /* Allocate a backend specific context structure. */ + PVMSVGA3DBACKENDDXCONTEXT pBackendDXContext = (PVMSVGA3DBACKENDDXCONTEXT)RTMemAllocZ(sizeof(VMSVGA3DBACKENDDXCONTEXT)); + AssertPtrReturn(pBackendDXContext, VERR_NO_MEMORY); + pDXContext->pBackendDXContext = pBackendDXContext; + + LogFunc(("cid %d\n", pDXContext->cid)); + + int rc = dxDeviceCreate(pBackend, &pBackendDXContext->dxDevice); + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + LogFunc(("cid %d\n", pDXContext->cid)); + + if (pDXContext->pBackendDXContext) + { + /* Clean up context resources. */ + VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; + + for (uint32_t idxShaderState = 0; idxShaderState < RT_ELEMENTS(pBackendDXContext->resources.shaderState); ++idxShaderState) + { + ID3D11Buffer **papConstantBuffer = &pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers[0]; + D3D_RELEASE_ARRAY(RT_ELEMENTS(pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers), papConstantBuffer); + } + + for (uint32_t i = 0; i < RT_ELEMENTS(pBackendDXContext->resources.inputAssembly.vertexBuffers); ++i) + { + D3D_RELEASE(pBackendDXContext->resources.inputAssembly.vertexBuffers[i].pBuffer); + } + + D3D_RELEASE(pBackendDXContext->resources.inputAssembly.indexBuffer.pBuffer); + + if (pBackendDXContext->dxDevice.pImmediateContext) + dxDeviceFlush(&pBackendDXContext->dxDevice); /* Make sure that any pending draw calls are finished. */ + + if (pBackendDXContext->paRenderTargetView) + { + for (uint32_t i = 0; i < pBackendDXContext->cRenderTargetView; ++i) + D3D_RELEASE(pBackendDXContext->paRenderTargetView[i].u.pRenderTargetView); + } + if (pBackendDXContext->paDepthStencilView) + { + for (uint32_t i = 0; i < pBackendDXContext->cDepthStencilView; ++i) + D3D_RELEASE(pBackendDXContext->paDepthStencilView[i].u.pDepthStencilView); + } + if (pBackendDXContext->paShaderResourceView) + { + for (uint32_t i = 0; i < pBackendDXContext->cShaderResourceView; ++i) + D3D_RELEASE(pBackendDXContext->paShaderResourceView[i].u.pShaderResourceView); + } + if (pBackendDXContext->paElementLayout) + { + for (uint32_t i = 0; i < pBackendDXContext->cElementLayout; ++i) + D3D_RELEASE(pBackendDXContext->paElementLayout[i].pElementLayout); + } + if (pBackendDXContext->papBlendState) + D3D_RELEASE_ARRAY(pBackendDXContext->cBlendState, pBackendDXContext->papBlendState); + if (pBackendDXContext->papDepthStencilState) + D3D_RELEASE_ARRAY(pBackendDXContext->cDepthStencilState, pBackendDXContext->papDepthStencilState); + if (pBackendDXContext->papRasterizerState) + D3D_RELEASE_ARRAY(pBackendDXContext->cRasterizerState, pBackendDXContext->papRasterizerState); + if (pBackendDXContext->papSamplerState) + D3D_RELEASE_ARRAY(pBackendDXContext->cSamplerState, pBackendDXContext->papSamplerState); + if (pBackendDXContext->paQuery) + { + for (uint32_t i = 0; i < pBackendDXContext->cQuery; ++i) + dxDestroyQuery(&pBackendDXContext->paQuery[i]); + } + if (pBackendDXContext->paShader) + { + for (uint32_t i = 0; i < pBackendDXContext->cShader; ++i) + dxDestroyShader(&pBackendDXContext->paShader[i]); + } + if (pBackendDXContext->paStreamOutput) + { + for (uint32_t i = 0; i < pBackendDXContext->cStreamOutput; ++i) + dxDestroyStreamOutput(&pBackendDXContext->paStreamOutput[i]); + } + if (pBackendDXContext->paUnorderedAccessView) + { + for (uint32_t i = 0; i < pBackendDXContext->cUnorderedAccessView; ++i) + D3D_RELEASE(pBackendDXContext->paUnorderedAccessView[i].u.pUnorderedAccessView); + } + + RTMemFreeZ(pBackendDXContext->papBlendState, sizeof(pBackendDXContext->papBlendState[0]) * pBackendDXContext->cBlendState); + RTMemFreeZ(pBackendDXContext->papDepthStencilState, sizeof(pBackendDXContext->papDepthStencilState[0]) * pBackendDXContext->cDepthStencilState); + RTMemFreeZ(pBackendDXContext->papSamplerState, sizeof(pBackendDXContext->papSamplerState[0]) * pBackendDXContext->cSamplerState); + RTMemFreeZ(pBackendDXContext->papRasterizerState, sizeof(pBackendDXContext->papRasterizerState[0]) * pBackendDXContext->cRasterizerState); + RTMemFreeZ(pBackendDXContext->paElementLayout, sizeof(pBackendDXContext->paElementLayout[0]) * pBackendDXContext->cElementLayout); + RTMemFreeZ(pBackendDXContext->paRenderTargetView, sizeof(pBackendDXContext->paRenderTargetView[0]) * pBackendDXContext->cRenderTargetView); + RTMemFreeZ(pBackendDXContext->paDepthStencilView, sizeof(pBackendDXContext->paDepthStencilView[0]) * pBackendDXContext->cDepthStencilView); + RTMemFreeZ(pBackendDXContext->paShaderResourceView, sizeof(pBackendDXContext->paShaderResourceView[0]) * pBackendDXContext->cShaderResourceView); + RTMemFreeZ(pBackendDXContext->paQuery, sizeof(pBackendDXContext->paQuery[0]) * pBackendDXContext->cQuery); + RTMemFreeZ(pBackendDXContext->paShader, sizeof(pBackendDXContext->paShader[0]) * pBackendDXContext->cShader); + RTMemFreeZ(pBackendDXContext->paStreamOutput, sizeof(pBackendDXContext->paStreamOutput[0]) * pBackendDXContext->cStreamOutput); + RTMemFreeZ(pBackendDXContext->paUnorderedAccessView, sizeof(pBackendDXContext->paUnorderedAccessView[0]) * pBackendDXContext->cUnorderedAccessView); + + /* Destroy backend surfaces which belong to this context. */ + /** @todo The context should have a list of surfaces (and also shared resources). */ + /** @todo This should not be needed in fSingleDevice mode. */ + for (uint32_t sid = 0; sid < pThisCC->svga.p3dState->cSurfaces; ++sid) + { + PVMSVGA3DSURFACE const pSurface = pThisCC->svga.p3dState->papSurfaces[sid]; + if ( pSurface + && pSurface->id == sid) + { + if (pSurface->idAssociatedContext == pDXContext->cid) + { + if (pSurface->pBackendSurface) + vmsvga3dBackSurfaceDestroy(pThisCC, true, pSurface); + } + else if (pSurface->idAssociatedContext == DX_CID_BACKEND) + { + /* May have shared resources in this context. */ + if (pSurface->pBackendSurface) + { + DXSHAREDTEXTURE *pSharedTexture = (DXSHAREDTEXTURE *)RTAvlU32Get(&pSurface->pBackendSurface->SharedTextureTree, pDXContext->cid); + if (pSharedTexture) + { + Assert(pSharedTexture->sid == sid); + RTAvlU32Remove(&pSurface->pBackendSurface->SharedTextureTree, pDXContext->cid); + D3D_RELEASE(pSharedTexture->pTexture); + RTMemFreeZ(pSharedTexture, sizeof(*pSharedTexture)); + } + } + } + } + } + + dxDeviceDestroy(pBackend, &pBackendDXContext->dxDevice); + + RTMemFreeZ(pBackendDXContext, sizeof(*pBackendDXContext)); + pDXContext->pBackendDXContext = NULL; + } + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXBindContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend, pDXContext); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSwitchContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + if (!pBackend->fSingleDevice) + return VINF_NOT_IMPLEMENTED; /* Not required. */ + + /* The new context state will be applied by the generic DX code. */ + RT_NOREF(pDXContext); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXReadbackContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend, pDXContext); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXInvalidateContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetSingleConstantBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t slot, SVGA3dShaderType type, SVGA3dSurfaceId sid, uint32_t offsetInBytes, uint32_t sizeInBytes) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + if (sid == SVGA_ID_INVALID) + { + uint32_t const idxShaderState = type - SVGA3D_SHADERTYPE_MIN; + D3D_RELEASE(pDXContext->pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers[slot]); + return VINF_SUCCESS; + } + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, 0, 0, &pMipLevel); + AssertRCReturn(rc, rc); + + uint32_t const cbSurface = pMipLevel->cbSurface; + ASSERT_GUEST_RETURN( offsetInBytes < cbSurface + && sizeInBytes <= cbSurface - offsetInBytes, VERR_INVALID_PARAMETER); + + /* Constant buffers are created on demand. */ + Assert(pSurface->pBackendSurface == NULL); + + /* Upload the current data, if any. */ + D3D11_SUBRESOURCE_DATA *pInitialData = NULL; + D3D11_SUBRESOURCE_DATA initialData; + if (pMipLevel->pSurfaceData) + { + initialData.pSysMem = (uint8_t *)pMipLevel->pSurfaceData + offsetInBytes; + initialData.SysMemPitch = sizeInBytes; + initialData.SysMemSlicePitch = sizeInBytes; + + pInitialData = &initialData; + +#ifdef LOG_ENABLED + if (LogIs8Enabled()) + { + float *pValuesF = (float *)initialData.pSysMem; + for (unsigned i = 0; i < sizeInBytes / sizeof(float) / 4; ++i) + { + Log(("ConstantF[%d]: " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR "\n", + i, FLOAT_FMT_ARGS(pValuesF[i*4 + 0]), FLOAT_FMT_ARGS(pValuesF[i*4 + 1]), FLOAT_FMT_ARGS(pValuesF[i*4 + 2]), FLOAT_FMT_ARGS(pValuesF[i*4 + 3]))); + } + } +#endif + } + + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = sizeInBytes; + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bd.CPUAccessFlags = 0; + bd.MiscFlags = 0; + bd.StructureByteStride = 0; + + ID3D11Buffer *pBuffer = 0; + HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBuffer); + if (SUCCEEDED(hr)) + { + uint32_t const idxShaderState = type - SVGA3D_SHADERTYPE_MIN; + ID3D11Buffer **ppOldBuffer = &pDXContext->pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers[slot]; + LogFunc(("constant buffer: [%u][%u]: sid = %u, %u, %u (%p -> %p)\n", + idxShaderState, slot, sid, offsetInBytes, sizeInBytes, *ppOldBuffer, pBuffer)); + D3D_RELEASE(*ppOldBuffer); + *ppOldBuffer = pBuffer; + } + + return VINF_SUCCESS; +} + +static int dxSetShaderResources(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderType type) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + +//DEBUG_BREAKPOINT_TEST(); + AssertReturn(type >= SVGA3D_SHADERTYPE_MIN && type < SVGA3D_SHADERTYPE_MAX, VERR_INVALID_PARAMETER); + uint32_t const idxShaderState = type - SVGA3D_SHADERTYPE_MIN; + uint32_t const *pSRIds = &pDXContext->svgaDXContext.shaderState[idxShaderState].shaderResources[0]; + ID3D11ShaderResourceView *papShaderResourceView[SVGA3D_DX_MAX_SRVIEWS]; + for (uint32_t i = 0; i < SVGA3D_DX_MAX_SRVIEWS; ++i) + { + SVGA3dShaderResourceViewId shaderResourceViewId = pSRIds[i]; + if (shaderResourceViewId != SVGA3D_INVALID_ID) + { + ASSERT_GUEST_RETURN(shaderResourceViewId < pDXContext->pBackendDXContext->cShaderResourceView, VERR_INVALID_PARAMETER); + + DXVIEW *pDXView = &pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId]; + Assert(pDXView->u.pShaderResourceView); + papShaderResourceView[i] = pDXView->u.pShaderResourceView; + } + else + papShaderResourceView[i] = NULL; + } + + dxShaderResourceViewSet(pDevice, type, 0, SVGA3D_DX_MAX_SRVIEWS, papShaderResourceView); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetShaderResources(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startView, SVGA3dShaderType type, uint32_t cShaderResourceViewId, SVGA3dShaderResourceViewId const *paShaderResourceViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(startView, type, cShaderResourceViewId, paShaderResourceViewId); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, SVGA3dShaderType type) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(shaderId, type); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetSamplers(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startSampler, SVGA3dShaderType type, uint32_t cSamplerId, SVGA3dSamplerId const *paSamplerId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + ID3D11SamplerState *papSamplerState[SVGA3D_DX_MAX_SAMPLERS]; + for (uint32_t i = 0; i < cSamplerId; ++i) + { + SVGA3dSamplerId samplerId = paSamplerId[i]; + if (samplerId != SVGA3D_INVALID_ID) + { + ASSERT_GUEST_RETURN(samplerId < pDXContext->pBackendDXContext->cSamplerState, VERR_INVALID_PARAMETER); + papSamplerState[i] = pDXContext->pBackendDXContext->papSamplerState[samplerId]; + } + else + papSamplerState[i] = NULL; + } + + dxSamplerSet(pDevice, type, startSampler, cSamplerId, papSamplerState); + return VINF_SUCCESS; +} + + +static void vboxDXMatchShaderInput(DXSHADER *pDXShader, DXSHADER *pDXShaderPrior) +{ + /* For each input generic attribute of the shader find corresponding entry in the prior shader. */ + for (uint32_t i = 0; i < pDXShader->shaderInfo.cInputSignature; ++i) + { + SVGA3dDXSignatureEntry const *pSignatureEntry = &pDXShader->shaderInfo.aInputSignature[i]; + DXShaderAttributeSemantic *pSemantic = &pDXShader->shaderInfo.aInputSemantic[i]; + + if (pSignatureEntry->semanticName != SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED) + continue; + + int iMatch = -1; + for (uint32_t iPrior = 0; iPrior < pDXShaderPrior->shaderInfo.cOutputSignature; ++iPrior) + { + SVGA3dDXSignatureEntry const *pPriorSignatureEntry = &pDXShaderPrior->shaderInfo.aOutputSignature[iPrior]; + + if (pPriorSignatureEntry->semanticName != SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED) + continue; + + if (pPriorSignatureEntry->registerIndex == pSignatureEntry->registerIndex) + { + iMatch = iPrior; + if (pPriorSignatureEntry->mask == pSignatureEntry->mask) + break; /* Exact match, no need to continue search. */ + } + } + + if (iMatch >= 0) + { + SVGA3dDXSignatureEntry const *pPriorSignatureEntry = &pDXShaderPrior->shaderInfo.aOutputSignature[iMatch]; + DXShaderAttributeSemantic const *pPriorSemantic = &pDXShaderPrior->shaderInfo.aOutputSemantic[iMatch]; + + Assert(pPriorSignatureEntry->registerIndex == pSignatureEntry->registerIndex); + Assert((pPriorSignatureEntry->mask & pSignatureEntry->mask) == pSignatureEntry->mask); + RT_NOREF(pPriorSignatureEntry); + + pSemantic->SemanticIndex = pPriorSemantic->SemanticIndex; + } + } +} + + +static void vboxDXMatchShaderSignatures(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, DXSHADER *pDXShader) +{ + SVGA3dShaderId const shaderIdVS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_VS - SVGA3D_SHADERTYPE_MIN].shaderId; + SVGA3dShaderId const shaderIdHS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_HS - SVGA3D_SHADERTYPE_MIN].shaderId; + SVGA3dShaderId const shaderIdDS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_DS - SVGA3D_SHADERTYPE_MIN].shaderId; + SVGA3dShaderId const shaderIdGS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_GS - SVGA3D_SHADERTYPE_MIN].shaderId; + SVGA3dShaderId const shaderIdPS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_PS - SVGA3D_SHADERTYPE_MIN].shaderId; + + /* Try to fix the input semantic indices. Output is usually not changed. */ + switch (pDXShader->enmShaderType) + { + case SVGA3D_SHADERTYPE_VS: + { + /* Match input to input layout, which sets generic semantic indices to the source registerIndex (dxCreateInputLayout). */ + for (uint32_t i = 0; i < pDXShader->shaderInfo.cInputSignature; ++i) + { + SVGA3dDXSignatureEntry const *pSignatureEntry = &pDXShader->shaderInfo.aInputSignature[i]; + DXShaderAttributeSemantic *pSemantic = &pDXShader->shaderInfo.aInputSemantic[i]; + + if (pSignatureEntry->semanticName != SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED) + continue; + + pSemantic->SemanticIndex = pSignatureEntry->registerIndex; + } + break; + } + case SVGA3D_SHADERTYPE_HS: + { + /* Input of a HS shader is the output of VS. */ + DXSHADER *pDXShaderPrior; + if (shaderIdVS != SVGA3D_INVALID_ID) + pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdVS]; + else + pDXShaderPrior = NULL; + + if (pDXShaderPrior) + vboxDXMatchShaderInput(pDXShader, pDXShaderPrior); + + break; + } + case SVGA3D_SHADERTYPE_DS: + { + /* Input of a DS shader is the output of HS. */ + DXSHADER *pDXShaderPrior; + if (shaderIdHS != SVGA3D_INVALID_ID) + pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdHS]; + else + pDXShaderPrior = NULL; + + if (pDXShaderPrior) + vboxDXMatchShaderInput(pDXShader, pDXShaderPrior); + + break; + } + case SVGA3D_SHADERTYPE_GS: + { + /* Input signature of a GS shader is the output of DS or VS. */ + DXSHADER *pDXShaderPrior; + if (shaderIdDS != SVGA3D_INVALID_ID) + pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdDS]; + else if (shaderIdVS != SVGA3D_INVALID_ID) + pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdVS]; + else + pDXShaderPrior = NULL; + + if (pDXShaderPrior) + { + /* If GS shader does not have input signature (Windows guest can do that), + * then assign the prior shader signature as GS input. + */ + if (pDXShader->shaderInfo.cInputSignature == 0) + { + pDXShader->shaderInfo.cInputSignature = pDXShaderPrior->shaderInfo.cOutputSignature; + memcpy(pDXShader->shaderInfo.aInputSignature, + pDXShaderPrior->shaderInfo.aOutputSignature, + pDXShaderPrior->shaderInfo.cOutputSignature * sizeof(SVGA3dDXSignatureEntry)); + memcpy(pDXShader->shaderInfo.aInputSemantic, + pDXShaderPrior->shaderInfo.aOutputSemantic, + pDXShaderPrior->shaderInfo.cOutputSignature * sizeof(DXShaderAttributeSemantic)); + } + else + vboxDXMatchShaderInput(pDXShader, pDXShaderPrior); + } + + /* Output signature of a GS shader is the input of the pixel shader. */ + if (shaderIdPS != SVGA3D_INVALID_ID) + { + /* If GS shader does not have output signature (Windows guest can do that), + * then assign the PS shader signature as GS output. + */ + if (pDXShader->shaderInfo.cOutputSignature == 0) + { + DXSHADER const *pDXShaderPosterior = &pDXContext->pBackendDXContext->paShader[shaderIdPS]; + pDXShader->shaderInfo.cOutputSignature = pDXShaderPosterior->shaderInfo.cInputSignature; + memcpy(pDXShader->shaderInfo.aOutputSignature, + pDXShaderPosterior->shaderInfo.aInputSignature, + pDXShaderPosterior->shaderInfo.cInputSignature * sizeof(SVGA3dDXSignatureEntry)); + memcpy(pDXShader->shaderInfo.aOutputSemantic, + pDXShaderPosterior->shaderInfo.aInputSemantic, + pDXShaderPosterior->shaderInfo.cInputSignature * sizeof(DXShaderAttributeSemantic)); + } + } + + SVGA3dStreamOutputId const soid = pDXContext->svgaDXContext.streamOut.soid; + if (soid != SVGA3D_INVALID_ID) + { + ASSERT_GUEST_RETURN_VOID(soid < pDXContext->pBackendDXContext->cStreamOutput); + + /* Set semantic names and indices for SO declaration entries according to the shader output. */ + SVGACOTableDXStreamOutputEntry const *pStreamOutputEntry = &pDXContext->cot.paStreamOutput[soid]; + DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; + + if (pDXStreamOutput->cDeclarationEntry == 0) + { + int rc = dxDefineStreamOutput(pThisCC, pDXContext, soid, pStreamOutputEntry, pDXShader); + AssertRCReturnVoid(rc); +#ifdef LOG_ENABLED + Log6(("Stream output declaration:\n\n")); + Log6(("Stream SemanticName SemanticIndex StartComponent ComponentCount OutputSlot\n")); + Log6(("------ -------------- ------------- -------------- -------------- ----------\n")); + for (unsigned i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) + { + D3D11_SO_DECLARATION_ENTRY *p = &pDXStreamOutput->aDeclarationEntry[i]; + Log6(("%d %-14s %d %d %d %d\n", + p->Stream, p->SemanticName, p->SemanticIndex, p->StartComponent, p->ComponentCount, p->OutputSlot)); + } + Log6(("\n")); +#endif + + } + } + break; + } + case SVGA3D_SHADERTYPE_PS: + { + /* Input of a PS shader is the output of GS, DS or VS. */ + DXSHADER *pDXShaderPrior; + if (shaderIdGS != SVGA3D_INVALID_ID) + pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdGS]; + else if (shaderIdDS != SVGA3D_INVALID_ID) + pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdDS]; + else if (shaderIdVS != SVGA3D_INVALID_ID) + pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdVS]; + else + pDXShaderPrior = NULL; + + if (pDXShaderPrior) + vboxDXMatchShaderInput(pDXShader, pDXShaderPrior); + break; + } + default: + break; + } + + /* Intermediate shaders normally have both input and output signatures. However it is ok if they do not. + * Just catch this unusual case in order to see if everything is fine. + */ + Assert( ( pDXShader->enmShaderType == SVGA3D_SHADERTYPE_VS + || pDXShader->enmShaderType == SVGA3D_SHADERTYPE_PS + || pDXShader->enmShaderType == SVGA3D_SHADERTYPE_CS) + || (pDXShader->shaderInfo.cInputSignature && pDXShader->shaderInfo.cOutputSignature)); +} + + +static void vboxDXUpdateVSInputSignature(PVMSVGA3DDXCONTEXT pDXContext, DXSHADER *pDXShader) +{ + SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; + if (elementLayoutId != SVGA3D_INVALID_ID) + { + SVGACOTableDXElementLayoutEntry const *pElementLayout = &pDXContext->cot.paElementLayout[elementLayoutId]; + for (uint32_t i = 0; i < RT_MIN(pElementLayout->numDescs, pDXShader->shaderInfo.cInputSignature); ++i) + { + SVGA3dInputElementDesc const *pElementDesc = &pElementLayout->descs[i]; + SVGA3dDXSignatureEntry *pSignatureEntry = &pDXShader->shaderInfo.aInputSignature[i]; + pSignatureEntry->componentType = DXShaderComponentTypeFromFormat(pElementDesc->format); + } + } +} + + +static void dxCreateInputLayout(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId, DXSHADER *pDXShader) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturnVoid(pDevice->pDevice); + + SVGACOTableDXElementLayoutEntry const *pEntry = &pDXContext->cot.paElementLayout[elementLayoutId]; + DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; + + if (pDXElementLayout->cElementDesc == 0) + { + /* Semantic name is not interpreted by D3D, therefore arbitrary names can be used + * if they are consistent between the element layout and shader input signature. + * "In general, data passed between pipeline stages is completely generic and is not uniquely + * interpreted by the system; arbitrary semantics are allowed ..." + * + * However D3D runtime insists that "SemanticName string ("POSITIO1") cannot end with a number." + * + * System-Value semantics ("SV_*") between shaders require proper names of course. + * But they are irrelevant for input attributes. + */ + pDXElementLayout->cElementDesc = pEntry->numDescs; + for (uint32_t i = 0; i < pEntry->numDescs; ++i) + { + D3D11_INPUT_ELEMENT_DESC *pDst = &pDXElementLayout->aElementDesc[i]; + SVGA3dInputElementDesc const *pSrc = &pEntry->descs[i]; + pDst->SemanticName = "ATTRIB"; + pDst->SemanticIndex = pSrc->inputRegister; + pDst->Format = vmsvgaDXSurfaceFormat2Dxgi(pSrc->format); + Assert(pDst->Format != DXGI_FORMAT_UNKNOWN); + pDst->InputSlot = pSrc->inputSlot; + pDst->AlignedByteOffset = pSrc->alignedByteOffset; + pDst->InputSlotClass = (D3D11_INPUT_CLASSIFICATION)pSrc->inputSlotClass; + pDst->InstanceDataStepRate = pSrc->instanceDataStepRate; + } + } + + HRESULT hr = pDevice->pDevice->CreateInputLayout(pDXElementLayout->aElementDesc, + pDXElementLayout->cElementDesc, + pDXShader->pvDXBC, + pDXShader->cbDXBC, + &pDXElementLayout->pElementLayout); + Assert(SUCCEEDED(hr)); RT_NOREF(hr); +} + + +static void dxSetConstantBuffers(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ +//DEBUG_BREAKPOINT_TEST(); + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; + + AssertCompile(RT_ELEMENTS(pBackendDXContext->resources.shaderState[0].constantBuffers) == SVGA3D_DX_MAX_CONSTBUFFERS); + + for (uint32_t idxShaderState = 0; idxShaderState < SVGA3D_NUM_SHADERTYPE; ++idxShaderState) + { + SVGA3dShaderType const shaderType = (SVGA3dShaderType)(idxShaderState + SVGA3D_SHADERTYPE_MIN); + for (uint32_t idxSlot = 0; idxSlot < SVGA3D_DX_MAX_CONSTBUFFERS; ++idxSlot) + { + ID3D11Buffer **pBufferContext = &pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers[idxSlot]; + ID3D11Buffer **pBufferPipeline = &pBackend->resources.shaderState[idxShaderState].constantBuffers[idxSlot]; + if (*pBufferContext != *pBufferPipeline) + { + LogFunc(("constant buffer: [%u][%u]: %p -> %p\n", + idxShaderState, idxSlot, *pBufferPipeline, *pBufferContext)); + dxConstantBufferSet(pDXDevice, idxSlot, shaderType, *pBufferContext); + + if (*pBufferContext) + (*pBufferContext)->AddRef(); + D3D_RELEASE(*pBufferPipeline); + *pBufferPipeline = *pBufferContext; + } + } + } +} + +static void dxSetVertexBuffers(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ +//DEBUG_BREAKPOINT_TEST(); + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; + + AssertCompile(RT_ELEMENTS(pBackendDXContext->resources.inputAssembly.vertexBuffers) == SVGA3D_DX_MAX_VERTEXBUFFERS); + + ID3D11Buffer *paResources[SVGA3D_DX_MAX_VERTEXBUFFERS]; + UINT paStride[SVGA3D_DX_MAX_VERTEXBUFFERS]; + UINT paOffset[SVGA3D_DX_MAX_VERTEXBUFFERS]; + + int32_t idxMaxSlot = -1; + for (uint32_t i = 0; i < SVGA3D_DX_MAX_VERTEXBUFFERS; ++i) + { + DXBOUNDVERTEXBUFFER *pBufferContext = &pBackendDXContext->resources.inputAssembly.vertexBuffers[i]; + DXBOUNDVERTEXBUFFER *pBufferPipeline = &pBackend->resources.inputAssembly.vertexBuffers[i]; + if ( pBufferContext->pBuffer != pBufferPipeline->pBuffer + || pBufferContext->stride != pBufferPipeline->stride + || pBufferContext->offset != pBufferPipeline->offset) + { + LogFunc(("vertex buffer: [%u]: sid = %u, %p (stride %d, off %d) -> %p (stride %d, off %d)\n", + i, pDXContext->svgaDXContext.inputAssembly.vertexBuffers[i].bufferId, + pBufferPipeline->pBuffer, pBufferPipeline->stride, pBufferPipeline->offset, + pBufferContext->pBuffer, pBufferContext->stride, pBufferContext->offset)); + + if (pBufferContext->pBuffer != pBufferPipeline->pBuffer) + { + if (pBufferContext->pBuffer) + pBufferContext->pBuffer->AddRef(); + D3D_RELEASE(pBufferPipeline->pBuffer); + } + *pBufferPipeline = *pBufferContext; + + idxMaxSlot = i; + } +#ifdef LOG_ENABLED + else if (pBufferContext->pBuffer) + { + LogFunc(("vertex buffer: [%u]: sid = %u, %p (stride %d, off %d)\n", + i, pDXContext->svgaDXContext.inputAssembly.vertexBuffers[i].bufferId, + pBufferContext->pBuffer, pBufferContext->stride, pBufferContext->offset)); + } +#endif + + paResources[i] = pBufferContext->pBuffer; + if (pBufferContext->pBuffer) + { + paStride[i] = pBufferContext->stride; + paOffset[i] = pBufferContext->offset; + } + else + { + paStride[i] = 0; + paOffset[i] = 0; + } + } + + LogFunc(("idxMaxSlot = %d\n", idxMaxSlot)); + if (idxMaxSlot >= 0) + pDXDevice->pImmediateContext->IASetVertexBuffers(0, idxMaxSlot + 1, paResources, paStride, paOffset); +} + +static void dxSetIndexBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ +//DEBUG_BREAKPOINT_TEST(); + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; + + DXBOUNDINDEXBUFFER *pBufferContext = &pBackendDXContext->resources.inputAssembly.indexBuffer; + DXBOUNDINDEXBUFFER *pBufferPipeline = &pBackend->resources.inputAssembly.indexBuffer; + if ( pBufferContext->pBuffer != pBufferPipeline->pBuffer + || pBufferContext->indexBufferOffset != pBufferPipeline->indexBufferOffset + || pBufferContext->indexBufferFormat != pBufferPipeline->indexBufferFormat) + { + LogFunc(("index_buffer: sid = %u, %p -> %p\n", + pDXContext->svgaDXContext.inputAssembly.indexBufferSid, pBufferPipeline->pBuffer, pBufferContext->pBuffer)); + + if (pBufferContext->pBuffer != pBufferPipeline->pBuffer) + { + if (pBufferContext->pBuffer) + pBufferContext->pBuffer->AddRef(); + D3D_RELEASE(pBufferPipeline->pBuffer); + } + *pBufferPipeline = *pBufferContext; + + pDXDevice->pImmediateContext->IASetIndexBuffer(pBufferContext->pBuffer, pBufferContext->indexBufferFormat, pBufferContext->indexBufferOffset); + } +} + +#ifdef LOG_ENABLED +static void dxDbgLogVertexElement(DXGI_FORMAT Format, void const *pvElementData) +{ + switch (Format) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + float const *pValues = (float const *)pvElementData; + Log8(("{ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " },", + FLOAT_FMT_ARGS(pValues[0]), FLOAT_FMT_ARGS(pValues[1]), FLOAT_FMT_ARGS(pValues[2]), FLOAT_FMT_ARGS(pValues[3]))); + break; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + float const *pValues = (float const *)pvElementData; + Log8(("{ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " },", + FLOAT_FMT_ARGS(pValues[0]), FLOAT_FMT_ARGS(pValues[1]), FLOAT_FMT_ARGS(pValues[2]))); + break; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + float const *pValues = (float const *)pvElementData; + Log8(("{ " FLOAT_FMT_STR ", " FLOAT_FMT_STR " },", + FLOAT_FMT_ARGS(pValues[0]), FLOAT_FMT_ARGS(pValues[1]))); + break; + } + case DXGI_FORMAT_R16G16_FLOAT: + { + uint16_t const *pValues = (uint16_t const *)pvElementData; + Log8(("{ f16 " FLOAT_FMT_STR ", " FLOAT_FMT_STR " },", + FLOAT_FMT_ARGS(float16ToFloat(pValues[0])), FLOAT_FMT_ARGS(float16ToFloat(pValues[1])))); + break; + } + case DXGI_FORMAT_R32G32_SINT: + { + int32_t const *pValues = (int32_t const *)pvElementData; + Log8(("{ %d, %d },", + pValues[0], pValues[1])); + break; + } + case DXGI_FORMAT_R32G32_UINT: + { + uint32_t const *pValues = (uint32_t const *)pvElementData; + Log8(("{ %u, %u },", + pValues[0], pValues[1])); + break; + } + case DXGI_FORMAT_R32_SINT: + { + int32_t const *pValues = (int32_t const *)pvElementData; + Log8(("{ %d },", + pValues[0])); + break; + } + case DXGI_FORMAT_R32_UINT: + { + uint32_t const *pValues = (uint32_t const *)pvElementData; + Log8(("{ %u },", + pValues[0])); + break; + } + case DXGI_FORMAT_R16G16_SINT: + { + int16_t const *pValues = (int16_t const *)pvElementData; + Log8(("{ s %d, %d },", + pValues[0], pValues[1])); + break; + } + case DXGI_FORMAT_R16G16_UINT: + { + uint16_t const *pValues = (uint16_t const *)pvElementData; + Log8(("{ u %u, %u },", + pValues[0], pValues[1])); + break; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + uint8_t const *pValues = (uint8_t const *)pvElementData; + Log8(("{ 8unorm %u, %u, %u, %u },", + pValues[0], pValues[1], pValues[2], pValues[3])); + break; + } + case DXGI_FORMAT_R8G8_UNORM: + { + uint8_t const *pValues = (uint8_t const *)pvElementData; + Log8(("{ 8unorm %u, %u },", + pValues[0], pValues[1])); + break; + } + default: + Log8(("{ ??? DXGI_FORMAT %d },", + Format)); + AssertFailed(); + } +} + + +static void dxDbgDumpVertexData(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCount, uint32_t startVertexLocation) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + for (uint32_t iSlot = 0; iSlot < SVGA3D_DX_MAX_VERTEXBUFFERS; ++iSlot) + { + DXBOUNDVERTEXBUFFER *pBufferPipeline = &pBackend->resources.inputAssembly.vertexBuffers[iSlot]; + uint32_t const sid = pDXContext->svgaDXContext.inputAssembly.vertexBuffers[iSlot].bufferId; + if (sid == SVGA3D_INVALID_ID) + { + Assert(pBufferPipeline->pBuffer == 0); + continue; + } + + Assert(pBufferPipeline->pBuffer); + + SVGA3dSurfaceImageId image; + image.sid = sid; + image.face = 0; + image.mipmap = 0; + + VMSVGA3D_MAPPED_SURFACE map; + int rc = vmsvga3dBackSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + uint8_t const *pu8VertexData = (uint8_t *)map.pvData; + pu8VertexData += pBufferPipeline->offset; + pu8VertexData += startVertexLocation * pBufferPipeline->stride; + + SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; + DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; + Assert(pDXElementLayout->cElementDesc > 0); + + Log8(("Vertex buffer dump: sid = %u, vertexCount %u, startVertexLocation %d, offset = %d, stride = %d:\n", + sid, vertexCount, startVertexLocation, pBufferPipeline->offset, pBufferPipeline->stride)); + + for (uint32_t v = 0; v < vertexCount; ++v) + { + Log8(("slot[%u] v%u { ", iSlot, startVertexLocation + v)); + + for (uint32_t iElement = 0; iElement < pDXElementLayout->cElementDesc; ++iElement) + { + D3D11_INPUT_ELEMENT_DESC *pElement = &pDXElementLayout->aElementDesc[iElement]; + if (pElement->InputSlot == iSlot) + dxDbgLogVertexElement(pElement->Format, pu8VertexData + pElement->AlignedByteOffset); + } + + Log8((" }\n")); + + if (pBufferPipeline->stride == 0) + break; + + pu8VertexData += pBufferPipeline->stride; + } + + vmsvga3dBackSurfaceUnmap(pThisCC, &image, &map, /* fWritten = */ false); + } + } +} + + +static void dxDbgDumpIndexedVertexData(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCount, uint32_t startIndexLocation, int32_t baseVertexLocation) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + SVGA3dSurfaceImageId image; + + DXBOUNDINDEXBUFFER *pIB = &pBackend->resources.inputAssembly.indexBuffer; + uint32_t const sidIB = pDXContext->svgaDXContext.inputAssembly.indexBufferSid; + if (sidIB == SVGA3D_INVALID_ID) + { + Assert(pIB->pBuffer == 0); + return; + } + + Assert(pIB->pBuffer); + UINT const BytesPerIndex = pIB->indexBufferFormat == DXGI_FORMAT_R16_UINT ? 2 : 4; + + void *pvIndexBuffer; + uint32_t cbIndexBuffer; + int rc = dxReadBuffer(pDXDevice, pIB->pBuffer, pIB->indexBufferOffset + startIndexLocation * BytesPerIndex, indexCount * BytesPerIndex, &pvIndexBuffer, &cbIndexBuffer); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + uint8_t const *pu8IndexData = (uint8_t *)pvIndexBuffer; + + for (uint32_t iSlot = 0; iSlot < SVGA3D_DX_MAX_VERTEXBUFFERS; ++iSlot) + { + DXBOUNDVERTEXBUFFER *pVB = &pBackend->resources.inputAssembly.vertexBuffers[iSlot]; + uint32_t const sidVB = pDXContext->svgaDXContext.inputAssembly.vertexBuffers[iSlot].bufferId; + if (sidVB == SVGA3D_INVALID_ID) + { + Assert(pVB->pBuffer == 0); + continue; + } + + Assert(pVB->pBuffer); + + image.sid = sidVB; + image.face = 0; + image.mipmap = 0; + + VMSVGA3D_MAPPED_SURFACE mapVB; + rc = vmsvga3dBackSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &mapVB); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + uint8_t const *pu8VertexData = (uint8_t *)mapVB.pvData; + pu8VertexData += pVB->offset; + pu8VertexData += baseVertexLocation * pVB->stride; + + SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; + DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; + Assert(pDXElementLayout->cElementDesc > 0); + + Log8(("Vertex buffer dump: sid = %u, indexCount %u, startIndexLocation %d, baseVertexLocation %d, offset = %d, stride = %d:\n", + sidVB, indexCount, startIndexLocation, baseVertexLocation, pVB->offset, pVB->stride)); + + for (uint32_t i = 0; i < indexCount; ++i) + { + uint32_t Index; + if (BytesPerIndex == 2) + Index = ((uint16_t *)pu8IndexData)[i]; + else + Index = ((uint32_t *)pu8IndexData)[i]; + + Log8(("slot[%u] v%u { ", iSlot, Index)); + + for (uint32_t iElement = 0; iElement < pDXElementLayout->cElementDesc; ++iElement) + { + D3D11_INPUT_ELEMENT_DESC *pElement = &pDXElementLayout->aElementDesc[iElement]; + if (pElement->InputSlotClass != D3D11_INPUT_PER_VERTEX_DATA) + continue; + + if (pElement->InputSlot == iSlot) + { + uint8_t const *pu8Vertex = pu8VertexData + Index * pVB->stride; + dxDbgLogVertexElement(pElement->Format, pu8Vertex + pElement->AlignedByteOffset); + } + } + + Log8((" }\n")); + + if (pVB->stride == 0) + break; + } + + vmsvga3dBackSurfaceUnmap(pThisCC, &image, &mapVB, /* fWritten = */ false); + } + } + + RTMemFree(pvIndexBuffer); + } +} + + +static void dxDbgDumpInstanceData(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t instanceCount, uint32_t startInstanceLocation) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + SVGA3dSurfaceImageId image; + + /* + * Dump per-instance data. + */ + for (uint32_t iInstance = 0; iInstance < instanceCount; ++iInstance) + { + for (uint32_t iSlot = 0; iSlot < SVGA3D_DX_MAX_VERTEXBUFFERS; ++iSlot) + { + DXBOUNDVERTEXBUFFER *pVB = &pBackend->resources.inputAssembly.vertexBuffers[iSlot]; + uint32_t const sidVB = pDXContext->svgaDXContext.inputAssembly.vertexBuffers[iSlot].bufferId; + if (sidVB == SVGA3D_INVALID_ID) + { + Assert(pVB->pBuffer == 0); + continue; + } + + Assert(pVB->pBuffer); + + image.sid = sidVB; + image.face = 0; + image.mipmap = 0; + + VMSVGA3D_MAPPED_SURFACE mapVB; + int rc = vmsvga3dBackSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &mapVB); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + uint8_t const *pu8VertexData = (uint8_t *)mapVB.pvData; + pu8VertexData += pVB->offset; + pu8VertexData += startInstanceLocation * pVB->stride; + + SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; + DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; + Assert(pDXElementLayout->cElementDesc > 0); + + Log8(("Instance data dump: sid = %u, iInstance %u, startInstanceLocation %d, offset = %d, stride = %d:\n", + sidVB, iInstance, startInstanceLocation, pVB->offset, pVB->stride)); + + Log8(("slot[%u] i%u { ", iSlot, iInstance)); + for (uint32_t iElement = 0; iElement < pDXElementLayout->cElementDesc; ++iElement) + { + D3D11_INPUT_ELEMENT_DESC *pElement = &pDXElementLayout->aElementDesc[iElement]; + if (pElement->InputSlotClass != D3D11_INPUT_PER_INSTANCE_DATA) + continue; + + if (pElement->InputSlot == iSlot) + { + uint8_t const *pu8Vertex = pu8VertexData + iInstance * pVB->stride; + dxDbgLogVertexElement(pElement->Format, pu8Vertex + pElement->AlignedByteOffset); + } + } + Log8((" }\n")); + + vmsvga3dBackSurfaceUnmap(pThisCC, &image, &mapVB, /* fWritten = */ false); + } + } + } +} + +static void dxDbgDumpVertices_Draw(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCount, uint32_t startVertexLocation) +{ + dxDbgDumpVertexData(pThisCC, pDXContext, vertexCount, startVertexLocation); +} + + +static void dxDbgDumpVertices_DrawIndexed(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCount, uint32_t startIndexLocation, int32_t baseVertexLocation) +{ + dxDbgDumpIndexedVertexData(pThisCC, pDXContext, indexCount, startIndexLocation, baseVertexLocation); +} + + +static void dxDbgDumpVertices_DrawInstanced(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, + uint32_t vertexCountPerInstance, uint32_t instanceCount, + uint32_t startVertexLocation, uint32_t startInstanceLocation) +{ + dxDbgDumpVertexData(pThisCC, pDXContext, vertexCountPerInstance, startVertexLocation); + dxDbgDumpInstanceData(pThisCC, pDXContext, instanceCount, startInstanceLocation); +} + + +static void dxDbgDumpVertices_DrawIndexedInstanced(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, + uint32_t indexCountPerInstance, uint32_t instanceCount, + uint32_t startIndexLocation, int32_t baseVertexLocation, + uint32_t startInstanceLocation) +{ + dxDbgDumpIndexedVertexData(pThisCC, pDXContext, indexCountPerInstance, startIndexLocation, baseVertexLocation); + dxDbgDumpInstanceData(pThisCC, pDXContext, instanceCount, startInstanceLocation); +} +#endif + + +static void dxSetupPipeline(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + /* Make sure that any draw operations on shader resource views have finished. */ + AssertCompile(RT_ELEMENTS(pDXContext->svgaDXContext.shaderState) == SVGA3D_NUM_SHADERTYPE); + AssertCompile(RT_ELEMENTS(pDXContext->svgaDXContext.shaderState[0].shaderResources) == SVGA3D_DX_MAX_SRVIEWS); + + int rc; + + /* Unbind render target views because they mught be (re-)used as shader resource views. */ + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + pDXDevice->pImmediateContext->OMSetRenderTargetsAndUnorderedAccessViews(0, NULL, NULL, 0, 0, NULL, NULL); + for (unsigned i = 0; i < SVGA3D_DX11_1_MAX_UAVIEWS; ++i) + { + ID3D11UnorderedAccessView *pNullUA = 0; + pDXDevice->pImmediateContext->CSSetUnorderedAccessViews(i, 1, &pNullUA, NULL); + } + + dxSetConstantBuffers(pThisCC, pDXContext); + dxSetVertexBuffers(pThisCC, pDXContext); + dxSetIndexBuffer(pThisCC, pDXContext); + + /* + * Shader resources + */ + + /* Make sure that the shader resource views exist. */ + for (uint32_t idxShaderState = 0; idxShaderState < SVGA3D_NUM_SHADERTYPE; ++idxShaderState) + { + for (uint32_t idxSR = 0; idxSR < SVGA3D_DX_MAX_SRVIEWS; ++idxSR) + { + SVGA3dShaderResourceViewId const shaderResourceViewId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderResources[idxSR]; + if (shaderResourceViewId != SVGA3D_INVALID_ID) + { + ASSERT_GUEST_RETURN_VOID(shaderResourceViewId < pDXContext->pBackendDXContext->cShaderResourceView); + + SVGACOTableDXSRViewEntry const *pSRViewEntry = dxGetShaderResourceViewEntry(pDXContext, shaderResourceViewId); + AssertContinue(pSRViewEntry != NULL); + + uint32_t const sid = pSRViewEntry->sid; + + PVMSVGA3DSURFACE pSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + if (RT_FAILURE(rc)) + { + AssertMsgFailed(("sid = %u, rc = %Rrc\n", sid, rc)); + continue; + } + + /* The guest might have invalidated the surface in which case pSurface->pBackendSurface is NULL. */ + /** @todo This is not needed for "single DX device" mode. */ + if (pSurface->pBackendSurface) + { + /* Wait for the surface to finish drawing. */ + dxSurfaceWait(pThisCC->svga.p3dState, pSurface, pDXContext->cid); + } + + /* If a view has not been created yet, do it now. */ + if (!pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId].u.pView) + { +//DEBUG_BREAKPOINT_TEST(); + LogFunc(("Re-creating SRV: sid=%u srvid = %u\n", sid, shaderResourceViewId)); + rc = dxDefineShaderResourceView(pThisCC, pDXContext, shaderResourceViewId, pSRViewEntry); + AssertContinue(RT_SUCCESS(rc)); + } + + LogFunc(("srv[%d][%d] sid = %u, srvid = %u, format = %s(%d)\n", idxShaderState, idxSR, sid, shaderResourceViewId, vmsvgaLookupEnum((int)pSRViewEntry->format, &g_SVGA3dSurfaceFormat2String), pSRViewEntry->format)); + +#ifdef DUMP_BITMAPS + SVGA3dSurfaceImageId image; + image.sid = sid; + image.face = 0; + image.mipmap = 0; + VMSVGA3D_MAPPED_SURFACE map; + int rc2 = vmsvga3dSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map); + if (RT_SUCCESS(rc2)) + { + vmsvga3dMapWriteBmpFile(&map, "sr-"); + vmsvga3dSurfaceUnmap(pThisCC, &image, &map, /* fWritten = */ false); + } + else + Log(("Map failed %Rrc\n", rc)); +#endif + } + } + + /* Set shader resources. */ + rc = dxSetShaderResources(pThisCC, pDXContext, (SVGA3dShaderType)(idxShaderState + SVGA3D_SHADERTYPE_MIN)); + AssertRC(rc); + } + + /* + * Compute shader unordered access views + */ + + for (uint32_t idxUA = 0; idxUA < SVGA3D_DX11_1_MAX_UAVIEWS; ++idxUA) + { + SVGA3dUAViewId const uaViewId = pDXContext->svgaDXContext.csuaViewIds[idxUA]; + if (uaViewId != SVGA3D_INVALID_ID) + { +//DEBUG_BREAKPOINT_TEST(); + ASSERT_GUEST_RETURN_VOID(uaViewId < pDXContext->pBackendDXContext->cUnorderedAccessView); + + SVGACOTableDXUAViewEntry const *pUAViewEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); + AssertContinue(pUAViewEntry != NULL); + + uint32_t const sid = pUAViewEntry->sid; + + PVMSVGA3DSURFACE pSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + AssertRCReturnVoid(rc); + + /* The guest might have invalidated the surface in which case pSurface->pBackendSurface is NULL. */ + /** @todo This is not needed for "single DX device" mode. */ + if (pSurface->pBackendSurface) + { + /* Wait for the surface to finish drawing. */ + dxSurfaceWait(pThisCC->svga.p3dState, pSurface, pDXContext->cid); + } + + /* If a view has not been created yet, do it now. */ + if (!pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId].u.pView) + { + LogFunc(("Re-creating UAV: sid=%u uaid = %u\n", sid, uaViewId)); + rc = dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pUAViewEntry); + AssertContinue(RT_SUCCESS(rc)); + } + + LogFunc(("csuav[%d] sid = %u, uaid = %u\n", idxUA, sid, uaViewId)); + } + } + + /* Set views. */ + rc = dxSetCSUnorderedAccessViews(pThisCC, pDXContext); + AssertRC(rc); + + /* + * Render targets and unordered access views. + */ + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturnVoid(pDevice->pDevice); + + /* Make sure that the render target views exist. Similar to SRVs. */ + if (pDXContext->svgaDXContext.renderState.depthStencilViewId != SVGA3D_INVALID_ID) + { + uint32_t const viewId = pDXContext->svgaDXContext.renderState.depthStencilViewId; + + ASSERT_GUEST_RETURN_VOID(viewId < pDXContext->pBackendDXContext->cDepthStencilView); + + SVGACOTableDXDSViewEntry const *pDSViewEntry = dxGetDepthStencilViewEntry(pDXContext, viewId); + AssertReturnVoid(pDSViewEntry != NULL); + + PVMSVGA3DSURFACE pSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pDSViewEntry->sid, &pSurface); + AssertRCReturnVoid(rc); + + /* If a view has not been created yet, do it now. */ + if (!pDXContext->pBackendDXContext->paDepthStencilView[viewId].u.pView) + { +//DEBUG_BREAKPOINT_TEST(); + LogFunc(("Re-creating DSV: sid=%u dsvid = %u\n", pDSViewEntry->sid, viewId)); + rc = dxDefineDepthStencilView(pThisCC, pDXContext, viewId, pDSViewEntry); + AssertReturnVoid(RT_SUCCESS(rc)); + } + + LogFunc(("dsv sid = %u, dsvid = %u\n", pDSViewEntry->sid, viewId)); + } + + for (uint32_t i = 0; i < SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS; ++i) + { + if (pDXContext->svgaDXContext.renderState.renderTargetViewIds[i] != SVGA3D_INVALID_ID) + { + uint32_t const viewId = pDXContext->svgaDXContext.renderState.renderTargetViewIds[i]; + + ASSERT_GUEST_RETURN_VOID(viewId < pDXContext->pBackendDXContext->cRenderTargetView); + + SVGACOTableDXRTViewEntry const *pRTViewEntry = dxGetRenderTargetViewEntry(pDXContext, viewId); + AssertReturnVoid(pRTViewEntry != NULL); + + PVMSVGA3DSURFACE pSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pRTViewEntry->sid, &pSurface); + AssertRCReturnVoid(rc); + + /* If a view has not been created yet, do it now. */ + if (!pDXContext->pBackendDXContext->paRenderTargetView[viewId].u.pView) + { +//DEBUG_BREAKPOINT_TEST(); + LogFunc(("Re-creating RTV: sid=%u rtvid = %u\n", pRTViewEntry->sid, viewId)); + rc = dxDefineRenderTargetView(pThisCC, pDXContext, viewId, pRTViewEntry); + AssertReturnVoid(RT_SUCCESS(rc)); + } + + LogFunc(("rtv sid = %u, rtvid = %u, format = %s(%d)\n", pRTViewEntry->sid, viewId, vmsvgaLookupEnum((int)pRTViewEntry->format, &g_SVGA3dSurfaceFormat2String), pRTViewEntry->format)); + } + } + + for (uint32_t idxUA = 0; idxUA < SVGA3D_DX11_1_MAX_UAVIEWS; ++idxUA) + { + SVGA3dUAViewId const uaViewId = pDXContext->svgaDXContext.uaViewIds[idxUA]; + if (uaViewId != SVGA3D_INVALID_ID) + { +//DEBUG_BREAKPOINT_TEST(); + ASSERT_GUEST_RETURN_VOID(uaViewId < pDXContext->pBackendDXContext->cUnorderedAccessView); + + SVGACOTableDXUAViewEntry const *pUAViewEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); + AssertContinue(pUAViewEntry != NULL); + + uint32_t const sid = pUAViewEntry->sid; + + PVMSVGA3DSURFACE pSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + AssertRCReturnVoid(rc); + + /* The guest might have invalidated the surface in which case pSurface->pBackendSurface is NULL. */ + /** @todo This is not needed for "single DX device" mode. */ + if (pSurface->pBackendSurface) + { + /* Wait for the surface to finish drawing. */ + dxSurfaceWait(pThisCC->svga.p3dState, pSurface, pDXContext->cid); + } + + /* If a view has not been created yet, do it now. */ + if (!pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId].u.pView) + { + LogFunc(("Re-creating UAV: sid=%u uaid = %u\n", sid, uaViewId)); + rc = dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pUAViewEntry); + AssertContinue(RT_SUCCESS(rc)); + } + + LogFunc(("uav[%d] sid = %u, uaid = %u\n", idxUA, sid, uaViewId)); + } + } + + /* Set render targets. */ + rc = dxSetRenderTargets(pThisCC, pDXContext); + AssertRC(rc); + + /* + * Shaders + */ + + for (uint32_t idxShaderState = 0; idxShaderState < SVGA3D_NUM_SHADERTYPE; ++idxShaderState) + { + DXSHADER *pDXShader; + SVGA3dShaderType const shaderType = (SVGA3dShaderType)(idxShaderState + SVGA3D_SHADERTYPE_MIN); + SVGA3dShaderId const shaderId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderId; + + if (shaderId != SVGA3D_INVALID_ID) + { + pDXShader = &pDXContext->pBackendDXContext->paShader[shaderId]; + if (pDXShader->pShader == NULL) + { + /* Create a new shader. */ + + /* Apply resource types to a pixel shader. */ + if (shaderType == SVGA3D_SHADERTYPE_PS) /* Others too? */ + { + VGPU10_RESOURCE_DIMENSION aResourceDimension[SVGA3D_DX_MAX_SRVIEWS]; + RT_ZERO(aResourceDimension); + VGPU10_RESOURCE_RETURN_TYPE aResourceReturnType[SVGA3D_DX_MAX_SRVIEWS]; + RT_ZERO(aResourceReturnType); + uint32_t cResources = 0; + + for (uint32_t idxSR = 0; idxSR < SVGA3D_DX_MAX_SRVIEWS; ++idxSR) + { + SVGA3dShaderResourceViewId const shaderResourceViewId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderResources[idxSR]; + if (shaderResourceViewId != SVGA3D_INVALID_ID) + { + SVGACOTableDXSRViewEntry const *pSRViewEntry = dxGetShaderResourceViewEntry(pDXContext, shaderResourceViewId); + AssertContinue(pSRViewEntry != NULL); + + PVMSVGA3DSURFACE pSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pSRViewEntry->sid, &pSurface); + AssertRCReturnVoid(rc); + + aResourceReturnType[idxSR] = DXShaderResourceReturnTypeFromFormat(pSRViewEntry->format); + + switch (pSRViewEntry->resourceDimension) + { + case SVGA3D_RESOURCE_BUFFEREX: + case SVGA3D_RESOURCE_BUFFER: + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_BUFFER; + break; + case SVGA3D_RESOURCE_TEXTURE1D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE1D; + else + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE1DARRAY; + break; + case SVGA3D_RESOURCE_TEXTURE2D: + if (pSurface->surfaceDesc.numArrayElements <= 1) + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE2D; + else + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE2DARRAY; + break; + case SVGA3D_RESOURCE_TEXTURE3D: + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE3D; + break; + case SVGA3D_RESOURCE_TEXTURECUBE: + if (pSurface->surfaceDesc.numArrayElements <= 6) + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURECUBE; + else + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURECUBEARRAY; + break; + default: + ASSERT_GUEST_FAILED(); + aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE2D; + } + + cResources = idxSR + 1; + + /* Update componentType of the pixel shader output signature to correspond to the bound resources. */ + if (idxSR < pDXShader->shaderInfo.cOutputSignature) + { + SVGA3dDXSignatureEntry *pSignatureEntry = &pDXShader->shaderInfo.aOutputSignature[idxSR]; + pSignatureEntry->componentType = DXShaderComponentTypeFromFormat(pSRViewEntry->format); + } + } + } + + rc = DXShaderUpdateResources(&pDXShader->shaderInfo, aResourceDimension, aResourceReturnType, cResources); + AssertRC(rc); /* Ignore rc because the shader will most likely work anyway. */ + } + + if (shaderType == SVGA3D_SHADERTYPE_VS) + { + /* Update componentType of the vertex shader input signature to correspond to the input declaration. */ + vboxDXUpdateVSInputSignature(pDXContext, pDXShader); + } + + vboxDXMatchShaderSignatures(pThisCC, pDXContext, pDXShader); + + rc = DXShaderCreateDXBC(&pDXShader->shaderInfo, &pDXShader->pvDXBC, &pDXShader->cbDXBC); + if (RT_SUCCESS(rc)) + { +#ifdef LOG_ENABLED + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + if (pBackend->pfnD3DDisassemble && LogIs6Enabled()) + { + ID3D10Blob *pBlob = 0; + HRESULT hr2 = pBackend->pfnD3DDisassemble(pDXShader->pvDXBC, pDXShader->cbDXBC, 0, NULL, &pBlob); + if (SUCCEEDED(hr2) && pBlob && pBlob->GetBufferSize()) + Log6(("%s\n", pBlob->GetBufferPointer())); + else + AssertFailed(); + D3D_RELEASE(pBlob); + } + LogFunc(("Shader: set cid=%u shid=%u type=%d, GuestSignatures %d\n", pDXContext->cid, shaderId, pDXShader->enmShaderType, pDXShader->shaderInfo.fGuestSignatures)); +#endif + + HRESULT hr = dxShaderCreate(pThisCC, pDXContext, pDXShader); + if (FAILED(hr)) + rc = VERR_INVALID_STATE; + } + } + + LogFunc(("Shader: cid=%u shid=%u type=%d, GuestSignatures %d, %Rrc\n", pDXContext->cid, shaderId, pDXShader->enmShaderType, pDXShader->shaderInfo.fGuestSignatures, rc)); + } + else + pDXShader = NULL; + + if (RT_SUCCESS(rc)) + dxShaderSet(pThisCC, pDXContext, shaderType, pDXShader); + + AssertRC(rc); + } + + /* + * InputLayout + */ + SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; + ID3D11InputLayout *pInputLayout = NULL; + if (elementLayoutId != SVGA3D_INVALID_ID) + { + DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; + if (!pDXElementLayout->pElementLayout) + { + uint32_t const idxShaderState = SVGA3D_SHADERTYPE_VS - SVGA3D_SHADERTYPE_MIN; + uint32_t const shid = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderId; + if (shid < pDXContext->pBackendDXContext->cShader) + { + DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[shid]; + if (pDXShader->pvDXBC) + dxCreateInputLayout(pThisCC, pDXContext, elementLayoutId, pDXShader); + else + LogRelMax(16, ("VMSVGA: DX shader bytecode is not available in DXSetInputLayout: shid = %u\n", shid)); + } + else + LogRelMax(16, ("VMSVGA: DX shader is not set in DXSetInputLayout: shid = 0x%x\n", shid)); + } + + pInputLayout = pDXElementLayout->pElementLayout; + + LogFunc(("Input layout id %u\n", elementLayoutId)); + } + + pDevice->pImmediateContext->IASetInputLayout(pInputLayout); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDraw(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCount, uint32_t startVertexLocation) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + dxSetupPipeline(pThisCC, pDXContext); + +#ifdef LOG_ENABLED + if (LogIs8Enabled()) + dxDbgDumpVertices_Draw(pThisCC, pDXContext, vertexCount, startVertexLocation); +#endif + + if (pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN) + pDevice->pImmediateContext->Draw(vertexCount, startVertexLocation); + else + { + /* + * Emulate SVGA3D_PRIMITIVE_TRIANGLEFAN using an indexed draw of a triangle list. + */ + + /* Make sure that 16 bit indices are enough. */ + if (vertexCount > 65535) + { + LogRelMax(1, ("VMSVGA: ignore Draw(TRIANGLEFAN, %u)\n", vertexCount)); + return VERR_NOT_SUPPORTED; + } + + /* Generate indices. */ + UINT const IndexCount = 3 * (vertexCount - 2); /* 3_per_triangle * num_triangles */ + UINT const cbAlloc = IndexCount * sizeof(USHORT); + USHORT *paIndices = (USHORT *)RTMemAlloc(cbAlloc); + AssertReturn(paIndices, VERR_NO_MEMORY); + USHORT iVertex = 1; + for (UINT i = 0; i < IndexCount; i+= 3) + { + paIndices[i] = 0; + paIndices[i + 1] = iVertex; + ++iVertex; + paIndices[i + 2] = iVertex; + } + + D3D11_SUBRESOURCE_DATA InitData; + InitData.pSysMem = paIndices; + InitData.SysMemPitch = cbAlloc; + InitData.SysMemSlicePitch = cbAlloc; + + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = cbAlloc; + bd.Usage = D3D11_USAGE_IMMUTABLE; + bd.BindFlags = D3D11_BIND_INDEX_BUFFER; + //bd.CPUAccessFlags = 0; + //bd.MiscFlags = 0; + //bd.StructureByteStride = 0; + + ID3D11Buffer *pIndexBuffer = 0; + HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, &InitData, &pIndexBuffer); + Assert(SUCCEEDED(hr));RT_NOREF(hr); + + /* Save the current index buffer. */ + ID3D11Buffer *pSavedIndexBuffer = 0; + DXGI_FORMAT SavedFormat = DXGI_FORMAT_UNKNOWN; + UINT SavedOffset = 0; + pDevice->pImmediateContext->IAGetIndexBuffer(&pSavedIndexBuffer, &SavedFormat, &SavedOffset); + + /* Set up the device state. */ + pDevice->pImmediateContext->IASetIndexBuffer(pIndexBuffer, DXGI_FORMAT_R16_UINT, 0); + pDevice->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + UINT const StartIndexLocation = 0; + INT const BaseVertexLocation = startVertexLocation; + pDevice->pImmediateContext->DrawIndexed(IndexCount, StartIndexLocation, BaseVertexLocation); + + /* Restore the device state. */ + pDevice->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + pDevice->pImmediateContext->IASetIndexBuffer(pSavedIndexBuffer, SavedFormat, SavedOffset); + D3D_RELEASE(pSavedIndexBuffer); + + /* Cleanup. */ + D3D_RELEASE(pIndexBuffer); + RTMemFree(paIndices); + } + + /* Note which surfaces are being drawn. */ + dxTrackRenderTargets(pThisCC, pDXContext); + +#ifdef DX_FLUSH_AFTER_DRAW + dxDeviceFlush(pDevice); +#endif + + return VINF_SUCCESS; +} + +static int dxReadBuffer(DXDEVICE *pDevice, ID3D11Buffer *pBuffer, UINT Offset, UINT Bytes, void **ppvData, uint32_t *pcbData) +{ + D3D11_BUFFER_DESC desc; + RT_ZERO(desc); + pBuffer->GetDesc(&desc); + + AssertReturn( Offset < desc.ByteWidth + && Bytes <= desc.ByteWidth - Offset, VERR_INVALID_STATE); + + void *pvData = RTMemAlloc(Bytes); + if (!pvData) + return VERR_NO_MEMORY; + + *ppvData = pvData; + *pcbData = Bytes; + +#ifdef DX_COMMON_STAGING_BUFFER + int rc = dxStagingBufferRealloc(pDevice, Bytes); + if (RT_SUCCESS(rc)) + { + /* Copy 'Bytes' bytes starting at 'Offset' from the buffer to the start of staging buffer. */ + ID3D11Resource *pDstResource = pDevice->pStagingBuffer; + UINT DstSubresource = 0; + UINT DstX = 0; + UINT DstY = 0; + UINT DstZ = 0; + ID3D11Resource *pSrcResource = pBuffer; + UINT SrcSubresource = 0; + D3D11_BOX SrcBox; + SrcBox.left = Offset; + SrcBox.top = 0; + SrcBox.front = 0; + SrcBox.right = Offset + Bytes; + SrcBox.bottom = 1; + SrcBox.back = 1; + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + UINT const Subresource = 0; /* Buffers have only one subresource. */ + HRESULT hr = pDevice->pImmediateContext->Map(pDevice->pStagingBuffer, Subresource, + D3D11_MAP_READ, /* MapFlags = */ 0, &mappedResource); + if (SUCCEEDED(hr)) + { + memcpy(pvData, mappedResource.pData, Bytes); + + /* Unmap the staging buffer. */ + pDevice->pImmediateContext->Unmap(pDevice->pStagingBuffer, Subresource); + } + else + AssertFailedStmt(rc = VERR_NOT_SUPPORTED); + + } +#else + uint32_t const cbAlloc = Bytes; + + D3D11_SUBRESOURCE_DATA *pInitialData = NULL; + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = Bytes; + bd.Usage = D3D11_USAGE_STAGING; + //bd.BindFlags = 0; /* No bind flags are allowed for staging resources. */ + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; + + int rc = VINF_SUCCESS; + ID3D11Buffer *pStagingBuffer; + HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pStagingBuffer); + if (SUCCEEDED(hr)) + { + /* Copy from the buffer to the staging buffer. */ + ID3D11Resource *pDstResource = pStagingBuffer; + UINT DstSubresource = 0; + UINT DstX = 0; + UINT DstY = 0; + UINT DstZ = 0; + ID3D11Resource *pSrcResource = pBuffer; + UINT SrcSubresource = 0; + D3D11_BOX SrcBox; + SrcBox.left = Offset; + SrcBox.top = 0; + SrcBox.front = 0; + SrcBox.right = Offset + Bytes; + SrcBox.bottom = 1; + SrcBox.back = 1; + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + UINT const Subresource = 0; /* Buffers have only one subresource. */ + hr = pDevice->pImmediateContext->Map(pStagingBuffer, Subresource, + D3D11_MAP_READ, /* MapFlags = */ 0, &mappedResource); + if (SUCCEEDED(hr)) + { + memcpy(pvData, mappedResource.pData, Bytes); + + /* Unmap the staging buffer. */ + pDevice->pImmediateContext->Unmap(pStagingBuffer, Subresource); + } + else + AssertFailedStmt(rc = VERR_NOT_SUPPORTED); + + D3D_RELEASE(pStagingBuffer); + } + else + { + rc = VERR_NO_MEMORY; + } +#endif + + if (RT_FAILURE(rc)) + { + RTMemFree(*ppvData); + *ppvData = NULL; + *pcbData = 0; + } + + return rc; +} + + +static int dxDrawIndexedTriangleFan(DXDEVICE *pDevice, uint32_t IndexCountTF, uint32_t StartIndexLocationTF, int32_t BaseVertexLocationTF) +{ + /* + * Emulate an indexed SVGA3D_PRIMITIVE_TRIANGLEFAN using an indexed draw of triangle list. + */ + + /* Make sure that 16 bit indices are enough. */ + if (IndexCountTF > 65535) + { + LogRelMax(1, ("VMSVGA: ignore DrawIndexed(TRIANGLEFAN, %u)\n", IndexCountTF)); + return VERR_NOT_SUPPORTED; + } + + /* Save the current index buffer. */ + ID3D11Buffer *pSavedIndexBuffer = 0; + DXGI_FORMAT SavedFormat = DXGI_FORMAT_UNKNOWN; + UINT SavedOffset = 0; + pDevice->pImmediateContext->IAGetIndexBuffer(&pSavedIndexBuffer, &SavedFormat, &SavedOffset); + + AssertReturn( SavedFormat == DXGI_FORMAT_R16_UINT + || SavedFormat == DXGI_FORMAT_R32_UINT, VERR_NOT_SUPPORTED); + + /* How many bytes are used by triangle fan indices. */ + UINT const BytesPerIndexTF = SavedFormat == DXGI_FORMAT_R16_UINT ? 2 : 4; + UINT const BytesTF = BytesPerIndexTF * IndexCountTF; + + /* Read the current index buffer content to obtain indices. */ + void *pvDataTF; + uint32_t cbDataTF; + int rc = dxReadBuffer(pDevice, pSavedIndexBuffer, StartIndexLocationTF, BytesTF, &pvDataTF, &cbDataTF); + AssertRCReturn(rc, rc); + AssertReturnStmt(cbDataTF >= BytesPerIndexTF, RTMemFree(pvDataTF), VERR_INVALID_STATE); + + /* Generate indices for triangle list. */ + UINT const IndexCount = 3 * (IndexCountTF - 2); /* 3_per_triangle * num_triangles */ + UINT const cbAlloc = IndexCount * sizeof(USHORT); + USHORT *paIndices = (USHORT *)RTMemAlloc(cbAlloc); + AssertReturnStmt(paIndices, RTMemFree(pvDataTF), VERR_NO_MEMORY); + + USHORT iVertex = 1; + if (BytesPerIndexTF == 2) + { + USHORT *paIndicesTF = (USHORT *)pvDataTF; + for (UINT i = 0; i < IndexCount; i+= 3) + { + paIndices[i] = paIndicesTF[0]; + AssertBreakStmt(iVertex < IndexCountTF, rc = VERR_INVALID_STATE); + paIndices[i + 1] = paIndicesTF[iVertex]; + ++iVertex; + AssertBreakStmt(iVertex < IndexCountTF, rc = VERR_INVALID_STATE); + paIndices[i + 2] = paIndicesTF[iVertex]; + } + } + else + { + UINT *paIndicesTF = (UINT *)pvDataTF; + for (UINT i = 0; i < IndexCount; i+= 3) + { + paIndices[i] = paIndicesTF[0]; + AssertBreakStmt(iVertex < IndexCountTF, rc = VERR_INVALID_STATE); + paIndices[i + 1] = paIndicesTF[iVertex]; + ++iVertex; + AssertBreakStmt(iVertex < IndexCountTF, rc = VERR_INVALID_STATE); + paIndices[i + 2] = paIndicesTF[iVertex]; + } + } + + D3D11_SUBRESOURCE_DATA InitData; + InitData.pSysMem = paIndices; + InitData.SysMemPitch = cbAlloc; + InitData.SysMemSlicePitch = cbAlloc; + + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = cbAlloc; + bd.Usage = D3D11_USAGE_IMMUTABLE; + bd.BindFlags = D3D11_BIND_INDEX_BUFFER; + //bd.CPUAccessFlags = 0; + //bd.MiscFlags = 0; + //bd.StructureByteStride = 0; + + ID3D11Buffer *pIndexBuffer = 0; + HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, &InitData, &pIndexBuffer); + Assert(SUCCEEDED(hr));RT_NOREF(hr); + + /* Set up the device state. */ + pDevice->pImmediateContext->IASetIndexBuffer(pIndexBuffer, DXGI_FORMAT_R16_UINT, 0); + pDevice->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + UINT const StartIndexLocation = 0; + INT const BaseVertexLocation = BaseVertexLocationTF; + pDevice->pImmediateContext->DrawIndexed(IndexCount, StartIndexLocation, BaseVertexLocation); + + /* Restore the device state. */ + pDevice->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + pDevice->pImmediateContext->IASetIndexBuffer(pSavedIndexBuffer, SavedFormat, SavedOffset); + D3D_RELEASE(pSavedIndexBuffer); + + /* Cleanup. */ + D3D_RELEASE(pIndexBuffer); + RTMemFree(paIndices); + RTMemFree(pvDataTF); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDrawIndexed(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCount, uint32_t startIndexLocation, int32_t baseVertexLocation) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + dxSetupPipeline(pThisCC, pDXContext); + +#ifdef LOG_ENABLED + if (LogIs8Enabled()) + dxDbgDumpVertices_DrawIndexed(pThisCC, pDXContext, indexCount, startIndexLocation, baseVertexLocation); +#endif + + if (pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN) + pDevice->pImmediateContext->DrawIndexed(indexCount, startIndexLocation, baseVertexLocation); + else + { + dxDrawIndexedTriangleFan(pDevice, indexCount, startIndexLocation, baseVertexLocation); + } + + /* Note which surfaces are being drawn. */ + dxTrackRenderTargets(pThisCC, pDXContext); + +#ifdef DX_FLUSH_AFTER_DRAW + dxDeviceFlush(pDevice); +#endif + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDrawInstanced(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, + uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + dxSetupPipeline(pThisCC, pDXContext); + +#ifdef LOG_ENABLED + if (LogIs8Enabled()) + dxDbgDumpVertices_DrawInstanced(pThisCC, pDXContext, vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation); +#endif + + Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); + + pDevice->pImmediateContext->DrawInstanced(vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation); + + /* Note which surfaces are being drawn. */ + dxTrackRenderTargets(pThisCC, pDXContext); + +#ifdef DX_FLUSH_AFTER_DRAW + dxDeviceFlush(pDevice); +#endif + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDrawIndexedInstanced(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, + uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndexLocation, int32_t baseVertexLocation, uint32_t startInstanceLocation) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + dxSetupPipeline(pThisCC, pDXContext); + +#ifdef LOG_ENABLED + if (LogIs8Enabled()) + dxDbgDumpVertices_DrawIndexedInstanced(pThisCC, pDXContext, indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); +#endif + + Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); + + pDevice->pImmediateContext->DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); + + /* Note which surfaces are being drawn. */ + dxTrackRenderTargets(pThisCC, pDXContext); + +#ifdef DX_FLUSH_AFTER_DRAW + dxDeviceFlush(pDevice); +#endif + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDrawAuto(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + dxSetupPipeline(pThisCC, pDXContext); + + Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); + + pDevice->pImmediateContext->DrawAuto(); + + /* Note which surfaces are being drawn. */ + dxTrackRenderTargets(pThisCC, pDXContext); + +#ifdef DX_FLUSH_AFTER_DRAW + dxDeviceFlush(pDevice); +#endif + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetInputLayout(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(elementLayoutId); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetVertexBuffers(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startBuffer, uint32_t cVertexBuffer, SVGA3dVertexBuffer const *paVertexBuffer) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + for (uint32_t i = 0; i < cVertexBuffer; ++i) + { + uint32_t const idxVertexBuffer = startBuffer + i; + + /* Get corresponding resource. Create the buffer if does not yet exist. */ + if (paVertexBuffer[i].sid != SVGA_ID_INVALID) + { + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, paVertexBuffer[i].sid, &pSurface); + AssertRCReturn(rc, rc); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the resource and initialize it with the current surface data. */ + rc = vmsvga3dBackSurfaceCreateBuffer(pThisCC, pDXContext, pSurface); + AssertRCReturn(rc, rc); + } + Assert(pSurface->pBackendSurface->u.pBuffer); + + DXBOUNDVERTEXBUFFER *pBoundBuffer = &pDXContext->pBackendDXContext->resources.inputAssembly.vertexBuffers[idxVertexBuffer]; + if ( pBoundBuffer->pBuffer != pSurface->pBackendSurface->u.pBuffer + || pBoundBuffer->stride != paVertexBuffer[i].stride + || pBoundBuffer->offset != paVertexBuffer[i].offset) + { + LogFunc(("vertex buffer: [%u]: sid = %u, offset %u, stride %u (%p -> %p)\n", + idxVertexBuffer, paVertexBuffer[i].sid, paVertexBuffer[i].offset, paVertexBuffer[i].stride, pBoundBuffer->pBuffer, pSurface->pBackendSurface->u.pBuffer)); + + if (pBoundBuffer->pBuffer != pSurface->pBackendSurface->u.pBuffer) + { + D3D_RELEASE(pBoundBuffer->pBuffer); + pBoundBuffer->pBuffer = pSurface->pBackendSurface->u.pBuffer; + pBoundBuffer->pBuffer->AddRef(); + } + pBoundBuffer->stride = paVertexBuffer[i].stride; + pBoundBuffer->offset = paVertexBuffer[i].offset; + } + } + else + { + DXBOUNDVERTEXBUFFER *pBoundBuffer = &pDXContext->pBackendDXContext->resources.inputAssembly.vertexBuffers[idxVertexBuffer]; + D3D_RELEASE(pBoundBuffer->pBuffer); + pBoundBuffer->stride = 0; + pBoundBuffer->offset = 0; + } + } + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetIndexBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId sid, SVGA3dSurfaceFormat format, uint32_t offset) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* Get corresponding resource. Create the buffer if does not yet exist. */ + if (sid != SVGA_ID_INVALID) + { + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + AssertRCReturn(rc, rc); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the resource and initialize it with the current surface data. */ + rc = vmsvga3dBackSurfaceCreateBuffer(pThisCC, pDXContext, pSurface); + AssertRCReturn(rc, rc); + } + + DXGI_FORMAT const enmDxgiFormat = vmsvgaDXSurfaceFormat2Dxgi(format); + AssertReturn(enmDxgiFormat == DXGI_FORMAT_R16_UINT || enmDxgiFormat == DXGI_FORMAT_R32_UINT, VERR_INVALID_PARAMETER); + + DXBOUNDINDEXBUFFER *pBoundBuffer = &pDXContext->pBackendDXContext->resources.inputAssembly.indexBuffer; + if ( pBoundBuffer->pBuffer != pSurface->pBackendSurface->u.pBuffer + || pBoundBuffer->indexBufferOffset != offset + || pBoundBuffer->indexBufferFormat != enmDxgiFormat) + { + LogFunc(("index_buffer: sid = %u, offset %u, (%p -> %p)\n", + sid, offset, pBoundBuffer->pBuffer, pSurface->pBackendSurface->u.pBuffer)); + + if (pBoundBuffer->pBuffer != pSurface->pBackendSurface->u.pBuffer) + { + D3D_RELEASE(pBoundBuffer->pBuffer); + pBoundBuffer->pBuffer = pSurface->pBackendSurface->u.pBuffer; + pBoundBuffer->pBuffer->AddRef(); + } + pBoundBuffer->indexBufferOffset = offset; + pBoundBuffer->indexBufferFormat = enmDxgiFormat; + } + } + else + { + DXBOUNDINDEXBUFFER *pBoundBuffer = &pDXContext->pBackendDXContext->resources.inputAssembly.indexBuffer; + D3D_RELEASE(pBoundBuffer->pBuffer); + pBoundBuffer->indexBufferOffset = 0; + pBoundBuffer->indexBufferFormat = DXGI_FORMAT_UNKNOWN; + } + + return VINF_SUCCESS; +} + +static D3D11_PRIMITIVE_TOPOLOGY dxTopology(SVGA3dPrimitiveType primitiveType) +{ + static D3D11_PRIMITIVE_TOPOLOGY const aD3D11PrimitiveTopology[SVGA3D_PRIMITIVE_MAX] = + { + D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED, + D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, + D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, + D3D11_PRIMITIVE_TOPOLOGY_LINELIST, + D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, + D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, /* SVGA3D_PRIMITIVE_TRIANGLEFAN: No FAN in D3D11. */ + D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ, + D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ, + D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ, + D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ, + D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST, + D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST, + }; + return aD3D11PrimitiveTopology[primitiveType]; +} + +static DECLCALLBACK(int) vmsvga3dBackDXSetTopology(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dPrimitiveType topology) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + D3D11_PRIMITIVE_TOPOLOGY const enmTopology = dxTopology(topology); + pDevice->pImmediateContext->IASetPrimitiveTopology(enmTopology); + return VINF_SUCCESS; +} + + +static int dxSetRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + UINT UAVStartSlot = 0; + UINT NumUAVs = 0; + ID3D11UnorderedAccessView *apUnorderedAccessViews[SVGA3D_DX11_1_MAX_UAVIEWS]; + UINT aUAVInitialCounts[SVGA3D_DX11_1_MAX_UAVIEWS]; + for (uint32_t idxUA = 0; idxUA < SVGA3D_DX11_1_MAX_UAVIEWS; ++idxUA) + { + SVGA3dUAViewId const uaViewId = pDXContext->svgaDXContext.uaViewIds[idxUA]; + if (uaViewId != SVGA3D_INVALID_ID) + { + if (NumUAVs == 0) + UAVStartSlot = idxUA; + NumUAVs = idxUA - UAVStartSlot + 1; + apUnorderedAccessViews[idxUA] = pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId].u.pUnorderedAccessView; + + SVGACOTableDXUAViewEntry const *pEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); + aUAVInitialCounts[idxUA] = pEntry->structureCount; + } + else + { + apUnorderedAccessViews[idxUA] = NULL; + aUAVInitialCounts[idxUA] = (UINT)-1; + } + } + + UINT NumRTVs = 0; + ID3D11RenderTargetView *apRenderTargetViews[SVGA3D_MAX_RENDER_TARGETS]; + RT_ZERO(apRenderTargetViews); + for (uint32_t i = 0; i < pDXContext->cRenderTargets; ++i) + { + SVGA3dRenderTargetViewId const renderTargetViewId = pDXContext->svgaDXContext.renderState.renderTargetViewIds[i]; + if (renderTargetViewId != SVGA3D_INVALID_ID) + { + ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->pBackendDXContext->cRenderTargetView, VERR_INVALID_PARAMETER); + apRenderTargetViews[i] = pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId].u.pRenderTargetView; + ++NumRTVs; + } + } + + /* RTVs are followed by UAVs. */ + Assert(NumUAVs == 0 || NumRTVs <= pDXContext->svgaDXContext.uavSpliceIndex); + + ID3D11DepthStencilView *pDepthStencilView = NULL; + SVGA3dDepthStencilViewId const depthStencilViewId = pDXContext->svgaDXContext.renderState.depthStencilViewId; + if (depthStencilViewId != SVGA_ID_INVALID) + pDepthStencilView = pDXContext->pBackendDXContext->paDepthStencilView[depthStencilViewId].u.pDepthStencilView; + + pDevice->pImmediateContext->OMSetRenderTargetsAndUnorderedAccessViews(NumRTVs, + apRenderTargetViews, + pDepthStencilView, + pDXContext->svgaDXContext.uavSpliceIndex, + NumUAVs, + apUnorderedAccessViews, + aUAVInitialCounts); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, uint32_t cRenderTargetViewId, SVGA3dRenderTargetViewId const *paRenderTargetViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(depthStencilViewId, cRenderTargetViewId, paRenderTargetViewId); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetBlendState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId, float const blendFactor[4], uint32_t sampleMask) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + if (blendId != SVGA3D_INVALID_ID) + { + ID3D11BlendState1 *pBlendState = pDXContext->pBackendDXContext->papBlendState[blendId]; + pDevice->pImmediateContext->OMSetBlendState(pBlendState, blendFactor, sampleMask); + } + else + pDevice->pImmediateContext->OMSetBlendState(NULL, NULL, 0); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetDepthStencilState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId, uint32_t stencilRef) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + if (depthStencilId != SVGA3D_INVALID_ID) + { + ID3D11DepthStencilState *pDepthStencilState = pDXContext->pBackendDXContext->papDepthStencilState[depthStencilId]; + pDevice->pImmediateContext->OMSetDepthStencilState(pDepthStencilState, stencilRef); + } + else + pDevice->pImmediateContext->OMSetDepthStencilState(NULL, 0); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetRasterizerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(pBackend); + + if (rasterizerId != SVGA3D_INVALID_ID) + { + ID3D11RasterizerState1 *pRasterizerState = pDXContext->pBackendDXContext->papRasterizerState[rasterizerId]; + pDevice->pImmediateContext->RSSetState(pRasterizerState); + } + else + pDevice->pImmediateContext->RSSetState(NULL); + + return VINF_SUCCESS; +} + + +typedef struct VGPU10QUERYINFO +{ + SVGA3dQueryType svgaQueryType; + uint32_t cbDataVMSVGA; + D3D11_QUERY dxQueryType; + uint32_t cbDataD3D11; +} VGPU10QUERYINFO; + +static VGPU10QUERYINFO const *dxQueryInfo(SVGA3dQueryType type) +{ + static VGPU10QUERYINFO const aQueryInfo[SVGA3D_QUERYTYPE_MAX] = + { + { SVGA3D_QUERYTYPE_OCCLUSION, sizeof(SVGADXOcclusionQueryResult), + D3D11_QUERY_OCCLUSION, sizeof(UINT64) }, + { SVGA3D_QUERYTYPE_TIMESTAMP, sizeof(SVGADXTimestampQueryResult), + D3D11_QUERY_TIMESTAMP, sizeof(UINT64) }, + { SVGA3D_QUERYTYPE_TIMESTAMPDISJOINT, sizeof(SVGADXTimestampDisjointQueryResult), + D3D11_QUERY_TIMESTAMP_DISJOINT, sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT) }, + { SVGA3D_QUERYTYPE_PIPELINESTATS, sizeof(SVGADXPipelineStatisticsQueryResult), + D3D11_QUERY_PIPELINE_STATISTICS, sizeof(D3D11_QUERY_DATA_PIPELINE_STATISTICS) }, + { SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE, sizeof(SVGADXOcclusionPredicateQueryResult), + D3D11_QUERY_OCCLUSION_PREDICATE, sizeof(BOOL) }, + { SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS, sizeof(SVGADXStreamOutStatisticsQueryResult), + D3D11_QUERY_SO_STATISTICS, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, + { SVGA3D_QUERYTYPE_STREAMOVERFLOWPREDICATE, sizeof(SVGADXStreamOutPredicateQueryResult), + D3D11_QUERY_SO_OVERFLOW_PREDICATE, sizeof(BOOL) }, + { SVGA3D_QUERYTYPE_OCCLUSION64, sizeof(SVGADXOcclusion64QueryResult), + D3D11_QUERY_OCCLUSION, sizeof(UINT64) }, + { SVGA3D_QUERYTYPE_SOSTATS_STREAM0, sizeof(SVGADXStreamOutStatisticsQueryResult), + D3D11_QUERY_SO_STATISTICS_STREAM0, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, + { SVGA3D_QUERYTYPE_SOSTATS_STREAM1, sizeof(SVGADXStreamOutStatisticsQueryResult), + D3D11_QUERY_SO_STATISTICS_STREAM1, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, + { SVGA3D_QUERYTYPE_SOSTATS_STREAM2, sizeof(SVGADXStreamOutStatisticsQueryResult), + D3D11_QUERY_SO_STATISTICS_STREAM2, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, + { SVGA3D_QUERYTYPE_SOSTATS_STREAM3, sizeof(SVGADXStreamOutStatisticsQueryResult), + D3D11_QUERY_SO_STATISTICS_STREAM3, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, + { SVGA3D_QUERYTYPE_SOP_STREAM0, sizeof(SVGADXStreamOutPredicateQueryResult), + D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0, sizeof(BOOL) }, + { SVGA3D_QUERYTYPE_SOP_STREAM1, sizeof(SVGADXStreamOutPredicateQueryResult), + D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1, sizeof(BOOL) }, + { SVGA3D_QUERYTYPE_SOP_STREAM2, sizeof(SVGADXStreamOutPredicateQueryResult), + D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2, sizeof(BOOL) }, + { SVGA3D_QUERYTYPE_SOP_STREAM3, sizeof(SVGADXStreamOutPredicateQueryResult), + D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3, sizeof(BOOL) }, + }; + + ASSERT_GUEST_RETURN(type < RT_ELEMENTS(aQueryInfo), NULL); + return &aQueryInfo[type]; +} + +static int dxDefineQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGACOTableDXQueryEntry const *pEntry) +{ + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); + + DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; + VGPU10QUERYINFO const *pQueryInfo = dxQueryInfo((SVGA3dQueryType)pEntry->type); + if (!pQueryInfo) + return VERR_INVALID_PARAMETER; + + D3D11_QUERY_DESC desc; + desc.Query = pQueryInfo->dxQueryType; + desc.MiscFlags = 0; + if (pEntry->flags & SVGA3D_DXQUERY_FLAG_PREDICATEHINT) + desc.MiscFlags |= (UINT)D3D11_QUERY_MISC_PREDICATEHINT; + + HRESULT hr = pDXDevice->pDevice->CreateQuery(&desc, &pDXQuery->pQuery); + AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); + + return VINF_SUCCESS; +} + + +static int dxDestroyQuery(DXQUERY *pDXQuery) +{ + D3D_RELEASE(pDXQuery->pQuery); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGACOTableDXQueryEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxDefineQuery(pThisCC, pDXContext, queryId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; + dxDestroyQuery(pDXQuery); + + return VINF_SUCCESS; +} + + +/** @todo queryId makes pDXQuery redundant */ +static int dxBeginQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, DXQUERY *pDXQuery) +{ + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); + + /* Begin is disabled for some queries. */ + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + if (pEntry->type == SVGA3D_QUERYTYPE_TIMESTAMP) + return VINF_SUCCESS; + + pDXDevice->pImmediateContext->Begin(pDXQuery->pQuery); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXBeginQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; + int rc = dxBeginQuery(pThisCC, pDXContext, queryId, pDXQuery); + return rc; +} + + +static int dxGetQueryResult(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, + SVGADXQueryResultUnion *pQueryResult, uint32_t *pcbOut) +{ + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); + + typedef union _DXQUERYRESULT + { + UINT64 occlusion; + UINT64 timestamp; + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timestampDisjoint; + D3D11_QUERY_DATA_PIPELINE_STATISTICS pipelineStatistics; + BOOL occlusionPredicate; + D3D11_QUERY_DATA_SO_STATISTICS soStatistics; + BOOL soOverflowPredicate; + } DXQUERYRESULT; + + DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + VGPU10QUERYINFO const *pQueryInfo = dxQueryInfo((SVGA3dQueryType)pEntry->type); + if (!pQueryInfo) + return VERR_INVALID_PARAMETER; + + DXQUERYRESULT dxQueryResult; + while (pDXDevice->pImmediateContext->GetData(pDXQuery->pQuery, &dxQueryResult, pQueryInfo->cbDataD3D11, 0) != S_OK) + { + RTThreadYield(); + } + + /* Copy back the result. */ + switch (pEntry->type) + { + case SVGA3D_QUERYTYPE_OCCLUSION: + pQueryResult->occ.samplesRendered = (uint32_t)dxQueryResult.occlusion; + break; + case SVGA3D_QUERYTYPE_TIMESTAMP: + pQueryResult->ts.timestamp = dxQueryResult.timestamp; + break; + case SVGA3D_QUERYTYPE_TIMESTAMPDISJOINT: + pQueryResult->tsDisjoint.realFrequency = dxQueryResult.timestampDisjoint.Frequency; + pQueryResult->tsDisjoint.disjoint = dxQueryResult.timestampDisjoint.Disjoint; + break; + case SVGA3D_QUERYTYPE_PIPELINESTATS: + pQueryResult->pipelineStats.inputAssemblyVertices = dxQueryResult.pipelineStatistics.IAVertices; + pQueryResult->pipelineStats.inputAssemblyPrimitives = dxQueryResult.pipelineStatistics.IAPrimitives; + pQueryResult->pipelineStats.vertexShaderInvocations = dxQueryResult.pipelineStatistics.VSInvocations; + pQueryResult->pipelineStats.geometryShaderInvocations = dxQueryResult.pipelineStatistics.GSInvocations; + pQueryResult->pipelineStats.geometryShaderPrimitives = dxQueryResult.pipelineStatistics.GSPrimitives; + pQueryResult->pipelineStats.clipperInvocations = dxQueryResult.pipelineStatistics.CInvocations; + pQueryResult->pipelineStats.clipperPrimitives = dxQueryResult.pipelineStatistics.CPrimitives; + pQueryResult->pipelineStats.pixelShaderInvocations = dxQueryResult.pipelineStatistics.PSInvocations; + pQueryResult->pipelineStats.hullShaderInvocations = dxQueryResult.pipelineStatistics.HSInvocations; + pQueryResult->pipelineStats.domainShaderInvocations = dxQueryResult.pipelineStatistics.DSInvocations; + pQueryResult->pipelineStats.computeShaderInvocations = dxQueryResult.pipelineStatistics.CSInvocations; + break; + case SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE: + pQueryResult->occPred.anySamplesRendered = dxQueryResult.occlusionPredicate; + break; + case SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS: + case SVGA3D_QUERYTYPE_SOSTATS_STREAM0: + case SVGA3D_QUERYTYPE_SOSTATS_STREAM1: + case SVGA3D_QUERYTYPE_SOSTATS_STREAM2: + case SVGA3D_QUERYTYPE_SOSTATS_STREAM3: + pQueryResult->soStats.numPrimitivesWritten = dxQueryResult.soStatistics.NumPrimitivesWritten; + pQueryResult->soStats.numPrimitivesRequired = dxQueryResult.soStatistics.PrimitivesStorageNeeded; + break; + case SVGA3D_QUERYTYPE_STREAMOVERFLOWPREDICATE: + case SVGA3D_QUERYTYPE_SOP_STREAM0: + case SVGA3D_QUERYTYPE_SOP_STREAM1: + case SVGA3D_QUERYTYPE_SOP_STREAM2: + case SVGA3D_QUERYTYPE_SOP_STREAM3: + pQueryResult->soPred.overflowed = dxQueryResult.soOverflowPredicate; + break; + case SVGA3D_QUERYTYPE_OCCLUSION64: + pQueryResult->occ64.samplesRendered = dxQueryResult.occlusion; + break; + } + + *pcbOut = pQueryInfo->cbDataVMSVGA; + return VINF_SUCCESS; +} + +static int dxEndQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, + SVGADXQueryResultUnion *pQueryResult, uint32_t *pcbOut) +{ + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); + + DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; + pDXDevice->pImmediateContext->End(pDXQuery->pQuery); + + /** @todo Consider issuing QueryEnd and getting data later in FIFO thread loop. */ + return dxGetQueryResult(pThisCC, pDXContext, queryId, pQueryResult, pcbOut); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXEndQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, + SVGA3dQueryId queryId, SVGADXQueryResultUnion *pQueryResult, uint32_t *pcbOut) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + int rc = dxEndQuery(pThisCC, pDXContext, queryId, pQueryResult, pcbOut); + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetPredication(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, uint32_t predicateValue) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); + + if (queryId != SVGA3D_INVALID_ID) + { + DEBUG_BREAKPOINT_TEST(); + DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + + VGPU10QUERYINFO const *pQueryInfo = dxQueryInfo((SVGA3dQueryType)pEntry->type); + if (!pQueryInfo) + return VERR_INVALID_PARAMETER; + + D3D_RELEASE(pDXQuery->pQuery); + + D3D11_QUERY_DESC desc; + desc.Query = pQueryInfo->dxQueryType; + desc.MiscFlags = 0; + if (pEntry->flags & SVGA3D_DXQUERY_FLAG_PREDICATEHINT) + desc.MiscFlags |= (UINT)D3D11_QUERY_MISC_PREDICATEHINT; + + HRESULT hr = pDXDevice->pDevice->CreatePredicate(&desc, &pDXQuery->pPredicate); + AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); + + pDXDevice->pImmediateContext->SetPredication(pDXQuery->pPredicate, RT_BOOL(predicateValue)); + } + else + pDXDevice->pImmediateContext->SetPredication(NULL, FALSE); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetSOTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cSOTarget, SVGA3dSoTarget const *paSoTarget) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* For each paSoTarget[i]: + * If the stream outout buffer object does not exist then create it. + * If the surface has been updated by the guest then update the buffer object. + * Use SOSetTargets to set the buffers. + */ + + ID3D11Buffer *paResource[SVGA3D_DX_MAX_SOTARGETS]; + UINT paOffset[SVGA3D_DX_MAX_SOTARGETS]; + + /* Always re-bind all 4 SO targets. They can be NULL. */ + for (uint32_t i = 0; i < SVGA3D_DX_MAX_SOTARGETS; ++i) + { + /* Get corresponding resource. Create the buffer if does not yet exist. */ + if (i < cSOTarget && paSoTarget[i].sid != SVGA_ID_INVALID) + { + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, paSoTarget[i].sid, &pSurface); + AssertRCReturn(rc, rc); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the resource. */ + rc = vmsvga3dBackSurfaceCreateSoBuffer(pThisCC, pDXContext, pSurface); + AssertRCReturn(rc, rc); + } + + /** @todo How paSoTarget[i].sizeInBytes is used? Maybe when the buffer is created? */ + paResource[i] = pSurface->pBackendSurface->u.pBuffer; + paOffset[i] = paSoTarget[i].offset; + } + else + { + paResource[i] = NULL; + paOffset[i] = 0; + } + } + + pDevice->pImmediateContext->SOSetTargets(SVGA3D_DX_MAX_SOTARGETS, paResource, paOffset); + + pDXContext->pBackendDXContext->cSOTarget = cSOTarget; + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetViewports(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cViewport, SVGA3dViewport const *paViewport) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(pBackend); + + /* D3D11_VIEWPORT is identical to SVGA3dViewport. */ + D3D11_VIEWPORT *pViewports = (D3D11_VIEWPORT *)paViewport; + + pDevice->pImmediateContext->RSSetViewports(cViewport, pViewports); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetScissorRects(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cRect, SVGASignedRect const *paRect) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* D3D11_RECT is identical to SVGASignedRect. */ + D3D11_RECT *pRects = (D3D11_RECT *)paRect; + + pDevice->pImmediateContext->RSSetScissorRects(cRect, pRects); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXClearRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGA3dRGBAFloat const *pRGBA) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + DXVIEW *pDXView = &pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId]; + if (!pDXView->u.pRenderTargetView) + { +//DEBUG_BREAKPOINT_TEST(); + /* (Re-)create the render target view, because a creation of a view is deferred until a draw or a clear call. */ + SVGACOTableDXRTViewEntry const *pEntry = &pDXContext->cot.paRTView[renderTargetViewId]; + int rc = dxDefineRenderTargetView(pThisCC, pDXContext, renderTargetViewId, pEntry); + AssertRCReturn(rc, rc); + } + pDevice->pImmediateContext->ClearRenderTargetView(pDXView->u.pRenderTargetView, pRGBA->value); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackVBDXClearRenderTargetViewRegion(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, + SVGA3dRGBAFloat const *pColor, uint32_t cRect, SVGASignedRect const *paRect) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + DXVIEW *pDXView = &pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId]; + if (!pDXView->u.pRenderTargetView) + { + /* (Re-)create the render target view, because a creation of a view is deferred until a draw or a clear call. */ + SVGACOTableDXRTViewEntry const *pEntry = &pDXContext->cot.paRTView[renderTargetViewId]; + int rc = dxDefineRenderTargetView(pThisCC, pDXContext, renderTargetViewId, pEntry); + AssertRCReturn(rc, rc); + } + pDevice->pImmediateContext->ClearView(pDXView->u.pRenderTargetView, pColor->value, (D3D11_RECT *)paRect, cRect); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXClearDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t flags, SVGA3dDepthStencilViewId depthStencilViewId, float depth, uint8_t stencil) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + DXVIEW *pDXView = &pDXContext->pBackendDXContext->paDepthStencilView[depthStencilViewId]; + if (!pDXView->u.pDepthStencilView) + { +//DEBUG_BREAKPOINT_TEST(); + /* (Re-)create the depth stencil view, because a creation of a view is deferred until a draw or a clear call. */ + SVGACOTableDXDSViewEntry const *pEntry = &pDXContext->cot.paDSView[depthStencilViewId]; + int rc = dxDefineDepthStencilView(pThisCC, pDXContext, depthStencilViewId, pEntry); + AssertRCReturn(rc, rc); + } + pDevice->pImmediateContext->ClearDepthStencilView(pDXView->u.pDepthStencilView, flags, depth, stencil); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXPredCopyRegion(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId dstSid, uint32_t dstSubResource, SVGA3dSurfaceId srcSid, uint32_t srcSubResource, SVGA3dCopyBox const *pBox) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + PVMSVGA3DSURFACE pSrcSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, srcSid, &pSrcSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DSURFACE pDstSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, dstSid, &pDstSurface); + AssertRCReturn(rc, rc); + + if (pSrcSurface->pBackendSurface == NULL) + { + /* Create the resource. */ + if (pSrcSurface->format != SVGA3D_BUFFER) + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSrcSurface); + else + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSrcSurface); + AssertRCReturn(rc, rc); + } + + if (pDstSurface->pBackendSurface == NULL) + { + /* Create the resource. */ + if (pSrcSurface->format != SVGA3D_BUFFER) + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pDstSurface); + else + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pDstSurface); + AssertRCReturn(rc, rc); + } + + LogFunc(("cid %d: src cid %d%s -> dst cid %d%s\n", + pDXContext->cid, pSrcSurface->idAssociatedContext, + (pSrcSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "", + pDstSurface->idAssociatedContext, + (pDstSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "")); + + /* Clip the box. */ + /** @todo Use [src|dst]SubResource to index p[Src|Dst]Surface->paMipmapLevels array directly. */ + uint32_t iSrcFace; + uint32_t iSrcMipmap; + vmsvga3dCalcMipmapAndFace(pSrcSurface->cLevels, srcSubResource, &iSrcMipmap, &iSrcFace); + + uint32_t iDstFace; + uint32_t iDstMipmap; + vmsvga3dCalcMipmapAndFace(pDstSurface->cLevels, dstSubResource, &iDstMipmap, &iDstFace); + + PVMSVGA3DMIPMAPLEVEL pSrcMipLevel; + rc = vmsvga3dMipmapLevel(pSrcSurface, iSrcFace, iSrcMipmap, &pSrcMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + PVMSVGA3DMIPMAPLEVEL pDstMipLevel; + rc = vmsvga3dMipmapLevel(pDstSurface, iDstFace, iDstMipmap, &pDstMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + SVGA3dCopyBox clipBox = *pBox; + vmsvgaR3ClipCopyBox(&pSrcMipLevel->mipmapSize, &pDstMipLevel->mipmapSize, &clipBox); + + UINT DstSubresource = dstSubResource; + UINT DstX = clipBox.x; + UINT DstY = clipBox.y; + UINT DstZ = clipBox.z; + + UINT SrcSubresource = srcSubResource; + D3D11_BOX SrcBox; + SrcBox.left = clipBox.srcx; + SrcBox.top = clipBox.srcy; + SrcBox.front = clipBox.srcz; + SrcBox.right = clipBox.srcx + clipBox.w; + SrcBox.bottom = clipBox.srcy + clipBox.h; + SrcBox.back = clipBox.srcz + clipBox.d; + + ID3D11Resource *pDstResource; + ID3D11Resource *pSrcResource; + + pDstResource = dxResource(pThisCC->svga.p3dState, pDstSurface, pDXContext); + pSrcResource = dxResource(pThisCC->svga.p3dState, pSrcSurface, pDXContext); + + pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox); + +#ifdef DUMP_BITMAPS + SVGA3dSurfaceImageId image; + image.sid = pDstSurface->id; + image.face = 0; + image.mipmap = 0; + VMSVGA3D_MAPPED_SURFACE map; + int rc2 = vmsvga3dSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map); + if (RT_SUCCESS(rc2)) + { + vmsvga3dMapWriteBmpFile(&map, "copyregion-"); + vmsvga3dSurfaceUnmap(pThisCC, &image, &map, /* fWritten = */ false); + } + else + Log(("Map failed %Rrc\n", rc)); +#endif + + pDstSurface->pBackendSurface->cidDrawing = pDXContext->cid; + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXPredCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId dstSid, SVGA3dSurfaceId srcSid) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + PVMSVGA3DSURFACE pSrcSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, srcSid, &pSrcSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DSURFACE pDstSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, dstSid, &pDstSurface); + AssertRCReturn(rc, rc); + + if (pSrcSurface->pBackendSurface == NULL) + { + /* Create the resource. */ + if (pSrcSurface->format != SVGA3D_BUFFER) + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSrcSurface); + else + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSrcSurface); + AssertRCReturn(rc, rc); + } + + if (pDstSurface->pBackendSurface == NULL) + { + /* Create the resource. */ + if (pSrcSurface->format != SVGA3D_BUFFER) + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pDstSurface); + else + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pDstSurface); + AssertRCReturn(rc, rc); + } + + LogFunc(("cid %d: src cid %d%s -> dst cid %d%s\n", + pDXContext->cid, pSrcSurface->idAssociatedContext, + (pSrcSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "", + pDstSurface->idAssociatedContext, + (pDstSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "")); + + ID3D11Resource *pDstResource = dxResource(pThisCC->svga.p3dState, pDstSurface, pDXContext); + ID3D11Resource *pSrcResource = dxResource(pThisCC->svga.p3dState, pSrcSurface, pDXContext); + + pDevice->pImmediateContext->CopyResource(pDstResource, pSrcResource); + + pDstSurface->pBackendSurface->cidDrawing = pDXContext->cid; + return VINF_SUCCESS; +} + + +#include "shaders/d3d11blitter.hlsl.vs.h" +#include "shaders/d3d11blitter.hlsl.ps.h" + +#define HTEST(stmt) \ + hr = stmt; \ + AssertReturn(SUCCEEDED(hr), hr) + + +static void BlitRelease(D3D11BLITTER *pBlitter) +{ + D3D_RELEASE(pBlitter->pVertexShader); + D3D_RELEASE(pBlitter->pPixelShader); + D3D_RELEASE(pBlitter->pSamplerState); + D3D_RELEASE(pBlitter->pRasterizerState); + D3D_RELEASE(pBlitter->pBlendState); + RT_ZERO(*pBlitter); +} + + +static HRESULT BlitInit(D3D11BLITTER *pBlitter, ID3D11Device1 *pDevice, ID3D11DeviceContext1 *pImmediateContext) +{ + HRESULT hr; + + RT_ZERO(*pBlitter); + + pBlitter->pDevice = pDevice; + pBlitter->pImmediateContext = pImmediateContext; + + HTEST(pBlitter->pDevice->CreateVertexShader(g_vs_blitter, sizeof(g_vs_blitter), NULL, &pBlitter->pVertexShader)); + HTEST(pBlitter->pDevice->CreatePixelShader(g_ps_blitter, sizeof(g_ps_blitter), NULL, &pBlitter->pPixelShader)); + + D3D11_SAMPLER_DESC SamplerDesc; + SamplerDesc.Filter = D3D11_FILTER_ANISOTROPIC; + SamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + SamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + SamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + SamplerDesc.MipLODBias = 0.0f; + SamplerDesc.MaxAnisotropy = 4; + SamplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + SamplerDesc.BorderColor[0] = 0.0f; + SamplerDesc.BorderColor[1] = 0.0f; + SamplerDesc.BorderColor[2] = 0.0f; + SamplerDesc.BorderColor[3] = 0.0f; + SamplerDesc.MinLOD = 0.0f; + SamplerDesc.MaxLOD = 0.0f; + HTEST(pBlitter->pDevice->CreateSamplerState(&SamplerDesc, &pBlitter->pSamplerState)); + + D3D11_RASTERIZER_DESC1 RasterizerDesc; + RasterizerDesc.FillMode = D3D11_FILL_SOLID; + RasterizerDesc.CullMode = D3D11_CULL_NONE; + RasterizerDesc.FrontCounterClockwise = FALSE; + RasterizerDesc.DepthBias = 0; + RasterizerDesc.DepthBiasClamp = 0.0f; + RasterizerDesc.SlopeScaledDepthBias = 0.0f; + RasterizerDesc.DepthClipEnable = FALSE; + RasterizerDesc.ScissorEnable = FALSE; + RasterizerDesc.MultisampleEnable = FALSE; + RasterizerDesc.AntialiasedLineEnable = FALSE; + RasterizerDesc.ForcedSampleCount = 0; + HTEST(pBlitter->pDevice->CreateRasterizerState1(&RasterizerDesc, &pBlitter->pRasterizerState)); + + D3D11_BLEND_DESC1 BlendDesc; + BlendDesc.AlphaToCoverageEnable = FALSE; + BlendDesc.IndependentBlendEnable = FALSE; + for (unsigned i = 0; i < RT_ELEMENTS(BlendDesc.RenderTarget); ++i) + { + BlendDesc.RenderTarget[i].BlendEnable = FALSE; + BlendDesc.RenderTarget[i].LogicOpEnable = FALSE; + BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_SRC_COLOR; + BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO; + BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; + BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO; + BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; + BlendDesc.RenderTarget[i].LogicOp = D3D11_LOGIC_OP_CLEAR; + BlendDesc.RenderTarget[i].RenderTargetWriteMask = 0xF; + } + HTEST(pBlitter->pDevice->CreateBlendState1(&BlendDesc, &pBlitter->pBlendState)); + + return S_OK; +} + + +static HRESULT BlitFromTexture(D3D11BLITTER *pBlitter, ID3D11RenderTargetView *pDstRenderTargetView, + float cDstWidth, float cDstHeight, D3D11_RECT const &rectDst, + ID3D11ShaderResourceView *pSrcShaderResourceView) +{ + HRESULT hr; + + /* + * Save pipeline state. + */ + struct + { + D3D11_PRIMITIVE_TOPOLOGY Topology; + ID3D11InputLayout *pInputLayout; + ID3D11Buffer *pConstantBuffer; + ID3D11VertexShader *pVertexShader; + ID3D11HullShader *pHullShader; + ID3D11DomainShader *pDomainShader; + ID3D11GeometryShader *pGeometryShader; + ID3D11ShaderResourceView *pShaderResourceView; + ID3D11PixelShader *pPixelShader; + ID3D11SamplerState *pSamplerState; + ID3D11RasterizerState *pRasterizerState; + ID3D11BlendState *pBlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11RenderTargetView *apRenderTargetView[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; + ID3D11DepthStencilView *pDepthStencilView; + UINT NumViewports; + D3D11_VIEWPORT aViewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + } SavedState; + + pBlitter->pImmediateContext->IAGetPrimitiveTopology(&SavedState.Topology); + pBlitter->pImmediateContext->IAGetInputLayout(&SavedState.pInputLayout); + pBlitter->pImmediateContext->VSGetConstantBuffers(0, 1, &SavedState.pConstantBuffer); + pBlitter->pImmediateContext->VSGetShader(&SavedState.pVertexShader, NULL, NULL); + pBlitter->pImmediateContext->HSGetShader(&SavedState.pHullShader, NULL, NULL); + pBlitter->pImmediateContext->DSGetShader(&SavedState.pDomainShader, NULL, NULL); + pBlitter->pImmediateContext->GSGetShader(&SavedState.pGeometryShader, NULL, NULL); + pBlitter->pImmediateContext->PSGetShaderResources(0, 1, &SavedState.pShaderResourceView); + pBlitter->pImmediateContext->PSGetShader(&SavedState.pPixelShader, NULL, NULL); + pBlitter->pImmediateContext->PSGetSamplers(0, 1, &SavedState.pSamplerState); + pBlitter->pImmediateContext->RSGetState(&SavedState.pRasterizerState); + pBlitter->pImmediateContext->OMGetBlendState(&SavedState.pBlendState, SavedState.BlendFactor, &SavedState.SampleMask); + pBlitter->pImmediateContext->OMGetRenderTargets(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView, &SavedState.pDepthStencilView); + SavedState.NumViewports = RT_ELEMENTS(SavedState.aViewport); + pBlitter->pImmediateContext->RSGetViewports(&SavedState.NumViewports, &SavedState.aViewport[0]); + + /* + * Setup pipeline for the blitter. + */ + + /* Render target is first. + * If the source texture is bound as a render target, then this call will unbind it + * and allow to use it as the shader resource. + */ + pBlitter->pImmediateContext->OMSetRenderTargets(1, &pDstRenderTargetView, NULL); + + /* Input assembler. */ + pBlitter->pImmediateContext->IASetInputLayout(NULL); + pBlitter->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + /* Constant buffer. */ + struct + { + float scaleX; + float scaleY; + float offsetX; + float offsetY; + } VSConstantBuffer; + VSConstantBuffer.scaleX = (float)(rectDst.right - rectDst.left) / cDstWidth; + VSConstantBuffer.scaleY = (float)(rectDst.bottom - rectDst.top) / cDstHeight; + VSConstantBuffer.offsetX = (float)(rectDst.right + rectDst.left) / cDstWidth - 1.0f; + VSConstantBuffer.offsetY = -((float)(rectDst.bottom + rectDst.top) / cDstHeight - 1.0f); + + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = &VSConstantBuffer; + initialData.SysMemPitch = sizeof(VSConstantBuffer); + initialData.SysMemSlicePitch = sizeof(VSConstantBuffer); + + D3D11_BUFFER_DESC bd; + RT_ZERO(bd); + bd.ByteWidth = sizeof(VSConstantBuffer); + bd.Usage = D3D11_USAGE_IMMUTABLE; + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + + ID3D11Buffer *pConstantBuffer; + HTEST(pBlitter->pDevice->CreateBuffer(&bd, &initialData, &pConstantBuffer)); + pBlitter->pImmediateContext->VSSetConstantBuffers(0, 1, &pConstantBuffer); + D3D_RELEASE(pConstantBuffer); /* xSSetConstantBuffers "will hold a reference to the interfaces passed in." */ + + /* Vertex shader. */ + pBlitter->pImmediateContext->VSSetShader(pBlitter->pVertexShader, NULL, 0); + + /* Unused shaders. */ + pBlitter->pImmediateContext->HSSetShader(NULL, NULL, 0); + pBlitter->pImmediateContext->DSSetShader(NULL, NULL, 0); + pBlitter->pImmediateContext->GSSetShader(NULL, NULL, 0); + + /* Shader resource view. */ + pBlitter->pImmediateContext->PSSetShaderResources(0, 1, &pSrcShaderResourceView); + + /* Pixel shader. */ + pBlitter->pImmediateContext->PSSetShader(pBlitter->pPixelShader, NULL, 0); + + /* Sampler. */ + pBlitter->pImmediateContext->PSSetSamplers(0, 1, &pBlitter->pSamplerState); + + /* Rasterizer. */ + pBlitter->pImmediateContext->RSSetState(pBlitter->pRasterizerState); + + /* Blend state. */ + static FLOAT const BlendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pBlitter->pImmediateContext->OMSetBlendState(pBlitter->pBlendState, BlendFactor, 0xffffffff); + + /* Viewport. */ + D3D11_VIEWPORT Viewport; + Viewport.TopLeftX = 0; + Viewport.TopLeftY = 0; + Viewport.Width = cDstWidth; + Viewport.Height = cDstHeight; + Viewport.MinDepth = 0.0f; + Viewport.MaxDepth = 1.0f; + pBlitter->pImmediateContext->RSSetViewports(1, &Viewport); + + /* Draw. */ + pBlitter->pImmediateContext->Draw(4, 0); + + /* + * Restore pipeline state. + */ + pBlitter->pImmediateContext->IASetPrimitiveTopology(SavedState.Topology); + pBlitter->pImmediateContext->IASetInputLayout(SavedState.pInputLayout); + D3D_RELEASE(SavedState.pInputLayout); + pBlitter->pImmediateContext->VSSetConstantBuffers(0, 1, &SavedState.pConstantBuffer); + D3D_RELEASE(SavedState.pConstantBuffer); + pBlitter->pImmediateContext->VSSetShader(SavedState.pVertexShader, NULL, 0); + D3D_RELEASE(SavedState.pVertexShader); + + pBlitter->pImmediateContext->HSSetShader(SavedState.pHullShader, NULL, 0); + D3D_RELEASE(SavedState.pHullShader); + pBlitter->pImmediateContext->DSSetShader(SavedState.pDomainShader, NULL, 0); + D3D_RELEASE(SavedState.pDomainShader); + pBlitter->pImmediateContext->GSSetShader(SavedState.pGeometryShader, NULL, 0); + D3D_RELEASE(SavedState.pGeometryShader); + + pBlitter->pImmediateContext->PSSetShaderResources(0, 1, &SavedState.pShaderResourceView); + D3D_RELEASE(SavedState.pShaderResourceView); + pBlitter->pImmediateContext->PSSetShader(SavedState.pPixelShader, NULL, 0); + D3D_RELEASE(SavedState.pPixelShader); + pBlitter->pImmediateContext->PSSetSamplers(0, 1, &SavedState.pSamplerState); + D3D_RELEASE(SavedState.pSamplerState); + pBlitter->pImmediateContext->RSSetState(SavedState.pRasterizerState); + D3D_RELEASE(SavedState.pRasterizerState); + pBlitter->pImmediateContext->OMSetBlendState(SavedState.pBlendState, SavedState.BlendFactor, SavedState.SampleMask); + D3D_RELEASE(SavedState.pBlendState); + pBlitter->pImmediateContext->OMSetRenderTargets(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView, SavedState.pDepthStencilView); + D3D_RELEASE_ARRAY(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView); + D3D_RELEASE(SavedState.pDepthStencilView); + pBlitter->pImmediateContext->RSSetViewports(SavedState.NumViewports, &SavedState.aViewport[0]); + + return S_OK; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXPresentBlt(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, + SVGA3dSurfaceId dstSid, uint32_t dstSubResource, SVGA3dBox const *pBoxDst, + SVGA3dSurfaceId srcSid, uint32_t srcSubResource, SVGA3dBox const *pBoxSrc, + SVGA3dDXPresentBltMode mode) +{ + RT_NOREF(mode); + + ASSERT_GUEST_RETURN(pBoxDst->z == 0 && pBoxDst->d == 1, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pBoxSrc->z == 0 && pBoxSrc->d == 1, VERR_INVALID_PARAMETER); + + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + PVMSVGA3DSURFACE pSrcSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, srcSid, &pSrcSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DSURFACE pDstSurface; + rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, dstSid, &pDstSurface); + AssertRCReturn(rc, rc); + + if (pSrcSurface->pBackendSurface == NULL) + { + /* Create the resource. */ + if (pSrcSurface->format != SVGA3D_BUFFER) + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSrcSurface); + else + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSrcSurface); + AssertRCReturn(rc, rc); + } + + if (pDstSurface->pBackendSurface == NULL) + { + /* Create the resource. */ + if (pSrcSurface->format != SVGA3D_BUFFER) + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pDstSurface); + else + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pDstSurface); + AssertRCReturn(rc, rc); + } + + LogFunc(("cid %d: src cid %d%s -> dst cid %d%s\n", + pDXContext->cid, pSrcSurface->idAssociatedContext, + (pSrcSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "", + pDstSurface->idAssociatedContext, + (pDstSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "")); + + /* Clip the box. */ + /** @todo Use [src|dst]SubResource to index p[Src|Dst]Surface->paMipmapLevels array directly. */ + uint32_t iSrcFace; + uint32_t iSrcMipmap; + vmsvga3dCalcMipmapAndFace(pSrcSurface->cLevels, srcSubResource, &iSrcMipmap, &iSrcFace); + + uint32_t iDstFace; + uint32_t iDstMipmap; + vmsvga3dCalcMipmapAndFace(pDstSurface->cLevels, dstSubResource, &iDstMipmap, &iDstFace); + + PVMSVGA3DMIPMAPLEVEL pSrcMipLevel; + rc = vmsvga3dMipmapLevel(pSrcSurface, iSrcFace, iSrcMipmap, &pSrcMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + PVMSVGA3DMIPMAPLEVEL pDstMipLevel; + rc = vmsvga3dMipmapLevel(pDstSurface, iDstFace, iDstMipmap, &pDstMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + SVGA3dBox clipBoxSrc = *pBoxSrc; + vmsvgaR3ClipBox(&pSrcMipLevel->mipmapSize, &clipBoxSrc); + + SVGA3dBox clipBoxDst = *pBoxDst; + vmsvgaR3ClipBox(&pDstMipLevel->mipmapSize, &clipBoxDst); + + ID3D11Resource *pDstResource = dxResource(pThisCC->svga.p3dState, pDstSurface, pDXContext); + ID3D11Resource *pSrcResource = dxResource(pThisCC->svga.p3dState, pSrcSurface, pDXContext); + + D3D11_RENDER_TARGET_VIEW_DESC RTVDesc; + RT_ZERO(RTVDesc); + RTVDesc.Format = vmsvgaDXSurfaceFormat2Dxgi(pDstSurface->format);; + RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + RTVDesc.Texture2D.MipSlice = dstSubResource; + + ID3D11RenderTargetView *pDstRenderTargetView; + HRESULT hr = pDevice->pDevice->CreateRenderTargetView(pDstResource, &RTVDesc, &pDstRenderTargetView); + AssertReturn(SUCCEEDED(hr), VERR_NOT_SUPPORTED); + + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + RT_ZERO(SRVDesc); + SRVDesc.Format = vmsvgaDXSurfaceFormat2Dxgi(pSrcSurface->format); + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MostDetailedMip = srcSubResource; + SRVDesc.Texture2D.MipLevels = 1; + + ID3D11ShaderResourceView *pSrcShaderResourceView; + hr = pDevice->pDevice->CreateShaderResourceView(pSrcResource, &SRVDesc, &pSrcShaderResourceView); + AssertReturnStmt(SUCCEEDED(hr), D3D_RELEASE(pDstRenderTargetView), VERR_NOT_SUPPORTED); + + D3D11_RECT rectDst; + rectDst.left = pBoxDst->x; + rectDst.top = pBoxDst->y; + rectDst.right = pBoxDst->x + pBoxDst->w; + rectDst.bottom = pBoxDst->y + pBoxDst->h; + + BlitFromTexture(&pDevice->Blitter, pDstRenderTargetView, (float)pDstMipLevel->mipmapSize.width, (float)pDstMipLevel->mipmapSize.height, + rectDst, pSrcShaderResourceView); + + D3D_RELEASE(pSrcShaderResourceView); + D3D_RELEASE(pDstRenderTargetView); + + pDstSurface->pBackendSurface->cidDrawing = pDXContext->cid; + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXGenMips(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + ID3D11ShaderResourceView *pShaderResourceView = pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId].u.pShaderResourceView; + AssertReturn(pShaderResourceView, VERR_INVALID_STATE); + + SVGACOTableDXSRViewEntry const *pSRViewEntry = dxGetShaderResourceViewEntry(pDXContext, shaderResourceViewId); + AssertReturn(pSRViewEntry, VERR_INVALID_STATE); + + uint32_t const sid = pSRViewEntry->sid; + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + AssertRCReturn(rc, rc); + AssertReturn(pSurface->pBackendSurface, VERR_INVALID_STATE); + + pDevice->pImmediateContext->GenerateMips(pShaderResourceView); + + pSurface->pBackendSurface->cidDrawing = pDXContext->cid; + return VINF_SUCCESS; +} + + +static int dxDefineShaderResourceView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId, SVGACOTableDXSRViewEntry const *pEntry) +{ + /* Get corresponding resource for pEntry->sid. Create the surface if does not yet exist. */ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pEntry->sid, &pSurface); + AssertRCReturn(rc, rc); + + ID3D11ShaderResourceView *pShaderResourceView; + DXVIEW *pView = &pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId]; + Assert(pView->u.pView == NULL); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the actual texture or buffer. */ + /** @todo One function to create all resources from surfaces. */ + if (pSurface->format != SVGA3D_BUFFER) + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSurface); + else + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); + + AssertRCReturn(rc, rc); + } + + HRESULT hr = dxShaderResourceViewCreate(pThisCC, pDXContext, pEntry, pSurface, &pShaderResourceView); + AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); + + return dxViewInit(pView, pSurface, pDXContext, shaderResourceViewId, VMSVGA3D_VIEWTYPE_SHADERRESOURCE, pShaderResourceView); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineShaderResourceView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId, SVGACOTableDXSRViewEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /** @todo Probably not necessary because SRVs are defined in setupPipeline. */ + return dxDefineShaderResourceView(pThisCC, pDXContext, shaderResourceViewId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyShaderResourceView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxViewDestroy(&pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId]); +} + + +static int dxDefineRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGACOTableDXRTViewEntry const *pEntry) +{ + /* Get corresponding resource for pEntry->sid. Create the surface if does not yet exist. */ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pEntry->sid, &pSurface); + AssertRCReturn(rc, rc); + + DXVIEW *pView = &pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId]; + Assert(pView->u.pView == NULL); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the actual texture. */ + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSurface); + AssertRCReturn(rc, rc); + } + + ID3D11RenderTargetView *pRenderTargetView; + HRESULT hr = dxRenderTargetViewCreate(pThisCC, pDXContext, pEntry, pSurface, &pRenderTargetView); + AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); + + return dxViewInit(pView, pSurface, pDXContext, renderTargetViewId, VMSVGA3D_VIEWTYPE_RENDERTARGET, pRenderTargetView); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGACOTableDXRTViewEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + return dxDefineRenderTargetView(pThisCC, pDXContext, renderTargetViewId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxViewDestroy(&pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId]); +} + + +static int dxDefineDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, SVGACOTableDXDSViewEntry const *pEntry) +{ + /* Get corresponding resource for pEntry->sid. Create the surface if does not yet exist. */ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pEntry->sid, &pSurface); + AssertRCReturn(rc, rc); + + DXVIEW *pView = &pDXContext->pBackendDXContext->paDepthStencilView[depthStencilViewId]; + Assert(pView->u.pView == NULL); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the actual texture. */ + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSurface); + AssertRCReturn(rc, rc); + } + + ID3D11DepthStencilView *pDepthStencilView; + HRESULT hr = dxDepthStencilViewCreate(pThisCC, pDXContext, pEntry, pSurface, &pDepthStencilView); + AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); + + return dxViewInit(pView, pSurface, pDXContext, depthStencilViewId, VMSVGA3D_VIEWTYPE_DEPTHSTENCIL, pDepthStencilView); +} + +static DECLCALLBACK(int) vmsvga3dBackDXDefineDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, SVGACOTableDXDSViewEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + return dxDefineDepthStencilView(pThisCC, pDXContext, depthStencilViewId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxViewDestroy(&pDXContext->pBackendDXContext->paDepthStencilView[depthStencilViewId]); +} + + +static int dxDefineElementLayout(PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId, SVGACOTableDXElementLayoutEntry const *pEntry) +{ + DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; + D3D_RELEASE(pDXElementLayout->pElementLayout); + pDXElementLayout->cElementDesc = 0; + RT_ZERO(pDXElementLayout->aElementDesc); + + RT_NOREF(pEntry); + + return VINF_SUCCESS; +} + + +static int dxDestroyElementLayout(DXELEMENTLAYOUT *pDXElementLayout) +{ + D3D_RELEASE(pDXElementLayout->pElementLayout); + pDXElementLayout->cElementDesc = 0; + RT_ZERO(pDXElementLayout->aElementDesc); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineElementLayout(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId, SVGACOTableDXElementLayoutEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(pBackend); + + /* Not much can be done here because ID3D11Device::CreateInputLayout requires + * a pShaderBytecodeWithInputSignature which is not known at this moment. + * InputLayout object will be created in setupPipeline. + */ + + Assert(elementLayoutId == pEntry->elid); + + return dxDefineElementLayout(pDXContext, elementLayoutId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyElementLayout(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; + dxDestroyElementLayout(pDXElementLayout); + + return VINF_SUCCESS; +} + + +static int dxDefineBlendState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, + SVGA3dBlendStateId blendId, SVGACOTableDXBlendStateEntry const *pEntry) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + HRESULT hr = dxBlendStateCreate(pDevice, pEntry, &pDXContext->pBackendDXContext->papBlendState[blendId]); + if (SUCCEEDED(hr)) + return VINF_SUCCESS; + return VERR_INVALID_STATE; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineBlendState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, + SVGA3dBlendStateId blendId, SVGACOTableDXBlendStateEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxDefineBlendState(pThisCC, pDXContext, blendId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyBlendState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + D3D_RELEASE(pDXContext->pBackendDXContext->papBlendState[blendId]); + return VINF_SUCCESS; +} + + +static int dxDefineDepthStencilState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId, SVGACOTableDXDepthStencilEntry const *pEntry) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + HRESULT hr = dxDepthStencilStateCreate(pDevice, pEntry, &pDXContext->pBackendDXContext->papDepthStencilState[depthStencilId]); + if (SUCCEEDED(hr)) + return VINF_SUCCESS; + return VERR_INVALID_STATE; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineDepthStencilState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId, SVGACOTableDXDepthStencilEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxDefineDepthStencilState(pThisCC, pDXContext, depthStencilId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyDepthStencilState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + D3D_RELEASE(pDXContext->pBackendDXContext->papDepthStencilState[depthStencilId]); + return VINF_SUCCESS; +} + + +static int dxDefineRasterizerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId, SVGACOTableDXRasterizerStateEntry const *pEntry) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + HRESULT hr = dxRasterizerStateCreate(pDevice, pEntry, &pDXContext->pBackendDXContext->papRasterizerState[rasterizerId]); + if (SUCCEEDED(hr)) + return VINF_SUCCESS; + return VERR_INVALID_STATE; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineRasterizerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId, SVGACOTableDXRasterizerStateEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxDefineRasterizerState(pThisCC, pDXContext, rasterizerId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyRasterizerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + D3D_RELEASE(pDXContext->pBackendDXContext->papRasterizerState[rasterizerId]); + return VINF_SUCCESS; +} + + +static int dxDefineSamplerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSamplerId samplerId, SVGACOTableDXSamplerEntry const *pEntry) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + HRESULT hr = dxSamplerStateCreate(pDevice, pEntry, &pDXContext->pBackendDXContext->papSamplerState[samplerId]); + if (SUCCEEDED(hr)) + return VINF_SUCCESS; + return VERR_INVALID_STATE; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineSamplerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSamplerId samplerId, SVGACOTableDXSamplerEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxDefineSamplerState(pThisCC, pDXContext, samplerId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroySamplerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSamplerId samplerId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + D3D_RELEASE(pDXContext->pBackendDXContext->papSamplerState[samplerId]); + return VINF_SUCCESS; +} + + +static int dxDefineShader(PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, SVGACOTableDXShaderEntry const *pEntry) +{ + /** @todo A common approach for creation of COTable backend objects: runtime, empty DX COTable, live DX COTable. */ + DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[shaderId]; + Assert(pDXShader->enmShaderType == SVGA3D_SHADERTYPE_INVALID); + + /* Init the backend shader structure, if the shader has not been created yet. */ + pDXShader->enmShaderType = pEntry->type; + pDXShader->pShader = NULL; + pDXShader->soid = SVGA_ID_INVALID; + + return VINF_SUCCESS; +} + + +static int dxDestroyShader(DXSHADER *pDXShader) +{ + pDXShader->enmShaderType = SVGA3D_SHADERTYPE_INVALID; + DXShaderFree(&pDXShader->shaderInfo); + D3D_RELEASE(pDXShader->pShader); + RTMemFree(pDXShader->pvDXBC); + pDXShader->pvDXBC = NULL; + pDXShader->cbDXBC = 0; + pDXShader->soid = SVGA_ID_INVALID; + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, SVGACOTableDXShaderEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxDefineShader(pDXContext, shaderId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[shaderId]; + dxDestroyShader(pDXShader); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXBindShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, DXShaderInfo const *pShaderInfo) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(pBackend); + + DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[shaderId]; + if (pDXShader->pvDXBC) + { + /* New DXBC code and new shader must be created. */ + D3D_RELEASE(pDXShader->pShader); + RTMemFree(pDXShader->pvDXBC); + pDXShader->pvDXBC = NULL; + pDXShader->cbDXBC = 0; + } + + pDXShader->shaderInfo = *pShaderInfo; + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineStreamOutput(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid, SVGACOTableDXStreamOutputEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; + dxDestroyStreamOutput(pDXStreamOutput); + + RT_NOREF(pEntry); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyStreamOutput(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; + dxDestroyStreamOutput(pDXStreamOutput); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetStreamOutput(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend, pDXContext, soid); + + return VINF_SUCCESS; +} + + +static int dxCOTableRealloc(void **ppvCOTable, uint32_t *pcCOTable, uint32_t cbEntry, uint32_t cEntries, uint32_t cValidEntries) +{ + uint32_t const cCOTableCurrent = *pcCOTable; + + if (*pcCOTable != cEntries) + { + /* Grow/shrink the array. */ + if (cEntries) + { + void *pvNew = RTMemRealloc(*ppvCOTable, cEntries * cbEntry); + AssertReturn(pvNew, VERR_NO_MEMORY); + *ppvCOTable = pvNew; + } + else + { + RTMemFree(*ppvCOTable); + *ppvCOTable = NULL; + } + + *pcCOTable = cEntries; + } + + if (*ppvCOTable) + { + uint32_t const cEntriesToKeep = RT_MIN(cCOTableCurrent, cValidEntries); + memset((uint8_t *)(*ppvCOTable) + cEntriesToKeep * cbEntry, 0, (cEntries - cEntriesToKeep) * cbEntry); + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackDXSetCOTable(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableType type, uint32_t cValidEntries) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; + + int rc = VINF_SUCCESS; + + /* + * 1) Release current backend table, if exists; + * 2) Reallocate memory for the new backend table; + * 3) If cValidEntries is not zero, then re-define corresponding backend table elements. + */ + switch (type) + { + case SVGA_COTABLE_RTVIEW: + /* Clear current entries. */ + if (pBackendDXContext->paRenderTargetView) + { + for (uint32_t i = 0; i < pBackendDXContext->cRenderTargetView; ++i) + { + DXVIEW *pDXView = &pBackendDXContext->paRenderTargetView[i]; + if (i < cValidEntries) + dxViewRemoveFromList(pDXView); /* Remove from list because DXVIEW array will be reallocated. */ + else + dxViewDestroy(pDXView); + } + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->paRenderTargetView, &pBackendDXContext->cRenderTargetView, + sizeof(pBackendDXContext->paRenderTargetView[0]), pDXContext->cot.cRTView, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXRTViewEntry const *pEntry = &pDXContext->cot.paRTView[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + /* Define views which were not defined yet in backend. */ + DXVIEW *pDXView = &pBackendDXContext->paRenderTargetView[i]; + /** @todo Verify that the pEntry content still corresponds to the view. */ + if (pDXView->u.pView) + dxViewAddToList(pThisCC, pDXView); + else if (pDXView->enmViewType == VMSVGA3D_VIEWTYPE_NONE) + dxDefineRenderTargetView(pThisCC, pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_DSVIEW: + if (pBackendDXContext->paDepthStencilView) + { + for (uint32_t i = 0; i < pBackendDXContext->cDepthStencilView; ++i) + { + DXVIEW *pDXView = &pBackendDXContext->paDepthStencilView[i]; + if (i < cValidEntries) + dxViewRemoveFromList(pDXView); /* Remove from list because DXVIEW array will be reallocated. */ + else + dxViewDestroy(pDXView); + } + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->paDepthStencilView, &pBackendDXContext->cDepthStencilView, + sizeof(pBackendDXContext->paDepthStencilView[0]), pDXContext->cot.cDSView, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXDSViewEntry const *pEntry = &pDXContext->cot.paDSView[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + /* Define views which were not defined yet in backend. */ + DXVIEW *pDXView = &pBackendDXContext->paDepthStencilView[i]; + /** @todo Verify that the pEntry content still corresponds to the view. */ + if (pDXView->u.pView) + dxViewAddToList(pThisCC, pDXView); + else if (pDXView->enmViewType == VMSVGA3D_VIEWTYPE_NONE) + dxDefineDepthStencilView(pThisCC, pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_SRVIEW: + if (pBackendDXContext->paShaderResourceView) + { + for (uint32_t i = 0; i < pBackendDXContext->cShaderResourceView; ++i) + { + DXVIEW *pDXView = &pBackendDXContext->paShaderResourceView[i]; + if (i < cValidEntries) + dxViewRemoveFromList(pDXView); /* Remove from list because DXVIEW array will be reallocated. */ + else + dxViewDestroy(pDXView); + } + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->paShaderResourceView, &pBackendDXContext->cShaderResourceView, + sizeof(pBackendDXContext->paShaderResourceView[0]), pDXContext->cot.cSRView, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXSRViewEntry const *pEntry = &pDXContext->cot.paSRView[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + /* Define views which were not defined yet in backend. */ + DXVIEW *pDXView = &pBackendDXContext->paShaderResourceView[i]; + /** @todo Verify that the pEntry content still corresponds to the view. */ + if (pDXView->u.pView) + dxViewAddToList(pThisCC, pDXView); + else if (pDXView->enmViewType == VMSVGA3D_VIEWTYPE_NONE) + dxDefineShaderResourceView(pThisCC, pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_ELEMENTLAYOUT: + if (pBackendDXContext->paElementLayout) + { + for (uint32_t i = cValidEntries; i < pBackendDXContext->cElementLayout; ++i) + D3D_RELEASE(pBackendDXContext->paElementLayout[i].pElementLayout); + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->paElementLayout, &pBackendDXContext->cElementLayout, + sizeof(pBackendDXContext->paElementLayout[0]), pDXContext->cot.cElementLayout, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXElementLayoutEntry const *pEntry = &pDXContext->cot.paElementLayout[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + dxDefineElementLayout(pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_BLENDSTATE: + if (pBackendDXContext->papBlendState) + { + for (uint32_t i = cValidEntries; i < pBackendDXContext->cBlendState; ++i) + D3D_RELEASE(pBackendDXContext->papBlendState[i]); + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->papBlendState, &pBackendDXContext->cBlendState, + sizeof(pBackendDXContext->papBlendState[0]), pDXContext->cot.cBlendState, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXBlendStateEntry const *pEntry = &pDXContext->cot.paBlendState[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + dxDefineBlendState(pThisCC, pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_DEPTHSTENCIL: + if (pBackendDXContext->papDepthStencilState) + { + for (uint32_t i = cValidEntries; i < pBackendDXContext->cDepthStencilState; ++i) + D3D_RELEASE(pBackendDXContext->papDepthStencilState[i]); + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->papDepthStencilState, &pBackendDXContext->cDepthStencilState, + sizeof(pBackendDXContext->papDepthStencilState[0]), pDXContext->cot.cDepthStencil, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXDepthStencilEntry const *pEntry = &pDXContext->cot.paDepthStencil[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + dxDefineDepthStencilState(pThisCC, pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_RASTERIZERSTATE: + if (pBackendDXContext->papRasterizerState) + { + for (uint32_t i = cValidEntries; i < pBackendDXContext->cRasterizerState; ++i) + D3D_RELEASE(pBackendDXContext->papRasterizerState[i]); + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->papRasterizerState, &pBackendDXContext->cRasterizerState, + sizeof(pBackendDXContext->papRasterizerState[0]), pDXContext->cot.cRasterizerState, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXRasterizerStateEntry const *pEntry = &pDXContext->cot.paRasterizerState[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + dxDefineRasterizerState(pThisCC, pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_SAMPLER: + if (pBackendDXContext->papSamplerState) + { + for (uint32_t i = cValidEntries; i < pBackendDXContext->cSamplerState; ++i) + D3D_RELEASE(pBackendDXContext->papSamplerState[i]); + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->papSamplerState, &pBackendDXContext->cSamplerState, + sizeof(pBackendDXContext->papSamplerState[0]), pDXContext->cot.cSampler, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXSamplerEntry const *pEntry = &pDXContext->cot.paSampler[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + dxDefineSamplerState(pThisCC, pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_STREAMOUTPUT: + if (pBackendDXContext->paStreamOutput) + { + for (uint32_t i = cValidEntries; i < pBackendDXContext->cStreamOutput; ++i) + dxDestroyStreamOutput(&pBackendDXContext->paStreamOutput[i]); + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->paStreamOutput, &pBackendDXContext->cStreamOutput, + sizeof(pBackendDXContext->paStreamOutput[0]), pDXContext->cot.cStreamOutput, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXStreamOutputEntry const *pEntry = &pDXContext->cot.paStreamOutput[i]; + /** @todo The caller must verify the COTable content using same rules as when a new entry is defined. */ + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + /* Reset the stream output backend data. It will be re-created when a GS shader with this streamoutput + * will be set in setupPipeline. + */ + DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[i]; + dxDestroyStreamOutput(pDXStreamOutput); + } + break; + case SVGA_COTABLE_DXQUERY: + if (pBackendDXContext->paQuery) + { + /* Destroy the no longer used entries. */ + for (uint32_t i = cValidEntries; i < pBackendDXContext->cQuery; ++i) + dxDestroyQuery(&pBackendDXContext->paQuery[i]); + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->paQuery, &pBackendDXContext->cQuery, + sizeof(pBackendDXContext->paQuery[0]), pDXContext->cot.cQuery, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXQueryEntry const *pEntry = &pDXContext->cot.paQuery[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + /* Define queries which were not defined yet in backend. */ + DXQUERY *pDXQuery = &pBackendDXContext->paQuery[i]; + if ( pEntry->type != SVGA3D_QUERYTYPE_INVALID + && pDXQuery->pQuery == NULL) + dxDefineQuery(pThisCC, pDXContext, i, pEntry); + else + Assert(pEntry->type == SVGA3D_QUERYTYPE_INVALID || pDXQuery->pQuery); + } + break; + case SVGA_COTABLE_DXSHADER: + if (pBackendDXContext->paShader) + { + /* Destroy the no longer used entries. */ + for (uint32_t i = cValidEntries; i < pBackendDXContext->cShader; ++i) + dxDestroyShader(&pBackendDXContext->paShader[i]); + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->paShader, &pBackendDXContext->cShader, + sizeof(pBackendDXContext->paShader[0]), pDXContext->cot.cShader, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXShaderEntry const *pEntry = &pDXContext->cot.paShader[i]; + /** @todo The caller must verify the COTable content using same rules as when a new entry is defined. */ + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + /* Define shaders which were not defined yet in backend. */ + DXSHADER *pDXShader = &pBackendDXContext->paShader[i]; + if ( pEntry->type != SVGA3D_SHADERTYPE_INVALID + && pDXShader->enmShaderType == SVGA3D_SHADERTYPE_INVALID) + dxDefineShader(pDXContext, i, pEntry); + else + Assert(pEntry->type == pDXShader->enmShaderType); + + } + break; + case SVGA_COTABLE_UAVIEW: + if (pBackendDXContext->paUnorderedAccessView) + { + for (uint32_t i = 0; i < pBackendDXContext->cUnorderedAccessView; ++i) + { + DXVIEW *pDXView = &pBackendDXContext->paUnorderedAccessView[i]; + if (i < cValidEntries) + dxViewRemoveFromList(pDXView); /* Remove from list because DXVIEW array will be reallocated. */ + else + dxViewDestroy(pDXView); + } + } + + rc = dxCOTableRealloc((void **)&pBackendDXContext->paUnorderedAccessView, &pBackendDXContext->cUnorderedAccessView, + sizeof(pBackendDXContext->paUnorderedAccessView[0]), pDXContext->cot.cUAView, cValidEntries); + AssertRCBreak(rc); + + for (uint32_t i = 0; i < cValidEntries; ++i) + { + SVGACOTableDXUAViewEntry const *pEntry = &pDXContext->cot.paUAView[i]; + if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) + continue; /* Skip uninitialized entry. */ + + /* Define views which were not defined yet in backend. */ + DXVIEW *pDXView = &pBackendDXContext->paUnorderedAccessView[i]; + /** @todo Verify that the pEntry content still corresponds to the view. */ + if (pDXView->u.pView) + dxViewAddToList(pThisCC, pDXView); + else if (pDXView->enmViewType == VMSVGA3D_VIEWTYPE_NONE) + dxDefineUnorderedAccessView(pThisCC, pDXContext, i, pEntry); + } + break; + case SVGA_COTABLE_MAX: break; /* Compiler warning */ + } + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXBufferCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSurfaceCopyAndReadback(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXMoveQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXBindAllShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXHint(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXBufferUpdate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXCondBindAllShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackScreenCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackIntraSurfaceCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceImageId const &surface, SVGA3dCopyBox const &box) +{ + RT_NOREF(pDXContext); + + LogFunc(("sid %u\n", surface.sid)); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DBACKEND pBackend = pState->pBackend; + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, surface.sid, &pSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, surface.face, surface.mipmap, &pMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + /* Clip the box. */ + SVGA3dCopyBox clipBox = box; + vmsvgaR3ClipCopyBox(&pMipLevel->mipmapSize, &pMipLevel->mipmapSize, &clipBox); + + LogFunc(("surface%s cid %d\n", + pSurface->pBackendSurface ? "" : " sysmem", + pSurface ? pSurface->idAssociatedContext : SVGA_ID_INVALID)); + + if (pSurface->pBackendSurface) + { + /* Surface -> Surface. */ + DXDEVICE *pDXDevice = &pBackend->dxDevice; + + UINT DstSubresource = vmsvga3dCalcSubresource(surface.mipmap, surface.face, pSurface->cLevels); + UINT DstX = clipBox.x; + UINT DstY = clipBox.y; + UINT DstZ = clipBox.z; + + UINT SrcSubresource = DstSubresource; + D3D11_BOX SrcBox; + SrcBox.left = clipBox.srcx; + SrcBox.top = clipBox.srcy; + SrcBox.front = clipBox.srcz; + SrcBox.right = clipBox.srcx + clipBox.w; + SrcBox.bottom = clipBox.srcy + clipBox.h; + SrcBox.back = clipBox.srcz + clipBox.d; + + ID3D11Resource *pDstResource; + ID3D11Resource *pSrcResource; + pDstResource = dxResource(pState, pSurface, NULL); + pSrcResource = pDstResource; + + pDXDevice->pImmediateContext->CopySubresourceRegion1(pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, &SrcBox, 0); + } + else + { + /* Memory -> Memory. */ + uint32_t const cxBlocks = (clipBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock; + uint32_t const cyBlocks = (clipBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock; + uint32_t const cbRow = cxBlocks * pSurface->cbBlock; + + uint8_t const *pu8Src = (uint8_t *)pMipLevel->pSurfaceData + + (clipBox.srcx / pSurface->cxBlock) * pSurface->cbBlock + + (clipBox.srcy / pSurface->cyBlock) * pMipLevel->cbSurfacePitch + + clipBox.srcz * pMipLevel->cbSurfacePlane; + + uint8_t *pu8Dst = (uint8_t *)pMipLevel->pSurfaceData + + (clipBox.x / pSurface->cxBlock) * pSurface->cbBlock + + (clipBox.y / pSurface->cyBlock) * pMipLevel->cbSurfacePitch + + clipBox.z * pMipLevel->cbSurfacePlane; + + for (uint32_t z = 0; z < clipBox.d; ++z) + { + uint8_t const *pu8PlaneSrc = pu8Src; + uint8_t *pu8PlaneDst = pu8Dst; + + for (uint32_t y = 0; y < cyBlocks; ++y) + { + memmove(pu8PlaneDst, pu8PlaneSrc, cbRow); + pu8PlaneDst += pMipLevel->cbSurfacePitch; + pu8PlaneSrc += pMipLevel->cbSurfacePitch; + } + + pu8Src += pMipLevel->cbSurfacePlane; + pu8Dst += pMipLevel->cbSurfacePlane; + } + } + + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXResolveCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXPredResolveCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXPredConvertRegion(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXPredConvert(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackWholeSurfaceCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static int dxDefineUnorderedAccessView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, SVGACOTableDXUAViewEntry const *pEntry) +{ + /* Get corresponding resource for pEntry->sid. Create the surface if does not yet exist. */ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pEntry->sid, &pSurface); + AssertRCReturn(rc, rc); + + ID3D11UnorderedAccessView *pUnorderedAccessView; + DXVIEW *pView = &pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]; + Assert(pView->u.pView == NULL); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the actual texture or buffer. */ + /** @todo One function to create all resources from surfaces. */ + if (pSurface->format != SVGA3D_BUFFER) + rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSurface); + else + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); + + AssertRCReturn(rc, rc); + } + + HRESULT hr = dxUnorderedAccessViewCreate(pThisCC, pDXContext, pEntry, pSurface, &pUnorderedAccessView); + AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); + + return dxViewInit(pView, pSurface, pDXContext, uaViewId, VMSVGA3D_VIEWTYPE_UNORDEREDACCESS, pUnorderedAccessView); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDefineUAView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, SVGACOTableDXUAViewEntry const *pEntry) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /** @todo Probably not necessary because UAVs are defined in setupPipeline. */ + return dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pEntry); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDestroyUAView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + return dxViewDestroy(&pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]); +} + + +static DECLCALLBACK(int) vmsvga3dBackDXClearUAViewUint(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, uint32_t const aValues[4]) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + DXVIEW *pDXView = &pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]; + if (!pDXView->u.pUnorderedAccessView) + { + /* (Re-)create the view, because a creation of a view is deferred until a draw or a clear call. */ + SVGACOTableDXUAViewEntry const *pEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); + int rc = dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pEntry); + AssertRCReturn(rc, rc); + } + pDevice->pImmediateContext->ClearUnorderedAccessViewUint(pDXView->u.pUnorderedAccessView, aValues); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXClearUAViewFloat(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, float const aValues[4]) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + DXVIEW *pDXView = &pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]; + if (!pDXView->u.pUnorderedAccessView) + { + /* (Re-)create the view, because a creation of a view is deferred until a draw or a clear call. */ + SVGACOTableDXUAViewEntry const *pEntry = &pDXContext->cot.paUAView[uaViewId]; + int rc = dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pEntry); + AssertRCReturn(rc, rc); + } + pDevice->pImmediateContext->ClearUnorderedAccessViewFloat(pDXView->u.pUnorderedAccessView, aValues); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXCopyStructureCount(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId srcUAViewId, SVGA3dSurfaceId destSid, uint32_t destByteOffset) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* Get corresponding resource. Create the buffer if does not yet exist. */ + ID3D11Buffer *pDstBuffer; + if (destSid != SVGA3D_INVALID_ID) + { + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, destSid, &pSurface); + AssertRCReturn(rc, rc); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the resource and initialize it with the current surface data. */ + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); + AssertRCReturn(rc, rc); + } + + pDstBuffer = pSurface->pBackendSurface->u.pBuffer; + } + else + pDstBuffer = NULL; + + ID3D11UnorderedAccessView *pSrcView; + if (srcUAViewId != SVGA3D_INVALID_ID) + { + DXVIEW *pDXView = &pDXContext->pBackendDXContext->paUnorderedAccessView[srcUAViewId]; + AssertReturn(pDXView->u.pUnorderedAccessView, VERR_INVALID_STATE); + pSrcView = pDXView->u.pUnorderedAccessView; + } + else + pSrcView = NULL; + + pDevice->pImmediateContext->CopyStructureCount(pDstBuffer, destByteOffset, pSrcView); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetUAViews(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t uavSpliceIndex, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(uavSpliceIndex, cUAViewId, paUAViewId); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDrawIndexedInstancedIndirect(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId argsBufferSid, uint32_t byteOffsetForArgs) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* Get corresponding resource. Create the buffer if does not yet exist. */ + ID3D11Buffer *pBufferForArgs; + if (argsBufferSid != SVGA_ID_INVALID) + { + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, argsBufferSid, &pSurface); + AssertRCReturn(rc, rc); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the resource and initialize it with the current surface data. */ + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); + AssertRCReturn(rc, rc); + } + + pBufferForArgs = pSurface->pBackendSurface->u.pBuffer; + } + else + pBufferForArgs = NULL; + + dxSetupPipeline(pThisCC, pDXContext); + + Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); + + pDevice->pImmediateContext->DrawIndexedInstancedIndirect(pBufferForArgs, byteOffsetForArgs); + + /* Note which surfaces are being drawn. */ + dxTrackRenderTargets(pThisCC, pDXContext); + +#ifdef DX_FLUSH_AFTER_DRAW + dxDeviceFlush(pDevice); +#endif + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDrawInstancedIndirect(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId argsBufferSid, uint32_t byteOffsetForArgs) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + /* Get corresponding resource. Create the buffer if does not yet exist. */ + ID3D11Buffer *pBufferForArgs; + if (argsBufferSid != SVGA_ID_INVALID) + { + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, argsBufferSid, &pSurface); + AssertRCReturn(rc, rc); + + if (pSurface->pBackendSurface == NULL) + { + /* Create the resource and initialize it with the current surface data. */ + rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); + AssertRCReturn(rc, rc); + } + + pBufferForArgs = pSurface->pBackendSurface->u.pBuffer; + } + else + pBufferForArgs = NULL; + + dxSetupPipeline(pThisCC, pDXContext); + + Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); + + pDevice->pImmediateContext->DrawInstancedIndirect(pBufferForArgs, byteOffsetForArgs); + + /* Note which surfaces are being drawn. */ + dxTrackRenderTargets(pThisCC, pDXContext); + +#ifdef DX_FLUSH_AFTER_DRAW + dxDeviceFlush(pDevice); +#endif + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDispatch(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + dxSetupPipeline(pThisCC, pDXContext); + + pDevice->pImmediateContext->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ); + +#ifdef DX_FLUSH_AFTER_DRAW + dxDeviceFlush(pDevice); +#endif + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXDispatchIndirect(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackWriteZeroSurface(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackHintZeroSurface(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXTransferToBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackLogicOpsBitBlt(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackLogicOpsTransBlt(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackLogicOpsStretchBlt(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackLogicOpsColorFill(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackLogicOpsAlphaBlend(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackLogicOpsClearTypeBlend(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static int dxSetCSUnorderedAccessViews(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + +//DEBUG_BREAKPOINT_TEST(); + uint32_t const *pUAIds = &pDXContext->svgaDXContext.csuaViewIds[0]; + ID3D11UnorderedAccessView *papUnorderedAccessView[SVGA3D_DX11_1_MAX_UAVIEWS]; + UINT aUAVInitialCounts[SVGA3D_DX11_1_MAX_UAVIEWS]; + for (uint32_t i = 0; i < SVGA3D_DX11_1_MAX_UAVIEWS; ++i) + { + SVGA3dUAViewId const uaViewId = pUAIds[i]; + if (uaViewId != SVGA3D_INVALID_ID) + { + ASSERT_GUEST_RETURN(uaViewId < pDXContext->pBackendDXContext->cUnorderedAccessView, VERR_INVALID_PARAMETER); + + DXVIEW *pDXView = &pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]; + Assert(pDXView->u.pUnorderedAccessView); + papUnorderedAccessView[i] = pDXView->u.pUnorderedAccessView; + + SVGACOTableDXUAViewEntry const *pEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); + aUAVInitialCounts[i] = pEntry->structureCount; + } + else + { + papUnorderedAccessView[i] = NULL; + aUAVInitialCounts[i] = (UINT)-1; + } + } + + dxCSUnorderedAccessViewSet(pDevice, 0, SVGA3D_DX11_1_MAX_UAVIEWS, papUnorderedAccessView, aUAVInitialCounts); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetCSUAViews(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startIndex, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + RT_NOREF(pBackend); + + DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); + AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); + + RT_NOREF(startIndex, cUAViewId, paUAViewId); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetMinLOD(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSetShaderIface(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackSurfaceStretchBltNonMSToMS(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXBindShaderIface(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; + + RT_NOREF(pBackend, pDXContext); + AssertFailed(); /** @todo Implement */ + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXLoadState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM) +{ + RT_NOREF(pThisCC); + uint32_t u32; + int rc; + + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertLogRelRCReturn(rc, rc); + AssertLogRelRCReturn(u32 == pDXContext->pBackendDXContext->cShader, VERR_INVALID_STATE); + + for (uint32_t i = 0; i < pDXContext->pBackendDXContext->cShader; ++i) + { + DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[i]; + + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertLogRelRCReturn(rc, rc); + AssertLogRelReturn((SVGA3dShaderType)u32 == pDXShader->enmShaderType, VERR_INVALID_STATE); + + if (pDXShader->enmShaderType == SVGA3D_SHADERTYPE_INVALID) + continue; + + pHlp->pfnSSMGetU32(pSSM, &pDXShader->soid); + + pHlp->pfnSSMGetU32(pSSM, &u32); + pDXShader->shaderInfo.enmProgramType = (VGPU10_PROGRAM_TYPE)u32; + + rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cbBytecode); + AssertLogRelRCReturn(rc, rc); + AssertLogRelReturn(pDXShader->shaderInfo.cbBytecode <= 2 * SVGA3D_MAX_SHADER_MEMORY_BYTES, VERR_INVALID_STATE); + + if (pDXShader->shaderInfo.cbBytecode) + { + pDXShader->shaderInfo.pvBytecode = RTMemAlloc(pDXShader->shaderInfo.cbBytecode); + AssertPtrReturn(pDXShader->shaderInfo.pvBytecode, VERR_NO_MEMORY); + pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.pvBytecode, pDXShader->shaderInfo.cbBytecode); + } + + rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cInputSignature); + AssertLogRelRCReturn(rc, rc); + AssertLogRelReturn(pDXShader->shaderInfo.cInputSignature <= 32, VERR_INVALID_STATE); + if (pDXShader->shaderInfo.cInputSignature) + pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.aInputSignature, pDXShader->shaderInfo.cInputSignature * sizeof(SVGA3dDXSignatureEntry)); + + rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cOutputSignature); + AssertLogRelRCReturn(rc, rc); + AssertLogRelReturn(pDXShader->shaderInfo.cOutputSignature <= 32, VERR_INVALID_STATE); + if (pDXShader->shaderInfo.cOutputSignature) + pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.aOutputSignature, pDXShader->shaderInfo.cOutputSignature * sizeof(SVGA3dDXSignatureEntry)); + + rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cPatchConstantSignature); + AssertLogRelRCReturn(rc, rc); + AssertLogRelReturn(pDXShader->shaderInfo.cPatchConstantSignature <= 32, VERR_INVALID_STATE); + if (pDXShader->shaderInfo.cPatchConstantSignature) + pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.aPatchConstantSignature, pDXShader->shaderInfo.cPatchConstantSignature * sizeof(SVGA3dDXSignatureEntry)); + + rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cDclResource); + AssertLogRelRCReturn(rc, rc); + AssertLogRelReturn(pDXShader->shaderInfo.cDclResource <= SVGA3D_DX_MAX_SRVIEWS, VERR_INVALID_STATE); + if (pDXShader->shaderInfo.cDclResource) + pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.aOffDclResource, pDXShader->shaderInfo.cDclResource * sizeof(uint32_t)); + + DXShaderGenerateSemantics(&pDXShader->shaderInfo); + } + + rc = pHlp->pfnSSMGetU32(pSSM, &pDXContext->pBackendDXContext->cSOTarget); + AssertLogRelRCReturn(rc, rc); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackDXSaveState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM) +{ + RT_NOREF(pThisCC); + int rc; + + pHlp->pfnSSMPutU32(pSSM, pDXContext->pBackendDXContext->cShader); + for (uint32_t i = 0; i < pDXContext->pBackendDXContext->cShader; ++i) + { + DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[i]; + + pHlp->pfnSSMPutU32(pSSM, (uint32_t)pDXShader->enmShaderType); + if (pDXShader->enmShaderType == SVGA3D_SHADERTYPE_INVALID) + continue; + + pHlp->pfnSSMPutU32(pSSM, pDXShader->soid); + + pHlp->pfnSSMPutU32(pSSM, (uint32_t)pDXShader->shaderInfo.enmProgramType); + + pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cbBytecode); + if (pDXShader->shaderInfo.cbBytecode) + pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.pvBytecode, pDXShader->shaderInfo.cbBytecode); + + pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cInputSignature); + if (pDXShader->shaderInfo.cInputSignature) + pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.aInputSignature, pDXShader->shaderInfo.cInputSignature * sizeof(SVGA3dDXSignatureEntry)); + + pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cOutputSignature); + if (pDXShader->shaderInfo.cOutputSignature) + pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.aOutputSignature, pDXShader->shaderInfo.cOutputSignature * sizeof(SVGA3dDXSignatureEntry)); + + pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cPatchConstantSignature); + if (pDXShader->shaderInfo.cPatchConstantSignature) + pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.aPatchConstantSignature, pDXShader->shaderInfo.cPatchConstantSignature * sizeof(SVGA3dDXSignatureEntry)); + + pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cDclResource); + if (pDXShader->shaderInfo.cDclResource) + pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.aOffDclResource, pDXShader->shaderInfo.cDclResource * sizeof(uint32_t)); + } + rc = pHlp->pfnSSMPutU32(pSSM, pDXContext->pBackendDXContext->cSOTarget); + AssertLogRelRCReturn(rc, rc); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackQueryInterface(PVGASTATECC pThisCC, char const *pszInterfaceName, void *pvInterfaceFuncs, size_t cbInterfaceFuncs) +{ + RT_NOREF(pThisCC); + + int rc = VINF_SUCCESS; + if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_DX) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSDX)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCSDX *p = (VMSVGA3DBACKENDFUNCSDX *)pvInterfaceFuncs; + p->pfnDXSaveState = vmsvga3dBackDXSaveState; + p->pfnDXLoadState = vmsvga3dBackDXLoadState; + p->pfnDXDefineContext = vmsvga3dBackDXDefineContext; + p->pfnDXDestroyContext = vmsvga3dBackDXDestroyContext; + p->pfnDXBindContext = vmsvga3dBackDXBindContext; + p->pfnDXSwitchContext = vmsvga3dBackDXSwitchContext; + p->pfnDXReadbackContext = vmsvga3dBackDXReadbackContext; + p->pfnDXInvalidateContext = vmsvga3dBackDXInvalidateContext; + p->pfnDXSetSingleConstantBuffer = vmsvga3dBackDXSetSingleConstantBuffer; + p->pfnDXSetShaderResources = vmsvga3dBackDXSetShaderResources; + p->pfnDXSetShader = vmsvga3dBackDXSetShader; + p->pfnDXSetSamplers = vmsvga3dBackDXSetSamplers; + p->pfnDXDraw = vmsvga3dBackDXDraw; + p->pfnDXDrawIndexed = vmsvga3dBackDXDrawIndexed; + p->pfnDXDrawInstanced = vmsvga3dBackDXDrawInstanced; + p->pfnDXDrawIndexedInstanced = vmsvga3dBackDXDrawIndexedInstanced; + p->pfnDXDrawAuto = vmsvga3dBackDXDrawAuto; + p->pfnDXSetInputLayout = vmsvga3dBackDXSetInputLayout; + p->pfnDXSetVertexBuffers = vmsvga3dBackDXSetVertexBuffers; + p->pfnDXSetIndexBuffer = vmsvga3dBackDXSetIndexBuffer; + p->pfnDXSetTopology = vmsvga3dBackDXSetTopology; + p->pfnDXSetRenderTargets = vmsvga3dBackDXSetRenderTargets; + p->pfnDXSetBlendState = vmsvga3dBackDXSetBlendState; + p->pfnDXSetDepthStencilState = vmsvga3dBackDXSetDepthStencilState; + p->pfnDXSetRasterizerState = vmsvga3dBackDXSetRasterizerState; + p->pfnDXDefineQuery = vmsvga3dBackDXDefineQuery; + p->pfnDXDestroyQuery = vmsvga3dBackDXDestroyQuery; + p->pfnDXBeginQuery = vmsvga3dBackDXBeginQuery; + p->pfnDXEndQuery = vmsvga3dBackDXEndQuery; + p->pfnDXSetPredication = vmsvga3dBackDXSetPredication; + p->pfnDXSetSOTargets = vmsvga3dBackDXSetSOTargets; + p->pfnDXSetViewports = vmsvga3dBackDXSetViewports; + p->pfnDXSetScissorRects = vmsvga3dBackDXSetScissorRects; + p->pfnDXClearRenderTargetView = vmsvga3dBackDXClearRenderTargetView; + p->pfnDXClearDepthStencilView = vmsvga3dBackDXClearDepthStencilView; + p->pfnDXPredCopyRegion = vmsvga3dBackDXPredCopyRegion; + p->pfnDXPredCopy = vmsvga3dBackDXPredCopy; + p->pfnDXPresentBlt = vmsvga3dBackDXPresentBlt; + p->pfnDXGenMips = vmsvga3dBackDXGenMips; + p->pfnDXDefineShaderResourceView = vmsvga3dBackDXDefineShaderResourceView; + p->pfnDXDestroyShaderResourceView = vmsvga3dBackDXDestroyShaderResourceView; + p->pfnDXDefineRenderTargetView = vmsvga3dBackDXDefineRenderTargetView; + p->pfnDXDestroyRenderTargetView = vmsvga3dBackDXDestroyRenderTargetView; + p->pfnDXDefineDepthStencilView = vmsvga3dBackDXDefineDepthStencilView; + p->pfnDXDestroyDepthStencilView = vmsvga3dBackDXDestroyDepthStencilView; + p->pfnDXDefineElementLayout = vmsvga3dBackDXDefineElementLayout; + p->pfnDXDestroyElementLayout = vmsvga3dBackDXDestroyElementLayout; + p->pfnDXDefineBlendState = vmsvga3dBackDXDefineBlendState; + p->pfnDXDestroyBlendState = vmsvga3dBackDXDestroyBlendState; + p->pfnDXDefineDepthStencilState = vmsvga3dBackDXDefineDepthStencilState; + p->pfnDXDestroyDepthStencilState = vmsvga3dBackDXDestroyDepthStencilState; + p->pfnDXDefineRasterizerState = vmsvga3dBackDXDefineRasterizerState; + p->pfnDXDestroyRasterizerState = vmsvga3dBackDXDestroyRasterizerState; + p->pfnDXDefineSamplerState = vmsvga3dBackDXDefineSamplerState; + p->pfnDXDestroySamplerState = vmsvga3dBackDXDestroySamplerState; + p->pfnDXDefineShader = vmsvga3dBackDXDefineShader; + p->pfnDXDestroyShader = vmsvga3dBackDXDestroyShader; + p->pfnDXBindShader = vmsvga3dBackDXBindShader; + p->pfnDXDefineStreamOutput = vmsvga3dBackDXDefineStreamOutput; + p->pfnDXDestroyStreamOutput = vmsvga3dBackDXDestroyStreamOutput; + p->pfnDXSetStreamOutput = vmsvga3dBackDXSetStreamOutput; + p->pfnDXSetCOTable = vmsvga3dBackDXSetCOTable; + p->pfnDXBufferCopy = vmsvga3dBackDXBufferCopy; + p->pfnDXSurfaceCopyAndReadback = vmsvga3dBackDXSurfaceCopyAndReadback; + p->pfnDXMoveQuery = vmsvga3dBackDXMoveQuery; + p->pfnDXBindAllShader = vmsvga3dBackDXBindAllShader; + p->pfnDXHint = vmsvga3dBackDXHint; + p->pfnDXBufferUpdate = vmsvga3dBackDXBufferUpdate; + p->pfnDXCondBindAllShader = vmsvga3dBackDXCondBindAllShader; + p->pfnScreenCopy = vmsvga3dBackScreenCopy; + p->pfnIntraSurfaceCopy = vmsvga3dBackIntraSurfaceCopy; + p->pfnDXResolveCopy = vmsvga3dBackDXResolveCopy; + p->pfnDXPredResolveCopy = vmsvga3dBackDXPredResolveCopy; + p->pfnDXPredConvertRegion = vmsvga3dBackDXPredConvertRegion; + p->pfnDXPredConvert = vmsvga3dBackDXPredConvert; + p->pfnWholeSurfaceCopy = vmsvga3dBackWholeSurfaceCopy; + p->pfnDXDefineUAView = vmsvga3dBackDXDefineUAView; + p->pfnDXDestroyUAView = vmsvga3dBackDXDestroyUAView; + p->pfnDXClearUAViewUint = vmsvga3dBackDXClearUAViewUint; + p->pfnDXClearUAViewFloat = vmsvga3dBackDXClearUAViewFloat; + p->pfnDXCopyStructureCount = vmsvga3dBackDXCopyStructureCount; + p->pfnDXSetUAViews = vmsvga3dBackDXSetUAViews; + p->pfnDXDrawIndexedInstancedIndirect = vmsvga3dBackDXDrawIndexedInstancedIndirect; + p->pfnDXDrawInstancedIndirect = vmsvga3dBackDXDrawInstancedIndirect; + p->pfnDXDispatch = vmsvga3dBackDXDispatch; + p->pfnDXDispatchIndirect = vmsvga3dBackDXDispatchIndirect; + p->pfnWriteZeroSurface = vmsvga3dBackWriteZeroSurface; + p->pfnHintZeroSurface = vmsvga3dBackHintZeroSurface; + p->pfnDXTransferToBuffer = vmsvga3dBackDXTransferToBuffer; + p->pfnLogicOpsBitBlt = vmsvga3dBackLogicOpsBitBlt; + p->pfnLogicOpsTransBlt = vmsvga3dBackLogicOpsTransBlt; + p->pfnLogicOpsStretchBlt = vmsvga3dBackLogicOpsStretchBlt; + p->pfnLogicOpsColorFill = vmsvga3dBackLogicOpsColorFill; + p->pfnLogicOpsAlphaBlend = vmsvga3dBackLogicOpsAlphaBlend; + p->pfnLogicOpsClearTypeBlend = vmsvga3dBackLogicOpsClearTypeBlend; + p->pfnDXSetCSUAViews = vmsvga3dBackDXSetCSUAViews; + p->pfnDXSetMinLOD = vmsvga3dBackDXSetMinLOD; + p->pfnDXSetShaderIface = vmsvga3dBackDXSetShaderIface; + p->pfnSurfaceStretchBltNonMSToMS = vmsvga3dBackSurfaceStretchBltNonMSToMS; + p->pfnDXBindShaderIface = vmsvga3dBackDXBindShaderIface; + p->pfnVBDXClearRenderTargetViewRegion = vmsvga3dBackVBDXClearRenderTargetViewRegion; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_MAP) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSMAP)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCSMAP *p = (VMSVGA3DBACKENDFUNCSMAP *)pvInterfaceFuncs; + p->pfnSurfaceMap = vmsvga3dBackSurfaceMap; + p->pfnSurfaceUnmap = vmsvga3dBackSurfaceUnmap; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_GBO) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSGBO)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCSGBO *p = (VMSVGA3DBACKENDFUNCSGBO *)pvInterfaceFuncs; + p->pfnScreenTargetBind = vmsvga3dScreenTargetBind; + p->pfnScreenTargetUpdate = vmsvga3dScreenTargetUpdate; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_3D) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCS3D)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCS3D *p = (VMSVGA3DBACKENDFUNCS3D *)pvInterfaceFuncs; + p->pfnInit = vmsvga3dBackInit; + p->pfnPowerOn = vmsvga3dBackPowerOn; + p->pfnTerminate = vmsvga3dBackTerminate; + p->pfnReset = vmsvga3dBackReset; + p->pfnQueryCaps = vmsvga3dBackQueryCaps; + p->pfnChangeMode = vmsvga3dBackChangeMode; + p->pfnCreateTexture = vmsvga3dBackCreateTexture; + p->pfnSurfaceDestroy = vmsvga3dBackSurfaceDestroy; + p->pfnSurfaceInvalidateImage = vmsvga3dBackSurfaceInvalidateImage; + p->pfnSurfaceCopy = vmsvga3dBackSurfaceCopy; + p->pfnSurfaceDMACopyBox = vmsvga3dBackSurfaceDMACopyBox; + p->pfnSurfaceStretchBlt = vmsvga3dBackSurfaceStretchBlt; + p->pfnUpdateHostScreenViewport = vmsvga3dBackUpdateHostScreenViewport; + p->pfnDefineScreen = vmsvga3dBackDefineScreen; + p->pfnDestroyScreen = vmsvga3dBackDestroyScreen; + p->pfnSurfaceBlitToScreen = vmsvga3dBackSurfaceBlitToScreen; + p->pfnSurfaceUpdateHeapBuffers = vmsvga3dBackSurfaceUpdateHeapBuffers; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_VGPU9) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSVGPU9)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCSVGPU9 *p = (VMSVGA3DBACKENDFUNCSVGPU9 *)pvInterfaceFuncs; + p->pfnContextDefine = vmsvga3dBackContextDefine; + p->pfnContextDestroy = vmsvga3dBackContextDestroy; + p->pfnSetTransform = vmsvga3dBackSetTransform; + p->pfnSetZRange = vmsvga3dBackSetZRange; + p->pfnSetRenderState = vmsvga3dBackSetRenderState; + p->pfnSetRenderTarget = vmsvga3dBackSetRenderTarget; + p->pfnSetTextureState = vmsvga3dBackSetTextureState; + p->pfnSetMaterial = vmsvga3dBackSetMaterial; + p->pfnSetLightData = vmsvga3dBackSetLightData; + p->pfnSetLightEnabled = vmsvga3dBackSetLightEnabled; + p->pfnSetViewPort = vmsvga3dBackSetViewPort; + p->pfnSetClipPlane = vmsvga3dBackSetClipPlane; + p->pfnCommandClear = vmsvga3dBackCommandClear; + p->pfnDrawPrimitives = vmsvga3dBackDrawPrimitives; + p->pfnSetScissorRect = vmsvga3dBackSetScissorRect; + p->pfnGenerateMipmaps = vmsvga3dBackGenerateMipmaps; + p->pfnShaderDefine = vmsvga3dBackShaderDefine; + p->pfnShaderDestroy = vmsvga3dBackShaderDestroy; + p->pfnShaderSet = vmsvga3dBackShaderSet; + p->pfnShaderSetConst = vmsvga3dBackShaderSetConst; + p->pfnOcclusionQueryCreate = vmsvga3dBackOcclusionQueryCreate; + p->pfnOcclusionQueryDelete = vmsvga3dBackOcclusionQueryDelete; + p->pfnOcclusionQueryBegin = vmsvga3dBackOcclusionQueryBegin; + p->pfnOcclusionQueryEnd = vmsvga3dBackOcclusionQueryEnd; + p->pfnOcclusionQueryGetData = vmsvga3dBackOcclusionQueryGetData; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else + rc = VERR_NOT_IMPLEMENTED; + return rc; +} + + +extern VMSVGA3DBACKENDDESC const g_BackendDX = +{ + "DX", + vmsvga3dBackQueryInterface +}; diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-savedstate.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-savedstate.cpp new file mode 100644 index 00000000..838be7cb --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-savedstate.cpp @@ -0,0 +1,464 @@ +/* $Id: DevVGA-SVGA3d-dx-savedstate.cpp $ */ +/** @file + * DevSVGA3d - VMWare SVGA device, 3D parts - DX backend saved state. + */ + +/* + * Copyright (C) 2022-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include +#include + +#include +#include + +#include /* required by DevVGA.h */ + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#include "DevVGA-SVGA3d-internal.h" +#include "DevVGA-SVGA-internal.h" + +/* + * Load + */ + +static int vmsvga3dDXLoadSurface(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM) +{ + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + int rc; + + uint32_t sid; + rc = pHlp->pfnSSMGetU32(pSSM, &sid); + AssertRCReturn(rc, rc); + + if (sid == SVGA3D_INVALID_ID) + return VINF_SUCCESS; + + /* Define the surface. */ + SVGAOTableSurfaceEntry entrySurface; + rc = vmsvgaR3OTableReadSurface(pThisCC->svga.pSvgaR3State, sid, &entrySurface); + AssertRCReturn(rc, rc); + + /** @todo fAllocMipLevels=false and alloc miplevels if there is data to be loaded. */ + rc = vmsvga3dSurfaceDefine(pThisCC, sid, entrySurface.surface1Flags, entrySurface.format, + entrySurface.multisampleCount, entrySurface.autogenFilter, + entrySurface.numMipLevels, &entrySurface.size, + entrySurface.arraySize, + /* fAllocMipLevels = */ true); + AssertRCReturn(rc, rc); + + PVMSVGA3DSURFACE pSurface = p3dState->papSurfaces[sid]; + AssertReturn(pSurface->id == sid, VERR_INTERNAL_ERROR); + + /* Load the surface fields which are not part of SVGAOTableSurfaceEntry. */ + pHlp->pfnSSMGetU32(pSSM, &pSurface->idAssociatedContext); + + /* Load miplevels data to the surface buffers. */ + for (uint32_t j = 0; j < pSurface->cLevels * pSurface->surfaceDesc.numArrayElements; j++) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j]; + + /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */ + Assert(pMipmapLevel->cbSurface); + AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR); + + /* Fetch the data present boolean first. */ + bool fDataPresent; + rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent); + AssertRCReturn(rc, rc); + + if (fDataPresent) + { + rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface); + AssertRCReturn(rc, rc); + + pMipmapLevel->fDirty = true; + pSurface->fDirty = true; + } + else + pMipmapLevel->fDirty = false; + } + + return VINF_SUCCESS; +} + +static int vmsvga3dDXLoadContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM) +{ + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + uint32_t u32; + int rc; + + uint32_t cid; + rc = pHlp->pfnSSMGetU32(pSSM, &cid); + AssertRCReturn(rc, rc); + + if (cid == SVGA3D_INVALID_ID) + return VINF_SUCCESS; + + /* Define the context. */ + rc = vmsvga3dDXDefineContext(pThisCC, cid); + AssertRCReturn(rc, rc); + + PVMSVGA3DDXCONTEXT pDXContext = p3dState->papDXContexts[cid]; + AssertReturn(pDXContext->cid == cid, VERR_INTERNAL_ERROR); + + /* Load the context. */ + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertRCReturn(rc, rc); + AssertReturn(u32 == sizeof(SVGADXContextMobFormat), VERR_INVALID_STATE); + + pHlp->pfnSSMGetMem(pSSM, &pDXContext->svgaDXContext, sizeof(SVGADXContextMobFormat)); + + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertLogRelRCReturn(rc, rc); + AssertReturn(u32 == RT_ELEMENTS(pDXContext->aCOTMobs), VERR_INVALID_STATE); + + for (unsigned i = 0; i < RT_ELEMENTS(pDXContext->aCOTMobs); ++i) + { + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertLogRelRCReturn(rc, rc); + pDXContext->aCOTMobs[i] = vmsvgaR3MobGet(pSvgaR3State, u32); + Assert(pDXContext->aCOTMobs[i] || u32 == SVGA_ID_INVALID); + } + + struct + { + SVGACOTableType COTableType; + uint32_t cbEntry; + uint32_t *pcEntries; + void **ppaEntries; + } cot[] = + { + {SVGA_COTABLE_RTVIEW, sizeof(SVGACOTableDXRTViewEntry), &pDXContext->cot.cRTView, (void **)&pDXContext->cot.paRTView}, + {SVGA_COTABLE_DSVIEW, sizeof(SVGACOTableDXDSViewEntry), &pDXContext->cot.cDSView, (void **)&pDXContext->cot.paDSView}, + {SVGA_COTABLE_SRVIEW, sizeof(SVGACOTableDXSRViewEntry), &pDXContext->cot.cSRView, (void **)&pDXContext->cot.paSRView}, + {SVGA_COTABLE_ELEMENTLAYOUT, sizeof(SVGACOTableDXElementLayoutEntry), &pDXContext->cot.cElementLayout, (void **)&pDXContext->cot.paElementLayout}, + {SVGA_COTABLE_BLENDSTATE, sizeof(SVGACOTableDXBlendStateEntry), &pDXContext->cot.cBlendState, (void **)&pDXContext->cot.paBlendState}, + {SVGA_COTABLE_DEPTHSTENCIL, sizeof(SVGACOTableDXDepthStencilEntry), &pDXContext->cot.cDepthStencil, (void **)&pDXContext->cot.paDepthStencil}, + {SVGA_COTABLE_RASTERIZERSTATE, sizeof(SVGACOTableDXRasterizerStateEntry), &pDXContext->cot.cRasterizerState, (void **)&pDXContext->cot.paRasterizerState}, + {SVGA_COTABLE_SAMPLER, sizeof(SVGACOTableDXSamplerEntry), &pDXContext->cot.cSampler, (void **)&pDXContext->cot.paSampler}, + {SVGA_COTABLE_STREAMOUTPUT, sizeof(SVGACOTableDXStreamOutputEntry), &pDXContext->cot.cStreamOutput, (void **)&pDXContext->cot.paStreamOutput}, + {SVGA_COTABLE_DXQUERY, sizeof(SVGACOTableDXQueryEntry), &pDXContext->cot.cQuery, (void **)&pDXContext->cot.paQuery}, + {SVGA_COTABLE_DXSHADER, sizeof(SVGACOTableDXShaderEntry), &pDXContext->cot.cShader, (void **)&pDXContext->cot.paShader}, + {SVGA_COTABLE_UAVIEW, sizeof(SVGACOTableDXUAViewEntry), &pDXContext->cot.cUAView, (void **)&pDXContext->cot.paUAView}, + }; + + AssertCompile(RT_ELEMENTS(cot) == RT_ELEMENTS(pDXContext->aCOTMobs)); + for (unsigned i = 0; i < RT_ELEMENTS(cot); ++i) + { + uint32_t cEntries; + pHlp->pfnSSMGetU32(pSSM, &cEntries); + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertRCReturn(rc, rc); + AssertReturn(u32 == cot[i].cbEntry, VERR_INVALID_STATE); + + *cot[i].pcEntries = cEntries; + *cot[i].ppaEntries = vmsvgaR3MobBackingStorePtr(pDXContext->aCOTMobs[cot[i].COTableType], 0); + + if (cEntries) + { + rc = pSvgaR3State->pFuncsDX->pfnDXSetCOTable(pThisCC, pDXContext, cot[i].COTableType, cEntries); + AssertLogRelRCReturn(rc, rc); + } + } + + rc = pSvgaR3State->pFuncsDX->pfnDXLoadState(pThisCC, pDXContext, pHlp, pSSM); + AssertRCReturn(rc, rc); + + return VINF_SUCCESS; +} + +int vmsvga3dDXLoadExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) +{ + RT_NOREF(pThis, uPass); + + if (uVersion < VGA_SAVEDSTATE_VERSION_VMSVGA_DX) + AssertFailedReturn(VERR_INVALID_STATE); + + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + int rc; + + /* + * VMSVGA3DSTATE + */ + pHlp->pfnSSMGetU32(pSSM, &p3dState->cSurfaces); + rc = pHlp->pfnSSMGetU32(pSSM, &p3dState->cDXContexts); + AssertRCReturn(rc, rc); + + /* + * Surfaces + */ + if (p3dState->cSurfaces) + { + p3dState->papSurfaces = (PVMSVGA3DSURFACE *)RTMemAlloc(p3dState->cSurfaces * sizeof(PVMSVGA3DSURFACE)); + AssertReturn(p3dState->papSurfaces, VERR_NO_MEMORY); + for (uint32_t i = 0; i < p3dState->cSurfaces; ++i) + { + p3dState->papSurfaces[i] = (PVMSVGA3DSURFACE)RTMemAllocZ(sizeof(VMSVGA3DSURFACE)); + AssertPtrReturn(p3dState->papSurfaces[i], VERR_NO_MEMORY); + p3dState->papSurfaces[i]->id = SVGA3D_INVALID_ID; + } + + for (uint32_t i = 0; i < p3dState->cSurfaces; ++i) + { + rc = vmsvga3dDXLoadSurface(pHlp, pThisCC, pSSM); + AssertRCReturn(rc, rc); + } + } + else + p3dState->papSurfaces = NULL; + + /* + * DX contexts + */ + if (p3dState->cDXContexts) + { + p3dState->papDXContexts = (PVMSVGA3DDXCONTEXT *)RTMemAlloc(p3dState->cDXContexts * sizeof(PVMSVGA3DDXCONTEXT)); + AssertReturn(p3dState->papDXContexts, VERR_NO_MEMORY); + for (uint32_t i = 0; i < p3dState->cDXContexts; ++i) + { + p3dState->papDXContexts[i] = (PVMSVGA3DDXCONTEXT)RTMemAllocZ(sizeof(VMSVGA3DDXCONTEXT)); + AssertPtrReturn(p3dState->papDXContexts[i], VERR_NO_MEMORY); + p3dState->papDXContexts[i]->cid = SVGA3D_INVALID_ID; + } + + for (uint32_t i = 0; i < p3dState->cDXContexts; ++i) + { + rc = vmsvga3dDXLoadContext(pHlp, pThisCC, pSSM); + AssertRCReturn(rc, rc); + } + } + else + p3dState->papDXContexts = NULL; + + if (pSvgaR3State->idDXContextCurrent != SVGA_ID_INVALID) + vmsvga3dDXSwitchContext(pThisCC, pSvgaR3State->idDXContextCurrent); + + return VINF_SUCCESS; +} + +/* + * Save + */ + +static int vmsvga3dDXSaveSurface(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DSURFACE pSurface) +{ + RT_NOREF(pThisCC); + int rc; + + rc = pHlp->pfnSSMPutU32(pSSM, pSurface->id); + AssertRCReturn(rc, rc); + + if (pSurface->id == SVGA3D_INVALID_ID) + return VINF_SUCCESS; + + /* Save the surface fields which are not part of SVGAOTableSurfaceEntry. */ + pHlp->pfnSSMPutU32(pSSM, pSurface->idAssociatedContext); + + for (uint32_t iArray = 0; iArray < pSurface->surfaceDesc.numArrayElements; ++iArray) + { + for (uint32_t iMipmap = 0; iMipmap < pSurface->cLevels; ++iMipmap) + { + uint32_t idx = iMipmap + iArray * pSurface->cLevels; + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx]; + + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + if (pMipmapLevel->pSurfaceData) + { + /* Data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, true); + AssertRCReturn(rc, rc); + + Assert(pMipmapLevel->cbSurface); + rc = pHlp->pfnSSMPutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface); + AssertRCReturn(rc, rc); + } + else + { + /* No data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, false); + AssertRCReturn(rc, rc); + } + } + else + { + SVGA3dSurfaceImageId image; + image.sid = pSurface->id; + image.face = iArray; + image.mipmap = iMipmap; + + VMSGA3D_BOX_DIMENSIONS dims; + rc = vmsvga3dGetBoxDimensions(pThisCC, &image, NULL, &dims); + AssertRCReturn(rc, rc); + + VMSVGA3D_MAPPED_SURFACE map; + rc = vmsvga3dSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map); + if (RT_SUCCESS(rc)) + { + /* Save mapped surface data. */ + pHlp->pfnSSMPutBool(pSSM, true); + if (map.cbRow == map.cbRowPitch) + { + rc = pHlp->pfnSSMPutMem(pSSM, map.pvData, pMipmapLevel->cbSurface); + AssertRCReturn(rc, rc); + } + else + { + uint8_t *pu8Map = (uint8_t *)map.pvData; + for (uint32_t z = 0; z < map.box.d; ++z) + { + uint8_t *pu8MapPlane = pu8Map; + for (uint32_t y = 0; y < dims.cyBlocks; ++y) + { + rc = pHlp->pfnSSMPutMem(pSSM, pu8MapPlane, dims.cbRow); + AssertRCReturn(rc, rc); + + pu8MapPlane += map.cbRowPitch; + } + pu8Map += map.cbDepthPitch; + } + } + + vmsvga3dSurfaceUnmap(pThisCC, &image, &map, false); + } + else + { + AssertFailed(); + + /* No data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, false); + AssertRCReturn(rc, rc); + } + } + } + } + + return VINF_SUCCESS; +} + +static int vmsvga3dDXSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DDXCONTEXT pDXContext) +{ + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + int rc; + + rc = pHlp->pfnSSMPutU32(pSSM, pDXContext->cid); + AssertRCReturn(rc, rc); + + if (pDXContext->cid == SVGA3D_INVALID_ID) + return VINF_SUCCESS; + + /* Save the context. */ + pHlp->pfnSSMPutU32(pSSM, sizeof(SVGADXContextMobFormat)); + pHlp->pfnSSMPutMem(pSSM, &pDXContext->svgaDXContext, sizeof(SVGADXContextMobFormat)); + + rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pDXContext->aCOTMobs)); + AssertLogRelRCReturn(rc, rc); + for (unsigned i = 0; i < RT_ELEMENTS(pDXContext->aCOTMobs); ++i) + { + uint32_t const mobId = vmsvgaR3MobId(pDXContext->aCOTMobs[i]); + rc = pHlp->pfnSSMPutU32(pSSM, mobId); + AssertLogRelRCReturn(rc, rc); + } + + struct + { + uint32_t cEntries; + uint32_t cbEntry; + void *paEntries; + } cot[] = + { + {pDXContext->cot.cRTView, sizeof(SVGACOTableDXRTViewEntry), pDXContext->cot.paRTView}, + {pDXContext->cot.cDSView, sizeof(SVGACOTableDXDSViewEntry), pDXContext->cot.paDSView}, + {pDXContext->cot.cSRView, sizeof(SVGACOTableDXSRViewEntry), pDXContext->cot.paSRView}, + {pDXContext->cot.cElementLayout, sizeof(SVGACOTableDXElementLayoutEntry), pDXContext->cot.paElementLayout}, + {pDXContext->cot.cBlendState, sizeof(SVGACOTableDXBlendStateEntry), pDXContext->cot.paBlendState}, + {pDXContext->cot.cDepthStencil, sizeof(SVGACOTableDXDepthStencilEntry), pDXContext->cot.paDepthStencil}, + {pDXContext->cot.cRasterizerState, sizeof(SVGACOTableDXRasterizerStateEntry), pDXContext->cot.paRasterizerState}, + {pDXContext->cot.cSampler, sizeof(SVGACOTableDXSamplerEntry), pDXContext->cot.paSampler}, + {pDXContext->cot.cStreamOutput, sizeof(SVGACOTableDXStreamOutputEntry), pDXContext->cot.paStreamOutput}, + {pDXContext->cot.cQuery, sizeof(SVGACOTableDXQueryEntry), pDXContext->cot.paQuery}, + {pDXContext->cot.cShader, sizeof(SVGACOTableDXShaderEntry), pDXContext->cot.paShader}, + {pDXContext->cot.cUAView, sizeof(SVGACOTableDXUAViewEntry), pDXContext->cot.paUAView}, + }; + + AssertCompile(RT_ELEMENTS(cot) == RT_ELEMENTS(pDXContext->aCOTMobs)); + for (unsigned i = 0; i < RT_ELEMENTS(cot); ++i) + { + pHlp->pfnSSMPutU32(pSSM, cot[i].cEntries); + rc = pHlp->pfnSSMPutU32(pSSM, cot[i].cbEntry); + AssertLogRelRCReturn(rc, rc); + } + + rc = pSvgaR3State->pFuncsDX->pfnDXSaveState(pThisCC, pDXContext, pHlp, pSSM); + AssertRCReturn(rc, rc); + + return VINF_SUCCESS; +} + +int vmsvga3dDXSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM) +{ + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + int rc; + + /* + * VMSVGA3DSTATE + */ + pHlp->pfnSSMPutU32(pSSM, p3dState->cSurfaces); + rc = pHlp->pfnSSMPutU32(pSSM, p3dState->cDXContexts); + AssertRCReturn(rc, rc); + + /* + * Surfaces + */ + for (uint32_t sid = 0; sid < p3dState->cSurfaces; ++sid) + { + rc = vmsvga3dDXSaveSurface(pHlp, pThisCC, pSSM, p3dState->papSurfaces[sid]); + AssertRCReturn(rc, rc); + } + + /* + * DX contexts + */ + for (uint32_t cid = 0; cid < p3dState->cDXContexts; ++cid) + { + rc = vmsvga3dDXSaveContext(pHlp, pThisCC, pSSM, p3dState->papDXContexts[cid]); + AssertRCReturn(rc, rc); + } + + return VINF_SUCCESS; +} diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-shader.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-shader.cpp new file mode 100644 index 00000000..7634b2cc --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-shader.cpp @@ -0,0 +1,3056 @@ +/* $Id: DevVGA-SVGA3d-dx-shader.cpp $ */ +/** @file + * DevVMWare - VMWare SVGA device - VGPU10+ (DX) shader utilities. + */ + +/* + * Copyright (C) 2020-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include + +#include +#include +#include +#include +#include + +#include "DevVGA-SVGA3d-dx-shader.h" + +#ifdef RT_OS_WINDOWS +#include +#else +#define D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM 2 +#define D3D11_SB_EXTENDED_OPCODE_RESOURCE_RETURN_TYPE 3 +#endif + +/* + * + * DXBC shader binary format definitions. + * + */ + +/* DXBC container header. */ +typedef struct DXBCHeader +{ + uint32_t u32DXBC; /* 0x43425844 = 'D', 'X', 'B', 'C' */ + uint8_t au8Hash[16]; /* Modified MD5 hash. See dxbcHash. */ + uint32_t u32Version; /* 1 */ + uint32_t cbTotal; /* Total size in bytes. Including the header. */ + uint32_t cBlob; /* Number of entries in aBlobOffset array. */ + uint32_t aBlobOffset[1]; /* Offsets of blobs from the start of DXBC header. */ +} DXBCHeader; + +#define DXBC_MAGIC RT_MAKE_U32_FROM_U8('D', 'X', 'B', 'C') + +/* DXBC blob header. */ +typedef struct DXBCBlobHeader +{ + uint32_t u32BlobType; /* FourCC code. DXBC_BLOB_TYPE_* */ + uint32_t cbBlob; /* Size of the blob excluding the blob header. 4 bytes aligned. */ + /* Followed by the blob's data. */ +} DXBCBlobHeader; + +/* DXBC blob types. */ +#define DXBC_BLOB_TYPE_ISGN RT_MAKE_U32_FROM_U8('I', 'S', 'G', 'N') +#define DXBC_BLOB_TYPE_OSGN RT_MAKE_U32_FROM_U8('O', 'S', 'G', 'N') +#define DXBC_BLOB_TYPE_PCSG RT_MAKE_U32_FROM_U8('P', 'C', 'S', 'G') +#define DXBC_BLOB_TYPE_SHDR RT_MAKE_U32_FROM_U8('S', 'H', 'D', 'R') +/** @todo More... */ + +/* 'SHDR' blob data format. */ +typedef struct DXBCBlobSHDR +{ + VGPU10ProgramToken programToken; + uint32_t cToken; /* Number of 32 bit tokens including programToken and cToken. */ + uint32_t au32Token[1]; /* cToken - 2 number of tokens. */ +} DXBCBlobSHDR; + +/* Element of an input or output signature. */ +typedef struct DXBCBlobIOSGNElement +{ + uint32_t offElementName; /* Offset of the semantic's name relative to the start of the blob data. */ + uint32_t idxSemantic; /* Semantic index. */ + uint32_t enmSystemValue; /* SVGA3dDXSignatureSemanticName */ + uint32_t enmComponentType; /* 1 - unsigned, 2 - integer, 3 - float. */ + uint32_t idxRegister; /* Shader register index. Elements must be sorted by register index. */ + union + { + struct + { + uint32_t mask : 8; /* Component mask. Lower 4 bits represent X, Y, Z, W channels. */ + uint32_t mask2 : 8; /* Which components are used in the shader. */ + uint32_t pad : 16; + } m; + uint32_t mask; + } u; +} DXBCBlobIOSGNElement; + +/* 'ISGN' and 'OSGN' blob data format. */ +typedef struct DXBCBlobIOSGN +{ + uint32_t cElement; /* Number of signature elements. */ + uint32_t offElement; /* Offset of the first element from the start of the blob. Equals to 8. */ + DXBCBlobIOSGNElement aElement[1]; /* Signature elements. Size is cElement. */ + /* Followed by ASCIIZ semantic names. */ +} DXBCBlobIOSGN; + + +/* + * VGPU10 shader parser definitions. + */ + +/* Parsed info about an operand index. */ +typedef struct VGPUOperandIndex +{ + uint32_t indexRepresentation; /* VGPU10_OPERAND_INDEX_REPRESENTATION */ + uint64_t iOperandImmediate; /* Needs up to a qword. */ + struct VGPUOperand *pOperandRelative; /* For VGPU10_OPERAND_INDEX_*RELATIVE */ +} VGPUOperandIndex; + +/* Parsed info about an operand. */ +typedef struct VGPUOperand +{ + uint32_t numComponents : 2; /* VGPU10_OPERAND_NUM_COMPONENTS */ + uint32_t selectionMode : 2; /* VGPU10_OPERAND_4_COMPONENT_SELECTION_MODE */ + uint32_t mask : 4; /* 4-bits X, Y, Z, W mask for VGPU10_OPERAND_4_COMPONENT_MASK_MODE. */ + uint32_t operandType : 8; /* VGPU10_OPERAND_TYPE */ + uint32_t indexDimension : 2; /* VGPU10_OPERAND_INDEX_DIMENSION */ + VGPUOperandIndex aOperandIndex[VGPU10_OPERAND_INDEX_3D]; /* Up to 3. */ + uint32_t aImm[4]; /* Immediate values for VGPU10_OPERAND_TYPE_IMMEDIATE* */ + uint32_t cOperandToken; /* Number of tokens in this operand. */ + uint32_t const *paOperandToken; /* Pointer to operand tokens in the input buffer. */ +} VGPUOperand; + +/* Parsed info about an opcode. */ +typedef struct VGPUOpcode +{ + uint32_t cOpcodeToken; /* Number of tokens for this operation. */ + uint32_t opcodeType; /* VGPU10_OPCODE_* */ + uint32_t opcodeSubtype; /* For example VGPU10_VMWARE_OPCODE_* */ + uint32_t semanticName; /* SVGA3dDXSignatureSemanticName for system value declarations. */ + uint32_t cOperand; /* Number of operands for this instruction. */ + uint32_t aIdxOperand[8]; /* Indices of the instruction operands in the aValOperand array. */ + /* 8 should be enough for everyone. */ + VGPUOperand aValOperand[16]; /* Operands including VGPU10_OPERAND_INDEX_*RELATIVE if they are used: */ + /* Operand1, VGPU10_OPERAND_INDEX_*RELATIVE for Operand1, ... */ + /* ... */ + /* OperandN, VGPU10_OPERAND_INDEX_*RELATIVE for OperandN, ... */ + /* 16 probably should be enough for everyone. */ + uint32_t const *paOpcodeToken; /* Pointer to opcode tokens in the input buffer. */ +} VGPUOpcode; + +typedef struct VGPUOpcodeInfo +{ + uint32_t cOperand; /* Number of operands for this opcode. */ +} VGPUOpcodeInfo; + +static VGPUOpcodeInfo const g_aOpcodeInfo[] = +{ + { 3 }, /* VGPU10_OPCODE_ADD */ + { 3 }, /* VGPU10_OPCODE_AND */ + { 0 }, /* VGPU10_OPCODE_BREAK */ + { 1 }, /* VGPU10_OPCODE_BREAKC */ + { 1 }, /* VGPU10_OPCODE_CALL */ + { 2 }, /* VGPU10_OPCODE_CALLC */ + { 1 }, /* VGPU10_OPCODE_CASE */ + { 0 }, /* VGPU10_OPCODE_CONTINUE */ + { 1 }, /* VGPU10_OPCODE_CONTINUEC */ + { 0 }, /* VGPU10_OPCODE_CUT */ + { 0 }, /* VGPU10_OPCODE_DEFAULT */ + { 2 }, /* VGPU10_OPCODE_DERIV_RTX */ + { 2 }, /* VGPU10_OPCODE_DERIV_RTY */ + { 1 }, /* VGPU10_OPCODE_DISCARD */ + { 3 }, /* VGPU10_OPCODE_DIV */ + { 3 }, /* VGPU10_OPCODE_DP2 */ + { 3 }, /* VGPU10_OPCODE_DP3 */ + { 3 }, /* VGPU10_OPCODE_DP4 */ + { 0 }, /* VGPU10_OPCODE_ELSE */ + { 0 }, /* VGPU10_OPCODE_EMIT */ + { 0 }, /* VGPU10_OPCODE_EMITTHENCUT */ + { 0 }, /* VGPU10_OPCODE_ENDIF */ + { 0 }, /* VGPU10_OPCODE_ENDLOOP */ + { 0 }, /* VGPU10_OPCODE_ENDSWITCH */ + { 3 }, /* VGPU10_OPCODE_EQ */ + { 2 }, /* VGPU10_OPCODE_EXP */ + { 2 }, /* VGPU10_OPCODE_FRC */ + { 2 }, /* VGPU10_OPCODE_FTOI */ + { 2 }, /* VGPU10_OPCODE_FTOU */ + { 3 }, /* VGPU10_OPCODE_GE */ + { 3 }, /* VGPU10_OPCODE_IADD */ + { 1 }, /* VGPU10_OPCODE_IF */ + { 3 }, /* VGPU10_OPCODE_IEQ */ + { 3 }, /* VGPU10_OPCODE_IGE */ + { 3 }, /* VGPU10_OPCODE_ILT */ + { 4 }, /* VGPU10_OPCODE_IMAD */ + { 3 }, /* VGPU10_OPCODE_IMAX */ + { 3 }, /* VGPU10_OPCODE_IMIN */ + { 4 }, /* VGPU10_OPCODE_IMUL */ + { 3 }, /* VGPU10_OPCODE_INE */ + { 2 }, /* VGPU10_OPCODE_INEG */ + { 3 }, /* VGPU10_OPCODE_ISHL */ + { 3 }, /* VGPU10_OPCODE_ISHR */ + { 2 }, /* VGPU10_OPCODE_ITOF */ + { 1 }, /* VGPU10_OPCODE_LABEL */ + { 3 }, /* VGPU10_OPCODE_LD */ + { 4 }, /* VGPU10_OPCODE_LD_MS */ + { 2 }, /* VGPU10_OPCODE_LOG */ + { 0 }, /* VGPU10_OPCODE_LOOP */ + { 3 }, /* VGPU10_OPCODE_LT */ + { 4 }, /* VGPU10_OPCODE_MAD */ + { 3 }, /* VGPU10_OPCODE_MIN */ + { 3 }, /* VGPU10_OPCODE_MAX */ + { UINT32_MAX }, /* VGPU10_OPCODE_CUSTOMDATA: special opcode */ + { 2 }, /* VGPU10_OPCODE_MOV */ + { 4 }, /* VGPU10_OPCODE_MOVC */ + { 3 }, /* VGPU10_OPCODE_MUL */ + { 3 }, /* VGPU10_OPCODE_NE */ + { 0 }, /* VGPU10_OPCODE_NOP */ + { 2 }, /* VGPU10_OPCODE_NOT */ + { 3 }, /* VGPU10_OPCODE_OR */ + { 3 }, /* VGPU10_OPCODE_RESINFO */ + { 0 }, /* VGPU10_OPCODE_RET */ + { 1 }, /* VGPU10_OPCODE_RETC */ + { 2 }, /* VGPU10_OPCODE_ROUND_NE */ + { 2 }, /* VGPU10_OPCODE_ROUND_NI */ + { 2 }, /* VGPU10_OPCODE_ROUND_PI */ + { 2 }, /* VGPU10_OPCODE_ROUND_Z */ + { 2 }, /* VGPU10_OPCODE_RSQ */ + { 4 }, /* VGPU10_OPCODE_SAMPLE */ + { 5 }, /* VGPU10_OPCODE_SAMPLE_C */ + { 5 }, /* VGPU10_OPCODE_SAMPLE_C_LZ */ + { 5 }, /* VGPU10_OPCODE_SAMPLE_L */ + { 6 }, /* VGPU10_OPCODE_SAMPLE_D */ + { 5 }, /* VGPU10_OPCODE_SAMPLE_B */ + { 2 }, /* VGPU10_OPCODE_SQRT */ + { 1 }, /* VGPU10_OPCODE_SWITCH */ + { 3 }, /* VGPU10_OPCODE_SINCOS */ + { 4 }, /* VGPU10_OPCODE_UDIV */ + { 3 }, /* VGPU10_OPCODE_ULT */ + { 3 }, /* VGPU10_OPCODE_UGE */ + { 4 }, /* VGPU10_OPCODE_UMUL */ + { 4 }, /* VGPU10_OPCODE_UMAD */ + { 3 }, /* VGPU10_OPCODE_UMAX */ + { 3 }, /* VGPU10_OPCODE_UMIN */ + { 3 }, /* VGPU10_OPCODE_USHR */ + { 2 }, /* VGPU10_OPCODE_UTOF */ + { 3 }, /* VGPU10_OPCODE_XOR */ + { 1 }, /* VGPU10_OPCODE_DCL_RESOURCE */ + { 1 }, /* VGPU10_OPCODE_DCL_CONSTANT_BUFFER */ + { 1 }, /* VGPU10_OPCODE_DCL_SAMPLER */ + { 1 }, /* VGPU10_OPCODE_DCL_INDEX_RANGE */ + { 0 }, /* VGPU10_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY */ + { 0 }, /* VGPU10_OPCODE_DCL_GS_INPUT_PRIMITIVE */ + { 0 }, /* VGPU10_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT */ + { 1 }, /* VGPU10_OPCODE_DCL_INPUT */ + { 1 }, /* VGPU10_OPCODE_DCL_INPUT_SGV */ + { 1 }, /* VGPU10_OPCODE_DCL_INPUT_SIV */ + { 1 }, /* VGPU10_OPCODE_DCL_INPUT_PS */ + { 1 }, /* VGPU10_OPCODE_DCL_INPUT_PS_SGV */ + { 1 }, /* VGPU10_OPCODE_DCL_INPUT_PS_SIV */ + { 1 }, /* VGPU10_OPCODE_DCL_OUTPUT */ + { 1 }, /* VGPU10_OPCODE_DCL_OUTPUT_SGV */ + { 1 }, /* VGPU10_OPCODE_DCL_OUTPUT_SIV */ + { 0 }, /* VGPU10_OPCODE_DCL_TEMPS */ + { 0 }, /* VGPU10_OPCODE_DCL_INDEXABLE_TEMP */ + { 0 }, /* VGPU10_OPCODE_DCL_GLOBAL_FLAGS */ + { UINT32_MAX }, /* VGPU10_OPCODE_VMWARE: special opcode */ + { 4 }, /* VGPU10_OPCODE_LOD */ + { 4 }, /* VGPU10_OPCODE_GATHER4 */ + { 3 }, /* VGPU10_OPCODE_SAMPLE_POS */ + { 2 }, /* VGPU10_OPCODE_SAMPLE_INFO */ + { UINT32_MAX }, /* VGPU10_OPCODE_RESERVED1: special opcode */ + { 0 }, /* VGPU10_OPCODE_HS_DECLS */ + { 0 }, /* VGPU10_OPCODE_HS_CONTROL_POINT_PHASE */ + { 0 }, /* VGPU10_OPCODE_HS_FORK_PHASE */ + { 0 }, /* VGPU10_OPCODE_HS_JOIN_PHASE */ + { 1 }, /* VGPU10_OPCODE_EMIT_STREAM */ + { 1 }, /* VGPU10_OPCODE_CUT_STREAM */ + { 1 }, /* VGPU10_OPCODE_EMITTHENCUT_STREAM */ + { 1 }, /* VGPU10_OPCODE_INTERFACE_CALL */ + { 2 }, /* VGPU10_OPCODE_BUFINFO */ + { 2 }, /* VGPU10_OPCODE_DERIV_RTX_COARSE */ + { 2 }, /* VGPU10_OPCODE_DERIV_RTX_FINE */ + { 2 }, /* VGPU10_OPCODE_DERIV_RTY_COARSE */ + { 2 }, /* VGPU10_OPCODE_DERIV_RTY_FINE */ + { 5 }, /* VGPU10_OPCODE_GATHER4_C */ + { 5 }, /* VGPU10_OPCODE_GATHER4_PO */ + { 6 }, /* VGPU10_OPCODE_GATHER4_PO_C */ + { 2 }, /* VGPU10_OPCODE_RCP */ + { 2 }, /* VGPU10_OPCODE_F32TOF16 */ + { 2 }, /* VGPU10_OPCODE_F16TOF32 */ + { 4 }, /* VGPU10_OPCODE_UADDC */ + { 4 }, /* VGPU10_OPCODE_USUBB */ + { 2 }, /* VGPU10_OPCODE_COUNTBITS */ + { 2 }, /* VGPU10_OPCODE_FIRSTBIT_HI */ + { 2 }, /* VGPU10_OPCODE_FIRSTBIT_LO */ + { 2 }, /* VGPU10_OPCODE_FIRSTBIT_SHI */ + { 4 }, /* VGPU10_OPCODE_UBFE */ + { 4 }, /* VGPU10_OPCODE_IBFE */ + { 5 }, /* VGPU10_OPCODE_BFI */ + { 2 }, /* VGPU10_OPCODE_BFREV */ + { 5 }, /* VGPU10_OPCODE_SWAPC */ + { 1 }, /* VGPU10_OPCODE_DCL_STREAM */ + { 0 }, /* VGPU10_OPCODE_DCL_FUNCTION_BODY */ + { 0 }, /* VGPU10_OPCODE_DCL_FUNCTION_TABLE */ + { 0 }, /* VGPU10_OPCODE_DCL_INTERFACE */ + { 0 }, /* VGPU10_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT */ + { 0 }, /* VGPU10_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT */ + { 0 }, /* VGPU10_OPCODE_DCL_TESS_DOMAIN */ + { 0 }, /* VGPU10_OPCODE_DCL_TESS_PARTITIONING */ + { 0 }, /* VGPU10_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE */ + { 0 }, /* VGPU10_OPCODE_DCL_HS_MAX_TESSFACTOR */ + { 0 }, /* VGPU10_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT */ + { 0 }, /* VGPU10_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ + { 0 }, /* VGPU10_OPCODE_DCL_THREAD_GROUP */ + { 1 }, /* VGPU10_OPCODE_DCL_UAV_TYPED */ + { 1 }, /* VGPU10_OPCODE_DCL_UAV_RAW */ + { 1 }, /* VGPU10_OPCODE_DCL_UAV_STRUCTURED */ + { 1 }, /* VGPU10_OPCODE_DCL_TGSM_RAW */ + { 1 }, /* VGPU10_OPCODE_DCL_TGSM_STRUCTURED */ + { 1 }, /* VGPU10_OPCODE_DCL_RESOURCE_RAW */ + { 1 }, /* VGPU10_OPCODE_DCL_RESOURCE_STRUCTURED */ + { 3 }, /* VGPU10_OPCODE_LD_UAV_TYPED */ + { 3 }, /* VGPU10_OPCODE_STORE_UAV_TYPED */ + { 3 }, /* VGPU10_OPCODE_LD_RAW */ + { 3 }, /* VGPU10_OPCODE_STORE_RAW */ + { 4 }, /* VGPU10_OPCODE_LD_STRUCTURED */ + { 4 }, /* VGPU10_OPCODE_STORE_STRUCTURED */ + { 3 }, /* VGPU10_OPCODE_ATOMIC_AND */ + { 3 }, /* VGPU10_OPCODE_ATOMIC_OR */ + { 3 }, /* VGPU10_OPCODE_ATOMIC_XOR */ + { 4 }, /* VGPU10_OPCODE_ATOMIC_CMP_STORE */ + { 3 }, /* VGPU10_OPCODE_ATOMIC_IADD */ + { 3 }, /* VGPU10_OPCODE_ATOMIC_IMAX */ + { 3 }, /* VGPU10_OPCODE_ATOMIC_IMIN */ + { 3 }, /* VGPU10_OPCODE_ATOMIC_UMAX */ + { 3 }, /* VGPU10_OPCODE_ATOMIC_UMIN */ + { 2 }, /* VGPU10_OPCODE_IMM_ATOMIC_ALLOC */ + { 2 }, /* VGPU10_OPCODE_IMM_ATOMIC_CONSUME */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_IADD */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_AND */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_OR */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_XOR */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_EXCH */ + { 5 }, /* VGPU10_OPCODE_IMM_ATOMIC_CMP_EXCH */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_IMAX */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_IMIN */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_UMAX */ + { 4 }, /* VGPU10_OPCODE_IMM_ATOMIC_UMIN */ + { 0 }, /* VGPU10_OPCODE_SYNC */ + { 3 }, /* VGPU10_OPCODE_DADD */ + { 3 }, /* VGPU10_OPCODE_DMAX */ + { 3 }, /* VGPU10_OPCODE_DMIN */ + { 3 }, /* VGPU10_OPCODE_DMUL */ + { 3 }, /* VGPU10_OPCODE_DEQ */ + { 3 }, /* VGPU10_OPCODE_DGE */ + { 3 }, /* VGPU10_OPCODE_DLT */ + { 3 }, /* VGPU10_OPCODE_DNE */ + { 2 }, /* VGPU10_OPCODE_DMOV */ + { 4 }, /* VGPU10_OPCODE_DMOVC */ + { 2 }, /* VGPU10_OPCODE_DTOF */ + { 2 }, /* VGPU10_OPCODE_FTOD */ + { 3 }, /* VGPU10_OPCODE_EVAL_SNAPPED */ + { 3 }, /* VGPU10_OPCODE_EVAL_SAMPLE_INDEX */ + { 2 }, /* VGPU10_OPCODE_EVAL_CENTROID */ + { 0 }, /* VGPU10_OPCODE_DCL_GS_INSTANCE_COUNT */ + { 0 }, /* VGPU10_OPCODE_ABORT */ + { 0 }, /* VGPU10_OPCODE_DEBUG_BREAK */ + { 0 }, /* VGPU10_OPCODE_RESERVED0 */ + { 3 }, /* VGPU10_OPCODE_DDIV */ + { 4 }, /* VGPU10_OPCODE_DFMA */ + { 2 }, /* VGPU10_OPCODE_DRCP */ + { 4 }, /* VGPU10_OPCODE_MSAD */ + { 2 }, /* VGPU10_OPCODE_DTOI */ + { 2 }, /* VGPU10_OPCODE_DTOU */ + { 2 }, /* VGPU10_OPCODE_ITOD */ + { 2 }, /* VGPU10_OPCODE_UTOD */ +}; +AssertCompile(RT_ELEMENTS(g_aOpcodeInfo) == VGPU10_NUM_OPCODES); + +#ifdef LOG_ENABLED +/* + * + * Helpers to translate a VGPU10 shader constant to a string. + * + */ + +#define SVGA_CASE_ID2STR(idx) case idx: return #idx + +static const char *dxbcOpcodeToString(uint32_t opcodeType) +{ + VGPU10_OPCODE_TYPE enm = (VGPU10_OPCODE_TYPE)opcodeType; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_OPCODE_ADD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_AND); + SVGA_CASE_ID2STR(VGPU10_OPCODE_BREAK); + SVGA_CASE_ID2STR(VGPU10_OPCODE_BREAKC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_CALL); + SVGA_CASE_ID2STR(VGPU10_OPCODE_CALLC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_CASE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_CONTINUE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_CONTINUEC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_CUT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DEFAULT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DERIV_RTX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DERIV_RTY); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DISCARD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DIV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DP2); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DP3); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DP4); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ELSE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EMIT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EMITTHENCUT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ENDIF); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ENDLOOP); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ENDSWITCH); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EQ); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EXP); + SVGA_CASE_ID2STR(VGPU10_OPCODE_FRC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_FTOI); + SVGA_CASE_ID2STR(VGPU10_OPCODE_FTOU); + SVGA_CASE_ID2STR(VGPU10_OPCODE_GE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IADD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IF); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IEQ); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IGE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ILT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMAD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMAX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMUL); + SVGA_CASE_ID2STR(VGPU10_OPCODE_INE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_INEG); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ISHL); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ISHR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ITOF); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LABEL); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LD_MS); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LOG); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LOOP); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_MAD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_MIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_MAX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_CUSTOMDATA); + SVGA_CASE_ID2STR(VGPU10_OPCODE_MOV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_MOVC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_MUL); + SVGA_CASE_ID2STR(VGPU10_OPCODE_NE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_NOP); + SVGA_CASE_ID2STR(VGPU10_OPCODE_NOT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_OR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_RESINFO); + SVGA_CASE_ID2STR(VGPU10_OPCODE_RET); + SVGA_CASE_ID2STR(VGPU10_OPCODE_RETC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ROUND_NE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ROUND_NI); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ROUND_PI); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ROUND_Z); + SVGA_CASE_ID2STR(VGPU10_OPCODE_RSQ); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SAMPLE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SAMPLE_C); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SAMPLE_C_LZ); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SAMPLE_L); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SAMPLE_D); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SAMPLE_B); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SQRT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SWITCH); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SINCOS); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UDIV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ULT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UGE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UMUL); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UMAD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UMAX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UMIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_USHR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UTOF); + SVGA_CASE_ID2STR(VGPU10_OPCODE_XOR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_RESOURCE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_CONSTANT_BUFFER); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_SAMPLER); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INDEX_RANGE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_GS_INPUT_PRIMITIVE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INPUT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INPUT_SGV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INPUT_SIV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INPUT_PS); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INPUT_PS_SGV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INPUT_PS_SIV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_OUTPUT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_OUTPUT_SGV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_OUTPUT_SIV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_TEMPS); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INDEXABLE_TEMP); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_GLOBAL_FLAGS); + SVGA_CASE_ID2STR(VGPU10_OPCODE_VMWARE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LOD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_GATHER4); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SAMPLE_POS); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SAMPLE_INFO); + SVGA_CASE_ID2STR(VGPU10_OPCODE_RESERVED1); + SVGA_CASE_ID2STR(VGPU10_OPCODE_HS_DECLS); + SVGA_CASE_ID2STR(VGPU10_OPCODE_HS_CONTROL_POINT_PHASE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_HS_FORK_PHASE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_HS_JOIN_PHASE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EMIT_STREAM); + SVGA_CASE_ID2STR(VGPU10_OPCODE_CUT_STREAM); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EMITTHENCUT_STREAM); + SVGA_CASE_ID2STR(VGPU10_OPCODE_INTERFACE_CALL); + SVGA_CASE_ID2STR(VGPU10_OPCODE_BUFINFO); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DERIV_RTX_COARSE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DERIV_RTX_FINE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DERIV_RTY_COARSE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DERIV_RTY_FINE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_GATHER4_C); + SVGA_CASE_ID2STR(VGPU10_OPCODE_GATHER4_PO); + SVGA_CASE_ID2STR(VGPU10_OPCODE_GATHER4_PO_C); + SVGA_CASE_ID2STR(VGPU10_OPCODE_RCP); + SVGA_CASE_ID2STR(VGPU10_OPCODE_F32TOF16); + SVGA_CASE_ID2STR(VGPU10_OPCODE_F16TOF32); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UADDC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_USUBB); + SVGA_CASE_ID2STR(VGPU10_OPCODE_COUNTBITS); + SVGA_CASE_ID2STR(VGPU10_OPCODE_FIRSTBIT_HI); + SVGA_CASE_ID2STR(VGPU10_OPCODE_FIRSTBIT_LO); + SVGA_CASE_ID2STR(VGPU10_OPCODE_FIRSTBIT_SHI); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UBFE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IBFE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_BFI); + SVGA_CASE_ID2STR(VGPU10_OPCODE_BFREV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SWAPC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_STREAM); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_FUNCTION_BODY); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_FUNCTION_TABLE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INTERFACE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_TESS_DOMAIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_TESS_PARTITIONING); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_HS_MAX_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_THREAD_GROUP); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_UAV_TYPED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_UAV_RAW); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_UAV_STRUCTURED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_TGSM_RAW); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_TGSM_STRUCTURED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_RESOURCE_RAW); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_RESOURCE_STRUCTURED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LD_UAV_TYPED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_STORE_UAV_TYPED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LD_RAW); + SVGA_CASE_ID2STR(VGPU10_OPCODE_STORE_RAW); + SVGA_CASE_ID2STR(VGPU10_OPCODE_LD_STRUCTURED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_STORE_STRUCTURED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_AND); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_OR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_XOR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_CMP_STORE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_IADD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_IMAX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_IMIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_UMAX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ATOMIC_UMIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_ALLOC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_CONSUME); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_IADD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_AND); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_OR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_XOR); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_EXCH); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_CMP_EXCH); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_IMAX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_IMIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_UMAX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_IMM_ATOMIC_UMIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_SYNC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DADD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DMAX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DMIN); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DMUL); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DEQ); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DGE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DLT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DNE); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DMOV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DMOVC); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DTOF); + SVGA_CASE_ID2STR(VGPU10_OPCODE_FTOD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EVAL_SNAPPED); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EVAL_SAMPLE_INDEX); + SVGA_CASE_ID2STR(VGPU10_OPCODE_EVAL_CENTROID); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DCL_GS_INSTANCE_COUNT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ABORT); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DEBUG_BREAK); + SVGA_CASE_ID2STR(VGPU10_OPCODE_RESERVED0); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DDIV); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DFMA); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DRCP); + SVGA_CASE_ID2STR(VGPU10_OPCODE_MSAD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DTOI); + SVGA_CASE_ID2STR(VGPU10_OPCODE_DTOU); + SVGA_CASE_ID2STR(VGPU10_OPCODE_ITOD); + SVGA_CASE_ID2STR(VGPU10_OPCODE_UTOD); + SVGA_CASE_ID2STR(VGPU10_NUM_OPCODES); + } + return NULL; +} + + +static const char *dxbcShaderTypeToString(uint32_t value) +{ + VGPU10_PROGRAM_TYPE enm = (VGPU10_PROGRAM_TYPE)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_PIXEL_SHADER); + SVGA_CASE_ID2STR(VGPU10_VERTEX_SHADER); + SVGA_CASE_ID2STR(VGPU10_GEOMETRY_SHADER); + SVGA_CASE_ID2STR(VGPU10_HULL_SHADER); + SVGA_CASE_ID2STR(VGPU10_DOMAIN_SHADER); + SVGA_CASE_ID2STR(VGPU10_COMPUTE_SHADER); + } + return NULL; +} + + +static const char *dxbcCustomDataClassToString(uint32_t value) +{ + VGPU10_CUSTOMDATA_CLASS enm = (VGPU10_CUSTOMDATA_CLASS)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_CUSTOMDATA_COMMENT); + SVGA_CASE_ID2STR(VGPU10_CUSTOMDATA_DEBUGINFO); + SVGA_CASE_ID2STR(VGPU10_CUSTOMDATA_OPAQUE); + SVGA_CASE_ID2STR(VGPU10_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER); + } + return NULL; +} + + +static const char *dxbcSystemNameToString(uint32_t value) +{ + VGPU10_SYSTEM_NAME enm = (VGPU10_SYSTEM_NAME)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_NAME_UNDEFINED); + SVGA_CASE_ID2STR(VGPU10_NAME_POSITION); + SVGA_CASE_ID2STR(VGPU10_NAME_CLIP_DISTANCE); + SVGA_CASE_ID2STR(VGPU10_NAME_CULL_DISTANCE); + SVGA_CASE_ID2STR(VGPU10_NAME_RENDER_TARGET_ARRAY_INDEX); + SVGA_CASE_ID2STR(VGPU10_NAME_VIEWPORT_ARRAY_INDEX); + SVGA_CASE_ID2STR(VGPU10_NAME_VERTEX_ID); + SVGA_CASE_ID2STR(VGPU10_NAME_PRIMITIVE_ID); + SVGA_CASE_ID2STR(VGPU10_NAME_INSTANCE_ID); + SVGA_CASE_ID2STR(VGPU10_NAME_IS_FRONT_FACE); + SVGA_CASE_ID2STR(VGPU10_NAME_SAMPLE_INDEX); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_TRI_INSIDE_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_LINE_DETAIL_TESSFACTOR); + SVGA_CASE_ID2STR(VGPU10_NAME_FINAL_LINE_DENSITY_TESSFACTOR); + } + return NULL; +} + + +static const char *dxbcOperandTypeToString(uint32_t value) +{ + VGPU10_OPERAND_TYPE enm = (VGPU10_OPERAND_TYPE)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_TEMP); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_OUTPUT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INDEXABLE_TEMP); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_IMMEDIATE32); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_IMMEDIATE64); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_SAMPLER); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_RESOURCE); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_CONSTANT_BUFFER); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_LABEL); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_PRIMITIVEID); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_OUTPUT_DEPTH); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_NULL); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_RASTERIZER); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_OUTPUT_COVERAGE_MASK); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_STREAM); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_FUNCTION_BODY); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_FUNCTION_TABLE); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INTERFACE); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_FUNCTION_INPUT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_FUNCTION_OUTPUT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_FORK_INSTANCE_ID); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_CONTROL_POINT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_OUTPUT_CONTROL_POINT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_PATCH_CONSTANT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_DOMAIN_POINT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_THIS_POINTER); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_UAV); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_THREAD_ID); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_THREAD_GROUP_ID); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_COVERAGE_MASK); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_INPUT_GS_INSTANCE_ID); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL); + SVGA_CASE_ID2STR(VGPU10_OPERAND_TYPE_CYCLE_COUNTER); + SVGA_CASE_ID2STR(VGPU10_NUM_OPERANDS); + } + return NULL; +} + + +static const char *dxbcExtendedOperandTypeToString(uint32_t value) +{ + VGPU10_EXTENDED_OPERAND_TYPE enm = (VGPU10_EXTENDED_OPERAND_TYPE)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_EXTENDED_OPERAND_EMPTY); + SVGA_CASE_ID2STR(VGPU10_EXTENDED_OPERAND_MODIFIER); + } + return NULL; +} + + +static const char *dxbcOperandModifierToString(uint32_t value) +{ + VGPU10_OPERAND_MODIFIER enm = (VGPU10_OPERAND_MODIFIER)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_OPERAND_MODIFIER_NONE); + SVGA_CASE_ID2STR(VGPU10_OPERAND_MODIFIER_NEG); + SVGA_CASE_ID2STR(VGPU10_OPERAND_MODIFIER_ABS); + SVGA_CASE_ID2STR(VGPU10_OPERAND_MODIFIER_ABSNEG); + } + return NULL; +} + + +static const char *dxbcOperandNumComponentsToString(uint32_t value) +{ + VGPU10_OPERAND_NUM_COMPONENTS enm = (VGPU10_OPERAND_NUM_COMPONENTS)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_OPERAND_0_COMPONENT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_1_COMPONENT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_4_COMPONENT); + SVGA_CASE_ID2STR(VGPU10_OPERAND_N_COMPONENT); + } + return NULL; +} + + +static const char *dxbcOperandComponentModeToString(uint32_t value) +{ + VGPU10_OPERAND_4_COMPONENT_SELECTION_MODE enm = (VGPU10_OPERAND_4_COMPONENT_SELECTION_MODE)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_OPERAND_4_COMPONENT_MASK_MODE); + SVGA_CASE_ID2STR(VGPU10_OPERAND_4_COMPONENT_SWIZZLE_MODE); + SVGA_CASE_ID2STR(VGPU10_OPERAND_4_COMPONENT_SELECT_1_MODE); + } + return NULL; +} + + +static const char *dxbcOperandComponentNameToString(uint32_t value) +{ + VGPU10_COMPONENT_NAME enm = (VGPU10_COMPONENT_NAME)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_COMPONENT_X); + SVGA_CASE_ID2STR(VGPU10_COMPONENT_Y); + SVGA_CASE_ID2STR(VGPU10_COMPONENT_Z); + SVGA_CASE_ID2STR(VGPU10_COMPONENT_W); + } + return NULL; +} + + +static const char *dxbcOperandIndexDimensionToString(uint32_t value) +{ + VGPU10_OPERAND_INDEX_DIMENSION enm = (VGPU10_OPERAND_INDEX_DIMENSION)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_0D); + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_1D); + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_2D); + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_3D); + } + return NULL; +} + + +static const char *dxbcOperandIndexRepresentationToString(uint32_t value) +{ + VGPU10_OPERAND_INDEX_REPRESENTATION enm = (VGPU10_OPERAND_INDEX_REPRESENTATION)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_IMMEDIATE32); + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_IMMEDIATE64); + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_RELATIVE); + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE); + SVGA_CASE_ID2STR(VGPU10_OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE); + } + return NULL; +} + + +static const char *dxbcInterpolationModeToString(uint32_t value) +{ + VGPU10_INTERPOLATION_MODE enm = (VGPU10_INTERPOLATION_MODE)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_INTERPOLATION_UNDEFINED); + SVGA_CASE_ID2STR(VGPU10_INTERPOLATION_CONSTANT); + SVGA_CASE_ID2STR(VGPU10_INTERPOLATION_LINEAR); + SVGA_CASE_ID2STR(VGPU10_INTERPOLATION_LINEAR_CENTROID); + SVGA_CASE_ID2STR(VGPU10_INTERPOLATION_LINEAR_NOPERSPECTIVE); + SVGA_CASE_ID2STR(VGPU10_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID); + SVGA_CASE_ID2STR(VGPU10_INTERPOLATION_LINEAR_SAMPLE); + SVGA_CASE_ID2STR(VGPU10_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE); + } + return NULL; +} + + +static const char *dxbcResourceDimensionToString(uint32_t value) +{ + VGPU10_RESOURCE_DIMENSION enm = (VGPU10_RESOURCE_DIMENSION)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_UNKNOWN); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_BUFFER); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURE1D); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURE2D); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURE2DMS); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURE3D); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURECUBE); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURE1DARRAY); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURE2DARRAY); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURE2DMSARRAY); + SVGA_CASE_ID2STR(VGPU10_RESOURCE_DIMENSION_TEXTURECUBEARRAY); + } + return NULL; +} + + +static const char *dxbcVmwareOpcodeTypeToString(uint32_t value) +{ + VGPU10_VMWARE_OPCODE_TYPE enm = (VGPU10_VMWARE_OPCODE_TYPE)value; + switch (enm) + { + SVGA_CASE_ID2STR(VGPU10_VMWARE_OPCODE_IDIV); + SVGA_CASE_ID2STR(VGPU10_VMWARE_OPCODE_DFRC); + SVGA_CASE_ID2STR(VGPU10_VMWARE_OPCODE_DRSQ); + SVGA_CASE_ID2STR(VGPU10_VMWARE_NUM_OPCODES); + } + return NULL; +} + +#endif /* LOG_ENABLED */ + +/* + * MD5 from IPRT (alt-md5.cpp) for DXBC hash calculation. + * DXBC hash function uses a different padding for the data, see dxbcHash. + * Therefore RTMd5Final is not needed. Two functions have been renamed: dxbcRTMd5Update dxbcRTMd5Init. + */ + + +/* The four core functions - F1 is optimized somewhat */ +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + + +/** + * The core of the MD5 algorithm, this alters an existing MD5 hash to reflect + * the addition of 16 longwords of new data. RTMd5Update blocks the data and + * converts bytes into longwords for this routine. + */ +static void rtMd5Transform(uint32_t buf[4], uint32_t const in[16]) +{ + uint32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + /* fn, w, x, y, z, data, s) */ + MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + + +#ifdef RT_BIG_ENDIAN +/* + * Note: this code is harmless on little-endian machines. + */ +static void rtMd5ByteReverse(uint32_t *buf, unsigned int longs) +{ + uint32_t t; + do + { + t = *buf; + t = RT_LE2H_U32(t); + *buf = t; + buf++; + } while (--longs); +} +#else /* little endian - do nothing */ +# define rtMd5ByteReverse(buf, len) do { /* Nothing */ } while (0) +#endif + + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +static void dxbcRTMd5Init(PRTMD5CONTEXT pCtx) +{ + pCtx->AltPrivate.buf[0] = 0x67452301; + pCtx->AltPrivate.buf[1] = 0xefcdab89; + pCtx->AltPrivate.buf[2] = 0x98badcfe; + pCtx->AltPrivate.buf[3] = 0x10325476; + + pCtx->AltPrivate.bits[0] = 0; + pCtx->AltPrivate.bits[1] = 0; +} + + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +/** @todo Optimize this, because len is always a multiple of 64. */ +static void dxbcRTMd5Update(PRTMD5CONTEXT pCtx, const void *pvBuf, size_t len) +{ + const uint8_t *buf = (const uint8_t *)pvBuf; + uint32_t t; + + /* Update bitcount */ + t = pCtx->AltPrivate.bits[0]; + if ((pCtx->AltPrivate.bits[0] = t + ((uint32_t) len << 3)) < t) + pCtx->AltPrivate.bits[1]++; /* Carry from low to high */ + pCtx->AltPrivate.bits[1] += (uint32_t)(len >> 29); + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + if (t) + { + uint8_t *p = (uint8_t *) pCtx->AltPrivate.in + t; + + t = 64 - t; + if (len < t) + { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + rtMd5ByteReverse(pCtx->AltPrivate.in, 16); + rtMd5Transform(pCtx->AltPrivate.buf, pCtx->AltPrivate.in); + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ +#ifndef RT_BIG_ENDIAN + if (!((uintptr_t)buf & 0x3)) + { + while (len >= 64) { + rtMd5Transform(pCtx->AltPrivate.buf, (uint32_t const *)buf); + buf += 64; + len -= 64; + } + } + else +#endif + { + while (len >= 64) { + memcpy(pCtx->AltPrivate.in, buf, 64); + rtMd5ByteReverse(pCtx->AltPrivate.in, 16); + rtMd5Transform(pCtx->AltPrivate.buf, pCtx->AltPrivate.in); + buf += 64; + len -= 64; + } + } + + /* Handle any remaining bytes of data */ + memcpy(pCtx->AltPrivate.in, buf, len); +} + + +static void dxbcHash(void const *pvData, uint32_t cbData, uint8_t pabDigest[RTMD5HASHSIZE]) +{ + size_t const kBlockSize = 64; + uint8_t au8BlockBuffer[kBlockSize]; + + static uint8_t const s_au8Padding[kBlockSize] = + { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + RTMD5CONTEXT Ctx; + PRTMD5CONTEXT const pCtx = &Ctx; + dxbcRTMd5Init(pCtx); + + uint8_t const *pu8Data = (uint8_t *)pvData; + size_t cbRemaining = cbData; + + size_t const cbCompleteBlocks = cbData & ~ (kBlockSize - 1); + dxbcRTMd5Update(pCtx, pu8Data, cbCompleteBlocks); + pu8Data += cbCompleteBlocks; + cbRemaining -= cbCompleteBlocks; + + /* Custom padding. */ + if (cbRemaining >= kBlockSize - 2 * sizeof(uint32_t)) + { + /* Two additional blocks. */ + memcpy(&au8BlockBuffer[0], pu8Data, cbRemaining); + memcpy(&au8BlockBuffer[cbRemaining], s_au8Padding, kBlockSize - cbRemaining); + dxbcRTMd5Update(pCtx, au8BlockBuffer, kBlockSize); + + memset(&au8BlockBuffer[sizeof(uint32_t)], 0, kBlockSize - 2 * sizeof(uint32_t)); + } + else + { + /* One additional block. */ + memcpy(&au8BlockBuffer[sizeof(uint32_t)], pu8Data, cbRemaining); + memcpy(&au8BlockBuffer[sizeof(uint32_t) + cbRemaining], s_au8Padding, kBlockSize - cbRemaining - 2 * sizeof(uint32_t)); + } + + /* Set the first and last dwords of the last block. */ + *(uint32_t *)&au8BlockBuffer[0] = cbData << 3; + *(uint32_t *)&au8BlockBuffer[kBlockSize - sizeof(uint32_t)] = (cbData << 1) | 1; + dxbcRTMd5Update(pCtx, au8BlockBuffer, kBlockSize); + + AssertCompile(sizeof(pCtx->AltPrivate.buf) == RTMD5HASHSIZE); + memcpy(pabDigest, pCtx->AltPrivate.buf, RTMD5HASHSIZE); +} + + +/* + * + * Shader token reader. + * + */ + +typedef struct DXBCTokenReader +{ + uint32_t const *pToken; /* Next token to read. */ + uint32_t cToken; /* How many tokens total. */ + uint32_t cRemainingToken; /* How many tokens remain. */ +} DXBCTokenReader; + + +#ifdef LOG_ENABLED +DECLINLINE(uint32_t) dxbcTokenReaderByteOffset(DXBCTokenReader *r) +{ + return (r->cToken - r->cRemainingToken) * 4; +} +#endif + + +#if 0 // Unused for now +DECLINLINE(uint32_t) dxbcTokenReaderRemaining(DXBCTokenReader *r) +{ + return r->cRemainingToken; +} +#endif + + +DECLINLINE(uint32_t const *) dxbcTokenReaderPtr(DXBCTokenReader *r) +{ + return r->pToken; +} + + +DECLINLINE(bool) dxbcTokenReaderCanRead(DXBCTokenReader *r, uint32_t cToken) +{ + return cToken <= r->cRemainingToken; +} + + +DECLINLINE(void) dxbcTokenReaderSkip(DXBCTokenReader *r, uint32_t cToken) +{ + AssertReturnVoid(r->cRemainingToken >= cToken); + r->cRemainingToken -= cToken; + r->pToken += cToken; +} + + +DECLINLINE(uint32_t) dxbcTokenReaderRead32(DXBCTokenReader *r) +{ + AssertReturn(r->cRemainingToken, 0); + --r->cRemainingToken; + return *(r->pToken++); +} + + +DECLINLINE(uint64_t) dxbcTokenReaderRead64(DXBCTokenReader *r) +{ + uint64_t const u64Low = dxbcTokenReaderRead32(r); + uint64_t const u64High = dxbcTokenReaderRead32(r); + return u64Low + (u64High << 32); +} + + +/* + * + * Byte writer. + * + */ + +typedef struct DXBCByteWriter +{ + uint8_t *pu8ByteCodeBegin; /* First byte of the buffer. */ + uint8_t *pu8ByteCodePtr; /* Next byte to be written. */ + uint32_t cbAllocated; /* How many bytes allocated in the buffer. */ + uint32_t cbRemaining; /* How many bytes remain in the buffer. */ + uint32_t cbWritten; /* Offset of first never written byte. + * Since the writer allows to jump in the buffer, this field tracks + * the upper boundary of the written data. + */ + int32_t rc; +} DXBCByteWriter; + + +typedef struct DXBCByteWriterState +{ + uint32_t off; /* Offset of the next free byte. */ +} DXBCByteWriterState; + + +DECLINLINE(void *) dxbcByteWriterPtr(DXBCByteWriter *w) +{ + return w->pu8ByteCodePtr; +} + + +DECLINLINE(uint32_t) dxbcByteWriterSize(DXBCByteWriter *w) +{ + return (uint32_t)(w->pu8ByteCodePtr - w->pu8ByteCodeBegin); +} + + +static bool dxbcByteWriterRealloc(DXBCByteWriter *w, uint32_t cbNew) +{ + void *pvNew = RTMemAllocZ(cbNew); + if (!pvNew) + { + w->rc = VERR_NO_MEMORY; + return false; + } + + uint32_t const cbCurrent = dxbcByteWriterSize(w); + if (cbCurrent) + { + memcpy(pvNew, w->pu8ByteCodeBegin, cbCurrent); + RTMemFree(w->pu8ByteCodeBegin); + } + else + Assert(w->pu8ByteCodeBegin == NULL); + + w->pu8ByteCodeBegin = (uint8_t *)pvNew; + w->pu8ByteCodePtr = w->pu8ByteCodeBegin + cbCurrent; + w->cbAllocated = cbNew; + w->cbRemaining = cbNew - cbCurrent; + return true; +} + + +DECLINLINE(bool) dxbcByteWriterSetOffset(DXBCByteWriter *w, uint32_t off, DXBCByteWriterState *pSavedWriterState) +{ + if (RT_FAILURE(w->rc)) + return false; + + uint32_t const cbNew = RT_ALIGN_32(off, 1024); + uint32_t const cbMax = 2 * SVGA3D_MAX_SHADER_MEMORY_BYTES; + AssertReturnStmt(off < cbMax && cbNew < cbMax, w->rc = VERR_INVALID_PARAMETER, false); + + if (cbNew > w->cbAllocated) + { + if (!dxbcByteWriterRealloc(w, cbNew)) + return false; + } + + pSavedWriterState->off = dxbcByteWriterSize(w); + + w->pu8ByteCodePtr = w->pu8ByteCodeBegin + off; + w->cbRemaining = w->cbAllocated - off; + return true; +} + + +DECLINLINE(void) dxbcByteWriterRestore(DXBCByteWriter *w, DXBCByteWriterState *pSavedWriterState) +{ + w->pu8ByteCodePtr = w->pu8ByteCodeBegin + pSavedWriterState->off; + w->cbRemaining = w->cbAllocated - pSavedWriterState->off; +} + + +DECLINLINE(void) dxbcByteWriterCommit(DXBCByteWriter *w, uint32_t cbCommit) +{ + if (RT_FAILURE(w->rc)) + return; + + Assert(cbCommit < w->cbRemaining); + cbCommit = RT_MIN(cbCommit, w->cbRemaining); + w->pu8ByteCodePtr += cbCommit; + w->cbRemaining -= cbCommit; + w->cbWritten = RT_MAX(w->cbWritten, w->cbAllocated - w->cbRemaining); +} + + +DECLINLINE(bool) dxbcByteWriterCanWrite(DXBCByteWriter *w, uint32_t cbMore) +{ + if (RT_FAILURE(w->rc)) + return false; + + if (cbMore <= w->cbRemaining) + return true; + + /* Do not allow to allocate more than 2 * SVGA3D_MAX_SHADER_MEMORY_BYTES */ + uint32_t const cbMax = 2 * SVGA3D_MAX_SHADER_MEMORY_BYTES; + AssertReturnStmt(cbMore < cbMax && RT_ALIGN_32(cbMore, 4096) <= cbMax - w->cbAllocated, w->rc = VERR_INVALID_PARAMETER, false); + + uint32_t cbNew = w->cbAllocated + RT_ALIGN_32(cbMore, 4096); + return dxbcByteWriterRealloc(w, cbNew); +} + + +DECLINLINE(bool) dxbcByteWriterAddTokens(DXBCByteWriter *w, uint32_t const *paToken, uint32_t cToken) +{ + uint32_t const cbWrite = cToken * sizeof(uint32_t); + if (dxbcByteWriterCanWrite(w, cbWrite)) + { + memcpy(dxbcByteWriterPtr(w), paToken, cbWrite); + dxbcByteWriterCommit(w, cbWrite); + return true; + } + + AssertFailed(); + return false; +} + + +DECLINLINE(bool) dxbcByteWriterInit(DXBCByteWriter *w, uint32_t cbInitial) +{ + RT_ZERO(*w); + return dxbcByteWriterCanWrite(w, cbInitial); +} + + +DECLINLINE(void) dxbcByteWriterReset(DXBCByteWriter *w) +{ + RTMemFree(w->pu8ByteCodeBegin); + RT_ZERO(*w); +} + + +DECLINLINE(void) dxbcByteWriterFetchData(DXBCByteWriter *w, void **ppv, uint32_t *pcb) +{ + *ppv = w->pu8ByteCodeBegin; + *pcb = w->cbWritten; + + w->pu8ByteCodeBegin = NULL; + dxbcByteWriterReset(w); +} + + +/* + * + * VGPU10 shader parser. + * + */ + +/* Parse an instruction operand. */ +static int dxbcParseOperand(DXBCTokenReader *r, VGPUOperand *paOperand, uint32_t *pcOperandRemain) +{ + ASSERT_GUEST_RETURN(*pcOperandRemain > 0, VERR_NOT_SUPPORTED); + + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + + paOperand->paOperandToken = dxbcTokenReaderPtr(r); + paOperand->cOperandToken = 0; + + VGPU10OperandToken0 operand0; + operand0.value = dxbcTokenReaderRead32(r); + + Log6((" %s(%d) %s(%d) %s(%d) %s(%d)\n", + dxbcOperandNumComponentsToString(operand0.numComponents), operand0.numComponents, + dxbcOperandComponentModeToString(operand0.selectionMode), operand0.selectionMode, + dxbcOperandTypeToString(operand0.operandType), operand0.operandType, + dxbcOperandIndexDimensionToString(operand0.indexDimension), operand0.indexDimension)); + + ASSERT_GUEST_RETURN(operand0.numComponents <= VGPU10_OPERAND_4_COMPONENT, VERR_INVALID_PARAMETER); + if ( operand0.operandType != VGPU10_OPERAND_TYPE_IMMEDIATE32 + && operand0.operandType != VGPU10_OPERAND_TYPE_IMMEDIATE64) + { + if (operand0.numComponents == VGPU10_OPERAND_4_COMPONENT) + { + ASSERT_GUEST_RETURN(operand0.selectionMode <= VGPU10_OPERAND_4_COMPONENT_SELECT_1_MODE, VERR_INVALID_PARAMETER); + switch (operand0.selectionMode) + { + case VGPU10_OPERAND_4_COMPONENT_MASK_MODE: + Log6((" Mask %#x\n", operand0.mask)); + break; + case VGPU10_OPERAND_4_COMPONENT_SWIZZLE_MODE: + Log6((" Swizzle %s(%d) %s(%d) %s(%d) %s(%d)\n", + dxbcOperandComponentNameToString(operand0.swizzleX), operand0.swizzleX, + dxbcOperandComponentNameToString(operand0.swizzleY), operand0.swizzleY, + dxbcOperandComponentNameToString(operand0.swizzleZ), operand0.swizzleZ, + dxbcOperandComponentNameToString(operand0.swizzleW), operand0.swizzleW)); + break; + case VGPU10_OPERAND_4_COMPONENT_SELECT_1_MODE: + Log6((" Select %s(%d)\n", + dxbcOperandComponentNameToString(operand0.selectMask), operand0.selectMask)); + break; + default: /* Never happens. */ + break; + } + } + } + + if (operand0.extended) + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + + VGPU10OperandToken1 operand1; + operand1.value = dxbcTokenReaderRead32(r); + + Log6((" %s(%d) %s(%d)\n", + dxbcExtendedOperandTypeToString(operand1.extendedOperandType), operand1.extendedOperandType, + dxbcOperandModifierToString(operand1.operandModifier), operand1.operandModifier)); + } + + ASSERT_GUEST_RETURN(operand0.operandType < VGPU10_NUM_OPERANDS, VERR_INVALID_PARAMETER); + + if ( operand0.operandType == VGPU10_OPERAND_TYPE_IMMEDIATE32 + || operand0.operandType == VGPU10_OPERAND_TYPE_IMMEDIATE64) + { + uint32_t cComponent = 0; + if (operand0.numComponents == VGPU10_OPERAND_4_COMPONENT) + cComponent = 4; + else if (operand0.numComponents == VGPU10_OPERAND_1_COMPONENT) + cComponent = 1; + + for (uint32_t i = 0; i < cComponent; ++i) + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + paOperand->aImm[i] = dxbcTokenReaderRead32(r); + } + } + + paOperand->numComponents = operand0.numComponents; + paOperand->selectionMode = operand0.selectionMode; + paOperand->mask = operand0.mask; + paOperand->operandType = operand0.operandType; + paOperand->indexDimension = operand0.indexDimension; + + int rc = VINF_SUCCESS; + /* 'indexDimension' tells the number of indices. 'i' is the array index, i.e. i = 0 for 1D, etc. */ + for (uint32_t i = 0; i < operand0.indexDimension; ++i) + { + if (i == 0) /* VGPU10_OPERAND_INDEX_1D */ + paOperand->aOperandIndex[i].indexRepresentation = operand0.index0Representation; + else if (i == 1) /* VGPU10_OPERAND_INDEX_2D */ + paOperand->aOperandIndex[i].indexRepresentation = operand0.index1Representation; + else /* VGPU10_OPERAND_INDEX_3D */ + continue; /* Skip because it is "rarely if ever used" and is not supported by VGPU10. */ + + uint32_t const indexRepresentation = paOperand->aOperandIndex[i].indexRepresentation; + switch (indexRepresentation) + { + case VGPU10_OPERAND_INDEX_IMMEDIATE32: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + paOperand->aOperandIndex[i].iOperandImmediate = dxbcTokenReaderRead32(r); + break; + } + case VGPU10_OPERAND_INDEX_IMMEDIATE64: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 2), VERR_INVALID_PARAMETER); + paOperand->aOperandIndex[i].iOperandImmediate = dxbcTokenReaderRead64(r); + break; + } + case VGPU10_OPERAND_INDEX_RELATIVE: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + paOperand->aOperandIndex[i].pOperandRelative = &paOperand[1]; + Log6((" [operand index %d] parsing relative\n", i)); + rc = dxbcParseOperand(r, &paOperand[1], pcOperandRemain); + break; + } + case VGPU10_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 2), VERR_INVALID_PARAMETER); + paOperand->aOperandIndex[i].iOperandImmediate = dxbcTokenReaderRead32(r); + paOperand->aOperandIndex[i].pOperandRelative = &paOperand[1]; + Log6((" [operand index %d] parsing relative\n", i)); + rc = dxbcParseOperand(r, &paOperand[1], pcOperandRemain); + break; + } + case VGPU10_OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 3), VERR_INVALID_PARAMETER); + paOperand->aOperandIndex[i].iOperandImmediate = dxbcTokenReaderRead64(r); + paOperand->aOperandIndex[i].pOperandRelative = &paOperand[1]; + Log6((" [operand index %d] parsing relative\n", i)); + rc = dxbcParseOperand(r, &paOperand[1], pcOperandRemain); + break; + } + default: + ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER); + } + Log6((" [operand index %d] %s(%d): %#llx%s\n", + i, dxbcOperandIndexRepresentationToString(indexRepresentation), indexRepresentation, + paOperand->aOperandIndex[i].iOperandImmediate, paOperand->aOperandIndex[i].pOperandRelative ? " + relative" : "")); + if (RT_FAILURE(rc)) + break; + } + + paOperand->cOperandToken = dxbcTokenReaderPtr(r) - paOperand->paOperandToken; + + *pcOperandRemain -= 1; + return VINF_SUCCESS; +} + + +/* Parse an instruction. */ +static int dxbcParseOpcode(DXBCTokenReader *r, VGPUOpcode *pOpcode) +{ + RT_ZERO(*pOpcode); + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + + pOpcode->paOpcodeToken = dxbcTokenReaderPtr(r); + + VGPU10OpcodeToken0 opcode; + opcode.value = dxbcTokenReaderRead32(r); + + pOpcode->opcodeType = opcode.opcodeType; + ASSERT_GUEST_RETURN(pOpcode->opcodeType < VGPU10_NUM_OPCODES, VERR_INVALID_PARAMETER); + + Log6(("[%#x] %s length %d\n", + dxbcTokenReaderByteOffset(r) - 4, dxbcOpcodeToString(pOpcode->opcodeType), opcode.instructionLength)); + + uint32_t const cOperand = g_aOpcodeInfo[pOpcode->opcodeType].cOperand; + if (cOperand != UINT32_MAX) + { + ASSERT_GUEST_RETURN(cOperand < RT_ELEMENTS(pOpcode->aIdxOperand), VERR_INVALID_PARAMETER); + + pOpcode->cOpcodeToken = opcode.instructionLength; + uint32_t cOpcode = 1; /* Opcode token + extended opcode tokens. */ + if (opcode.extended) + { + if ( pOpcode->opcodeType == VGPU10_OPCODE_DCL_FUNCTION_BODY + || pOpcode->opcodeType == VGPU10_OPCODE_DCL_FUNCTION_TABLE + || pOpcode->opcodeType == VGPU10_OPCODE_DCL_INTERFACE + || pOpcode->opcodeType == VGPU10_OPCODE_INTERFACE_CALL + || pOpcode->opcodeType == VGPU10_OPCODE_DCL_THREAD_GROUP) + { + /* "next DWORD contains ... the actual instruction length in DWORD since it may not fit into 7 bits" */ + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + pOpcode->cOpcodeToken = dxbcTokenReaderRead32(r); + ++cOpcode; + } + else + { + VGPU10OpcodeToken1 opcode1; + do + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + opcode1.value = dxbcTokenReaderRead32(r); + ++cOpcode; + ASSERT_GUEST( opcode1.opcodeType == VGPU10_EXTENDED_OPCODE_SAMPLE_CONTROLS + || opcode1.opcodeType == D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM + || opcode1.opcodeType == D3D11_SB_EXTENDED_OPCODE_RESOURCE_RETURN_TYPE); + } while(opcode1.extended); + } + } + + ASSERT_GUEST_RETURN(pOpcode->cOpcodeToken >= 1 && pOpcode->cOpcodeToken < 256, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, pOpcode->cOpcodeToken - cOpcode), VERR_INVALID_PARAMETER); + +#ifdef LOG_ENABLED + Log6((" %08X", opcode.value)); + for (uint32_t i = 1; i < pOpcode->cOpcodeToken; ++i) + Log6((" %08X", r->pToken[i - 1])); + Log6(("\n")); + + if (pOpcode->opcodeType == VGPU10_OPCODE_DCL_RESOURCE) + Log6((" %s\n", + dxbcResourceDimensionToString(opcode.resourceDimension))); + else + Log6((" %s\n", + dxbcInterpolationModeToString(opcode.interpolationMode))); +#endif + /* Additional tokens before operands. */ + switch (pOpcode->opcodeType) + { + case VGPU10_OPCODE_INTERFACE_CALL: + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* Function index */ + break; + + default: + break; + } + + /* Operands. */ + uint32_t cOperandRemain = RT_ELEMENTS(pOpcode->aValOperand); + for (uint32_t i = 0; i < cOperand; ++i) + { + Log6((" [operand %d]\n", i)); + uint32_t const idxOperand = RT_ELEMENTS(pOpcode->aValOperand) - cOperandRemain; + pOpcode->aIdxOperand[i] = idxOperand; + int rc = dxbcParseOperand(r, &pOpcode->aValOperand[idxOperand], &cOperandRemain); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), VERR_INVALID_PARAMETER); + } + + pOpcode->cOperand = cOperand; + + /* Additional tokens after operands. */ + switch (pOpcode->opcodeType) + { + case VGPU10_OPCODE_DCL_INPUT_SIV: + case VGPU10_OPCODE_DCL_INPUT_SGV: + case VGPU10_OPCODE_DCL_INPUT_PS_SIV: + case VGPU10_OPCODE_DCL_INPUT_PS_SGV: + case VGPU10_OPCODE_DCL_OUTPUT_SIV: + case VGPU10_OPCODE_DCL_OUTPUT_SGV: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + + VGPU10NameToken name; + name.value = dxbcTokenReaderRead32(r); + Log6((" %s(%d)\n", + dxbcSystemNameToString(name.name), name.name)); + pOpcode->semanticName = name.name; + break; + } + case VGPU10_OPCODE_DCL_RESOURCE: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* ResourceReturnTypeToken */ + break; + } + case VGPU10_OPCODE_DCL_TEMPS: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* number of temps */ + break; + } + case VGPU10_OPCODE_DCL_INDEXABLE_TEMP: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 3), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 3); /* register index; number of registers; number of components */ + break; + } + case VGPU10_OPCODE_DCL_INDEX_RANGE: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* count of registers */ + break; + } + case VGPU10_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* maximum number of primitives */ + break; + } + case VGPU10_OPCODE_DCL_GS_INSTANCE_COUNT: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* number of instances */ + break; + } + case VGPU10_OPCODE_DCL_HS_MAX_TESSFACTOR: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* maximum TessFactor */ + break; + } + case VGPU10_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + case VGPU10_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* number of instances of the current fork/join phase program to execute */ + break; + } + case VGPU10_OPCODE_DCL_THREAD_GROUP: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 3), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 3); /* Thread Group dimensions as UINT32: x, y, z */ + break; + } + case VGPU10_OPCODE_DCL_UAV_TYPED: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* ResourceReturnTypeToken */ + break; + } + case VGPU10_OPCODE_DCL_UAV_STRUCTURED: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* byte stride */ + break; + } + case VGPU10_OPCODE_DCL_TGSM_RAW: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* element count */ + break; + } + case VGPU10_OPCODE_DCL_TGSM_STRUCTURED: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 2), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 2); /* struct byte stride; struct count */ + break; + } + case VGPU10_OPCODE_DCL_RESOURCE_STRUCTURED: + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + dxbcTokenReaderSkip(r, 1); /* struct byte stride */ + break; + } + default: + break; + } + } + else + { + /* Special opcodes. */ + if (pOpcode->opcodeType == VGPU10_OPCODE_CUSTOMDATA) + { + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, 1), VERR_INVALID_PARAMETER); + pOpcode->cOpcodeToken = dxbcTokenReaderRead32(r); + + if (pOpcode->cOpcodeToken < 2) + pOpcode->cOpcodeToken = 2; + ASSERT_GUEST_RETURN(dxbcTokenReaderCanRead(r, pOpcode->cOpcodeToken - 2), VERR_INVALID_PARAMETER); + +#ifdef LOG_ENABLED + Log6((" %08X", opcode.value)); + for (uint32_t i = 1; i < pOpcode->cOpcodeToken; ++i) + Log6((" %08X", r->pToken[i - 1])); + Log6(("\n")); + + Log6((" %s\n", + dxbcCustomDataClassToString(opcode.customDataClass))); +#endif + dxbcTokenReaderSkip(r, pOpcode->cOpcodeToken - 2); + } + else if (pOpcode->opcodeType == VGPU10_OPCODE_VMWARE) + { + pOpcode->cOpcodeToken = opcode.instructionLength; + pOpcode->opcodeSubtype = opcode.vmwareOpcodeType; + +#ifdef LOG_ENABLED + Log6((" %08X", opcode.value)); + for (uint32_t i = 1; i < pOpcode->cOpcodeToken; ++i) + Log6((" %08X", r->pToken[i - 1])); + Log6(("\n")); + + Log6((" %s(%d)\n", + dxbcVmwareOpcodeTypeToString(opcode.vmwareOpcodeType), opcode.vmwareOpcodeType)); +#endif + + if (opcode.vmwareOpcodeType == VGPU10_VMWARE_OPCODE_IDIV) + { + /* Integer divide. */ + pOpcode->cOperand = 4; /* dstQuit, dstRem, src0, src1. */ + } + else if (opcode.vmwareOpcodeType == VGPU10_VMWARE_OPCODE_DFRC) + { + /* Double precision fraction. */ + pOpcode->cOperand = 2; /* dst, src. */ + } + else if (opcode.vmwareOpcodeType == VGPU10_VMWARE_OPCODE_DRSQ) + { + /* Double precision reciprocal square root. */ + pOpcode->cOperand = 2; /* dst, src. */ + } + else + { + ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER); + } + + /* Operands. */ + uint32_t cOperandRemain = RT_ELEMENTS(pOpcode->aValOperand); + for (uint32_t i = 0; i < pOpcode->cOperand; ++i) + { + Log6((" [operand %d]\n", i)); + uint32_t const idxOperand = RT_ELEMENTS(pOpcode->aValOperand) - cOperandRemain; + pOpcode->aIdxOperand[i] = idxOperand; + int rc = dxbcParseOperand(r, &pOpcode->aValOperand[idxOperand], &cOperandRemain); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), VERR_INVALID_PARAMETER); + } + } + else + ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER); + + // pOpcode->cOperand = 0; + } + + return VINF_SUCCESS; +} + + +typedef struct DXBCOUTPUTCTX +{ + VGPU10ProgramToken programToken; + uint32_t cToken; /* Number of tokens in the original shader code. */ + + uint32_t offSubroutine; /* Current offset where to write subroutines. */ +} DXBCOUTPUTCTX; + + +static void dxbcOutputInit(DXBCOUTPUTCTX *pOutctx, VGPU10ProgramToken const *pProgramToken, uint32_t cToken) +{ + RT_ZERO(*pOutctx); + pOutctx->programToken = *pProgramToken; + pOutctx->cToken = cToken; + + pOutctx->offSubroutine = cToken * 4; +} + + +static void dxbcEmitCall(DXBCByteWriter *w, VGPUOpcode const *pOpcode, uint32_t label) +{ + VGPU10OpcodeToken0 opcode; + VGPU10OperandToken0 operand; + + opcode.value = 0; + opcode.opcodeType = VGPU10_OPCODE_CALL; + opcode.instructionLength = 3; + dxbcByteWriterAddTokens(w, &opcode.value, 1); + + operand.value = 0; + operand.numComponents = VGPU10_OPERAND_1_COMPONENT; + operand.operandType = VGPU10_OPERAND_TYPE_LABEL; + operand.indexDimension = VGPU10_OPERAND_INDEX_1D; + operand.index0Representation = VGPU10_OPERAND_INDEX_IMMEDIATE32; + dxbcByteWriterAddTokens(w, &operand.value, 1); + + dxbcByteWriterAddTokens(w, &label, 1); + + opcode.value = 0; + opcode.opcodeType = VGPU10_OPCODE_NOP; + opcode.instructionLength = 1; + for (unsigned i = 0; i < pOpcode->cOpcodeToken - 3; ++i) + dxbcByteWriterAddTokens(w, &opcode.value, 1); +} + + +static void dxbcEmitLabel(DXBCByteWriter *w, uint32_t label) +{ + VGPU10OpcodeToken0 opcode; + VGPU10OperandToken0 operand; + + opcode.value = 0; + opcode.opcodeType = VGPU10_OPCODE_LABEL; + opcode.instructionLength = 3; + dxbcByteWriterAddTokens(w, &opcode.value, 1); + + operand.value = 0; + operand.numComponents = VGPU10_OPERAND_1_COMPONENT; + operand.operandType = VGPU10_OPERAND_TYPE_LABEL; + operand.indexDimension = VGPU10_OPERAND_INDEX_1D; + operand.index0Representation = VGPU10_OPERAND_INDEX_IMMEDIATE32; + dxbcByteWriterAddTokens(w, &operand.value, 1); + dxbcByteWriterAddTokens(w, &label, 1); +} + + +static void dxbcEmitRet(DXBCByteWriter *w) +{ + VGPU10OpcodeToken0 opcode; + + opcode.value = 0; + opcode.opcodeType = VGPU10_OPCODE_RET; + opcode.instructionLength = 1; + dxbcByteWriterAddTokens(w, &opcode.value, 1); +} + + +static int dxbcEmitVmwareIDIV(DXBCOUTPUTCTX *pOutctx, DXBCByteWriter *w, VGPUOpcode *pOpcode) +{ + /* Insert a call and append a subroutne. */ + VGPU10OpcodeToken0 opcode; + + uint32_t const label = (pOutctx->offSubroutine - dxbcByteWriterSize(w)) / 4; + + dxbcEmitCall(w, pOpcode, label); + + /* + * Subroutine. + */ + DXBCByteWriterState savedWriterState; + if (!dxbcByteWriterSetOffset(w, pOutctx->offSubroutine, &savedWriterState)) + return w->rc; + + dxbcEmitLabel(w, label); + + /* Just output UDIV for now. */ + opcode.value = 0; + opcode.opcodeType = VGPU10_OPCODE_UDIV; + opcode.instructionLength = pOpcode->cOpcodeToken; + dxbcByteWriterAddTokens(w, &opcode.value, 1); + dxbcByteWriterAddTokens(w, &pOpcode->paOpcodeToken[1], pOpcode->cOpcodeToken - 1); + + dxbcEmitRet(w); + + pOutctx->offSubroutine = dxbcByteWriterSize(w); + dxbcByteWriterRestore(w, &savedWriterState); + + return w->rc; +} + + +static int dxbcEmitVmwareDFRC(DXBCOUTPUTCTX *pOutctx, DXBCByteWriter *w, VGPUOpcode *pOpcode) +{ + /* Insert a call and append a subroutine. */ + VGPU10OpcodeToken0 opcode; + + uint32_t const label = (pOutctx->offSubroutine - dxbcByteWriterSize(w)) / 4; + + dxbcEmitCall(w, pOpcode, label); + + /* + * Subroutine. + */ + DXBCByteWriterState savedWriterState; + if (!dxbcByteWriterSetOffset(w, pOutctx->offSubroutine, &savedWriterState)) + return w->rc; + + dxbcEmitLabel(w, label); + + /* Just output a MOV for now. */ + opcode.value = 0; + opcode.opcodeType = VGPU10_OPCODE_MOV; + opcode.instructionLength = pOpcode->cOpcodeToken; + dxbcByteWriterAddTokens(w, &opcode.value, 1); + dxbcByteWriterAddTokens(w, &pOpcode->paOpcodeToken[1], pOpcode->cOpcodeToken - 1); + + dxbcEmitRet(w); + + pOutctx->offSubroutine = dxbcByteWriterSize(w); + dxbcByteWriterRestore(w, &savedWriterState); + + return w->rc; +} + + +static int dxbcEmitVmwareDRSQ(DXBCOUTPUTCTX *pOutctx, DXBCByteWriter *w, VGPUOpcode *pOpcode) +{ + /* Insert a call and append a subroutine. */ + VGPU10OpcodeToken0 opcode; + + uint32_t const label = (pOutctx->offSubroutine - dxbcByteWriterSize(w)) / 4; + + dxbcEmitCall(w, pOpcode, label); + + /* + * Subroutine. + */ + DXBCByteWriterState savedWriterState; + if (!dxbcByteWriterSetOffset(w, pOutctx->offSubroutine, &savedWriterState)) + return w->rc; + + dxbcEmitLabel(w, label); + + /* Just output a MOV for now. */ + opcode.value = 0; + opcode.opcodeType = VGPU10_OPCODE_MOV; + opcode.instructionLength = pOpcode->cOpcodeToken; + dxbcByteWriterAddTokens(w, &opcode.value, 1); + dxbcByteWriterAddTokens(w, &pOpcode->paOpcodeToken[1], pOpcode->cOpcodeToken - 1); + + dxbcEmitRet(w); + + pOutctx->offSubroutine = dxbcByteWriterSize(w); + dxbcByteWriterRestore(w, &savedWriterState); + + return w->rc; +} + + +static int dxbcOutputOpcode(DXBCOUTPUTCTX *pOutctx, DXBCByteWriter *w, VGPUOpcode *pOpcode) +{ +#ifdef DEBUG + void *pvBegin = dxbcByteWriterPtr(w); +#endif + + if ( pOutctx->programToken.programType == VGPU10_PIXEL_SHADER + && pOpcode->opcodeType == VGPU10_OPCODE_DCL_RESOURCE) + { + /** @todo This is a workaround. */ + /* Sometimes the guest (Mesa) created a shader with uninitialized resource dimension. + * Use texture 2d because it is what a pixel shader normally uses. + */ + ASSERT_GUEST_RETURN(pOpcode->cOpcodeToken == 4, VERR_INVALID_PARAMETER); + + VGPU10OpcodeToken0 opcode; + opcode.value = pOpcode->paOpcodeToken[0]; + if (opcode.resourceDimension == VGPU10_RESOURCE_DIMENSION_BUFFER) + { + opcode.resourceDimension = VGPU10_RESOURCE_DIMENSION_TEXTURE2D; + dxbcByteWriterAddTokens(w, &opcode.value, 1); + dxbcByteWriterAddTokens(w, &pOpcode->paOpcodeToken[1], 2); + uint32_t const returnType = 0x5555; /* float */ + dxbcByteWriterAddTokens(w, &returnType, 1); + return VINF_SUCCESS; + } + } + else if (pOpcode->opcodeType == VGPU10_OPCODE_VMWARE) + { + if (pOpcode->opcodeSubtype == VGPU10_VMWARE_OPCODE_IDIV) + return dxbcEmitVmwareIDIV(pOutctx, w, pOpcode); + if (pOpcode->opcodeSubtype == VGPU10_VMWARE_OPCODE_DFRC) + return dxbcEmitVmwareDFRC(pOutctx, w, pOpcode); + if (pOpcode->opcodeSubtype == VGPU10_VMWARE_OPCODE_DRSQ) + return dxbcEmitVmwareDRSQ(pOutctx, w, pOpcode); + + ASSERT_GUEST_FAILED_RETURN(VERR_NOT_SUPPORTED); + } + +#ifdef DEBUG + /* The code above must emit either nothing or everything. */ + Assert((uintptr_t)pvBegin == (uintptr_t)dxbcByteWriterPtr(w)); +#endif + + /* Just emit the unmodified instruction. */ + dxbcByteWriterAddTokens(w, pOpcode->paOpcodeToken, pOpcode->cOpcodeToken); + return VINF_SUCCESS; +} + + +static int dxbcOutputFinalize(DXBCOUTPUTCTX *pOutctx, DXBCByteWriter *w) +{ + RT_NOREF(pOutctx, w); + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) signatureEntryCmp(void const *pvElement1, void const *pvElement2, void *pvUser) +{ + SVGA3dDXSignatureEntry const *e1 = (SVGA3dDXSignatureEntry *)pvElement1; + SVGA3dDXSignatureEntry const *e2 = (SVGA3dDXSignatureEntry *)pvElement2; + RT_NOREF(pvUser); + + if (e1->registerIndex < e2->registerIndex) + return -1; + if (e1->registerIndex > e2->registerIndex) + return 1; + if ((e1->mask & 0xf) < (e2->mask & 0xf)) + return -1; + if ((e1->mask & 0xf) > (e2->mask & 0xf)) + return 1; + return 0; +} + + +static void dxbcGenerateSemantics(DXShaderInfo *pInfo, uint32_t cSignature, + SVGA3dDXSignatureEntry *paSignature, + DXShaderAttributeSemantic *paSemantic, + uint32_t u32BlobType); + + +/* + * Parse and verify the shader byte code. Extract input and output signatures into pInfo. + */ +int DXShaderParse(void const *pvShaderCode, uint32_t cbShaderCode, DXShaderInfo *pInfo) +{ + if (pInfo) + RT_ZERO(*pInfo); + + ASSERT_GUEST_RETURN(cbShaderCode <= SVGA3D_MAX_SHADER_MEMORY_BYTES, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN((cbShaderCode & 0x3) == 0, VERR_INVALID_PARAMETER); /* Aligned to the token size. */ + ASSERT_GUEST_RETURN(cbShaderCode >= 8, VERR_INVALID_PARAMETER); /* At least program and length tokens. */ + + uint32_t const *paToken = (uint32_t *)pvShaderCode; + + VGPU10ProgramToken const *pProgramToken = (VGPU10ProgramToken *)&paToken[0]; + ASSERT_GUEST_RETURN( pProgramToken->majorVersion >= 4 + && pProgramToken->programType <= VGPU10_COMPUTE_SHADER, VERR_INVALID_PARAMETER); + if (pInfo) + pInfo->enmProgramType = (VGPU10_PROGRAM_TYPE)pProgramToken->programType; + + uint32_t const cToken = paToken[1]; + Log6(("Shader version %d.%d type %s(%d) Length %d\n", + pProgramToken->majorVersion, pProgramToken->minorVersion, dxbcShaderTypeToString(pProgramToken->programType), pProgramToken->programType, cToken)); + ASSERT_GUEST_RETURN(cbShaderCode / 4 >= cToken, VERR_INVALID_PARAMETER); /* Declared length should be less or equal to the actual. */ + + /* Write the parsed (and possibly modified) shader to a memory buffer. */ + DXBCByteWriter dxbcByteWriter; + DXBCByteWriter *w = &dxbcByteWriter; + if (!dxbcByteWriterInit(w, 4096 + cbShaderCode)) + return VERR_NO_MEMORY; + + dxbcByteWriterAddTokens(w, paToken, 2); + + DXBCTokenReader parser; + RT_ZERO(parser); + + DXBCTokenReader *r = &parser; + r->pToken = &paToken[2]; + r->cToken = r->cRemainingToken = cToken - 2; + + DXBCOUTPUTCTX outctx; + dxbcOutputInit(&outctx, pProgramToken, cToken); + + int rc = VINF_SUCCESS; + while (dxbcTokenReaderCanRead(r, 1)) + { + uint32_t const offOpcode = dxbcByteWriterSize(w); + + VGPUOpcode opcode; + rc = dxbcParseOpcode(r, &opcode); + ASSERT_GUEST_STMT_BREAK(RT_SUCCESS(rc), rc = VERR_INVALID_PARAMETER); + + rc = dxbcOutputOpcode(&outctx, w, &opcode); + AssertRCBreak(rc); + + if (pInfo) + { + /* Remember offsets of DCL_RESOURCE instructions. */ + if ( outctx.programToken.programType == VGPU10_PIXEL_SHADER + && opcode.opcodeType == VGPU10_OPCODE_DCL_RESOURCE) + { + if ( opcode.cOperand == 1 + && opcode.aValOperand[0].indexDimension == VGPU10_OPERAND_INDEX_1D + && opcode.aValOperand[0].aOperandIndex[0].indexRepresentation == VGPU10_OPERAND_INDEX_IMMEDIATE32) + { + uint32_t const indexResource = opcode.aValOperand[0].aOperandIndex[0].iOperandImmediate; + if (indexResource < SVGA3D_DX_MAX_SRVIEWS) + { + ASSERT_GUEST(pInfo->aOffDclResource[indexResource] == 0); + pInfo->aOffDclResource[indexResource] = offOpcode; + pInfo->cDclResource = RT_MAX(pInfo->cDclResource, indexResource + 1); + } + else + ASSERT_GUEST_FAILED(); + } + else + ASSERT_GUEST_FAILED(); + } + + /* Fetch signatures. */ + SVGA3dDXSignatureEntry *pSignatureEntry = NULL; + switch (opcode.opcodeType) + { + case VGPU10_OPCODE_DCL_INPUT: + case VGPU10_OPCODE_DCL_INPUT_SIV: + //case VGPU10_OPCODE_DCL_INPUT_SGV: + case VGPU10_OPCODE_DCL_INPUT_PS: + //case VGPU10_OPCODE_DCL_INPUT_PS_SIV: + //case VGPU10_OPCODE_DCL_INPUT_PS_SGV: + //case VGPU10_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + ASSERT_GUEST_STMT_BREAK(pInfo->cInputSignature < RT_ELEMENTS(pInfo->aInputSignature), rc = VERR_INVALID_PARAMETER); + pSignatureEntry = &pInfo->aInputSignature[pInfo->cInputSignature++]; + break; + case VGPU10_OPCODE_DCL_OUTPUT: + case VGPU10_OPCODE_DCL_OUTPUT_SIV: + case VGPU10_OPCODE_DCL_OUTPUT_SGV: + //case VGPU10_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + ASSERT_GUEST_STMT_BREAK(pInfo->cOutputSignature < RT_ELEMENTS(pInfo->aOutputSignature), rc = VERR_INVALID_PARAMETER); + pSignatureEntry = &pInfo->aOutputSignature[pInfo->cOutputSignature++]; + break; + default: + break; + } + + if (RT_FAILURE(rc)) + break; + + if (pSignatureEntry) + { + ASSERT_GUEST_STMT_BREAK( opcode.aValOperand[0].aOperandIndex[0].indexRepresentation == VGPU10_OPERAND_INDEX_IMMEDIATE32 + || opcode.aValOperand[0].aOperandIndex[0].indexRepresentation == VGPU10_OPERAND_INDEX_IMMEDIATE64, + rc = VERR_NOT_SUPPORTED); + + uint32_t const indexDimension = opcode.aValOperand[0].indexDimension; + if (indexDimension == VGPU10_OPERAND_INDEX_0D) + { + if (opcode.aValOperand[0].operandType == VGPU10_OPERAND_TYPE_INPUT_PRIMITIVEID) + { + pSignatureEntry->registerIndex = 0; + pSignatureEntry->semanticName = SVGADX_SIGNATURE_SEMANTIC_NAME_PRIMITIVE_ID; + } + else if (opcode.aValOperand[0].operandType == VGPU10_OPERAND_TYPE_OUTPUT_DEPTH) + { + /* oDepth is always last in the signature. Register index is equal to 0xFFFFFFFF. */ + pSignatureEntry->registerIndex = 0xFFFFFFFF; + pSignatureEntry->semanticName = SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED; + } + else if (opcode.aValOperand[0].operandType <= VGPU10_OPERAND_TYPE_SM50_MAX) + { + pSignatureEntry->registerIndex = 0; + pSignatureEntry->semanticName = opcode.semanticName; + } + else + ASSERT_GUEST_FAILED_STMT_BREAK(rc = VERR_NOT_SUPPORTED); + } + else + { + ASSERT_GUEST_STMT_BREAK( indexDimension == VGPU10_OPERAND_INDEX_1D + || indexDimension == VGPU10_OPERAND_INDEX_2D + || indexDimension == VGPU10_OPERAND_INDEX_3D, + rc = VERR_NOT_SUPPORTED); + /* The register index seems to be in the highest dimension. */ + pSignatureEntry->registerIndex = opcode.aValOperand[0].aOperandIndex[indexDimension - VGPU10_OPERAND_INDEX_1D].iOperandImmediate; + pSignatureEntry->semanticName = opcode.semanticName; + } + pSignatureEntry->mask = opcode.aValOperand[0].mask; + pSignatureEntry->componentType = SVGADX_SIGNATURE_REGISTER_COMPONENT_UNKNOWN; // Will be updated by vboxDXUpdateVSInputSignature + pSignatureEntry->minPrecision = SVGADX_SIGNATURE_MIN_PRECISION_DEFAULT; + } + } + } + + if (RT_FAILURE(rc)) + { + return rc; + } + + rc = dxbcOutputFinalize(&outctx, w); + if (RT_FAILURE(rc)) + { + return rc; + } + + dxbcByteWriterFetchData(w, &pInfo->pvBytecode, &pInfo->cbBytecode); + uint32_t *pcOutputToken = (uint32_t *)pInfo->pvBytecode + 1; + *pcOutputToken = pInfo->cbBytecode / 4; + + /* Sort signatures by register index and mask because the host API need them to be sorted. */ + if (pInfo->cInputSignature) + { + RTSortShell(pInfo->aInputSignature, pInfo->cInputSignature, sizeof(pInfo->aInputSignature[0]), + signatureEntryCmp, NULL); + dxbcGenerateSemantics(pInfo, pInfo->cInputSignature, + pInfo->aInputSignature, + pInfo->aInputSemantic, DXBC_BLOB_TYPE_ISGN); + } + if (pInfo->cOutputSignature) + { + RTSortShell(pInfo->aOutputSignature, pInfo->cOutputSignature, sizeof(pInfo->aOutputSignature[0]), + signatureEntryCmp, NULL); + dxbcGenerateSemantics(pInfo, pInfo->cOutputSignature, + pInfo->aOutputSignature, + pInfo->aOutputSemantic, DXBC_BLOB_TYPE_OSGN); + } + if (pInfo->cPatchConstantSignature) + { + RTSortShell(pInfo->aPatchConstantSignature, pInfo->cPatchConstantSignature, sizeof(pInfo->aPatchConstantSignature[0]), + signatureEntryCmp, NULL); + dxbcGenerateSemantics(pInfo, pInfo->cPatchConstantSignature, + pInfo->aPatchConstantSignature, + pInfo->aPatchConstantSemantic, DXBC_BLOB_TYPE_PCSG); + } + +#ifdef LOG_ENABLED + if (pInfo->cInputSignature) + { + Log6(("Input signatures:\n")); + for (uint32_t i = 0; i < pInfo->cInputSignature; ++i) + Log6((" [%u]: %u %u 0x%X, %s %d\n", + i, pInfo->aInputSignature[i].registerIndex, pInfo->aInputSignature[i].semanticName, pInfo->aInputSignature[i].mask, + pInfo->aInputSemantic[i].pcszSemanticName, pInfo->aInputSemantic[i].SemanticIndex)); + } + if (pInfo->cOutputSignature) + { + Log6(("Output signatures:\n")); + for (uint32_t i = 0; i < pInfo->cOutputSignature; ++i) + Log6((" [%u]: %u %u 0x%X, %s %d\n", + i, pInfo->aOutputSignature[i].registerIndex, pInfo->aOutputSignature[i].semanticName, pInfo->aOutputSignature[i].mask, + pInfo->aOutputSemantic[i].pcszSemanticName, pInfo->aOutputSemantic[i].SemanticIndex)); + } + if (pInfo->cPatchConstantSignature) + { + Log6(("Patch constant signatures:\n")); + for (uint32_t i = 0; i < pInfo->cPatchConstantSignature; ++i) + Log6((" [%u]: %u %u 0x%X, %s %d\n", + i, pInfo->aPatchConstantSignature[i].registerIndex, pInfo->aPatchConstantSignature[i].semanticName, pInfo->aPatchConstantSignature[i].mask, + pInfo->aPatchConstantSemantic[i].pcszSemanticName, pInfo->aPatchConstantSemantic[i].SemanticIndex)); + } +#endif + + return VINF_SUCCESS; +} + + +void DXShaderGenerateSemantics(DXShaderInfo *pInfo) +{ + if (pInfo->cInputSignature) + dxbcGenerateSemantics(pInfo, pInfo->cInputSignature, + pInfo->aInputSignature, + pInfo->aInputSemantic, DXBC_BLOB_TYPE_ISGN); + if (pInfo->cOutputSignature) + dxbcGenerateSemantics(pInfo, pInfo->cOutputSignature, + pInfo->aOutputSignature, + pInfo->aOutputSemantic, DXBC_BLOB_TYPE_OSGN); + if (pInfo->cPatchConstantSignature) + dxbcGenerateSemantics(pInfo, pInfo->cPatchConstantSignature, + pInfo->aPatchConstantSignature, + pInfo->aPatchConstantSemantic, DXBC_BLOB_TYPE_PCSG); +} + + +void DXShaderSortSignatures(DXShaderInfo *pInfo) +{ + /* Sort signatures by register index and mask because the host API need them to be sorted. */ + if (pInfo->cInputSignature) + { + RTSortShell(pInfo->aInputSignature, pInfo->cInputSignature, sizeof(pInfo->aInputSignature[0]), + signatureEntryCmp, NULL); + } + if (pInfo->cOutputSignature) + { + RTSortShell(pInfo->aOutputSignature, pInfo->cOutputSignature, sizeof(pInfo->aOutputSignature[0]), + signatureEntryCmp, NULL); + } + if (pInfo->cPatchConstantSignature) + { + RTSortShell(pInfo->aPatchConstantSignature, pInfo->cPatchConstantSignature, sizeof(pInfo->aPatchConstantSignature[0]), + signatureEntryCmp, NULL); + } +} + + +void DXShaderFree(DXShaderInfo *pInfo) +{ + RTMemFree(pInfo->pvBytecode); + RT_ZERO(*pInfo); +} + + +#if 0 // Unused. Replaced with dxbcSemanticInfo. +static char const *dxbcSemanticName(SVGA3dDXSignatureSemanticName enmSemanticName) +{ + /* https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics#system-value-semantics */ + switch (enmSemanticName) + { + case SVGADX_SIGNATURE_SEMANTIC_NAME_POSITION: return "SV_Position"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_CLIP_DISTANCE: return "SV_ClipDistance"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_CULL_DISTANCE: return "SV_CullDistance"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_RENDER_TARGET_ARRAY_INDEX: return "SV_RenderTargetArrayIndex"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_VIEWPORT_ARRAY_INDEX: return "SV_ViewportArrayIndex"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_VERTEX_ID: return "SV_VertexID"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_PRIMITIVE_ID: return "SV_PrimitiveID"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_INSTANCE_ID: return "SV_InstanceID"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_IS_FRONT_FACE: return "SV_IsFrontFace"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_SAMPLE_INDEX: return "SV_SampleIndex"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: return "SV_FinalQuadUeq0EdgeTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: return "SV_FinalQuadVeq0EdgeTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: return "SV_FinalQuadUeq1EdgeTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: return "SV_FinalQuadVeq1EdgeTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: return "SV_FinalQuadUInsideTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: return "SV_FinalQuadVInsideTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: return "SV_FinalTriUeq0EdgeTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: return "SV_FinalTriVeq0EdgeTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: return "SV_FinalTriWeq0EdgeTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_INSIDE_TESSFACTOR: return "SV_FinalTriInsideTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DETAIL_TESSFACTOR: return "SV_FinalLineDetailTessFactor"; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DENSITY_TESSFACTOR: return "SV_FinalLineDensityTessFactor"; + default: + Assert(enmSemanticName == SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED); + break; + } + /* Generic. Arbitrary name. It does not have any meaning. */ + return "ATTRIB"; +} +#endif + + +/* https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics#system-value-semantics + * Type: + * 0 - undefined + * 1 - unsigned int + * 2 - signed int + * 3 - float + */ +typedef struct VGPUSemanticInfo +{ + char const *pszName; + uint32_t u32Type; +} VGPUSemanticInfo; + +static VGPUSemanticInfo const g_aSemanticInfo[SVGADX_SIGNATURE_SEMANTIC_NAME_MAX] = +{ + { "ATTRIB", 0 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED 0 + { "SV_Position", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_POSITION 1 + { "SV_ClipDistance", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_CLIP_DISTANCE 2 + { "SV_CullDistance", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_CULL_DISTANCE 3 + { "SV_RenderTargetArrayIndex", 1 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_RENDER_TARGET_ARRAY_INDEX 4 + { "SV_ViewportArrayIndex", 1 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_VIEWPORT_ARRAY_INDEX 5 + { "SV_VertexID", 1 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_VERTEX_ID 6 + { "SV_PrimitiveID", 1 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_PRIMITIVE_ID 7 + { "SV_InstanceID", 1 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_INSTANCE_ID 8 + { "SV_IsFrontFace", 1 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_IS_FRONT_FACE 9 + { "SV_SampleIndex", 1 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_SAMPLE_INDEX 10 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR 11 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR 12 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR 13 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR 14 + { "SV_InsideTessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR 15 + { "SV_InsideTessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR 16 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR 17 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR 18 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR 19 + { "SV_InsideTessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_INSIDE_TESSFACTOR 20 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DETAIL_TESSFACTOR 21 + { "SV_TessFactor", 3 }, // SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DENSITY_TESSFACTOR 22 +}; + +static VGPUSemanticInfo const g_SemanticPSOutput = + { "SV_TARGET", 3 }; // SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED 0 + + +/* A clone of D3D_NAME */ +typedef enum +{ + D3D_SV_UNDEFINED = 0, + D3D_SV_POSITION = 1, + D3D_SV_CLIP_DISTANCE = 2, + D3D_SV_CULL_DISTANCE = 3, + D3D_SV_RENDER_TARGET_ARRAY_INDEX = 4, + D3D_SV_VIEWPORT_ARRAY_INDEX = 5, + D3D_SV_VERTEX_ID = 6, + D3D_SV_PRIMITIVE_ID = 7, + D3D_SV_INSTANCE_ID = 8, + D3D_SV_IS_FRONT_FACE = 9, + D3D_SV_SAMPLE_INDEX = 10, + D3D_SV_FINAL_QUAD_EDGE_TESSFACTOR = 11, + D3D_SV_FINAL_QUAD_INSIDE_TESSFACTOR = 12, + D3D_SV_FINAL_TRI_EDGE_TESSFACTOR = 13, + D3D_SV_FINAL_TRI_INSIDE_TESSFACTOR = 14, + D3D_SV_FINAL_LINE_DETAIL_TESSFACTOR = 15, + D3D_SV_FINAL_LINE_DENSITY_TESSFACTOR = 16 +} D3DSYSTEMVALUE; + +static uint32_t svga2dxSystemValue(SVGA3dDXSignatureSemanticName semanticName) +{ + switch (semanticName) + { + case SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED: return D3D_SV_UNDEFINED; + case SVGADX_SIGNATURE_SEMANTIC_NAME_POSITION: return D3D_SV_POSITION; + case SVGADX_SIGNATURE_SEMANTIC_NAME_CLIP_DISTANCE: return D3D_SV_CLIP_DISTANCE; + case SVGADX_SIGNATURE_SEMANTIC_NAME_CULL_DISTANCE: return D3D_SV_CULL_DISTANCE; + case SVGADX_SIGNATURE_SEMANTIC_NAME_RENDER_TARGET_ARRAY_INDEX: return D3D_SV_RENDER_TARGET_ARRAY_INDEX; + case SVGADX_SIGNATURE_SEMANTIC_NAME_VIEWPORT_ARRAY_INDEX: return D3D_SV_VIEWPORT_ARRAY_INDEX; + case SVGADX_SIGNATURE_SEMANTIC_NAME_VERTEX_ID: return D3D_SV_VERTEX_ID; + case SVGADX_SIGNATURE_SEMANTIC_NAME_PRIMITIVE_ID: return D3D_SV_PRIMITIVE_ID; + case SVGADX_SIGNATURE_SEMANTIC_NAME_INSTANCE_ID: return D3D_SV_INSTANCE_ID; + case SVGADX_SIGNATURE_SEMANTIC_NAME_IS_FRONT_FACE: return D3D_SV_IS_FRONT_FACE; + case SVGADX_SIGNATURE_SEMANTIC_NAME_SAMPLE_INDEX: return D3D_SV_SAMPLE_INDEX; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: return D3D_SV_FINAL_QUAD_EDGE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: return D3D_SV_FINAL_QUAD_EDGE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: return D3D_SV_FINAL_QUAD_EDGE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: return D3D_SV_FINAL_QUAD_EDGE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: return D3D_SV_FINAL_QUAD_INSIDE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: return D3D_SV_FINAL_QUAD_INSIDE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: return D3D_SV_FINAL_TRI_EDGE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: return D3D_SV_FINAL_TRI_EDGE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: return D3D_SV_FINAL_TRI_EDGE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_INSIDE_TESSFACTOR: return D3D_SV_FINAL_TRI_INSIDE_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DETAIL_TESSFACTOR: return D3D_SV_FINAL_LINE_DETAIL_TESSFACTOR; + case SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DENSITY_TESSFACTOR: return D3D_SV_FINAL_LINE_DENSITY_TESSFACTOR; + } + + AssertFailedReturn(D3D_SV_UNDEFINED); +} + +static VGPUSemanticInfo const *dxbcSemanticInfo(DXShaderInfo const *pInfo, SVGA3dDXSignatureSemanticName enmSemanticName, uint32_t u32BlobType) +{ + if (enmSemanticName < RT_ELEMENTS(g_aSemanticInfo)) + { + if ( enmSemanticName == 0 + && pInfo->enmProgramType == VGPU10_PIXEL_SHADER + && u32BlobType == DXBC_BLOB_TYPE_OSGN) + return &g_SemanticPSOutput; + return &g_aSemanticInfo[enmSemanticName]; + } + return &g_aSemanticInfo[0]; +} + + +static void dxbcGenerateSemantics(DXShaderInfo *pInfo, uint32_t cSignature, + SVGA3dDXSignatureEntry *paSignature, + DXShaderAttributeSemantic *paSemantic, + uint32_t u32BlobType) +{ + for (uint32_t iSignatureEntry = 0; iSignatureEntry < cSignature; ++iSignatureEntry) + { + SVGA3dDXSignatureEntry *pSignatureEntry = &paSignature[iSignatureEntry]; + DXShaderAttributeSemantic *pSemantic = &paSemantic[iSignatureEntry]; + + ASSERT_GUEST_RETURN_VOID(pSignatureEntry->semanticName < SVGADX_SIGNATURE_SEMANTIC_NAME_MAX); + + VGPUSemanticInfo const *pSemanticInfo = dxbcSemanticInfo(pInfo, pSignatureEntry->semanticName, u32BlobType); + pSemantic->pcszSemanticName = pSemanticInfo->pszName; + pSemantic->SemanticIndex = 0; + if (pSignatureEntry->componentType == SVGADX_SIGNATURE_REGISTER_COMPONENT_UNKNOWN) + pSignatureEntry->componentType = pSemanticInfo->u32Type; + for (uint32_t i = 0; i < iSignatureEntry; ++i) + { + DXShaderAttributeSemantic const *pPriorSemantic = &paSemantic[i]; + if (RTStrCmp(pPriorSemantic->pcszSemanticName, pSemantic->pcszSemanticName) == 0) + ++pSemantic->SemanticIndex; + } + } +} + + +static int dxbcCreateIOSGNBlob(DXShaderInfo const *pInfo, DXBCHeader *pHdr, uint32_t u32BlobType, uint32_t cSignature, + SVGA3dDXSignatureEntry const *paSignature, DXShaderAttributeSemantic const *paSemantic, DXBCByteWriter *w) +{ + RT_NOREF(pInfo); + AssertReturn(cSignature <= SVGA3D_DX_SM41_MAX_VERTEXINPUTREGISTERS, VERR_INVALID_PARAMETER); + + uint32_t cbBlob = RT_UOFFSETOF_DYN(DXBCBlobIOSGN, aElement[cSignature]); + if (!dxbcByteWriterCanWrite(w, sizeof(DXBCBlobHeader) + cbBlob)) + return VERR_NO_MEMORY; + + Log6(("Create signature type %c%c%c%c (0x%RX32)\n", + RT_BYTE1(u32BlobType), RT_BYTE2(u32BlobType), RT_BYTE3(u32BlobType), RT_BYTE4(u32BlobType), u32BlobType)); + + DXBCBlobHeader *pHdrBlob = (DXBCBlobHeader *)dxbcByteWriterPtr(w); + pHdrBlob->u32BlobType = u32BlobType; + // pHdrBlob->cbBlob = 0; + + DXBCBlobIOSGN *pHdrISGN = (DXBCBlobIOSGN *)&pHdrBlob[1]; + pHdrISGN->cElement = cSignature; + pHdrISGN->offElement = RT_UOFFSETOF(DXBCBlobIOSGN, aElement[0]); + +#ifdef DEBUG + /* Check that signatures are sorted by register index because the host API need them to be sorted. */ + uint32_t idxRegisterLast = 0; +#endif + + for (uint32_t iSignatureEntry = 0; iSignatureEntry < cSignature; ++iSignatureEntry) + { + SVGA3dDXSignatureEntry const *srcEntry = &paSignature[iSignatureEntry]; + DXShaderAttributeSemantic const *srcSemantic = &paSemantic[iSignatureEntry]; + DXBCBlobIOSGNElement *dst = &pHdrISGN->aElement[iSignatureEntry]; + + dst->offElementName = 0; + for (uint32_t i = 0; i < iSignatureEntry; ++i) + { + DXBCBlobIOSGNElement const *pElement = &pHdrISGN->aElement[i]; + char const *pszElementName = (char *)pHdrISGN + pElement->offElementName; + if (RTStrCmp(pszElementName, srcSemantic->pcszSemanticName) == 0) + { + dst->offElementName = pElement->offElementName; + break; + } + } + dst->idxSemantic = srcSemantic->SemanticIndex; + dst->enmSystemValue = svga2dxSystemValue(srcEntry->semanticName); + dst->enmComponentType = srcEntry->componentType; + dst->idxRegister = srcEntry->registerIndex; + dst->u.mask = srcEntry->mask; + + Log6((" [%u]: %s[%u] sv %u type %u reg %u mask %X\n", + iSignatureEntry, srcSemantic->pcszSemanticName, dst->idxSemantic, + dst->enmSystemValue, dst->enmComponentType, dst->idxRegister, dst->u.mask)); + +#ifdef DEBUG + Assert(idxRegisterLast <= dst->idxRegister); + idxRegisterLast = dst->idxRegister; +#endif + + if (dst->offElementName == 0) + { + /* Store the semantic name for this element. */ + dst->offElementName = cbBlob; /* Offset of the semantic's name relative to the start of the blob (without DXBCBlobHeader). */ + uint32_t const cbElementName = (uint32_t)strlen(srcSemantic->pcszSemanticName) + 1; + if (!dxbcByteWriterCanWrite(w, sizeof(DXBCBlobHeader) + cbBlob + cbElementName)) + return VERR_NO_MEMORY; + + memcpy((char *)pHdrISGN + dst->offElementName, srcSemantic->pcszSemanticName, cbElementName); + cbBlob += cbElementName; + } + } + + /* Blobs are 4 bytes aligned. Commit the blob data. */ + cbBlob = RT_ALIGN_32(cbBlob, 4); + pHdrBlob->cbBlob = cbBlob; + pHdr->cbTotal += cbBlob + sizeof(DXBCBlobHeader); + dxbcByteWriterCommit(w, cbBlob + sizeof(DXBCBlobHeader)); + return VINF_SUCCESS; +} + + +static int dxbcCreateSHDRBlob(DXBCHeader *pHdr, uint32_t u32BlobType, + void const *pvShader, uint32_t cbShader, DXBCByteWriter *w) +{ + uint32_t cbBlob = cbShader; + if (!dxbcByteWriterCanWrite(w, sizeof(DXBCBlobHeader) + cbBlob)) + return VERR_NO_MEMORY; + + DXBCBlobHeader *pHdrBlob = (DXBCBlobHeader *)dxbcByteWriterPtr(w); + pHdrBlob->u32BlobType = u32BlobType; + // pHdrBlob->cbBlob = 0; + + memcpy(&pHdrBlob[1], pvShader, cbShader); + + /* Blobs are 4 bytes aligned. Commit the blob data. */ + cbBlob = RT_ALIGN_32(cbBlob, 4); + pHdrBlob->cbBlob = cbBlob; + pHdr->cbTotal += cbBlob + sizeof(DXBCBlobHeader); + dxbcByteWriterCommit(w, cbBlob + sizeof(DXBCBlobHeader)); + return VINF_SUCCESS; +} + + +/* + * Create a DXBC container with signature and shader code data blobs. + */ +static int dxbcCreateFromInfo(DXShaderInfo const *pInfo, void const *pvShader, uint32_t cbShader, DXBCByteWriter *w) +{ + int rc; + + /* Create a DXBC container with ISGN, OSGN and SHDR blobs. */ + uint32_t cBlob = 3; + if ( pInfo->enmProgramType == VGPU10_HULL_SHADER + || pInfo->enmProgramType == VGPU10_DOMAIN_SHADER) + ++cBlob; + + uint32_t const cbHdr = RT_UOFFSETOF_DYN(DXBCHeader, aBlobOffset[cBlob]); /* Header with blob offsets. */ + if (!dxbcByteWriterCanWrite(w, cbHdr)) + return VERR_NO_MEMORY; + + /* Container header. */ + DXBCHeader *pHdr = (DXBCHeader *)dxbcByteWriterPtr(w); + pHdr->u32DXBC = DXBC_MAGIC; + // RT_ZERO(pHdr->au8Hash); + pHdr->u32Version = 1; + pHdr->cbTotal = cbHdr; + pHdr->cBlob = cBlob; + //RT_ZERO(pHdr->aBlobOffset); + dxbcByteWriterCommit(w, cbHdr); + +#ifdef LOG_ENABLED + if (pInfo->cInputSignature) + { + Log6(("Input signatures:\n")); + for (uint32_t i = 0; i < pInfo->cInputSignature; ++i) + Log6((" [%u]: %u %u 0x%X, %s %d\n", + i, pInfo->aInputSignature[i].registerIndex, pInfo->aInputSignature[i].semanticName, pInfo->aInputSignature[i].mask, + pInfo->aInputSemantic[i].pcszSemanticName, pInfo->aInputSemantic[i].SemanticIndex)); + } + if (pInfo->cOutputSignature) + { + Log6(("Output signatures:\n")); + for (uint32_t i = 0; i < pInfo->cOutputSignature; ++i) + Log6((" [%u]: %u %u 0x%X, %s %d\n", + i, pInfo->aOutputSignature[i].registerIndex, pInfo->aOutputSignature[i].semanticName, pInfo->aOutputSignature[i].mask, + pInfo->aOutputSemantic[i].pcszSemanticName, pInfo->aOutputSemantic[i].SemanticIndex)); + } + if (pInfo->cPatchConstantSignature) + { + Log6(("Patch constant signatures:\n")); + for (uint32_t i = 0; i < pInfo->cPatchConstantSignature; ++i) + Log6((" [%u]: %u %u 0x%X, %s %d\n", + i, pInfo->aPatchConstantSignature[i].registerIndex, pInfo->aPatchConstantSignature[i].semanticName, pInfo->aPatchConstantSignature[i].mask, + pInfo->aPatchConstantSemantic[i].pcszSemanticName, pInfo->aPatchConstantSemantic[i].SemanticIndex)); + } +#endif + + /* Blobs. */ + uint32_t iBlob = 0; + + pHdr->aBlobOffset[iBlob++] = dxbcByteWriterSize(w); + rc = dxbcCreateIOSGNBlob(pInfo, pHdr, DXBC_BLOB_TYPE_ISGN, pInfo->cInputSignature, &pInfo->aInputSignature[0], pInfo->aInputSemantic, w); + AssertRCReturn(rc, rc); + + pHdr->aBlobOffset[iBlob++] = dxbcByteWriterSize(w); + rc = dxbcCreateIOSGNBlob(pInfo, pHdr, DXBC_BLOB_TYPE_OSGN, pInfo->cOutputSignature, &pInfo->aOutputSignature[0], pInfo->aOutputSemantic, w); + AssertRCReturn(rc, rc); + + if ( pInfo->enmProgramType == VGPU10_HULL_SHADER + || pInfo->enmProgramType == VGPU10_DOMAIN_SHADER) + { + pHdr->aBlobOffset[iBlob++] = dxbcByteWriterSize(w); + rc = dxbcCreateIOSGNBlob(pInfo, pHdr, DXBC_BLOB_TYPE_PCSG, pInfo->cPatchConstantSignature, &pInfo->aPatchConstantSignature[0], pInfo->aPatchConstantSemantic, w); + AssertRCReturn(rc, rc); + } + + pHdr->aBlobOffset[iBlob++] = dxbcByteWriterSize(w); + rc = dxbcCreateSHDRBlob(pHdr, DXBC_BLOB_TYPE_SHDR, pvShader, cbShader, w); + AssertRCReturn(rc, rc); + + Assert(iBlob == cBlob); + + AssertCompile(RT_UOFFSETOF(DXBCHeader, u32Version) == 0x14); + dxbcHash(&pHdr->u32Version, pHdr->cbTotal - RT_UOFFSETOF(DXBCHeader, u32Version), pHdr->au8Hash); + + return VINF_SUCCESS; +} + + +int DXShaderCreateDXBC(DXShaderInfo const *pInfo, void **ppvDXBC, uint32_t *pcbDXBC) +{ + /* Build DXBC container. */ + int rc; + DXBCByteWriter dxbcByteWriter; + DXBCByteWriter *w = &dxbcByteWriter; + if (dxbcByteWriterInit(w, 4096 + pInfo->cbBytecode)) + { + rc = dxbcCreateFromInfo(pInfo, pInfo->pvBytecode, pInfo->cbBytecode, w); + if (RT_SUCCESS(rc)) + dxbcByteWriterFetchData(w, ppvDXBC, pcbDXBC); + } + else + rc = VERR_NO_MEMORY; + return rc; +} + + +static char const *dxbcGetOutputSemanticName(DXShaderInfo const *pInfo, uint32_t idxRegister, uint32_t u32BlobType, + uint32_t cSignature, SVGA3dDXSignatureEntry const *paSignature, + SVGA3dDXSignatureSemanticName *pSemanticName) +{ + for (uint32_t i = 0; i < cSignature; ++i) + { + SVGA3dDXSignatureEntry const *p = &paSignature[i]; + if (p->registerIndex == idxRegister) + { + AssertReturn(p->semanticName < SVGADX_SIGNATURE_SEMANTIC_NAME_MAX, NULL); + VGPUSemanticInfo const *pSemanticInfo = dxbcSemanticInfo(pInfo, p->semanticName, u32BlobType); + *pSemanticName = p->semanticName; + return pSemanticInfo->pszName; + } + } + return NULL; +} + +char const *DXShaderGetOutputSemanticName(DXShaderInfo const *pInfo, uint32_t idxRegister, SVGA3dDXSignatureSemanticName *pSemanticName) +{ + return dxbcGetOutputSemanticName(pInfo, idxRegister, DXBC_BLOB_TYPE_OSGN, pInfo->cOutputSignature, &pInfo->aOutputSignature[0], pSemanticName); +} + +VGPU10_RESOURCE_RETURN_TYPE DXShaderResourceReturnTypeFromFormat(SVGA3dSurfaceFormat format) +{ + /** @todo This is auto-generated from format names and needs a review. */ + switch (format) + { + case SVGA3D_R32G32B32A32_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R32G32B32A32_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_R32G32B32_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_R32G32B32_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R32G32B32_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_R16G16B16A16_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R16G16B16A16_SNORM: return VGPU10_RETURN_TYPE_SNORM; + case SVGA3D_R16G16B16A16_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_R32G32_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R32G32_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_D32_FLOAT_S8X24_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R32_FLOAT_X8X24: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_X32_G8X24_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R10G10B10A2_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R11G11B10_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_R8G8B8A8_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R8G8B8A8_UNORM_SRGB: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R8G8B8A8_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R8G8B8A8_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_R16G16_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R16G16_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_D32_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_R32_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R32_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_D24_UNORM_S8_UINT: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R24_UNORM_X8: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_X24_G8_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R8G8_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R8G8_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R8G8_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_R16_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R16_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R16_SNORM: return VGPU10_RETURN_TYPE_SNORM; + case SVGA3D_R16_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_R8_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R8_UINT: return VGPU10_RETURN_TYPE_UINT; + case SVGA3D_R8_SNORM: return VGPU10_RETURN_TYPE_SNORM; + case SVGA3D_R8_SINT: return VGPU10_RETURN_TYPE_SINT; + case SVGA3D_R8G8_B8G8_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_G8R8_G8B8_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC1_UNORM_SRGB: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC2_UNORM_SRGB: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC3_UNORM_SRGB: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC4_SNORM: return VGPU10_RETURN_TYPE_SNORM; + case SVGA3D_BC5_SNORM: return VGPU10_RETURN_TYPE_SNORM; + case SVGA3D_R10G10B10_XR_BIAS_A2_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_B8G8R8A8_UNORM_SRGB: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_B8G8R8X8_UNORM_SRGB: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R32G32B32A32_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_R16G16B16A16_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_R16G16B16A16_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R32G32_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_R10G10B10A2_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R8G8B8A8_SNORM: return VGPU10_RETURN_TYPE_SNORM; + case SVGA3D_R16G16_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_R16G16_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R16G16_SNORM: return VGPU10_RETURN_TYPE_SNORM; + case SVGA3D_R32_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_R8G8_SNORM: return VGPU10_RETURN_TYPE_SNORM; + case SVGA3D_R16_FLOAT: return VGPU10_RETURN_TYPE_FLOAT; + case SVGA3D_D16_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_A8_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC1_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC2_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC3_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_B5G6R5_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_B5G5R5A1_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_B8G8R8A8_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_B8G8R8X8_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC4_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC5_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_B4G4R4A4_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC7_UNORM: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_BC7_UNORM_SRGB: return VGPU10_RETURN_TYPE_UNORM; + case SVGA3D_R9G9B9E5_SHAREDEXP: return VGPU10_RETURN_TYPE_FLOAT; + default: + break; + } + return VGPU10_RETURN_TYPE_UNORM; +} + + +SVGA3dDXSignatureRegisterComponentType DXShaderComponentTypeFromFormat(SVGA3dSurfaceFormat format) +{ + /** @todo This is auto-generated from format names and needs a review. */ + switch (format) + { + case SVGA3D_R32G32B32A32_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R32G32B32A32_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_R32G32B32_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R32G32B32_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R32G32B32_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_R16G16B16A16_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R16G16B16A16_SNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16G16B16A16_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_R32G32_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R32G32_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_D32_FLOAT_S8X24_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R32_FLOAT_X8X24: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_X32_G8X24_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R10G10B10A2_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R11G11B10_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R8G8B8A8_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R8G8B8A8_UNORM_SRGB: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R8G8B8A8_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R8G8B8A8_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_R16G16_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R16G16_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_D32_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R32_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R32_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_D24_UNORM_S8_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R24_UNORM_X8: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_X24_G8_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R8G8_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R8G8_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R8G8_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_R16_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R16_SNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_R8_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R8_UINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32; + case SVGA3D_R8_SNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R8_SINT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32; + case SVGA3D_R8G8_B8G8_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_G8R8_G8B8_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC1_UNORM_SRGB: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC2_UNORM_SRGB: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC3_UNORM_SRGB: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC4_SNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC5_SNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R10G10B10_XR_BIAS_A2_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_B8G8R8A8_UNORM_SRGB: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_B8G8R8X8_UNORM_SRGB: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R32G32B32A32_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16G16B16A16_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16G16B16A16_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R32G32_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R10G10B10A2_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R8G8B8A8_SNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16G16_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16G16_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16G16_SNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R32_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R8G8_SNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R16_FLOAT: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_D16_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_A8_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC1_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC2_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC3_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_B5G6R5_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_B5G5R5A1_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_B8G8R8A8_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_B8G8R8X8_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC4_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC5_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_B4G4R4A4_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC7_UNORM: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_BC7_UNORM_SRGB: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + case SVGA3D_R9G9B9E5_SHAREDEXP: return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; + default: + break; + } + return SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32; +} + + +int DXShaderUpdateResources(DXShaderInfo const *pInfo, VGPU10_RESOURCE_DIMENSION *paResourceDimension, + VGPU10_RESOURCE_RETURN_TYPE *paResourceReturnType, uint32_t cResources) +{ + for (uint32_t i = 0; i < pInfo->cDclResource; ++i) + { + VGPU10_RESOURCE_DIMENSION const resourceDimension = i < cResources ? paResourceDimension[i] : VGPU10_RESOURCE_DIMENSION_TEXTURE2D; + AssertContinue(resourceDimension <= VGPU10_RESOURCE_DIMENSION_TEXTURECUBEARRAY); + + VGPU10_RESOURCE_RETURN_TYPE const resourceReturnType = i < cResources ? paResourceReturnType[i] : VGPU10_RETURN_TYPE_FLOAT; + AssertContinue(resourceReturnType <= VGPU10_RETURN_TYPE_MIXED); + + uint32_t const offToken = pInfo->aOffDclResource[i]; + AssertContinue(offToken < pInfo->cbBytecode); + if (offToken == 0) /* nothing at this index */ + continue; + + uint32_t *paToken = (uint32_t *)((uintptr_t)pInfo->pvBytecode + offToken); + + VGPU10OpcodeToken0 *pOpcode = (VGPU10OpcodeToken0 *)&paToken[0]; + if (resourceDimension != VGPU10_RESOURCE_DIMENSION_UNKNOWN) + pOpcode->resourceDimension = resourceDimension; + // paToken[1] unmodified + // paToken[2] unmodified + VGPU10ResourceReturnTypeToken *pReturnTypeToken = (VGPU10ResourceReturnTypeToken *)&paToken[3]; + if ((uint8_t)resourceReturnType != 0) + { + pReturnTypeToken->component0 = (uint8_t)resourceReturnType; + pReturnTypeToken->component1 = (uint8_t)resourceReturnType; + pReturnTypeToken->component2 = (uint8_t)resourceReturnType; + pReturnTypeToken->component3 = (uint8_t)resourceReturnType; + } + } + + return VINF_SUCCESS; +} + +#ifdef DXBC_STANDALONE_TEST +static int dxbcCreateFromBytecode(void const *pvShaderCode, uint32_t cbShaderCode, void **ppvDXBC, uint32_t *pcbDXBC) +{ + /* Parse the shader bytecode and create DXBC container with resource, signature and shader bytecode blobs. */ + DXShaderInfo info; + RT_ZERO(info); + int rc = DXShaderParse(pvShaderCode, cbShaderCode, &info); + if (RT_SUCCESS(rc)) + rc = DXShaderCreateDXBC(&info, ppvDXBC, pcbDXBC); + return rc; +} + +static int parseShaderVM(void const *pvShaderCode, uint32_t cbShaderCode) +{ + void *pv = NULL; + uint32_t cb = 0; + int rc = dxbcCreateFromBytecode(pvShaderCode, cbShaderCode, &pv, &cb); + if (RT_SUCCESS(rc)) + { + /* Hexdump DXBC */ + printf("{\n"); + uint8_t *pu8 = (uint8_t *)pv; + for (uint32_t i = 0; i < cb; ++i) + { + if ((i % 16) == 0) + { + if (i > 0) + printf(",\n"); + + printf(" 0x%02x", pu8[i]); + } + else + { + printf(", 0x%02x", pu8[i]); + } + } + printf("\n"); + printf("};\n"); + + RTMemFree(pv); + } + + return rc; +} + +static DXBCBlobHeader *dxbcFindBlob(DXBCHeader *pDXBCHeader, uint32_t u32BlobType) +{ + uint8_t const *pu8DXBCBegin = (uint8_t *)pDXBCHeader; + for (uint32_t i = 0; i < pDXBCHeader->cBlob; ++i) + { + DXBCBlobHeader *pCurrentBlob = (DXBCBlobHeader *)&pu8DXBCBegin[pDXBCHeader->aBlobOffset[i]]; + if (pCurrentBlob->u32BlobType == u32BlobType) + return pCurrentBlob; + } + return NULL; +} + +static int dxbcExtractShaderCode(DXBCHeader *pDXBCHeader, void **ppvCode, uint32_t *pcbCode) +{ + DXBCBlobHeader *pBlob = dxbcFindBlob(pDXBCHeader, DXBC_BLOB_TYPE_SHDR); + AssertReturn(pBlob, VERR_NOT_IMPLEMENTED); + + DXBCBlobSHDR *pSHDR = (DXBCBlobSHDR *)&pBlob[1]; + *pcbCode = pSHDR->cToken * 4; + *ppvCode = RTMemAlloc(*pcbCode); + AssertReturn(*ppvCode, VERR_NO_MEMORY); + + memcpy(*ppvCode, pSHDR, *pcbCode); + return VINF_SUCCESS; +} + +static int parseShaderDXBC(void const *pvDXBC) +{ + DXBCHeader *pDXBCHeader = (DXBCHeader *)pvDXBC; + void *pvShaderCode = NULL; + uint32_t cbShaderCode = 0; + int rc = dxbcExtractShaderCode(pDXBCHeader, &pvShaderCode, &cbShaderCode); + if (RT_SUCCESS(rc)) + { + rc = parseShaderVM(pvShaderCode, cbShaderCode); + RTMemFree(pvShaderCode); + } + return rc; +} +#endif /* DXBC_STANDALONE_TEST */ diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-shader.h b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-shader.h new file mode 100644 index 00000000..5c307b31 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-shader.h @@ -0,0 +1,88 @@ +/* $Id: DevVGA-SVGA3d-dx-shader.h $ */ +/** @file + * DevVGA - VMWare SVGA device - VGPU10+ (DX) shader utilities. + */ + +/* + * Copyright (C) 2020-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_dx_shader_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_dx_shader_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifndef VMSVGA3D_DX +# error "This include file is for VMSVGA3D_DX." +#endif + +#include + +#include "vmsvga_headers_begin.h" +#pragma pack(1) /* VMSVGA structures are '__packed'. */ +#include +#include +#pragma pack() +#include "vmsvga_headers_end.h" + +/* SVGA3dDXSignatureRegisterComponentType (D3D10_SB_REGISTER_COMPONENT_TYPE) */ +#define SVGADX_SIGNATURE_REGISTER_COMPONENT_UINT32 1 +#define SVGADX_SIGNATURE_REGISTER_COMPONENT_SINT32 2 +#define SVGADX_SIGNATURE_REGISTER_COMPONENT_FLOAT32 3 + +typedef struct DXShaderAttributeSemantic +{ + const char *pcszSemanticName; + uint32_t SemanticIndex; +} DXShaderAttributeSemantic; + +typedef struct DXShaderInfo +{ + VGPU10_PROGRAM_TYPE enmProgramType; + bool fGuestSignatures : 1; + void *pvBytecode; + uint32_t cbBytecode; + uint32_t cInputSignature; + uint32_t cOutputSignature; + uint32_t cPatchConstantSignature; + uint32_t cDclResource; + SVGA3dDXSignatureEntry aInputSignature[32]; + SVGA3dDXSignatureEntry aOutputSignature[32]; + SVGA3dDXSignatureEntry aPatchConstantSignature[32]; + DXShaderAttributeSemantic aInputSemantic[32]; + DXShaderAttributeSemantic aOutputSemantic[32]; + DXShaderAttributeSemantic aPatchConstantSemantic[32]; + uint32_t aOffDclResource[SVGA3D_DX_MAX_SRVIEWS]; +} DXShaderInfo; + +int DXShaderParse(void const *pvCode, uint32_t cbCode, DXShaderInfo *pInfo); +void DXShaderGenerateSemantics(DXShaderInfo *pInfo); +void DXShaderSortSignatures(DXShaderInfo *pInfo); +void DXShaderFree(DXShaderInfo *pInfo); +int DXShaderUpdateResources(DXShaderInfo const *pInfo, VGPU10_RESOURCE_DIMENSION *paResourceDimension, + VGPU10_RESOURCE_RETURN_TYPE *paResourceReturnType, uint32_t cResources); +VGPU10_RESOURCE_RETURN_TYPE DXShaderResourceReturnTypeFromFormat(SVGA3dSurfaceFormat format); +SVGA3dDXSignatureRegisterComponentType DXShaderComponentTypeFromFormat(SVGA3dSurfaceFormat format); +int DXShaderCreateDXBC(DXShaderInfo const *pInfo, void **ppvDXBC, uint32_t *pcbDXBC); +char const *DXShaderGetOutputSemanticName(DXShaderInfo const *pInfo, uint32_t idxRegister, SVGA3dDXSignatureSemanticName *pSemanticName); + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_dx_shader_h */ diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx.cpp new file mode 100644 index 00000000..268c812d --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx.cpp @@ -0,0 +1,3256 @@ +/* $Id: DevVGA-SVGA3d-dx.cpp $ */ +/** @file + * DevSVGA3d - VMWare SVGA device, 3D parts - Common code for DX backend interface. + */ + +/* + * Copyright (C) 2020-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include +#include + +#include +#include + +#include /* required by DevVGA.h */ + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#include "DevVGA-SVGA3d-internal.h" +#include "DevVGA-SVGA-internal.h" + + +/* + * Helpers. + */ + +static int dxMobWrite(PVMSVGAR3STATE pSvgaR3State, SVGAMobId mobid, uint32_t off, void const *pvData, uint32_t cbData) +{ + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, mobid); + ASSERT_GUEST_RETURN(pMob, VERR_INVALID_STATE); + + return vmsvgaR3MobWrite(pSvgaR3State, pMob, off, pvData, cbData); +} + + +/* + * + * Command handlers. + * + */ + +int vmsvga3dDXUnbindContext(PVGASTATECC pThisCC, uint32_t cid, SVGADXContextMobFormat *pSvgaDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXBindContext, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, cid, &pDXContext); + AssertRCReturn(rc, rc); + + /* Copy the host structure back to the guest memory. */ + memcpy(pSvgaDXContext, &pDXContext->svgaDXContext, sizeof(*pSvgaDXContext)); + + return rc; +} + + +int vmsvga3dDXSwitchContext(PVGASTATECC pThisCC, uint32_t cid) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSwitchContext, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, cid, &pDXContext); + AssertRCReturn(rc, rc); + + /* Notify the host backend that context is about to be switched. */ + rc = pSvgaR3State->pFuncsDX->pfnDXSwitchContext(pThisCC, pDXContext); + if (rc == VINF_NOT_IMPLEMENTED || RT_FAILURE(rc)) + return rc; + + /** @todo Keep track of changes in the pipeline and apply only modified state. */ + /* It is not necessary to restore SVGADXContextMobFormat::shaderState::shaderResources + * because they are applied by the backend before each Draw call. + */ + #define DX_STATE_VS 0x00000001 + #define DX_STATE_PS 0x00000002 + #define DX_STATE_SAMPLERS 0x00000004 + #define DX_STATE_INPUTLAYOUT 0x00000008 + #define DX_STATE_TOPOLOGY 0x00000010 + #define DX_STATE_BLENDSTATE 0x00000080 + #define DX_STATE_DEPTHSTENCILSTATE 0x00000100 + #define DX_STATE_SOTARGETS 0x00000200 + #define DX_STATE_VIEWPORTS 0x00000400 + #define DX_STATE_SCISSORRECTS 0x00000800 + #define DX_STATE_RASTERIZERSTATE 0x00001000 + #define DX_STATE_RENDERTARGETS 0x00002000 + #define DX_STATE_GS 0x00004000 + uint32_t u32TrackedState = 0 + | DX_STATE_VS + | DX_STATE_PS + | DX_STATE_SAMPLERS + | DX_STATE_INPUTLAYOUT + | DX_STATE_TOPOLOGY + | DX_STATE_BLENDSTATE + | DX_STATE_DEPTHSTENCILSTATE + | DX_STATE_SOTARGETS + | DX_STATE_VIEWPORTS + | DX_STATE_SCISSORRECTS + | DX_STATE_RASTERIZERSTATE + | DX_STATE_RENDERTARGETS + | DX_STATE_GS + ; + + LogFunc(("cid = %d, state = 0x%08X\n", cid, u32TrackedState)); + + if (u32TrackedState & DX_STATE_VS) + { + u32TrackedState &= ~DX_STATE_VS; + + SVGA3dShaderType const shaderType = SVGA3D_SHADERTYPE_VS; + + uint32_t const idxShaderState = shaderType - SVGA3D_SHADERTYPE_MIN; + SVGA3dShaderId shaderId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderId; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetShader(pThisCC, pDXContext, shaderId, shaderType); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_PS) + { + u32TrackedState &= ~DX_STATE_PS; + + SVGA3dShaderType const shaderType = SVGA3D_SHADERTYPE_PS; + + uint32_t const idxShaderState = shaderType - SVGA3D_SHADERTYPE_MIN; + SVGA3dShaderId shaderId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderId; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetShader(pThisCC, pDXContext, shaderId, shaderType); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_GS) + { + u32TrackedState &= ~DX_STATE_GS; + + SVGA3dShaderType const shaderType = SVGA3D_SHADERTYPE_GS; + + uint32_t const idxShaderState = shaderType - SVGA3D_SHADERTYPE_MIN; + SVGA3dShaderId shaderId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderId; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetShader(pThisCC, pDXContext, shaderId, shaderType); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_SAMPLERS) + { + u32TrackedState &= ~DX_STATE_SAMPLERS; + + for (int i = SVGA3D_SHADERTYPE_MIN; i < SVGA3D_SHADERTYPE_MAX; ++i) + { + SVGA3dShaderType const shaderType = (SVGA3dShaderType)i; + uint32_t const idxShaderState = shaderType - SVGA3D_SHADERTYPE_MIN; + + uint32_t startSampler = 0; + uint32_t cSamplerId = SVGA3D_DX_MAX_SAMPLERS; + SVGA3dSamplerId *paSamplerId = &pDXContext->svgaDXContext.shaderState[idxShaderState].samplers[0]; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetSamplers(pThisCC, pDXContext, startSampler, shaderType, cSamplerId, paSamplerId); + AssertRC(rc); + } + } + + + if (u32TrackedState & DX_STATE_INPUTLAYOUT) + { + u32TrackedState &= ~DX_STATE_INPUTLAYOUT; + + SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetInputLayout(pThisCC, pDXContext, elementLayoutId); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_TOPOLOGY) + { + u32TrackedState &= ~DX_STATE_TOPOLOGY; + + SVGA3dPrimitiveType const topology = (SVGA3dPrimitiveType)pDXContext->svgaDXContext.inputAssembly.topology; + + if (topology != SVGA3D_PRIMITIVE_INVALID) + rc = pSvgaR3State->pFuncsDX->pfnDXSetTopology(pThisCC, pDXContext, topology); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_BLENDSTATE) + { + u32TrackedState &= ~DX_STATE_BLENDSTATE; + + SVGA3dBlendStateId const blendId = pDXContext->svgaDXContext.renderState.blendStateId; + /* SVGADXContextMobFormat uses uint32_t array to store the blend factors, however they are in fact 32 bit floats. */ + float const *paBlendFactor = (float *)&pDXContext->svgaDXContext.renderState.blendFactor[0]; + uint32_t const sampleMask = pDXContext->svgaDXContext.renderState.sampleMask; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetBlendState(pThisCC, pDXContext, blendId, paBlendFactor, sampleMask); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_DEPTHSTENCILSTATE) + { + u32TrackedState &= ~DX_STATE_DEPTHSTENCILSTATE; + + SVGA3dDepthStencilStateId const depthStencilId = pDXContext->svgaDXContext.renderState.depthStencilStateId; + uint32_t const stencilRef = pDXContext->svgaDXContext.renderState.stencilRef; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetDepthStencilState(pThisCC, pDXContext, depthStencilId, stencilRef); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_SOTARGETS) + { + u32TrackedState &= ~DX_STATE_SOTARGETS; + + uint32_t cSoTarget = SVGA3D_DX_MAX_SOTARGETS; + SVGA3dSoTarget aSoTarget[SVGA3D_DX_MAX_SOTARGETS]; + for (uint32_t i = 0; i < SVGA3D_DX_MAX_SOTARGETS; ++i) + { + aSoTarget[i].sid = pDXContext->svgaDXContext.streamOut.targets[i]; + /** @todo Offset is not stored in svgaDXContext. Should it be stored elsewhere by the host? */ + aSoTarget[i].offset = 0; + aSoTarget[i].sizeInBytes = 0; + } + + rc = pSvgaR3State->pFuncsDX->pfnDXSetSOTargets(pThisCC, pDXContext, cSoTarget, aSoTarget); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_VIEWPORTS) + { + u32TrackedState &= ~DX_STATE_VIEWPORTS; + + uint32_t const cViewport = pDXContext->svgaDXContext.numViewports; + SVGA3dViewport const *paViewport = &pDXContext->svgaDXContext.viewports[0]; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetViewports(pThisCC, pDXContext, cViewport, paViewport); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_SCISSORRECTS) + { + u32TrackedState &= ~DX_STATE_SCISSORRECTS; + + uint32_t const cRect = pDXContext->svgaDXContext.numScissorRects; + SVGASignedRect const *paRect = &pDXContext->svgaDXContext.scissorRects[0]; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetScissorRects(pThisCC, pDXContext, cRect, paRect); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_RASTERIZERSTATE) + { + u32TrackedState &= ~DX_STATE_RASTERIZERSTATE; + + SVGA3dRasterizerStateId const rasterizerId = pDXContext->svgaDXContext.renderState.rasterizerStateId; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetRasterizerState(pThisCC, pDXContext, rasterizerId); + AssertRC(rc); + } + + + if (u32TrackedState & DX_STATE_RENDERTARGETS) + { + u32TrackedState &= ~DX_STATE_RENDERTARGETS; + + SVGA3dDepthStencilViewId const depthStencilViewId = (SVGA3dDepthStencilViewId)pDXContext->svgaDXContext.renderState.depthStencilViewId; + uint32_t const cRenderTargetViewId = SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS; + SVGA3dRenderTargetViewId const *paRenderTargetViewId = (SVGA3dRenderTargetViewId *)&pDXContext->svgaDXContext.renderState.renderTargetViewIds[0]; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetRenderTargets(pThisCC, pDXContext, depthStencilViewId, cRenderTargetViewId, paRenderTargetViewId); + AssertRC(rc); + } + + Assert(u32TrackedState == 0); + + return rc; +} + + +/** + * Create a new 3D DX context. + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param cid Context id to be created. + */ +int vmsvga3dDXDefineContext(PVGASTATECC pThisCC, uint32_t cid) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineContext, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + + LogFunc(("cid %d\n", cid)); + + AssertReturn(cid < SVGA3D_MAX_CONTEXT_IDS, VERR_INVALID_PARAMETER); + + if (cid >= p3dState->cDXContexts) + { + /* Grow the array. */ + uint32_t cNew = RT_ALIGN(cid + 15, 16); + void *pvNew = RTMemRealloc(p3dState->papDXContexts, sizeof(p3dState->papDXContexts[0]) * cNew); + AssertReturn(pvNew, VERR_NO_MEMORY); + p3dState->papDXContexts = (PVMSVGA3DDXCONTEXT *)pvNew; + while (p3dState->cDXContexts < cNew) + { + pDXContext = (PVMSVGA3DDXCONTEXT)RTMemAllocZ(sizeof(*pDXContext)); + AssertReturn(pDXContext, VERR_NO_MEMORY); + pDXContext->cid = SVGA3D_INVALID_ID; + p3dState->papDXContexts[p3dState->cDXContexts++] = pDXContext; + } + } + /* If one already exists with this id, then destroy it now. */ + if (p3dState->papDXContexts[cid]->cid != SVGA3D_INVALID_ID) + vmsvga3dDXDestroyContext(pThisCC, cid); + + pDXContext = p3dState->papDXContexts[cid]; + memset(pDXContext, 0, sizeof(*pDXContext)); + + /* 0xFFFFFFFF (SVGA_ID_INVALID) is a better initial value than 0 for most of svgaDXContext fields. */ + memset(&pDXContext->svgaDXContext, 0xFF, sizeof(pDXContext->svgaDXContext)); + pDXContext->svgaDXContext.inputAssembly.topology = SVGA3D_PRIMITIVE_INVALID; + pDXContext->svgaDXContext.numViewports = 0; + pDXContext->svgaDXContext.numScissorRects = 0; + pDXContext->cid = cid; + + /* Init the backend specific data. */ + rc = pSvgaR3State->pFuncsDX->pfnDXDefineContext(pThisCC, pDXContext); + + /* Cleanup on failure. */ + if (RT_FAILURE(rc)) + vmsvga3dDXDestroyContext(pThisCC, cid); + + return rc; +} + + +int vmsvga3dDXDestroyContext(PVGASTATECC pThisCC, uint32_t cid) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyContext, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, cid, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDestroyContext(pThisCC, pDXContext); + + RT_ZERO(*pDXContext); + pDXContext->cid = SVGA3D_INVALID_ID; + + return rc; +} + + +int vmsvga3dDXBindContext(PVGASTATECC pThisCC, uint32_t cid, SVGADXContextMobFormat *pSvgaDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXBindContext, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, cid, &pDXContext); + AssertRCReturn(rc, rc); + + if (pSvgaDXContext) + memcpy(&pDXContext->svgaDXContext, pSvgaDXContext, sizeof(*pSvgaDXContext)); + + rc = pSvgaR3State->pFuncsDX->pfnDXBindContext(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXReadbackContext(PVGASTATECC pThisCC, uint32_t idDXContext, SVGADXContextMobFormat *pSvgaDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXReadbackContext, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXReadbackContext(pThisCC, pDXContext); + if (RT_SUCCESS(rc)) + memcpy(pSvgaDXContext, &pDXContext->svgaDXContext, sizeof(*pSvgaDXContext)); + return rc; +} + + +int vmsvga3dDXInvalidateContext(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXInvalidateContext, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXInvalidateContext(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXSetSingleConstantBuffer(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetSingleConstantBuffer const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetSingleConstantBuffer, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(pCmd->slot < SVGA3D_DX_MAX_CONSTBUFFERS, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->type >= SVGA3D_SHADERTYPE_MIN && pCmd->type < SVGA3D_SHADERTYPE_MAX, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const idxShaderState = pCmd->type - SVGA3D_SHADERTYPE_MIN; + SVGA3dConstantBufferBinding *pCBB = &pDXContext->svgaDXContext.shaderState[idxShaderState].constantBuffers[pCmd->slot]; + pCBB->sid = pCmd->sid; + pCBB->offsetInBytes = pCmd->offsetInBytes; + pCBB->sizeInBytes = pCmd->sizeInBytes; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetSingleConstantBuffer(pThisCC, pDXContext, pCmd->slot, pCmd->type, pCmd->sid, pCmd->offsetInBytes, pCmd->sizeInBytes); + return rc; +} + + +int vmsvga3dDXSetShaderResources(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetShaderResources const *pCmd, uint32_t cShaderResourceViewId, SVGA3dShaderResourceViewId const *paShaderResourceViewId) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetShaderResources, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(pCmd->startView < SVGA3D_DX_MAX_SRVIEWS, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(cShaderResourceViewId <= SVGA3D_DX_MAX_SRVIEWS - pCmd->startView, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->type >= SVGA3D_SHADERTYPE_MIN && pCmd->type < SVGA3D_SHADERTYPE_MAX, VERR_INVALID_PARAMETER); + for (uint32_t i = 0; i < cShaderResourceViewId; ++i) + ASSERT_GUEST_RETURN( paShaderResourceViewId[i] < pDXContext->cot.cSRView + || paShaderResourceViewId[i] == SVGA3D_INVALID_ID, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const idxShaderState = pCmd->type - SVGA3D_SHADERTYPE_MIN; + for (uint32_t i = 0; i < cShaderResourceViewId; ++i) + { + SVGA3dShaderResourceViewId const shaderResourceViewId = paShaderResourceViewId[i]; + pDXContext->svgaDXContext.shaderState[idxShaderState].shaderResources[pCmd->startView + i] = shaderResourceViewId; + } + + rc = pSvgaR3State->pFuncsDX->pfnDXSetShaderResources(pThisCC, pDXContext, pCmd->startView, pCmd->type, cShaderResourceViewId, paShaderResourceViewId); + return rc; +} + + +int vmsvga3dDXSetShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetShader const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetShader, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN( pCmd->shaderId < pDXContext->cot.cShader + || pCmd->shaderId == SVGA_ID_INVALID, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->type >= SVGA3D_SHADERTYPE_MIN && pCmd->type < SVGA3D_SHADERTYPE_MAX, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const idxShaderState = pCmd->type - SVGA3D_SHADERTYPE_MIN; + pDXContext->svgaDXContext.shaderState[idxShaderState].shaderId = pCmd->shaderId; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetShader(pThisCC, pDXContext, pCmd->shaderId, pCmd->type); + return rc; +} + + +int vmsvga3dDXSetSamplers(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetSamplers const *pCmd, uint32_t cSamplerId, SVGA3dSamplerId const *paSamplerId) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetSamplers, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(pCmd->startSampler < SVGA3D_DX_MAX_SAMPLERS, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(cSamplerId <= SVGA3D_DX_MAX_SAMPLERS - pCmd->startSampler, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->type >= SVGA3D_SHADERTYPE_MIN && pCmd->type < SVGA3D_SHADERTYPE_MAX, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const idxShaderState = pCmd->type - SVGA3D_SHADERTYPE_MIN; + for (uint32_t i = 0; i < cSamplerId; ++i) + { + SVGA3dSamplerId const samplerId = paSamplerId[i]; + ASSERT_GUEST_RETURN( samplerId < pDXContext->cot.cSampler + || samplerId == SVGA_ID_INVALID, VERR_INVALID_PARAMETER); + pDXContext->svgaDXContext.shaderState[idxShaderState].samplers[pCmd->startSampler + i] = samplerId; + } + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXSetSamplers(pThisCC, pDXContext, pCmd->startSampler, pCmd->type, cSamplerId, paSamplerId); + return rc; +} + + +#ifdef DUMP_BITMAPS +static void vmsvga3dDXDrawDumpRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, const char *pszPrefix = NULL) +{ + for (uint32_t i = 0; i < SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS; ++i) + { + if (pDXContext->svgaDXContext.renderState.renderTargetViewIds[i] != SVGA3D_INVALID_ID) + { + SVGACOTableDXRTViewEntry *pRTViewEntry = &pDXContext->cot.paRTView[pDXContext->svgaDXContext.renderState.renderTargetViewIds[i]]; + Log(("Dump RT[%u] sid = %u rtvid = %u\n", i, pRTViewEntry->sid, pDXContext->svgaDXContext.renderState.renderTargetViewIds[i])); + + SVGA3dSurfaceImageId image; + image.sid = pRTViewEntry->sid; + image.face = 0; + image.mipmap = 0; + VMSVGA3D_MAPPED_SURFACE map; + int rc = vmsvga3dSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map); + if (RT_SUCCESS(rc)) + { + vmsvga3dMapWriteBmpFile(&map, pszPrefix ? pszPrefix : "rt-"); + vmsvga3dSurfaceUnmap(pThisCC, &image, &map, /* fWritten = */ false); + } + else + Log(("Map failed %Rrc\n", rc)); + } + } +} +#endif + +int vmsvga3dDXDraw(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDraw const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDraw, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDraw(pThisCC, pDXContext, pCmd->vertexCount, pCmd->startVertexLocation); +#ifdef DUMP_BITMAPS + vmsvga3dDXDrawDumpRenderTargets(pThisCC, pDXContext); +#endif + return rc; +} + + +int vmsvga3dDXDrawIndexed(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexed const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDrawIndexed, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDrawIndexed(pThisCC, pDXContext, pCmd->indexCount, pCmd->startIndexLocation, pCmd->baseVertexLocation); +#ifdef DUMP_BITMAPS + vmsvga3dDXDrawDumpRenderTargets(pThisCC, pDXContext); +#endif + return rc; +} + + +int vmsvga3dDXDrawInstanced(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawInstanced const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDrawInstanced, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDrawInstanced(pThisCC, pDXContext, + pCmd->vertexCountPerInstance, pCmd->instanceCount, pCmd->startVertexLocation, pCmd->startInstanceLocation); +#ifdef DUMP_BITMAPS + vmsvga3dDXDrawDumpRenderTargets(pThisCC, pDXContext); +#endif + return rc; +} + + +int vmsvga3dDXDrawIndexedInstanced(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexedInstanced const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDrawIndexedInstanced, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDrawIndexedInstanced(pThisCC, pDXContext, + pCmd->indexCountPerInstance, pCmd->instanceCount, pCmd->startIndexLocation, pCmd->baseVertexLocation, pCmd->startInstanceLocation); +#ifdef DUMP_BITMAPS + vmsvga3dDXDrawDumpRenderTargets(pThisCC, pDXContext); +#endif + return rc; +} + + +int vmsvga3dDXDrawAuto(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDrawAuto, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDrawAuto(pThisCC, pDXContext); +#ifdef DUMP_BITMAPS + vmsvga3dDXDrawDumpRenderTargets(pThisCC, pDXContext); +#endif + return rc; +} + + +int vmsvga3dDXSetInputLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dElementLayoutId elementLayoutId) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetInputLayout, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN( elementLayoutId == SVGA3D_INVALID_ID + || elementLayoutId < pDXContext->cot.cElementLayout, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pDXContext->svgaDXContext.inputAssembly.layoutId = elementLayoutId; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetInputLayout(pThisCC, pDXContext, elementLayoutId); + return rc; +} + + +int vmsvga3dDXSetVertexBuffers(PVGASTATECC pThisCC, uint32_t idDXContext, uint32_t startBuffer, uint32_t cVertexBuffer, SVGA3dVertexBuffer const *paVertexBuffer) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetVertexBuffers, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(startBuffer < SVGA3D_DX_MAX_VERTEXBUFFERS, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(cVertexBuffer <= SVGA3D_DX_MAX_VERTEXBUFFERS - startBuffer, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + for (uint32_t i = 0; i < cVertexBuffer; ++i) + { + uint32_t const idxVertexBuffer = startBuffer + i; + + pDXContext->svgaDXContext.inputAssembly.vertexBuffers[idxVertexBuffer].bufferId = paVertexBuffer[i].sid; + pDXContext->svgaDXContext.inputAssembly.vertexBuffers[idxVertexBuffer].stride = paVertexBuffer[i].stride; + pDXContext->svgaDXContext.inputAssembly.vertexBuffers[idxVertexBuffer].offset = paVertexBuffer[i].offset; + } + + rc = pSvgaR3State->pFuncsDX->pfnDXSetVertexBuffers(pThisCC, pDXContext, startBuffer, cVertexBuffer, paVertexBuffer); + return rc; +} + + +int vmsvga3dDXSetIndexBuffer(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetIndexBuffer const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetIndexBuffer, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + pDXContext->svgaDXContext.inputAssembly.indexBufferSid = pCmd->sid; + pDXContext->svgaDXContext.inputAssembly.indexBufferOffset = pCmd->offset; + pDXContext->svgaDXContext.inputAssembly.indexBufferFormat = pCmd->format; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetIndexBuffer(pThisCC, pDXContext, pCmd->sid, pCmd->format, pCmd->offset); + return rc; +} + + +int vmsvga3dDXSetTopology(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dPrimitiveType topology) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetTopology, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(topology >= SVGA3D_PRIMITIVE_MIN && topology < SVGA3D_PRIMITIVE_MAX, VERR_INVALID_PARAMETER); + + pDXContext->svgaDXContext.inputAssembly.topology = topology; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetTopology(pThisCC, pDXContext, topology); + return rc; +} + + +int vmsvga3dDXSetRenderTargets(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dDepthStencilViewId depthStencilViewId, uint32_t cRenderTargetViewId, SVGA3dRenderTargetViewId const *paRenderTargetViewId) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetRenderTargets, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN( depthStencilViewId < pDXContext->cot.cDSView + || depthStencilViewId == SVGA_ID_INVALID, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(cRenderTargetViewId <= SVGA3D_MAX_RENDER_TARGETS, VERR_INVALID_PARAMETER); + for (uint32_t i = 0; i < cRenderTargetViewId; ++i) + ASSERT_GUEST_RETURN( paRenderTargetViewId[i] < pDXContext->cot.cRTView + || paRenderTargetViewId[i] == SVGA_ID_INVALID, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pDXContext->svgaDXContext.renderState.depthStencilViewId = depthStencilViewId; + for (uint32_t i = 0; i < cRenderTargetViewId; ++i) + pDXContext->svgaDXContext.renderState.renderTargetViewIds[i] = paRenderTargetViewId[i]; + + /* Remember how many render target slots must be set. */ + pDXContext->cRenderTargets = RT_MAX(pDXContext->cRenderTargets, cRenderTargetViewId); + + rc = pSvgaR3State->pFuncsDX->pfnDXSetRenderTargets(pThisCC, pDXContext, depthStencilViewId, cRenderTargetViewId, paRenderTargetViewId); + return rc; +} + + +int vmsvga3dDXSetBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetBlendState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetBlendState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dBlendStateId const blendId = pCmd->blendId; + + ASSERT_GUEST_RETURN( blendId == SVGA3D_INVALID_ID + || blendId < pDXContext->cot.cBlendState, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pDXContext->svgaDXContext.renderState.blendStateId = blendId; + /* SVGADXContextMobFormat uses uint32_t array to store the blend factors, however they are in fact 32 bit floats. */ + memcpy(pDXContext->svgaDXContext.renderState.blendFactor, pCmd->blendFactor, sizeof(pDXContext->svgaDXContext.renderState.blendFactor)); + pDXContext->svgaDXContext.renderState.sampleMask = pCmd->sampleMask; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetBlendState(pThisCC, pDXContext, blendId, pCmd->blendFactor, pCmd->sampleMask); + return rc; +} + + +int vmsvga3dDXSetDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetDepthStencilState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetDepthStencilState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dDepthStencilStateId const depthStencilId = pCmd->depthStencilId; + + ASSERT_GUEST_RETURN( depthStencilId == SVGA3D_INVALID_ID + || depthStencilId < pDXContext->cot.cDepthStencil, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pDXContext->svgaDXContext.renderState.depthStencilStateId = depthStencilId; + pDXContext->svgaDXContext.renderState.stencilRef = pCmd->stencilRef; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetDepthStencilState(pThisCC, pDXContext, depthStencilId, pCmd->stencilRef); + return rc; +} + + +int vmsvga3dDXSetRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dRasterizerStateId rasterizerId) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetRasterizerState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN( rasterizerId == SVGA3D_INVALID_ID + || rasterizerId < pDXContext->cot.cRasterizerState, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pDXContext->svgaDXContext.renderState.rasterizerStateId = rasterizerId; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetRasterizerState(pThisCC, pDXContext, rasterizerId); + return rc; +} + + +int vmsvga3dDXDefineQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineQuery const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineQuery, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dQueryId const queryId = pCmd->queryId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paQuery, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(queryId < pDXContext->cot.cQuery, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->type >= SVGA3D_QUERYTYPE_MIN && pCmd->type < SVGA3D_QUERYTYPE_MAX, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Cleanup the current query. */ + pSvgaR3State->pFuncsDX->pfnDXDestroyQuery(pThisCC, pDXContext, queryId); + + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + pEntry->type = pCmd->type; + pEntry->state = SVGADX_QDSTATE_IDLE; + pEntry->flags = pCmd->flags; + pEntry->mobid = SVGA_ID_INVALID; + pEntry->offset = 0; + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineQuery(pThisCC, pDXContext, queryId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyQuery const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyQuery, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dQueryId const queryId = pCmd->queryId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paQuery, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(queryId < pDXContext->cot.cQuery, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pSvgaR3State->pFuncsDX->pfnDXDestroyQuery(pThisCC, pDXContext, queryId); + + /* Cleanup COTable entry.*/ + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + pEntry->type = SVGA3D_QUERYTYPE_INVALID; + pEntry->state = SVGADX_QDSTATE_INVALID; + pEntry->flags = 0; + pEntry->mobid = SVGA_ID_INVALID; + pEntry->offset = 0; + + return rc; +} + + +int vmsvga3dDXBindQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindQuery const *pCmd, PVMSVGAMOB pMob) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dQueryId const queryId = pCmd->queryId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paQuery, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(queryId < pDXContext->cot.cQuery, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + pEntry->mobid = vmsvgaR3MobId(pMob); + + return rc; +} + + +int vmsvga3dDXSetQueryOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetQueryOffset const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dQueryId const queryId = pCmd->queryId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paQuery, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(queryId < pDXContext->cot.cQuery, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + pEntry->offset = pCmd->mobOffset; + + return rc; +} + + +int vmsvga3dDXBeginQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBeginQuery const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXBeginQuery, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dQueryId const queryId = pCmd->queryId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paQuery, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(queryId < pDXContext->cot.cQuery, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + Assert(pEntry->state == SVGADX_QDSTATE_IDLE || pEntry->state == SVGADX_QDSTATE_PENDING || pEntry->state == SVGADX_QDSTATE_FINISHED); + if (pEntry->state != SVGADX_QDSTATE_ACTIVE) + { + rc = pSvgaR3State->pFuncsDX->pfnDXBeginQuery(pThisCC, pDXContext, queryId); + if (RT_SUCCESS(rc)) + { + pEntry->state = SVGADX_QDSTATE_ACTIVE; + + /* Update the guest status of the query. */ + uint32_t const u32 = SVGA3D_QUERYSTATE_PENDING; + dxMobWrite(pSvgaR3State, pEntry->mobid, pEntry->offset, &u32, sizeof(u32)); + } + else + { + uint32_t const u32 = SVGA3D_QUERYSTATE_FAILED; + dxMobWrite(pSvgaR3State, pEntry->mobid, pEntry->offset, &u32, sizeof(u32)); + } + } + return rc; +} + + +static int dxEndQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGACOTableDXQueryEntry *pEntry) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + + int rc = VINF_SUCCESS; + if (pEntry->state == SVGADX_QDSTATE_ACTIVE || pEntry->state == SVGADX_QDSTATE_IDLE) + { + pEntry->state = SVGADX_QDSTATE_PENDING; + + uint32_t u32QueryState; + SVGADXQueryResultUnion queryResult; + uint32_t cbQuery = 0; /* Actual size of query data returned by backend. */ + rc = pSvgaR3State->pFuncsDX->pfnDXEndQuery(pThisCC, pDXContext, queryId, &queryResult, &cbQuery); + if (RT_SUCCESS(rc)) + { + /* Write the result after SVGA3dQueryState. */ + dxMobWrite(pSvgaR3State, pEntry->mobid, pEntry->offset + sizeof(uint32_t), &queryResult, cbQuery); + + u32QueryState = SVGA3D_QUERYSTATE_SUCCEEDED; + } + else + u32QueryState = SVGA3D_QUERYSTATE_FAILED; + + dxMobWrite(pSvgaR3State, pEntry->mobid, pEntry->offset, &u32QueryState, sizeof(u32QueryState)); + + if (RT_SUCCESS(rc)) + pEntry->state = SVGADX_QDSTATE_FINISHED; + } + else + AssertStmt(pEntry->state == SVGADX_QDSTATE_FINISHED, rc = VERR_INVALID_STATE); + + return rc; +} + + +int vmsvga3dDXEndQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXEndQuery const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXEndQuery, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dQueryId const queryId = pCmd->queryId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paQuery, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(queryId < pDXContext->cot.cQuery, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; + rc = dxEndQuery(pThisCC, pDXContext, queryId, pEntry); + return rc; +} + + +int vmsvga3dDXReadbackQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXReadbackQuery const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dQueryId const queryId = pCmd->queryId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paQuery, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(queryId < pDXContext->cot.cQuery, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* The device does not cache queries. So this is a NOP. */ + + return rc; +} + + +int vmsvga3dDXSetPredication(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetPredication const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetPredication, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dQueryId const queryId = pCmd->queryId; + + ASSERT_GUEST_RETURN( queryId == SVGA3D_INVALID_ID + || queryId < pDXContext->cot.cQuery, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXSetPredication(pThisCC, pDXContext, queryId, pCmd->predicateValue); + return rc; +} + + +int vmsvga3dDXSetSOTargets(PVGASTATECC pThisCC, uint32_t idDXContext, uint32_t cSoTarget, SVGA3dSoTarget const *paSoTarget) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetSOTargets, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(cSoTarget <= SVGA3D_DX_MAX_SOTARGETS, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /** @todo Offset is not stored in svgaDXContext. Should it be stored elsewhere? */ + for (uint32_t i = 0; i < SVGA3D_DX_MAX_SOTARGETS; ++i) + pDXContext->svgaDXContext.streamOut.targets[i] = i < cSoTarget ? paSoTarget[i].sid : SVGA3D_INVALID_ID; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetSOTargets(pThisCC, pDXContext, cSoTarget, paSoTarget); + return rc; +} + + +int vmsvga3dDXSetViewports(PVGASTATECC pThisCC, uint32_t idDXContext, uint32_t cViewport, SVGA3dViewport const *paViewport) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetViewports, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(cViewport <= SVGA3D_DX_MAX_VIEWPORTS, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pDXContext->svgaDXContext.numViewports = (uint8_t)cViewport; + for (uint32_t i = 0; i < cViewport; ++i) + pDXContext->svgaDXContext.viewports[i] = paViewport[i]; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetViewports(pThisCC, pDXContext, cViewport, paViewport); + return rc; +} + + +int vmsvga3dDXSetScissorRects(PVGASTATECC pThisCC, uint32_t idDXContext, uint32_t cRect, SVGASignedRect const *paRect) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetScissorRects, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(cRect <= SVGA3D_DX_MAX_SCISSORRECTS, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pDXContext->svgaDXContext.numScissorRects = (uint8_t)cRect; + for (uint32_t i = 0; i < cRect; ++i) + pDXContext->svgaDXContext.scissorRects[i] = paRect[i]; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetScissorRects(pThisCC, pDXContext, cRect, paRect); + return rc; +} + + +int vmsvga3dDXClearRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearRenderTargetView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXClearRenderTargetView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dRenderTargetViewId const renderTargetViewId = pCmd->renderTargetViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paRTView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->cot.cRTView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXClearRenderTargetView(pThisCC, pDXContext, renderTargetViewId, &pCmd->rgba); + return rc; +} + + +int vmsvga3dDXClearDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearDepthStencilView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXClearDepthStencilView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dDepthStencilViewId const depthStencilViewId = pCmd->depthStencilViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paDSView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(depthStencilViewId < pDXContext->cot.cDSView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXClearDepthStencilView(pThisCC, pDXContext, pCmd->flags, depthStencilViewId, pCmd->depth, (uint8_t)pCmd->stencil); + return rc; +} + + +int vmsvga3dDXPredCopyRegion(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredCopyRegion const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXPredCopyRegion, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + /** @todo Memcpy if both resources do not have the hardware resource. */ + + rc = pSvgaR3State->pFuncsDX->pfnDXPredCopyRegion(pThisCC, pDXContext, pCmd->dstSid, pCmd->dstSubResource, pCmd->srcSid, pCmd->srcSubResource, &pCmd->box); + return rc; +} + + +int vmsvga3dDXPredCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredCopy const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXPredCopy, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXPredCopy(pThisCC, pDXContext, pCmd->dstSid, pCmd->srcSid); + return rc; +} + + +int vmsvga3dDXPresentBlt(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPresentBlt const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXPresentBlt, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXPresentBlt(pThisCC, pDXContext, + pCmd->dstSid, pCmd->destSubResource, &pCmd->boxDest, + pCmd->srcSid, pCmd->srcSubResource, &pCmd->boxSrc, pCmd->mode); + return rc; +} + + +int vmsvga3dDXGenMips(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXGenMips const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXGenMips, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dShaderResourceViewId const shaderResourceViewId = pCmd->shaderResourceViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paSRView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(shaderResourceViewId < pDXContext->cot.cSRView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXGenMips(pThisCC, pDXContext, shaderResourceViewId); + return rc; +} + + +int vmsvga3dDXDefineShaderResourceView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineShaderResourceView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineShaderResourceView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dShaderResourceViewId const shaderResourceViewId = pCmd->shaderResourceViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paSRView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(shaderResourceViewId < pDXContext->cot.cSRView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXSRViewEntry *pEntry = &pDXContext->cot.paSRView[shaderResourceViewId]; + pEntry->sid = pCmd->sid; + pEntry->format = pCmd->format; + pEntry->resourceDimension = pCmd->resourceDimension; + pEntry->desc = pCmd->desc; + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineShaderResourceView(pThisCC, pDXContext, shaderResourceViewId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyShaderResourceView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyShaderResourceView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyShaderResourceView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dShaderResourceViewId const shaderResourceViewId = pCmd->shaderResourceViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paSRView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(shaderResourceViewId < pDXContext->cot.cSRView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXSRViewEntry *pEntry = &pDXContext->cot.paSRView[shaderResourceViewId]; + RT_ZERO(*pEntry); + + rc = pSvgaR3State->pFuncsDX->pfnDXDestroyShaderResourceView(pThisCC, pDXContext, shaderResourceViewId); + return rc; +} + + +int vmsvga3dDXDefineRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineRenderTargetView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineRenderTargetView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dRenderTargetViewId const renderTargetViewId = pCmd->renderTargetViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paRTView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->cot.cRTView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXRTViewEntry *pEntry = &pDXContext->cot.paRTView[renderTargetViewId]; + pEntry->sid = pCmd->sid; + pEntry->format = pCmd->format; + pEntry->resourceDimension = pCmd->resourceDimension; + pEntry->desc = pCmd->desc; + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineRenderTargetView(pThisCC, pDXContext, renderTargetViewId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyRenderTargetView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyRenderTargetView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dRenderTargetViewId const renderTargetViewId = pCmd->renderTargetViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paRTView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->cot.cRTView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXRTViewEntry *pEntry = &pDXContext->cot.paRTView[renderTargetViewId]; + RT_ZERO(*pEntry); + + for (uint32_t i = 0; i < SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS; ++i) + { + if (pDXContext->svgaDXContext.renderState.renderTargetViewIds[i] == renderTargetViewId) + pDXContext->svgaDXContext.renderState.renderTargetViewIds[i] = SVGA_ID_INVALID; + } + + rc = pSvgaR3State->pFuncsDX->pfnDXDestroyRenderTargetView(pThisCC, pDXContext, renderTargetViewId); + return rc; +} + + +int vmsvga3dDXDefineDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineDepthStencilView_v2 const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineDepthStencilView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dDepthStencilViewId const depthStencilViewId = pCmd->depthStencilViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paDSView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(depthStencilViewId < pDXContext->cot.cDSView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXDSViewEntry *pEntry = &pDXContext->cot.paDSView[depthStencilViewId]; + pEntry->sid = pCmd->sid; + pEntry->format = pCmd->format; + pEntry->resourceDimension = pCmd->resourceDimension; + pEntry->mipSlice = pCmd->mipSlice; + pEntry->firstArraySlice = pCmd->firstArraySlice; + pEntry->arraySize = pCmd->arraySize; + pEntry->flags = pCmd->flags; + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineDepthStencilView(pThisCC, pDXContext, depthStencilViewId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyDepthStencilView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyDepthStencilView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dDepthStencilViewId const depthStencilViewId = pCmd->depthStencilViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paDSView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(depthStencilViewId < pDXContext->cot.cDSView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXDSViewEntry *pEntry = &pDXContext->cot.paDSView[depthStencilViewId]; + RT_ZERO(*pEntry); + + rc = pSvgaR3State->pFuncsDX->pfnDXDestroyDepthStencilView(pThisCC, pDXContext, depthStencilViewId); + return rc; +} + + +int vmsvga3dDXDefineElementLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dElementLayoutId elementLayoutId, uint32_t cDesc, SVGA3dInputElementDesc const *paDesc) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineElementLayout, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(pDXContext->cot.paElementLayout, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(elementLayoutId < pDXContext->cot.cElementLayout, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXElementLayoutEntry *pEntry = &pDXContext->cot.paElementLayout[elementLayoutId]; + pEntry->elid = elementLayoutId; + pEntry->numDescs = RT_MIN(cDesc, RT_ELEMENTS(pEntry->descs)); + memcpy(pEntry->descs, paDesc, pEntry->numDescs * sizeof(pEntry->descs[0])); + +#ifdef LOG_ENABLED + Log6(("Element layout %d: slot off fmt class step reg\n", pEntry->elid)); + for (uint32_t i = 0; i < pEntry->numDescs; ++i) + { + Log6((" [%u]: %u 0x%02X %d %u %u %u\n", + i, + pEntry->descs[i].inputSlot, + pEntry->descs[i].alignedByteOffset, + pEntry->descs[i].format, + pEntry->descs[i].inputSlotClass, + pEntry->descs[i].instanceDataStepRate, + pEntry->descs[i].inputRegister + )); + } +#endif + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineElementLayout(pThisCC, pDXContext, elementLayoutId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyElementLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyElementLayout const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyElementLayout, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dElementLayoutId const elementLayoutId = pCmd->elementLayoutId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paElementLayout, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(elementLayoutId < pDXContext->cot.cElementLayout, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pSvgaR3State->pFuncsDX->pfnDXDestroyElementLayout(pThisCC, pDXContext, elementLayoutId); + + SVGACOTableDXElementLayoutEntry *pEntry = &pDXContext->cot.paElementLayout[elementLayoutId]; + RT_ZERO(*pEntry); + pEntry->elid = SVGA3D_INVALID_ID; + + return rc; +} + + +int vmsvga3dDXDefineBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineBlendState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineBlendState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dBlendStateId const blendId = pCmd->blendId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paBlendState, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(blendId < pDXContext->cot.cBlendState, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXBlendStateEntry *pEntry = &pDXContext->cot.paBlendState[blendId]; + pEntry->alphaToCoverageEnable = pCmd->alphaToCoverageEnable; + pEntry->independentBlendEnable = pCmd->independentBlendEnable; + memcpy(pEntry->perRT, pCmd->perRT, sizeof(pEntry->perRT)); + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineBlendState(pThisCC, pDXContext, blendId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyBlendState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyBlendState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dBlendStateId const blendId = pCmd->blendId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paBlendState, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(blendId < pDXContext->cot.cBlendState, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pSvgaR3State->pFuncsDX->pfnDXDestroyBlendState(pThisCC, pDXContext, blendId); + + SVGACOTableDXBlendStateEntry *pEntry = &pDXContext->cot.paBlendState[blendId]; + RT_ZERO(*pEntry); + + return rc; +} + + +int vmsvga3dDXDefineDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineDepthStencilState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineDepthStencilState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dDepthStencilStateId const depthStencilId = pCmd->depthStencilId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paDepthStencil, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(depthStencilId < pDXContext->cot.cDepthStencil, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXDepthStencilEntry *pEntry = &pDXContext->cot.paDepthStencil[depthStencilId]; + pEntry->depthEnable = pCmd->depthEnable; + pEntry->depthWriteMask = pCmd->depthWriteMask; + pEntry->depthFunc = pCmd->depthFunc; + pEntry->stencilEnable = pCmd->stencilEnable; + pEntry->frontEnable = pCmd->frontEnable; + pEntry->backEnable = pCmd->backEnable; + pEntry->stencilReadMask = pCmd->stencilReadMask; + pEntry->stencilWriteMask = pCmd->stencilWriteMask; + + pEntry->frontStencilFailOp = pCmd->frontStencilFailOp; + pEntry->frontStencilDepthFailOp = pCmd->frontStencilDepthFailOp; + pEntry->frontStencilPassOp = pCmd->frontStencilPassOp; + pEntry->frontStencilFunc = pCmd->frontStencilFunc; + + pEntry->backStencilFailOp = pCmd->backStencilFailOp; + pEntry->backStencilDepthFailOp = pCmd->backStencilDepthFailOp; + pEntry->backStencilPassOp = pCmd->backStencilPassOp; + pEntry->backStencilFunc = pCmd->backStencilFunc; + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineDepthStencilState(pThisCC, pDXContext, depthStencilId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyDepthStencilState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyDepthStencilState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dDepthStencilStateId const depthStencilId = pCmd->depthStencilId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paDepthStencil, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(depthStencilId < pDXContext->cot.cDepthStencil, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pSvgaR3State->pFuncsDX->pfnDXDestroyDepthStencilState(pThisCC, pDXContext, depthStencilId); + + SVGACOTableDXDepthStencilEntry *pEntry = &pDXContext->cot.paDepthStencil[depthStencilId]; + RT_ZERO(*pEntry); + + return rc; +} + + +int vmsvga3dDXDefineRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineRasterizerState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineRasterizerState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dRasterizerStateId const rasterizerId = pCmd->rasterizerId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paRasterizerState, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(rasterizerId < pDXContext->cot.cRasterizerState, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXRasterizerStateEntry *pEntry = &pDXContext->cot.paRasterizerState[rasterizerId]; + pEntry->fillMode = pCmd->fillMode; + pEntry->cullMode = pCmd->cullMode; + pEntry->frontCounterClockwise = pCmd->frontCounterClockwise; + pEntry->provokingVertexLast = pCmd->provokingVertexLast; + pEntry->depthBias = pCmd->depthBias; + pEntry->depthBiasClamp = pCmd->depthBiasClamp; + pEntry->slopeScaledDepthBias = pCmd->slopeScaledDepthBias; + pEntry->depthClipEnable = pCmd->depthClipEnable; + pEntry->scissorEnable = pCmd->scissorEnable; + pEntry->multisampleEnable = pCmd->multisampleEnable; + pEntry->antialiasedLineEnable = pCmd->antialiasedLineEnable; + pEntry->lineWidth = pCmd->lineWidth; + pEntry->lineStippleEnable = pCmd->lineStippleEnable; + pEntry->lineStippleFactor = pCmd->lineStippleFactor; + pEntry->lineStipplePattern = pCmd->lineStipplePattern; + pEntry->forcedSampleCount = 0; /** @todo Not in pCmd. */ + RT_ZERO(pEntry->mustBeZero); + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineRasterizerState(pThisCC, pDXContext, rasterizerId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyRasterizerState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyRasterizerState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dRasterizerStateId const rasterizerId = pCmd->rasterizerId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paRasterizerState, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(rasterizerId < pDXContext->cot.cRasterizerState, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXDestroyRasterizerState(pThisCC, pDXContext, rasterizerId); + + SVGACOTableDXRasterizerStateEntry *pEntry = &pDXContext->cot.paRasterizerState[rasterizerId]; + RT_ZERO(*pEntry); + + return rc; +} + + +int vmsvga3dDXDefineSamplerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineSamplerState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineSamplerState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dSamplerId const samplerId = pCmd->samplerId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paSampler, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(samplerId < pDXContext->cot.cSampler, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXSamplerEntry *pEntry = &pDXContext->cot.paSampler[samplerId]; + pEntry->filter = pCmd->filter; + pEntry->addressU = pCmd->addressU; + pEntry->addressV = pCmd->addressV; + pEntry->addressW = pCmd->addressW; + pEntry->mipLODBias = pCmd->mipLODBias; + pEntry->maxAnisotropy = pCmd->maxAnisotropy; + pEntry->comparisonFunc = pCmd->comparisonFunc; + pEntry->borderColor = pCmd->borderColor; + pEntry->minLOD = pCmd->minLOD; + pEntry->maxLOD = pCmd->maxLOD; + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineSamplerState(pThisCC, pDXContext, samplerId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroySamplerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroySamplerState const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroySamplerState, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dSamplerId const samplerId = pCmd->samplerId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paSampler, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(samplerId < pDXContext->cot.cSampler, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pSvgaR3State->pFuncsDX->pfnDXDestroySamplerState(pThisCC, pDXContext, samplerId); + + SVGACOTableDXSamplerEntry *pEntry = &pDXContext->cot.paSampler[samplerId]; + RT_ZERO(*pEntry); + + return rc; +} + + +int vmsvga3dDXDefineShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineShader const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineShader, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dShaderId const shaderId = pCmd->shaderId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paShader, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(shaderId < pDXContext->cot.cShader, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->type >= SVGA3D_SHADERTYPE_MIN && pCmd->type < SVGA3D_SHADERTYPE_MAX, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->sizeInBytes >= 8, VERR_INVALID_PARAMETER); /* Version Token + Length Token. */ + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Cleanup the current shader. */ + pSvgaR3State->pFuncsDX->pfnDXDestroyShader(pThisCC, pDXContext, shaderId); + + SVGACOTableDXShaderEntry *pEntry = &pDXContext->cot.paShader[shaderId]; + pEntry->type = pCmd->type; + pEntry->sizeInBytes = pCmd->sizeInBytes; + pEntry->offsetInBytes = 0; + pEntry->mobid = SVGA_ID_INVALID; + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineShader(pThisCC, pDXContext, shaderId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyShader const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyShader, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dShaderId const shaderId = pCmd->shaderId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paShader, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(shaderId < pDXContext->cot.cShader, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pSvgaR3State->pFuncsDX->pfnDXDestroyShader(pThisCC, pDXContext, shaderId); + + /* Cleanup COTable entries.*/ + SVGACOTableDXShaderEntry *pEntry = &pDXContext->cot.paShader[shaderId]; + pEntry->type = SVGA3D_SHADERTYPE_INVALID; + pEntry->sizeInBytes = 0; + pEntry->offsetInBytes = 0; + pEntry->mobid = SVGA_ID_INVALID; + + /** @todo Destroy shaders on context and backend deletion. */ + return rc; +} + + +static int dxBindShader(DXShaderInfo *pShaderInfo, PVMSVGAMOB pMob, SVGACOTableDXShaderEntry const *pEntry, void const *pvShaderBytecode) +{ + /* How many bytes the MOB can hold. */ + uint32_t const cbMob = vmsvgaR3MobSize(pMob) - pEntry->offsetInBytes; + ASSERT_GUEST_RETURN(cbMob >= pEntry->sizeInBytes, VERR_INVALID_PARAMETER); + AssertReturn(pEntry->sizeInBytes >= 8, VERR_INTERNAL_ERROR); /* Host ensures this in DefineShader. */ + + int rc = DXShaderParse(pvShaderBytecode, pEntry->sizeInBytes, pShaderInfo); + if (RT_SUCCESS(rc)) + { + /* Get the length of the shader bytecode. */ + uint32_t const *pau32Token = (uint32_t *)pvShaderBytecode; /* Tokens */ + uint32_t const cToken = pau32Token[1]; /* Length of the shader in tokens. */ + ASSERT_GUEST_RETURN(cToken <= pEntry->sizeInBytes / 4, VERR_INVALID_PARAMETER); + + /* Check if the shader contains SVGA3dDXSignatureHeader and signature entries after the bytecode. + * If they are not there (Linux guest driver does not provide them), then it is fine + * and the signatures generated by DXShaderParse will be used. + */ + uint32_t cbSignaturesAvail = pEntry->sizeInBytes - cToken * 4; /* How many bytes for signatures are available. */ + if (cbSignaturesAvail >= sizeof(SVGA3dDXSignatureHeader)) + { + cbSignaturesAvail -= sizeof(SVGA3dDXSignatureHeader); + + SVGA3dDXSignatureHeader const *pSignatureHeader = (SVGA3dDXSignatureHeader *)((uint8_t *)pvShaderBytecode + cToken * 4); + if (pSignatureHeader->headerVersion == SVGADX_SIGNATURE_HEADER_VERSION_0) + { + ASSERT_GUEST_RETURN( pSignatureHeader->numInputSignatures <= RT_ELEMENTS(pShaderInfo->aInputSignature) + && pSignatureHeader->numOutputSignatures <= RT_ELEMENTS(pShaderInfo->aOutputSignature) + && pSignatureHeader->numPatchConstantSignatures <= RT_ELEMENTS(pShaderInfo->aPatchConstantSignature), + VERR_INVALID_PARAMETER); + + uint32_t const cSignature = pSignatureHeader->numInputSignatures + + pSignatureHeader->numOutputSignatures + + pSignatureHeader->numPatchConstantSignatures; + uint32_t const cbSignature = cSignature * sizeof(SVGA3dDXSignatureEntry); + ASSERT_GUEST_RETURN(cbSignaturesAvail >= cbSignature, VERR_INVALID_PARAMETER); + + /* The shader does not need guesswork. */ + pShaderInfo->fGuestSignatures = true; + + /* Copy to DXShaderInfo. */ + uint8_t const *pu8Signatures = (uint8_t *)&pSignatureHeader[1]; + pShaderInfo->cInputSignature = pSignatureHeader->numInputSignatures; + memcpy(pShaderInfo->aInputSignature, pu8Signatures, pSignatureHeader->numInputSignatures * sizeof(SVGA3dDXSignatureEntry)); + + pu8Signatures += pSignatureHeader->numInputSignatures * sizeof(SVGA3dDXSignatureEntry); + pShaderInfo->cOutputSignature = pSignatureHeader->numOutputSignatures; + memcpy(pShaderInfo->aOutputSignature, pu8Signatures, pSignatureHeader->numOutputSignatures * sizeof(SVGA3dDXSignatureEntry)); + + pu8Signatures += pSignatureHeader->numOutputSignatures * sizeof(SVGA3dDXSignatureEntry); + pShaderInfo->cPatchConstantSignature = pSignatureHeader->numPatchConstantSignatures; + memcpy(pShaderInfo->aPatchConstantSignature, pu8Signatures, pSignatureHeader->numPatchConstantSignatures * sizeof(SVGA3dDXSignatureEntry)); + + /* Sort must be called before GenerateSemantics which assigns attribute indices + * based on the order of attributes. + */ + DXShaderSortSignatures(pShaderInfo); + DXShaderGenerateSemantics(pShaderInfo); + } + } + } + + return rc; +} + + +int vmsvga3dDXBindShader(PVGASTATECC pThisCC, SVGA3dCmdDXBindShader const *pCmd, PVMSVGAMOB pMob) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXBindShader, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, pCmd->cid, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(pCmd->shid < pDXContext->cot.cShader, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* 'type' and 'sizeInBytes' has been already initialized by DefineShader. */ + SVGACOTableDXShaderEntry *pEntry = &pDXContext->cot.paShader[pCmd->shid]; + //pEntry->type; + //pEntry->sizeInBytes; + pEntry->offsetInBytes = pCmd->offsetInBytes; + pEntry->mobid = vmsvgaR3MobId(pMob); + + if (pMob) + { + /* Bind a mob to the shader. */ + + /* Create a memory pointer for the MOB, which is accessible by host. */ + rc = vmsvgaR3MobBackingStoreCreate(pSvgaR3State, pMob, vmsvgaR3MobSize(pMob)); + if (RT_SUCCESS(rc)) + { + /* Get pointer to the shader bytecode. This will also verify the offset. */ + void const *pvShaderBytecode = vmsvgaR3MobBackingStorePtr(pMob, pEntry->offsetInBytes); + ASSERT_GUEST_RETURN(pvShaderBytecode, VERR_INVALID_PARAMETER); + + /* Get the shader and optional signatures from the MOB. */ + DXShaderInfo shaderInfo; + RT_ZERO(shaderInfo); + rc = dxBindShader(&shaderInfo, pMob, pEntry, pvShaderBytecode); + if (RT_SUCCESS(rc)) + { + /* pfnDXBindShader makes a copy of shaderInfo on success. */ + rc = pSvgaR3State->pFuncsDX->pfnDXBindShader(pThisCC, pDXContext, pCmd->shid, &shaderInfo); + } + AssertRC(rc); + + /** @todo Backing store is not needed anymore in any case? */ + if (RT_FAILURE(rc)) + { + DXShaderFree(&shaderInfo); + + vmsvgaR3MobBackingStoreDelete(pSvgaR3State, pMob); + } + } + } + else + { + /* Unbind. */ + /** @todo Nothing to do here but release the MOB? */ + vmsvgaR3MobBackingStoreDelete(pSvgaR3State, pMob); + } + + return rc; +} + + +int vmsvga3dDXDefineStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineStreamOutput const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineStreamOutput, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dStreamOutputId const soid = pCmd->soid; + + ASSERT_GUEST_RETURN(pDXContext->cot.paStreamOutput, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(soid < pDXContext->cot.cStreamOutput, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->numOutputStreamEntries < SVGA3D_MAX_DX10_STREAMOUT_DECLS, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXStreamOutputEntry *pEntry = &pDXContext->cot.paStreamOutput[soid]; + pEntry->numOutputStreamEntries = pCmd->numOutputStreamEntries; + memcpy(pEntry->decl, pCmd->decl, sizeof(pEntry->decl)); + memcpy(pEntry->streamOutputStrideInBytes, pCmd->streamOutputStrideInBytes, sizeof(pEntry->streamOutputStrideInBytes)); + pEntry->rasterizedStream = 0; // Apparently invalid in this command: pCmd->rasterizedStream; + pEntry->numOutputStreamStrides = 0; + pEntry->mobid = SVGA_ID_INVALID; + pEntry->offsetInBytes = 0; + pEntry->usesMob = 0; + pEntry->pad0 = 0; + pEntry->pad1 = 0; + RT_ZERO(pEntry->pad2); + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineStreamOutput(pThisCC, pDXContext, soid, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyStreamOutput const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyStreamOutput, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dStreamOutputId const soid = pCmd->soid; + + ASSERT_GUEST_RETURN(pDXContext->cot.paStreamOutput, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(soid < pDXContext->cot.cStreamOutput, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXDestroyStreamOutput(pThisCC, pDXContext, soid); + + SVGACOTableDXStreamOutputEntry *pEntry = &pDXContext->cot.paStreamOutput[soid]; + RT_ZERO(*pEntry); + pEntry->mobid = SVGA_ID_INVALID; + + return rc; +} + + +int vmsvga3dDXSetStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetStreamOutput const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetStreamOutput, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dStreamOutputId const soid = pCmd->soid; + + ASSERT_GUEST_RETURN( soid == SVGA_ID_INVALID + || soid < pDXContext->cot.cStreamOutput, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pDXContext->svgaDXContext.streamOut.soid = soid; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetStreamOutput(pThisCC, pDXContext, soid); + return rc; +} + + +static int dxSetOrGrowCOTable(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGAMOB pMob, + SVGACOTableType type, uint32_t validSizeInBytes, bool fGrow) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + int rc = VINF_SUCCESS; + + ASSERT_GUEST_RETURN(type < RT_ELEMENTS(pDXContext->aCOTMobs), VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t cbCOT; + if (pMob) + { + /* Bind a new mob to the COTable. */ + cbCOT = vmsvgaR3MobSize(pMob); + + ASSERT_GUEST_RETURN(validSizeInBytes <= cbCOT, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Create a memory pointer, which is accessible by host. */ + rc = vmsvgaR3MobBackingStoreCreate(pSvgaR3State, pMob, validSizeInBytes); + } + else + { + /* Unbind. */ + validSizeInBytes = 0; + cbCOT = 0; + vmsvgaR3MobBackingStoreDelete(pSvgaR3State, pDXContext->aCOTMobs[type]); + } + + uint32_t cEntries = 0; + uint32_t cValidEntries = 0; + if (RT_SUCCESS(rc)) + { + static uint32_t const s_acbEntry[SVGA_COTABLE_MAX] = + { + sizeof(SVGACOTableDXRTViewEntry), + sizeof(SVGACOTableDXDSViewEntry), + sizeof(SVGACOTableDXSRViewEntry), + sizeof(SVGACOTableDXElementLayoutEntry), + sizeof(SVGACOTableDXBlendStateEntry), + sizeof(SVGACOTableDXDepthStencilEntry), + sizeof(SVGACOTableDXRasterizerStateEntry), + sizeof(SVGACOTableDXSamplerEntry), + sizeof(SVGACOTableDXStreamOutputEntry), + sizeof(SVGACOTableDXQueryEntry), + sizeof(SVGACOTableDXShaderEntry), + sizeof(SVGACOTableDXUAViewEntry), + }; + + cEntries = cbCOT / s_acbEntry[type]; + cValidEntries = validSizeInBytes / s_acbEntry[type]; + } + + if (RT_SUCCESS(rc)) + { + if ( fGrow + && pDXContext->aCOTMobs[type] + && cValidEntries) + { + /* Copy entries from the current mob to the new mob. */ + void const *pvSrc = vmsvgaR3MobBackingStorePtr(pDXContext->aCOTMobs[type], 0); + void *pvDst = vmsvgaR3MobBackingStorePtr(pMob, 0); + if (pvSrc && pvDst) + memcpy(pvDst, pvSrc, validSizeInBytes); + else + AssertFailedStmt(rc = VERR_INVALID_STATE); + } + } + + if (RT_SUCCESS(rc)) + { + pDXContext->aCOTMobs[type] = pMob; + + void *pvCOT = vmsvgaR3MobBackingStorePtr(pMob, 0); + switch (type) + { + case SVGA_COTABLE_RTVIEW: + pDXContext->cot.paRTView = (SVGACOTableDXRTViewEntry *)pvCOT; + pDXContext->cot.cRTView = cEntries; + break; + case SVGA_COTABLE_DSVIEW: + pDXContext->cot.paDSView = (SVGACOTableDXDSViewEntry *)pvCOT; + pDXContext->cot.cDSView = cEntries; + break; + case SVGA_COTABLE_SRVIEW: + pDXContext->cot.paSRView = (SVGACOTableDXSRViewEntry *)pvCOT; + pDXContext->cot.cSRView = cEntries; + break; + case SVGA_COTABLE_ELEMENTLAYOUT: + pDXContext->cot.paElementLayout = (SVGACOTableDXElementLayoutEntry *)pvCOT; + pDXContext->cot.cElementLayout = cEntries; + break; + case SVGA_COTABLE_BLENDSTATE: + pDXContext->cot.paBlendState = (SVGACOTableDXBlendStateEntry *)pvCOT; + pDXContext->cot.cBlendState = cEntries; + break; + case SVGA_COTABLE_DEPTHSTENCIL: + pDXContext->cot.paDepthStencil = (SVGACOTableDXDepthStencilEntry *)pvCOT; + pDXContext->cot.cDepthStencil = cEntries; + break; + case SVGA_COTABLE_RASTERIZERSTATE: + pDXContext->cot.paRasterizerState = (SVGACOTableDXRasterizerStateEntry *)pvCOT; + pDXContext->cot.cRasterizerState = cEntries; + break; + case SVGA_COTABLE_SAMPLER: + pDXContext->cot.paSampler = (SVGACOTableDXSamplerEntry *)pvCOT; + pDXContext->cot.cSampler = cEntries; + break; + case SVGA_COTABLE_STREAMOUTPUT: + pDXContext->cot.paStreamOutput = (SVGACOTableDXStreamOutputEntry *)pvCOT; + pDXContext->cot.cStreamOutput = cEntries; + break; + case SVGA_COTABLE_DXQUERY: + pDXContext->cot.paQuery = (SVGACOTableDXQueryEntry *)pvCOT; + pDXContext->cot.cQuery = cEntries; + break; + case SVGA_COTABLE_DXSHADER: + pDXContext->cot.paShader = (SVGACOTableDXShaderEntry *)pvCOT; + pDXContext->cot.cShader = cEntries; + break; + case SVGA_COTABLE_UAVIEW: + pDXContext->cot.paUAView = (SVGACOTableDXUAViewEntry *)pvCOT; + pDXContext->cot.cUAView = cEntries; + break; + case SVGA_COTABLE_MAX: break; /* Compiler warning */ + } + } + else + vmsvgaR3MobBackingStoreDelete(pSvgaR3State, pMob); + + /* Notify the backend. */ + if (RT_SUCCESS(rc)) + rc = pSvgaR3State->pFuncsDX->pfnDXSetCOTable(pThisCC, pDXContext, type, cValidEntries); + + return rc; +} + + +int vmsvga3dDXSetCOTable(PVGASTATECC pThisCC, SVGA3dCmdDXSetCOTable const *pCmd, PVMSVGAMOB pMob) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetCOTable, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, pCmd->cid, &pDXContext); + AssertRCReturn(rc, rc); + RT_UNTRUSTED_VALIDATED_FENCE(); + + return dxSetOrGrowCOTable(pThisCC, pDXContext, pMob, pCmd->type, pCmd->validSizeInBytes, false); +} + + +int vmsvga3dDXReadbackCOTable(PVGASTATECC pThisCC, SVGA3dCmdDXReadbackCOTable const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, pCmd->cid, &pDXContext); + AssertRCReturn(rc, rc); + RT_UNTRUSTED_VALIDATED_FENCE(); + + ASSERT_GUEST_RETURN(pCmd->type < RT_ELEMENTS(pDXContext->aCOTMobs), VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + PVMSVGAMOB pMob = pDXContext->aCOTMobs[pCmd->type]; + rc = vmsvgaR3MobBackingStoreWriteToGuest(pSvgaR3State, pMob); + return rc; +} + + +int vmsvga3dDXBufferCopy(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXBufferCopy, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXBufferCopy(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXSurfaceCopyAndReadback(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSurfaceCopyAndReadback, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXSurfaceCopyAndReadback(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXMoveQuery(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXMoveQuery, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXMoveQuery(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXBindAllQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindAllQuery const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + RT_NOREF(idDXContext); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, pCmd->cid, &pDXContext); + AssertRCReturn(rc, rc); + + for (uint32_t i = 0; i < pDXContext->cot.cQuery; ++i) + { + SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[i]; + if (pEntry->type != SVGA3D_QUERYTYPE_INVALID) + pEntry->mobid = pCmd->mobid; + } + + return rc; +} + + +int vmsvga3dDXReadbackAllQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXReadbackAllQuery const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + RT_NOREF(idDXContext); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, pCmd->cid, &pDXContext); + AssertRCReturn(rc, rc); + + /* "Read back cached states from the device if they exist." + * The device does not cache queries. So this is a NOP. + */ + RT_NOREF(pDXContext); + + return rc; +} + + +int vmsvga3dDXBindAllShader(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXBindAllShader, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXBindAllShader(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXHint(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXHint, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXHint(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXBufferUpdate(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXBufferUpdate, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXBufferUpdate(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXSetConstantBufferOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetConstantBufferOffset const *pCmd, SVGA3dShaderType type) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetSingleConstantBuffer, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(pCmd->slot < SVGA3D_DX_MAX_CONSTBUFFERS, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint32_t const idxShaderState = type - SVGA3D_SHADERTYPE_MIN; + SVGA3dConstantBufferBinding *pCBB = &pDXContext->svgaDXContext.shaderState[idxShaderState].constantBuffers[pCmd->slot]; + + /* Only 'offsetInBytes' is updated. */ + // pCBB->sid; + pCBB->offsetInBytes = pCmd->offsetInBytes; + // pCBB->sizeInBytes; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetSingleConstantBuffer(pThisCC, pDXContext, pCmd->slot, type, pCBB->sid, pCBB->offsetInBytes, pCBB->sizeInBytes); + return rc; +} + + +int vmsvga3dDXCondBindAllShader(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXCondBindAllShader, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXCondBindAllShader(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dScreenCopy(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnScreenCopy, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnScreenCopy(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXGrowCOTable(PVGASTATECC pThisCC, SVGA3dCmdDXGrowCOTable const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetCOTable, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, pCmd->cid, &pDXContext); + AssertRCReturn(rc, rc); + + PVMSVGAMOB pMob = vmsvgaR3MobGet(pSvgaR3State, pCmd->mobid); + return dxSetOrGrowCOTable(pThisCC, pDXContext, pMob, pCmd->type, pCmd->validSizeInBytes, true); +} + + +int vmsvga3dIntraSurfaceCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdIntraSurfaceCopy const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnIntraSurfaceCopy, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnIntraSurfaceCopy(pThisCC, pDXContext, pCmd->surface, pCmd->box); + return rc; +} + + +int vmsvga3dDXResolveCopy(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXResolveCopy, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXResolveCopy(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXPredResolveCopy(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXPredResolveCopy, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXPredResolveCopy(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXPredConvertRegion(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXPredConvertRegion, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXPredConvertRegion(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXPredConvert(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXPredConvert, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXPredConvert(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dWholeSurfaceCopy(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnWholeSurfaceCopy, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnWholeSurfaceCopy(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXDefineUAView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineUAView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDefineUAView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dUAViewId const uaViewId = pCmd->uaViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paUAView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(uaViewId < pDXContext->cot.cUAView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXUAViewEntry *pEntry = &pDXContext->cot.paUAView[uaViewId]; + pEntry->sid = pCmd->sid; + pEntry->format = pCmd->format; + pEntry->resourceDimension = pCmd->resourceDimension; + pEntry->desc = pCmd->desc; + pEntry->structureCount = 0; + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineUAView(pThisCC, pDXContext, uaViewId, pEntry); + return rc; +} + + +int vmsvga3dDXDestroyUAView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyUAView const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDestroyUAView, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dUAViewId const uaViewId = pCmd->uaViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paUAView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(uaViewId < pDXContext->cot.cUAView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXUAViewEntry *pEntry = &pDXContext->cot.paUAView[uaViewId]; + RT_ZERO(*pEntry); + + rc = pSvgaR3State->pFuncsDX->pfnDXDestroyUAView(pThisCC, pDXContext, uaViewId); + return rc; +} + + +int vmsvga3dDXClearUAViewUint(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearUAViewUint const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXClearUAViewUint, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dUAViewId const uaViewId = pCmd->uaViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paUAView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(uaViewId < pDXContext->cot.cUAView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXClearUAViewUint(pThisCC, pDXContext, uaViewId, pCmd->value.value); + return rc; +} + + +int vmsvga3dDXClearUAViewFloat(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearUAViewFloat const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXClearUAViewFloat, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dUAViewId const uaViewId = pCmd->uaViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paUAView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(uaViewId < pDXContext->cot.cUAView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXClearUAViewFloat(pThisCC, pDXContext, uaViewId, pCmd->value.value); + return rc; +} + + +int vmsvga3dDXCopyStructureCount(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXCopyStructureCount const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXCopyStructureCount, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dUAViewId const uaViewId = pCmd->srcUAViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paUAView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(uaViewId < pDXContext->cot.cUAView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnDXCopyStructureCount(pThisCC, pDXContext, uaViewId, pCmd->destSid, pCmd->destByteOffset); + return rc; +} + + +int vmsvga3dDXSetUAViews(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetUAViews const *pCmd, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetUAViews, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(pCmd->uavSpliceIndex <= SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(cUAViewId <= SVGA3D_DX11_1_MAX_UAVIEWS, VERR_INVALID_PARAMETER); + for (uint32_t i = 0; i < cUAViewId; ++i) + ASSERT_GUEST_RETURN( paUAViewId[i] < pDXContext->cot.cUAView + || paUAViewId[i] == SVGA3D_INVALID_ID, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + for (uint32_t i = 0; i < cUAViewId; ++i) + { + SVGA3dUAViewId const uaViewId = paUAViewId[i]; + pDXContext->svgaDXContext.uaViewIds[i] = uaViewId; + } + pDXContext->svgaDXContext.uavSpliceIndex = pCmd->uavSpliceIndex; + + rc = pSvgaR3State->pFuncsDX->pfnDXSetUAViews(pThisCC, pDXContext, pCmd->uavSpliceIndex, cUAViewId, paUAViewId); + return rc; +} + + +int vmsvga3dDXDrawIndexedInstancedIndirect(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexedInstancedIndirect const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDrawIndexedInstancedIndirect, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDrawIndexedInstancedIndirect(pThisCC, pDXContext, pCmd->argsBufferSid, pCmd->byteOffsetForArgs); + return rc; +} + + +int vmsvga3dDXDrawInstancedIndirect(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawInstancedIndirect const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDrawInstancedIndirect, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDrawInstancedIndirect(pThisCC, pDXContext, pCmd->argsBufferSid, pCmd->byteOffsetForArgs); + return rc; +} + + +int vmsvga3dDXDispatch(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDispatch const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDispatch, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDispatch(pThisCC, pDXContext, pCmd->threadGroupCountX, pCmd->threadGroupCountY, pCmd->threadGroupCountZ); + return rc; +} + + +int vmsvga3dDXDispatchIndirect(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXDispatchIndirect, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXDispatchIndirect(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dWriteZeroSurface(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnWriteZeroSurface, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnWriteZeroSurface(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dHintZeroSurface(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnHintZeroSurface, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnHintZeroSurface(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXTransferToBuffer(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXTransferToBuffer, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXTransferToBuffer(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXSetStructureCount(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetStructureCount const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dUAViewId const uaViewId = pCmd->uaViewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paUAView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(uaViewId < pDXContext->cot.cUAView, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXUAViewEntry *pEntry = &pDXContext->cot.paUAView[uaViewId]; + pEntry->structureCount = pCmd->structureCount; + + return VINF_SUCCESS; +} + + +int vmsvga3dLogicOpsBitBlt(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnLogicOpsBitBlt, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnLogicOpsBitBlt(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dLogicOpsTransBlt(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnLogicOpsTransBlt, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnLogicOpsTransBlt(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dLogicOpsStretchBlt(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnLogicOpsStretchBlt, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnLogicOpsStretchBlt(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dLogicOpsColorFill(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnLogicOpsColorFill, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnLogicOpsColorFill(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dLogicOpsAlphaBlend(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnLogicOpsAlphaBlend, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnLogicOpsAlphaBlend(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dLogicOpsClearTypeBlend(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnLogicOpsClearTypeBlend, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnLogicOpsClearTypeBlend(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXSetCSUAViews(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetCSUAViews const *pCmd, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetCSUAViews, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN(pCmd->startIndex < SVGA3D_DX11_1_MAX_UAVIEWS, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(cUAViewId <= SVGA3D_DX11_1_MAX_UAVIEWS - pCmd->startIndex, VERR_INVALID_PARAMETER); + for (uint32_t i = 0; i < cUAViewId; ++i) + ASSERT_GUEST_RETURN( paUAViewId[i] < pDXContext->cot.cUAView + || paUAViewId[i] == SVGA3D_INVALID_ID, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + for (uint32_t i = 0; i < cUAViewId; ++i) + { + SVGA3dUAViewId const uaViewId = paUAViewId[i]; + pDXContext->svgaDXContext.csuaViewIds[pCmd->startIndex + i] = uaViewId; + } + + rc = pSvgaR3State->pFuncsDX->pfnDXSetCSUAViews(pThisCC, pDXContext, pCmd->startIndex, cUAViewId, paUAViewId); + return rc; +} + + +int vmsvga3dDXSetMinLOD(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetMinLOD, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXSetMinLOD(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXDefineStreamOutputWithMob(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineStreamOutputWithMob const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dStreamOutputId const soid = pCmd->soid; + + ASSERT_GUEST_RETURN(pDXContext->cot.paStreamOutput, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(soid < pDXContext->cot.cStreamOutput, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(pCmd->numOutputStreamEntries < SVGA3D_MAX_STREAMOUT_DECLS, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXStreamOutputEntry *pEntry = &pDXContext->cot.paStreamOutput[soid]; + pEntry->numOutputStreamEntries = pCmd->numOutputStreamEntries; + RT_ZERO(pEntry->decl); + memcpy(pEntry->streamOutputStrideInBytes, pCmd->streamOutputStrideInBytes, sizeof(pEntry->streamOutputStrideInBytes)); + pEntry->rasterizedStream = pCmd->rasterizedStream; + pEntry->numOutputStreamStrides = pCmd->numOutputStreamStrides; + pEntry->mobid = SVGA_ID_INVALID; + pEntry->offsetInBytes = 0; + pEntry->usesMob = 1; + pEntry->pad0 = 0; + pEntry->pad1 = 0; + RT_ZERO(pEntry->pad2); + + rc = pSvgaR3State->pFuncsDX->pfnDXDefineStreamOutput(pThisCC, pDXContext, soid, pEntry); + return rc; +} + + +int vmsvga3dDXSetShaderIface(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXSetShaderIface, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXSetShaderIface(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXBindStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindStreamOutput const *pCmd) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + SVGA3dStreamOutputId const soid = pCmd->soid; + + ASSERT_GUEST_RETURN(pDXContext->cot.paStreamOutput, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(soid < pDXContext->cot.cStreamOutput, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + SVGACOTableDXStreamOutputEntry *pEntry = &pDXContext->cot.paStreamOutput[soid]; + + ASSERT_GUEST_RETURN(pCmd->sizeInBytes >= pEntry->numOutputStreamEntries * sizeof(SVGA3dStreamOutputDeclarationEntry), VERR_INVALID_PARAMETER); + ASSERT_GUEST(pEntry->usesMob); + + pEntry->mobid = pCmd->mobid; + pEntry->offsetInBytes = pCmd->offsetInBytes; + pEntry->usesMob = 1; + + return VINF_SUCCESS; +} + + +int vmsvga3dSurfaceStretchBltNonMSToMS(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnSurfaceStretchBltNonMSToMS, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnSurfaceStretchBltNonMSToMS(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dDXBindShaderIface(PVGASTATECC pThisCC, uint32_t idDXContext) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnDXBindShaderIface, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + rc = pSvgaR3State->pFuncsDX->pfnDXBindShaderIface(pThisCC, pDXContext); + return rc; +} + + +int vmsvga3dVBDXClearRenderTargetViewRegion(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdVBDXClearRenderTargetViewRegion const *pCmd, uint32_t cRect, SVGASignedRect const *paRect) +{ + int rc; + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsDX && pSvgaR3State->pFuncsDX->pfnVBDXClearRenderTargetViewRegion, VERR_INVALID_STATE); + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturn(p3dState, VERR_INVALID_STATE); + + PVMSVGA3DDXCONTEXT pDXContext; + rc = vmsvga3dDXContextFromCid(p3dState, idDXContext, &pDXContext); + AssertRCReturn(rc, rc); + + SVGA3dRenderTargetViewId const renderTargetViewId = pCmd->viewId; + + ASSERT_GUEST_RETURN(pDXContext->cot.paRTView, VERR_INVALID_STATE); + ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->cot.cRTView, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(cRect <= 65536, VERR_INVALID_PARAMETER); /* Arbitrary limit. */ + RT_UNTRUSTED_VALIDATED_FENCE(); + + rc = pSvgaR3State->pFuncsDX->pfnVBDXClearRenderTargetViewRegion(pThisCC, pDXContext, renderTargetViewId, &pCmd->color, cRect, paRect); + return rc; +} + diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glHlp.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glHlp.cpp new file mode 100644 index 00000000..3baec0f6 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glHlp.cpp @@ -0,0 +1,768 @@ +/* $Id: DevVGA-SVGA3d-glHlp.cpp $ */ +/** @file + * DevVMWare - VMWare SVGA device OpenGL backend + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#ifdef DEBUG_bird +//# define RTMEM_WRAP_TO_EF_APIS +#endif +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include + +#include +#include + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d-internal.h" + +/* Parameters for glVertexAttribPointer. */ +typedef struct VertexAttribDesc +{ + GLint size; + GLenum type; + GLboolean normalized; + GLsizei stride; + GLsizei offset; +} VertexAttribDesc; + +/* Information about a shader program. */ +typedef struct ShaderProgram +{ + GLuint vertexShader; /* Vertex shader name. */ + GLuint fragmentShader; /* Fragment shader name. */ + GLuint program; /* Shader program name. */ + GLint sSourceTex; /* Location of the texture sampler uniform in the shader. */ + GLint uTexInfo; /* Location of the texture information uniform in the shader. */ +} ShaderProgram; + +/* Texture format conversion data. + * Uses a fragment (pixel) shader to render a source texture in one format + * to the target texture in another format. + */ +typedef struct VMSVGA3DFORMATCONVERTER +{ + PVMSVGA3DSTATE pState; + + ShaderProgram programYUY2ToRGB; /* From the YUY2 emulated format to the actual RGB texture. */ + ShaderProgram programYUY2FromRGB; /* From the actual RGB texture to the emulated YUY2 format. */ + ShaderProgram programUYVYToRGB; /* From the UYVY emulated format to the actual RGB texture. */ + ShaderProgram programUYVYFromRGB; /* From the actual RGB texture to the emulated UYVY format. */ + + GLuint framebuffer; /* Framebuffer object name. */ + + GLuint vertexBuffer; /* Vertex attribute buffer. Position + texcoord. */ +} VMSVGA3DFORMATCONVERTER; + +/* Parameters for glVertexAttribPointer. */ +static const VertexAttribDesc aVertexAttribs[] = +{ + {2, GL_FLOAT, GL_FALSE, 16, 0 }, /* Position. */ + {2, GL_FLOAT, GL_FALSE, 16, 8 } /* Texcoord. */ +}; + +/* Triangle fan */ +static float const aAttribData[] = +{ + /* positions texcoords */ + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 0.0f, 1.0f +}; + +static const GLchar shaderHeaderSource[] = +{ + " #version 120\n" +}; + +static const GLchar vertexShaderSource[] = +{ + " attribute vec2 attrib0;\n" + " attribute vec2 attrib1;\n" + " void main(void)\n" + " {\n" + " gl_TexCoord[0].xy = attrib1;\n" + " gl_Position = vec4(attrib0.x, attrib0.y, 0.0f, 1.0f);\n" + " }\n" +}; + +static const GLchar fetchYUY2Source[] = +{ + " vec4 fetchYUV(vec4 texColor)\n" + " {\n" + " return vec4(texColor.b, texColor.g, texColor.r, texColor.a);\n" + " }\n" +}; + +static const GLchar fetchUYVYSource[] = +{ + " vec4 fetchYUV(vec4 texColor)\n" + " {\n" + " return vec4(texColor.g, texColor.b, texColor.a, texColor.r);\n" + " }\n" +}; + +static const GLchar YUV2RGBShaderSource[] = +{ + " uniform sampler2D sSourceTex;\n" + " uniform vec4 uTexInfo;\n" + " \n" + " const mat3 yuvCoeffs = mat3\n" + " (\n" + " 1.164383f, 0.0f, 1.596027f, // first column \n" + " 1.164383f, -0.391762f, -0.812968f, // second column\n" + " 1.164383f, 2.017232f, 0.0f // third column\n" + " );\n" + " \n" + " void main() {\n" + " // Input texcoords are in [0;1] range for the target.\n" + " vec2 texCoord = gl_TexCoord[0].xy;\n" + " // Convert to the target coords in pixels: xPixel = texCoord.x * TextureWidth. \n" + " float xTargetPixel = texCoord.x * uTexInfo.x;\n" + " // Source texture is half width, i.e. it contains data in pixels [0; width / 2 - 1].\n" + " float xSourcePixel = xTargetPixel / 2.0f;\n" + " // Remainder is about 0.25 for even pixels and about 0.75 for odd pixels.\n" + " float remainder = fract(xSourcePixel);\n" + " // Back to the normalized coords: texCoord.x = xPixel / Width.\n" + " texCoord.x = xSourcePixel * uTexInfo.z;\n" + " vec4 texColor = texture2D(sSourceTex, texCoord);\n" + " vec4 y0uy1v = fetchYUV(texColor);\n" + " // Get y0 for even x coordinates and y1 for odd ones.\n" + " float y = remainder < 0.5f ? y0uy1v.x : y0uy1v.z;\n" + " // Make a vector for easier calculation.\n" + " vec3 yuv = vec3(y, y0uy1v.y, y0uy1v.w);\n" + " yuv -= vec3(0.0627f, 0.502f, 0.502f);\n" + " vec3 bgr = yuv * yuvCoeffs;\n" + " //vec3 bgr;\n" + " //bgr.r = 1.164383 * yuv.x + 1.596027 * yuv.z;\n" + " //bgr.g = 1.164383 * yuv.x - 0.391762 * yuv.y - 0.812968 * yuv.z;\n" + " //bgr.b = 1.164383 * yuv.x + 2.017232 * yuv.y;\n" + " bgr = clamp(bgr, 0.0f, 1.0f);\n" + " gl_FragData[0] = vec4(bgr, 1.0f);\n" + " }\n" +}; + +static const GLchar storeYUY2Source[] = +{ + " vec4 storeYUV(float y0, float u, float y1, float v)\n" + " {\n" + " return vec4(y1, u, y0, v);\n" + " }\n" +}; + +static const GLchar storeUYVYSource[] = +{ + " vec4 storeYUV(float y0, float u, float y1, float v)\n" + " {\n" + " return vec4(u, y1, v, y0);\n" + " }\n" +}; + +static const GLchar RGB2YUVShaderSource[] = +{ + " uniform sampler2D sSourceTex;\n" + " uniform vec4 uTexInfo;\n" + " \n" + " const mat3 bgrCoeffs = mat3\n" + " (\n" + " 0.2578f, 0.5039f, 0.0977f, // first column \n" + " -0.1484f, -0.2891f, 0.4375f, // second column\n" + " 0.4375f, -0.3672f, -0.0703f // third column\n" + " );\n" + " const vec3 yuvShift = vec3(0.0647f, 0.5039f, 0.5039f);\n" + " \n" + " void main() {\n" + " // Input texcoords are in [0;1] range for the target.\n" + " vec2 texCoordDst = gl_TexCoord[0].xy;\n" + " // Convert to the target coords in pixels: xPixel = TexCoord.x * TextureWidth.\n" + " float xTargetPixel = texCoordDst.x * uTexInfo.x;\n" + " vec4 bgraOutputPixel;\n" + " if (xTargetPixel < uTexInfo.x / 2.0f)\n" + " {\n" + " // Target texture is half width, i.e. it contains data in pixels [0; width / 2 - 1].\n" + " // Compute the source texture coords for the pixels which will be used to compute the target pixel.\n" + " vec2 texCoordSrc = texCoordDst;\n" + " texCoordSrc.x *= 2.0f;\n" + " // Even pixel. Fetch two BGRA source pixels.\n" + " vec4 texColor0 = texture2D(sSourceTex, texCoordSrc);\n" + " // Advance one pixel (+ 1/Width)\n" + " texCoordSrc.x += uTexInfo.z;\n" + " vec4 texColor1 = texture2D(sSourceTex, texCoordSrc);\n" + " vec3 yuv0 = texColor0.rgb * bgrCoeffs;\n" + " yuv0 += yuvShift;\n" + " vec3 yuv1 = texColor1.rgb * bgrCoeffs;\n" + " yuv1 += yuvShift;\n" + " float y0 = yuv0.r;\n" + " float u = (yuv0.g + yuv1.g) / 2.0f;\n" + " float y1 = yuv1.r;\n" + " float v = (yuv0.b + yuv1.b) / 2.0f;\n" + " bgraOutputPixel = storeYUV(y0, u, y1, v);\n" + " }\n" + " else\n" + " {\n" + " // [width / 2; width - 1] pixels are not used. Set to something.\n" + " bgraOutputPixel = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n" + " }\n" + " bgraOutputPixel = clamp(bgraOutputPixel, 0.0f, 1.0f);\n" + " gl_FragData[0] = bgraOutputPixel;\n" + " }\n" +}; + +#define GL_CHECK_ERROR() do { \ + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); \ + if (pContext->lastError != GL_NO_ERROR) \ + LogRelMax(10, ("VMSVGA: %s (%d): GL error 0x%x\n", __FUNCTION__, __LINE__, pContext->lastError)); \ +} while (0) + +/* Compile shaders and link a shader program. */ +static void createShaderProgram(PVMSVGA3DSTATE pState, + ShaderProgram *pProgram, + int cVertexSources, const GLchar **apszVertexSources, + int cFragmentSources, const GLchar **apszFragmentSources) +{ + AssertReturnVoid(pState->idActiveContext == VMSVGA3D_SHARED_CTX_ID); + + /* Everything is done on the shared context. The pState and pContext are for GL_CHECK_ERROR macro. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + + int success; + char szInfoLog[1024]; + + /* + * VERTEX shader. + */ + pProgram->vertexShader = pState->ext.glCreateShader(GL_VERTEX_SHADER); + GL_CHECK_ERROR(); + + pState->ext.glShaderSource(pProgram->vertexShader, cVertexSources, apszVertexSources, NULL); + GL_CHECK_ERROR(); + + pState->ext.glCompileShader(pProgram->vertexShader); + GL_CHECK_ERROR(); + + pState->ext.glGetShaderiv(pProgram->vertexShader, GL_COMPILE_STATUS, &success); + GL_CHECK_ERROR(); + if (!success) + { + pState->ext.glGetShaderInfoLog(pProgram->vertexShader, sizeof(szInfoLog), NULL, szInfoLog); + GL_CHECK_ERROR(); + LogRelMax(10, ("VMSVGA: Vertex shader compilation error:\n%s\n", szInfoLog)); + }; + + /* + * FRAGMENT shader. + */ + pProgram->fragmentShader = pState->ext.glCreateShader(GL_FRAGMENT_SHADER); + GL_CHECK_ERROR(); + + pState->ext.glShaderSource(pProgram->fragmentShader, cFragmentSources, apszFragmentSources, NULL); + GL_CHECK_ERROR(); + + pState->ext.glCompileShader(pProgram->fragmentShader); + GL_CHECK_ERROR(); + + pState->ext.glGetShaderiv(pProgram->fragmentShader, GL_COMPILE_STATUS, &success); + GL_CHECK_ERROR(); + if (!success) + { + pState->ext.glGetShaderInfoLog(pProgram->fragmentShader, sizeof(szInfoLog), NULL, szInfoLog); + GL_CHECK_ERROR(); + LogRelMax(10, ("VMSVGA: Fragment shader compilation error:\n%s\n", szInfoLog)); + }; + + /* + * Program + */ + pProgram->program = pState->ext.glCreateProgram(); + GL_CHECK_ERROR(); + + pState->ext.glAttachShader(pProgram->program, pProgram->vertexShader); + GL_CHECK_ERROR(); + + pState->ext.glAttachShader(pProgram->program, pProgram->fragmentShader); + GL_CHECK_ERROR(); + + pState->ext.glLinkProgram(pProgram->program); + GL_CHECK_ERROR(); + + pState->ext.glGetProgramiv(pProgram->program, GL_LINK_STATUS, &success); + if(!success) + { + pState->ext.glGetProgramInfoLog(pProgram->program, sizeof(szInfoLog), NULL, szInfoLog); + GL_CHECK_ERROR(); + LogRelMax(10, ("VMSVGA: Shader program link error:\n%s\n", szInfoLog)); + } + + pProgram->sSourceTex = pState->ext.glGetUniformLocation(pProgram->program, "sSourceTex"); + GL_CHECK_ERROR(); + + pProgram->uTexInfo = pState->ext.glGetUniformLocation(pProgram->program, "uTexInfo"); + GL_CHECK_ERROR(); +} + +/* Delete a shader program and associated shaders. */ +static void deleteShaderProgram(PVMSVGA3DSTATE pState, + ShaderProgram *pProgram) +{ + AssertReturnVoid(pState->idActiveContext == VMSVGA3D_SHARED_CTX_ID); + + /* Everything is done on the shared context. The pState and pContext are for GL_CHECK_ERROR macro. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + + if (pProgram->program) + { + if (pProgram->vertexShader) + { + pState->ext.glDetachShader(pProgram->program, pProgram->vertexShader); + GL_CHECK_ERROR(); + + pState->ext.glDeleteShader(pProgram->vertexShader); + GL_CHECK_ERROR(); + } + + if (pProgram->fragmentShader) + { + pState->ext.glDetachShader(pProgram->program, pProgram->fragmentShader); + GL_CHECK_ERROR(); + + pState->ext.glDeleteShader(pProgram->fragmentShader); + GL_CHECK_ERROR(); + } + + pState->ext.glDeleteProgram(pProgram->program); + GL_CHECK_ERROR(); + } + + RT_ZERO(*pProgram); +} + +/* Initialize the format conversion. Allocate and create necessary resources. */ +static void formatConversionInit(PVMSVGA3DSTATE pState) +{ + AssertReturnVoid(pState->idActiveContext == VMSVGA3D_SHARED_CTX_ID); + + PVMSVGA3DFORMATCONVERTER pConv = pState->pConv; + AssertReturnVoid(pConv); + + /* The pState and pContext variables are for GL_CHECK_ERROR macro. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + + pConv->pState = pState; + + /* + * Shader programs. + */ + static const GLchar *apszVertexShaderSources[] = + { + shaderHeaderSource, + vertexShaderSource + }; + + static const GLchar * apszYUY2ToRGBSources[] = + { + shaderHeaderSource, + fetchYUY2Source, + YUV2RGBShaderSource + }; + + static const GLchar *apszUYVYToRGBSources[] = + { + shaderHeaderSource, + fetchUYVYSource, + YUV2RGBShaderSource + }; + + static const GLchar *apszYUY2FromRGBSources[] = + { + shaderHeaderSource, + storeYUY2Source, + RGB2YUVShaderSource + }; + + static const GLchar *apszUYVYFromRGBSources[] = + { + shaderHeaderSource, + storeUYVYSource, + RGB2YUVShaderSource + }; + + createShaderProgram(pState, &pConv->programYUY2ToRGB, + RT_ELEMENTS(apszVertexShaderSources), apszVertexShaderSources, + RT_ELEMENTS(apszYUY2ToRGBSources), apszYUY2ToRGBSources); + + createShaderProgram(pState, &pConv->programUYVYToRGB, + RT_ELEMENTS(apszVertexShaderSources), apszVertexShaderSources, + RT_ELEMENTS(apszUYVYToRGBSources), apszUYVYToRGBSources); + + createShaderProgram(pState, &pConv->programYUY2FromRGB, + RT_ELEMENTS(apszVertexShaderSources), apszVertexShaderSources, + RT_ELEMENTS(apszYUY2FromRGBSources), apszYUY2FromRGBSources); + + createShaderProgram(pState, &pConv->programUYVYFromRGB, + RT_ELEMENTS(apszVertexShaderSources), apszVertexShaderSources, + RT_ELEMENTS(apszUYVYFromRGBSources), apszUYVYFromRGBSources); + + /* + * Create a framebuffer object which is used for rendering to a texture. + */ + pState->ext.glGenFramebuffers(1, &pConv->framebuffer); + GL_CHECK_ERROR(); + + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pConv->framebuffer); + GL_CHECK_ERROR(); + + static GLenum aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 }; + pState->ext.glDrawBuffers(RT_ELEMENTS(aDrawBuffers), aDrawBuffers); + GL_CHECK_ERROR(); + + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + GL_CHECK_ERROR(); + + /* + * Vertex attribute array. + */ + pState->ext.glGenBuffers(1, &pConv->vertexBuffer); + GL_CHECK_ERROR(); + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pConv->vertexBuffer); + GL_CHECK_ERROR(); + + pState->ext.glBufferData(GL_ARRAY_BUFFER, sizeof(aAttribData), aAttribData, GL_STATIC_DRAW); + GL_CHECK_ERROR(); + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0); + GL_CHECK_ERROR(); +} + +/* Delete everything. */ +static void formatConversionDestroy(PVMSVGA3DSTATE pState) +{ + AssertReturnVoid(pState->idActiveContext == VMSVGA3D_SHARED_CTX_ID); + + PVMSVGA3DFORMATCONVERTER pConv = pState->pConv; + AssertReturnVoid(pConv); + + /* The pState and pContext variables are for GL_CHECK_ERROR macro. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + + if (pConv->framebuffer != 0) + { + /* The code keeps nothing attached. */ + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pConv->framebuffer); + GL_CHECK_ERROR(); + + GLint texture = -1; + pState->ext.glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &texture); + GL_CHECK_ERROR(); + AssertMsg(texture == 0, ("texture %d\n", texture)); + + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + GL_CHECK_ERROR(); + + pState->ext.glDeleteFramebuffers(1, &pConv->framebuffer); + GL_CHECK_ERROR(); + + pConv->framebuffer = 0; + } + + deleteShaderProgram(pState, &pConv->programUYVYFromRGB); + deleteShaderProgram(pState, &pConv->programYUY2FromRGB); + deleteShaderProgram(pState, &pConv->programUYVYToRGB); + deleteShaderProgram(pState, &pConv->programYUY2ToRGB); + + if (pConv->vertexBuffer) + { + pState->ext.glDeleteBuffers(1, &pConv->vertexBuffer); + GL_CHECK_ERROR(); + + pConv->vertexBuffer = 0; + } + + pConv->pState = 0; +} + +/* Make use of a shader program for the current context and initialize the program uniforms. */ +static void setShaderProgram(PVMSVGA3DSTATE pState, + ShaderProgram *pProgram, + uint32_t cWidth, + uint32_t cHeight) +{ + AssertReturnVoid(pState->idActiveContext == VMSVGA3D_SHARED_CTX_ID); + + /* Everything is done on the shared context. The pState and pContext are for GL_CHECK_ERROR macro. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + + pState->ext.glUseProgram(pProgram->program); + GL_CHECK_ERROR(); + + pState->ext.glUniform1i(pProgram->sSourceTex, 0); + GL_CHECK_ERROR(); + + float aTextureInfo[4]; + aTextureInfo[0] = (float)cWidth; + aTextureInfo[1] = (float)cHeight; + aTextureInfo[2] = 1.0f / (float)cWidth; /* Pixel width in texture coords. */ + aTextureInfo[3] = 1.0f / (float)cHeight; /* Pixel height in texture coords. */ + + pState->ext.glUniform4fv(pProgram->uTexInfo, 1, aTextureInfo); + GL_CHECK_ERROR(); +} + +/* Attach the texture which must be used as the render target + * to the GL_DRAW_FRAMEBUFFER as GL_COLOR_ATTACHMENT0. + */ +static void setRenderTarget(PVMSVGA3DSTATE pState, + GLuint texture, + uint32_t iMipmap) +{ + AssertReturnVoid(pState->idActiveContext == VMSVGA3D_SHARED_CTX_ID); + + PVMSVGA3DFORMATCONVERTER pConv = pState->pConv; + AssertReturnVoid(pConv); + + /* Everything is done on the shared context. The pState and pContext are for GL_CHECK_ERROR macro. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pConv->framebuffer); + GL_CHECK_ERROR(); + + glBindTexture(GL_TEXTURE_2D, texture); + GL_CHECK_ERROR(); + + pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, iMipmap); + GL_CHECK_ERROR(); + + glBindTexture(GL_TEXTURE_2D, 0); + GL_CHECK_ERROR(); + + Assert(pState->ext.glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); +} + +/* Undo what setRenderTarget did. */ +static void unsetRenderTarget(PVMSVGA3DSTATE pState, + GLuint texture) +{ + AssertReturnVoid(pState->idActiveContext == VMSVGA3D_SHARED_CTX_ID); + + /* Everything is done on the shared context. The pState and pContext are for GL_CHECK_ERROR macro. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + + RT_NOREF(texture); + + pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + GL_CHECK_ERROR(); + + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + GL_CHECK_ERROR(); +} + +/** Convert one texture to another. + * + * @param pState The backend. + * @param pCurrentContext The current context, which must be restored before returning. + * @param pSurface The surface which needs conversion. + * @param iMipmap The mipmap level which needs to be converted. + * @param fToRGB True for conversion from the intermediate texture emulated format + * to the RGB format of the actual texture. + * False for conversion from the actual RGB texture to the intermediate texture. + */ +static void doRender(PVMSVGA3DSTATE pState, + PVMSVGA3DCONTEXT pCurrentContext, + PVMSVGA3DSURFACE pSurface, + uint32_t iMipmap, + bool fToRGB) +{ + if (!fToRGB) + { + /** @todo Disable readback transfers for now. They cause crash in glDrawArrays with Mesa 19.2 after + * a previously converted texture is deleted and another texture is being converted. + * Such transfer are useless anyway for the emulated YUV formats and the guest should not need them usually. + */ + return; + } + + LogFunc(("formatConversion: idActiveContext %u, pConv %p, sid=%u, oglid=%u, oglidEmul=%u, mm=%u, %s\n", + pState->idActiveContext, pState->pConv, pSurface->id, pSurface->oglId.texture, pSurface->idEmulated, iMipmap, fToRGB ? "ToRGB" : "FromRGB")); + + PVMSVGA3DFORMATCONVERTER pConv = pState->pConv; + AssertReturnVoid(pConv); + + ShaderProgram *pProgram = NULL; + GLuint sourceTexture = 0; + GLuint targetTexture = 0; + if (fToRGB) + { + if (pSurface->format == SVGA3D_YUY2) + { + pProgram = &pConv->programYUY2ToRGB; + } + else if (pSurface->format == SVGA3D_UYVY) + { + pProgram = &pConv->programUYVYToRGB; + } + sourceTexture = pSurface->idEmulated; + targetTexture = pSurface->oglId.texture; + } + else + { + if (pSurface->format == SVGA3D_YUY2) + { + pProgram = &pConv->programYUY2FromRGB; + } + else if (pSurface->format == SVGA3D_UYVY) + { + pProgram = &pConv->programUYVYFromRGB; + } + sourceTexture = pSurface->oglId.texture; + targetTexture = pSurface->idEmulated; + } + + AssertReturnVoid(pProgram); + + PVMSVGA3DMIPMAPLEVEL pMipmapLevel; + int rc = vmsvga3dMipmapLevel(pSurface, 0, iMipmap, &pMipmapLevel); + AssertRCReturnVoid(rc); + + uint32_t const cWidth = pMipmapLevel->mipmapSize.width; + uint32_t const cHeight = pMipmapLevel->mipmapSize.height; + + /* Use the shared context, where all textures are created. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + setShaderProgram(pState, pProgram, cWidth, cHeight); + + setRenderTarget(pState, targetTexture, iMipmap); + + glViewport(0, 0, cWidth, cHeight); + GL_CHECK_ERROR(); + + glDisable(GL_DEPTH_TEST); + GL_CHECK_ERROR(); + + pState->ext.glActiveTexture(GL_TEXTURE0); + GL_CHECK_ERROR(); + + glBindTexture(GL_TEXTURE_2D, sourceTexture); + GL_CHECK_ERROR(); + + /* Make sure to set the simplest filter. Otherwise the conversion will not work. */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + GL_CHECK_ERROR(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + GL_CHECK_ERROR(); + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pConv->vertexBuffer); + GL_CHECK_ERROR(); + + GLuint index; + for (index = 0; index < RT_ELEMENTS(aVertexAttribs); ++index) + { + pState->ext.glEnableVertexAttribArray(index); + GL_CHECK_ERROR(); + + pState->ext.glVertexAttribPointer(index, aVertexAttribs[index].size, aVertexAttribs[index].type, + aVertexAttribs[index].normalized, aVertexAttribs[index].stride, + (const GLvoid *)(uintptr_t)aVertexAttribs[index].offset); + GL_CHECK_ERROR(); + } + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + GL_CHECK_ERROR(); + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0); + GL_CHECK_ERROR(); + + glBindTexture(GL_TEXTURE_2D, 0); + GL_CHECK_ERROR(); + + unsetRenderTarget(pState, targetTexture); + + pState->ext.glUseProgram(0); + GL_CHECK_ERROR(); + + for (index = 0; index < RT_ELEMENTS(aVertexAttribs); ++index) + { + pState->ext.glDisableVertexAttribArray(index); + GL_CHECK_ERROR(); + } + + /* Restore the current context. */ + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pCurrentContext); +} + +void FormatConvUpdateTexture(PVMSVGA3DSTATE pState, + PVMSVGA3DCONTEXT pCurrentContext, + PVMSVGA3DSURFACE pSurface, + uint32_t iMipmap) +{ + doRender(pState, pCurrentContext, pSurface, iMipmap, true); +} + +void FormatConvReadTexture(PVMSVGA3DSTATE pState, + PVMSVGA3DCONTEXT pCurrentContext, + PVMSVGA3DSURFACE pSurface, + uint32_t iMipmap) +{ + doRender(pState, pCurrentContext, pSurface, iMipmap, false); +} + +void vmsvga3dOnSharedContextDefine(PVMSVGA3DSTATE pState) +{ + /* Use the shared context, where all textures are created. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* + * Format conversion. + */ + Assert(pState->pConv == NULL); + + pState->pConv = (VMSVGA3DFORMATCONVERTER *)RTMemAllocZ(sizeof(VMSVGA3DFORMATCONVERTER)); + AssertReturnVoid(pState->pConv); + + formatConversionInit(pState); +} + +void vmsvga3dOnSharedContextDestroy(PVMSVGA3DSTATE pState) +{ + /* Use the shared context, where all textures are created. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + if (pState->pConv) + { + formatConversionDestroy(pState); + + RTMemFree(pState->pConv); + pState->pConv = NULL; + } +} diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.cpp new file mode 100644 index 00000000..3a0b56e3 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.cpp @@ -0,0 +1,428 @@ +/* $Id: DevVGA-SVGA3d-glLdr.cpp $ */ +/** @file + * DevVGA - VMWare SVGA device - 3D part, dynamic loading of GL function. + */ + +/* + * Copyright (C) 2018-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#define VMSVGA3D_GL_DEFINE_PFN +#include "DevVGA-SVGA3d-glLdr.h" + +#include +#include +#include +#include +#include +#include + +#ifdef RT_OS_WINDOWS +# define OGLGETPROCADDRESS MyWinGetProcAddress +DECLINLINE(PFNRT) MyWinGetProcAddress(const char *pszSymbol) +{ + int rc; + + static RTLDRMOD s_hOpenGL32 = NULL; + if (s_hOpenGL32 == NULL) + { + rc = RTLdrLoadSystem("opengl32", /* fNoUnload = */ true, &s_hOpenGL32); + if (RT_FAILURE(rc)) + s_hOpenGL32 = NULL; + } + + typedef PROC (WINAPI *PFNWGLGETPROCADDRESS)(LPCSTR); + static PFNWGLGETPROCADDRESS s_wglGetProcAddress = NULL; + if (s_wglGetProcAddress == NULL) + { + if (s_hOpenGL32 != NULL) + { + rc = RTLdrGetSymbol(s_hOpenGL32, "wglGetProcAddress", (void **)&s_wglGetProcAddress); + if (RT_FAILURE(rc)) + s_wglGetProcAddress = NULL; + } + } + + if (s_wglGetProcAddress) + { + /* Khronos: [on failure] "some implementations will return other values. 1, 2, and 3 are used, as well as -1". */ + PFNRT p = (PFNRT)s_wglGetProcAddress(pszSymbol); + if (RT_VALID_PTR(p)) + return p; + + /* Might be an exported symbol. */ + rc = RTLdrGetSymbol(s_hOpenGL32, pszSymbol, (void **)&p); + if (RT_SUCCESS(rc)) + return p; + } + + return 0; +} + +#elif defined(RT_OS_DARWIN) +# include +# define OGLGETPROCADDRESS MyNSGLGetProcAddress +/** Resolves an OpenGL symbol. */ +static void *MyNSGLGetProcAddress(const char *pszSymbol) +{ + /* Another copy in shaderapi.c. */ + static void *s_pvImage = NULL; + if (s_pvImage == NULL) + s_pvImage = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); + return s_pvImage ? dlsym(s_pvImage, pszSymbol) : NULL; +} + +#else +# define OGLGETPROCADDRESS MyGLXGetProcAddress +static PFNRT MyGLXGetProcAddress(const char *pszSymbol) +{ + int rc; + + static RTLDRMOD s_hGL = NULL; + if (s_hGL == NULL) + { + static const char s_szLibGL[] = "libGL.so.1"; + rc = RTLdrLoadEx(s_szLibGL, &s_hGL, RTLDRLOAD_FLAGS_GLOBAL | RTLDRLOAD_FLAGS_NO_UNLOAD, NULL); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: failed to load %s: %Rrc\n", s_szLibGL, rc)); + s_hGL = NULL; + return NULL; + } + } + + typedef PFNRT (* PFNGLXGETPROCADDRESS)(const GLubyte * procName); + static PFNGLXGETPROCADDRESS s_glXGetProcAddress = NULL; + if (s_glXGetProcAddress == NULL) + { + rc = RTLdrGetSymbol(s_hGL, "glXGetProcAddress", (void **)&s_glXGetProcAddress); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: failed to get glXGetProcAddress: %Rrc\n", rc)); + s_glXGetProcAddress = NULL; + return NULL; + } + } + + PFNRT p = s_glXGetProcAddress((const GLubyte *)pszSymbol); + if (RT_VALID_PTR(p)) + return p; + + /* Might be an exported symbol. */ + rc = RTLdrGetSymbol(s_hGL, pszSymbol, (void **)&p); + if (RT_SUCCESS(rc)) + return p; + + return NULL; +} + +static PFNRT MyX11GetProcAddress(const char *pszSymbol) +{ + int rc; + + static RTLDRMOD s_hX11 = NULL; + if (s_hX11 == NULL) + { + static const char s_szLibX11[] = "libX11.so.6"; + rc = RTLdrLoadEx(s_szLibX11, &s_hX11, RTLDRLOAD_FLAGS_LOCAL | RTLDRLOAD_FLAGS_NO_UNLOAD, NULL); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: failed to load %s: %Rrc\n", s_szLibX11, rc)); + s_hX11 = NULL; + return NULL; + } + } + + PFNRT p = NULL; + rc = RTLdrGetSymbol(s_hX11, pszSymbol, (void **)&p); + if (RT_SUCCESS(rc)) + return p; + + return NULL; +} + +#define X11GETPROC_(ProcName) do { \ + *(PFNRT *)&pfn_##ProcName = pfnRet = MyX11GetProcAddress(#ProcName); \ + if (pfnRet) { /* likely */ } \ + else \ + { \ + AssertLogRelMsg(pfnRet, ("%s missing\n", #ProcName)); \ + return PDMDevHlpVMSetError(pDevIns, VERR_VGA_GL_SYMBOL_NOT_FOUND, RT_SRC_POS, \ + "Missing libX11 symbol '%s'\n", #ProcName); \ + } \ +} while(0) +#endif + +#define GLGETPROC_(ProcName, NameSuffix) do { \ + *(PFNRT *)&pfn_##ProcName = pfnRet = OGLGETPROCADDRESS(#ProcName NameSuffix); \ + if (pfnRet) { /* likely */ } \ + else \ + { \ + AssertLogRelMsg(pfnRet, ("%s missing\n", #ProcName NameSuffix)); \ + return PDMDevHlpVMSetError(pDevIns, VERR_VGA_GL_SYMBOL_NOT_FOUND, RT_SRC_POS, \ + "Missing OpenGL symbol '%s'\n", #ProcName NameSuffix); \ + } \ +} while(0) + +int glLdrInit(PPDMDEVINS pDevIns) +{ + /** @todo r=bird: Perhaps make this template include file driven? See + * include/VBox/dbus.h, include/VBox/dbus-calls.h and iprt/runtime-loader.h for + * instance. Regardless, it would be would be nice if we could move up the + * RTLdrLoadSystem/dlopen bits and have separate error reporting for those, + * making use of VERR_VGA_GL_LOAD_FAILURE. I can look into that, but + * probably only after the release is out... */ + +#ifdef RT_OS_WINDOWS + pfn_wglCreateContext = 0; + pfn_wglDeleteContext = 0; + pfn_wglMakeCurrent = 0; + pfn_wglShareLists = 0; +#elif defined(RT_OS_LINUX) + pfn_XConfigureWindow = 0; + pfn_XCloseDisplay = 0; + pfn_XCreateColormap = 0; + pfn_XCreatePixmap = 0; + pfn_XCreateWindow = 0; + pfn_XDefaultRootWindow = 0; + pfn_XDestroyWindow = 0; + pfn_XFree = 0; + pfn_XFreePixmap = 0; + pfn_XInitThreads = 0; + pfn_XNextEvent = 0; + pfn_XOpenDisplay = 0; + pfn_XPending = 0; + pfn_XSetErrorHandler = 0; + pfn_XSync = 0; + pfn_XScreenNumberOfScreen = 0; + pfn_XMapWindow = 0; + pfn_XGetWindowAttributes = 0; + pfn_glXGetFBConfigAttrib = 0; + pfn_glXGetVisualFromFBConfig = 0; + pfn_glXQueryVersion = 0; + pfn_glXChooseFBConfig = 0; + pfn_glXChooseVisual = 0; + pfn_glXCreateContext = 0; + pfn_glXCreatePixmap = 0; + pfn_glXMakeCurrent = 0; + pfn_glXDestroyContext = 0; + pfn_glXDestroyPixmap = 0; +#endif + pfn_glAlphaFunc = 0; + pfn_glBegin = 0; + pfn_glBindTexture = 0; + pfn_glBlendColor = 0; + pfn_glBlendEquation = 0; + pfn_glBlendFunc = 0; + pfn_glClear = 0; + pfn_glClearColor = 0; + pfn_glClearDepth = 0; + pfn_glClearStencil = 0; + pfn_glClientActiveTexture = 0; + pfn_glClipPlane = 0; + pfn_glColorMask = 0; + pfn_glColorPointer = 0; + pfn_glCullFace = 0; + pfn_glDeleteTextures = 0; + pfn_glDepthFunc = 0; + pfn_glDepthMask = 0; + pfn_glDepthRange = 0; + pfn_glDisable = 0; + pfn_glDisableClientState = 0; + pfn_glDrawArrays = 0; + pfn_glDrawElements = 0; + pfn_glEnable = 0; + pfn_glEnableClientState = 0; + pfn_glEnd = 0; + pfn_glFinish = 0; + pfn_glFlush = 0; + pfn_glFogf = 0; + pfn_glFogfv = 0; + pfn_glFogi = 0; + pfn_glFrontFace = 0; + pfn_glGenTextures = 0; + pfn_glGetBooleanv = 0; + pfn_glGetError = 0; + pfn_glGetFloatv = 0; + pfn_glGetIntegerv = 0; + pfn_glGetString = 0; + pfn_glGetTexImage = 0; + pfn_glLightModelfv = 0; + pfn_glLightf = 0; + pfn_glLightfv = 0; + pfn_glLineWidth = 0; + pfn_glLoadIdentity = 0; + pfn_glLoadMatrixf = 0; + pfn_glMaterialfv = 0; + pfn_glMatrixMode = 0; + pfn_glMultMatrixf = 0; + pfn_glNormalPointer = 0; + pfn_glOrtho = 0; + pfn_glPixelStorei = 0; + pfn_glPointSize = 0; + pfn_glPolygonMode = 0; + pfn_glPolygonOffset = 0; + pfn_glPopAttrib = 0; + pfn_glPopMatrix = 0; + pfn_glPushAttrib = 0; + pfn_glPushMatrix = 0; + pfn_glScissor = 0; + pfn_glShadeModel = 0; + pfn_glStencilFunc = 0; + pfn_glStencilMask = 0; + pfn_glStencilOp = 0; + pfn_glTexCoord2f = 0; + pfn_glTexCoordPointer = 0; + pfn_glTexImage2D = 0; + pfn_glTexParameterf = 0; + pfn_glTexParameterfv = 0; + pfn_glTexParameteri = 0; + pfn_glTexSubImage2D = 0; + pfn_glVertex2i = 0; + pfn_glVertexPointer = 0; + pfn_glViewport = 0; + + PFNRT pfnRet; +#ifdef RT_OS_WINDOWS + GLGETPROC_(wglCreateContext, ""); + GLGETPROC_(wglDeleteContext, ""); + GLGETPROC_(wglMakeCurrent, ""); + GLGETPROC_(wglShareLists, ""); +#elif defined(RT_OS_LINUX) + X11GETPROC_(XConfigureWindow); + X11GETPROC_(XCloseDisplay); + X11GETPROC_(XCreateColormap); + X11GETPROC_(XCreatePixmap); + X11GETPROC_(XCreateWindow); + X11GETPROC_(XDefaultRootWindow); + X11GETPROC_(XDestroyWindow); + X11GETPROC_(XFree); + X11GETPROC_(XFreePixmap); + X11GETPROC_(XInitThreads); + X11GETPROC_(XNextEvent); + X11GETPROC_(XOpenDisplay); + X11GETPROC_(XPending); + X11GETPROC_(XSetErrorHandler); + X11GETPROC_(XSync); + X11GETPROC_(XScreenNumberOfScreen); + X11GETPROC_(XMapWindow); + X11GETPROC_(XGetWindowAttributes); + GLGETPROC_(glXGetFBConfigAttrib, ""); + GLGETPROC_(glXGetVisualFromFBConfig, ""); + GLGETPROC_(glXQueryVersion, ""); + GLGETPROC_(glXChooseFBConfig, ""); + GLGETPROC_(glXChooseVisual, ""); + GLGETPROC_(glXCreateContext, ""); + GLGETPROC_(glXCreatePixmap, ""); + GLGETPROC_(glXMakeCurrent, ""); + GLGETPROC_(glXDestroyContext, ""); + GLGETPROC_(glXDestroyPixmap, ""); +#endif + GLGETPROC_(glAlphaFunc, ""); + GLGETPROC_(glBegin, ""); + GLGETPROC_(glBindTexture, ""); + GLGETPROC_(glBlendFunc, ""); + GLGETPROC_(glClear, ""); + GLGETPROC_(glClearColor, ""); + GLGETPROC_(glClearDepth, ""); + GLGETPROC_(glClearStencil, ""); + GLGETPROC_(glClipPlane, ""); + GLGETPROC_(glColorMask, ""); + GLGETPROC_(glColorPointer, ""); + GLGETPROC_(glCullFace, ""); + GLGETPROC_(glDeleteTextures, ""); + GLGETPROC_(glDepthFunc, ""); + GLGETPROC_(glDepthMask, ""); + GLGETPROC_(glDepthRange, ""); + GLGETPROC_(glDisable, ""); + GLGETPROC_(glDisableClientState, ""); + GLGETPROC_(glDrawArrays, ""); + GLGETPROC_(glDrawElements, ""); + GLGETPROC_(glEnable, ""); + GLGETPROC_(glEnableClientState, ""); + GLGETPROC_(glEnd, ""); + GLGETPROC_(glFinish, ""); + GLGETPROC_(glFlush, ""); + GLGETPROC_(glFogf, ""); + GLGETPROC_(glFogfv, ""); + GLGETPROC_(glFogi, ""); + GLGETPROC_(glFrontFace, ""); + GLGETPROC_(glGenTextures, ""); + GLGETPROC_(glGetBooleanv, ""); + GLGETPROC_(glGetError, ""); + GLGETPROC_(glGetFloatv, ""); + GLGETPROC_(glGetIntegerv, ""); + GLGETPROC_(glGetString, ""); + GLGETPROC_(glGetTexImage, ""); + GLGETPROC_(glLightModelfv, ""); + GLGETPROC_(glLightf, ""); + GLGETPROC_(glLightfv, ""); + GLGETPROC_(glLineWidth, ""); + GLGETPROC_(glLoadIdentity, ""); + GLGETPROC_(glLoadMatrixf, ""); + GLGETPROC_(glMaterialfv, ""); + GLGETPROC_(glMatrixMode, ""); + GLGETPROC_(glMultMatrixf, ""); + GLGETPROC_(glNormalPointer, ""); + GLGETPROC_(glOrtho, ""); + GLGETPROC_(glPixelStorei, ""); + GLGETPROC_(glPointSize, ""); + GLGETPROC_(glPolygonMode, ""); + GLGETPROC_(glPolygonOffset, ""); + GLGETPROC_(glPopAttrib, ""); + GLGETPROC_(glPopMatrix, ""); + GLGETPROC_(glPushAttrib, ""); + GLGETPROC_(glPushMatrix, ""); + GLGETPROC_(glScissor, ""); + GLGETPROC_(glShadeModel, ""); + GLGETPROC_(glStencilFunc, ""); + GLGETPROC_(glStencilMask, ""); + GLGETPROC_(glStencilOp, ""); + GLGETPROC_(glTexCoord2f, ""); + GLGETPROC_(glTexCoordPointer, ""); + GLGETPROC_(glTexImage2D, ""); + GLGETPROC_(glTexParameterf, ""); + GLGETPROC_(glTexParameterfv, ""); + GLGETPROC_(glTexParameteri, ""); + GLGETPROC_(glTexSubImage2D, ""); + GLGETPROC_(glVertex2i, ""); + GLGETPROC_(glVertexPointer, ""); + GLGETPROC_(glViewport, ""); + +#ifdef RT_OS_LINUX + XInitThreads(); +#endif + return VINF_SUCCESS; +} + +PFNRT glLdrGetProcAddress(const char *pszSymbol) +{ + return OGLGETPROCADDRESS(pszSymbol); +} + +int glLdrGetExtFunctions(PPDMDEVINS pDevIns) +{ + PFNRT pfnRet; + GLGETPROC_(glBlendColor, ""); + GLGETPROC_(glBlendEquation, ""); + GLGETPROC_(glClientActiveTexture, ""); + return VINF_SUCCESS; +} diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.h b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.h new file mode 100644 index 00000000..6deb9cb2 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-glLdr.h @@ -0,0 +1,443 @@ +/* $Id: DevVGA-SVGA3d-glLdr.h $ */ +/** @file + * DevVGA - VMWare SVGA device - 3D part, dynamic loading of GL function. + */ + +/* + * Copyright (C) 2018-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_glLdr_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_glLdr_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifndef VMSVGA3D_OPENGL +# error "This include file is for VMSVGA3D_OPENGL." +#endif + +#include + +/** @todo VBOX_VMSVGA3D_GL_HACK_LEVEL is not necessary when dynamic loading is used. */ + +#ifdef RT_OS_WINDOWS +# include +# include +# include "vmsvga_glext/wglext.h" + +#elif defined(RT_OS_DARWIN) +# include +# include +# include +# define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED +# include +# include "DevVGA-SVGA3d-cocoa.h" +// HACK +typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); +# define GL_RGBA_S3TC 0x83A2 +# define GL_ALPHA8_EXT 0x803c +# define GL_LUMINANCE8_EXT 0x8040 +# define GL_LUMINANCE16_EXT 0x8042 +# define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +# define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +# define GL_INT_2_10_10_10_REV 0x8D9F + +#else +# include +# include +# include +# include +# define VBOX_VMSVGA3D_GL_HACK_LEVEL 0x103 +#endif + +#ifndef __glext_h__ +# undef GL_GLEXT_VERSION /** @todo r=bird: We include GL/glext.h above which also defines this and we'll end up with + * a clash if the system one does not use the same header guard as ours. So, I'm wondering + * whether this include is really needed, and if it is, whether we should use a unique header + * guard macro on it, so we'll have the same problems everywhere... */ +#endif +#include "vmsvga_glext/glext.h" + + +#ifdef RT_OS_WINDOWS +# define GLAPIENTRY APIENTRY +#else +# define GLAPIENTRY +#endif + +#define GLAPIENTRYP GLAPIENTRY * + +#ifdef VMSVGA3D_GL_DEFINE_PFN +# define GLPFN +#else +# define GLPFN extern +#endif + +/** Load OpenGL library and initialize function pointers. */ +int glLdrInit(PPDMDEVINS pDevIns); +/** Resolve an OpenGL function name. */ +PFNRT glLdrGetProcAddress(const char *pszSymbol); +/** Get pointers to extension function. They are available on Windows only when OpenGL context is set. */ +int glLdrGetExtFunctions(PPDMDEVINS pDevIns); + +/* + * All OpenGL function used by VMSVGA backend. + */ + +/* + * GL 1.1 functions (exported from OpenGL32 on Windows). + */ +GLPFN void (GLAPIENTRYP pfn_glAlphaFunc)(GLenum func, GLclampf ref); +#define glAlphaFunc pfn_glAlphaFunc + +GLPFN void (GLAPIENTRYP pfn_glBegin)(GLenum mode); +#define glBegin pfn_glBegin + +GLPFN void (GLAPIENTRYP pfn_glBindTexture)(GLenum target, GLuint texture); +#define glBindTexture pfn_glBindTexture + +GLPFN void (GLAPIENTRYP pfn_glBlendFunc)(GLenum sfactor, GLenum dfactor); +#define glBlendFunc pfn_glBlendFunc + +GLPFN void (GLAPIENTRYP pfn_glClear)(GLbitfield mask); +#define glClear pfn_glClear + +GLPFN void (GLAPIENTRYP pfn_glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +#define glClearColor pfn_glClearColor + +GLPFN void (GLAPIENTRYP pfn_glClearDepth)(GLclampd depth); +#define glClearDepth pfn_glClearDepth + +GLPFN void (GLAPIENTRYP pfn_glClearStencil)(GLint s); +#define glClearStencil pfn_glClearStencil + +GLPFN void (GLAPIENTRYP pfn_glClipPlane)(GLenum plane, const GLdouble *equation); +#define glClipPlane pfn_glClipPlane + +GLPFN void (GLAPIENTRYP pfn_glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +#define glColorMask pfn_glColorMask + +GLPFN void (GLAPIENTRYP pfn_glColorPointer)(GLint size, GLenum type, GLsizei stride, const void *pointer); +#define glColorPointer pfn_glColorPointer + +GLPFN void (GLAPIENTRYP pfn_glCullFace)(GLenum mode); +#define glCullFace pfn_glCullFace + +GLPFN void (GLAPIENTRYP pfn_glDeleteTextures)(GLsizei n, const GLuint *textures); +#define glDeleteTextures pfn_glDeleteTextures + +GLPFN void (GLAPIENTRYP pfn_glDepthFunc)(GLenum func); +#define glDepthFunc pfn_glDepthFunc + +GLPFN void (GLAPIENTRYP pfn_glDepthMask)(GLboolean flag); +#define glDepthMask pfn_glDepthMask + +GLPFN void (GLAPIENTRYP pfn_glDepthRange)(GLclampd zNear, GLclampd zFar); +#define glDepthRange pfn_glDepthRange + +GLPFN void (GLAPIENTRYP pfn_glDisable)(GLenum cap); +#define glDisable pfn_glDisable + +GLPFN void (GLAPIENTRYP pfn_glDisableClientState)(GLenum array); +#define glDisableClientState pfn_glDisableClientState + +GLPFN void (GLAPIENTRYP pfn_glDrawArrays)(GLenum mode, GLint first, GLsizei count); +#define glDrawArrays pfn_glDrawArrays + +GLPFN void (GLAPIENTRYP pfn_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void *indices); +#define glDrawElements pfn_glDrawElements + +GLPFN void (GLAPIENTRYP pfn_glEnable)(GLenum cap); +#define glEnable pfn_glEnable + +GLPFN void (GLAPIENTRYP pfn_glEnableClientState)(GLenum array); +#define glEnableClientState pfn_glEnableClientState + +GLPFN void (GLAPIENTRYP pfn_glEnd)(void); +#define glEnd pfn_glEnd + +GLPFN void (GLAPIENTRYP pfn_glFinish)(void); +#define glFinish pfn_glFinish + +GLPFN void (GLAPIENTRYP pfn_glFlush)(void); +#define glFlush pfn_glFlush + +GLPFN void (GLAPIENTRYP pfn_glFogf)(GLenum pname, GLfloat param); +#define glFogf pfn_glFogf + +GLPFN void (GLAPIENTRYP pfn_glFogfv)(GLenum pname, const GLfloat *params); +#define glFogfv pfn_glFogfv + +GLPFN void (GLAPIENTRYP pfn_glFogi)(GLenum pname, GLint param); +#define glFogi pfn_glFogi + +GLPFN void (GLAPIENTRYP pfn_glFrontFace)(GLenum mode); +#define glFrontFace pfn_glFrontFace + +GLPFN void (GLAPIENTRYP pfn_glGenTextures)(GLsizei n, GLuint *textures); +#define glGenTextures pfn_glGenTextures + +GLPFN void (GLAPIENTRYP pfn_glGetBooleanv)(GLenum pname, GLboolean *params); +#define glGetBooleanv pfn_glGetBooleanv + +GLPFN GLenum (GLAPIENTRYP pfn_glGetError)(void); +#define glGetError pfn_glGetError + +GLPFN void (GLAPIENTRYP pfn_glGetFloatv)(GLenum pname, GLfloat *params); +#define glGetFloatv pfn_glGetFloatv + +GLPFN void (GLAPIENTRYP pfn_glGetIntegerv)(GLenum pname, GLint *params); +#define glGetIntegerv pfn_glGetIntegerv + +GLPFN const GLubyte * (GLAPIENTRYP pfn_glGetString)(GLenum name); +#define glGetString pfn_glGetString + +GLPFN void (GLAPIENTRYP pfn_glGetTexImage)(GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +#define glGetTexImage pfn_glGetTexImage + +GLPFN void (GLAPIENTRYP pfn_glLightModelfv)(GLenum pname, const GLfloat *params); +#define glLightModelfv pfn_glLightModelfv + +GLPFN void (GLAPIENTRYP pfn_glLightf)(GLenum light, GLenum pname, GLfloat param); +#define glLightf pfn_glLightf + +GLPFN void (GLAPIENTRYP pfn_glLightfv)(GLenum light, GLenum pname, const GLfloat *params); +#define glLightfv pfn_glLightfv + +GLPFN void (GLAPIENTRYP pfn_glLineWidth)(GLfloat width); +#define glLineWidth pfn_glLineWidth + +GLPFN void (GLAPIENTRYP pfn_glLoadIdentity)(void); +#define glLoadIdentity pfn_glLoadIdentity + +GLPFN void (GLAPIENTRYP pfn_glLoadMatrixf)(const GLfloat *m); +#define glLoadMatrixf pfn_glLoadMatrixf + +GLPFN void (GLAPIENTRYP pfn_glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params); +#define glMaterialfv pfn_glMaterialfv + +GLPFN void (GLAPIENTRYP pfn_glMatrixMode)(GLenum mode); +#define glMatrixMode pfn_glMatrixMode + +GLPFN void (GLAPIENTRYP pfn_glMultMatrixf)(const GLfloat *m); +#define glMultMatrixf pfn_glMultMatrixf + +GLPFN void (GLAPIENTRYP pfn_glNormalPointer)(GLenum type, GLsizei stride, const void *pointer); +#define glNormalPointer pfn_glNormalPointer + +GLPFN void (GLAPIENTRYP pfn_glOrtho)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal); +#define glOrtho pfn_glOrtho + +GLPFN void (GLAPIENTRYP pfn_glPixelStorei)(GLenum pname, GLint param); +#define glPixelStorei pfn_glPixelStorei + +GLPFN void (GLAPIENTRYP pfn_glPointSize)(GLfloat size); +#define glPointSize pfn_glPointSize + +GLPFN void (GLAPIENTRYP pfn_glPolygonMode)(GLenum face, GLenum mode); +#define glPolygonMode pfn_glPolygonMode + +GLPFN void (GLAPIENTRYP pfn_glPolygonOffset)(GLfloat factor, GLfloat units); +#define glPolygonOffset pfn_glPolygonOffset + +GLPFN void (GLAPIENTRYP pfn_glPopAttrib)(void); +#define glPopAttrib pfn_glPopAttrib + +GLPFN void (GLAPIENTRYP pfn_glPopMatrix)(void); +#define glPopMatrix pfn_glPopMatrix + +GLPFN void (GLAPIENTRYP pfn_glPushAttrib)(GLbitfield mask); +#define glPushAttrib pfn_glPushAttrib + +GLPFN void (GLAPIENTRYP pfn_glPushMatrix)(void); +#define glPushMatrix pfn_glPushMatrix + +GLPFN void (GLAPIENTRYP pfn_glScissor)(GLint x, GLint y, GLsizei width, GLsizei height); +#define glScissor pfn_glScissor + +GLPFN void (GLAPIENTRYP pfn_glShadeModel)(GLenum mode); +#define glShadeModel pfn_glShadeModel + +GLPFN void (GLAPIENTRYP pfn_glStencilFunc)(GLenum func, GLint ref, GLuint mask); +#define glStencilFunc pfn_glStencilFunc + +GLPFN void (GLAPIENTRYP pfn_glStencilMask)(GLuint mask); +#define glStencilMask pfn_glStencilMask + +GLPFN void (GLAPIENTRYP pfn_glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass); +#define glStencilOp pfn_glStencilOp + +GLPFN void (GLAPIENTRYP pfn_glTexCoord2f)(GLfloat s, GLfloat t); +#define glTexCoord2f pfn_glTexCoord2f + +GLPFN void (GLAPIENTRYP pfn_glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const void *pointer); +#define glTexCoordPointer pfn_glTexCoordPointer + +GLPFN void (GLAPIENTRYP pfn_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +#define glTexImage2D pfn_glTexImage2D + +GLPFN void (GLAPIENTRYP pfn_glTexParameterf)(GLenum target, GLenum pname, GLfloat param); +#define glTexParameterf pfn_glTexParameterf + +GLPFN void (GLAPIENTRYP pfn_glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params); +#define glTexParameterfv pfn_glTexParameterfv + +GLPFN void (GLAPIENTRYP pfn_glTexParameteri)(GLenum target, GLenum pname, GLint param); +#define glTexParameteri pfn_glTexParameteri + +GLPFN void (GLAPIENTRYP pfn_glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +#define glTexSubImage2D pfn_glTexSubImage2D + +GLPFN void (GLAPIENTRYP pfn_glVertex2i)(GLint x, GLint y); +#define glVertex2i pfn_glVertex2i + +GLPFN void (GLAPIENTRYP pfn_glVertexPointer)(GLint size, GLenum type, GLsizei stride, const void *pointer); +#define glVertexPointer pfn_glVertexPointer + +GLPFN void (GLAPIENTRYP pfn_glViewport)(GLint x, GLint y, GLsizei width, GLsizei height); +#define glViewport pfn_glViewport + +/* + * Extension functions (not exported from OpenGL32 on Windows). + */ +GLPFN void (GLAPIENTRYP pfn_glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +#define glBlendColor pfn_glBlendColor + +GLPFN void (GLAPIENTRYP pfn_glBlendEquation)(GLenum mode); +#define glBlendEquation pfn_glBlendEquation + +GLPFN void (GLAPIENTRYP pfn_glClientActiveTexture)(GLenum texture); +#define glClientActiveTexture pfn_glClientActiveTexture + +#ifdef RT_OS_WINDOWS +/* + * WGL. + */ +GLPFN HGLRC (WINAPI *pfn_wglCreateContext)(HDC); +#define wglCreateContext pfn_wglCreateContext + +GLPFN BOOL (WINAPI *pfn_wglDeleteContext)(HGLRC); +#define wglDeleteContext pfn_wglDeleteContext + +GLPFN BOOL (WINAPI *pfn_wglMakeCurrent)(HDC, HGLRC); +#define wglMakeCurrent pfn_wglMakeCurrent + +GLPFN BOOL (WINAPI *pfn_wglShareLists)(HGLRC, HGLRC); +#define wglShareLists pfn_wglShareLists + +#elif defined(RT_OS_LINUX) +/* + * GLX + */ +GLPFN int (* pfn_glXGetFBConfigAttrib)(Display * dpy, GLXFBConfig config, int attribute, int * value); +#define glXGetFBConfigAttrib pfn_glXGetFBConfigAttrib + +GLPFN XVisualInfo * (* pfn_glXGetVisualFromFBConfig)(Display * dpy, GLXFBConfig config); +#define glXGetVisualFromFBConfig pfn_glXGetVisualFromFBConfig + +GLPFN Bool (* pfn_glXQueryVersion)(Display * dpy, int * major, int * minor); +#define glXQueryVersion pfn_glXQueryVersion + +GLPFN GLXFBConfig * (* pfn_glXChooseFBConfig)(Display * dpy, int screen, const int * attrib_list, int * nelements); +#define glXChooseFBConfig pfn_glXChooseFBConfig + +GLPFN XVisualInfo* (* pfn_glXChooseVisual)(Display * dpy, int screen, int * attribList); +#define glXChooseVisual pfn_glXChooseVisual + +GLPFN GLXContext (* pfn_glXCreateContext)(Display * dpy, XVisualInfo * vis, GLXContext shareList, Bool direct); +#define glXCreateContext pfn_glXCreateContext + +GLPFN GLXPixmap (* pfn_glXCreatePixmap)(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list); +#define glXCreatePixmap pfn_glXCreatePixmap + +GLPFN Bool (* pfn_glXMakeCurrent)(Display * dpy, GLXDrawable drawable, GLXContext ctx); +#define glXMakeCurrent pfn_glXMakeCurrent + +GLPFN void (* pfn_glXDestroyContext)(Display * dpy, GLXContext ctx); +#define glXDestroyContext pfn_glXDestroyContext + +GLPFN void (* pfn_glXDestroyPixmap)(Display * dpy, GLXPixmap Pixmap); +#define glXDestroyPixmap pfn_glXDestroyPixmap + +/* + * X11 + */ +GLPFN int (* pfn_XConfigureWindow)(Display *display, Window w, unsigned value_mask, XWindowChanges *changes); +#define XConfigureWindow pfn_XConfigureWindow + +GLPFN int (* pfn_XCloseDisplay)(Display *display); +#define XCloseDisplay pfn_XCloseDisplay + +GLPFN Colormap (* pfn_XCreateColormap)(Display *display, Window w, Visual *visual, int alloc); +#define XCreateColormap pfn_XCreateColormap + +GLPFN Pixmap (* pfn_XCreatePixmap)(Display *display, Drawable d, unsigned int width, unsigned int height, unsigned int depth); +#define XCreatePixmap pfn_XCreatePixmap + +GLPFN Window (* pfn_XCreateWindow)(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, + unsigned int border_width, int depth, unsigned int window_class, Visual *visual, unsigned long valuemask, XSetWindowAttributes *attributes); +#define XCreateWindow pfn_XCreateWindow + +GLPFN Window (* pfn_XDefaultRootWindow)(Display *display); +#define XDefaultRootWindow pfn_XDefaultRootWindow + +GLPFN int (* pfn_XDestroyWindow)(Display *display, Window w); +#define XDestroyWindow pfn_XDestroyWindow + +GLPFN int (* pfn_XFree)(void *data); +#define XFree pfn_XFree + +GLPFN int (* pfn_XFreePixmap)(Display *display, Pixmap pixmap); +#define XFreePixmap pfn_XFreePixmap + +GLPFN Status (* pfn_XInitThreads)(void); +#define XInitThreads pfn_XInitThreads + +GLPFN int (* pfn_XNextEvent)(Display *display, XEvent *event_return); +#define XNextEvent pfn_XNextEvent + +GLPFN Display *(* pfn_XOpenDisplay)(char *display_name); +#define XOpenDisplay pfn_XOpenDisplay + +GLPFN int (* pfn_XPending)(Display *display); +#define XPending pfn_XPending + +GLPFN int (* (* pfn_XSetErrorHandler)(int (*handler)(Display *, XErrorEvent *)))(Display *, XErrorEvent *); +#define XSetErrorHandler pfn_XSetErrorHandler + +GLPFN int (* pfn_XSync)(Display *display, Bool discard); +#define XSync pfn_XSync + +GLPFN int (* pfn_XScreenNumberOfScreen)(Screen *screen); +#define XScreenNumberOfScreen pfn_XScreenNumberOfScreen + +GLPFN int (* pfn_XMapWindow)(Display *display, Window w); +#define XMapWindow pfn_XMapWindow + +GLPFN Status (* pfn_XGetWindowAttributes)(Display *display, Window w, XWindowAttributes *window_attributes_return); +#define XGetWindowAttributes pfn_XGetWindowAttributes + +#endif + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_glLdr_h */ diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-hlp.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-hlp.cpp new file mode 100644 index 00000000..0a74af98 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-hlp.cpp @@ -0,0 +1,466 @@ +/* $Id: DevVGA-SVGA3d-hlp.cpp $ */ +/** @file + * DevVMWare - VMWare SVGA device helpers + */ + +/* + * Copyright (C) 2020-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include + +#ifdef SHADER_VERIFY_STANDALONE +# include +//# define Log3(a) printf a - /** @todo r=bird: This is strictly forbidden. Noone redefines Log macros ever! */ +//# define LogRel(a) printf a - /** @todo r=bird: This is strictly forbidden. Noone redefines Log macros ever! */ +#else +# include +#endif + +#include +#include +#include +#include + +#include "DevVGA-SVGA.h" + +/** Per shader data is stored in this structure. */ +typedef struct VMSVGA3DSHADERPARSECONTEXT +{ + /** Version token. */ + SVGA3dShaderVersion version; + + SVGA3dShaderOpCodeType currentOpcode; + union + { + SVGA3DOpDclArgs *pDclArgs; + } u; +} VMSVGA3DSHADERPARSECONTEXT; + +/** Callback which parses a parameter token. + * + * @param pCtx The shader data. + * @param Op Instruction opcode which the token is used with. + * @param Token The parameter token which must be parsed. + * @param idxToken Index of the parameter token in the instruction. 0 for the first parameter. + * + * @return VBox error code. + */ +typedef int FNSHADERPARSETOKEN(VMSVGA3DSHADERPARSECONTEXT* pCtx, uint32_t Op, uint32_t Token, uint32_t idxToken); +typedef FNSHADERPARSETOKEN* PFNSHADERPARSETOKEN; + +/** Information about a shader opcode. */ +typedef struct VMSVGA3DSHADERPARSEOP +{ + /** Opcode. */ + SVGA3dShaderOpCodeType Op; + /** Maximum number of parameters. */ + uint32_t Length; + /** Pointer to callback, which parse each parameter. + * The size is the number of maximum possible parameters: dest + 3 * src + */ + PFNSHADERPARSETOKEN apfnParse[4]; +} VMSVGA3DSHADERPARSEOP; + +static int vmsvga3dShaderParseRegOffset(VMSVGA3DSHADERPARSECONTEXT *pCtx, + bool fIsSrc, + SVGA3dShaderRegType regType, + uint32_t off) +{ + RT_NOREF(pCtx, fIsSrc); + + switch (regType) + { + case SVGA3DREG_TEMP: + break; + case SVGA3DREG_INPUT: + break; + case SVGA3DREG_CONST: + break; + case SVGA3DREG_ADDR /* also SVGA3DREG_TEXTURE */: + break; + case SVGA3DREG_RASTOUT: + break; + case SVGA3DREG_ATTROUT: + break; + case SVGA3DREG_TEXCRDOUT /* also SVGA3DREG_OUTPUT */: + break; + case SVGA3DREG_CONSTINT: + break; + case SVGA3DREG_COLOROUT: + break; + case SVGA3DREG_DEPTHOUT: + break; + case SVGA3DREG_SAMPLER: + break; + case SVGA3DREG_CONST2: + break; + case SVGA3DREG_CONST3: + break; + case SVGA3DREG_CONST4: + break; + case SVGA3DREG_CONSTBOOL: + break; + case SVGA3DREG_LOOP: + break; + case SVGA3DREG_TEMPFLOAT16: + break; + case SVGA3DREG_MISCTYPE: + ASSERT_GUEST_RETURN( off == SVGA3DMISCREG_POSITION + || off == SVGA3DMISCREG_FACE, VERR_PARSE_ERROR); + break; + case SVGA3DREG_LABEL: + break; + case SVGA3DREG_PREDICATE: + break; + default: + ASSERT_GUEST_FAILED_RETURN(VERR_PARSE_ERROR); + } + + return VINF_SUCCESS; +} + +/* Parse a declaration parameter token: + * https://docs.microsoft.com/en-us/windows-hardware/drivers/display/dcl-instruction + * + * See FNSHADERPARSETOKEN. + */ +static int vmsvga3dShaderParseDclToken(VMSVGA3DSHADERPARSECONTEXT* pCtx, uint32_t Op, uint32_t Token, uint32_t idxToken) +{ + RT_NOREF(pCtx, Op, Token, idxToken); + return VINF_SUCCESS; +} + +/* Parse a label (D3DSPR_LABEL) parameter token. + * + * See FNSHADERPARSETOKEN. + */ +static int vmsvga3dShaderParseLabelToken(VMSVGA3DSHADERPARSECONTEXT* pCtx, uint32_t Op, uint32_t Token, uint32_t idxToken) +{ + RT_NOREF(pCtx, Op, Token, idxToken); + return VINF_SUCCESS; +} + +/* Parse a destination parameter token: + * https://docs.microsoft.com/en-us/windows-hardware/drivers/display/destination-parameter-token + * See FNSHADERPARSETOKEN. + */ +static int vmsvga3dShaderParseDestToken(VMSVGA3DSHADERPARSECONTEXT* pCtx, uint32_t Op, uint32_t Token, uint32_t idxToken) +{ + RT_NOREF(pCtx, Op, idxToken); + + SVGA3dShaderDestToken dest; + dest.value = Token; + + SVGA3dShaderRegType const regType = (SVGA3dShaderRegType)(dest.type_upper << 3 | dest.type_lower); + Log3(("Dest: type %d, r0 %d, shfScale %d, dstMod %d, mask 0x%x, r1 %d, relAddr %d, num %d\n", + regType, dest.reserved0, dest.shfScale, dest.dstMod, dest.mask, dest.reserved1, dest.relAddr, dest.num)); + + if (pCtx->currentOpcode == SVGA3DOP_DCL && regType == SVGA3DREG_SAMPLER) + { + if (pCtx->u.pDclArgs->type == SVGA3DSAMP_UNKNOWN) + { + Log3(("Replacing SVGA3DSAMP_UNKNOWN with SVGA3DSAMP_2D\n")); + pCtx->u.pDclArgs->type = SVGA3DSAMP_2D; + } + } + + return vmsvga3dShaderParseRegOffset(pCtx, false, regType, dest.num); +} + +/* Parse a source parameter token: + * https://docs.microsoft.com/en-us/windows-hardware/drivers/display/source-parameter-token + * See FNSHADERPARSETOKEN. + */ +static int vmsvga3dShaderParseSrcToken(VMSVGA3DSHADERPARSECONTEXT* pCtx, uint32_t Op, uint32_t Token, uint32_t idxToken) +{ + RT_NOREF(pCtx, Op, idxToken); + + SVGA3dShaderSrcToken src; + src.value = Token; + + SVGA3dShaderRegType const regType = (SVGA3dShaderRegType)(src.type_upper << 3 | src.type_lower); + Log3(("Src: type %d, r0 %d, srcMod %d, swizzle 0x%x, r1 %d, relAddr %d, num %d\n", + regType, src.reserved0, src.srcMod, src.swizzle, src.reserved1, src.relAddr, src.num)); + + return vmsvga3dShaderParseRegOffset(pCtx, true, regType, src.num); +} + +/* Shortcut defines. */ +#define PT_DCL vmsvga3dShaderParseDclToken +#define PT_LBL vmsvga3dShaderParseLabelToken +#define PT_DEST vmsvga3dShaderParseDestToken +#define PT_SRC vmsvga3dShaderParseSrcToken + +/* Information about opcodes: + * https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/d3d9types/ne-d3d9types-_d3dshader_instruction_opcode_type + */ +static const VMSVGA3DSHADERPARSEOP aOps[] = +{ + /* Op Length Parameters */ + /* 00 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 01 */ { SVGA3DOP_MOV, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 02 */ { SVGA3DOP_ADD, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 03 */ { SVGA3DOP_SUB, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 04 */ { SVGA3DOP_MAD, 4, { PT_DEST, PT_SRC, PT_SRC, PT_SRC } }, + /* 05 */ { SVGA3DOP_MUL, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 06 */ { SVGA3DOP_RCP, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 07 */ { SVGA3DOP_RSQ, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 08 */ { SVGA3DOP_DP3, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 09 */ { SVGA3DOP_DP4, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 10 */ { SVGA3DOP_MIN, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 11 */ { SVGA3DOP_MAX, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 12 */ { SVGA3DOP_SLT, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 13 */ { SVGA3DOP_SGE, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 14 */ { SVGA3DOP_EXP, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 15 */ { SVGA3DOP_LOG, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 16 */ { SVGA3DOP_LIT, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 17 */ { SVGA3DOP_DST, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 18 */ { SVGA3DOP_LRP, 4, { PT_DEST, PT_SRC, PT_SRC, PT_SRC } }, + /* 19 */ { SVGA3DOP_FRC, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 20 */ { SVGA3DOP_M4x4, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 21 */ { SVGA3DOP_M4x3, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 22 */ { SVGA3DOP_M3x4, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 23 */ { SVGA3DOP_M3x3, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 24 */ { SVGA3DOP_M3x2, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 25 */ { SVGA3DOP_CALL, 1, { PT_LBL, NULL, NULL, NULL } }, + /* 26 */ { SVGA3DOP_CALLNZ, 2, { PT_LBL, PT_SRC, NULL, NULL } }, + /* 27 */ { SVGA3DOP_LOOP, 1, { PT_SRC, NULL, NULL, NULL } }, + /* 28 */ { SVGA3DOP_RET, 0, { NULL, NULL, NULL, NULL } }, + /* 29 */ { SVGA3DOP_ENDLOOP, 0, { NULL, NULL, NULL, NULL } }, + /* 30 */ { SVGA3DOP_LABEL, 1, { PT_LBL, NULL, NULL, NULL } }, + /* 31 */ { SVGA3DOP_DCL, 2, { PT_DCL, PT_DEST, NULL, NULL } }, + /* 32 */ { SVGA3DOP_POW, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 33 */ { SVGA3DOP_CRS, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 34 */ { SVGA3DOP_SGN, 4, { PT_DEST, PT_SRC, PT_SRC, PT_SRC } }, + /* 35 */ { SVGA3DOP_ABS, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 36 */ { SVGA3DOP_NRM, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 37 */ { SVGA3DOP_SINCOS, 4, { PT_DEST, PT_SRC, PT_SRC, PT_SRC } }, + /* 38 */ { SVGA3DOP_REP, 1, { PT_SRC, NULL, NULL, NULL } }, + /* 39 */ { SVGA3DOP_ENDREP, 0, { NULL, NULL, NULL, NULL } }, + /* 40 */ { SVGA3DOP_IF, 1, { PT_SRC, NULL, NULL, NULL } }, + /* 41 */ { SVGA3DOP_IFC, 2, { PT_SRC, PT_SRC, NULL, NULL } }, + /* 42 */ { SVGA3DOP_ELSE, 0, { NULL, NULL, NULL, NULL } }, + /* 43 */ { SVGA3DOP_ENDIF, 0, { NULL, NULL, NULL, NULL } }, + /* 44 */ { SVGA3DOP_BREAK, 0, { NULL, NULL, NULL, NULL } }, + /* 45 */ { SVGA3DOP_BREAKC, 2, { PT_SRC, PT_SRC, NULL, NULL } }, + /* 46 */ { SVGA3DOP_MOVA, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 47 */ { SVGA3DOP_DEFB, 2, { PT_DEST, NULL, NULL, NULL } }, + /* 48 */ { SVGA3DOP_DEFI, 5, { PT_DEST, NULL, NULL, NULL } }, + /* 49 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 50 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 51 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 52 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 53 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 54 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 55 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 56 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 57 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 58 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 59 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 60 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 61 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 62 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 63 */ { SVGA3DOP_NOP, 0, { NULL, NULL, NULL, NULL } }, + /* 64 */ { SVGA3DOP_TEXCOORD, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 65 */ { SVGA3DOP_TEXKILL, 1, { PT_DEST, NULL, NULL, NULL } }, + /* 66 */ { SVGA3DOP_TEX, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, // pre-1.4 = tex dest, post-1.4 = texld dest, src, src + /* 67 */ { SVGA3DOP_TEXBEM, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 68 */ { SVGA3DOP_TEXBEML, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 69 */ { SVGA3DOP_TEXREG2AR, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 70 */ { SVGA3DOP_TEXREG2GB, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 71 */ { SVGA3DOP_TEXM3x2PAD, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 72 */ { SVGA3DOP_TEXM3x2TEX, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 73 */ { SVGA3DOP_TEXM3x3PAD, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 74 */ { SVGA3DOP_TEXM3x3TEX, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 75 */ { SVGA3DOP_RESERVED0, 0, { NULL, NULL, NULL, NULL } }, + /* 76 */ { SVGA3DOP_TEXM3x3SPEC, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 77 */ { SVGA3DOP_TEXM3x3VSPEC, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 78 */ { SVGA3DOP_EXPP, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 79 */ { SVGA3DOP_LOGP, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 80 */ { SVGA3DOP_CND, 4, { PT_DEST, PT_SRC, PT_SRC, PT_SRC } }, + /* 81 */ { SVGA3DOP_DEF, 5, { PT_DEST, NULL, NULL, NULL } }, + /* 82 */ { SVGA3DOP_TEXREG2RGB, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 83 */ { SVGA3DOP_TEXDP3TEX, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 84 */ { SVGA3DOP_TEXM3x2DEPTH, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 85 */ { SVGA3DOP_TEXDP3, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 86 */ { SVGA3DOP_TEXM3x3, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 87 */ { SVGA3DOP_TEXDEPTH, 1, { PT_DEST, NULL, NULL, NULL } }, + /* 88 */ { SVGA3DOP_CMP, 4, { PT_DEST, PT_SRC, PT_SRC, PT_SRC } }, + /* 89 */ { SVGA3DOP_BEM, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 90 */ { SVGA3DOP_DP2ADD, 4, { PT_DEST, PT_SRC, PT_SRC, PT_SRC } }, + /* 91 */ { SVGA3DOP_DSX, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 92 */ { SVGA3DOP_DSY, 2, { PT_DEST, PT_SRC, NULL, NULL } }, + /* 93 */ { SVGA3DOP_TEXLDD, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 94 */ { SVGA3DOP_SETP, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 95 */ { SVGA3DOP_TEXLDL, 3, { PT_DEST, PT_SRC, PT_SRC, NULL } }, + /* 96 */ { SVGA3DOP_BREAKP, 1, { PT_SRC, NULL, NULL, NULL } }, +}; + +#undef PT_DCL +#undef PT_LBL +#undef PT_DEST +#undef PT_SRC + +/* Parse the shader code + * https://docs.microsoft.com/en-us/windows-hardware/drivers/display/shader-code-format + */ +int vmsvga3dShaderParse(SVGA3dShaderType type, uint32_t cbShaderData, uint32_t* pShaderData) +{ + uint32_t *paTokensStart = (uint32_t*)pShaderData; + uint32_t const cTokens = cbShaderData / sizeof(uint32_t); + + ASSERT_GUEST_RETURN(cTokens * sizeof(uint32_t) == cbShaderData, VERR_INVALID_PARAMETER); + + /* Need at least the version token and SVGA3DOP_END instruction token. 48KB is an arbitrary limit. */ + ASSERT_GUEST_RETURN(cTokens >= 2 && cTokens < (48 * _1K) / sizeof(paTokensStart[0]), VERR_INVALID_PARAMETER); + +#ifdef LOG_ENABLED + Log3(("Shader code:\n")); + const uint32_t cTokensPerLine = 8; + for (uint32_t iToken = 0; iToken < cTokens; ++iToken) + { + if ((iToken % cTokensPerLine) == 0) + { + if (iToken == 0) + Log3(("0x%08X,", paTokensStart[iToken])); + else + Log3(("\n0x%08X,", paTokensStart[iToken])); + } + else + Log3((" 0x%08X,", paTokensStart[iToken])); + } + Log3(("\n")); +#endif + + VMSVGA3DSHADERPARSECONTEXT ctx; + RT_ZERO(ctx); + + /* "The first token must be a version token." */ + ctx.version = *(SVGA3dShaderVersion*)paTokensStart; + ASSERT_GUEST_RETURN(ctx.version.type == SVGA3D_VS_TYPE + || ctx.version.type == SVGA3D_PS_TYPE, VERR_PARSE_ERROR); + /* A vertex shader should not be defined with a pixel shader bytecode (and visa versa)*/ + ASSERT_GUEST_RETURN((ctx.version.type == SVGA3D_VS_TYPE && type == SVGA3D_SHADERTYPE_VS) + || (ctx.version.type == SVGA3D_PS_TYPE && type == SVGA3D_SHADERTYPE_PS), VERR_PARSE_ERROR); + ASSERT_GUEST_RETURN(ctx.version.major >= 2 && ctx.version.major <= 4, VERR_PARSE_ERROR); + + /* Scan the tokens. Immediately return an error code on any unexpected data. */ + uint32_t *paTokensEnd = &paTokensStart[cTokens]; + uint32_t *pToken = &paTokensStart[1]; /* Skip the version token. */ + bool bEndTokenFound = false; + while (pToken < paTokensEnd) + { + SVGA3dShaderInstToken const token = *(SVGA3dShaderInstToken*)pToken; + + /* Figure out the instruction length, which is how many tokens follow the instruction token. */ + uint32_t const cInstLen = token.op == SVGA3DOP_COMMENT + ? token.comment_size + : token.size; + + Log3(("op %d, cInstLen %d\n", token.op, cInstLen)); + + /* Must not be greater than the number of remaining tokens. */ + ASSERT_GUEST_RETURN(cInstLen < (uintptr_t)(paTokensEnd - pToken), VERR_PARSE_ERROR); + + /* Stop parsing if this is the SVGA3DOP_END instruction. */ + if (token.op == SVGA3DOP_END) + { + ASSERT_GUEST_RETURN(token.value == 0x0000FFFF, VERR_PARSE_ERROR); + bEndTokenFound = true; + break; + } + + ctx.currentOpcode = (SVGA3dShaderOpCodeType)token.op; + + /* If this instrution is in the aOps table. */ + if (token.op <= SVGA3DOP_BREAKP) + { + VMSVGA3DSHADERPARSEOP const* pOp = &aOps[token.op]; + + if (ctx.currentOpcode == SVGA3DOP_DCL) + ctx.u.pDclArgs = (SVGA3DOpDclArgs *)&pToken[1]; + + /* cInstLen can be greater than pOp->Length. + * W10 guest sends a vertex shader MUL instruction with length 4. + * So figure out the actual number of valid parameters. + */ + uint32_t const cParams = RT_MIN(cInstLen, pOp->Length); + + /* Parse paramater tokens. */ + uint32_t i; + for (i = 0; i < RT_MIN(cParams, RT_ELEMENTS(pOp->apfnParse)); ++i) + { + if (!pOp->apfnParse[i]) + continue; + + int rc = pOp->apfnParse[i](&ctx, token.op, pToken[i + 1], i); + if (RT_FAILURE(rc)) + return rc; + } + } + else if (token.op == SVGA3DOP_PHASE + || token.op == SVGA3DOP_COMMENT) + { + } + else + ASSERT_GUEST_FAILED_RETURN(VERR_PARSE_ERROR); + + /* Next token. */ + pToken += cInstLen + 1; + } + + if (!bEndTokenFound) + { + ASSERT_GUEST_FAILED_RETURN(VERR_PARSE_ERROR); + } + + return VINF_SUCCESS; +} + +void vmsvga3dShaderLogRel(char const *pszMsg, SVGA3dShaderType type, uint32_t cbShaderData, uint32_t const *pShaderData) +{ + /* Dump the shader code. */ + static int scLogged = 0; + if (scLogged < 8) + { + ++scLogged; + + LogRel(("VMSVGA: %s shader: %s:\n", (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", pszMsg)); + const uint32_t cTokensPerLine = 8; + const uint32_t *paTokens = (uint32_t *)pShaderData; + const uint32_t cTokens = cbShaderData / sizeof(uint32_t); + for (uint32_t iToken = 0; iToken < cTokens; ++iToken) + { + if ((iToken % cTokensPerLine) == 0) + { + if (iToken == 0) + LogRel(("0x%08X,", paTokens[iToken])); + else + LogRel(("\n0x%08X,", paTokens[iToken])); + } + else + LogRel((" 0x%08X,", paTokens[iToken])); + } + LogRel(("\n")); + } +} diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-info.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-info.cpp new file mode 100644 index 00000000..0b26e640 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-info.cpp @@ -0,0 +1,1935 @@ +/* $Id: DevVGA-SVGA3d-info.cpp $ */ +/** @file + * DevSVGA3d - VMWare SVGA device, 3D parts - Introspection and debugging. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include + +#include +#include +#include + +#include + +#include /* required by DevVGA.h */ +#include /* required by DevVGA.h */ + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +#include "DevVGA-SVGA3d-internal.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** Enum value to string mappings for SVGA3dSurfaceFormat, prefix "SVGA3D_". */ +static const VMSVGAINFOENUM g_aSVGA3dSurfaceFormats[] = +{ + { SVGA3D_FORMAT_INVALID , "FORMAT_INVALID" }, + { SVGA3D_X8R8G8B8 , "X8R8G8B8" }, + { SVGA3D_A8R8G8B8 , "A8R8G8B8" }, + { SVGA3D_R5G6B5 , "R5G6B5" }, + { SVGA3D_X1R5G5B5 , "X1R5G5B5" }, + { SVGA3D_A1R5G5B5 , "A1R5G5B5" }, + { SVGA3D_A4R4G4B4 , "A4R4G4B4" }, + { SVGA3D_Z_D32 , "Z_D32" }, + { SVGA3D_Z_D16 , "Z_D16" }, + { SVGA3D_Z_D24S8 , "Z_D24S8" }, + { SVGA3D_Z_D15S1 , "Z_D15S1" }, + { SVGA3D_LUMINANCE8 , "LUMINANCE8" }, + { SVGA3D_LUMINANCE4_ALPHA4 , "LUMINANCE4_ALPHA4" }, + { SVGA3D_LUMINANCE16 , "LUMINANCE16" }, + { SVGA3D_LUMINANCE8_ALPHA8 , "LUMINANCE8_ALPHA8" }, + { SVGA3D_DXT1 , "DXT1" }, + { SVGA3D_DXT2 , "DXT2" }, + { SVGA3D_DXT3 , "DXT3" }, + { SVGA3D_DXT4 , "DXT4" }, + { SVGA3D_DXT5 , "DXT5" }, + { SVGA3D_BUMPU8V8 , "BUMPU8V8" }, + { SVGA3D_BUMPL6V5U5 , "BUMPL6V5U5" }, + { SVGA3D_BUMPX8L8V8U8 , "BUMPX8L8V8U8" }, + { SVGA3D_FORMAT_DEAD1 , "FORMAT_DEAD1" }, + { SVGA3D_ARGB_S10E5 , "ARGB_S10E5" }, + { SVGA3D_ARGB_S23E8 , "ARGB_S23E8" }, + { SVGA3D_A2R10G10B10 , "A2R10G10B10" }, + { SVGA3D_V8U8 , "V8U8" }, + { SVGA3D_Q8W8V8U8 , "Q8W8V8U8" }, + { SVGA3D_CxV8U8 , "CxV8U8" }, + { SVGA3D_X8L8V8U8 , "X8L8V8U8" }, + { SVGA3D_A2W10V10U10 , "A2W10V10U10" }, + { SVGA3D_ALPHA8 , "ALPHA8" }, + { SVGA3D_R_S10E5 , "R_S10E5" }, + { SVGA3D_R_S23E8 , "R_S23E8" }, + { SVGA3D_RG_S10E5 , "RG_S10E5" }, + { SVGA3D_RG_S23E8 , "RG_S23E8" }, + { SVGA3D_BUFFER , "BUFFER" }, + { SVGA3D_Z_D24X8 , "Z_D24X8" }, + { SVGA3D_V16U16 , "V16U16" }, + { SVGA3D_G16R16 , "G16R16" }, + { SVGA3D_A16B16G16R16 , "A16B16G16R16" }, + { SVGA3D_UYVY , "UYVY" }, + { SVGA3D_YUY2 , "YUY2" }, + { SVGA3D_NV12 , "NV12" }, + { SVGA3D_FORMAT_DEAD2 , "FORMAT_DEAD2" }, + { SVGA3D_R32G32B32A32_TYPELESS , "R32G32B32A32_TYPELESS" }, + { SVGA3D_R32G32B32A32_UINT , "R32G32B32A32_UINT" }, + { SVGA3D_R32G32B32A32_SINT , "R32G32B32A32_SINT" }, + { SVGA3D_R32G32B32_TYPELESS , "R32G32B32_TYPELESS" }, + { SVGA3D_R32G32B32_FLOAT , "R32G32B32_FLOAT" }, + { SVGA3D_R32G32B32_UINT , "R32G32B32_UINT" }, + { SVGA3D_R32G32B32_SINT , "R32G32B32_SINT" }, + { SVGA3D_R16G16B16A16_TYPELESS , "R16G16B16A16_TYPELESS" }, + { SVGA3D_R16G16B16A16_UINT , "R16G16B16A16_UINT" }, + { SVGA3D_R16G16B16A16_SNORM , "R16G16B16A16_SNORM" }, + { SVGA3D_R16G16B16A16_SINT , "R16G16B16A16_SINT" }, + { SVGA3D_R32G32_TYPELESS , "R32G32_TYPELESS" }, + { SVGA3D_R32G32_UINT , "R32G32_UINT" }, + { SVGA3D_R32G32_SINT , "R32G32_SINT" }, + { SVGA3D_R32G8X24_TYPELESS , "R32G8X24_TYPELESS" }, + { SVGA3D_D32_FLOAT_S8X24_UINT , "D32_FLOAT_S8X24_UINT" }, + { SVGA3D_R32_FLOAT_X8X24 , "R32_FLOAT_X8X24" }, + { SVGA3D_X32_G8X24_UINT , "X32_G8X24_UINT" }, + { SVGA3D_R10G10B10A2_TYPELESS , "R10G10B10A2_TYPELESS" }, + { SVGA3D_R10G10B10A2_UINT , "R10G10B10A2_UINT" }, + { SVGA3D_R11G11B10_FLOAT , "R11G11B10_FLOAT" }, + { SVGA3D_R8G8B8A8_TYPELESS , "R8G8B8A8_TYPELESS" }, + { SVGA3D_R8G8B8A8_UNORM , "R8G8B8A8_UNORM" }, + { SVGA3D_R8G8B8A8_UNORM_SRGB , "R8G8B8A8_UNORM_SRGB" }, + { SVGA3D_R8G8B8A8_UINT , "R8G8B8A8_UINT" }, + { SVGA3D_R8G8B8A8_SINT , "R8G8B8A8_SINT" }, + { SVGA3D_R16G16_TYPELESS , "R16G16_TYPELESS" }, + { SVGA3D_R16G16_UINT , "R16G16_UINT" }, + { SVGA3D_R16G16_SINT , "R16G16_SINT" }, + { SVGA3D_R32_TYPELESS , "R32_TYPELESS" }, + { SVGA3D_D32_FLOAT , "D32_FLOAT" }, + { SVGA3D_R32_UINT , "R32_UINT" }, + { SVGA3D_R32_SINT , "R32_SINT" }, + { SVGA3D_R24G8_TYPELESS , "R24G8_TYPELESS" }, + { SVGA3D_D24_UNORM_S8_UINT , "D24_UNORM_S8_UINT" }, + { SVGA3D_R24_UNORM_X8 , "R24_UNORM_X8" }, + { SVGA3D_X24_G8_UINT , "X24_G8_UINT" }, + { SVGA3D_R8G8_TYPELESS , "R8G8_TYPELESS" }, + { SVGA3D_R8G8_UNORM , "R8G8_UNORM" }, + { SVGA3D_R8G8_UINT , "R8G8_UINT" }, + { SVGA3D_R8G8_SINT , "R8G8_SINT" }, + { SVGA3D_R16_TYPELESS , "R16_TYPELESS" }, + { SVGA3D_R16_UNORM , "R16_UNORM" }, + { SVGA3D_R16_UINT , "R16_UINT" }, + { SVGA3D_R16_SNORM , "R16_SNORM" }, + { SVGA3D_R16_SINT , "R16_SINT" }, + { SVGA3D_R8_TYPELESS , "R8_TYPELESS" }, + { SVGA3D_R8_UNORM , "R8_UNORM" }, + { SVGA3D_R8_UINT , "R8_UINT" }, + { SVGA3D_R8_SNORM , "R8_SNORM" }, + { SVGA3D_R8_SINT , "R8_SINT" }, + { SVGA3D_P8 , "P8" }, + { SVGA3D_R9G9B9E5_SHAREDEXP , "R9G9B9E5_SHAREDEXP" }, + { SVGA3D_R8G8_B8G8_UNORM , "R8G8_B8G8_UNORM" }, + { SVGA3D_G8R8_G8B8_UNORM , "G8R8_G8B8_UNORM" }, + { SVGA3D_BC1_TYPELESS , "BC1_TYPELESS" }, + { SVGA3D_BC1_UNORM_SRGB , "BC1_UNORM_SRGB" }, + { SVGA3D_BC2_TYPELESS , "BC2_TYPELESS" }, + { SVGA3D_BC2_UNORM_SRGB , "BC2_UNORM_SRGB" }, + { SVGA3D_BC3_TYPELESS , "BC3_TYPELESS" }, + { SVGA3D_BC3_UNORM_SRGB , "BC3_UNORM_SRGB" }, + { SVGA3D_BC4_TYPELESS , "BC4_TYPELESS" }, + { SVGA3D_ATI1 , "ATI1" }, + { SVGA3D_BC4_SNORM , "BC4_SNORM" }, + { SVGA3D_BC5_TYPELESS , "BC5_TYPELESS" }, + { SVGA3D_ATI2 , "ATI2" }, + { SVGA3D_BC5_SNORM , "BC5_SNORM" }, + { SVGA3D_R10G10B10_XR_BIAS_A2_UNORM , "R10G10B10_XR_BIAS_A2_UNORM" }, + { SVGA3D_B8G8R8A8_TYPELESS , "B8G8R8A8_TYPELESS" }, + { SVGA3D_B8G8R8A8_UNORM_SRGB , "B8G8R8A8_UNORM_SRGB" }, + { SVGA3D_B8G8R8X8_TYPELESS , "B8G8R8X8_TYPELESS" }, + { SVGA3D_B8G8R8X8_UNORM_SRGB , "B8G8R8X8_UNORM_SRGB" }, + { SVGA3D_Z_DF16 , "Z_DF16" }, + { SVGA3D_Z_DF24 , "Z_DF24" }, + { SVGA3D_Z_D24S8_INT , "Z_D24S8_INT" }, + { SVGA3D_YV12 , "YV12" }, + { SVGA3D_R32G32B32A32_FLOAT , "R32G32B32A32_FLOAT" }, + { SVGA3D_R16G16B16A16_FLOAT , "R16G16B16A16_FLOAT" }, + { SVGA3D_R16G16B16A16_UNORM , "R16G16B16A16_UNORM" }, + { SVGA3D_R32G32_FLOAT , "R32G32_FLOAT" }, + { SVGA3D_R10G10B10A2_UNORM , "R10G10B10A2_UNORM" }, + { SVGA3D_R8G8B8A8_SNORM , "R8G8B8A8_SNORM" }, + { SVGA3D_R16G16_FLOAT , "R16G16_FLOAT" }, + { SVGA3D_R16G16_UNORM , "R16G16_UNORM" }, + { SVGA3D_R16G16_SNORM , "R16G16_SNORM" }, + { SVGA3D_R32_FLOAT , "R32_FLOAT" }, + { SVGA3D_R8G8_SNORM , "R8G8_SNORM" }, + { SVGA3D_R16_FLOAT , "R16_FLOAT" }, + { SVGA3D_D16_UNORM , "D16_UNORM" }, + { SVGA3D_A8_UNORM , "A8_UNORM" }, + { SVGA3D_BC1_UNORM , "BC1_UNORM" }, + { SVGA3D_BC2_UNORM , "BC2_UNORM" }, + { SVGA3D_BC3_UNORM , "BC3_UNORM" }, + { SVGA3D_B5G6R5_UNORM , "B5G6R5_UNORM" }, + { SVGA3D_B5G5R5A1_UNORM , "B5G5R5A1_UNORM" }, + { SVGA3D_B8G8R8A8_UNORM , "B8G8R8A8_UNORM" }, + { SVGA3D_B8G8R8X8_UNORM , "B8G8R8X8_UNORM" }, + { SVGA3D_BC4_UNORM , "BC4_UNORM" }, + { SVGA3D_BC5_UNORM , "BC5_UNORM" }, + { SVGA3D_B4G4R4A4_UNORM , "B4G4R4A4_UNORM" }, + { SVGA3D_BC6H_TYPELESS , "BC6H_TYPELESS" }, + { SVGA3D_BC6H_UF16 , "BC6H_UF16" }, + { SVGA3D_BC6H_SF16 , "BC6H_SF16" }, + { SVGA3D_BC7_TYPELESS , "BC7_TYPELESS" }, + { SVGA3D_BC7_UNORM , "BC7_UNORM" }, + { SVGA3D_BC7_UNORM_SRGB , "BC7_UNORM_SRGB" }, + { SVGA3D_AYUV , "AYUV" }, +}; +VMSVGAINFOENUMMAP_MAKE(RT_NOTHING, g_SVGA3dSurfaceFormat2String, g_aSVGA3dSurfaceFormats, "SVGA3D_"); + +/** Values for SVGA3dTextureFilter, prefix SVGA3D_TEX_FILTER_. */ +static const char * const g_apszTexureFilters[] = +{ + "NONE", + "NEAREST", + "LINEAR", + "ANISOTROPIC", + "FLATCUBIC", + "GAUSSIANCUBIC", + "PYRAMIDALQUAD", + "GAUSSIANQUAD", +}; + +/** SVGA3dSurface1Flags values, prefix SVGA3D_SURFACE_. */ +static VMSVGAINFOFLAGS32 const g_aSvga3DSurfaceFlags[] = +{ + { SVGA3D_SURFACE_CUBEMAP , "CUBEMAP" }, + { SVGA3D_SURFACE_HINT_STATIC , "HINT_STATIC" }, + { SVGA3D_SURFACE_HINT_DYNAMIC , "HINT_DYNAMIC" }, + { SVGA3D_SURFACE_HINT_INDEXBUFFER , "HINT_INDEXBUFFER" }, + { SVGA3D_SURFACE_HINT_VERTEXBUFFER , "HINT_VERTEXBUFFER" }, + { SVGA3D_SURFACE_HINT_TEXTURE , "HINT_TEXTURE" }, + { SVGA3D_SURFACE_HINT_RENDERTARGET , "HINT_RENDERTARGET" }, + { SVGA3D_SURFACE_HINT_DEPTHSTENCIL , "HINT_DEPTHSTENCIL" }, + { SVGA3D_SURFACE_HINT_WRITEONLY , "HINT_WRITEONLY" }, + { SVGA3D_SURFACE_DEAD2 , "MASKABLE_ANTIALIAS" }, /* SVGA3D_SURFACE_MASKABLE_ANTIALIAS */ + { SVGA3D_SURFACE_AUTOGENMIPMAPS , "AUTOGENMIPMAPS" }, +}; + + +#ifdef VMSVGA3D_DIRECT3D + +/** Values for D3DFORMAT, prefix D3DFMT_. */ +static VMSVGAINFOENUM const g_aD3DFormats[] = +{ + { D3DFMT_UNKNOWN , "UNKNOWN" }, + { D3DFMT_R8G8B8 , "R8G8B8" }, + { D3DFMT_A8R8G8B8 , "A8R8G8B8" }, + { D3DFMT_X8R8G8B8 , "X8R8G8B8" }, + { D3DFMT_R5G6B5 , "R5G6B5" }, + { D3DFMT_X1R5G5B5 , "X1R5G5B5" }, + { D3DFMT_A1R5G5B5 , "A1R5G5B5" }, + { D3DFMT_A4R4G4B4 , "A4R4G4B4" }, + { D3DFMT_R3G3B2 , "R3G3B2" }, + { D3DFMT_A8 , "A8" }, + { D3DFMT_A8R3G3B2 , "A8R3G3B2" }, + { D3DFMT_X4R4G4B4 , "X4R4G4B4" }, + { D3DFMT_A2B10G10R10 , "A2B10G10R10" }, + { D3DFMT_A8B8G8R8 , "A8B8G8R8" }, + { D3DFMT_X8B8G8R8 , "X8B8G8R8" }, + { D3DFMT_G16R16 , "G16R16" }, + { D3DFMT_A2R10G10B10 , "A2R10G10B10" }, + { D3DFMT_A16B16G16R16 , "A16B16G16R16" }, + { D3DFMT_A8P8 , "A8P8" }, + { D3DFMT_P8 , "P8" }, + { D3DFMT_L8 , "L8" }, + { D3DFMT_A8L8 , "A8L8" }, + { D3DFMT_A4L4 , "A4L4" }, + { D3DFMT_V8U8 , "V8U8" }, + { D3DFMT_L6V5U5 , "L6V5U5" }, + { D3DFMT_X8L8V8U8 , "X8L8V8U8" }, + { D3DFMT_Q8W8V8U8 , "Q8W8V8U8" }, + { D3DFMT_V16U16 , "V16U16" }, + { D3DFMT_A2W10V10U10 , "A2W10V10U10" }, + { D3DFMT_D16_LOCKABLE , "D16_LOCKABLE" }, + { D3DFMT_D32 , "D32" }, + { D3DFMT_D15S1 , "D15S1" }, + { D3DFMT_D24S8 , "D24S8" }, + { D3DFMT_D24X8 , "D24X8" }, + { D3DFMT_D24X4S4 , "D24X4S4" }, + { D3DFMT_D16 , "D16" }, + { D3DFMT_L16 , "L16" }, + { D3DFMT_D32F_LOCKABLE , "D32F_LOCKABLE" }, + { D3DFMT_D24FS8 , "D24FS8" }, + { D3DFMT_VERTEXDATA , "VERTEXDATA" }, + { D3DFMT_INDEX16 , "INDEX16" }, + { D3DFMT_INDEX32 , "INDEX32" }, + { D3DFMT_Q16W16V16U16 , "Q16W16V16U16" }, + { D3DFMT_R16F , "R16F" }, + { D3DFMT_G16R16F , "G16R16F" }, + { D3DFMT_A16B16G16R16F , "A16B16G16R16F" }, + { D3DFMT_R32F , "R32F" }, + { D3DFMT_G32R32F , "G32R32F" }, + { D3DFMT_A32B32G32R32F , "A32B32G32R32F" }, + { D3DFMT_CxV8U8 , "CxV8U8" }, + /* Fourcc values, MSB is in the right most char: */ + { D3DFMT_MULTI2_ARGB8 , "MULTI2_ARGB8" }, + { D3DFMT_DXT1 , "DXT1" }, + { D3DFMT_DXT2 , "DXT2" }, + { D3DFMT_YUY2 , "YUY2" }, + { D3DFMT_DXT3 , "DXT3" }, + { D3DFMT_DXT4 , "DXT4" }, + { D3DFMT_DXT5 , "DXT5" }, + { D3DFMT_G8R8_G8B8 , "G8R8_G8B8" }, + { D3DFMT_R8G8_B8G8 , "R8G8_B8G8" }, + { D3DFMT_UYVY , "UYVY" }, + { D3DFMT_FORCE_DWORD , "FORCE_DWORD" }, /* UINT32_MAX */ +}; +VMSVGAINFOENUMMAP_MAKE(static, g_D3DFormat2String, g_aD3DFormats, "D3DFMT_"); + +/** Values for D3DMULTISAMPLE_TYPE, prefix D3DMULTISAMPLE_. */ +static VMSVGAINFOENUM const g_aD3DMultiSampleTypes[] = +{ + { D3DMULTISAMPLE_NONE , "NONE" }, + { D3DMULTISAMPLE_NONMASKABLE , "NONMASKABLE" }, + { D3DMULTISAMPLE_2_SAMPLES , "2_SAMPLES" }, + { D3DMULTISAMPLE_3_SAMPLES , "3_SAMPLES" }, + { D3DMULTISAMPLE_4_SAMPLES , "4_SAMPLES" }, + { D3DMULTISAMPLE_5_SAMPLES , "5_SAMPLES" }, + { D3DMULTISAMPLE_6_SAMPLES , "6_SAMPLES" }, + { D3DMULTISAMPLE_7_SAMPLES , "7_SAMPLES" }, + { D3DMULTISAMPLE_8_SAMPLES , "8_SAMPLES" }, + { D3DMULTISAMPLE_9_SAMPLES , "9_SAMPLES" }, + { D3DMULTISAMPLE_10_SAMPLES , "10_SAMPLES" }, + { D3DMULTISAMPLE_11_SAMPLES , "11_SAMPLES" }, + { D3DMULTISAMPLE_12_SAMPLES , "12_SAMPLES" }, + { D3DMULTISAMPLE_13_SAMPLES , "13_SAMPLES" }, + { D3DMULTISAMPLE_14_SAMPLES , "14_SAMPLES" }, + { D3DMULTISAMPLE_15_SAMPLES , "15_SAMPLES" }, + { D3DMULTISAMPLE_16_SAMPLES , "16_SAMPLES" }, + { D3DMULTISAMPLE_FORCE_DWORD , "FORCE_DWORD" }, +}; +VMSVGAINFOENUMMAP_MAKE(static, g_D3DMultiSampleType2String, g_aD3DMultiSampleTypes, "D3DMULTISAMPLE_"); + +/** D3DUSAGE_XXX flag value, prefix D3DUSAGE_. */ +static VMSVGAINFOFLAGS32 const g_aD3DUsageFlags[] = +{ + { D3DUSAGE_RENDERTARGET , "RENDERTARGET" }, + { D3DUSAGE_DEPTHSTENCIL , "DEPTHSTENCIL" }, + { D3DUSAGE_WRITEONLY , "WRITEONLY" }, + { D3DUSAGE_SOFTWAREPROCESSING , "SOFTWAREPROCESSING" }, + { D3DUSAGE_DONOTCLIP , "DONOTCLIP" }, + { D3DUSAGE_POINTS , "POINTS" }, + { D3DUSAGE_RTPATCHES , "RTPATCHES" }, + { D3DUSAGE_NPATCHES , "NPATCHES" }, + { D3DUSAGE_DYNAMIC , "DYNAMIC" }, + { D3DUSAGE_AUTOGENMIPMAP , "AUTOGENMIPMAP" }, + { D3DUSAGE_RESTRICTED_CONTENT , "RESTRICTED_CONTENT" }, + { D3DUSAGE_RESTRICT_SHARED_RESOURCE_DRIVER , "RESTRICT_SHARED_RESOURCE_DRIVER" }, + { D3DUSAGE_RESTRICT_SHARED_RESOURCE , "RESTRICT_SHARED_RESOURCE" }, + { D3DUSAGE_DMAP , "DMAP" }, + { D3DUSAGE_NONSECURE , "NONSECURE" }, + { D3DUSAGE_TEXTAPI , "TEXTAPI" }, +}; + +#endif /* VMSVGA3D_DIRECT3D */ + + +void vmsvga3dInfoU32Flags(PCDBGFINFOHLP pHlp, uint32_t fFlags, const char *pszPrefix, PCVMSVGAINFOFLAGS32 paFlags, uint32_t cFlags) +{ + for (uint32_t i = 0; i < cFlags; i++) + if ((paFlags[i].fFlags & fFlags) == paFlags[i].fFlags) + { + Assert(paFlags[i].fFlags); + pHlp->pfnPrintf(pHlp, " %s%s", pszPrefix, paFlags[i].pszJohnny); + fFlags &= ~paFlags[i].fFlags; + if (!fFlags) + return; + } + if (fFlags) + pHlp->pfnPrintf(pHlp, " UNKNOWN_%#x", fFlags); +} + + +/** + * Worker for vmsvgaR3Info that display details of a host window. + * + * @param pHlp The output methods. + * @param idHostWindow The host window handle/id/whatever. + */ +void vmsvga3dInfoHostWindow(PCDBGFINFOHLP pHlp, uint64_t idHostWindow) +{ +#ifdef RT_OS_WINDOWS + HWND hwnd = (HWND)(uintptr_t)idHostWindow; + Assert((uintptr_t)hwnd == idHostWindow); + if (hwnd != NULL) + { + WINDOWINFO Info; + RT_ZERO(Info); + Info.cbSize = sizeof(Info); + if (GetWindowInfo(hwnd, &Info)) + { + pHlp->pfnPrintf(pHlp, " Window rect: xLeft=%d, yTop=%d, xRight=%d, yBottom=%d (cx=%d, cy=%d)\n", + Info.rcWindow.left, Info.rcWindow.top, Info.rcWindow.right, Info.rcWindow.bottom, + Info.rcWindow.right - Info.rcWindow.left, Info.rcWindow.bottom - Info.rcWindow.top); + pHlp->pfnPrintf(pHlp, " Client rect: xLeft=%d, yTop=%d, xRight=%d, yBottom=%d (cx=%d, cy=%d)\n", + Info.rcClient.left, Info.rcClient.top, Info.rcClient.right, Info.rcClient.bottom, + Info.rcClient.right - Info.rcClient.left, Info.rcClient.bottom - Info.rcClient.top); + pHlp->pfnPrintf(pHlp, " Style: %#x", Info.dwStyle); + static const VMSVGAINFOFLAGS32 g_aStyles[] = + { + { WS_POPUP , "POPUP" }, + { WS_CHILD , "CHILD" }, + { WS_MINIMIZE , "MINIMIZE" }, + { WS_VISIBLE , "VISIBLE" }, + { WS_DISABLED , "DISABLED" }, + { WS_CLIPSIBLINGS , "CLIPSIBLINGS" }, + { WS_CLIPCHILDREN , "CLIPCHILDREN" }, + { WS_MAXIMIZE , "MAXIMIZE" }, + { WS_BORDER , "BORDER" }, + { WS_DLGFRAME , "DLGFRAME" }, + { WS_VSCROLL , "VSCROLL" }, + { WS_HSCROLL , "HSCROLL" }, + { WS_SYSMENU , "SYSMENU" }, + { WS_THICKFRAME , "THICKFRAME" }, + { WS_GROUP , "GROUP" }, + { WS_TABSTOP , "TABSTOP" }, + }; + vmsvga3dInfoU32Flags(pHlp, Info.dwStyle, "", g_aStyles, RT_ELEMENTS(g_aStyles)); + pHlp->pfnPrintf(pHlp, "\n"); + + pHlp->pfnPrintf(pHlp, " ExStyle: %#x", Info.dwExStyle); + static const VMSVGAINFOFLAGS32 g_aExStyles[] = + { + { WS_EX_DLGMODALFRAME, "DLGMODALFRAME" }, + { 0x00000002, "DRAGDETECT" }, + { WS_EX_NOPARENTNOTIFY, "NOPARENTNOTIFY" }, + { WS_EX_TOPMOST, "TOPMOST" }, + { WS_EX_ACCEPTFILES, "ACCEPTFILES" }, + { WS_EX_TRANSPARENT, "TRANSPARENT" }, + { WS_EX_MDICHILD, "MDICHILD" }, + { WS_EX_TOOLWINDOW, "TOOLWINDOW" }, + { WS_EX_WINDOWEDGE, "WINDOWEDGE" }, + { WS_EX_CLIENTEDGE, "CLIENTEDGE" }, + { WS_EX_CONTEXTHELP, "CONTEXTHELP" }, + { WS_EX_RIGHT, "RIGHT" }, + /*{ WS_EX_LEFT, "LEFT" }, = 0 */ + { WS_EX_RTLREADING, "RTLREADING" }, + /*{ WS_EX_LTRREADING, "LTRREADING" }, = 0 */ + { WS_EX_LEFTSCROLLBAR, "LEFTSCROLLBAR" }, + /*{ WS_EX_RIGHTSCROLLBAR, "RIGHTSCROLLBAR" }, = 0 */ + { WS_EX_CONTROLPARENT, "CONTROLPARENT" }, + { WS_EX_STATICEDGE, "STATICEDGE" }, + { WS_EX_APPWINDOW, "APPWINDOW" }, + { WS_EX_LAYERED, "LAYERED" }, + { WS_EX_NOINHERITLAYOUT, "NOINHERITLAYOUT" }, + { WS_EX_LAYOUTRTL, "LAYOUTRTL" }, + { WS_EX_COMPOSITED, "COMPOSITED" }, + { WS_EX_NOACTIVATE, "NOACTIVATE" }, + }; + vmsvga3dInfoU32Flags(pHlp, Info.dwExStyle, "", g_aExStyles, RT_ELEMENTS(g_aExStyles)); + pHlp->pfnPrintf(pHlp, "\n"); + + pHlp->pfnPrintf(pHlp, " Window Status: %#x\n", Info.dwWindowStatus); + if (Info.cxWindowBorders || Info.cyWindowBorders) + pHlp->pfnPrintf(pHlp, " Borders: cx=%u, cy=%u\n", Info.cxWindowBorders, Info.cyWindowBorders); + pHlp->pfnPrintf(pHlp, " Window Type: %#x\n", Info.atomWindowType); + pHlp->pfnPrintf(pHlp, " Creator Ver: %#x\n", Info.wCreatorVersion); + } + else + pHlp->pfnPrintf(pHlp, " GetWindowInfo: last error %d\n", GetLastError()); + } + +#elif defined(RT_OS_DARWIN) + int rc = ExplicitlyLoadVBoxSVGA3DObjC(false /*fResolveAllImports*/, NULL /*pErrInfo*/); + if (RT_SUCCESS(rc)) + vmsvga3dCocoaViewInfo(pHlp, (NativeNSViewRef)(uintptr_t)idHostWindow); + else + pHlp->pfnPrintf(pHlp, " Windows info: vmsvga3dCocoaViewInfo failed to load (%Rrc)\n", rc); + +#else + RT_NOREF(idHostWindow); + pHlp->pfnPrintf(pHlp, " Windows info: Not implemented on this platform\n"); +#endif +} + + +/** + * Looks up an enum value in a translation table. + * + * @returns The value name. + * @param iValue The value to name. + * @param pEnumMap Enum value to string mapping. + */ +const char *vmsvgaLookupEnum(int32_t iValue, PCVMSVGAINFOENUMMAP pEnumMap) +{ + PCVMSVGAINFOENUM paValues = pEnumMap->paValues; + +#ifdef VBOX_STRICT + /* + * Check that it's really sorted, or the binary lookup won't work right. + */ + if (!*pEnumMap->pfAsserted) + { + *pEnumMap->pfAsserted = true; + for (uint32_t i = 1; i < pEnumMap->cValues; i++) + AssertMsg(paValues[i - 1].iValue <= paValues[i].iValue, + ("i = %d: %d followed by %d", i, paValues[i - 1].iValue, paValues[i].iValue)); + } +#endif + + /* + * Binary search + */ + uint32_t iStart = 0; + uint32_t iEnd = (uint32_t)pEnumMap->cValues; + for (;;) + { + uint32_t i = iStart + (iEnd - iStart) / 2; + if (iValue < paValues[i].iValue) + { + if (i > iStart) + iEnd = i; + else + break; + } + else if (iValue > paValues[i].iValue) + { + i++; + if (i < iEnd) + iStart = i; + else + break; + } + else + return paValues[i].pszName; + } + return NULL; +} + + +/** + * Formats an enum value as a string, sparse mapping table. + * + * @returns pszBuffer. + * @param pszBuffer The output buffer. + * @param cbBuffer The size of the output buffer. + * @param pszName The variable name, optional. + * @param iValue The enum value. + * @param fPrefix Whether to prepend the prefix or not. + * @param pEnumMap Enum value to string mapping. + */ +char *vmsvgaFormatEnumValueEx(char *pszBuffer, size_t cbBuffer, const char *pszName, int32_t iValue, + bool fPrefix, PCVMSVGAINFOENUMMAP pEnumMap) +{ + const char *pszValueName = vmsvgaLookupEnum(iValue, pEnumMap); + const char *pszPrefix = fPrefix ? pEnumMap->pszPrefix : ""; + if (pszValueName) + { + if (pszName) + RTStrPrintf(pszBuffer, cbBuffer, "%s = %s%s (%#x)", pszName, pszPrefix, pszValueName, iValue); + else + RTStrPrintf(pszBuffer, cbBuffer, "%s%s (%#x)", pszPrefix, pszValueName, iValue); + return pszBuffer; + } + + if (pszName) + RTStrPrintf(pszBuffer, cbBuffer, "%s = %sUNKNOWN_%d (%#x)", pszName, pszPrefix, iValue, iValue); + else + RTStrPrintf(pszBuffer, cbBuffer, "%sUNKNOWN_%d (%#x)", pszPrefix, iValue, iValue); + return pszBuffer; +} + + +/** + * Formats an enum value as a string. + * + * @returns pszBuffer. + * @param pszBuffer The output buffer. + * @param cbBuffer The size of the output buffer. + * @param pszName The variable name, optional. + * @param uValue The enum value. + * @param pszPrefix The prefix of the enum values. Empty string if + * none. This helps reduce the memory footprint + * as well as the source code size. + * @param papszValues One to one string mapping of the enum values. + * @param cValues The number of values in the mapping. + */ +char *vmsvgaFormatEnumValue(char *pszBuffer, size_t cbBuffer, const char *pszName, uint32_t uValue, + const char *pszPrefix, const char * const *papszValues, size_t cValues) +{ + if (uValue < cValues) + { + if (pszName) + RTStrPrintf(pszBuffer, cbBuffer, "%s = %s%s (%#x)", pszName, pszPrefix, papszValues[uValue], uValue); + else + RTStrPrintf(pszBuffer, cbBuffer, "%s%s (%#x)", pszPrefix, papszValues[uValue], uValue); + } + else + { + if (pszName) + RTStrPrintf(pszBuffer, cbBuffer, "%s = %sUNKNOWN_%d (%#x)", pszName, pszPrefix, uValue, uValue); + else + RTStrPrintf(pszBuffer, cbBuffer, "%sUNKNOWN_%d (%#x)", pszPrefix, uValue, uValue); + } + return pszBuffer; +} + + +/** + * DBGF info printer for vmsvga3dAsciiPrint. + * + * @param pszLine The line to print. + * @param pvUser The debug info helpers. + */ +DECLCALLBACK(void) vmsvga3dAsciiPrintlnInfo(const char *pszLine, void *pvUser) +{ + PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser; + pHlp->pfnPrintf(pHlp, ">%s<\n", pszLine); +} + + +/** + * Log printer for vmsvga3dAsciiPrint. + * + * @param pszLine The line to print. + * @param pvUser Ignored. + */ +DECLCALLBACK(void) vmsvga3dAsciiPrintlnLog(const char *pszLine, void *pvUser) +{ + size_t cch = strlen(pszLine); + while (cch > 0 && pszLine[cch - 1] == ' ') + cch--; + RTLogPrintf("%.*s\n", cch, pszLine); + NOREF(pvUser); +} + + +void vmsvga3dAsciiPrint(PFNVMSVGAASCIIPRINTLN pfnPrintLine, void *pvUser, void const *pvImage, size_t cbImage, + uint32_t cx, uint32_t cy, uint32_t cbScanline, SVGA3dSurfaceFormat enmFormat, bool fInvY, + uint32_t cchMaxX, uint32_t cchMaxY) +{ + RT_NOREF(cbImage); + + /* + * Skip stuff we can't or won't need to handle. + */ + if (!cx || !cy || !cchMaxX || !cchMaxY) + return; + switch (enmFormat) + { + /* Compressed. */ + case SVGA3D_DXT1: + case SVGA3D_DXT2: + case SVGA3D_DXT3: + case SVGA3D_DXT4: + case SVGA3D_DXT5: + return; + /* Generic. */ + case SVGA3D_BUFFER: + return; + default: + break; /* ok */ + } + + /* + * Figure the pixel conversion factors. + */ + uint32_t cxPerChar = cx / cchMaxX + 1; + uint32_t cyPerChar = cy / cchMaxY + 1; + /** @todo try keep aspect... */ + uint32_t const cchLine = (cx + cxPerChar - 1) / cxPerChar; + uint32_t const cbSrcPixel = vmsvga3dSurfaceFormatSize(enmFormat, NULL, NULL); + + /* + * The very simple conversion we're doing in this function is based on + * mapping a block of converted pixels to an ASCII character of similar + * weigth. We do that by summing up all the 8-bit gray scale pixels in + * that block, applying a conversion factor and getting an index into an + * array of increasingly weighty characters. + */ + static const char s_szPalette[] = " ..`',:;icodxkO08XNWM"; + static const uint32_t s_cchPalette = sizeof(s_szPalette) - 1; + uint32_t const cPixelsWeightPerChar = cxPerChar * cyPerChar * 256; + + /* + * Do the work + */ + uint32_t *pauScanline = (uint32_t *)RTMemTmpAllocZ(sizeof(pauScanline[0]) * cchLine + cchLine + 1); + if (!pauScanline) + return; + char *pszLine = (char *)&pauScanline[cchLine]; + RTCPTRUNION uSrc; + uSrc.pv = pvImage; + if (fInvY) + uSrc.pu8 += (cy - 1) * cbScanline; + uint32_t cyLeft = cy; + uint32_t cyLeftInScanline = cyPerChar; + bool fHitFormatAssert = false; + for (;;) + { + /* + * Process the scanline. This is tedious because of all the + * different formats. We generally ignore alpha, unless it's + * all we've got to work with. + * Color to 8-bit grayscale conversion is done by averaging. + */ +#define CONVERT_SCANLINE(a_RdExpr, a_AddExpr) \ + do { \ + for (uint32_t xSrc = 0, xDst = 0, cxLeftInChar = cxPerChar; xSrc < cx; xSrc++) \ + { \ + a_RdExpr; \ + pauScanline[xDst] += (a_AddExpr) & 0xff; \ + Assert(pauScanline[xDst] <= cPixelsWeightPerChar); \ + if (--cxLeftInChar == 0) \ + { \ + xDst++; \ + cxLeftInChar = cxPerChar; \ + } \ + } \ + } while (0) + + switch (enmFormat) + { + /* Unsigned RGB and super/subsets. */ + case SVGA3D_X8R8G8B8: + case SVGA3D_A8R8G8B8: + CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc], + ( ( u32Tmp & 0xff) /* B */ + + ((u32Tmp >> 8) & 0xff) /* G */ + + ((u32Tmp >> 16) & 0xff) /* R */) / 3); + break; + case SVGA3D_R5G6B5: + CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc], + ( ( u16Tmp & 0x1f) * 8 + + ((u16Tmp >> 5) & 0x3f) * 4 + + ( u16Tmp >> 11) * 8 ) / 3 ); + break; + case SVGA3D_X1R5G5B5: + case SVGA3D_A1R5G5B5: + CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc], + ( ( u16Tmp & 0x1f) * 8 + + ((u16Tmp >> 5) & 0x1f) * 8 + + ((u16Tmp >> 10) & 0x1f) * 8) / 3 ); + break; + case SVGA3D_A4R4G4B4: + CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc], + ( ( u16Tmp & 0xf) * 16 + + ((u16Tmp >> 4) & 0xf) * 16 + + ((u16Tmp >> 8) & 0xf) * 16) / 3 ); + break; + case SVGA3D_A16B16G16R16: + CONVERT_SCANLINE(uint64_t const u64Tmp = uSrc.pu64[xSrc], + ( ((u64Tmp >> 8) & 0xff) /* R */ + + ((u64Tmp >> 24) & 0xff) /* G */ + + ((u64Tmp >> 40) & 0xff) /* B */ ) / 3); + break; + case SVGA3D_A2R10G10B10: + CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc], + ( ( u32Tmp & 0x3ff) /* B */ + + ((u32Tmp >> 10) & 0x3ff) /* G */ + + ((u32Tmp >> 20) & 0x3ff) /* R */ ) / (3 * 4)); + break; + case SVGA3D_G16R16: + CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc], + ( (u32Tmp & 0xffff) /* R */ + + (u32Tmp >> 16 ) /* G */) / 0x200); + break; + + /* Depth. */ + case SVGA3D_Z_D32: + CONVERT_SCANLINE(uint32_t const u32Tmp = ~((uSrc.pu32[xSrc] >> 1) | uSrc.pu32[xSrc]) & UINT32_C(0x44444444), + (( u32Tmp >> (2 - 0)) & RT_BIT_32(0)) + | ((u32Tmp >> ( 6 - 1)) & RT_BIT_32(1)) + | ((u32Tmp >> (10 - 2)) & RT_BIT_32(2)) + | ((u32Tmp >> (14 - 3)) & RT_BIT_32(3)) + | ((u32Tmp >> (18 - 4)) & RT_BIT_32(4)) + | ((u32Tmp >> (22 - 5)) & RT_BIT_32(5)) + | ((u32Tmp >> (26 - 6)) & RT_BIT_32(6)) + | ((u32Tmp >> (30 - 7)) & RT_BIT_32(7)) ); + break; + case SVGA3D_Z_D16: + CONVERT_SCANLINE(uint16_t const u16Tmp = ~uSrc.pu16[xSrc], + ((u16Tmp >> ( 1 - 0)) & RT_BIT_32(0)) + | ((u16Tmp >> ( 3 - 1)) & RT_BIT_32(1)) + | ((u16Tmp >> ( 5 - 2)) & RT_BIT_32(2)) + | ((u16Tmp >> ( 7 - 3)) & RT_BIT_32(3)) + | ((u16Tmp >> ( 9 - 4)) & RT_BIT_32(4)) + | ((u16Tmp >> (11 - 5)) & RT_BIT_32(5)) + | ((u16Tmp >> (13 - 6)) & RT_BIT_32(6)) + | ((u16Tmp >> (15 - 7)) & RT_BIT_32(7)) ); + break; + case SVGA3D_Z_D24S8: + CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc], + ( u32Tmp & 0xff) /* stencile */ + | ((~u32Tmp >> 18) & 0x3f)); + break; + case SVGA3D_Z_D15S1: + CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc], + ( (u16Tmp & 0x01) << 7) /* stencile */ + | ((~u16Tmp >> 8) & 0x7f)); + break; + + /* Pure alpha. */ + case SVGA3D_ALPHA8: + CONVERT_SCANLINE(RT_NOTHING, uSrc.pu8[xSrc]); + break; + + /* Luminance */ + case SVGA3D_LUMINANCE8: + CONVERT_SCANLINE(RT_NOTHING, uSrc.pu8[xSrc]); + break; + case SVGA3D_LUMINANCE4_ALPHA4: + CONVERT_SCANLINE(RT_NOTHING, uSrc.pu8[xSrc] & 0xf0); + break; + case SVGA3D_LUMINANCE16: + CONVERT_SCANLINE(RT_NOTHING, uSrc.pu16[xSrc] >> 8); + break; + case SVGA3D_LUMINANCE8_ALPHA8: + CONVERT_SCANLINE(RT_NOTHING, uSrc.pu16[xSrc] >> 8); + break; + + /* Not supported. */ + case SVGA3D_DXT1: + case SVGA3D_DXT2: + case SVGA3D_DXT3: + case SVGA3D_DXT4: + case SVGA3D_DXT5: + case SVGA3D_BUFFER: + AssertFailedBreak(); + + /* Not considered for implementation yet. */ + case SVGA3D_BUMPU8V8: + case SVGA3D_BUMPL6V5U5: + case SVGA3D_BUMPX8L8V8U8: + case SVGA3D_FORMAT_DEAD1: + case SVGA3D_ARGB_S10E5: + case SVGA3D_ARGB_S23E8: + case SVGA3D_V8U8: + case SVGA3D_Q8W8V8U8: + case SVGA3D_CxV8U8: + case SVGA3D_X8L8V8U8: + case SVGA3D_A2W10V10U10: + case SVGA3D_R_S10E5: + case SVGA3D_R_S23E8: + case SVGA3D_RG_S10E5: + case SVGA3D_RG_S23E8: + case SVGA3D_Z_D24X8: + case SVGA3D_V16U16: + case SVGA3D_UYVY: + case SVGA3D_YUY2: + case SVGA3D_NV12: + case SVGA3D_FORMAT_DEAD2: /* Old SVGA3D_AYUV */ + case SVGA3D_ATI1: + case SVGA3D_ATI2: + case SVGA3D_Z_DF16: + case SVGA3D_Z_DF24: + case SVGA3D_Z_D24S8_INT: + if (!fHitFormatAssert) + { + AssertMsgFailed(("%s is not implemented\n", vmsvgaLookupEnum((int)enmFormat, &g_SVGA3dSurfaceFormat2String))); + fHitFormatAssert = true; + } + RT_FALL_THRU(); + default: + /* Lazy programmer fallbacks. */ + if (cbSrcPixel == 4) + CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc], + ( ( u32Tmp & 0xff) + + ((u32Tmp >> 8) & 0xff) + + ((u32Tmp >> 16) & 0xff) + + ((u32Tmp >> 24) & 0xff) ) / 4); + else if (cbSrcPixel == 3) + CONVERT_SCANLINE(RT_NOTHING, + ( (uint32_t)uSrc.pu8[xSrc * 4] + + (uint32_t)uSrc.pu8[xSrc * 4 + 1] + + (uint32_t)uSrc.pu8[xSrc * 4 + 2] ) / 3); + else if (cbSrcPixel == 2) + CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc], + ( ( u16Tmp & 0xf) + + ((u16Tmp >> 4) & 0xf) + + ((u16Tmp >> 8) & 0xf) + + ((u16Tmp >> 12) & 0xf) ) * 4 /* mul 16 div 4 */ ); + else if (cbSrcPixel == 1) + CONVERT_SCANLINE(RT_NOTHING, uSrc.pu8[xSrc]); + else + AssertFailed(); + break; + + } + + /* + * Print we've reached the end of a block in y direction or if we're at + * the end of the image. + */ + cyLeft--; + if (--cyLeftInScanline == 0 || cyLeft == 0) + { + for (uint32_t i = 0; i < cchLine; i++) + { + uint32_t off = pauScanline[i] * s_cchPalette / cPixelsWeightPerChar; Assert(off < s_cchPalette); + pszLine[i] = s_szPalette[off < sizeof(s_szPalette) - 1 ? off : sizeof(s_szPalette) - 1]; + } + pszLine[cchLine] = '\0'; + pfnPrintLine(pszLine, pvUser); + + if (!cyLeft) + break; + cyLeftInScanline = cyPerChar; + RT_BZERO(pauScanline, sizeof(pauScanline[0]) * cchLine); + } + + /* + * Advance. + */ + if (!fInvY) + uSrc.pu8 += cbScanline; + else + uSrc.pu8 -= cbScanline; + } +} + + + +/** + * Formats a SVGA3dRenderState structure as a string. + * + * @returns pszBuffer. + * @param pszBuffer Output string buffer. + * @param cbBuffer Size of output buffer. + * @param pRenderState The SVGA3d render state to format. + */ +char *vmsvga3dFormatRenderState(char *pszBuffer, size_t cbBuffer, SVGA3dRenderState const *pRenderState) +{ + /* + * List of render state names with type prefix. + * + * First char in the name is a type indicator: + * - '*' = requires special handling. + * - 'f' = SVGA3dbool + * - 'd' = uint32_t + * - 'r' = float + * - 'b' = SVGA3dBlendOp + * - 'c' = SVGA3dColor, SVGA3dColorMask + * - 'e' = SVGA3dBlendEquation + * - 'm' = SVGA3dColorMask + * - 'p' = SVGA3dCmpFunc + * - 's' = SVGA3dStencilOp + * - 'v' = SVGA3dVertexMaterial + * - 'w' = SVGA3dWrapFlags + */ + static const char * const s_apszRenderStateNamesAndType[] = + { + "*" "INVALID", /* invalid */ + "f" "ZENABLE", /* SVGA3dBool */ + "f" "ZWRITEENABLE", /* SVGA3dBool */ + "f" "ALPHATESTENABLE", /* SVGA3dBool */ + "f" "DITHERENABLE", /* SVGA3dBool */ + "f" "BLENDENABLE", /* SVGA3dBool */ + "f" "FOGENABLE", /* SVGA3dBool */ + "f" "SPECULARENABLE", /* SVGA3dBool */ + "f" "STENCILENABLE", /* SVGA3dBool */ + "f" "LIGHTINGENABLE", /* SVGA3dBool */ + "f" "NORMALIZENORMALS", /* SVGA3dBool */ + "f" "POINTSPRITEENABLE", /* SVGA3dBool */ + "f" "POINTSCALEENABLE", /* SVGA3dBool */ + "x" "STENCILREF", /* uint32_t */ + "x" "STENCILMASK", /* uint32_t */ + "x" "STENCILWRITEMASK", /* uint32_t */ + "r" "FOGSTART", /* float */ + "r" "FOGEND", /* float */ + "r" "FOGDENSITY", /* float */ + "r" "POINTSIZE", /* float */ + "r" "POINTSIZEMIN", /* float */ + "r" "POINTSIZEMAX", /* float */ + "r" "POINTSCALE_A", /* float */ + "r" "POINTSCALE_B", /* float */ + "r" "POINTSCALE_C", /* float */ + "c" "FOGCOLOR", /* SVGA3dColor */ + "c" "AMBIENT", /* SVGA3dColor */ + "*" "CLIPPLANEENABLE", /* SVGA3dClipPlanes */ + "*" "FOGMODE", /* SVGA3dFogMode */ + "*" "FILLMODE", /* SVGA3dFillMode */ + "*" "SHADEMODE", /* SVGA3dShadeMode */ + "*" "LINEPATTERN", /* SVGA3dLinePattern */ + "b" "SRCBLEND", /* SVGA3dBlendOp */ + "b" "DSTBLEND", /* SVGA3dBlendOp */ + "e" "BLENDEQUATION", /* SVGA3dBlendEquation */ + "*" "CULLMODE", /* SVGA3dFace */ + "p" "ZFUNC", /* SVGA3dCmpFunc */ + "p" "ALPHAFUNC", /* SVGA3dCmpFunc */ + "p" "STENCILFUNC", /* SVGA3dCmpFunc */ + "s" "STENCILFAIL", /* SVGA3dStencilOp */ + "s" "STENCILZFAIL", /* SVGA3dStencilOp */ + "s" "STENCILPASS", /* SVGA3dStencilOp */ + "r" "ALPHAREF", /* float */ + "*" "FRONTWINDING", /* SVGA3dFrontWinding */ + "*" "COORDINATETYPE", /* SVGA3dCoordinateType */ + "r" "ZBIAS", /* float */ + "f" "RANGEFOGENABLE", /* SVGA3dBool */ + "c" "COLORWRITEENABLE", /* SVGA3dColorMask */ + "f" "VERTEXMATERIALENABLE", /* SVGA3dBool */ + "v" "DIFFUSEMATERIALSOURCE", /* SVGA3dVertexMaterial */ + "v" "SPECULARMATERIALSOURCE", /* SVGA3dVertexMaterial */ + "v" "AMBIENTMATERIALSOURCE", /* SVGA3dVertexMaterial */ + "v" "EMISSIVEMATERIALSOURCE", /* SVGA3dVertexMaterial */ + "c" "TEXTUREFACTOR", /* SVGA3dColor */ + "f" "LOCALVIEWER", /* SVGA3dBool */ + "f" "SCISSORTESTENABLE", /* SVGA3dBool */ + "c" "BLENDCOLOR", /* SVGA3dColor */ + "f" "STENCILENABLE2SIDED", /* SVGA3dBool */ + "p" "CCWSTENCILFUNC", /* SVGA3dCmpFunc */ + "s" "CCWSTENCILFAIL", /* SVGA3dStencilOp */ + "s" "CCWSTENCILZFAIL", /* SVGA3dStencilOp */ + "s" "CCWSTENCILPASS", /* SVGA3dStencilOp */ + "*" "VERTEXBLEND", /* SVGA3dVertexBlendFlags */ + "r" "SLOPESCALEDEPTHBIAS", /* float */ + "r" "DEPTHBIAS", /* float */ + "r" "OUTPUTGAMMA", /* float */ + "f" "ZVISIBLE", /* SVGA3dBool */ + "f" "LASTPIXEL", /* SVGA3dBool */ + "f" "CLIPPING", /* SVGA3dBool */ + "w" "WRAP0", /* SVGA3dWrapFlags */ + "w" "WRAP1", /* SVGA3dWrapFlags */ + "w" "WRAP2", /* SVGA3dWrapFlags */ + "w" "WRAP3", /* SVGA3dWrapFlags */ + "w" "WRAP4", /* SVGA3dWrapFlags */ + "w" "WRAP5", /* SVGA3dWrapFlags */ + "w" "WRAP6", /* SVGA3dWrapFlags */ + "w" "WRAP7", /* SVGA3dWrapFlags */ + "w" "WRAP8", /* SVGA3dWrapFlags */ + "w" "WRAP9", /* SVGA3dWrapFlags */ + "w" "WRAP10", /* SVGA3dWrapFlags */ + "w" "WRAP11", /* SVGA3dWrapFlags */ + "w" "WRAP12", /* SVGA3dWrapFlags */ + "w" "WRAP13", /* SVGA3dWrapFlags */ + "w" "WRAP14", /* SVGA3dWrapFlags */ + "w" "WRAP15", /* SVGA3dWrapFlags */ + "f" "MULTISAMPLEANTIALIAS", /* SVGA3dBool */ + "x" "MULTISAMPLEMASK", /* uint32_t */ + "f" "INDEXEDVERTEXBLENDENABLE", /* SVGA3dBool */ + "r" "TWEENFACTOR", /* float */ + "f" "ANTIALIASEDLINEENABLE", /* SVGA3dBool */ + "c" "COLORWRITEENABLE1", /* SVGA3dColorMask */ + "c" "COLORWRITEENABLE2", /* SVGA3dColorMask */ + "c" "COLORWRITEENABLE3", /* SVGA3dColorMask */ + "f" "SEPARATEALPHABLENDENABLE", /* SVGA3dBool */ + "b" "SRCBLENDALPHA", /* SVGA3dBlendOp */ + "b" "DSTBLENDALPHA", /* SVGA3dBlendOp */ + "e" "BLENDEQUATIONALPHA", /* SVGA3dBlendEquation */ + "*" "TRANSPARENCYANTIALIAS", /* SVGA3dTransparencyAntialiasType */ + "r" "LINEWIDTH", /* float */ + }; + + uint32_t iState = pRenderState->state; + if (iState != SVGA3D_RS_INVALID) + { + if (iState < RT_ELEMENTS(s_apszRenderStateNamesAndType)) + { + const char *pszName = s_apszRenderStateNamesAndType[iState]; + char const chType = *pszName++; + + union + { + uint32_t u; + float r; + SVGA3dColorMask Color; + } uValue; + uValue.u = pRenderState->uintValue; + + switch (chType) + { + case 'f': + if (uValue.u == 0) + RTStrPrintf(pszBuffer, cbBuffer, "%s = false", pszName); + else if (uValue.u == 1) + RTStrPrintf(pszBuffer, cbBuffer, "%s = true", pszName); + else + RTStrPrintf(pszBuffer, cbBuffer, "%s = true (%#x)", pszName, uValue.u); + break; + case 'x': + RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x (%d)", pszName, uValue.u, uValue.u); + break; + case 'r': + RTStrPrintf(pszBuffer, cbBuffer, "%s = %d.%06u (%#x)", + pszName, (int)uValue.r, (unsigned)(uValue.r * 1000000) % 1000000U, uValue.u); + break; + case 'c': //SVGA3dColor, SVGA3dColorMask + RTStrPrintf(pszBuffer, cbBuffer, "%s = RGBA(%d,%d,%d,%d) (%#x)", pszName, + uValue.Color.red, uValue.Color.green, uValue.Color.blue, uValue.Color.alpha, uValue.u); + break; + case 'w': //SVGA3dWrapFlags + RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x%s", pszName, uValue.u, + uValue.u <= SVGA3D_WRAPCOORD_ALL ? " (out of bounds" : ""); + break; + default: + AssertFailed(); RT_FALL_THRU(); + case 'b': //SVGA3dBlendOp + case 'e': //SVGA3dBlendEquation + case 'p': //SVGA3dCmpFunc + case 's': //SVGA3dStencilOp + case 'v': //SVGA3dVertexMaterial + case '*': + RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x", pszName, uValue.u); + break; + } + } + else + RTStrPrintf(pszBuffer, cbBuffer, "UNKNOWN_%d_%#x = %#x", iState, iState, pRenderState->uintValue); + } + else + RTStrPrintf(pszBuffer, cbBuffer, "INVALID"); + return pszBuffer; +} + + +/** + * Formats a SVGA3dTextureState structure as a string. + * + * @returns pszBuffer. + * @param pszBuffer Output string buffer. + * @param cbBuffer Size of output buffer. + * @param pTextureState The SVGA3d texture state to format. + */ +char *vmsvga3dFormatTextureState(char *pszBuffer, size_t cbBuffer, SVGA3dTextureState const *pTextureState) +{ + static const char * const s_apszTextureStateNamesAndType[] = + { + "*" "INVALID", /* invalid */ + "x" "BIND_TEXTURE", /* SVGA3dSurfaceId */ + "m" "COLOROP", /* SVGA3dTextureCombiner */ + "a" "COLORARG1", /* SVGA3dTextureArgData */ + "a" "COLORARG2", /* SVGA3dTextureArgData */ + "m" "ALPHAOP", /* SVGA3dTextureCombiner */ + "a" "ALPHAARG1", /* SVGA3dTextureArgData */ + "a" "ALPHAARG2", /* SVGA3dTextureArgData */ + "e" "ADDRESSU", /* SVGA3dTextureAddress */ + "e" "ADDRESSV", /* SVGA3dTextureAddress */ + "l" "MIPFILTER", /* SVGA3dTextureFilter */ + "l" "MAGFILTER", /* SVGA3dTextureFilter */ + "m" "MINFILTER", /* SVGA3dTextureFilter */ + "c" "BORDERCOLOR", /* SVGA3dColor */ + "r" "TEXCOORDINDEX", /* uint32_t */ + "t" "TEXTURETRANSFORMFLAGS", /* SVGA3dTexTransformFlags */ + "g" "TEXCOORDGEN", /* SVGA3dTextureCoordGen */ + "r" "BUMPENVMAT00", /* float */ + "r" "BUMPENVMAT01", /* float */ + "r" "BUMPENVMAT10", /* float */ + "r" "BUMPENVMAT11", /* float */ + "x" "TEXTURE_MIPMAP_LEVEL", /* uint32_t */ + "r" "TEXTURE_LOD_BIAS", /* float */ + "x" "TEXTURE_ANISOTROPIC_LEVEL", /* uint32_t */ + "e" "ADDRESSW", /* SVGA3dTextureAddress */ + "r" "GAMMA", /* float */ + "r" "BUMPENVLSCALE", /* float */ + "r" "BUMPENVLOFFSET", /* float */ + "a" "COLORARG0", /* SVGA3dTextureArgData */ + "a" "ALPHAARG0" /* SVGA3dTextureArgData */ + }; + + /* + * Format the stage first. + */ + char *pszRet = pszBuffer; + size_t cchPrefix = RTStrPrintf(pszBuffer, cbBuffer, "[%u] ", pTextureState->stage); + if (cchPrefix < cbBuffer) + { + cbBuffer -= cchPrefix; + pszBuffer += cchPrefix; + } + else + cbBuffer = 0; + + /* + * Format the name and value. + */ + uint32_t iName = pTextureState->name; + if (iName != SVGA3D_TS_INVALID) + { + if (iName < RT_ELEMENTS(s_apszTextureStateNamesAndType)) + { + const char *pszName = s_apszTextureStateNamesAndType[iName]; + char chType = *pszName++; + + union + { + uint32_t u; + float r; + SVGA3dColorMask Color; + } uValue; + uValue.u = pTextureState->value; + + switch (chType) + { + case 'x': + RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x (%d)", pszName, uValue.u, uValue.u); + break; + + case 'r': + RTStrPrintf(pszBuffer, cbBuffer, "%s = %d.%06u (%#x)", + pszName, (int)uValue.r, (unsigned)(uValue.r * 1000000) % 1000000U, uValue.u); + break; + + case 'a': //SVGA3dTextureArgData + { + static const char * const s_apszValues[] = + { + "INVALID", "CONSTANT", "PREVIOUS", "DIFFUSE", "TEXTURE", "SPECULAR" + }; + vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u, + "SVGA3D_TA_", s_apszValues, RT_ELEMENTS(s_apszValues)); + break; + } + + case 'c': //SVGA3dColor, SVGA3dColorMask + RTStrPrintf(pszBuffer, cbBuffer, "%s = RGBA(%d,%d,%d,%d) (%#x)", pszName, + uValue.Color.red, uValue.Color.green, uValue.Color.blue, uValue.Color.alpha, uValue.u); + break; + + case 'e': //SVGA3dTextureAddress + { + static const char * const s_apszValues[] = + { + "INVALID", "WRAP", "MIRROR", "CLAMP", "BORDER", "MIRRORONCE", "EDGE", + }; + vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u, + "SVGA3D_TEX_ADDRESS_", s_apszValues, RT_ELEMENTS(s_apszValues)); + break; + } + + case 'l': //SVGA3dTextureFilter + { + static const char * const s_apszValues[] = + { + "NONE", "NEAREST", "LINEAR", "ANISOTROPIC", "FLATCUBIC", "GAUSSIANCUBIC", "PYRAMIDALQUAD", "GAUSSIANQUAD", + }; + vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u, + "SVGA3D_TEX_FILTER_", s_apszValues, RT_ELEMENTS(s_apszValues)); + break; + } + + case 'g': //SVGA3dTextureCoordGen + { + static const char * const s_apszValues[] = + { + "OFF", "EYE_POSITION", "EYE_NORMAL", "REFLECTIONVECTOR", "SPHERE", + }; + vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u, + "SVGA3D_TEXCOORD_GEN_", s_apszValues, RT_ELEMENTS(s_apszValues)); + break; + } + + case 'm': //SVGA3dTextureCombiner + { + static const char * const s_apszValues[] = + { + "INVALID", "DISABLE", "SELECTARG1", "SELECTARG2", "MODULATE", "ADD", "ADDSIGNED", "SUBTRACT", + "BLENDTEXTUREALPHA", "BLENDDIFFUSEALPHA", "BLENDCURRENTALPHA", "BLENDFACTORALPHA", "MODULATE2X", + "MODULATE4X", "DSDT", "DOTPRODUCT3", "BLENDTEXTUREALPHAPM", "ADDSIGNED2X", "ADDSMOOTH", "PREMODULATE", + "MODULATEALPHA_ADDCOLOR", "MODULATECOLOR_ADDALPHA", "MODULATEINVALPHA_ADDCOLOR", + "MODULATEINVCOLOR_ADDALPHA", "BUMPENVMAPLUMINANCE", "MULTIPLYADD", "LERP", + }; + vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u, + "SVGA3D_TC_", s_apszValues, RT_ELEMENTS(s_apszValues)); + break; + } + + default: + AssertFailed(); + RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x\n", pszName, uValue.u); + break; + } + } + else + RTStrPrintf(pszBuffer, cbBuffer, "UNKNOWN_%d_%#x = %#x\n", iName, iName, pTextureState->value); + } + else + RTStrPrintf(pszBuffer, cbBuffer, "INVALID"); + return pszRet; +} + + + +static const char * const g_apszTransformTypes[] = +{ + "SVGA3D_TRANSFORM_INVALID", + "SVGA3D_TRANSFORM_WORLD", + "SVGA3D_TRANSFORM_VIEW", + "SVGA3D_TRANSFORM_PROJECTION", + "SVGA3D_TRANSFORM_TEXTURE0", + "SVGA3D_TRANSFORM_TEXTURE1", + "SVGA3D_TRANSFORM_TEXTURE2", + "SVGA3D_TRANSFORM_TEXTURE3", + "SVGA3D_TRANSFORM_TEXTURE4", + "SVGA3D_TRANSFORM_TEXTURE5", + "SVGA3D_TRANSFORM_TEXTURE6", + "SVGA3D_TRANSFORM_TEXTURE7", + "SVGA3D_TRANSFORM_WORLD1", + "SVGA3D_TRANSFORM_WORLD2", + "SVGA3D_TRANSFORM_WORLD3", +}; + +static const char * const g_apszFaces[] = +{ + "SVGA3D_FACE_INVALID", + "SVGA3D_FACE_NONE", + "SVGA3D_FACE_FRONT", + "SVGA3D_FACE_BACK", + "SVGA3D_FACE_FRONT_BACK", +}; + +static const char * const g_apszLightTypes[] = +{ + "SVGA3D_LIGHTTYPE_INVALID", + "SVGA3D_LIGHTTYPE_POINT", + "SVGA3D_LIGHTTYPE_SPOT1", + "SVGA3D_LIGHTTYPE_SPOT2", + "SVGA3D_LIGHTTYPE_DIRECTIONAL", +}; + +static const char * const g_apszRenderTargets[] = +{ + "SVGA3D_RT_DEPTH", + "SVGA3D_RT_STENCIL", + "SVGA3D_RT_COLOR0", + "SVGA3D_RT_COLOR1", + "SVGA3D_RT_COLOR2", + "SVGA3D_RT_COLOR3", + "SVGA3D_RT_COLOR4", + "SVGA3D_RT_COLOR5", + "SVGA3D_RT_COLOR6", + "SVGA3D_RT_COLOR7", +}; + +static void vmsvga3dInfoContextWorkerOne(PCDBGFINFOHLP pHlp, PVMSVGA3DCONTEXT pContext, bool fVerbose) +{ + RT_NOREF(fVerbose); + char szTmp[128]; + + pHlp->pfnPrintf(pHlp, "*** VMSVGA 3d context %#x (%d) ***\n", pContext->id, pContext->id); +#ifdef RT_OS_WINDOWS + pHlp->pfnPrintf(pHlp, "hwnd: %p\n", pContext->hwnd); + if (fVerbose) + vmsvga3dInfoHostWindow(pHlp, (uintptr_t)pContext->hwnd); +# ifdef VMSVGA3D_DIRECT3D + pHlp->pfnPrintf(pHlp, "pDevice: %p\n", pContext->pDevice); +# else + pHlp->pfnPrintf(pHlp, "hdc: %p\n", pContext->hdc); + pHlp->pfnPrintf(pHlp, "hglrc: %p\n", pContext->hglrc); +# endif + +#elif defined(RT_OS_DARWIN) + pHlp->pfnPrintf(pHlp, "cocoaView: %p\n", pContext->cocoaView); + if (pContext->cocoaView) + vmsvga3dInfoHostWindow(pHlp, (uintptr_t)pContext->cocoaView); + pHlp->pfnPrintf(pHlp, "cocoaContext: %p\n", pContext->cocoaContext); + if (pContext->fOtherProfile) + pHlp->pfnPrintf(pHlp, "fOtherProfile: true\n"); + +#else + pHlp->pfnPrintf(pHlp, "window: %p\n", pContext->window); + if (pContext->window) + vmsvga3dInfoHostWindow(pHlp, (uintptr_t)pContext->window); + pHlp->pfnPrintf(pHlp, "glxContext: %p\n", pContext->glxContext); + +#endif + + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); i++) + if (pContext->aSidActiveTextures[i] != SVGA3D_INVALID_ID) + pHlp->pfnPrintf(pHlp, "aSidActiveTextures[%u]: %#x\n", i, pContext->aSidActiveTextures[i]); + + pHlp->pfnPrintf(pHlp, "fUpdateFlags: %#x\n", pContext->state.u32UpdateFlags); + + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderState); i++) + if (pContext->state.aRenderState[i].state != SVGA3D_RS_INVALID) + pHlp->pfnPrintf(pHlp, "aRenderState[%3d]: %s\n", i, + vmsvga3dFormatRenderState(szTmp, sizeof(szTmp), &pContext->state.aRenderState[i])); + + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aTextureStates); i++) + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[i]); j++) + if (pContext->state.aTextureStates[i][j].name != SVGA3D_TS_INVALID) + pHlp->pfnPrintf(pHlp, "aTextureStates[%3d][%3d]: %s\n", i, j, + vmsvga3dFormatTextureState(szTmp, sizeof(szTmp), &pContext->state.aTextureStates[i][j])); + + AssertCompile(RT_ELEMENTS(g_apszTransformTypes) == SVGA3D_TRANSFORM_MAX); + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aTransformState); i++) + if (pContext->state.aTransformState[i].fValid) + { + pHlp->pfnPrintf(pHlp, "aTransformState[%s(%u)]:\n", g_apszTransformTypes[i], i); + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTransformState[i].matrix); j++) + pHlp->pfnPrintf(pHlp, + (j % 4) == 0 ? " [ " FLOAT_FMT_STR : (j % 4) < 3 ? ", " FLOAT_FMT_STR : ", " FLOAT_FMT_STR "]\n", + FLOAT_FMT_ARGS(pContext->state.aTransformState[i].matrix[j])); + } + + AssertCompile(RT_ELEMENTS(g_apszFaces) == SVGA3D_FACE_MAX); + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aMaterial); i++) + if (pContext->state.aMaterial[i].fValid) + { + pHlp->pfnPrintf(pHlp, "aTransformState[%s(%u)]: shininess=" FLOAT_FMT_STR "\n", + g_apszFaces[i], i, FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.shininess)); + pHlp->pfnPrintf(pHlp, " diffuse =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.diffuse[0]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.diffuse[1]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.diffuse[2]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.diffuse[3])); + pHlp->pfnPrintf(pHlp, " ambient =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.ambient[0]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.ambient[1]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.ambient[2]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.ambient[3])); + pHlp->pfnPrintf(pHlp, " specular=[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.specular[0]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.specular[1]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.specular[2]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.specular[3])); + pHlp->pfnPrintf(pHlp, " emissive=[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.emissive[0]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.emissive[1]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.emissive[2]), + FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.emissive[3])); + } + + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aClipPlane); i++) + if (pContext->state.aClipPlane[i].fValid) + pHlp->pfnPrintf(pHlp, "aClipPlane[%#04x]: [ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + i, + FLOAT_FMT_ARGS(pContext->state.aClipPlane[i].plane[0]), + FLOAT_FMT_ARGS(pContext->state.aClipPlane[i].plane[1]), + FLOAT_FMT_ARGS(pContext->state.aClipPlane[i].plane[2]), + FLOAT_FMT_ARGS(pContext->state.aClipPlane[i].plane[3])); + + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aLightData); i++) + if (pContext->state.aLightData[i].fValidData) + { + pHlp->pfnPrintf(pHlp, "aLightData[%#04x]: enabled=%RTbool inWorldSpace=%RTbool type=%s(%u)\n", + i, + pContext->state.aLightData[i].fEnabled, + pContext->state.aLightData[i].data.inWorldSpace, + (uint32_t)pContext->state.aLightData[i].data.type < RT_ELEMENTS(g_apszLightTypes) + ? g_apszLightTypes[pContext->state.aLightData[i].data.type] : "UNKNOWN", + pContext->state.aLightData[i].data.type); + pHlp->pfnPrintf(pHlp, " diffuse =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.diffuse[0]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.diffuse[1]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.diffuse[2]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.diffuse[3])); + pHlp->pfnPrintf(pHlp, " specular =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.specular[0]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.specular[1]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.specular[2]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.specular[3])); + pHlp->pfnPrintf(pHlp, " ambient =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.ambient[0]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.ambient[1]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.ambient[2]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.ambient[3])); + pHlp->pfnPrintf(pHlp, " position =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.position[0]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.position[1]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.position[2]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.position[3])); + pHlp->pfnPrintf(pHlp, " direction=[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n", + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.direction[0]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.direction[1]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.direction[2]), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.direction[3])); + pHlp->pfnPrintf(pHlp, " range=" FLOAT_FMT_STR " falloff=" FLOAT_FMT_STR "\n", + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.range), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.falloff)); + pHlp->pfnPrintf(pHlp, " attenuation0=" FLOAT_FMT_STR " attenuation1=" FLOAT_FMT_STR " attenuation2=" FLOAT_FMT_STR "\n", + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.attenuation0), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.attenuation1), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.attenuation2)); + pHlp->pfnPrintf(pHlp, " theta=" FLOAT_FMT_STR " phi=" FLOAT_FMT_STR "\n", + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.theta), + FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.phi)); + } + + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); i++) + if (pContext->state.aRenderTargets[i] != SVGA3D_INVALID_ID) + pHlp->pfnPrintf(pHlp, "aRenderTargets[%s/%u] = %#x (%d)\n", + i < RT_ELEMENTS(g_apszRenderTargets) ? g_apszRenderTargets[i] : "UNKNOWN", i, + pContext->state.aRenderTargets[i], pContext->state.aRenderTargets[i]); + + pHlp->pfnPrintf(pHlp, "RectScissor: (x,y,cx,cy)=(%u,%u,%u,%u)\n", + pContext->state.RectViewPort.x, pContext->state.RectViewPort.y, + pContext->state.RectViewPort.w, pContext->state.RectViewPort.h); + pHlp->pfnPrintf(pHlp, "zRange: (min,max)=(" FLOAT_FMT_STR ", " FLOAT_FMT_STR ")\n", + FLOAT_FMT_ARGS(pContext->state.zRange.min), + FLOAT_FMT_ARGS(pContext->state.zRange.max)); + pHlp->pfnPrintf(pHlp, "fUpdateFlags: %#x\n", pContext->state.u32UpdateFlags); + pHlp->pfnPrintf(pHlp, "shidPixel: %#x (%d)\n", pContext->state.shidPixel, pContext->state.shidPixel); + pHlp->pfnPrintf(pHlp, "shidVertex: %#x (%d)\n", pContext->state.shidVertex, pContext->state.shidVertex); + + for (uint32_t iWhich = 0; iWhich < 2; iWhich++) + { + uint32_t cConsts = iWhich == 0 ? pContext->state.cPixelShaderConst : pContext->state.cVertexShaderConst; + PVMSVGASHADERCONST paConsts = iWhich == 0 ? pContext->state.paPixelShaderConst : pContext->state.paVertexShaderConst; + const char *pszName = iWhich ? "paPixelShaderConst" : "paVertexShaderConst"; + + for (uint32_t i = 0; i < cConsts; i++) + if (paConsts[i].fValid) + { + if (paConsts[i].ctype == SVGA3D_CONST_TYPE_FLOAT) + pHlp->pfnPrintf(pHlp, "%s[%#x(%u)] = [" FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR "] ctype=FLOAT\n", + pszName, i, i, + FLOAT_FMT_ARGS(*(float *)&paConsts[i].value[0]), FLOAT_FMT_ARGS(*(float *)&paConsts[i].value[1]), + FLOAT_FMT_ARGS(*(float *)&paConsts[i].value[2]), FLOAT_FMT_ARGS(*(float *)&paConsts[i].value[3])); + else + pHlp->pfnPrintf(pHlp, "%s[%#x(%u)] = [%#x, %#x, %#x, %#x] ctype=%s\n", + pszName, i, i, + paConsts[i].value[0], paConsts[i].value[1], + paConsts[i].value[2], paConsts[i].value[3], + paConsts[i].ctype == SVGA3D_CONST_TYPE_INT ? "INT" + : paConsts[i].ctype == SVGA3D_CONST_TYPE_BOOL ? "BOOL" : "UNKNOWN"); + } + } + + for (uint32_t iWhich = 0; iWhich < 2; iWhich++) + { + uint32_t cShaders = iWhich == 0 ? pContext->cPixelShaders : pContext->cVertexShaders; + PVMSVGA3DSHADER paShaders = iWhich == 0 ? pContext->paPixelShader : pContext->paVertexShader; + const char *pszName = iWhich == 0 ? "paPixelShaders" : "paVertexShaders"; + for (uint32_t i = 0; i < cShaders; i++) + if (paShaders[i].id == i) + { + pHlp->pfnPrintf(pHlp, "%s[%u]: id=%#x cid=%#x type=%s(%d) cbData=%#x pvData=%p\n", + pszName, i, + paShaders[i].id, + paShaders[i].cid, + paShaders[i].type == SVGA3D_SHADERTYPE_VS ? "VS" + : paShaders[i].type == SVGA3D_SHADERTYPE_PS ? "PS" : "UNKNOWN", + paShaders[i].type, + paShaders[i].cbData, + paShaders[i].pShaderProgram); + } + } +} + + +void vmsvga3dInfoContextWorker(PVGASTATECC pThisCC, PCDBGFINFOHLP pHlp, uint32_t cid, bool fVerbose) +{ + /* Warning! This code is currently racing papContexts reallocation! */ + /* Warning! This code is currently racing papContexts reallocation! */ + /* Warning! This code is currently racing papContexts reallocation! */ + VMSVGA3DSTATE volatile *pState = pThisCC->svga.p3dState; + if (pState) + { + /* + * Deal with a specific request first. + */ + if (cid != UINT32_MAX) + { + if (cid < pState->cContexts) + { + PVMSVGA3DCONTEXT pContext = pState->papContexts[cid]; + if (pContext && pContext->id == cid) + { + vmsvga3dInfoContextWorkerOne(pHlp, pContext, fVerbose); + return; + } + } +#ifdef VMSVGA3D_OPENGL + else if ( cid == VMSVGA3D_SHARED_CTX_ID + && pState->SharedCtx.id == cid) + { + vmsvga3dInfoContextWorkerOne(pHlp, &((PVMSVGA3DSTATE)pState)->SharedCtx, fVerbose); + return; + } +#endif + pHlp->pfnPrintf(pHlp, "Context ID %#x not found.\n", cid); + } + else + { +#ifdef VMSVGA3D_OPENGL + /* + * Dump the shared context. + */ + if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) + { + pHlp->pfnPrintf(pHlp, "Shared context:\n"); + vmsvga3dInfoContextWorkerOne(pHlp, &((PVMSVGA3DSTATE)pState)->SharedCtx, fVerbose); + } +#endif + + /* + * Dump the per-screen contexts. + */ + /** @todo multi screen */ + + /* + * Dump all. + */ + uint32_t cContexts = pState->cContexts; + pHlp->pfnPrintf(pHlp, "cContexts=%d\n", cContexts); + for (cid = 0; cid < cContexts; cid++) + { + PVMSVGA3DCONTEXT pContext = pState->papContexts[cid]; + if (pContext && pContext->id == cid) + { + pHlp->pfnPrintf(pHlp, "\n"); + vmsvga3dInfoContextWorkerOne(pHlp, pContext, fVerbose); + } + } + } + } +} + + +#ifdef VMSVGA3D_DIRECT3D +/** + * Release all shared surface objects. + */ +static DECLCALLBACK(int) vmsvga3dInfoSharedObjectCallback(PAVLU32NODECORE pNode, void *pvUser) +{ + PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)pNode; + PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser; + + pHlp->pfnPrintf(pHlp, "Shared surface: %#x pv=%p\n", pSharedSurface->Core.Key, pSharedSurface->u.pCubeTexture); + + return 0; +} +#endif /* VMSVGA3D_DIRECT3D */ + +static int vmsvga3dInfoBmpWrite(const char *pszFilename, const void *pvBits, int w, int h, uint32_t cbPixel, uint32_t u32Mask) +{ + if ( cbPixel != 4 + && cbPixel != 2 + && cbPixel != 1) + return VERR_NOT_SUPPORTED; + + /* Always write BGRX bitmap for now. */ + const int cbBitmap = w * h * 4; + + FILE *f = fopen(pszFilename, "wb"); + if (!f) + return VERR_FILE_NOT_FOUND; + +#ifdef RT_OS_WINDOWS + if (cbPixel == 4) + { + BMPFILEHDR fileHdr; + RT_ZERO(fileHdr); + fileHdr.uType = BMP_HDR_MAGIC; + fileHdr.cbFileSize = sizeof(fileHdr) + sizeof(BITMAPV4HEADER) + cbBitmap; + fileHdr.offBits = sizeof(fileHdr) + sizeof(BITMAPV4HEADER); + + BITMAPV4HEADER hdrV4; + RT_ZERO(hdrV4); + hdrV4.bV4Size = sizeof(hdrV4); + hdrV4.bV4Width = w; + hdrV4.bV4Height = -h; + hdrV4.bV4Planes = 1; + hdrV4.bV4BitCount = 32; + hdrV4.bV4V4Compression = BI_BITFIELDS; + hdrV4.bV4SizeImage = cbBitmap; + hdrV4.bV4XPelsPerMeter = 2835; + hdrV4.bV4YPelsPerMeter = 2835; + // hdrV4.bV4ClrUsed = 0; + // hdrV4.bV4ClrImportant = 0; + hdrV4.bV4RedMask = 0x00ff0000; + hdrV4.bV4GreenMask = 0x0000ff00; + hdrV4.bV4BlueMask = 0x000000ff; + hdrV4.bV4AlphaMask = 0xff000000; + hdrV4.bV4CSType = LCS_WINDOWS_COLOR_SPACE; + // hdrV4.bV4Endpoints = {0}; + // hdrV4.bV4GammaRed = 0; + // hdrV4.bV4GammaGreen = 0; + // hdrV4.bV4GammaBlue = 0; + + fwrite(&fileHdr, 1, sizeof(fileHdr), f); + fwrite(&hdrV4, 1, sizeof(hdrV4), f); + } + else +#endif + { + BMPFILEHDR fileHdr; + RT_ZERO(fileHdr); + fileHdr.uType = BMP_HDR_MAGIC; + fileHdr.cbFileSize = sizeof(BMPFILEHDR) + sizeof(BMPWIN3XINFOHDR) + cbBitmap; + fileHdr.offBits = sizeof(BMPFILEHDR) + sizeof(BMPWIN3XINFOHDR); + + BMPWIN3XINFOHDR coreHdr; + RT_ZERO(coreHdr); + coreHdr.cbSize = sizeof(coreHdr); + coreHdr.uWidth = w; + coreHdr.uHeight = -h; + coreHdr.cPlanes = 1; + coreHdr.cBits = 32; + coreHdr.cbSizeImage = cbBitmap; + + fwrite(&fileHdr, 1, sizeof(fileHdr), f); + fwrite(&coreHdr, 1, sizeof(coreHdr), f); + } + + if (cbPixel == 4) + { + const uint32_t *s = (uint32_t *)pvBits; + int i; + for (i = 0; i < w * h; ++i) + { + const uint32_t u32 = *s++; + uint32_t u = u32 & u32Mask; + fwrite(&u, 1, 4, f); + } + } + else if (cbPixel == 2) + { + const uint16_t *s = (uint16_t *)pvBits; + int i; + for (i = 0; i < w * h; ++i) + { + const uint16_t u16 = *s++; + uint32_t u32 = u16; + uint32_t u = u32 & u32Mask; + fwrite(&u, 1, 4, f); + } + } + else if (cbPixel == 1) + { + const uint8_t *s = (uint8_t *)pvBits; + int i; + for (i = 0; i < w * h; ++i) + { + const uint8_t u8 = *s++; + uint32_t u32 = u8 * 0x10000 + u8 * 0x100 + u8; + uint32_t u = u32 & u32Mask; + fwrite(&u, 1, 4, f); + } + } + + fclose(f); + + return VINF_SUCCESS; +} + +void vmsvga3dInfoSurfaceToBitmap(PCDBGFINFOHLP pHlp, PVMSVGA3DSURFACE pSurface, + const char *pszPath, const char *pszNamePrefix, const char *pszNameSuffix) +{ + static volatile uint32_t sSeq = 0; + const uint32_t u32Seq = ASMAtomicIncU32(&sSeq); + + for (uint32_t i = 0; i < pSurface->cLevels; ++i) + { + if (!pSurface->paMipmapLevels[i].pSurfaceData) + continue; + + char szFilepath[4096]; + RTStrPrintf(szFilepath, sizeof(szFilepath), + "%s" RTPATH_SLASH_STR "%s-%u-sid%u-%u%s.bmp", + pszPath, pszNamePrefix, u32Seq, pSurface->id, i, pszNameSuffix); + + const uint32_t cbPixel = vmsvga3dSurfaceFormatSize(pSurface->format, NULL, NULL); + int rc = vmsvga3dInfoBmpWrite(szFilepath, + pSurface->paMipmapLevels[i].pSurfaceData, + pSurface->paMipmapLevels[i].mipmapSize.width, + pSurface->paMipmapLevels[i].mipmapSize.height, + cbPixel, 0xFFFFFFFF); + if (RT_SUCCESS(rc)) + { + Log(("Bitmap: %s\n", szFilepath)); + if (pHlp) + pHlp->pfnPrintf(pHlp, "Bitmap: %s\n", szFilepath); + } + else + { + Log(("Bitmap: %s %Rrc\n", szFilepath, rc)); + if (pHlp) + pHlp->pfnPrintf(pHlp, "Bitmap: %s %Rrc\n", szFilepath, rc); + } + } + +#if 0 + /* Alpha channel alone. */ + RTStrPrintf(szFilepath, sizeof(szFilepath), + "%s\\%s-%u-sid%u%s-a.bmp", + pszPath, pszNamePrefix, u32Seq, pSurface->id, pszNameSuffix); + vmsvga3dInfoBmpWrite(szFilepath, + pSurface->paMipmapLevels[0].pSurfaceData, + pSurface->paMipmapLevels[0].mipmapSize.width, + pSurface->paMipmapLevels[0].mipmapSize.height, + cbPixel, 0xFF000000); +#endif +} + +static void vmsvga3dInfoSurfaceWorkerOne(PCDBGFINFOHLP pHlp, PVMSVGA3DSURFACE pSurface, + bool fVerbose, uint32_t cxAscii, bool fInvY) +{ + char szTmp[128]; + + pHlp->pfnPrintf(pHlp, "*** VMSVGA 3d surface %#x (%d)%s ***\n", pSurface->id, pSurface->id, pSurface->fDirty ? " - dirty" : ""); + pHlp->pfnPrintf(pHlp, "idAssociatedContext: %#x\n", pSurface->idAssociatedContext); + pHlp->pfnPrintf(pHlp, "Format: %s\n", + vmsvgaFormatEnumValueEx(szTmp, sizeof(szTmp), NULL, (int)pSurface->format, false, &g_SVGA3dSurfaceFormat2String)); + pHlp->pfnPrintf(pHlp, "Flags: 0x%RX64", pSurface->f.surfaceFlags); + vmsvga3dInfoU32Flags(pHlp, pSurface->f.s.surface1Flags, "SVGA3D_SURFACE_", g_aSvga3DSurfaceFlags, RT_ELEMENTS(g_aSvga3DSurfaceFlags)); + pHlp->pfnPrintf(pHlp, "\n"); + if (pSurface->cFaces != 0) + pHlp->pfnPrintf(pHlp, "Faces: %u\n", pSurface->cFaces); + if (pSurface->cLevels != 0) + pHlp->pfnPrintf(pHlp, "Mipmap levels: %u\n", pSurface->cLevels); + for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++) + { + uint32_t iMipmap = iFace * pSurface->cLevels; + for (uint32_t iLevel = 0; iLevel < pSurface->cLevels; iLevel++, iMipmap++) + { + pHlp->pfnPrintf(pHlp, "Face #%u, mipmap #%u[%u]:%s cx=%u, cy=%u, cz=%u, cbSurface=%#x, cbPitch=%#x", + iFace, iLevel, iMipmap, iMipmap < 10 ? " " : "", + pSurface->paMipmapLevels[iMipmap].mipmapSize.width, + pSurface->paMipmapLevels[iMipmap].mipmapSize.height, + pSurface->paMipmapLevels[iMipmap].mipmapSize.depth, + pSurface->paMipmapLevels[iMipmap].cbSurface, + pSurface->paMipmapLevels[iMipmap].cbSurfacePitch); + if (pSurface->paMipmapLevels[iMipmap].pSurfaceData) + pHlp->pfnPrintf(pHlp, " pvData=%p", pSurface->paMipmapLevels[iMipmap].pSurfaceData); + if (pSurface->paMipmapLevels[iMipmap].fDirty) + pHlp->pfnPrintf(pHlp, " dirty"); + pHlp->pfnPrintf(pHlp, "\n"); + } + } + + pHlp->pfnPrintf(pHlp, "cbBlock: %u (%#x)\n", pSurface->cbBlock, pSurface->cbBlock); + pHlp->pfnPrintf(pHlp, "Multi-sample count: %u\n", pSurface->multiSampleCount); + pHlp->pfnPrintf(pHlp, "Autogen filter: %s\n", + vmsvgaFormatEnumValue(szTmp, sizeof(szTmp), NULL, pSurface->autogenFilter, + "SVGA3D_TEX_FILTER_", g_apszTexureFilters, RT_ELEMENTS(g_apszTexureFilters))); + +#ifdef VMSVGA3D_DIRECT3D + pHlp->pfnPrintf(pHlp, "formatD3D: %s\n", + vmsvgaFormatEnumValueEx(szTmp, sizeof(szTmp), NULL, pSurface->formatD3D, true, &g_D3DFormat2String)); + pHlp->pfnPrintf(pHlp, "fUsageD3D: %#x", pSurface->fUsageD3D); + vmsvga3dInfoU32Flags(pHlp, pSurface->fUsageD3D, "D3DUSAGE_", g_aD3DUsageFlags, RT_ELEMENTS(g_aD3DUsageFlags)); + pHlp->pfnPrintf(pHlp, "\n"); + pHlp->pfnPrintf(pHlp, "multiSampleTypeD3D: %s\n", + vmsvgaFormatEnumValueEx(szTmp, sizeof(szTmp), NULL, pSurface->multiSampleTypeD3D, + true, &g_D3DMultiSampleType2String)); + if (pSurface->hSharedObject != NULL) + pHlp->pfnPrintf(pHlp, "hSharedObject: %p\n", pSurface->hSharedObject); + if (pSurface->pQuery) + pHlp->pfnPrintf(pHlp, "pQuery: %p\n", pSurface->pQuery); + if (pSurface->u.pSurface) + pHlp->pfnPrintf(pHlp, "u.pXxxx: %p\n", pSurface->u.pSurface); + if (pSurface->bounce.pTexture) + pHlp->pfnPrintf(pHlp, "bounce.pXxxx: %p\n", pSurface->bounce.pTexture); + RTAvlU32DoWithAll(&pSurface->pSharedObjectTree, true /*fFromLeft*/, vmsvga3dInfoSharedObjectCallback, (void *)pHlp); + pHlp->pfnPrintf(pHlp, "fStencilAsTexture: %RTbool\n", pSurface->fStencilAsTexture); + +#elif defined(VMSVGA3D_OPENGL) + /** @todo */ +#else +# error "Build config error." +#endif + + if (fVerbose) + for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++) + { + uint32_t iMipmap = iFace * pSurface->cLevels; + for (uint32_t iLevel = 0; iLevel < pSurface->cLevels; iLevel++, iMipmap++) + if (pSurface->paMipmapLevels[iMipmap].pSurfaceData) + { + if (ASMMemIsZero(pSurface->paMipmapLevels[iMipmap].pSurfaceData, + pSurface->paMipmapLevels[iMipmap].cbSurface)) + pHlp->pfnPrintf(pHlp, "--- Face #%u, mipmap #%u[%u]: all zeros ---\n", iFace, iLevel, iMipmap); + else + { + pHlp->pfnPrintf(pHlp, "--- Face #%u, mipmap #%u[%u]: cx=%u, cy=%u, cz=%u ---\n", + iFace, iLevel, iMipmap, + pSurface->paMipmapLevels[iMipmap].mipmapSize.width, + pSurface->paMipmapLevels[iMipmap].mipmapSize.height, + pSurface->paMipmapLevels[iMipmap].mipmapSize.depth); + vmsvga3dAsciiPrint(vmsvga3dAsciiPrintlnInfo, (void *)pHlp, + pSurface->paMipmapLevels[iMipmap].pSurfaceData, + pSurface->paMipmapLevels[iMipmap].cbSurface, + pSurface->paMipmapLevels[iMipmap].mipmapSize.width, + pSurface->paMipmapLevels[iMipmap].mipmapSize.height, + pSurface->paMipmapLevels[iMipmap].cbSurfacePitch, + pSurface->format, + fInvY, + cxAscii, cxAscii * 3 / 4); + } + } + } +} + + +void vmsvga3dInfoSurfaceWorker(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PCDBGFINFOHLP pHlp, uint32_t sid, + bool fVerbose, uint32_t cxAscii, bool fInvY, const char *pszBitmapPath) +{ + /* Warning! This code is currently racing papSurfaces reallocation! */ + /* Warning! This code is currently racing papSurfaces reallocation! */ + /* Warning! This code is currently racing papSurfaces reallocation! */ + VMSVGA3DSTATE volatile *pState = pThisCC->svga.p3dState; + if (pState) + { + /* + * Deal with a specific request first. + */ + if (sid != UINT32_MAX) + { + if (sid < pState->cSurfaces) + { + PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; + if (pSurface && pSurface->id == sid) + { + if (fVerbose) + vmsvgaR33dSurfaceUpdateHeapBuffersOnFifoThread(pDevIns, pThis, pThisCC, sid); + vmsvga3dInfoSurfaceWorkerOne(pHlp, pSurface, fVerbose, cxAscii, fInvY); + if (pszBitmapPath && *pszBitmapPath) + vmsvga3dInfoSurfaceToBitmap(pHlp, pSurface, pszBitmapPath, "info", ""); + return; + } + } + pHlp->pfnPrintf(pHlp, "Surface ID %#x not found.\n", sid); + } + else + { + /* + * Dump all. + */ + if (fVerbose) + vmsvgaR33dSurfaceUpdateHeapBuffersOnFifoThread(pDevIns, pThis, pThisCC, UINT32_MAX); + uint32_t cSurfaces = pState->cSurfaces; + pHlp->pfnPrintf(pHlp, "cSurfaces=%d\n", cSurfaces); + for (sid = 0; sid < cSurfaces; sid++) + { + PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; + if (pSurface && pSurface->id == sid) + { + pHlp->pfnPrintf(pHlp, "\n"); + vmsvga3dInfoSurfaceWorkerOne(pHlp, pSurface, fVerbose, cxAscii, fInvY); + } + } + } + } + +} + diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h new file mode 100644 index 00000000..c3f8e57b --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h @@ -0,0 +1,1446 @@ +/* $Id: DevVGA-SVGA3d-internal.h $ */ +/** @file + * DevVMWare - VMWare SVGA device - 3D part, internal header. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_internal_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_internal_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* + * Assert sane compilation environment. + */ +#ifndef IN_RING3 +# error "VMSVGA3D_INCL_INTERNALS is only for ring-3 code" +#endif +#ifdef VMSVGA3D_OPENGL +# if defined(VMSVGA3D_DIRECT3D) +# error "Both VMSVGA3D_DIRECT3D and VMSVGA3D_OPENGL cannot be defined at the same time." +# endif +#elif !defined(VMSVGA3D_DIRECT3D) +# error "Either VMSVGA3D_OPENGL or VMSVGA3D_DIRECT3D must be defined." +#endif + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "DevVGA-SVGA3d.h" + +#if defined(VMSVGA3D_DYNAMIC_LOAD) && defined(VMSVGA3D_OPENGL) +# include "DevVGA-SVGA3d-glLdr.h" +#endif + +#ifdef RT_OS_WINDOWS +# include +# ifdef VMSVGA3D_DIRECT3D +# include +# include +# else +# include +# include "vmsvga_glext/wglext.h" +# endif + +#elif defined(RT_OS_DARWIN) +# include +# include +# include +# define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED +# include +# include "DevVGA-SVGA3d-cocoa.h" +/* work around conflicting definition of GLhandleARB in VMware's glext.h */ +//#define GL_ARB_shader_objects +// HACK +typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); +# if 0 +# define GL_RGBA_S3TC 0x83A2 +# define GL_ALPHA8_EXT 0x803c +# define GL_LUMINANCE8_EXT 0x8040 +# define GL_LUMINANCE16_EXT 0x8042 +# define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +# define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +# define GL_INT_2_10_10_10_REV 0x8D9F +# endif + +#else +# include +# include +# include +# include +# define VBOX_VMSVGA3D_GL_HACK_LEVEL 0x103 +#endif + +#ifdef VMSVGA3D_OPENGL +# ifndef __glext_h__ +# undef GL_GLEXT_VERSION /** @todo r=bird: We include GL/glext.h above which also defines this and we'll end up with + * a clash if the system one does not use the same header guard as ours. So, I'm wondering + * whether this include is really needed, and if it is, whether we should use a unique header + * guard macro on it, so we'll have the same problems everywhere... */ +# endif +# include "vmsvga_glext/glext.h" +# include "shaderlib/shaderlib.h" +#endif + +#ifdef VMSVGA3D_DX +#include "DevVGA-SVGA3d-dx-shader.h" +#endif + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#ifdef VMSVGA3D_OPENGL +/** OpenGL: Create a dedicated context for handling surfaces in, thus + * avoiding orphaned surfaces after context destruction. + * + * This cures, for instance, an assertion on fedora 21 that happens in + * vmsvga3dSurfaceStretchBlt if the login screen and the desktop has different + * sizes. The context of the login screen seems to have just been destroyed + * earlier and I believe the driver/X/whoever is attemting to strech the old + * screen content onto the new sized screen. + * + * @remarks This probably comes at a slight preformance expense, as we currently + * switches context when setting up the surface the first time. Not sure + * if we really need to, but as this is an experiment, I'm playing it safe. + * @remarks The define has been made default, thus should no longer be used. + */ +# define VMSVGA3D_OGL_WITH_SHARED_CTX +/** Fake surface ID for the shared context. */ +# define VMSVGA3D_SHARED_CTX_ID UINT32_C(0xffffeeee) + +/** @def VBOX_VMSVGA3D_GL_HACK_LEVEL + * Turns out that on Linux gl.h may often define the first 2-4 OpenGL versions + * worth of extensions, but missing out on a function pointer of fifteen. This + * causes headache for us when we use the function pointers below. This hack + * changes the code to call the known problematic functions directly. + * The value is ((x)<<16 | (y)) where x and y are taken from the GL_VERSION_x_y. + */ +# ifndef VBOX_VMSVGA3D_GL_HACK_LEVEL +# define VBOX_VMSVGA3D_GL_HACK_LEVEL 0 +# endif + +/** Invalid OpenGL ID. */ +# define OPENGL_INVALID_ID 0 + +# define VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState) \ + do { (pState)->idActiveContext = OPENGL_INVALID_ID; } while (0) + +/** @def VMSVGA3D_SET_CURRENT_CONTEXT + * Makes sure the @a pContext is the active OpenGL context. + * @parm pState The VMSVGA3d state. + * @parm pContext The new context. + */ +# ifdef RT_OS_WINDOWS +# define VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext) \ + do { \ + if ((pState)->idActiveContext != (pContext)->id) \ + { \ + BOOL fMakeCurrentRc = wglMakeCurrent((pContext)->hdc, (pContext)->hglrc); \ + Assert(fMakeCurrentRc == TRUE); RT_NOREF_PV(fMakeCurrentRc); \ + LogFlowFunc(("Changing context: %#x -> %#x\n", (pState)->idActiveContext, (pContext)->id)); \ + (pState)->idActiveContext = (pContext)->id; \ + } \ + } while (0) + +# elif defined(RT_OS_DARWIN) +# define VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext) \ + do { \ + if ((pState)->idActiveContext != (pContext)->id) \ + { \ + vmsvga3dCocoaViewMakeCurrentContext((pContext)->cocoaView, (pContext)->cocoaContext); \ + LogFlowFunc(("Changing context: %#x -> %#x\n", (pState)->idActiveContext, (pContext)->id)); \ + (pState)->idActiveContext = (pContext)->id; \ + } \ + } while (0) +# else +# define VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext) \ + do { \ + if ((pState)->idActiveContext != (pContext)->id) \ + { \ + Bool fMakeCurrentRc = glXMakeCurrent((pState)->display, \ + (pContext)->window, \ + (pContext)->glxContext); \ + Assert(fMakeCurrentRc == True); RT_NOREF_PV(fMakeCurrentRc); \ + LogFlowFunc(("Changing context: %#x -> %#x\n", (pState)->idActiveContext, (pContext)->id)); \ + (pState)->idActiveContext = (pContext)->id; \ + } \ + } while (0) +# endif + +/** @def VMSVGA3D_CLEAR_GL_ERRORS + * Clears all pending OpenGL errors. + * + * If I understood this correctly, OpenGL maintains a bitmask internally and + * glGetError gets the next bit (clearing it) from the bitmap and translates it + * into a GL_XXX constant value which it then returns. A single OpenGL call can + * set more than one bit, and they stick around across calls, from what I + * understand. + * + * So in order to be able to use glGetError to check whether a function + * succeeded, we need to call glGetError until all error bits have been cleared. + * This macro does that (in all types of builds). + * + * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS + */ +# define VMSVGA3D_CLEAR_GL_ERRORS() \ + do { \ + if (RT_UNLIKELY(glGetError() != GL_NO_ERROR)) /* predict no errors pending */ \ + { \ + uint32_t iErrorClearingLoopsLeft = 64; \ + while (glGetError() != GL_NO_ERROR && iErrorClearingLoopsLeft > 0) \ + iErrorClearingLoopsLeft--; \ + } \ + } while (0) + +/** @def VMSVGA3D_GET_LAST_GL_ERROR + * Gets the last OpenGL error, stores it in a_pContext->lastError and returns + * it. + * + * @returns Same as glGetError. + * @param a_pContext The context to store the error in. + * + * @sa VMSVGA3D_GL_IS_SUCCESS, VMSVGA3D_GL_COMPLAIN + */ +# define VMSVGA3D_GET_GL_ERROR(a_pContext) ((a_pContext)->lastError = glGetError()) + +/** @def VMSVGA3D_GL_SUCCESS + * Checks whether VMSVGA3D_GET_LAST_GL_ERROR() return GL_NO_ERROR. + * + * Will call glGetError() and store the result in a_pContext->lastError. + * Will predict GL_NO_ERROR outcome. + * + * @returns True on success, false on error. + * @parm a_pContext The context to store the error in. + * + * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_COMPLAIN + */ +# define VMSVGA3D_GL_IS_SUCCESS(a_pContext) RT_LIKELY((((a_pContext)->lastError = glGetError()) == GL_NO_ERROR)) + +/** @def VMSVGA3D_GL_COMPLAIN + * Complains about one or more OpenGL errors (first in a_pContext->lastError). + * + * Strict builds will trigger an assertion, while other builds will put the + * first few occurences in the release log. + * + * All GL errors will be cleared after invocation. Assumes lastError + * is an error, will not check for GL_NO_ERROR. + * + * @param a_pState The 3D state structure. + * @param a_pContext The context that holds the first error. + * @param a_LogRelDetails Argument list for LogRel or similar that describes + * the operation in greater detail. + * + * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS + */ +# ifdef VBOX_STRICT +# define VMSVGA3D_GL_COMPLAIN(a_pState, a_pContext, a_LogRelDetails) \ + do { \ + AssertMsg((a_pState)->idActiveContext == (a_pContext)->id, \ + ("idActiveContext=%#x id=%x\n", (a_pState)->idActiveContext, (a_pContext)->id)); \ + RTAssertMsg2Weak a_LogRelDetails; \ + GLenum iNextError; \ + while ((iNextError = glGetError()) != GL_NO_ERROR) \ + RTAssertMsg2Weak("next error: %#x\n", iNextError); \ + AssertMsgFailed(("first error: %#x (idActiveContext=%#x)\n", (a_pContext)->lastError, (a_pContext)->id)); \ + } while (0) +# else +# define VMSVGA3D_GL_COMPLAIN(a_pState, a_pContext, a_LogRelDetails) \ + do { \ + LogRelMax(32, ("VMSVGA3d: OpenGL error %#x (idActiveContext=%#x) on line %u ", (a_pContext)->lastError, (a_pContext)->id, __LINE__)); \ + GLenum iNextError; \ + while ((iNextError = glGetError()) != GL_NO_ERROR) \ + LogRelMax(32, (" - also error %#x ", iNextError)); \ + LogRelMax(32, a_LogRelDetails); \ + } while (0) +# endif + +/** @def VMSVGA3D_GL_GET_AND_COMPLAIN + * Combination of VMSVGA3D_GET_GL_ERROR and VMSVGA3D_GL_COMPLAIN, assuming that + * there is a pending error. + * + * @param a_pState The 3D state structure. + * @param a_pContext The context that holds the first error. + * @param a_LogRelDetails Argument list for LogRel or similar that describes + * the operation in greater detail. + * + * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS, VMSVGA3D_GL_COMPLAIN + */ +# define VMSVGA3D_GL_GET_AND_COMPLAIN(a_pState, a_pContext, a_LogRelDetails) \ + do { \ + VMSVGA3D_GET_GL_ERROR(a_pContext); \ + VMSVGA3D_GL_COMPLAIN(a_pState, a_pContext, a_LogRelDetails); \ + } while (0) + +/** @def VMSVGA3D_GL_ASSERT_SUCCESS + * Asserts that VMSVGA3D_GL_IS_SUCCESS is true, complains if not. + * + * Uses VMSVGA3D_GL_COMPLAIN for complaining, so check it out wrt to release + * logging in non-strict builds. + * + * @param a_pState The 3D state structure. + * @param a_pContext The context that holds the first error. + * @param a_LogRelDetails Argument list for LogRel or similar that describes + * the operation in greater detail. + * + * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS, VMSVGA3D_GL_COMPLAIN + */ +# define VMSVGA3D_GL_ASSERT_SUCCESS(a_pState, a_pContext, a_LogRelDetails) \ + if (VMSVGA3D_GL_IS_SUCCESS(a_pContext)) \ + { /* likely */ } \ + else do { \ + VMSVGA3D_GL_COMPLAIN(a_pState, a_pContext, a_LogRelDetails); \ + } while (0) + +/** @def VMSVGA3D_ASSERT_GL_CALL_EX + * Executes the specified OpenGL API call and asserts that it succeeded, variant + * with extra logging flexibility. + * + * ASSUMES no GL errors pending prior to invocation - caller should use + * VMSVGA3D_CLEAR_GL_ERRORS if uncertain. + * + * Uses VMSVGA3D_GL_COMPLAIN for complaining, so check it out wrt to release + * logging in non-strict builds. + * + * @param a_GlCall Expression making an OpenGL call. + * @param a_pState The 3D state structure. + * @param a_pContext The context that holds the first error. + * @param a_LogRelDetails Argument list for LogRel or similar that describes + * the operation in greater detail. + * + * @sa VMSVGA3D_ASSERT_GL_CALL, VMSVGA3D_GL_ASSERT_SUCCESS, + * VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS, VMSVGA3D_GL_COMPLAIN + */ +# define VMSVGA3D_ASSERT_GL_CALL_EX(a_GlCall, a_pState, a_pContext, a_LogRelDetails) \ + do { \ + (a_GlCall); \ + VMSVGA3D_GL_ASSERT_SUCCESS(a_pState, a_pContext, a_LogRelDetails); \ + } while (0) + +/** @def VMSVGA3D_ASSERT_GL_CALL + * Executes the specified OpenGL API call and asserts that it succeeded. + * + * ASSUMES no GL errors pending prior to invocation - caller should use + * VMSVGA3D_CLEAR_GL_ERRORS if uncertain. + * + * Uses VMSVGA3D_GL_COMPLAIN for complaining, so check it out wrt to release + * logging in non-strict builds. + * + * @param a_GlCall Expression making an OpenGL call. + * @param a_pState The 3D state structure. + * @param a_pContext The context that holds the first error. + * + * @sa VMSVGA3D_ASSERT_GL_CALL_EX, VMSVGA3D_GL_ASSERT_SUCCESS, + * VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS, VMSVGA3D_GL_COMPLAIN + */ +# define VMSVGA3D_ASSERT_GL_CALL(a_GlCall, a_pState, a_pContext) \ + VMSVGA3D_ASSERT_GL_CALL_EX(a_GlCall, a_pState, a_pContext, ("%s\n", #a_GlCall)) + + +/** @def VMSVGA3D_CHECK_LAST_ERROR + * Checks that the last OpenGL error code indicates success. + * + * Will assert and return VERR_INTERNAL_ERROR in strict builds, in other + * builds it will do nothing and is a NOOP. + * + * @parm pState The VMSVGA3d state. + * @parm pContext The context. + * + * @todo Replace with proper error handling, it's crazy to return + * VERR_INTERNAL_ERROR in strict builds and just barge on ahead in + * release builds. + */ +/** @todo Rename to VMSVGA3D_CHECK_LAST_ERROR_RETURN */ +# ifdef VBOX_STRICT +# define VMSVGA3D_CHECK_LAST_ERROR(pState, pContext) do { \ + Assert((pState)->idActiveContext == (pContext)->id); \ + (pContext)->lastError = glGetError(); \ + AssertMsgReturn((pContext)->lastError == GL_NO_ERROR, \ + ("%s (%d): last error 0x%x\n", __FUNCTION__, __LINE__, (pContext)->lastError), \ + VERR_INTERNAL_ERROR); \ + } while (0) +# else +# define VMSVGA3D_CHECK_LAST_ERROR(pState, pContext) do { } while (0) +# endif + +/** @def VMSVGA3D_CHECK_LAST_ERROR_WARN + * Checks that the last OpenGL error code indicates success. + * + * Will assert in strict builds, otherwise it's a NOOP. + * + * @parm pState The VMSVGA3d state. + * @parm pContext The new context. + */ +# ifdef VBOX_STRICT +# define VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext) do { \ + Assert((pState)->idActiveContext == (pContext)->id); \ + (pContext)->lastError = glGetError(); \ + AssertMsg((pContext)->lastError == GL_NO_ERROR, ("%s (%d): last error 0x%x\n", __FUNCTION__, __LINE__, (pContext)->lastError)); \ + } while (0) +# else +# define VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext) do { } while (0) +# endif + +#endif /* VMSVGA3D_OPENGL */ + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * Mipmap level. + */ +typedef struct VMSVGA3DMIPMAPLEVEL +{ + /** The mipmap size: width, height and depth. */ + SVGA3dSize mipmapSize; + /** Width in blocks: (width + cxBlock - 1) / cxBlock. SSM: not saved, recalculated on load. */ + uint32_t cBlocksX; + /** Height in blocks: (height + cyBlock - 1) / cyBlock. SSM: not saved, recalculated on load. */ + uint32_t cBlocksY; + /** Number of blocks: cBlocksX * cBlocksY * mipmapSize.depth. SSM: not saved, recalculated on load. */ + uint32_t cBlocks; + /** The scanline/pitch size in bytes: at least cBlocksX * cbBlock. */ + uint32_t cbSurfacePitch; + /** The size (in bytes) of the mipmap plane: cbSurfacePitch * cBlocksY */ + uint32_t cbSurfacePlane; + /** The size (in bytes) of the mipmap data when using the format the surface was + * defined with: cbSurfacePlane * mipmapSize.z */ + uint32_t cbSurface; + /** Pointer to the mipmap bytes (cbSurface). Often NULL. If the surface has + * been realized in hardware, this may be outdated. */ + void *pSurfaceData; + /** Set if pvSurfaceData contains data not realized in hardware or pushed to the + * hardware surface yet. */ + bool fDirty; +} VMSVGA3DMIPMAPLEVEL; +/** Pointer to a mipmap level. */ +typedef VMSVGA3DMIPMAPLEVEL *PVMSVGA3DMIPMAPLEVEL; + + +#ifdef VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +/** + * SSM descriptor table for the VMSVGA3DMIPMAPLEVEL structure. + */ +static SSMFIELD const g_aVMSVGA3DMIPMAPLEVELFields[] = +{ + SSMFIELD_ENTRY( VMSVGA3DMIPMAPLEVEL, mipmapSize), + SSMFIELD_ENTRY( VMSVGA3DMIPMAPLEVEL, cbSurface), + SSMFIELD_ENTRY( VMSVGA3DMIPMAPLEVEL, cbSurfacePitch), + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DMIPMAPLEVEL, pSurfaceData), + SSMFIELD_ENTRY_IGNORE( VMSVGA3DMIPMAPLEVEL, fDirty), + SSMFIELD_ENTRY_TERM() +}; +#endif + +typedef struct VMSVGATRANSFORMSTATE +{ + bool fValid; + float matrix[16]; +} VMSVGATRANSFORMSTATE; +typedef VMSVGATRANSFORMSTATE *PVMSVGATRANSFORMSTATE; + +typedef struct VMSVGAMATERIALSTATE +{ + bool fValid; + SVGA3dMaterial material; +} VMSVGAMATERIALSTATE; +typedef VMSVGAMATERIALSTATE *PVMSVGAMATERIALSTATE; + +typedef struct VMSVGACLIPPLANESTATE +{ + bool fValid; + float plane[4]; +} VMSVGACLIPPLANESTATE; +typedef VMSVGACLIPPLANESTATE *PVMSVGACLIPPLANESTATE; + +typedef struct VMSVGALIGHTSTATE +{ + bool fEnabled; + bool fValidData; + SVGA3dLightData data; +} VMSVGALIGHTSTATE; +typedef VMSVGALIGHTSTATE *PVMSVGALIGHTSTATE; + +typedef struct VMSVGASHADERCONST +{ + bool fValid; + SVGA3dShaderConstType ctype; + uint32_t value[4]; +} VMSVGASHADERCONST; +typedef VMSVGASHADERCONST *PVMSVGASHADERCONST; + +#ifdef VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +/** + * SSM descriptor table for the VMSVGASHADERCONST structure. + */ +static SSMFIELD const g_aVMSVGASHADERCONSTFields[] = +{ + SSMFIELD_ENTRY( VMSVGASHADERCONST, fValid), + SSMFIELD_ENTRY( VMSVGASHADERCONST, ctype), + SSMFIELD_ENTRY( VMSVGASHADERCONST, value), + SSMFIELD_ENTRY_TERM() +}; +#endif + +#ifdef VMSVGA3D_DIRECT3D + +/* What kind of Direct3D resource has been created for the VMSVGA3D surface. */ +typedef enum VMSVGA3DD3DRESTYPE +{ + VMSVGA3D_D3DRESTYPE_NONE = 0, + VMSVGA3D_D3DRESTYPE_SURFACE = 1, + VMSVGA3D_D3DRESTYPE_TEXTURE = 2, + VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE = 3, + VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE = 4, + VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER = 5, + VMSVGA3D_D3DRESTYPE_INDEX_BUFFER = 6 +} VMSVGA3DD3DRESTYPE; + +/** + * + */ +typedef struct +{ + /** Key is context id. */ + AVLU32NODECORE Core; + union + { + IDirect3DTexture9 *pTexture; + IDirect3DCubeTexture9 *pCubeTexture; + IDirect3DVolumeTexture9 *pVolumeTexture; + } u; +} VMSVGA3DSHAREDSURFACE; +typedef VMSVGA3DSHAREDSURFACE *PVMSVGA3DSHAREDSURFACE; +#endif /* VMSVGA3D_DIRECT3D */ + +#ifdef VMSVGA3D_OPENGL +/* What kind of OpenGL resource has been created for the VMSVGA3D surface. */ +typedef enum VMSVGA3DOGLRESTYPE +{ + VMSVGA3D_OGLRESTYPE_NONE = 0, + VMSVGA3D_OGLRESTYPE_BUFFER = 1, + VMSVGA3D_OGLRESTYPE_TEXTURE = 2, + VMSVGA3D_OGLRESTYPE_RENDERBUFFER = 3 +} VMSVGA3DOGLRESTYPE; +#endif + +/* The 3D backend surface. The actual structure is 3D API specific. */ +typedef struct VMSVGA3DBACKENDSURFACE *PVMSVGA3DBACKENDSURFACE; + +/** + * VMSVGA3d surface. + */ +typedef struct VMSVGA3DSURFACE +{ + PVMSVGA3DBACKENDSURFACE pBackendSurface; + + uint32_t id; /** @todo sid */ + /* Which context created the corresponding resource. + * SVGA_ID_INVALID means that resource has not been created yet. + * A resource has been created if VMSVGA3DSURFACE_HAS_HW_SURFACE is true. + * + */ + uint32_t idAssociatedContext; + + /** @todo Only numArrayElements field is used currently. The code uses old fields cLevels, etc for anything else. */ + VMSVGA3D_SURFACE_DESC surfaceDesc; + + union + { + struct + { + SVGA3dSurface1Flags surface1Flags; + SVGA3dSurface2Flags surface2Flags; + } s; + SVGA3dSurfaceAllFlags surfaceFlags; + } f; + SVGA3dSurfaceFormat format; +#ifdef VMSVGA3D_OPENGL + GLint internalFormatGL; + GLint formatGL; + GLint typeGL; + VMSVGA3DOGLRESTYPE enmOGLResType; /* Which resource was created for the surface. */ + union + { + GLuint texture; + GLuint buffer; + GLuint renderbuffer; + } oglId; + GLenum targetGL; /* GL_TEXTURE_* */ + GLenum bindingGL; /* GL_TEXTURE_BINDING_* */ + /* Emulated formats */ + bool fEmulated; /* Whether the texture format is emulated. */ + GLuint idEmulated; /* GL name of the intermediate texture. */ +#endif + uint32_t cFaces; /* Number of faces: 6 for cubemaps, 1 for everything else. */ + uint32_t cLevels; /* Number of mipmap levels per face. */ + PVMSVGA3DMIPMAPLEVEL paMipmapLevels; /* surfaceDesc.numArrayElements * cLevels elements. */ + uint32_t multiSampleCount; + SVGA3dTextureFilter autogenFilter; +#ifdef VMSVGA3D_DIRECT3D + D3DFORMAT formatD3D; + DWORD fUsageD3D; + D3DMULTISAMPLE_TYPE multiSampleTypeD3D; +#endif + + uint32_t cbBlock; /* block/pixel size in bytes */ + /* Dimensions of the surface block, usually 1x1 except for compressed formats. */ + uint32_t cxBlock; /* Block width in pixels. SSM: not saved, recalculated on load. */ + uint32_t cyBlock; /* Block height in pixels. SSM: not saved, recalculated on load. */ +#ifdef VMSVGA3D_OPENGL + uint32_t cbBlockGL; /* Block size of the OpenGL texture, same as cbBlock for not-emulated formats. */ +#endif + + /* Dirty state; surface was manually updated. */ + bool fDirty; + +#ifdef VMSVGA3D_DIRECT3D + /* Handle for shared objects (currently only textures & render targets). */ + HANDLE hSharedObject; + /** Event query inserted after each GPU operation that updates or uses this surface. */ + IDirect3DQuery9 *pQuery; + /** The context id where the query has been created. */ + uint32_t idQueryContext; + /** The type of actually created D3D resource. */ + VMSVGA3DD3DRESTYPE enmD3DResType; + union + { + IDirect3DSurface9 *pSurface; + IDirect3DTexture9 *pTexture; + IDirect3DCubeTexture9 *pCubeTexture; + IDirect3DVolumeTexture9 *pVolumeTexture; + IDirect3DVertexBuffer9 *pVertexBuffer; + IDirect3DIndexBuffer9 *pIndexBuffer; + } u; + union + { + IDirect3DTexture9 *pTexture; + IDirect3DCubeTexture9 *pCubeTexture; + IDirect3DVolumeTexture9 *pVolumeTexture; + } bounce; + /** AVL tree containing VMSVGA3DSHAREDSURFACE structures. */ + AVLU32TREE pSharedObjectTree; + bool fStencilAsTexture; + D3DFORMAT d3dfmtRequested; + union + { + IDirect3DTexture9 *pTexture; + IDirect3DCubeTexture9 *pCubeTexture; + IDirect3DVolumeTexture9 *pVolumeTexture; + } emulated; +#endif +} VMSVGA3DSURFACE; +/** Pointer to a 3d surface. */ +typedef VMSVGA3DSURFACE *PVMSVGA3DSURFACE; + +#ifdef VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +/** + * SSM descriptor table for the VMSVGA3DSURFACE structure. + */ +static SSMFIELD const g_aVMSVGA3DSURFACEFields[] = +{ + SSMFIELD_ENTRY( VMSVGA3DSURFACE, id), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, idAssociatedContext), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, f.s.surface1Flags), + SSMFIELD_ENTRY_VER( VMSVGA3DSURFACE, f.s.surface2Flags, VGA_SAVEDSTATE_VERSION_VMSVGA_DX_SFLAGS), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, format), +# ifdef VMSVGA3D_OPENGL + SSMFIELD_ENTRY( VMSVGA3DSURFACE, internalFormatGL), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, formatGL), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, typeGL), +# endif + SSMFIELD_ENTRY( VMSVGA3DSURFACE, cFaces), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, cLevels), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, multiSampleCount), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, autogenFilter), + SSMFIELD_ENTRY( VMSVGA3DSURFACE, cbBlock), + SSMFIELD_ENTRY_TERM() +}; +#endif + +/** Mask we frequently apply to VMSVGA3DSURFACE::flags for decing what kind + * of surface we're dealing. */ +#define VMSVGA3D_SURFACE_HINT_SWITCH_MASK \ + ( SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER \ + | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET \ + | SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_CUBEMAP ) + +/** @def VMSVGA3DSURFACE_HAS_HW_SURFACE + * Checks whether the surface has a host hardware/library surface. + * @returns true/false + * @param a_pSurface The VMSVGA3d surface. + */ +#ifdef VMSVGA3D_DIRECT3D +# define VMSVGA3DSURFACE_HAS_HW_SURFACE(a_pSurface) ((a_pSurface)->pBackendSurface != NULL || (a_pSurface)->u.pSurface != NULL) +#else +# define VMSVGA3DSURFACE_HAS_HW_SURFACE(a_pSurface) ((a_pSurface)->pBackendSurface != NULL || (a_pSurface)->oglId.texture != OPENGL_INVALID_ID) +#endif + +/** @def VMSVGA3DSURFACE_NEEDS_DATA + * Checks whether SurfaceDMA transfers must always update pSurfaceData, + * even if the surface has a host hardware resource. + * @returns true/false + * @param a_pSurface The VMSVGA3d surface. + */ +#ifdef VMSVGA3D_DIRECT3D +# define VMSVGA3DSURFACE_NEEDS_DATA(a_pSurface) \ + ( (a_pSurface)->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER \ + || (a_pSurface)->enmD3DResType == VMSVGA3D_D3DRESTYPE_INDEX_BUFFER) +#else +# define VMSVGA3DSURFACE_NEEDS_DATA(a_pSurface) \ + ((a_pSurface)->enmOGLResType == VMSVGA3D_OGLRESTYPE_BUFFER) +#endif + + +typedef struct VMSVGA3DSHADER +{ + uint32_t id; /** @todo Rename to shid. */ + uint32_t cid; + SVGA3dShaderType type; + uint32_t cbData; + void *pShaderProgram; + union + { +#ifdef VMSVGA3D_DIRECT3D + IDirect3DVertexShader9 *pVertexShader; + IDirect3DPixelShader9 *pPixelShader; +#else + void *pVertexShader; + void *pPixelShader; +#endif + } u; +} VMSVGA3DSHADER; +typedef VMSVGA3DSHADER *PVMSVGA3DSHADER; + +#ifdef VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +/** + * SSM descriptor table for the VMSVGA3DSHADER structure. + */ +static SSMFIELD const g_aVMSVGA3DSHADERFields[] = +{ + SSMFIELD_ENTRY( VMSVGA3DSHADER, id), + SSMFIELD_ENTRY( VMSVGA3DSHADER, cid), + SSMFIELD_ENTRY( VMSVGA3DSHADER, type), + SSMFIELD_ENTRY( VMSVGA3DSHADER, cbData), + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DSHADER, pShaderProgram), + SSMFIELD_ENTRY_TERM() +}; +#endif + +/** @name VMSVGA3D_UPDATE_XXX - ... + * @{ */ +#define VMSVGA3D_UPDATE_SCISSORRECT RT_BIT_32(0) +#define VMSVGA3D_UPDATE_ZRANGE RT_BIT_32(1) +#define VMSVGA3D_UPDATE_VIEWPORT RT_BIT_32(2) +#define VMSVGA3D_UPDATE_VERTEXSHADER RT_BIT_32(3) +#define VMSVGA3D_UPDATE_PIXELSHADER RT_BIT_32(4) +#define VMSVGA3D_UPDATE_TRANSFORM RT_BIT_32(5) +#define VMSVGA3D_UPDATE_MATERIAL RT_BIT_32(6) +/** @} */ + +/* Query states. Mostly used for saved state. */ +typedef enum VMSVGA3DQUERYSTATE +{ + VMSVGA3DQUERYSTATE_NULL = 0, /* Not created. */ + VMSVGA3DQUERYSTATE_SIGNALED = 1, /* Result obtained. The guest may or may not read the result yet. */ + VMSVGA3DQUERYSTATE_BUILDING = 2, /* In process of collecting data. */ + VMSVGA3DQUERYSTATE_ISSUED = 3, /* Data collected, but result is not yet obtained. */ + VMSVGA3DQUERYSTATE_32BIT = 0x7fffffff +} VMSVGA3DQUERYSTATE; +AssertCompileSize(VMSVGA3DQUERYSTATE, sizeof(uint32_t)); + +typedef struct VMSVGA3DQUERY +{ +#ifdef VMSVGA3D_DIRECT3D + IDirect3DQuery9 *pQuery; +#else /* VMSVGA3D_OPENGL */ + GLuint idQuery; +#endif + VMSVGA3DQUERYSTATE enmQueryState; /* VMSVGA3DQUERYSTATE_*. State is implicitly _NULL if pQuery is NULL. */ + uint32_t u32QueryResult; /* Generic result. Enough for all VGPU9 queries. */ +} VMSVGA3DQUERY; + +#ifdef VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +/** + * SSM descriptor table for the VMSVGA3DQUERY structure. + */ +static SSMFIELD const g_aVMSVGA3DQUERYFields[] = +{ +#ifdef VMSVGA3D_DIRECT3D + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DQUERY, pQuery), +#else /* VMSVGA3D_OPENGL */ + SSMFIELD_ENTRY_IGNORE( VMSVGA3DQUERY, idQuery), +#endif + SSMFIELD_ENTRY( VMSVGA3DQUERY, enmQueryState), + SSMFIELD_ENTRY( VMSVGA3DQUERY, u32QueryResult), + SSMFIELD_ENTRY_TERM() +}; +#endif + +#ifdef VMSVGA3D_DIRECT3D +#define VMSVGA3DQUERY_EXISTS(p) ((p)->pQuery && (p)->enmQueryState != VMSVGA3DQUERYSTATE_NULL) +#else +#define VMSVGA3DQUERY_EXISTS(p) ((p)->idQuery && (p)->enmQueryState != VMSVGA3DQUERYSTATE_NULL) +#endif + +/** + * VMSVGA3d context. + */ +typedef struct VMSVGA3DCONTEXT +{ + /** @todo Legacy contexts with DX backend. */ + + uint32_t id; +#ifdef RT_OS_WINDOWS +# ifdef VMSVGA3D_DIRECT3D + IDirect3DDevice9Ex *pDevice; +# else + /* Device context of the context window. */ + HDC hdc; + /* OpenGL rendering context handle. */ + HGLRC hglrc; +# endif + /* Device context window handle. */ + HWND hwnd; +#elif defined(RT_OS_DARWIN) + /* OpenGL rendering context */ + NativeNSOpenGLContextRef cocoaContext; + NativeNSViewRef cocoaView; + bool fOtherProfile; +#else + /** XGL rendering context handle */ + GLXContext glxContext; + /** Device context window handle */ + Window window; +#endif + +#ifdef VMSVGA3D_OPENGL + /* Framebuffer object associated with this context. */ + GLuint idFramebuffer; + /* Read and draw framebuffer objects for various operations. */ + GLuint idReadFramebuffer; + GLuint idDrawFramebuffer; + /* Last GL error recorded. */ + GLenum lastError; + void *pShaderContext; +#endif + + /* Current selected texture surfaces (if any) */ + uint32_t aSidActiveTextures[SVGA3D_MAX_SAMPLERS]; + /* Per context pixel and vertex shaders. */ + uint32_t cPixelShaders; + PVMSVGA3DSHADER paPixelShader; + uint32_t cVertexShaders; + PVMSVGA3DSHADER paVertexShader; + /* Keep track of the internal state to be able to recreate the context properly (save/restore, window resize). */ + struct + { + /** VMSVGA3D_UPDATE_XXX */ + uint32_t u32UpdateFlags; + + SVGA3dRenderState aRenderState[SVGA3D_RS_MAX]; + /* aTextureStates contains both TextureStageStates and SamplerStates, therefore [SVGA3D_MAX_SAMPLERS]. */ + SVGA3dTextureState aTextureStates[SVGA3D_MAX_SAMPLERS][SVGA3D_TS_MAX]; + VMSVGATRANSFORMSTATE aTransformState[SVGA3D_TRANSFORM_MAX]; + VMSVGAMATERIALSTATE aMaterial[SVGA3D_FACE_MAX]; + /* The aClipPlane array has a wrong (greater) size. Keep it for now because the array is a part of the saved state. */ + /** @todo Replace SVGA3D_CLIPPLANE_5 with SVGA3D_NUM_CLIPPLANES and increase the saved state version. */ + VMSVGACLIPPLANESTATE aClipPlane[SVGA3D_CLIPPLANE_5]; + VMSVGALIGHTSTATE aLightData[SVGA3D_MAX_LIGHTS]; + + uint32_t aRenderTargets[SVGA3D_RT_MAX]; + SVGA3dRect RectScissor; + SVGA3dRect RectViewPort; + SVGA3dZRange zRange; + uint32_t shidPixel; + uint32_t shidVertex; + + uint32_t cPixelShaderConst; + PVMSVGASHADERCONST paPixelShaderConst; + uint32_t cVertexShaderConst; + PVMSVGASHADERCONST paVertexShaderConst; + } state; + + /* Occlusion query. */ + VMSVGA3DQUERY occlusion; + +#ifdef VMSVGA3D_DIRECT3D + /* State which is currently applied to the D3D device. It is recreated as needed and not saved. + * The purpose is to remember the currently applied state and do not re-apply it if it has not changed. + * Unnecessary state changes are very bad for performance. + */ + struct + { + /* Vertex declaration. */ + IDirect3DVertexDeclaration9 *pVertexDecl; + uint32_t cVertexElements; + D3DVERTEXELEMENT9 aVertexElements[SVGA3D_MAX_VERTEX_ARRAYS + 1]; + } d3dState; +#endif +} VMSVGA3DCONTEXT; +/** Pointer to a VMSVGA3d context. */ +typedef VMSVGA3DCONTEXT *PVMSVGA3DCONTEXT; + +#ifdef VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +/* Verify that constants did not change for the legacy context saved state data. */ +AssertCompile(SVGA3D_RS_MAX == 99); +AssertCompile(SVGA3D_TRANSFORM_MAX == 15); +AssertCompile(SVGA3D_FACE_MAX == 5); +AssertCompile(SVGA3D_CLIPPLANE_5 == (1 << 5)); +AssertCompile(SVGA3D_MAX_LIGHTS == 32); +AssertCompile(SVGA3D_RT_MAX == 10); + +/** + * SSM descriptor table for the VMSVGA3DCONTEXT structure. + */ +static SSMFIELD const g_aVMSVGA3DCONTEXTFields[] = +{ + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, id), + +# ifdef RT_OS_WINDOWS +# ifdef VMSVGA3D_DIRECT3D + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DCONTEXT, pDevice), +# else + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, hdc), + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, hglrc), +# endif + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, hwnd), +# elif defined(RT_OS_DARWIN) + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, cocoaContext), + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, cocoaView), + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, fOtherProfile), +# else + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, glxContext), + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, window), +# endif + +#ifdef VMSVGA3D_OPENGL + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, idFramebuffer), + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, idReadFramebuffer), + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, idDrawFramebuffer), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, lastError), + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DCONTEXT, pShaderContext), +#endif + + SSMFIELD_ENTRY_IGNORE( VMSVGA3DCONTEXT, aSidActiveTextures), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, cPixelShaders), + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DCONTEXT, paPixelShader), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, cVertexShaders), + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DCONTEXT, paVertexShader), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.u32UpdateFlags), + + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.aRenderState), + SSMFIELD_ENTRY_OLD( state.aTextureStates, + sizeof(SVGA3dTextureState) * /*SVGA3D_MAX_TEXTURE_STAGE=*/ 8 * /*SVGA3D_TS_MAX=*/ 30), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.aTransformState), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.aMaterial), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.aClipPlane), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.aLightData), + + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.aRenderTargets), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.RectScissor), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.RectViewPort), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.zRange), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.shidPixel), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.shidVertex), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.cPixelShaderConst), + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DCONTEXT, state.paPixelShaderConst), + SSMFIELD_ENTRY( VMSVGA3DCONTEXT, state.cVertexShaderConst), + SSMFIELD_ENTRY_IGN_HCPTR( VMSVGA3DCONTEXT, state.paVertexShaderConst), + SSMFIELD_ENTRY_TERM() +}; +#endif /* VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS */ + + +#ifdef VMSVGA3D_DX +/* The 3D backend DX context. The actual structure is 3D API specific. */ +typedef struct VMSVGA3DBACKENDDXCONTEXT *PVMSVGA3DBACKENDDXCONTEXT; + +/** + * VMSVGA3D DX context (VGPU10+). DX contexts ids are a separate namespace from legacy context ids. + */ +typedef struct VMSVGA3DDXCONTEXT +{ + /** The DX context id. */ + uint32_t cid; + /** . */ + uint32_t u32Reserved; + /** . */ + uint32_t cRenderTargets; + /** Backend specific data. */ + PVMSVGA3DBACKENDDXCONTEXT pBackendDXContext; + /** Copy of the guest memory for this context. The guest will be updated on unbind. */ + SVGADXContextMobFormat svgaDXContext; + /* Context-Object Tables bound to this context. */ + PVMSVGAMOB aCOTMobs[SVGA_COTABLE_MAX]; + struct + { + SVGACOTableDXRTViewEntry *paRTView; + SVGACOTableDXDSViewEntry *paDSView; + SVGACOTableDXSRViewEntry *paSRView; + SVGACOTableDXElementLayoutEntry *paElementLayout; + SVGACOTableDXBlendStateEntry *paBlendState; + SVGACOTableDXDepthStencilEntry *paDepthStencil; + SVGACOTableDXRasterizerStateEntry *paRasterizerState; + SVGACOTableDXSamplerEntry *paSampler; + SVGACOTableDXStreamOutputEntry *paStreamOutput; + SVGACOTableDXQueryEntry *paQuery; + SVGACOTableDXShaderEntry *paShader; + SVGACOTableDXUAViewEntry *paUAView; + uint32_t cRTView; + uint32_t cDSView; + uint32_t cSRView; + uint32_t cElementLayout; + uint32_t cBlendState; + uint32_t cDepthStencil; + uint32_t cRasterizerState; + uint32_t cSampler; + uint32_t cStreamOutput; + uint32_t cQuery; + uint32_t cShader; + uint32_t cUAView; + } cot; +} VMSVGA3DDXCONTEXT; +/** Pointer to a VMSVGA3D DX context. */ +typedef VMSVGA3DDXCONTEXT *PVMSVGA3DDXCONTEXT; +#endif /* VMSVGA3D_DX */ + + +#ifdef VMSVGA3D_OPENGL +typedef struct VMSVGA3DFORMATCONVERTER *PVMSVGA3DFORMATCONVERTER; +#endif + +/* The 3D backend. The actual structure is 3D API specific. */ +typedef struct VMSVGA3DBACKEND *PVMSVGA3DBACKEND; + +/** + * VMSVGA3d state data. + * + * Allocated on the heap and pointed to by VMSVGAState::p3dState. + */ +typedef struct VMSVGA3DSTATE +{ + /** Backend specific data. */ + PVMSVGA3DBACKEND pBackend; + + /** The size of papContexts. */ + uint32_t cContexts; + /** The size of papSurfaces. */ + uint32_t cSurfaces; +#ifdef VMSVGA3D_DX + /** The size of papDXContexts. */ + uint32_t cDXContexts; + /** Reserved. */ + uint32_t u32Reserved; +#endif + /** Contexts indexed by ID. Grown as needed. */ + PVMSVGA3DCONTEXT *papContexts; + /** Surfaces indexed by ID. Grown as needed. */ + PVMSVGA3DSURFACE *papSurfaces; +#ifdef VMSVGA3D_DX + /** DX contexts indexed by ID. Grown as needed. */ + PVMSVGA3DDXCONTEXT *papDXContexts; +#endif + +#ifdef RT_OS_WINDOWS +# ifdef VMSVGA3D_DIRECT3D + IDirect3D9Ex *pD3D9; + D3DCAPS9 caps; + bool fSupportedSurfaceINTZ; + bool fSupportedSurfaceNULL; + bool fSupportedFormatUYVY : 1; + bool fSupportedFormatYUY2 : 1; + bool fSupportedFormatA8B8G8R8 : 1; +# endif + /** Window Thread. */ + R3PTRTYPE(RTTHREAD) pWindowThread; + DWORD idWindowThread; + HMODULE hInstance; + /** Window request semaphore. */ + RTSEMEVENT WndRequestSem; +#elif defined(RT_OS_DARWIN) +#else + /* The X display */ + Display *display; + R3PTRTYPE(RTTHREAD) pWindowThread; + bool bTerminate; +#endif + +#ifdef VMSVGA3D_OPENGL + float rsGLVersion; + /* Current active context. */ + uint32_t idActiveContext; + + struct + { + PFNGLISRENDERBUFFERPROC glIsRenderbuffer; + PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; + PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; + PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; + PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; + PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv; + PFNGLISFRAMEBUFFERPROC glIsFramebuffer; + PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; + PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; + PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; + PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; + PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; + PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; + PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; + PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; + PFNGLGENERATEMIPMAPPROC glGenerateMipmap; + PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample; + PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer; + PFNGLPOINTPARAMETERFPROC glPointParameterf; +#if VBOX_VMSVGA3D_GL_HACK_LEVEL < 0x102 + PFNGLBLENDCOLORPROC glBlendColor; + PFNGLBLENDEQUATIONPROC glBlendEquation; +#endif + PFNGLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate; + PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate; + PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate; + PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate; + PFNGLBINDBUFFERPROC glBindBuffer; + PFNGLDELETEBUFFERSPROC glDeleteBuffers; + PFNGLGENBUFFERSPROC glGenBuffers; + PFNGLBUFFERDATAPROC glBufferData; + PFNGLMAPBUFFERPROC glMapBuffer; + PFNGLUNMAPBUFFERPROC glUnmapBuffer; + PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; + PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray; + PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; + PFNGLFOGCOORDPOINTERPROC glFogCoordPointer; + PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex; + PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex; + PFNGLACTIVETEXTUREPROC glActiveTexture; +#if VBOX_VMSVGA3D_GL_HACK_LEVEL < 0x103 + PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture; +#endif + PFNGLGETPROGRAMIVARBPROC glGetProgramivARB; + PFNGLPROVOKINGVERTEXPROC glProvokingVertex; + PFNGLGENQUERIESPROC glGenQueries; + PFNGLDELETEQUERIESPROC glDeleteQueries; + PFNGLBEGINQUERYPROC glBeginQuery; + PFNGLENDQUERYPROC glEndQuery; + PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv; + PFNGLTEXIMAGE3DPROC glTexImage3D; + PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D; + PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor; + PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced; + PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced; + PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage; + PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D; + PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D; + PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D; + PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D; + PFNGLDRAWBUFFERSPROC glDrawBuffers; + PFNGLCREATESHADERPROC glCreateShader; + PFNGLSHADERSOURCEPROC glShaderSource; + PFNGLCOMPILESHADERPROC glCompileShader; + PFNGLGETSHADERIVPROC glGetShaderiv; + PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; + PFNGLCREATEPROGRAMPROC glCreateProgram; + PFNGLATTACHSHADERPROC glAttachShader; + PFNGLLINKPROGRAMPROC glLinkProgram; + PFNGLGETPROGRAMIVPROC glGetProgramiv; + PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; + PFNGLUSEPROGRAMPROC glUseProgram; + PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; + PFNGLUNIFORM1IPROC glUniform1i; + PFNGLUNIFORM4FVPROC glUniform4fv; + PFNGLDETACHSHADERPROC glDetachShader; + PFNGLDELETESHADERPROC glDeleteShader; + PFNGLDELETEPROGRAMPROC glDeleteProgram; + PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv; + PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv; + PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4Nubv; + PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv; + PFNGLVERTEXATTRIB4NSVPROC glVertexAttrib4Nsv; + PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4Nusv; + } ext; + + struct + { + bool fS3TCSupported : 1; + bool fTextureFilterAnisotropicSupported : 1; + GLint maxActiveLights; + GLint maxTextures; + GLint maxClipDistances; + GLint maxColorAttachments; + GLint maxRectangleTextureSize; + GLint maxTextureAnisotropy; + GLint maxVertexShaderInstructions; + GLint maxFragmentShaderInstructions; + GLint maxVertexShaderTemps; + GLint maxFragmentShaderTemps; + GLfloat flPointSize[2]; + SVGA3dPixelShaderVersion fragmentShaderVersion; + SVGA3dVertexShaderVersion vertexShaderVersion; + } caps; + + /** The GL_EXTENSIONS value (space padded) for the default OpenGL profile. + * Free with RTStrFree. */ + R3PTRTYPE(char *) pszExtensions; + + /** The GL_EXTENSIONS value (space padded) for the other OpenGL profile. + * Free with RTStrFree. + * + * This is used to detect shader model version since some implementations + * (darwin) hides extensions that have made it into core and probably a + * bunch of others when using a OpenGL core profile instead of a legacy one */ + R3PTRTYPE(char *) pszOtherExtensions; + /** The version of the other GL profile. */ + float rsOtherGLVersion; + + /** Shader talk back interface. */ + VBOXVMSVGASHADERIF ShaderIf; + +# ifdef VMSVGA3D_OPENGL + /** The shared context. */ + VMSVGA3DCONTEXT SharedCtx; + + /** Conversion of emulated formats. Resources are created on the SharedCtx. */ + PVMSVGA3DFORMATCONVERTER pConv; +# endif +#endif /* VMSVGA3D_OPENGL */ +} VMSVGA3DSTATE; + +#ifdef VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +/** + * SSM descriptor table for the VMSVGA3DSTATE structure. + * + * @remarks This isn't a complete structure markup, only fields with state. + */ +static SSMFIELD const g_aVMSVGA3DSTATEFields[] = +{ +# ifdef VMSVGA3D_OPENGL + SSMFIELD_ENTRY( VMSVGA3DSTATE, rsGLVersion), /** @todo Why are we saving the GL version?? */ +# endif + SSMFIELD_ENTRY( VMSVGA3DSTATE, cContexts), + SSMFIELD_ENTRY( VMSVGA3DSTATE, cSurfaces), + SSMFIELD_ENTRY_TERM() +}; +#endif /* VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS */ + + +#ifdef VMSVGA3D_DIRECT3D +D3DFORMAT vmsvga3dSurfaceFormat2D3D(SVGA3dSurfaceFormat format); +D3DMULTISAMPLE_TYPE vmsvga3dMultipeSampleCount2D3D(uint32_t multisampleCount); +DECLCALLBACK(int) vmsvga3dSharedSurfaceDestroyTree(PAVLU32NODECORE pNode, void *pvParam); +int vmsvga3dSurfaceFlush(PVMSVGA3DSURFACE pSurface); +#endif /* VMSVGA3D_DIRECT3D */ + + +#ifdef VMSVGA3D_OPENGL +/** Save and setup everything. */ +# define VMSVGA3D_PARANOID_TEXTURE_PACKING + +/** @name VMSVGAPACKPARAMS_* - which packing parameters were set. + * @{ */ +# define VMSVGAPACKPARAMS_ALIGNMENT RT_BIT_32(0) +# define VMSVGAPACKPARAMS_ROW_LENGTH RT_BIT_32(1) +# define VMSVGAPACKPARAMS_IMAGE_HEIGHT RT_BIT_32(2) +# define VMSVGAPACKPARAMS_SWAP_BYTES RT_BIT_32(3) +# define VMSVGAPACKPARAMS_LSB_FIRST RT_BIT_32(4) +# define VMSVGAPACKPARAMS_SKIP_ROWS RT_BIT_32(5) +# define VMSVGAPACKPARAMS_SKIP_PIXELS RT_BIT_32(6) +# define VMSVGAPACKPARAMS_SKIP_IMAGES RT_BIT_32(7) +/** @} */ + +/** + * Saved texture packing parameters (shared by both pack and unpack). + */ +typedef struct VMSVGAPACKPARAMS +{ + uint32_t fChanged; + GLint iAlignment; + GLint cxRow; + GLint cyImage; +# ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING + GLboolean fSwapBytes; + GLboolean fLsbFirst; + GLint cSkipRows; + GLint cSkipPixels; + GLint cSkipImages; +# endif +} VMSVGAPACKPARAMS; +/** Pointer to saved texture packing parameters. */ +typedef VMSVGAPACKPARAMS *PVMSVGAPACKPARAMS; +/** Pointer to const saved texture packing parameters. */ +typedef VMSVGAPACKPARAMS const *PCVMSVGAPACKPARAMS; + +void vmsvga3dOglSetPackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface, + PVMSVGAPACKPARAMS pSave); +void vmsvga3dOglRestorePackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface, + PCVMSVGAPACKPARAMS pSave); +void vmsvga3dOglSetUnpackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, GLint cxRow, GLint cyImage, + PVMSVGAPACKPARAMS pSave); +void vmsvga3dOglRestoreUnpackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, + PCVMSVGAPACKPARAMS pSave); + +/** @name VMSVGA3D_DEF_CTX_F_XXX - vmsvga3dContextDefineOgl flags. + * @{ */ +/** When clear, the context is created using the default OpenGL profile. + * When set, it's created using the alternative profile. The latter is only + * allowed if the VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE is set. */ +# define VMSVGA3D_DEF_CTX_F_OTHER_PROFILE RT_BIT_32(0) +/** Defining the shared context. */ +# define VMSVGA3D_DEF_CTX_F_SHARED_CTX RT_BIT_32(1) +/** Defining the init time context (EMT). */ +# define VMSVGA3D_DEF_CTX_F_INIT RT_BIT_32(2) +/** @} */ +int vmsvga3dContextDefineOgl(PVGASTATECC pThisCC, uint32_t cid, uint32_t fFlags); +void vmsvga3dSurfaceFormat2OGL(PVMSVGA3DSURFACE pSurface, SVGA3dSurfaceFormat format); + +#endif /* VMSVGA3D_OPENGL */ + + +/* DevVGA-SVGA3d-shared.cpp: */ +int vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, + uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4); + + +DECLINLINE(int) vmsvga3dContextFromCid(PVMSVGA3DSTATE pState, uint32_t cid, PVMSVGA3DCONTEXT *ppContext) +{ + AssertReturn(cid < pState->cContexts, VERR_INVALID_PARAMETER); + PVMSVGA3DCONTEXT const pContext = pState->papContexts[cid]; + if (RT_LIKELY(pContext && pContext->id == cid)) + { + *ppContext = pContext; + return VINF_SUCCESS; + } + LogRelMax(64, ("VMSVGA: unknown cid=%u (%s cid=%u)\n", cid, pContext ? "expected" : "null", pContext ? pContext->id : -1)); + return VERR_INVALID_PARAMETER; +} + +#ifdef VMSVGA3D_DX +DECLINLINE(int) vmsvga3dDXContextFromCid(PVMSVGA3DSTATE pState, uint32_t cid, PVMSVGA3DDXCONTEXT *ppDXContext) +{ + *ppDXContext = NULL; + AssertReturn(cid < pState->cDXContexts, VERR_INVALID_PARAMETER); + PVMSVGA3DDXCONTEXT const pDXContext = pState->papDXContexts[cid]; + if (RT_LIKELY(pDXContext && pDXContext->cid == cid)) + { + *ppDXContext = pDXContext; + return VINF_SUCCESS; + } + LogRelMax(64, ("VMSVGA: unknown DX cid=%u (%s cid=%u)\n", cid, pDXContext ? "expected" : "null", pDXContext ? pDXContext->cid : -1)); + return VERR_INVALID_PARAMETER; +} +#endif + +DECLINLINE(int) vmsvga3dSurfaceFromSid(PVMSVGA3DSTATE pState, uint32_t sid, PVMSVGA3DSURFACE *ppSurface) +{ + AssertReturn(sid < pState->cSurfaces, VERR_INVALID_PARAMETER); + PVMSVGA3DSURFACE const pSurface = pState->papSurfaces[sid]; + if (RT_LIKELY(pSurface && pSurface->id == sid)) + { + *ppSurface = pSurface; + return VINF_SUCCESS; + } + LogRelMax(64, ("VMSVGA: unknown sid=%u (%s sid=%u)\n", sid, pSurface ? "expected" : "null", pSurface ? pSurface->id : -1)); + return VERR_INVALID_PARAMETER; +} + +DECLINLINE(int) vmsvga3dMipmapLevel(PVMSVGA3DSURFACE pSurface, uint32_t iArrayElement, uint32_t mipmap, + PVMSVGA3DMIPMAPLEVEL *ppMipmapLevel) +{ + AssertMsgReturn(iArrayElement < pSurface->surfaceDesc.numArrayElements, + ("numArrayElements %d, iArrayElement %d\n", pSurface->surfaceDesc.numArrayElements, iArrayElement), + VERR_INVALID_PARAMETER); + AssertMsgReturn(mipmap < pSurface->cLevels, + ("numMipLevels %d, mipmap %d", pSurface->cLevels, mipmap), + VERR_INVALID_PARAMETER); + + *ppMipmapLevel = &pSurface->paMipmapLevels[iArrayElement * pSurface->cLevels + mipmap]; + return VINF_SUCCESS; +} + +void vmsvga3dInfoSurfaceToBitmap(PCDBGFINFOHLP pHlp, PVMSVGA3DSURFACE pSurface, + const char *pszPath, const char *pszNamePrefix, const char *pszNameSuffix); + +void vmsvga3dSurfaceMapInit(VMSVGA3D_MAPPED_SURFACE *pMap, VMSVGA3D_SURFACE_MAP enmMapType, SVGA3dBox const *pBox, + PVMSVGA3DSURFACE pSurface, void *pvData, uint32_t cbRowPitch, uint32_t cbDepthPitch); + +#if defined(RT_OS_WINDOWS) +#define D3D_RELEASE(ptr) do { \ + if (ptr) \ + { \ + (ptr)->Release(); \ + (ptr) = 0; \ + } \ +} while (0) +#endif + +#if defined(VMSVGA3D_DIRECT3D) +HRESULT D3D9UpdateTexture(PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pSurface); +HRESULT D3D9GetRenderTargetData(PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pSurface, + uint32_t uFace, + uint32_t uMipmap); +HRESULT D3D9GetSurfaceLevel(PVMSVGA3DSURFACE pSurface, + uint32_t uFace, + uint32_t uMipmap, + bool fBounce, + IDirect3DSurface9 **ppD3DSurface); +D3DFORMAT D3D9GetActualFormat(PVMSVGA3DSTATE pState, + D3DFORMAT d3dfmt); +bool D3D9CheckDeviceFormat(IDirect3D9 *pD3D9, + DWORD Usage, + D3DRESOURCETYPE RType, + D3DFORMAT CheckFormat); +#endif + +#ifdef VMSVGA3D_OPENGL +void vmsvga3dOnSharedContextDefine(PVMSVGA3DSTATE pState); +void vmsvga3dOnSharedContextDestroy(PVMSVGA3DSTATE pState); + +DECLINLINE(GLuint) GLTextureId(PVMSVGA3DSURFACE pSurface) +{ + return pSurface->fEmulated ? pSurface->idEmulated : pSurface->oglId.texture; +} + +void FormatConvUpdateTexture(PVMSVGA3DSTATE pState, + PVMSVGA3DCONTEXT pCurrentContext, + PVMSVGA3DSURFACE pSurface, + uint32_t iMipmap); +void FormatConvReadTexture(PVMSVGA3DSTATE pState, + PVMSVGA3DCONTEXT pCurrentContext, + PVMSVGA3DSURFACE pSurface, + uint32_t iMipmap); +#endif + +int vmsvga3dShaderParse(SVGA3dShaderType type, uint32_t cbShaderData, uint32_t *pShaderData); +void vmsvga3dShaderLogRel(char const *pszMsg, SVGA3dShaderType type, uint32_t cbShaderData, uint32_t const *pShaderData); + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_internal_h */ + diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp new file mode 100644 index 00000000..2175d2ca --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp @@ -0,0 +1,7967 @@ +/* $Id: DevVGA-SVGA3d-ogl.cpp $ */ +/** @file + * DevVMWare - VMWare SVGA device + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +/* Enable to disassemble defined shaders. (Windows host only) */ +#if defined(RT_OS_WINDOWS) && defined(DEBUG) && 0 /* Disabled as we don't have the DirectX SDK avaible atm. */ +# define DUMP_SHADER_DISASSEMBLY +#endif +#ifdef DEBUG_bird +//# define RTMEM_WRAP_TO_EF_APIS +#endif +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#define GL_SILENCE_DEPRECATION /* shut up deprecated warnings on darwin (10.15 sdk) */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include /* required by DevVGA.h */ +#include + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#include "DevVGA-SVGA3d-internal.h" + +#ifdef DUMP_SHADER_DISASSEMBLY +# include +#endif + +#include +#include +#include /* FLT_MIN */ + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#ifndef VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE +# define VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE 1.0 +#endif + +#ifdef VMSVGA3D_DYNAMIC_LOAD +# define OGLGETPROCADDRESS glLdrGetProcAddress +#else +#ifdef RT_OS_WINDOWS +# define OGLGETPROCADDRESS MyWinGetProcAddress +DECLINLINE(PROC) MyWinGetProcAddress(const char *pszSymbol) +{ + /* Khronos: [on failure] "some implementations will return other values. 1, 2, and 3 are used, as well as -1". */ + PROC p = wglGetProcAddress(pszSymbol); + if (RT_VALID_PTR(p)) + return p; + return 0; +} +#elif defined(RT_OS_DARWIN) +# include +# define OGLGETPROCADDRESS MyNSGLGetProcAddress +/** Resolves an OpenGL symbol. */ +static void *MyNSGLGetProcAddress(const char *pszSymbol) +{ + /* Another copy in shaderapi.c. */ + static void *s_pvImage = NULL; + if (s_pvImage == NULL) + s_pvImage = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); + return s_pvImage ? dlsym(s_pvImage, pszSymbol) : NULL; +} + +#else +# define OGLGETPROCADDRESS(x) glXGetProcAddress((const GLubyte *)x) +#endif +#endif + +/* Invert y-coordinate for OpenGL's bottom left origin. */ +#define D3D_TO_OGL_Y_COORD(ptrSurface, y_coordinate) (ptrSurface->paMipmapLevels[0].mipmapSize.height - (y_coordinate)) +#define D3D_TO_OGL_Y_COORD_MIPLEVEL(ptrMipLevel, y_coordinate) (ptrMipLevel->size.height - (y_coordinate)) + +/** + * Macro for doing something and then checking for errors during initialization. + * Uses AssertLogRelMsg. + */ +#define VMSVGA3D_INIT_CHECKED(a_Expr) \ + do \ + { \ + a_Expr; \ + GLenum iGlError = glGetError(); \ + AssertLogRelMsg(iGlError == GL_NO_ERROR, ("VMSVGA3d: %s -> %#x\n", #a_Expr, iGlError)); \ + } while (0) + +/** + * Macro for doing something and then checking for errors during initialization, + * doing the same in the other context when enabled. + * + * This will try both profiles in dual profile builds. Caller must be in the + * default context. + * + * Uses AssertLogRelMsg to indicate trouble. + */ +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE +# define VMSVGA3D_INIT_CHECKED_BOTH(a_pState, a_pContext, a_pOtherCtx, a_Expr) \ + do \ + { \ + for (uint32_t i = 0; i < 64; i++) if (glGetError() == GL_NO_ERROR) break; Assert(glGetError() == GL_NO_ERROR); \ + a_Expr; \ + GLenum iGlError = glGetError(); \ + if (iGlError != GL_NO_ERROR) \ + { \ + VMSVGA3D_SET_CURRENT_CONTEXT(a_pState, a_pOtherCtx); \ + for (uint32_t i = 0; i < 64; i++) if (glGetError() == GL_NO_ERROR) break; Assert(glGetError() == GL_NO_ERROR); \ + a_Expr; \ + GLenum iGlError2 = glGetError(); \ + AssertLogRelMsg(iGlError2 == GL_NO_ERROR, ("VMSVGA3d: %s -> %#x / %#x\n", #a_Expr, iGlError, iGlError2)); \ + VMSVGA3D_SET_CURRENT_CONTEXT(a_pState, a_pContext); \ + } \ + } while (0) +#else +# define VMSVGA3D_INIT_CHECKED_BOTH(a_pState, a_pContext, a_pOtherCtx, a_Expr) VMSVGA3D_INIT_CHECKED(a_Expr) +#endif + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/* Define the default light parameters as specified by MSDN. */ +/** @todo move out; fetched from Wine */ +const SVGA3dLightData vmsvga3d_default_light = +{ + SVGA3D_LIGHTTYPE_DIRECTIONAL, /* type */ + false, /* inWorldSpace */ + { 1.0f, 1.0f, 1.0f, 0.0f }, /* diffuse r,g,b,a */ + { 0.0f, 0.0f, 0.0f, 0.0f }, /* specular r,g,b,a */ + { 0.0f, 0.0f, 0.0f, 0.0f }, /* ambient r,g,b,a, */ + { 0.0f, 0.0f, 0.0f }, /* position x,y,z */ + { 0.0f, 0.0f, 1.0f }, /* direction x,y,z */ + 0.0f, /* range */ + 0.0f, /* falloff */ + 0.0f, 0.0f, 0.0f, /* attenuation 0,1,2 */ + 0.0f, /* theta */ + 0.0f /* phi */ +}; + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ +static int vmsvga3dContextDestroyOgl(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid); +static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid); +static void vmsvgaColor2GLFloatArray(uint32_t color, GLfloat *pRed, GLfloat *pGreen, GLfloat *pBlue, GLfloat *pAlpha); +static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData); +static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]); +static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type); +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext); +static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, PVMSVGA3DSURFACE pSurface); + +/* Generated by VBoxDef2LazyLoad from the VBoxSVGA3D.def and VBoxSVGA3DObjC.def files. */ +extern "C" int ExplicitlyLoadVBoxSVGA3D(bool fResolveAllImports, PRTERRINFO pErrInfo); + + +/** + * Checks if the given OpenGL extension is supported. + * + * @returns true if supported, false if not. + * @param pState The VMSVGA3d state. + * @param rsMinGLVersion The OpenGL version that introduced this feature + * into the core. + * @param pszWantedExtension The name of the OpenGL extension we want padded + * with one space at each end. + * @remarks Init time only. + */ +static bool vmsvga3dCheckGLExtension(PVMSVGA3DSTATE pState, float rsMinGLVersion, const char *pszWantedExtension) +{ + RT_NOREF(rsMinGLVersion); + /* check padding. */ + Assert(pszWantedExtension[0] == ' '); + Assert(pszWantedExtension[1] != ' '); + Assert(strchr(&pszWantedExtension[1], ' ') + 1 == strchr(pszWantedExtension, '\0')); + + /* Look it up. */ + bool fRet = false; + if (strstr(pState->pszExtensions, pszWantedExtension)) + fRet = true; + + /* Temporarily. Later start if (rsMinGLVersion != 0.0 && fActualGLVersion >= rsMinGLVersion) return true; */ +#ifdef RT_OS_DARWIN + AssertMsg( rsMinGLVersion == 0.0 + || fRet == (pState->rsGLVersion >= rsMinGLVersion) + || VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE == 2.1, + ("%s actual:%d min:%d fRet=%d\n", + pszWantedExtension, (int)(pState->rsGLVersion * 10), (int)(rsMinGLVersion * 10), fRet)); +#else + AssertMsg(rsMinGLVersion == 0.0 || fRet == (pState->rsGLVersion >= rsMinGLVersion), + ("%s actual:%d min:%d fRet=%d\n", + pszWantedExtension, (int)(pState->rsGLVersion * 10), (int)(rsMinGLVersion * 10), fRet)); +#endif + return fRet; +} + + +/** + * Outputs GL_EXTENSIONS list to the release log. + */ +static void vmsvga3dLogRelExtensions(const char *pszPrefix, const char *pszExtensions) +{ + /* OpenGL 3.0 interface (glGetString(GL_EXTENSIONS) return NULL). */ + bool fBuffered = RTLogRelSetBuffering(true); + + /* + * Determin the column widths first. + */ + size_t acchWidths[4] = { 1, 1, 1, 1 }; + uint32_t i; + const char *psz = pszExtensions; + for (i = 0; ; i++) + { + while (*psz == ' ') + psz++; + if (!*psz) + break; + + const char *pszEnd = strchr(psz, ' '); + AssertBreak(pszEnd); + size_t cch = pszEnd - psz; + + uint32_t iColumn = i % RT_ELEMENTS(acchWidths); + if (acchWidths[iColumn] < cch) + acchWidths[iColumn] = cch; + + psz = pszEnd; + } + + /* + * Output it. + */ + LogRel(("VMSVGA3d: %sOpenGL extensions (%d):", pszPrefix, i)); + psz = pszExtensions; + for (i = 0; ; i++) + { + while (*psz == ' ') + psz++; + if (!*psz) + break; + + const char *pszEnd = strchr(psz, ' '); + AssertBreak(pszEnd); + size_t cch = pszEnd - psz; + + uint32_t iColumn = i % RT_ELEMENTS(acchWidths); + if (iColumn == 0) + LogRel(("\nVMSVGA3d: %-*.*s", acchWidths[iColumn], cch, psz)); + else if (iColumn != RT_ELEMENTS(acchWidths) - 1) + LogRel((" %-*.*s", acchWidths[iColumn], cch, psz)); + else + LogRel((" %.*s", cch, psz)); + + psz = pszEnd; + } + + RTLogRelSetBuffering(fBuffered); + LogRel(("\n")); +} + +/** + * Gathers the GL_EXTENSIONS list, storing it as a space padded list at + * @a ppszExtensions. + * + * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY + * @param ppszExtensions Pointer to the string pointer. Free with RTStrFree. + * @param fGLProfileVersion The OpenGL profile version. + */ +static int vmsvga3dGatherExtensions(char **ppszExtensions, float fGLProfileVersion) +{ + int rc; + *ppszExtensions = NULL; + + /* + * Try the old glGetString interface first. + */ + const char *pszExtensions = (const char *)glGetString(GL_EXTENSIONS); + if (pszExtensions) + { + rc = RTStrAAppendExN(ppszExtensions, 3, " ", (size_t)1, pszExtensions, RTSTR_MAX, " ", (size_t)1); + AssertLogRelRCReturn(rc, rc); + } + else + { + /* + * The new interface where each extension string is retrieved separately. + * Note! Cannot use VMSVGA3D_INIT_CHECKED_GL_GET_INTEGER_VALUE here because + * the above GL_EXTENSIONS error lingers on darwin. sucks. + */ +#ifndef GL_NUM_EXTENSIONS +# define GL_NUM_EXTENSIONS 0x821D +#endif + GLint cExtensions = 1024; + glGetIntegerv(GL_NUM_EXTENSIONS, &cExtensions); + Assert(cExtensions != 1024); + + PFNGLGETSTRINGIPROC pfnGlGetStringi = (PFNGLGETSTRINGIPROC)OGLGETPROCADDRESS("glGetStringi"); + AssertLogRelReturn(pfnGlGetStringi, VERR_NOT_SUPPORTED); + + rc = RTStrAAppend(ppszExtensions, " "); + for (GLint i = 0; RT_SUCCESS(rc) && i < cExtensions; i++) + { + const char *pszExt = (const char *)pfnGlGetStringi(GL_EXTENSIONS, i); + if (pszExt) + rc = RTStrAAppendExN(ppszExtensions, 2, pfnGlGetStringi(GL_EXTENSIONS, i), RTSTR_MAX, " ", (size_t)1); + } + AssertRCReturn(rc, rc); + } + +#if 1 + /* + * Add extensions promoted into the core OpenGL profile. + */ + static const struct + { + float fGLVersion; + const char *pszzExtensions; + } s_aPromotedExtensions[] = + { + { + 1.1f, + " GL_EXT_vertex_array \0" + " GL_EXT_polygon_offset \0" + " GL_EXT_blend_logic_op \0" + " GL_EXT_texture \0" + " GL_EXT_copy_texture \0" + " GL_EXT_subtexture \0" + " GL_EXT_texture_object \0" + " GL_ARB_framebuffer_object \0" + " GL_ARB_map_buffer_range \0" + " GL_ARB_vertex_array_object \0" + "\0" + }, + { + 1.2f, + " EXT_texture3D \0" + " EXT_bgra \0" + " EXT_packed_pixels \0" + " EXT_rescale_normal \0" + " EXT_separate_specular_color \0" + " SGIS_texture_edge_clamp \0" + " SGIS_texture_lod \0" + " EXT_draw_range_elements \0" + "\0" + }, + { + 1.3f, + " GL_ARB_texture_compression \0" + " GL_ARB_texture_cube_map \0" + " GL_ARB_multisample \0" + " GL_ARB_multitexture \0" + " GL_ARB_texture_env_add \0" + " GL_ARB_texture_env_combine \0" + " GL_ARB_texture_env_dot3 \0" + " GL_ARB_texture_border_clamp \0" + " GL_ARB_transpose_matrix \0" + "\0" + }, + { + 1.5f, + " GL_SGIS_generate_mipmap \0" + /*" GL_NV_blend_equare \0"*/ + " GL_ARB_depth_texture \0" + " GL_ARB_shadow \0" + " GL_EXT_fog_coord \0" + " GL_EXT_multi_draw_arrays \0" + " GL_ARB_point_parameters \0" + " GL_EXT_secondary_color \0" + " GL_EXT_blend_func_separate \0" + " GL_EXT_stencil_wrap \0" + " GL_ARB_texture_env_crossbar \0" + " GL_EXT_texture_lod_bias \0" + " GL_ARB_texture_mirrored_repeat \0" + " GL_ARB_window_pos \0" + "\0" + }, + { + 1.6f, + " GL_ARB_vertex_buffer_object \0" + " GL_ARB_occlusion_query \0" + " GL_EXT_shadow_funcs \0" + }, + { + 2.0f, + " GL_ARB_shader_objects \0" /*??*/ + " GL_ARB_vertex_shader \0" /*??*/ + " GL_ARB_fragment_shader \0" /*??*/ + " GL_ARB_shading_language_100 \0" /*??*/ + " GL_ARB_draw_buffers \0" + " GL_ARB_texture_non_power_of_two \0" + " GL_ARB_point_sprite \0" + " GL_ATI_separate_stencil \0" + " GL_EXT_stencil_two_side \0" + "\0" + }, + { + 2.1f, + " GL_ARB_pixel_buffer_object \0" + " GL_EXT_texture_sRGB \0" + "\0" + }, + { + 3.0f, + " GL_ARB_framebuffer_object \0" + " GL_ARB_map_buffer_range \0" + " GL_ARB_vertex_array_object \0" + "\0" + }, + { + 3.1f, + " GL_ARB_copy_buffer \0" + " GL_ARB_uniform_buffer_object \0" + "\0" + }, + { + 3.2f, + " GL_ARB_vertex_array_bgra \0" + " GL_ARB_draw_elements_base_vertex \0" + " GL_ARB_fragment_coord_conventions \0" + " GL_ARB_provoking_vertex \0" + " GL_ARB_seamless_cube_map \0" + " GL_ARB_texture_multisample \0" + " GL_ARB_depth_clamp \0" + " GL_ARB_sync \0" + " GL_ARB_geometry_shader4 \0" /*??*/ + "\0" + }, + { + 3.3f, + " GL_ARB_blend_func_extended \0" + " GL_ARB_sampler_objects \0" + " GL_ARB_explicit_attrib_location \0" + " GL_ARB_occlusion_query2 \0" + " GL_ARB_shader_bit_encoding \0" + " GL_ARB_texture_rgb10_a2ui \0" + " GL_ARB_texture_swizzle \0" + " GL_ARB_timer_query \0" + " GL_ARB_vertex_type_2_10_10_10_rev \0" + "\0" + }, + { + 4.0f, + " GL_ARB_texture_query_lod \0" + " GL_ARB_draw_indirect \0" + " GL_ARB_gpu_shader5 \0" + " GL_ARB_gpu_shader_fp64 \0" + " GL_ARB_shader_subroutine \0" + " GL_ARB_tessellation_shader \0" + " GL_ARB_texture_buffer_object_rgb32 \0" + " GL_ARB_texture_cube_map_array \0" + " GL_ARB_texture_gather \0" + " GL_ARB_transform_feedback2 \0" + " GL_ARB_transform_feedback3 \0" + "\0" + }, + { + 4.1f, + " GL_ARB_ES2_compatibility \0" + " GL_ARB_get_program_binary \0" + " GL_ARB_separate_shader_objects \0" + " GL_ARB_shader_precision \0" + " GL_ARB_vertex_attrib_64bit \0" + " GL_ARB_viewport_array \0" + "\0" + } + }; + + uint32_t cPromoted = 0; + for (uint32_t i = 0; i < RT_ELEMENTS(s_aPromotedExtensions) && s_aPromotedExtensions[i].fGLVersion <= fGLProfileVersion; i++) + { + const char *pszExt = s_aPromotedExtensions[i].pszzExtensions; + while (*pszExt) + { +# ifdef VBOX_STRICT + size_t cchExt = strlen(pszExt); + Assert(cchExt > 3); + Assert(pszExt[0] == ' '); + Assert(pszExt[1] != ' '); + Assert(pszExt[cchExt - 2] != ' '); + Assert(pszExt[cchExt - 1] == ' '); +# endif + + if (strstr(*ppszExtensions, pszExt) == NULL) + { + if (cPromoted++ == 0) + { + rc = RTStrAAppend(ppszExtensions, " "); + AssertRCReturn(rc, rc); + } + + rc = RTStrAAppend(ppszExtensions, pszExt); + AssertRCReturn(rc, rc); + } + + pszExt = strchr(pszExt, '\0') + 1; + } + } +#endif + + return VINF_SUCCESS; +} + +/** Check whether this is an Intel GL driver. + * + * @returns true if this seems to be some Intel graphics. + */ +static bool vmsvga3dIsVendorIntel(void) +{ + return RTStrNICmp((char *)glGetString(GL_VENDOR), "Intel", 5) == 0; +} + +/** + * @interface_method_impl{VBOXVMSVGASHADERIF,pfnSwitchInitProfile} + */ +static DECLCALLBACK(void) vmsvga3dShaderIfSwitchInitProfile(PVBOXVMSVGASHADERIF pThis, bool fOtherProfile) +{ +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + PVMSVGA3DSTATE pState = RT_FROM_MEMBER(pThis, VMSVGA3DSTATE, ShaderIf); + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pState->papContexts[fOtherProfile ? 2 : 1]); +#else + NOREF(pThis); + NOREF(fOtherProfile); +#endif +} + + +/** + * @interface_method_impl{VBOXVMSVGASHADERIF,pfnGetNextExtension} + */ +static DECLCALLBACK(bool) vmsvga3dShaderIfGetNextExtension(PVBOXVMSVGASHADERIF pThis, void **ppvEnumCtx, + char *pszBuf, size_t cbBuf, bool fOtherProfile) +{ + PVMSVGA3DSTATE pState = RT_FROM_MEMBER(pThis, VMSVGA3DSTATE, ShaderIf); + const char *pszCur = *ppvEnumCtx ? (const char *)*ppvEnumCtx + : fOtherProfile ? pState->pszOtherExtensions : pState->pszExtensions; + while (*pszCur == ' ') + pszCur++; + if (!*pszCur) + return false; + + const char *pszEnd = strchr(pszCur, ' '); + AssertReturn(pszEnd, false); + size_t cch = pszEnd - pszCur; + if (cch < cbBuf) + { + memcpy(pszBuf, pszCur, cch); + pszBuf[cch] = '\0'; + } + else if (cbBuf > 0) + { + memcpy(pszBuf, "", RT_MIN(sizeof(""), cbBuf)); + pszBuf[cbBuf - 1] = '\0'; + } + + *ppvEnumCtx = (void *)pszEnd; + return true; +} + + +/** + * Initializes the VMSVGA3D state during VGA device construction. + * + * Failure are generally not fatal, 3D support will just be disabled. + * + * @returns VBox status code. + * @param pDevIns The device instance. + * @param pThis The shared VGA/VMSVGA state where svga.p3dState will be + * modified. + * @param pThisCC The VGA/VMSVGA state for ring-3. + */ +static DECLCALLBACK(int) vmsvga3dBackInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + int rc; + RT_NOREF(pDevIns, pThis, pThisCC); + + AssertCompile(GL_TRUE == 1); + AssertCompile(GL_FALSE == 0); + +#ifdef VMSVGA3D_DYNAMIC_LOAD + rc = glLdrInit(pDevIns); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: Error loading OpenGL library and resolving necessary functions: %Rrc\n", rc)); + return rc; + } +#endif + + /* + * Load and resolve imports from the external shared libraries. + */ + RTERRINFOSTATIC ErrInfo; + rc = ExplicitlyLoadVBoxSVGA3D(true /*fResolveAllImports*/, RTErrInfoInitStatic(&ErrInfo)); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: Error loading VBoxSVGA3D and resolving necessary functions: %Rrc - %s\n", rc, ErrInfo.Core.pszMsg)); + return rc; + } +#ifdef RT_OS_DARWIN + rc = ExplicitlyLoadVBoxSVGA3DObjC(true /*fResolveAllImports*/, RTErrInfoInitStatic(&ErrInfo)); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: Error loading VBoxSVGA3DObjC and resolving necessary functions: %Rrc - %s\n", rc, ErrInfo.Core.pszMsg)); + return rc; + } +#endif + +#ifdef RT_OS_WINDOWS + /* Create event semaphore and async IO thread. */ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + rc = RTSemEventCreate(&pState->WndRequestSem); + if (RT_SUCCESS(rc)) + { + rc = RTThreadCreate(&pState->pWindowThread, vmsvga3dWindowThread, pState->WndRequestSem, 0, RTTHREADTYPE_GUI, 0, + "VMSVGA3DWND"); + if (RT_SUCCESS(rc)) + return VINF_SUCCESS; + + /* bail out. */ + LogRel(("VMSVGA3d: RTThreadCreate failed: %Rrc\n", rc)); + RTSemEventDestroy(pState->WndRequestSem); + } + else + LogRel(("VMSVGA3d: RTSemEventCreate failed: %Rrc\n", rc)); + return rc; +#else + return VINF_SUCCESS; +#endif +} + +static int vmsvga3dLoadGLFunctions(PVMSVGA3DSTATE pState) +{ + /* A strict approach to get a proc address as recommended by Khronos: + * - "If the function is a core OpenGL function, then we need to check the OpenGL version". + * - "If the function is an extension, we need to check to see if the extension is supported." + */ + +/* Get a function address, return VERR_NOT_IMPLEMENTED on failure. */ +#define GLGETPROC_(ProcType, ProcName, NameSuffix) do { \ + pState->ext.ProcName = (ProcType)OGLGETPROCADDRESS(#ProcName NameSuffix); \ + AssertLogRelMsgReturn(pState->ext.ProcName, (#ProcName NameSuffix " missing"), VERR_NOT_IMPLEMENTED); \ +} while(0) + +/* Get an optional function address. LogRel on failure. */ +#define GLGETPROCOPT_(ProcType, ProcName, NameSuffix) do { \ + pState->ext.ProcName = (ProcType)OGLGETPROCADDRESS(#ProcName NameSuffix); \ + if (!pState->ext.ProcName) \ + { \ + LogRel(("VMSVGA3d: missing optional %s\n", #ProcName NameSuffix)); \ + AssertFailed(); \ + } \ +} while(0) + + /* OpenGL 2.0 or earlier core. Do not bother with extensions. */ + GLGETPROC_(PFNGLGENQUERIESPROC , glGenQueries, ""); + GLGETPROC_(PFNGLDELETEQUERIESPROC , glDeleteQueries, ""); + GLGETPROC_(PFNGLBEGINQUERYPROC , glBeginQuery, ""); + GLGETPROC_(PFNGLENDQUERYPROC , glEndQuery, ""); + GLGETPROC_(PFNGLGETQUERYOBJECTUIVPROC , glGetQueryObjectuiv, ""); + GLGETPROC_(PFNGLTEXIMAGE3DPROC , glTexImage3D, ""); + GLGETPROC_(PFNGLTEXSUBIMAGE3DPROC , glTexSubImage3D, ""); + GLGETPROC_(PFNGLGETCOMPRESSEDTEXIMAGEPROC , glGetCompressedTexImage, ""); + GLGETPROC_(PFNGLCOMPRESSEDTEXIMAGE2DPROC , glCompressedTexImage2D, ""); + GLGETPROC_(PFNGLCOMPRESSEDTEXIMAGE3DPROC , glCompressedTexImage3D, ""); + GLGETPROC_(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC , glCompressedTexSubImage2D, ""); + GLGETPROC_(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC , glCompressedTexSubImage3D, ""); + GLGETPROC_(PFNGLPOINTPARAMETERFPROC , glPointParameterf, ""); + GLGETPROC_(PFNGLBLENDEQUATIONSEPARATEPROC , glBlendEquationSeparate, ""); + GLGETPROC_(PFNGLBLENDFUNCSEPARATEPROC , glBlendFuncSeparate, ""); + GLGETPROC_(PFNGLSTENCILOPSEPARATEPROC , glStencilOpSeparate, ""); + GLGETPROC_(PFNGLSTENCILFUNCSEPARATEPROC , glStencilFuncSeparate, ""); + GLGETPROC_(PFNGLBINDBUFFERPROC , glBindBuffer, ""); + GLGETPROC_(PFNGLDELETEBUFFERSPROC , glDeleteBuffers, ""); + GLGETPROC_(PFNGLGENBUFFERSPROC , glGenBuffers, ""); + GLGETPROC_(PFNGLBUFFERDATAPROC , glBufferData, ""); + GLGETPROC_(PFNGLMAPBUFFERPROC , glMapBuffer, ""); + GLGETPROC_(PFNGLUNMAPBUFFERPROC , glUnmapBuffer, ""); + GLGETPROC_(PFNGLENABLEVERTEXATTRIBARRAYPROC , glEnableVertexAttribArray, ""); + GLGETPROC_(PFNGLDISABLEVERTEXATTRIBARRAYPROC , glDisableVertexAttribArray, ""); + GLGETPROC_(PFNGLVERTEXATTRIBPOINTERPROC , glVertexAttribPointer, ""); + GLGETPROC_(PFNGLACTIVETEXTUREPROC , glActiveTexture, ""); + /* glGetProgramivARB determines implementation limits for the program + * target (GL_FRAGMENT_PROGRAM_ARB, GL_VERTEX_PROGRAM_ARB). + * It differs from glGetProgramiv, which returns a parameter from a program object. + */ + GLGETPROC_(PFNGLGETPROGRAMIVARBPROC , glGetProgramivARB, ""); + GLGETPROC_(PFNGLFOGCOORDPOINTERPROC , glFogCoordPointer, ""); +#if VBOX_VMSVGA3D_GL_HACK_LEVEL < 0x102 + GLGETPROC_(PFNGLBLENDCOLORPROC , glBlendColor, ""); + GLGETPROC_(PFNGLBLENDEQUATIONPROC , glBlendEquation, ""); +#endif +#if VBOX_VMSVGA3D_GL_HACK_LEVEL < 0x103 + GLGETPROC_(PFNGLCLIENTACTIVETEXTUREPROC , glClientActiveTexture, ""); +#endif + GLGETPROC_(PFNGLDRAWBUFFERSPROC , glDrawBuffers, ""); + GLGETPROC_(PFNGLCREATESHADERPROC , glCreateShader, ""); + GLGETPROC_(PFNGLSHADERSOURCEPROC , glShaderSource, ""); + GLGETPROC_(PFNGLCOMPILESHADERPROC , glCompileShader, ""); + GLGETPROC_(PFNGLGETSHADERIVPROC , glGetShaderiv, ""); + GLGETPROC_(PFNGLGETSHADERINFOLOGPROC , glGetShaderInfoLog, ""); + GLGETPROC_(PFNGLCREATEPROGRAMPROC , glCreateProgram, ""); + GLGETPROC_(PFNGLATTACHSHADERPROC , glAttachShader, ""); + GLGETPROC_(PFNGLLINKPROGRAMPROC , glLinkProgram, ""); + GLGETPROC_(PFNGLGETPROGRAMIVPROC , glGetProgramiv, ""); + GLGETPROC_(PFNGLGETPROGRAMINFOLOGPROC , glGetProgramInfoLog, ""); + GLGETPROC_(PFNGLUSEPROGRAMPROC , glUseProgram, ""); + GLGETPROC_(PFNGLGETUNIFORMLOCATIONPROC , glGetUniformLocation, ""); + GLGETPROC_(PFNGLUNIFORM1IPROC , glUniform1i, ""); + GLGETPROC_(PFNGLUNIFORM4FVPROC , glUniform4fv, ""); + GLGETPROC_(PFNGLDETACHSHADERPROC , glDetachShader, ""); + GLGETPROC_(PFNGLDELETESHADERPROC , glDeleteShader, ""); + GLGETPROC_(PFNGLDELETEPROGRAMPROC , glDeleteProgram, ""); + + GLGETPROC_(PFNGLVERTEXATTRIB4FVPROC , glVertexAttrib4fv, ""); + GLGETPROC_(PFNGLVERTEXATTRIB4UBVPROC , glVertexAttrib4ubv, ""); + GLGETPROC_(PFNGLVERTEXATTRIB4NUBVPROC , glVertexAttrib4Nubv, ""); + GLGETPROC_(PFNGLVERTEXATTRIB4SVPROC , glVertexAttrib4sv, ""); + GLGETPROC_(PFNGLVERTEXATTRIB4NSVPROC , glVertexAttrib4Nsv, ""); + GLGETPROC_(PFNGLVERTEXATTRIB4NUSVPROC , glVertexAttrib4Nusv, ""); + + /* OpenGL 3.0 core, GL_ARB_instanced_arrays. Same functions names in the ARB and core specs. */ + if ( pState->rsGLVersion >= 3.0f + || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_framebuffer_object ")) + { + GLGETPROC_(PFNGLISRENDERBUFFERPROC , glIsRenderbuffer, ""); + GLGETPROC_(PFNGLBINDRENDERBUFFERPROC , glBindRenderbuffer, ""); + GLGETPROC_(PFNGLDELETERENDERBUFFERSPROC , glDeleteRenderbuffers, ""); + GLGETPROC_(PFNGLGENRENDERBUFFERSPROC , glGenRenderbuffers, ""); + GLGETPROC_(PFNGLRENDERBUFFERSTORAGEPROC , glRenderbufferStorage, ""); + GLGETPROC_(PFNGLGETRENDERBUFFERPARAMETERIVPROC , glGetRenderbufferParameteriv, ""); + GLGETPROC_(PFNGLISFRAMEBUFFERPROC , glIsFramebuffer, ""); + GLGETPROC_(PFNGLBINDFRAMEBUFFERPROC , glBindFramebuffer, ""); + GLGETPROC_(PFNGLDELETEFRAMEBUFFERSPROC , glDeleteFramebuffers, ""); + GLGETPROC_(PFNGLGENFRAMEBUFFERSPROC , glGenFramebuffers, ""); + GLGETPROC_(PFNGLCHECKFRAMEBUFFERSTATUSPROC , glCheckFramebufferStatus, ""); + GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE1DPROC , glFramebufferTexture1D, ""); + GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE2DPROC , glFramebufferTexture2D, ""); + GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE3DPROC , glFramebufferTexture3D, ""); + GLGETPROC_(PFNGLFRAMEBUFFERRENDERBUFFERPROC , glFramebufferRenderbuffer, ""); + GLGETPROC_(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC , glGetFramebufferAttachmentParameteriv, ""); + GLGETPROC_(PFNGLGENERATEMIPMAPPROC , glGenerateMipmap, ""); + GLGETPROC_(PFNGLBLITFRAMEBUFFERPROC , glBlitFramebuffer, ""); + GLGETPROC_(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC , glRenderbufferStorageMultisample, ""); + GLGETPROC_(PFNGLFRAMEBUFFERTEXTURELAYERPROC , glFramebufferTextureLayer, ""); + } + + /* OpenGL 3.1 core, GL_ARB_draw_instanced, GL_EXT_draw_instanced. */ + if (pState->rsGLVersion >= 3.1f) + { + GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, ""); + GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, ""); + } + else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_draw_instanced ")) + { + GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, "ARB"); + GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, "ARB"); + } + else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_draw_instanced ")) + { + GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, "EXT"); + GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, "EXT"); + } + + /* OpenGL 3.2 core, GL_ARB_draw_elements_base_vertex. Same functions names in the ARB and core specs. */ + if ( pState->rsGLVersion >= 3.2f + || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_draw_elements_base_vertex ")) + { + GLGETPROC_(PFNGLDRAWELEMENTSBASEVERTEXPROC , glDrawElementsBaseVertex, ""); + GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC , glDrawElementsInstancedBaseVertex, ""); + } + + /* Optional. OpenGL 3.2 core, GL_ARB_provoking_vertex. Same functions names in the ARB and core specs. */ + if ( pState->rsGLVersion >= 3.2f + || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_provoking_vertex ")) + { + GLGETPROCOPT_(PFNGLPROVOKINGVERTEXPROC , glProvokingVertex, ""); + } + + /* OpenGL 3.3 core, GL_ARB_instanced_arrays. */ + if (pState->rsGLVersion >= 3.3f) + { + GLGETPROC_(PFNGLVERTEXATTRIBDIVISORPROC , glVertexAttribDivisor, ""); + } + else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_instanced_arrays ")) + { + GLGETPROC_(PFNGLVERTEXATTRIBDIVISORARBPROC , glVertexAttribDivisor, "ARB"); + } + +#undef GLGETPROCOPT_ +#undef GLGETPROC_ + + return VINF_SUCCESS; +} + + +DECLINLINE(GLenum) vmsvga3dCubemapFaceFromIndex(uint32_t iFace) +{ + GLint Face; + switch (iFace) + { + case 0: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; break; + case 1: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; break; + case 2: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; break; + case 3: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; break; + case 4: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; break; + default: + case 5: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; break; + } + return Face; +} + + +/* We must delay window creation until the PowerOn phase. Init is too early and will cause failures. */ +static DECLCALLBACK(int) vmsvga3dBackPowerOn(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY); + PVMSVGA3DCONTEXT pContext; +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + PVMSVGA3DCONTEXT pOtherCtx; +#endif + int rc; + RT_NOREF(pDevIns, pThis); + + if (pState->rsGLVersion != 0.0) + return VINF_SUCCESS; /* already initialized (load state) */ + + /* + * OpenGL function calls aren't possible without a valid current context, so create a fake one here. + */ + rc = vmsvga3dContextDefineOgl(pThisCC, 1, VMSVGA3D_DEF_CTX_F_INIT); + AssertRCReturn(rc, rc); + + pContext = pState->papContexts[1]; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + +#ifdef VMSVGA3D_DYNAMIC_LOAD + /* Context is set and it is possible now to resolve extension functions. */ + rc = glLdrGetExtFunctions(pDevIns); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: Error resolving extension functions: %Rrc\n", rc)); + return rc; + } +#endif + + LogRel(("VMSVGA3d: OpenGL version: %s\n" + "VMSVGA3d: OpenGL Vendor: %s\n" + "VMSVGA3d: OpenGL Renderer: %s\n" + "VMSVGA3d: OpenGL shader language version: %s\n", + glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER), + glGetString(GL_SHADING_LANGUAGE_VERSION))); + + rc = vmsvga3dGatherExtensions(&pState->pszExtensions, VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE); + AssertRCReturn(rc, rc); + vmsvga3dLogRelExtensions("", pState->pszExtensions); + + pState->rsGLVersion = atof((const char *)glGetString(GL_VERSION)); + + +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + /* + * Get the extension list for the alternative profile so we can better + * figure out the shader model and stuff. + */ + rc = vmsvga3dContextDefineOgl(pThisCC, 2, VMSVGA3D_DEF_CTX_F_INIT | VMSVGA3D_DEF_CTX_F_OTHER_PROFILE); + AssertLogRelRCReturn(rc, rc); + pContext = pState->papContexts[1]; /* Array may have been reallocated. */ + + pOtherCtx = pState->papContexts[2]; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx); + + LogRel(("VMSVGA3d: Alternative OpenGL version: %s\n" + "VMSVGA3d: Alternative OpenGL Vendor: %s\n" + "VMSVGA3d: Alternative OpenGL Renderer: %s\n" + "VMSVGA3d: Alternative OpenGL shader language version: %s\n", + glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER), + glGetString(GL_SHADING_LANGUAGE_VERSION))); + + rc = vmsvga3dGatherExtensions(&pState->pszOtherExtensions, VBOX_VMSVGA3D_OTHER_OGL_PROFILE); + AssertRCReturn(rc, rc); + vmsvga3dLogRelExtensions("Alternative ", pState->pszOtherExtensions); + + pState->rsOtherGLVersion = atof((const char *)glGetString(GL_VERSION)); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); +#else + pState->pszOtherExtensions = (char *)""; + pState->rsOtherGLVersion = pState->rsGLVersion; +#endif + + /* + * Resolve GL function pointers and store them in pState->ext. + */ + rc = vmsvga3dLoadGLFunctions(pState); + if (RT_FAILURE(rc)) + { + LogRel(("VMSVGA3d: missing required OpenGL function or extension; aborting\n")); + return rc; + } + + /* + * Initialize the capabilities with sensible defaults. + */ + pState->caps.maxActiveLights = 1; + pState->caps.maxTextures = 1; + pState->caps.maxClipDistances = 4; + pState->caps.maxColorAttachments = 1; + pState->caps.maxRectangleTextureSize = 2048; + pState->caps.maxTextureAnisotropy = 1; + pState->caps.maxVertexShaderInstructions = 1024; + pState->caps.maxFragmentShaderInstructions = 1024; + pState->caps.vertexShaderVersion = SVGA3DVSVERSION_NONE; + pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_NONE; + pState->caps.flPointSize[0] = 1; + pState->caps.flPointSize[1] = 1; + + /* + * Query capabilities + */ + pState->caps.fS3TCSupported = vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_texture_compression_s3tc "); + pState->caps.fTextureFilterAnisotropicSupported = vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_texture_filter_anisotropic "); + + VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetIntegerv(GL_MAX_LIGHTS, &pState->caps.maxActiveLights)); + VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &pState->caps.maxTextures)); +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE /* The alternative profile has a higher number here (ati/darwin). */ + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx); + VMSVGA3D_INIT_CHECKED_BOTH(pState, pOtherCtx, pContext, glGetIntegerv(GL_MAX_CLIP_DISTANCES, &pState->caps.maxClipDistances)); + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); +#else + VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_CLIP_DISTANCES, &pState->caps.maxClipDistances)); +#endif + VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &pState->caps.maxColorAttachments)); + VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, &pState->caps.maxRectangleTextureSize)); + if (pState->caps.fTextureFilterAnisotropicSupported) + VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &pState->caps.maxTextureAnisotropy)); + VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pState->caps.flPointSize)); + + VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, + pState->ext.glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, + &pState->caps.maxFragmentShaderTemps)); + VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, + pState->ext.glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, + &pState->caps.maxFragmentShaderInstructions)); + VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, + pState->ext.glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, + &pState->caps.maxVertexShaderTemps)); + VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, + pState->ext.glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, + &pState->caps.maxVertexShaderInstructions)); + + /* http://http://www.opengl.org/wiki/Detecting_the_Shader_Model + * ARB Assembly Language + * These are done through testing the presence of extensions. You should test them in this order: + * GL_NV_gpu_program4: SM 4.0 or better. + * GL_NV_vertex_program3: SM 3.0 or better. + * GL_ARB_fragment_program: SM 2.0 or better. + * ATI does not support higher than SM 2.0 functionality in assembly shaders. + * + */ + /** @todo distinguish between vertex and pixel shaders??? */ +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE /* The alternative profile has a higher number here (ati/darwin). */ + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx); + const char *pszShadingLanguageVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); +#else + const char *pszShadingLanguageVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); +#endif + float v = pszShadingLanguageVersion ? atof(pszShadingLanguageVersion) : 0.0f; + if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_NV_gpu_program4 ") + || strstr(pState->pszOtherExtensions, " GL_NV_gpu_program4 ")) + { + pState->caps.vertexShaderVersion = SVGA3DVSVERSION_40; + pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_40; + } + else + if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_NV_vertex_program3 ") + || strstr(pState->pszOtherExtensions, " GL_NV_vertex_program3 ") + || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_shader_texture_lod ") /* Wine claims this suggests SM 3.0 support */ + || strstr(pState->pszOtherExtensions, " GL_ARB_shader_texture_lod ") + ) + { + pState->caps.vertexShaderVersion = SVGA3DVSVERSION_30; + pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_30; + } + else + if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_fragment_program ") + || strstr(pState->pszOtherExtensions, " GL_ARB_fragment_program ")) + { + pState->caps.vertexShaderVersion = SVGA3DVSVERSION_20; + pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_20; + } + else + { + LogRel(("VMSVGA3D: WARNING: unknown support for assembly shaders!!\n")); + pState->caps.vertexShaderVersion = SVGA3DVSVERSION_11; + pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_11; + } + + /* Now check the shading language version, in case it indicates a higher supported version. */ + if (v >= 3.30f) + { + pState->caps.vertexShaderVersion = RT_MAX(pState->caps.vertexShaderVersion, SVGA3DVSVERSION_40); + pState->caps.fragmentShaderVersion = RT_MAX(pState->caps.fragmentShaderVersion, SVGA3DPSVERSION_40); + } + else + if (v >= 1.20f) + { + pState->caps.vertexShaderVersion = RT_MAX(pState->caps.vertexShaderVersion, SVGA3DVSVERSION_20); + pState->caps.fragmentShaderVersion = RT_MAX(pState->caps.fragmentShaderVersion, SVGA3DPSVERSION_20); + } + + if ( !vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_vertex_array_bgra ") + && !vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_vertex_array_bgra ")) + { + LogRel(("VMSVGA3D: WARNING: Missing required extension GL_ARB_vertex_array_bgra (d3dcolor)!!!\n")); + } + + /* + * Tweak capabilities. + */ + /* Intel Windows drivers return 31, while the guest expects 32 at least. */ + if ( pState->caps.maxVertexShaderTemps < 32 + && vmsvga3dIsVendorIntel()) + pState->caps.maxVertexShaderTemps = 32; + +#if 0 + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = 11, + SVGA3D_DEVCAP_QUERY_TYPES = 15, + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = 16, + SVGA3D_DEVCAP_MAX_POINT_SIZE = 17, + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = 18, + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = 21, + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = 22, + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = 23, + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = 24, + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = 25, + SVGA3D_DEVCAP_MAX_VERTEX_INDEX = 26, + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = 28, + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = 29, + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = 30, + SVGA3D_DEVCAP_TEXTURE_OPS = 31, + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = 32, + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = 33, + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = 34, + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = 35, + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = 36, + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = 37, + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = 38, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = 39, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = 40, + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = 41, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = 42, + SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = 43, + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = 44, + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = 45, + SVGA3D_DEVCAP_SURFACEFMT_DXT1 = 46, + SVGA3D_DEVCAP_SURFACEFMT_DXT2 = 47, + SVGA3D_DEVCAP_SURFACEFMT_DXT3 = 48, + SVGA3D_DEVCAP_SURFACEFMT_DXT4 = 49, + SVGA3D_DEVCAP_SURFACEFMT_DXT5 = 50, + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = 51, + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = 52, + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = 53, + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = 54, + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = 55, + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = 56, + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = 57, + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = 58, + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = 59, + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = 60, + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = 61, + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = 63, + SVGA3D_DEVCAP_SURFACEFMT_V16U16 = 65, + SVGA3D_DEVCAP_SURFACEFMT_G16R16 = 66, + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = 67, + SVGA3D_DEVCAP_SURFACEFMT_UYVY = 68, + SVGA3D_DEVCAP_SURFACEFMT_YUY2 = 69, + SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = 70, + SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = 71, + SVGA3D_DEVCAP_ALPHATOCOVERAGE = 72, + SVGA3D_DEVCAP_SUPERSAMPLE = 73, + SVGA3D_DEVCAP_AUTOGENMIPMAPS = 74, + SVGA3D_DEVCAP_SURFACEFMT_NV12 = 75, + SVGA3D_DEVCAP_SURFACEFMT_AYUV = 76, + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = 79, + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = 80, + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = 81, + SVGA3D_DEVCAP_SURFACEFMT_ATI1 = 82, + SVGA3D_DEVCAP_SURFACEFMT_ATI2 = 83, +#endif + + LogRel(("VMSVGA3d: Capabilities:\n")); + LogRel(("VMSVGA3d: maxActiveLights=%-2d maxTextures=%-2d\n", + pState->caps.maxActiveLights, pState->caps.maxTextures)); + LogRel(("VMSVGA3d: maxClipDistances=%-2d maxColorAttachments=%-2d maxClipDistances=%d\n", + pState->caps.maxClipDistances, pState->caps.maxColorAttachments, pState->caps.maxClipDistances)); + LogRel(("VMSVGA3d: maxColorAttachments=%-2d maxTextureAnisotropy=%-2d maxRectangleTextureSize=%d\n", + pState->caps.maxColorAttachments, pState->caps.maxTextureAnisotropy, pState->caps.maxRectangleTextureSize)); + LogRel(("VMSVGA3d: maxVertexShaderTemps=%-2d maxVertexShaderInstructions=%d maxFragmentShaderInstructions=%d\n", + pState->caps.maxVertexShaderTemps, pState->caps.maxVertexShaderInstructions, pState->caps.maxFragmentShaderInstructions)); + LogRel(("VMSVGA3d: maxFragmentShaderTemps=%d flPointSize={%d.%02u, %d.%02u}\n", + pState->caps.maxFragmentShaderTemps, + (int)pState->caps.flPointSize[0], (int)(pState->caps.flPointSize[0] * 100) % 100, + (int)pState->caps.flPointSize[1], (int)(pState->caps.flPointSize[1] * 100) % 100)); + LogRel(("VMSVGA3d: fragmentShaderVersion=%-2d vertexShaderVersion=%-2d\n", + pState->caps.fragmentShaderVersion, pState->caps.vertexShaderVersion)); + LogRel(("VMSVGA3d: fS3TCSupported=%-2d fTextureFilterAnisotropicSupported=%d\n", + pState->caps.fS3TCSupported, pState->caps.fTextureFilterAnisotropicSupported)); + + + /* Initialize the shader library. */ + pState->ShaderIf.pfnSwitchInitProfile = vmsvga3dShaderIfSwitchInitProfile; + pState->ShaderIf.pfnGetNextExtension = vmsvga3dShaderIfGetNextExtension; + rc = ShaderInitLib(&pState->ShaderIf); + AssertRC(rc); + + /* Cleanup */ + rc = vmsvga3dBackContextDestroy(pThisCC, 1); + AssertRC(rc); +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + rc = vmsvga3dBackContextDestroy(pThisCC, 2); + AssertRC(rc); +#endif + + if ( pState->rsGLVersion < 3.0 + && pState->rsOtherGLVersion < 3.0 /* darwin: legacy profile hack */) + { + LogRel(("VMSVGA3d: unsupported OpenGL version; minimum is 3.0\n")); + return VERR_NOT_IMPLEMENTED; + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackReset(PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY); + + if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) + vmsvga3dContextDestroyOgl(pThisCC, &pState->SharedCtx, VMSVGA3D_SHARED_CTX_ID); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackTerminate(PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_WRONG_ORDER); + int rc; + + /* Terminate the shader library. */ + rc = ShaderDestroyLib(); + AssertRC(rc); + +#ifdef RT_OS_WINDOWS + /* Terminate the window creation thread. */ + rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_EXIT, 0, 0); + AssertRCReturn(rc, rc); + + RTSemEventDestroy(pState->WndRequestSem); +#elif defined(RT_OS_DARWIN) + +#elif defined(RT_OS_LINUX) + /* signal to the thread that it is supposed to exit */ + pState->bTerminate = true; + /* wait for it to terminate */ + rc = RTThreadWait(pState->pWindowThread, 10000, NULL); + AssertRC(rc); + XCloseDisplay(pState->display); +#endif + + RTStrFree(pState->pszExtensions); + pState->pszExtensions = NULL; +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + RTStrFree(pState->pszOtherExtensions); +#endif + pState->pszOtherExtensions = NULL; + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(void) vmsvga3dBackUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport) +{ + /** @todo Move the visible framebuffer content here, don't wait for the guest to + * redraw it. */ + +#ifdef RT_OS_DARWIN + RT_NOREF(pOldViewport); + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + if ( pState + && idScreen == 0 + && pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) + { + vmsvga3dCocoaViewUpdateViewport(pState->SharedCtx.cocoaView); + } +#else + RT_NOREF(pThisCC, idScreen, pOldViewport); +#endif +} + + +/** + * Worker for vmsvga3dBackQueryCaps that figures out supported operations for a + * given surface format capability. + * + * @returns Supported/indented operations (SVGA3DFORMAT_OP_XXX). + * @param idx3dCaps The SVGA3D_CAPS_XXX value of the surface format. + * + * @remarks See fromat_cap_table in svga_format.c (mesa/gallium) for a reference + * of implicit guest expectations: + * http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/svga/svga_format.c + */ +static uint32_t vmsvga3dGetSurfaceFormatSupport(uint32_t idx3dCaps) +{ + uint32_t result = 0; + + /** @todo missing: + * + * SVGA3DFORMAT_OP_PIXELSIZE + */ + + switch (idx3dCaps) + { + case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: + result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB + | SVGA3DFORMAT_OP_CONVERT_TO_ARGB + | SVGA3DFORMAT_OP_DISPLAYMODE /* Should not be set for alpha formats. */ + | SVGA3DFORMAT_OP_3DACCELERATION; /* implies OP_DISPLAYMODE */ + break; + + case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: + case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: + result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB + | SVGA3DFORMAT_OP_CONVERT_TO_ARGB + | SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET; + break; + } + + /** @todo check hardware caps! */ + switch (idx3dCaps) + { + case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: + case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: + case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: + case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: + result |= SVGA3DFORMAT_OP_TEXTURE + | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET + | SVGA3DFORMAT_OP_OFFSCREENPLAIN + | SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET + | SVGA3DFORMAT_OP_VOLUMETEXTURE + | SVGA3DFORMAT_OP_CUBETEXTURE + | SVGA3DFORMAT_OP_SRGBREAD + | SVGA3DFORMAT_OP_SRGBWRITE; + break; + + case SVGA3D_DEVCAP_SURFACEFMT_Z_D16: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: + result |= SVGA3DFORMAT_OP_ZSTENCIL + | SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH + | SVGA3DFORMAT_OP_TEXTURE /* Necessary for Ubuntu Unity */; + break; + + case SVGA3D_DEVCAP_SURFACEFMT_DXT1: + case SVGA3D_DEVCAP_SURFACEFMT_DXT2: + case SVGA3D_DEVCAP_SURFACEFMT_DXT3: + case SVGA3D_DEVCAP_SURFACEFMT_DXT4: + case SVGA3D_DEVCAP_SURFACEFMT_DXT5: + result |= SVGA3DFORMAT_OP_TEXTURE + | SVGA3DFORMAT_OP_VOLUMETEXTURE + | SVGA3DFORMAT_OP_CUBETEXTURE + | SVGA3DFORMAT_OP_SRGBREAD; + break; + + case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: + case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: + case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: + case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: + case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: + break; + + case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: + case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: + result |= SVGA3DFORMAT_OP_TEXTURE + | SVGA3DFORMAT_OP_VOLUMETEXTURE + | SVGA3DFORMAT_OP_CUBETEXTURE + | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET; + break; + + case SVGA3D_DEVCAP_SURFACEFMT_V16U16: + case SVGA3D_DEVCAP_SURFACEFMT_G16R16: + case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: + result |= SVGA3DFORMAT_OP_TEXTURE + | SVGA3DFORMAT_OP_VOLUMETEXTURE + | SVGA3DFORMAT_OP_CUBETEXTURE + | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET; + break; + + case SVGA3D_DEVCAP_SURFACEFMT_UYVY: + case SVGA3D_DEVCAP_SURFACEFMT_YUY2: + result |= SVGA3DFORMAT_OP_OFFSCREENPLAIN + | SVGA3DFORMAT_OP_CONVERT_TO_ARGB + | SVGA3DFORMAT_OP_TEXTURE; + break; + + case SVGA3D_DEVCAP_SURFACEFMT_NV12: + case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */ + break; + } + Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result))); + + return result; +} + +#if 0 /* unused */ +static uint32_t vmsvga3dGetDepthFormatSupport(PVMSVGA3DSTATE pState3D, uint32_t idx3dCaps) +{ + RT_NOREF(pState3D, idx3dCaps); + + /** @todo test this somehow */ + uint32_t result = SVGA3DFORMAT_OP_ZSTENCIL | SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH; + + Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result))); + return result; +} +#endif + + +static DECLCALLBACK(int) vmsvga3dBackQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + int rc = VINF_SUCCESS; + + *pu32Val = 0; + + /* + * The capabilities access by current (2015-03-01) linux sources (gallium, + * vmwgfx, xorg-video-vmware) are annotated, caps without xref annotations + * aren't access. + */ + + switch (idx3dCaps) + { + /* Linux: vmwgfx_fifo.c in kmod; only used with SVGA_CAP_GBOBJECTS. */ + case SVGA3D_DEVCAP_3D: + *pu32Val = 1; /* boolean? */ + break; + + case SVGA3D_DEVCAP_MAX_LIGHTS: + *pu32Val = pState->caps.maxActiveLights; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURES: + *pu32Val = pState->caps.maxTextures; + break; + + case SVGA3D_DEVCAP_MAX_CLIP_PLANES: + *pu32Val = pState->caps.maxClipDistances; + break; + + /* Linux: svga_screen.c in gallium; 3.0 or later required. */ + case SVGA3D_DEVCAP_VERTEX_SHADER_VERSION: + *pu32Val = pState->caps.vertexShaderVersion; + break; + + case SVGA3D_DEVCAP_VERTEX_SHADER: + /* boolean? */ + *pu32Val = (pState->caps.vertexShaderVersion != SVGA3DVSVERSION_NONE); + break; + + /* Linux: svga_screen.c in gallium; 3.0 or later required. */ + case SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION: + *pu32Val = pState->caps.fragmentShaderVersion; + break; + + case SVGA3D_DEVCAP_FRAGMENT_SHADER: + /* boolean? */ + *pu32Val = (pState->caps.fragmentShaderVersion != SVGA3DPSVERSION_NONE); + break; + + case SVGA3D_DEVCAP_S23E8_TEXTURES: + case SVGA3D_DEVCAP_S10E5_TEXTURES: + /* Must be obsolete by now; surface format caps specify the same thing. */ + rc = VERR_INVALID_PARAMETER; + break; + + case SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND: + break; + + /* + * 2. The BUFFER_FORMAT capabilities are deprecated, and they always + * return TRUE. Even on physical hardware that does not support + * these formats natively, the SVGA3D device will provide an emulation + * which should be invisible to the guest OS. + */ + case SVGA3D_DEVCAP_D16_BUFFER_FORMAT: + case SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT: + case SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_QUERY_TYPES: + break; + + case SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING: + break; + + /* Linux: svga_screen.c in gallium; capped at 80.0, default 1.0. */ + case SVGA3D_DEVCAP_MAX_POINT_SIZE: + AssertCompile(sizeof(uint32_t) == sizeof(float)); + *(float *)pu32Val = pState->caps.flPointSize[1]; + break; + + case SVGA3D_DEVCAP_MAX_SHADER_TEXTURES: + /** @todo ?? */ + rc = VERR_INVALID_PARAMETER; + break; + + /* Linux: svga_screen.c in gallium (for PIPE_CAP_MAX_TEXTURE_2D_LEVELS); have default if missing. */ + case SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH: + case SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT: + *pu32Val = pState->caps.maxRectangleTextureSize; + break; + + /* Linux: svga_screen.c in gallium (for PIPE_CAP_MAX_TEXTURE_3D_LEVELS); have default if missing. */ + case SVGA3D_DEVCAP_MAX_VOLUME_EXTENT: + //*pu32Val = pCaps->MaxVolumeExtent; + *pu32Val = 256; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT: + *pu32Val = 32768; /* hardcoded in Wine */ + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO: + //*pu32Val = pCaps->MaxTextureAspectRatio; + break; + + /* Linux: svga_screen.c in gallium (for PIPE_CAPF_MAX_TEXTURE_ANISOTROPY); defaults to 4.0. */ + case SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY: + *pu32Val = pState->caps.maxTextureAnisotropy; + break; + + case SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT: + case SVGA3D_DEVCAP_MAX_VERTEX_INDEX: + *pu32Val = 0xFFFFF; /* hardcoded in Wine */ + break; + + /* Linux: svga_screen.c in gallium (for PIPE_SHADER_VERTEX/PIPE_SHADER_CAP_MAX_INSTRUCTIONS); defaults to 512. */ + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS: + *pu32Val = pState->caps.maxVertexShaderInstructions; + break; + + case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS: + *pu32Val = pState->caps.maxFragmentShaderInstructions; + break; + + /* Linux: svga_screen.c in gallium (for PIPE_SHADER_VERTEX/PIPE_SHADER_CAP_MAX_TEMPS); defaults to 32. */ + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS: + *pu32Val = pState->caps.maxVertexShaderTemps; + break; + + /* Linux: svga_screen.c in gallium (for PIPE_SHADER_FRAGMENT/PIPE_SHADER_CAP_MAX_TEMPS); defaults to 32. */ + case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS: + *pu32Val = pState->caps.maxFragmentShaderTemps; + break; + + case SVGA3D_DEVCAP_TEXTURE_OPS: + break; + + case SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */ + break; + + case SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */ + break; + + case SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */ + break; + + case SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */ + break; + + case SVGA3D_DEVCAP_AUTOGENMIPMAPS: + //*pu32Val = !!(pCaps->Caps2 & D3DCAPS2_CANAUTOGENMIPMAP); + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES: + break; + + case SVGA3D_DEVCAP_MAX_RENDER_TARGETS: /** @todo same thing? */ + case SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS: + *pu32Val = pState->caps.maxColorAttachments; + break; + + /* + * This is the maximum number of SVGA context IDs that the guest + * can define using SVGA_3D_CMD_CONTEXT_DEFINE. + */ + case SVGA3D_DEVCAP_MAX_CONTEXT_IDS: + *pu32Val = SVGA3D_MAX_CONTEXT_IDS; + break; + + /* + * This is the maximum number of SVGA surface IDs that the guest + * can define using SVGA_3D_CMD_SURFACE_DEFINE*. + */ + case SVGA3D_DEVCAP_MAX_SURFACE_IDS: + *pu32Val = SVGA3D_MAX_SURFACE_IDS; + break; + +#if 0 /* Appeared more recently, not yet implemented. */ + /* Linux: svga_screen.c in gallium; defaults to FALSE. */ + case SVGA3D_DEVCAP_LINE_AA: + break; + /* Linux: svga_screen.c in gallium; defaults to FALSE. */ + case SVGA3D_DEVCAP_LINE_STIPPLE: + break; + /* Linux: svga_screen.c in gallium; defaults to 1.0. */ + case SVGA3D_DEVCAP_MAX_LINE_WIDTH: + break; + /* Linux: svga_screen.c in gallium; defaults to 1.0. */ + case SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH: + break; +#endif + + /* + * Supported surface formats. + * Linux: svga_format.c in gallium, format_cap_table defines implicit expectations. + */ + case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: + case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: + case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: + case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D16: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: + case SVGA3D_DEVCAP_SURFACEFMT_DXT1: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(idx3dCaps); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_DXT2: + case SVGA3D_DEVCAP_SURFACEFMT_DXT3: + case SVGA3D_DEVCAP_SURFACEFMT_DXT4: + case SVGA3D_DEVCAP_SURFACEFMT_DXT5: + case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: + case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: + case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: + case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: + case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: + case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: + case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: + case SVGA3D_DEVCAP_SURFACEFMT_V16U16: + case SVGA3D_DEVCAP_SURFACEFMT_G16R16: + case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: + case SVGA3D_DEVCAP_SURFACEFMT_UYVY: + case SVGA3D_DEVCAP_SURFACEFMT_YUY2: + case SVGA3D_DEVCAP_SURFACEFMT_NV12: + case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */ + *pu32Val = vmsvga3dGetSurfaceFormatSupport(idx3dCaps); + break; + + /* Linux: Not referenced in current sources. */ + case SVGA3D_DEVCAP_SURFACEFMT_ATI1: + case SVGA3D_DEVCAP_SURFACEFMT_ATI2: + Log(("CAPS: Unknown CAP %s\n", vmsvga3dGetCapString(idx3dCaps))); + rc = VERR_INVALID_PARAMETER; + *pu32Val = 0; + break; + + default: + Log(("CAPS: Unexpected CAP %d\n", idx3dCaps)); + rc = VERR_INVALID_PARAMETER; + break; + } + + Log(("CAPS: %s - %x\n", vmsvga3dGetCapString(idx3dCaps), *pu32Val)); + return rc; +} + +/** + * Convert SVGA format value to its OpenGL equivalent + * + * @remarks Clues to be had in format_texture_info table (wined3d/utils.c) with + * help from wined3dformat_from_d3dformat(). + */ +void vmsvga3dSurfaceFormat2OGL(PVMSVGA3DSURFACE pSurface, SVGA3dSurfaceFormat format) +{ +#if 0 +#define AssertTestFmt(f) AssertMsgFailed(("Test me - " #f "\n")) +#else +#define AssertTestFmt(f) do {} while(0) +#endif + /* Init cbBlockGL for non-emulated formats. */ + pSurface->cbBlockGL = pSurface->cbBlock; + + switch (format) + { + case SVGA3D_X8R8G8B8: /* D3DFMT_X8R8G8B8 - WINED3DFMT_B8G8R8X8_UNORM */ + pSurface->internalFormatGL = GL_RGB8; + pSurface->formatGL = GL_BGRA; + pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case SVGA3D_A8R8G8B8: /* D3DFMT_A8R8G8B8 - WINED3DFMT_B8G8R8A8_UNORM */ + pSurface->internalFormatGL = GL_RGBA8; + pSurface->formatGL = GL_BGRA; + pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case SVGA3D_R5G6B5: /* D3DFMT_R5G6B5 - WINED3DFMT_B5G6R5_UNORM */ + pSurface->internalFormatGL = GL_RGB5; + pSurface->formatGL = GL_RGB; + pSurface->typeGL = GL_UNSIGNED_SHORT_5_6_5; + AssertTestFmt(SVGA3D_R5G6B5); + break; + case SVGA3D_X1R5G5B5: /* D3DFMT_X1R5G5B5 - WINED3DFMT_B5G5R5X1_UNORM */ + pSurface->internalFormatGL = GL_RGB5; + pSurface->formatGL = GL_BGRA; + pSurface->typeGL = GL_UNSIGNED_SHORT_1_5_5_5_REV; + AssertTestFmt(SVGA3D_X1R5G5B5); + break; + case SVGA3D_A1R5G5B5: /* D3DFMT_A1R5G5B5 - WINED3DFMT_B5G5R5A1_UNORM */ + pSurface->internalFormatGL = GL_RGB5_A1; + pSurface->formatGL = GL_BGRA; + pSurface->typeGL = GL_UNSIGNED_SHORT_1_5_5_5_REV; + AssertTestFmt(SVGA3D_A1R5G5B5); + break; + case SVGA3D_A4R4G4B4: /* D3DFMT_A4R4G4B4 - WINED3DFMT_B4G4R4A4_UNORM */ + pSurface->internalFormatGL = GL_RGBA4; + pSurface->formatGL = GL_BGRA; + pSurface->typeGL = GL_UNSIGNED_SHORT_4_4_4_4_REV; + AssertTestFmt(SVGA3D_A4R4G4B4); + break; + + case SVGA3D_R8G8B8A8_UNORM: + pSurface->internalFormatGL = GL_RGBA8; + pSurface->formatGL = GL_RGBA; + pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + + case SVGA3D_Z_D32: /* D3DFMT_D32 - WINED3DFMT_D32_UNORM */ + pSurface->internalFormatGL = GL_DEPTH_COMPONENT32; + pSurface->formatGL = GL_DEPTH_COMPONENT; + pSurface->typeGL = GL_UNSIGNED_INT; + break; + case SVGA3D_Z_D16: /* D3DFMT_D16 - WINED3DFMT_D16_UNORM */ + pSurface->internalFormatGL = GL_DEPTH_COMPONENT16; /** @todo Wine suggests GL_DEPTH_COMPONENT24. */ + pSurface->formatGL = GL_DEPTH_COMPONENT; + pSurface->typeGL = GL_UNSIGNED_SHORT; + AssertTestFmt(SVGA3D_Z_D16); + break; + case SVGA3D_Z_D24S8: /* D3DFMT_D24S8 - WINED3DFMT_D24_UNORM_S8_UINT */ + pSurface->internalFormatGL = GL_DEPTH24_STENCIL8; + pSurface->formatGL = GL_DEPTH_STENCIL; + pSurface->typeGL = GL_UNSIGNED_INT_24_8; + break; + case SVGA3D_Z_D15S1: /* D3DFMT_D15S1 - WINED3DFMT_S1_UINT_D15_UNORM */ + pSurface->internalFormatGL = GL_DEPTH_COMPONENT16; /** @todo ??? */ + pSurface->formatGL = GL_DEPTH_STENCIL; + pSurface->typeGL = GL_UNSIGNED_SHORT; + /** @todo Wine sources hints at no hw support for this, so test this one! */ + AssertTestFmt(SVGA3D_Z_D15S1); + break; + case SVGA3D_Z_D24X8: /* D3DFMT_D24X8 - WINED3DFMT_X8D24_UNORM */ + pSurface->internalFormatGL = GL_DEPTH_COMPONENT24; + pSurface->formatGL = GL_DEPTH_COMPONENT; + pSurface->typeGL = GL_UNSIGNED_INT; + AssertTestFmt(SVGA3D_Z_D24X8); + break; + + /* Advanced D3D9 depth formats. */ + case SVGA3D_Z_DF16: /* D3DFMT_DF16? - not supported */ + pSurface->internalFormatGL = GL_DEPTH_COMPONENT16; + pSurface->formatGL = GL_DEPTH_COMPONENT; + pSurface->typeGL = GL_HALF_FLOAT; + break; + + case SVGA3D_Z_DF24: /* D3DFMT_DF24? - not supported */ + pSurface->internalFormatGL = GL_DEPTH_COMPONENT24; + pSurface->formatGL = GL_DEPTH_COMPONENT; + pSurface->typeGL = GL_FLOAT; /* ??? */ + break; + + case SVGA3D_Z_D24S8_INT: /* D3DFMT_D24S8 */ + pSurface->internalFormatGL = GL_DEPTH24_STENCIL8; + pSurface->formatGL = GL_DEPTH_STENCIL; + pSurface->typeGL = GL_UNSIGNED_INT_24_8; + break; + + case SVGA3D_DXT1: /* D3DFMT_DXT1 - WINED3DFMT_DXT1 */ + pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + pSurface->formatGL = GL_RGBA; /* not used */ + pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */ + break; + + case SVGA3D_DXT2: /* D3DFMT_DXT2 */ + /* "DXT2 and DXT3 are the same from an API perspective." */ + RT_FALL_THRU(); + case SVGA3D_DXT3: /* D3DFMT_DXT3 - WINED3DFMT_DXT3 */ + pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + pSurface->formatGL = GL_RGBA; /* not used */ + pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */ + break; + + case SVGA3D_DXT4: /* D3DFMT_DXT4 */ + /* "DXT4 and DXT5 are the same from an API perspective." */ + RT_FALL_THRU(); + case SVGA3D_DXT5: /* D3DFMT_DXT5 - WINED3DFMT_DXT5 */ + pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + pSurface->formatGL = GL_RGBA; /* not used */ + pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */ + break; + + case SVGA3D_LUMINANCE8: /* D3DFMT_? - ? */ + pSurface->internalFormatGL = GL_LUMINANCE8_EXT; + pSurface->formatGL = GL_LUMINANCE; + pSurface->typeGL = GL_UNSIGNED_BYTE; + break; + + case SVGA3D_LUMINANCE16: /* D3DFMT_? - ? */ + pSurface->internalFormatGL = GL_LUMINANCE16_EXT; + pSurface->formatGL = GL_LUMINANCE; + pSurface->typeGL = GL_UNSIGNED_SHORT; + break; + + case SVGA3D_LUMINANCE4_ALPHA4: /* D3DFMT_? - ? */ + pSurface->internalFormatGL = GL_LUMINANCE4_ALPHA4_EXT; + pSurface->formatGL = GL_LUMINANCE_ALPHA; + pSurface->typeGL = GL_UNSIGNED_BYTE; + break; + + case SVGA3D_LUMINANCE8_ALPHA8: /* D3DFMT_? - ? */ + pSurface->internalFormatGL = GL_LUMINANCE8_ALPHA8_EXT; + pSurface->formatGL = GL_LUMINANCE_ALPHA; + pSurface->typeGL = GL_UNSIGNED_BYTE; /* unsigned_short causes issues even though this type should be 16-bit */ + break; + + case SVGA3D_ALPHA8: /* D3DFMT_A8? - WINED3DFMT_A8_UNORM? */ + pSurface->internalFormatGL = GL_ALPHA8_EXT; + pSurface->formatGL = GL_ALPHA; + pSurface->typeGL = GL_UNSIGNED_BYTE; + break; + +#if 0 + + /* Bump-map formats */ + case SVGA3D_BUMPU8V8: + return D3DFMT_V8U8; + case SVGA3D_BUMPL6V5U5: + return D3DFMT_L6V5U5; + case SVGA3D_BUMPX8L8V8U8: + return D3DFMT_X8L8V8U8; + case SVGA3D_FORMAT_DEAD1: + /* No corresponding D3D9 equivalent. */ + AssertFailedReturn(D3DFMT_UNKNOWN); + /* signed bump-map formats */ + case SVGA3D_V8U8: + return D3DFMT_V8U8; + case SVGA3D_Q8W8V8U8: + return D3DFMT_Q8W8V8U8; + case SVGA3D_CxV8U8: + return D3DFMT_CxV8U8; + /* mixed bump-map formats */ + case SVGA3D_X8L8V8U8: + return D3DFMT_X8L8V8U8; + case SVGA3D_A2W10V10U10: + return D3DFMT_A2W10V10U10; +#endif + + case SVGA3D_ARGB_S10E5: /* 16-bit floating-point ARGB */ /* D3DFMT_A16B16G16R16F - WINED3DFMT_R16G16B16A16_FLOAT */ + pSurface->internalFormatGL = GL_RGBA16F; + pSurface->formatGL = GL_RGBA; +#if 0 /* bird: wine uses half float, sounds correct to me... */ + pSurface->typeGL = GL_FLOAT; +#else + pSurface->typeGL = GL_HALF_FLOAT; + AssertTestFmt(SVGA3D_ARGB_S10E5); +#endif + break; + + case SVGA3D_ARGB_S23E8: /* 32-bit floating-point ARGB */ /* D3DFMT_A32B32G32R32F - WINED3DFMT_R32G32B32A32_FLOAT */ + pSurface->internalFormatGL = GL_RGBA32F; + pSurface->formatGL = GL_RGBA; + pSurface->typeGL = GL_FLOAT; /* ?? - same as wine, so probably correct */ + break; + + case SVGA3D_A2R10G10B10: /* D3DFMT_A2R10G10B10 - WINED3DFMT_B10G10R10A2_UNORM */ + pSurface->internalFormatGL = GL_RGB10_A2; /* ?? - same as wine, so probably correct */ +#if 0 /* bird: Wine uses GL_BGRA instead of GL_RGBA. */ + pSurface->formatGL = GL_RGBA; +#else + pSurface->formatGL = GL_BGRA; +#endif + pSurface->typeGL = GL_UNSIGNED_INT; + AssertTestFmt(SVGA3D_A2R10G10B10); + break; + + + /* Single- and dual-component floating point formats */ + case SVGA3D_R_S10E5: /* D3DFMT_R16F - WINED3DFMT_R16_FLOAT */ + pSurface->internalFormatGL = GL_R16F; + pSurface->formatGL = GL_RED; +#if 0 /* bird: wine uses half float, sounds correct to me... */ + pSurface->typeGL = GL_FLOAT; +#else + pSurface->typeGL = GL_HALF_FLOAT; + AssertTestFmt(SVGA3D_R_S10E5); +#endif + break; + case SVGA3D_R_S23E8: /* D3DFMT_R32F - WINED3DFMT_R32_FLOAT */ + pSurface->internalFormatGL = GL_R32F; + pSurface->formatGL = GL_RED; + pSurface->typeGL = GL_FLOAT; + break; + case SVGA3D_RG_S10E5: /* D3DFMT_G16R16F - WINED3DFMT_R16G16_FLOAT */ + pSurface->internalFormatGL = GL_RG16F; + pSurface->formatGL = GL_RG; +#if 0 /* bird: wine uses half float, sounds correct to me... */ + pSurface->typeGL = GL_FLOAT; +#else + pSurface->typeGL = GL_HALF_FLOAT; + AssertTestFmt(SVGA3D_RG_S10E5); +#endif + break; + case SVGA3D_RG_S23E8: /* D3DFMT_G32R32F - WINED3DFMT_R32G32_FLOAT */ + pSurface->internalFormatGL = GL_RG32F; + pSurface->formatGL = GL_RG; + pSurface->typeGL = GL_FLOAT; + break; + + /* + * Any surface can be used as a buffer object, but SVGA3D_BUFFER is + * the most efficient format to use when creating new surfaces + * expressly for index or vertex data. + */ + case SVGA3D_BUFFER: + pSurface->internalFormatGL = -1; + pSurface->formatGL = -1; + pSurface->typeGL = -1; + break; + +#if 0 + return D3DFMT_UNKNOWN; + + case SVGA3D_V16U16: + return D3DFMT_V16U16; +#endif + + case SVGA3D_G16R16: /* D3DFMT_G16R16 - WINED3DFMT_R16G16_UNORM */ + pSurface->internalFormatGL = GL_RG16; + pSurface->formatGL = GL_RG; +#if 0 /* bird: Wine uses GL_UNSIGNED_SHORT here. */ + pSurface->typeGL = GL_UNSIGNED_INT; +#else + pSurface->typeGL = GL_UNSIGNED_SHORT; + AssertTestFmt(SVGA3D_G16R16); +#endif + break; + + case SVGA3D_A16B16G16R16: /* D3DFMT_A16B16G16R16 - WINED3DFMT_R16G16B16A16_UNORM */ + pSurface->internalFormatGL = GL_RGBA16; + pSurface->formatGL = GL_RGBA; +#if 0 /* bird: Wine uses GL_UNSIGNED_SHORT here. */ + pSurface->typeGL = GL_UNSIGNED_INT; /* ??? */ +#else + pSurface->typeGL = GL_UNSIGNED_SHORT; + AssertTestFmt(SVGA3D_A16B16G16R16); +#endif + break; + + case SVGA3D_R8G8B8A8_SNORM: + pSurface->internalFormatGL = GL_RGB8; + pSurface->formatGL = GL_BGRA; + pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV; + AssertTestFmt(SVGA3D_R8G8B8A8_SNORM); + break; + case SVGA3D_R16G16_UNORM: + pSurface->internalFormatGL = GL_RG16; + pSurface->formatGL = GL_RG; + pSurface->typeGL = GL_UNSIGNED_SHORT; + AssertTestFmt(SVGA3D_R16G16_UNORM); + break; + + /* Packed Video formats */ + case SVGA3D_UYVY: + case SVGA3D_YUY2: + /* Use a BRGA texture to hold the data and convert it to an actual BGRA. */ + pSurface->fEmulated = true; + pSurface->internalFormatGL = GL_RGBA8; + pSurface->formatGL = GL_BGRA; + pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV; + pSurface->cbBlockGL = 4 * pSurface->cxBlock * pSurface->cyBlock; + break; + +#if 0 + /* Planar video formats */ + case SVGA3D_NV12: + return (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2'); + + /* Video format with alpha */ + case SVGA3D_FORMAT_DEAD2: /* Old SVGA3D_AYUV */ + + case SVGA3D_ATI1: + case SVGA3D_ATI2: + /* Unknown; only in DX10 & 11 */ + break; +#endif + default: + AssertMsgFailed(("Unsupported format %d\n", format)); + break; + } +#undef AssertTestFmt +} + + +#if 0 +/** + * Convert SVGA multi sample count value to its D3D equivalent + */ +D3DMULTISAMPLE_TYPE vmsvga3dMultipeSampleCount2D3D(uint32_t multisampleCount) +{ + AssertCompile(D3DMULTISAMPLE_2_SAMPLES == 2); + AssertCompile(D3DMULTISAMPLE_16_SAMPLES == 16); + + if (multisampleCount > 16) + return D3DMULTISAMPLE_NONE; + + /** @todo exact same mapping as d3d? */ + return (D3DMULTISAMPLE_TYPE)multisampleCount; +} +#endif + +/** + * Destroy backend specific surface bits (part of SVGA_3D_CMD_SURFACE_DESTROY). + * + * @param pThisCC The device state. + * @param fClearCOTableEntry Not relevant for this backend. + * @param pSurface The surface being destroyed. + */ +static DECLCALLBACK(void) vmsvga3dBackSurfaceDestroy(PVGASTATECC pThisCC, bool fClearCOTableEntry, PVMSVGA3DSURFACE pSurface) +{ + RT_NOREF(fClearCOTableEntry); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturnVoid(pState); + + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + switch (pSurface->enmOGLResType) + { + case VMSVGA3D_OGLRESTYPE_BUFFER: + Assert(pSurface->oglId.buffer != OPENGL_INVALID_ID); + pState->ext.glDeleteBuffers(1, &pSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + break; + + case VMSVGA3D_OGLRESTYPE_TEXTURE: + Assert(pSurface->oglId.texture != OPENGL_INVALID_ID); + glDeleteTextures(1, &pSurface->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + if (pSurface->fEmulated) + { + if (pSurface->idEmulated) + { + glDeleteTextures(1, &pSurface->idEmulated); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + } + else + { + Assert(!pSurface->idEmulated); + } + break; + + case VMSVGA3D_OGLRESTYPE_RENDERBUFFER: + Assert(pSurface->oglId.renderbuffer != OPENGL_INVALID_ID); + pState->ext.glDeleteRenderbuffers(1, &pSurface->oglId.renderbuffer); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + break; + + default: + AssertMsg(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface), + ("hint=%#x, type=%d\n", + (pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK), pSurface->enmOGLResType)); + break; + } +} + + +static DECLCALLBACK(void) vmsvga3dBackSurfaceInvalidateImage(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface, uint32_t uFace, uint32_t uMipmap) +{ + RT_NOREF(pThisCC, pSurface, uFace, uMipmap); +} + + +static DECLCALLBACK(int) vmsvga3dBackSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src, + uint32_t cCopyBoxes, SVGA3dCopyBox *pBox) +{ + int rc; + + LogFunc(("Copy %d boxes from sid=%u face=%u mipmap=%u to sid=%u face=%u mipmap=%u\n", + cCopyBoxes, src.sid, src.face, src.mipmap, dest.sid, dest.face, dest.mipmap)); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DSURFACE pSurfaceSrc; + rc = vmsvga3dSurfaceFromSid(pState, src.sid, &pSurfaceSrc); + AssertRCReturn(rc, rc); + + PVMSVGA3DSURFACE pSurfaceDst; + rc = vmsvga3dSurfaceFromSid(pState, dest.sid, &pSurfaceDst); + AssertRCReturn(rc, rc); + + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurfaceSrc)) + { + /* The source surface is still in memory. */ + PVMSVGA3DMIPMAPLEVEL pMipmapLevelSrc; + rc = vmsvga3dMipmapLevel(pSurfaceSrc, src.face, src.mipmap, &pMipmapLevelSrc); + AssertRCReturn(rc, rc); + + PVMSVGA3DMIPMAPLEVEL pMipmapLevelDst; + rc = vmsvga3dMipmapLevel(pSurfaceDst, dest.face, dest.mipmap, &pMipmapLevelDst); + AssertRCReturn(rc, rc); + + /* The copy operation is performed on the shared context. */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Use glTexSubImage to upload the data to the destination texture. + * The latter must be an OpenGL texture. + */ + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurfaceDst)) + { + LogFunc(("dest sid=%u type=0x%x format=%d -> create texture\n", dest.sid, pSurfaceDst->f.s.surface1Flags, pSurfaceDst->format)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContext, pContext->id, pSurfaceDst); + AssertRCReturn(rc, rc); + } + + GLenum target; + if (pSurfaceDst->targetGL == GL_TEXTURE_CUBE_MAP) + target = vmsvga3dCubemapFaceFromIndex(dest.face); + else + { + AssertMsg(pSurfaceDst->targetGL == GL_TEXTURE_2D, ("Test %#x\n", pSurfaceDst->targetGL)); + target = pSurfaceDst->targetGL; + } + + /* Save the unpacking parameters and set what we need here. */ + VMSVGAPACKPARAMS SavedParams; + vmsvga3dOglSetUnpackParams(pState, pContext, + pMipmapLevelSrc->mipmapSize.width, + target == GL_TEXTURE_3D ? pMipmapLevelSrc->mipmapSize.height : 0, + &SavedParams); + + glBindTexture(pSurfaceDst->targetGL, pSurfaceDst->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + for (uint32_t i = 0; i < cCopyBoxes; ++i) + { + SVGA3dCopyBox clipBox = pBox[i]; + vmsvgaR3ClipCopyBox(&pMipmapLevelSrc->mipmapSize, &pMipmapLevelDst->mipmapSize, &clipBox); + if ( !clipBox.w + || !clipBox.h + || !clipBox.d) + { + LogFunc(("Skipped empty box.\n")); + continue; + } + + LogFunc(("copy box %d,%d,%d %dx%d to %d,%d,%d\n", + clipBox.srcx, clipBox.srcy, clipBox.srcz, clipBox.w, clipBox.h, clipBox.x, clipBox.y, clipBox.z)); + + uint32_t const u32BlockX = clipBox.srcx / pSurfaceSrc->cxBlock; + uint32_t const u32BlockY = clipBox.srcy / pSurfaceSrc->cyBlock; + uint32_t const u32BlockZ = clipBox.srcz; + Assert(u32BlockX * pSurfaceSrc->cxBlock == clipBox.srcx); + Assert(u32BlockY * pSurfaceSrc->cyBlock == clipBox.srcy); + + uint8_t const *pSrcBits = (uint8_t *)pMipmapLevelSrc->pSurfaceData + + pMipmapLevelSrc->cbSurfacePlane * u32BlockZ + + pMipmapLevelSrc->cbSurfacePitch * u32BlockY + + pSurfaceSrc->cbBlock * u32BlockX; + + if (target == GL_TEXTURE_3D) + { + if ( pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) + { + uint32_t const cBlocksX = (clipBox.w + pSurfaceSrc->cxBlock - 1) / pSurfaceSrc->cxBlock; + uint32_t const cBlocksY = (clipBox.h + pSurfaceSrc->cyBlock - 1) / pSurfaceSrc->cyBlock; + uint32_t const imageSize = cBlocksX * cBlocksY * clipBox.d * pSurfaceSrc->cbBlock; + pState->ext.glCompressedTexSubImage3D(target, dest.mipmap, + clipBox.x, clipBox.y, clipBox.z, + clipBox.w, clipBox.h, clipBox.d, + pSurfaceSrc->internalFormatGL, (GLsizei)imageSize, pSrcBits); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + else + { + pState->ext.glTexSubImage3D(target, dest.mipmap, + clipBox.x, clipBox.y, clipBox.z, + clipBox.w, clipBox.h, clipBox.d, + pSurfaceSrc->formatGL, pSurfaceSrc->typeGL, pSrcBits); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + } + else + { + if ( pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) + { + uint32_t const cBlocksX = (clipBox.w + pSurfaceSrc->cxBlock - 1) / pSurfaceSrc->cxBlock; + uint32_t const cBlocksY = (clipBox.h + pSurfaceSrc->cyBlock - 1) / pSurfaceSrc->cyBlock; + uint32_t const imageSize = cBlocksX * cBlocksY * pSurfaceSrc->cbBlock; + pState->ext.glCompressedTexSubImage2D(target, dest.mipmap, + clipBox.x, clipBox.y, clipBox.w, clipBox.h, + pSurfaceSrc->internalFormatGL, (GLsizei)imageSize, pSrcBits); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + else + { + glTexSubImage2D(target, dest.mipmap, + clipBox.x, clipBox.y, clipBox.w, clipBox.h, + pSurfaceSrc->formatGL, pSurfaceSrc->typeGL, pSrcBits); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + } + } + + glBindTexture(pSurfaceDst->targetGL, 0); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams); + + return VINF_SUCCESS; + } + + PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE); + for (uint32_t i = 0; i < cCopyBoxes; i++) + { + SVGA3dBox destBox, srcBox; + + srcBox.x = pBox[i].srcx; + srcBox.y = pBox[i].srcy; + srcBox.z = pBox[i].srcz; + srcBox.w = pBox[i].w; + srcBox.h = pBox[i].h; + srcBox.d = pBox[i].d; + + destBox.x = pBox[i].x; + destBox.y = pBox[i].y; + destBox.z = pBox[i].z; + destBox.w = pBox[i].w; + destBox.h = pBox[i].h; + destBox.d = pBox[i].d; + + /* No stretching is required, therefore use SVGA3D_STRETCH_BLT_POINT which translated to GL_NEAREST. */ + rc = vmsvga3dSurfaceStretchBlt(pThis, pThisCC, &dest, &destBox, &src, &srcBox, SVGA3D_STRETCH_BLT_POINT); + AssertRCReturn(rc, rc); + } + return VINF_SUCCESS; +} + + +/** + * Saves texture unpacking parameters and loads the specified ones. + * + * @param pState The VMSVGA3D state structure. + * @param pContext The active context. + * @param cxRow The number of pixels in a row. 0 for the entire width. + * @param cyImage The height of the image in pixels. 0 for the entire height. + * @param pSave Where to save stuff. + */ +void vmsvga3dOglSetUnpackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, GLint cxRow, GLint cyImage, + PVMSVGAPACKPARAMS pSave) +{ + RT_NOREF(pState); + + /* + * Save (ignore errors, setting the defaults we want and avoids restore). + */ + pSave->iAlignment = 1; + VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_ALIGNMENT, &pSave->iAlignment), pState, pContext); + pSave->cxRow = 0; + VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_ROW_LENGTH, &pSave->cxRow), pState, pContext); + pSave->cyImage = 0; + VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &pSave->cyImage), pState, pContext); + +#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING + pSave->fSwapBytes = GL_FALSE; + glGetBooleanv(GL_UNPACK_SWAP_BYTES, &pSave->fSwapBytes); + Assert(pSave->fSwapBytes == GL_FALSE); + + pSave->fLsbFirst = GL_FALSE; + glGetBooleanv(GL_UNPACK_LSB_FIRST, &pSave->fLsbFirst); + Assert(pSave->fLsbFirst == GL_FALSE); + + pSave->cSkipRows = 0; + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &pSave->cSkipRows); + Assert(pSave->cSkipRows == 0); + + pSave->cSkipPixels = 0; + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &pSave->cSkipPixels); + Assert(pSave->cSkipPixels == 0); + + pSave->cSkipImages = 0; + glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &pSave->cSkipImages); + Assert(pSave->cSkipImages == 0); + + VMSVGA3D_CLEAR_GL_ERRORS(); +#endif + + /* + * Setup unpack. + * + * Note! We use 1 as alignment here because we currently don't do any + * aligning of line pitches anywhere. + */ + pSave->fChanged = 0; + if (pSave->iAlignment != 1) + { + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1), pState, pContext); + pSave->fChanged |= VMSVGAPACKPARAMS_ALIGNMENT; + } + if (pSave->cxRow != cxRow) + { + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, cxRow), pState, pContext); + pSave->fChanged |= VMSVGAPACKPARAMS_ROW_LENGTH; + } + if (pSave->cyImage != cyImage) + { + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, cyImage), pState, pContext); + pSave->fChanged |= VMSVGAPACKPARAMS_IMAGE_HEIGHT; + } +#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING + if (pSave->fSwapBytes != 0) + { + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE), pState, pContext); + pSave->fChanged |= VMSVGAPACKPARAMS_SWAP_BYTES; + } + if (pSave->fLsbFirst != 0) + { + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE), pState, pContext); + pSave->fChanged |= VMSVGAPACKPARAMS_LSB_FIRST; + } + if (pSave->cSkipRows != 0) + { + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS, 0), pState, pContext); + pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_ROWS; + } + if (pSave->cSkipPixels != 0) + { + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0), pState, pContext); + pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_PIXELS; + } + if (pSave->cSkipImages != 0) + { + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0), pState, pContext); + pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_IMAGES; + } +#endif +} + + +/** + * Restores texture unpacking parameters. + * + * @param pState The VMSVGA3D state structure. + * @param pContext The active context. + * @param pSave Where stuff was saved. + */ +void vmsvga3dOglRestoreUnpackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, + PCVMSVGAPACKPARAMS pSave) +{ + RT_NOREF(pState); + + if (pSave->fChanged & VMSVGAPACKPARAMS_ALIGNMENT) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, pSave->iAlignment), pState, pContext); + if (pSave->fChanged & VMSVGAPACKPARAMS_ROW_LENGTH) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, pSave->cxRow), pState, pContext); + if (pSave->fChanged & VMSVGAPACKPARAMS_IMAGE_HEIGHT) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, pSave->cyImage), pState, pContext); +#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING + if (pSave->fChanged & VMSVGAPACKPARAMS_SWAP_BYTES) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SWAP_BYTES, pSave->fSwapBytes), pState, pContext); + if (pSave->fChanged & VMSVGAPACKPARAMS_LSB_FIRST) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_LSB_FIRST, pSave->fLsbFirst), pState, pContext); + if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_ROWS) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS, pSave->cSkipRows), pState, pContext); + if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_PIXELS) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS, pSave->cSkipPixels), pState, pContext); + if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_IMAGES) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_IMAGES, pSave->cSkipImages), pState, pContext); +#endif +} + +/** + * Create D3D/OpenGL texture object for the specified surface. + * + * Surfaces are created when needed. + * + * @param pThisCC The device context. + * @param pContext The context. + * @param idAssociatedContext Probably the same as pContext->id. + * @param pSurface The surface to create the texture for. + */ +static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, + PVMSVGA3DSURFACE pSurface) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + + RT_NOREF(idAssociatedContext); + + LogFunc(("sid=%u\n", pSurface->id)); + + uint32_t const numMipLevels = pSurface->cLevels; + + /* Fugure out what kind of texture we are creating. */ + GLenum binding; + GLenum target; + if (pSurface->f.s.surface1Flags & SVGA3D_SURFACE_CUBEMAP) + { + Assert(pSurface->cFaces == 6); + + binding = GL_TEXTURE_BINDING_CUBE_MAP; + target = GL_TEXTURE_CUBE_MAP; + } + else + { + if (pSurface->paMipmapLevels[0].mipmapSize.depth > 1) + { + binding = GL_TEXTURE_BINDING_3D; + target = GL_TEXTURE_3D; + } + else + { + Assert(pSurface->cFaces == 1); + + binding = GL_TEXTURE_BINDING_2D; + target = GL_TEXTURE_2D; + } + } + + /* All textures are created in the SharedCtx. */ + uint32_t idPrevCtx = pState->idActiveContext; + pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + glGenTextures(1, &pSurface->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + if (pSurface->fEmulated) + { + glGenTextures(1, &pSurface->idEmulated); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + pSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_TEXTURE; + + GLint activeTexture = 0; + glGetIntegerv(binding, &activeTexture); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Must bind texture to the current context in order to change it. */ + glBindTexture(target, pSurface->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Set the unpacking parameters. */ + VMSVGAPACKPARAMS SavedParams; + vmsvga3dOglSetUnpackParams(pState, pContext, 0, 0, &SavedParams); + + /** @todo Set the mip map generation filter settings. */ + + /* Set the mipmap base and max level parameters. */ + glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, pSurface->cLevels - 1); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + if (pSurface->fDirty) + LogFunc(("sync dirty texture\n")); + + /* Always allocate and initialize all mipmap levels; non-initialized mipmap levels used as render targets cause failures. */ + if (target == GL_TEXTURE_3D) + { + for (uint32_t i = 0; i < numMipLevels; ++i) + { + /* Allocate and initialize texture memory. Passing the zero filled pSurfaceData avoids + * exposing random host memory to the guest and helps a with the fedora 21 surface + * corruption issues (launchpad, background, search field, login). + */ + PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i]; + + LogFunc(("sync dirty 3D texture mipmap level %d (pitch %x) (dirty %d)\n", + i, pMipLevel->cbSurfacePitch, pMipLevel->fDirty)); + + if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) + { + pState->ext.glCompressedTexImage3D(GL_TEXTURE_3D, + i, + pSurface->internalFormatGL, + pMipLevel->mipmapSize.width, + pMipLevel->mipmapSize.height, + pMipLevel->mipmapSize.depth, + 0, + pMipLevel->cbSurface, + pMipLevel->pSurfaceData); + } + else + { + pState->ext.glTexImage3D(GL_TEXTURE_3D, + i, + pSurface->internalFormatGL, + pMipLevel->mipmapSize.width, + pMipLevel->mipmapSize.height, + pMipLevel->mipmapSize.depth, + 0, /* border */ + pSurface->formatGL, + pSurface->typeGL, + pMipLevel->pSurfaceData); + } + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pMipLevel->fDirty = false; + } + } + else if (target == GL_TEXTURE_CUBE_MAP) + { + for (uint32_t iFace = 0; iFace < 6; ++iFace) + { + GLenum const Face = vmsvga3dCubemapFaceFromIndex(iFace); + + for (uint32_t i = 0; i < numMipLevels; ++i) + { + PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[iFace * numMipLevels + i]; + Assert(pMipLevel->mipmapSize.width == pMipLevel->mipmapSize.height); + Assert(pMipLevel->mipmapSize.depth == 1); + + LogFunc(("sync cube texture face %d mipmap level %d (dirty %d)\n", + iFace, i, pMipLevel->fDirty)); + + if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) + { + pState->ext.glCompressedTexImage2D(Face, + i, + pSurface->internalFormatGL, + pMipLevel->mipmapSize.width, + pMipLevel->mipmapSize.height, + 0, + pMipLevel->cbSurface, + pMipLevel->pSurfaceData); + } + else + { + glTexImage2D(Face, + i, + pSurface->internalFormatGL, + pMipLevel->mipmapSize.width, + pMipLevel->mipmapSize.height, + 0, + pSurface->formatGL, + pSurface->typeGL, + pMipLevel->pSurfaceData); + } + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pMipLevel->fDirty = false; + } + } + } + else if (target == GL_TEXTURE_2D) + { + for (uint32_t i = 0; i < numMipLevels; ++i) + { + /* Allocate and initialize texture memory. Passing the zero filled pSurfaceData avoids + * exposing random host memory to the guest and helps a with the fedora 21 surface + * corruption issues (launchpad, background, search field, login). + */ + PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i]; + Assert(pMipLevel->mipmapSize.depth == 1); + + LogFunc(("sync dirty texture mipmap level %d (pitch %x) (dirty %d)\n", + i, pMipLevel->cbSurfacePitch, pMipLevel->fDirty)); + + if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) + { + pState->ext.glCompressedTexImage2D(GL_TEXTURE_2D, + i, + pSurface->internalFormatGL, + pMipLevel->mipmapSize.width, + pMipLevel->mipmapSize.height, + 0, + pMipLevel->cbSurface, + pMipLevel->pSurfaceData); + } + else + { + glTexImage2D(GL_TEXTURE_2D, + i, + pSurface->internalFormatGL, + pMipLevel->mipmapSize.width, + pMipLevel->mipmapSize.height, + 0, + pSurface->formatGL, + pSurface->typeGL, + NULL); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + if (pSurface->fEmulated) + { + /* Bind the emulated texture and init it. */ + glBindTexture(GL_TEXTURE_2D, pSurface->idEmulated); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glTexImage2D(GL_TEXTURE_2D, + i, + pSurface->internalFormatGL, + pMipLevel->mipmapSize.width, + pMipLevel->mipmapSize.height, + 0, + pSurface->formatGL, + pSurface->typeGL, + NULL); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + + /* Fetch texture data: either to the actual or to the emulated texture. + * The pSurfaceData buffer may be smaller than the entire texture + * for emulated formats, in which case only part of the texture is synched. + */ + uint32_t cBlocksX = pMipLevel->mipmapSize.width / pSurface->cxBlock; + uint32_t cBlocksY = pMipLevel->mipmapSize.height / pSurface->cyBlock; + glTexSubImage2D(GL_TEXTURE_2D, + i, + 0, + 0, + cBlocksX, + cBlocksY, + pSurface->formatGL, + pSurface->typeGL, + pMipLevel->pSurfaceData); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + if (pSurface->fEmulated) + { + /* Update the actual texture using the format converter. */ + FormatConvUpdateTexture(pState, pContext, pSurface, i); + + /* Rebind the actual texture. */ + glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + } + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + pMipLevel->fDirty = false; + } + } + + pSurface->fDirty = false; + + /* Restore unpacking parameters. */ + vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams); + + /* Restore the old active texture. */ + glBindTexture(target, activeTexture); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pSurface->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_TEXTURE; + pSurface->targetGL = target; + pSurface->bindingGL = binding; + + if (idPrevCtx < pState->cContexts && pState->papContexts[idPrevCtx]->id == idPrevCtx) + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pState->papContexts[idPrevCtx]); + return VINF_SUCCESS; +} + + +/** + * Backend worker for implementing SVGA_3D_CMD_SURFACE_STRETCHBLT. + * + * @returns VBox status code. + * @param pThis The VGA device instance. + * @param pState The VMSVGA3d state. + * @param pDstSurface The destination host surface. + * @param uDstFace The destination face (valid). + * @param uDstMipmap The destination mipmap level (valid). + * @param pDstBox The destination box. + * @param pSrcSurface The source host surface. + * @param uSrcFace The destination face (valid). + * @param uSrcMipmap The source mimap level (valid). + * @param pSrcBox The source box. + * @param enmMode The strecht blt mode . + * @param pContext The VMSVGA3d context (already current for OGL). + */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceStretchBlt(PVGASTATE pThis, PVMSVGA3DSTATE pState, + PVMSVGA3DSURFACE pDstSurface, uint32_t uDstFace, uint32_t uDstMipmap, SVGA3dBox const *pDstBox, + PVMSVGA3DSURFACE pSrcSurface, uint32_t uSrcFace, uint32_t uSrcMipmap, SVGA3dBox const *pSrcBox, + SVGA3dStretchBltMode enmMode, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThis); + + AssertReturn( RT_BOOL(pSrcSurface->f.s.surface1Flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) + == RT_BOOL(pDstSurface->f.s.surface1Flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL), VERR_NOT_IMPLEMENTED); + + GLenum glAttachment = GL_COLOR_ATTACHMENT0; + GLbitfield glMask = GL_COLOR_BUFFER_BIT; + if (pDstSurface->f.s.surface1Flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) + { + /** @todo Need GL_DEPTH_STENCIL_ATTACHMENT for depth/stencil formats? */ + glAttachment = GL_DEPTH_ATTACHMENT; + glMask = GL_DEPTH_BUFFER_BIT; + } + + /* Activate the read and draw framebuffer objects. */ + pState->ext.glBindFramebuffer(GL_READ_FRAMEBUFFER, pContext->idReadFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pContext->idDrawFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Bind the source and destination objects to the right place. */ + GLenum textarget; + if (pSrcSurface->targetGL == GL_TEXTURE_CUBE_MAP) + textarget = vmsvga3dCubemapFaceFromIndex(uSrcFace); + else + { + /// @todo later AssertMsg(pSrcSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pSrcSurface->targetGL)); + textarget = GL_TEXTURE_2D; + } + pState->ext.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment, textarget, + pSrcSurface->oglId.texture, uSrcMipmap); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + if (pDstSurface->targetGL == GL_TEXTURE_CUBE_MAP) + textarget = vmsvga3dCubemapFaceFromIndex(uDstFace); + else + { + /// @todo later AssertMsg(pDstSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pDstSurface->targetGL)); + textarget = GL_TEXTURE_2D; + } + pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, textarget, + pDstSurface->oglId.texture, uDstMipmap); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + Log(("src conv. (%d,%d)(%d,%d); dest conv (%d,%d)(%d,%d)\n", + pSrcBox->x, D3D_TO_OGL_Y_COORD(pSrcSurface, pSrcBox->y + pSrcBox->h), + pSrcBox->x + pSrcBox->w, D3D_TO_OGL_Y_COORD(pSrcSurface, pSrcBox->y), + pDstBox->x, D3D_TO_OGL_Y_COORD(pDstSurface, pDstBox->y + pDstBox->h), + pDstBox->x + pDstBox->w, D3D_TO_OGL_Y_COORD(pDstSurface, pDstBox->y))); + + pState->ext.glBlitFramebuffer(pSrcBox->x, + pSrcBox->y, + pSrcBox->x + pSrcBox->w, /* exclusive. */ + pSrcBox->y + pSrcBox->h, + pDstBox->x, + pDstBox->y, + pDstBox->x + pDstBox->w, /* exclusive. */ + pDstBox->y + pDstBox->h, + glMask, + (enmMode == SVGA3D_STRETCH_BLT_POINT) ? GL_NEAREST : GL_LINEAR); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Reset the frame buffer association */ + pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, pContext->idFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + return VINF_SUCCESS; +} + +/** + * Save texture packing parameters and loads those appropriate for the given + * surface. + * + * @param pState The VMSVGA3D state structure. + * @param pContext The active context. + * @param pSurface The surface. + * @param pSave Where to save stuff. + */ +void vmsvga3dOglSetPackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface, + PVMSVGAPACKPARAMS pSave) +{ + RT_NOREF(pState); + /* + * Save (ignore errors, setting the defaults we want and avoids restore). + */ + pSave->iAlignment = 1; + VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_PACK_ALIGNMENT, &pSave->iAlignment), pState, pContext); + pSave->cxRow = 0; + VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_PACK_ROW_LENGTH, &pSave->cxRow), pState, pContext); + +#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING + pSave->cyImage = 0; + glGetIntegerv(GL_PACK_IMAGE_HEIGHT, &pSave->cyImage); + Assert(pSave->cyImage == 0); + + pSave->fSwapBytes = GL_FALSE; + glGetBooleanv(GL_PACK_SWAP_BYTES, &pSave->fSwapBytes); + Assert(pSave->fSwapBytes == GL_FALSE); + + pSave->fLsbFirst = GL_FALSE; + glGetBooleanv(GL_PACK_LSB_FIRST, &pSave->fLsbFirst); + Assert(pSave->fLsbFirst == GL_FALSE); + + pSave->cSkipRows = 0; + glGetIntegerv(GL_PACK_SKIP_ROWS, &pSave->cSkipRows); + Assert(pSave->cSkipRows == 0); + + pSave->cSkipPixels = 0; + glGetIntegerv(GL_PACK_SKIP_PIXELS, &pSave->cSkipPixels); + Assert(pSave->cSkipPixels == 0); + + pSave->cSkipImages = 0; + glGetIntegerv(GL_PACK_SKIP_IMAGES, &pSave->cSkipImages); + Assert(pSave->cSkipImages == 0); + + VMSVGA3D_CLEAR_GL_ERRORS(); +#endif + + /* + * Setup unpack. + * + * Note! We use 1 as alignment here because we currently don't do any + * aligning of line pitches anywhere. + */ + NOREF(pSurface); + if (pSave->iAlignment != 1) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 1), pState, pContext); + if (pSave->cxRow != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ROW_LENGTH, 0), pState, pContext); +#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING + if (pSave->cyImage != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0), pState, pContext); + if (pSave->fSwapBytes != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE), pState, pContext); + if (pSave->fLsbFirst != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE), pState, pContext); + if (pSave->cSkipRows != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_ROWS, 0), pState, pContext); + if (pSave->cSkipPixels != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_PIXELS, 0), pState, pContext); + if (pSave->cSkipImages != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_IMAGES, 0), pState, pContext); +#endif +} + + +/** + * Restores texture packing parameters. + * + * @param pState The VMSVGA3D state structure. + * @param pContext The active context. + * @param pSurface The surface. + * @param pSave Where stuff was saved. + */ +void vmsvga3dOglRestorePackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface, + PCVMSVGAPACKPARAMS pSave) +{ + RT_NOREF(pState, pSurface); + if (pSave->iAlignment != 1) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, pSave->iAlignment), pState, pContext); + if (pSave->cxRow != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ROW_LENGTH, pSave->cxRow), pState, pContext); +#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING + if (pSave->cyImage != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_IMAGE_HEIGHT, pSave->cyImage), pState, pContext); + if (pSave->fSwapBytes != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SWAP_BYTES, pSave->fSwapBytes), pState, pContext); + if (pSave->fLsbFirst != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_LSB_FIRST, pSave->fLsbFirst), pState, pContext); + if (pSave->cSkipRows != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_ROWS, pSave->cSkipRows), pState, pContext); + if (pSave->cSkipPixels != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_PIXELS, pSave->cSkipPixels), pState, pContext); + if (pSave->cSkipImages != 0) + VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_IMAGES, pSave->cSkipImages), pState, pContext); +#endif +} + + +/** + * Backend worker for implementing SVGA_3D_CMD_SURFACE_DMA that copies one box. + * + * @returns Failure status code or @a rc. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pState The VMSVGA3d state. + * @param pSurface The host surface. + * @param pMipLevel Mipmap level. The caller knows it already. + * @param uHostFace The host face (valid). + * @param uHostMipmap The host mipmap level (valid). + * @param GuestPtr The guest pointer. + * @param cbGuestPitch The guest pitch. + * @param transfer The transfer direction. + * @param pBox The box to copy (clipped, valid, except for guest's srcx, srcy, srcz). + * @param pContext The context (for OpenGL). + * @param rc The current rc for all boxes. + * @param iBox The current box number (for Direct 3D). + */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, + PVMSVGA3DMIPMAPLEVEL pMipLevel, uint32_t uHostFace, uint32_t uHostMipmap, + SVGAGuestPtr GuestPtr, uint32_t cbGuestPitch, SVGA3dTransferType transfer, + SVGA3dCopyBox const *pBox, PVMSVGA3DCONTEXT pContext, int rc, int iBox) +{ + RT_NOREF(iBox); + + switch (pSurface->enmOGLResType) + { + case VMSVGA3D_OGLRESTYPE_TEXTURE: + { + uint32_t cbSurfacePitch; + uint8_t *pDoubleBuffer; + uint64_t offHst; + + uint32_t const u32HostBlockX = pBox->x / pSurface->cxBlock; + uint32_t const u32HostBlockY = pBox->y / pSurface->cyBlock; + uint32_t const u32HostZ = pBox->z; + Assert(u32HostBlockX * pSurface->cxBlock == pBox->x); + Assert(u32HostBlockY * pSurface->cyBlock == pBox->y); + + uint32_t const u32GuestBlockX = pBox->srcx / pSurface->cxBlock; + uint32_t const u32GuestBlockY = pBox->srcy / pSurface->cyBlock; + uint32_t const u32GuestZ = pBox->srcz / pSurface->cyBlock; + Assert(u32GuestBlockX * pSurface->cxBlock == pBox->srcx); + Assert(u32GuestBlockY * pSurface->cyBlock == pBox->srcy); + + uint32_t const cBlocksX = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock; + uint32_t const cBlocksY = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock; + AssertMsgReturn(cBlocksX && cBlocksY, ("Empty box %dx%d\n", pBox->w, pBox->h), VERR_INTERNAL_ERROR); + + GLenum texImageTarget; + if (pSurface->targetGL == GL_TEXTURE_3D) + { + texImageTarget = GL_TEXTURE_3D; + } + else if (pSurface->targetGL == GL_TEXTURE_CUBE_MAP) + { + texImageTarget = vmsvga3dCubemapFaceFromIndex(uHostFace); + } + else + { + AssertMsg(pSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pSurface->targetGL)); + texImageTarget = GL_TEXTURE_2D; + } + + /* The buffer must be large enough to hold entire texture in the OpenGL format. */ + pDoubleBuffer = (uint8_t *)RTMemAlloc(pSurface->cbBlockGL * pMipLevel->cBlocks); + AssertReturn(pDoubleBuffer, VERR_NO_MEMORY); + + if (transfer == SVGA3D_READ_HOST_VRAM) + { + /* Read the entire texture to the double buffer. */ + GLint activeTexture; + + /* Must bind texture to the current context in order to read it. */ + glGetIntegerv(pSurface->bindingGL, &activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glBindTexture(pSurface->targetGL, GLTextureId(pSurface)); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + if (pSurface->fEmulated) + { + FormatConvReadTexture(pState, pContext, pSurface, uHostMipmap); + } + + /* Set row length and alignment of the input data. */ + VMSVGAPACKPARAMS SavedParams; + vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams); + + if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) + { + pState->ext.glGetCompressedTexImage(texImageTarget, uHostMipmap, pDoubleBuffer); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + else + { + glGetTexImage(texImageTarget, uHostMipmap, pSurface->formatGL, pSurface->typeGL, pDoubleBuffer); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + + vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams); + + /* Restore the old active texture. */ + glBindTexture(pSurface->targetGL, activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + offHst = u32HostBlockX * pSurface->cbBlock + u32HostBlockY * pMipLevel->cbSurfacePitch + u32HostZ * pMipLevel->cbSurfacePlane; + cbSurfacePitch = pMipLevel->cbSurfacePitch; + } + else + { + /* The buffer will contain only the copied rectangle. */ + offHst = 0; + cbSurfacePitch = cBlocksX * pSurface->cbBlock; + } + + uint64_t offGst = u32GuestBlockX * pSurface->cbBlock + u32GuestBlockY * cbGuestPitch + u32GuestZ * cbGuestPitch * pMipLevel->mipmapSize.height; + + for (uint32_t iPlane = 0; iPlane < pBox->d; ++iPlane) + { + AssertBreak(offHst < UINT32_MAX); + AssertBreak(offGst < UINT32_MAX); + + rc = vmsvgaR3GmrTransfer(pThis, + pThisCC, + transfer, + pDoubleBuffer, + pMipLevel->cbSurface, + (uint32_t)offHst, + cbSurfacePitch, + GuestPtr, + (uint32_t)offGst, + cbGuestPitch, + cBlocksX * pSurface->cbBlock, + cBlocksY); + AssertRC(rc); + + offHst += pMipLevel->cbSurfacePlane; + offGst += pMipLevel->mipmapSize.height * cbGuestPitch; + } + + /* Update the opengl surface data. */ + if (transfer == SVGA3D_WRITE_HOST_VRAM) + { + GLint activeTexture = 0; + glGetIntegerv(pSurface->bindingGL, &activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /* Must bind texture to the current context in order to change it. */ + glBindTexture(pSurface->targetGL, GLTextureId(pSurface)); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + LogFunc(("copy texture mipmap level %d (pitch %x)\n", uHostMipmap, pMipLevel->cbSurfacePitch)); + + /* Set row length and alignment of the input data. */ + /* We do not need to set ROW_LENGTH to w here, because the image in pDoubleBuffer is tightly packed. */ + VMSVGAPACKPARAMS SavedParams; + vmsvga3dOglSetUnpackParams(pState, pContext, 0, 0, &SavedParams); + + if (texImageTarget == GL_TEXTURE_3D) + { + if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) + { + pState->ext.glCompressedTexSubImage3D(texImageTarget, + uHostMipmap, + pBox->x, + pBox->y, + pBox->z, + pBox->w, + pBox->h, + pBox->d, + pSurface->internalFormatGL, + cbSurfacePitch * cBlocksY * pBox->d, + pDoubleBuffer); + } + else + { + pState->ext.glTexSubImage3D(texImageTarget, + uHostMipmap, + u32HostBlockX, + u32HostBlockY, + pBox->z, + cBlocksX, + cBlocksY, + pBox->d, + pSurface->formatGL, + pSurface->typeGL, + pDoubleBuffer); + } + } + else + { + if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) + { + pState->ext.glCompressedTexSubImage2D(texImageTarget, + uHostMipmap, + pBox->x, + pBox->y, + pBox->w, + pBox->h, + pSurface->internalFormatGL, + cbSurfacePitch * cBlocksY, + pDoubleBuffer); + } + else + { + glTexSubImage2D(texImageTarget, + uHostMipmap, + u32HostBlockX, + u32HostBlockY, + cBlocksX, + cBlocksY, + pSurface->formatGL, + pSurface->typeGL, + pDoubleBuffer); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + if (pSurface->fEmulated) + { + /* Convert the texture to the actual texture if necessary */ + FormatConvUpdateTexture(pState, pContext, pSurface, uHostMipmap); + } + } + } + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /* Restore old values. */ + vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams); + + /* Restore the old active texture. */ + glBindTexture(pSurface->targetGL, activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + + Log4(("first line:\n%.*Rhxd\n", cBlocksX * pSurface->cbBlock, pDoubleBuffer)); + + /* Free the double buffer. */ + RTMemFree(pDoubleBuffer); + break; + } + + case VMSVGA3D_OGLRESTYPE_BUFFER: + { + /* Buffers are uncompressed. */ + AssertReturn(pSurface->cxBlock == 1 && pSurface->cyBlock == 1, VERR_INTERNAL_ERROR); + + /* Caller already clipped pBox and buffers are 1-dimensional. */ + Assert(pBox->y == 0 && pBox->h == 1 && pBox->z == 0 && pBox->d == 1); + + VMSVGA3D_CLEAR_GL_ERRORS(); + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer); + if (VMSVGA3D_GL_IS_SUCCESS(pContext)) + { + GLenum enmGlTransfer = (transfer == SVGA3D_READ_HOST_VRAM) ? GL_READ_ONLY : GL_WRITE_ONLY; + uint8_t *pbData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, enmGlTransfer); + if (RT_LIKELY(pbData != NULL)) + { +#if defined(VBOX_STRICT) && defined(RT_OS_DARWIN) + GLint cbStrictBufSize; + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &cbStrictBufSize); + Assert(VMSVGA3D_GL_IS_SUCCESS(pContext)); + AssertMsg(cbStrictBufSize >= (int32_t)pMipLevel->cbSurface, + ("cbStrictBufSize=%#x cbSurface=%#x pContext->id=%#x\n", (uint32_t)cbStrictBufSize, pMipLevel->cbSurface, pContext->id)); +#endif + Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n", + (pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_VERTEXBUFFER ? "vertex" : + (pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_INDEXBUFFER ? "index" : "buffer", + pBox->x, pBox->y, pBox->x + pBox->w, pBox->y + pBox->h)); + + /* The caller already copied the data to the pMipLevel->pSurfaceData buffer, see VMSVGA3DSURFACE_NEEDS_DATA. */ + uint32_t const offHst = pBox->x * pSurface->cbBlock; + uint32_t const cbWidth = pBox->w * pSurface->cbBlock; + + memcpy(pbData + offHst, (uint8_t *)pMipLevel->pSurfaceData + offHst, cbWidth); + + Log4(("Buffer updated at [0x%x;0x%x):\n%.*Rhxd\n", offHst, offHst + cbWidth, cbWidth, (uint8_t *)pbData + offHst)); + + pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + else + VMSVGA3D_GL_GET_AND_COMPLAIN(pState, pContext, ("glMapBuffer(GL_ARRAY_BUFFER, %#x) -> NULL\n", enmGlTransfer)); + } + else + VMSVGA3D_GL_COMPLAIN(pState, pContext, ("glBindBuffer(GL_ARRAY_BUFFER, %#x)\n", pSurface->oglId.buffer)); + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + default: + AssertFailed(); + break; + } + + return rc; +} + +static DECLCALLBACK(int) vmsvga3dBackGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + PVMSVGA3DSURFACE pSurface; + int rc = VINF_SUCCESS; + PVMSVGA3DCONTEXT pContext; + uint32_t cid; + GLint activeTexture = 0; + + AssertReturn(pState, VERR_NO_MEMORY); + + rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + + Assert(filter != SVGA3D_TEX_FILTER_FLATCUBIC); + Assert(filter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC); + pSurface->autogenFilter = filter; + + LogFunc(("sid=%u filter=%d\n", sid, filter)); + + cid = SVGA3D_INVALID_ID; + pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + if (pSurface->oglId.texture == OPENGL_INVALID_ID) + { + /* Unknown surface type; turn it into a texture. */ + LogFunc(("unknown src surface id=%x type=%d format=%d -> create texture\n", sid, pSurface->f.s.surface1Flags, pSurface->format)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pSurface); + AssertRCReturn(rc, rc); + } + else + { + /** @todo new filter */ + AssertFailed(); + } + + glGetIntegerv(pSurface->bindingGL, &activeTexture); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Must bind texture to the current context in order to change it. */ + glBindTexture(pSurface->targetGL, pSurface->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Generate the mip maps. */ + pState->ext.glGenerateMipmap(pSurface->targetGL); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Restore the old texture. */ + glBindTexture(pSurface->targetGL, activeTexture); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + return VINF_SUCCESS; +} + + +#ifdef RT_OS_LINUX +/** + * X11 event handling thread. + * + * @returns VINF_SUCCESS (ignored) + * @param hThreadSelf thread handle + * @param pvUser pointer to pState structure + */ +DECLCALLBACK(int) vmsvga3dXEventThread(RTTHREAD hThreadSelf, void *pvUser) +{ + RT_NOREF(hThreadSelf); + PVMSVGA3DSTATE pState = (PVMSVGA3DSTATE)pvUser; + while (!pState->bTerminate) + { + while (XPending(pState->display) > 0) + { + XEvent event; + XNextEvent(pState->display, &event); + + switch (event.type) + { + default: + break; + } + } + /* sleep for 16ms to not burn too many cycles */ + RTThreadSleep(16); + } + return VINF_SUCCESS; +} +#endif // RT_OS_LINUX + + +/** + * Create a new 3d context + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param cid Context id + * @param fFlags VMSVGA3D_DEF_CTX_F_XXX. + */ +int vmsvga3dContextDefineOgl(PVGASTATECC pThisCC, uint32_t cid, uint32_t fFlags) +{ + int rc; + PVMSVGA3DCONTEXT pContext; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + + AssertReturn(pState, VERR_NO_MEMORY); + AssertReturn( cid < SVGA3D_MAX_CONTEXT_IDS + || (cid == VMSVGA3D_SHARED_CTX_ID && (fFlags & VMSVGA3D_DEF_CTX_F_SHARED_CTX)), VERR_INVALID_PARAMETER); +#if !defined(VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE) || !(defined(RT_OS_DARWIN)) + AssertReturn(!(fFlags & VMSVGA3D_DEF_CTX_F_OTHER_PROFILE), VERR_INTERNAL_ERROR_3); +#endif + + Log(("vmsvga3dContextDefine id %x\n", cid)); + + if (cid == VMSVGA3D_SHARED_CTX_ID) + pContext = &pState->SharedCtx; + else + { + if (cid >= pState->cContexts) + { + /* Grow the array. */ + uint32_t cNew = RT_ALIGN(cid + 15, 16); + void *pvNew = RTMemRealloc(pState->papContexts, sizeof(pState->papContexts[0]) * cNew); + AssertReturn(pvNew, VERR_NO_MEMORY); + pState->papContexts = (PVMSVGA3DCONTEXT *)pvNew; + while (pState->cContexts < cNew) + { + pContext = (PVMSVGA3DCONTEXT)RTMemAllocZ(sizeof(*pContext)); + AssertReturn(pContext, VERR_NO_MEMORY); + pContext->id = SVGA3D_INVALID_ID; + pState->papContexts[pState->cContexts++] = pContext; + } + } + /* If one already exists with this id, then destroy it now. */ + if (pState->papContexts[cid]->id != SVGA3D_INVALID_ID) + vmsvga3dBackContextDestroy(pThisCC, cid); + + pContext = pState->papContexts[cid]; + } + + /* + * Find or create the shared context if needed (necessary for sharing e.g. textures between contexts). + */ + PVMSVGA3DCONTEXT pSharedCtx = NULL; + if (!(fFlags & (VMSVGA3D_DEF_CTX_F_INIT | VMSVGA3D_DEF_CTX_F_SHARED_CTX))) + { + pSharedCtx = &pState->SharedCtx; + if (pSharedCtx->id != VMSVGA3D_SHARED_CTX_ID) + { + rc = vmsvga3dContextDefineOgl(pThisCC, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX); + AssertLogRelRCReturn(rc, rc); + + /* Create resources which use the shared context. */ + vmsvga3dOnSharedContextDefine(pState); + } + } + + /* + * Initialize the context. + */ + memset(pContext, 0, sizeof(*pContext)); + pContext->id = cid; + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); i++) + pContext->aSidActiveTextures[i] = SVGA3D_INVALID_ID; + + pContext->state.shidVertex = SVGA3D_INVALID_ID; + pContext->state.shidPixel = SVGA3D_INVALID_ID; + pContext->idFramebuffer = OPENGL_INVALID_ID; + pContext->idReadFramebuffer = OPENGL_INVALID_ID; + pContext->idDrawFramebuffer = OPENGL_INVALID_ID; + + rc = ShaderContextCreate(&pContext->pShaderContext); + AssertRCReturn(rc, rc); + + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); i++) + pContext->state.aRenderTargets[i] = SVGA3D_INVALID_ID; + +#ifdef RT_OS_WINDOWS + /* Create a context window with minimal 4x4 size. We will never use the swapchain + * to present the rendered image. Rendered images from the guest will be copied to + * the VMSVGA SCREEN object, which can be either an offscreen render target or + * system memory in the guest VRAM. + */ + rc = vmsvga3dContextWindowCreate(pState->hInstance, pState->pWindowThread, pState->WndRequestSem, &pContext->hwnd); + AssertRCReturn(rc, rc); + + pContext->hdc = GetDC(pContext->hwnd); + AssertMsgReturn(pContext->hdc, ("GetDC %x failed with %d\n", pContext->hwnd, GetLastError()), VERR_INTERNAL_ERROR); + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ + 1, /* version number */ + PFD_DRAW_TO_WINDOW | /* support window */ + PFD_SUPPORT_OPENGL, /* support OpenGL */ + PFD_TYPE_RGBA, /* RGBA type */ + 24, /* 24-bit color depth */ + 0, 0, 0, 0, 0, 0, /* color bits ignored */ + 8, /* alpha buffer */ + 0, /* shift bit ignored */ + 0, /* no accumulation buffer */ + 0, 0, 0, 0, /* accum bits ignored */ + 16, /* set depth buffer */ + 16, /* set stencil buffer */ + 0, /* no auxiliary buffer */ + PFD_MAIN_PLANE, /* main layer */ + 0, /* reserved */ + 0, 0, 0 /* layer masks ignored */ + }; + int pixelFormat; + BOOL ret; + + pixelFormat = ChoosePixelFormat(pContext->hdc, &pfd); + /** @todo is this really necessary?? */ + pixelFormat = ChoosePixelFormat(pContext->hdc, &pfd); + AssertMsgReturn(pixelFormat != 0, ("ChoosePixelFormat failed with %d\n", GetLastError()), VERR_INTERNAL_ERROR); + + ret = SetPixelFormat(pContext->hdc, pixelFormat, &pfd); + AssertMsgReturn(ret == TRUE, ("SetPixelFormat failed with %d\n", GetLastError()), VERR_INTERNAL_ERROR); + + pContext->hglrc = wglCreateContext(pContext->hdc); + AssertMsgReturn(pContext->hglrc, ("wglCreateContext %x failed with %d\n", pContext->hdc, GetLastError()), VERR_INTERNAL_ERROR); + + if (pSharedCtx) + { + ret = wglShareLists(pSharedCtx->hglrc, pContext->hglrc); + AssertMsg(ret == TRUE, ("wglShareLists(%p, %p) failed with %d\n", pSharedCtx->hglrc, pContext->hglrc, GetLastError())); + } + +#elif defined(RT_OS_DARWIN) + pContext->fOtherProfile = RT_BOOL(fFlags & VMSVGA3D_DEF_CTX_F_OTHER_PROFILE); + + NativeNSOpenGLContextRef pShareContext = pSharedCtx ? pSharedCtx->cocoaContext : NULL; + vmsvga3dCocoaCreateViewAndContext(&pContext->cocoaView, &pContext->cocoaContext, + NULL, + 4, 4, + pShareContext, pContext->fOtherProfile); + +#else + if (pState->display == NULL) + { + /* get an X display and make sure we have glX 1.3 */ + pState->display = XOpenDisplay(0); + AssertLogRelMsgReturn(pState->display, ("XOpenDisplay failed"), VERR_INTERNAL_ERROR); + int glxMajor, glxMinor; + Bool ret = glXQueryVersion(pState->display, &glxMajor, &glxMinor); + AssertLogRelMsgReturn(ret && glxMajor == 1 && glxMinor >= 3, ("glX >=1.3 not present"), VERR_INTERNAL_ERROR); + /* start our X event handling thread */ + rc = RTThreadCreate(&pState->pWindowThread, vmsvga3dXEventThread, pState, 0, RTTHREADTYPE_GUI, RTTHREADFLAGS_WAITABLE, "VMSVGA3DXEVENT"); + AssertLogRelMsgReturn(RT_SUCCESS(rc), ("Async IO Thread creation for 3d window handling failed rc=%Rrc\n", rc), rc); + } + + Window defaultRootWindow = XDefaultRootWindow(pState->display); + /* Create a small 4x4 window required for GL context. */ + int attrib[] = + { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + //GLX_ALPHA_SIZE, 1, this flips the bbos screen + GLX_DOUBLEBUFFER, + None + }; + XVisualInfo *vi = glXChooseVisual(pState->display, DefaultScreen(pState->display), attrib); + AssertLogRelMsgReturn(vi, ("glXChooseVisual failed"), VERR_INTERNAL_ERROR); + XSetWindowAttributes swa; + swa.colormap = XCreateColormap(pState->display, defaultRootWindow, vi->visual, AllocNone); + AssertLogRelMsgReturn(swa.colormap, ("XCreateColormap failed"), VERR_INTERNAL_ERROR); + swa.border_pixel = 0; + swa.background_pixel = 0; + swa.event_mask = StructureNotifyMask; + unsigned long flags = CWBorderPixel | CWBackPixel | CWColormap | CWEventMask; + pContext->window = XCreateWindow(pState->display, defaultRootWindow, + 0, 0, 4, 4, + 0, vi->depth, InputOutput, + vi->visual, flags, &swa); + AssertLogRelMsgReturn(pContext->window, ("XCreateWindow failed"), VERR_INTERNAL_ERROR); + + /* The window is hidden by default and never mapped, because we only render offscreen and never present to it. */ + + GLXContext shareContext = pSharedCtx ? pSharedCtx->glxContext : NULL; + pContext->glxContext = glXCreateContext(pState->display, vi, shareContext, GL_TRUE); + XFree(vi); + AssertLogRelMsgReturn(pContext->glxContext, ("glXCreateContext failed"), VERR_INTERNAL_ERROR); +#endif + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* NULL during the first PowerOn call. */ + if (pState->ext.glGenFramebuffers) + { + /* Create a framebuffer object for this context. */ + pState->ext.glGenFramebuffers(1, &pContext->idFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Bind the object to the framebuffer target. */ + pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, pContext->idFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Create read and draw framebuffer objects for this context. */ + pState->ext.glGenFramebuffers(1, &pContext->idReadFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pState->ext.glGenFramebuffers(1, &pContext->idDrawFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + } +#if 0 + /** @todo move to shader lib!!! */ + /* Clear the screen */ + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + glClearColor(1.0f, 0.0f, 0.0f, 0.0f); + glClearIndex(0); + glClearDepth(1); + glClearStencil(0xffff); + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + if (pState->ext.glProvokingVertex) + pState->ext.glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); + /** @todo move to shader lib!!! */ +#endif + return VINF_SUCCESS; +} + +#if defined(RT_OS_LINUX) +/* + * HW accelerated graphics output. + */ + +/** + * VMSVGA3d screen data. + * + * Allocated on the heap and pointed to by VMSVGASCREENOBJECT::pHwScreen. + */ +typedef struct VMSVGAHWSCREEN +{ + /* OpenGL context, which is used for the screen updates. */ + GLXContext glxctx; + + /* The overlay window. */ + Window xwindow; + + /* The RGBA texture which hold the screen content. */ + GLuint idScreenTexture; + + /* Read and draw framebuffer objects for copying a surface to the screen texture. */ + GLuint idReadFramebuffer; + GLuint idDrawFramebuffer; +} VMSVGAHWSCREEN; + +/* Send a notification to the UI. */ +#if 0 /* Unused */ +static int vmsvga3dDrvNotifyHwScreen(PVGASTATECC pThisCC, VBOX3D_NOTIFY_TYPE enmNotification, + uint32_t idScreen, Pixmap pixmap, void *pvData, size_t cbData) +{ + uint8_t au8Buffer[128]; + AssertLogRelMsgReturn(cbData <= sizeof(au8Buffer) - sizeof(VBOX3DNOTIFY), + ("cbData %zu", cbData), + VERR_INVALID_PARAMETER); + + VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0]; + p->enmNotification = enmNotification; + p->iDisplay = idScreen; + p->u32Reserved = 0; + p->cbData = cbData + sizeof(uint64_t); + /* au8Data consists of a 64 bit pixmap handle followed by notification specific data. */ + AssertCompile(sizeof(pixmap) <= sizeof(uint64_t)); + *(uint64_t *)&p->au8Data[0] = (uint64_t)pixmap; + memcpy(&p->au8Data[sizeof(uint64_t)], pvData, cbData); + + int rc = pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p); + return rc; +} +#endif /* Unused */ + +static void vmsvga3dDrvNotifyHwOverlay(PVGASTATECC pThisCC, VBOX3D_NOTIFY_TYPE enmNotification, uint32_t idScreen) +{ + uint8_t au8Buffer[128]; + VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0]; + p->enmNotification = enmNotification; + p->iDisplay = idScreen; + p->u32Reserved = 0; + p->cbData = sizeof(uint64_t); + *(uint64_t *)&p->au8Data[0] = 0; + + pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p); +} + +/* Get X Window handle of the UI Framebuffer window. */ +static int vmsvga3dDrvQueryWindow(PVGASTATECC pThisCC, uint32_t idScreen, Window *pWindow) +{ + uint8_t au8Buffer[128]; + VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0]; + p->enmNotification = VBOX3D_NOTIFY_TYPE_HW_OVERLAY_GET_ID; + p->iDisplay = idScreen; + p->u32Reserved = 0; + p->cbData = sizeof(uint64_t); + *(uint64_t *)&p->au8Data[0] = 0; + + int rc = pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p); + if (RT_SUCCESS(rc)) + { + *pWindow = (Window)*(uint64_t *)&p->au8Data[0]; + } + return rc; +} + +static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) +{ + RT_NOREF(dpy); + LogRel4(("VMSVGA: XError %d\n", (int)ev->error_code)); + return 0; +} + +/* Create an overlay X window for the HW accelerated screen. */ +static int vmsvga3dHwScreenCreate(PVMSVGA3DSTATE pState, Window parentWindow, unsigned int cWidth, unsigned int cHeight, VMSVGAHWSCREEN *p) +{ + int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); + + int rc = VINF_SUCCESS; + + XWindowAttributes parentAttr; + if (XGetWindowAttributes(pState->display, parentWindow, &parentAttr) == 0) + return VERR_INVALID_PARAMETER; + + int const idxParentScreen = XScreenNumberOfScreen(parentAttr.screen); + + /* + * Create a new GL context, which will be used for copying to the screen. + */ + + /* FBConfig attributes for the overlay window. */ + static int const aConfigAttribList[] = + { + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, // Must support GLX windows + GLX_DOUBLEBUFFER, False, // Double buffering had a much lower performance. + GLX_RED_SIZE, 8, // True color RGB with 8 bits per channel. + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_STENCIL_SIZE, 0, // No stencil buffer + GLX_DEPTH_SIZE, 0, // No depth buffer + None + }; + + /* Find a suitable FB config. */ + int cConfigs = 0; + GLXFBConfig *paConfigs = glXChooseFBConfig(pState->display, idxParentScreen, aConfigAttribList, &cConfigs); + LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: paConfigs %p cConfigs %d\n", (void *)paConfigs, cConfigs)); + if (paConfigs) + { + XVisualInfo *vi = NULL; + int i = 0; + for (; i < cConfigs; ++i) + { + /* Use XFree to free the data returned in the previous iteration of this loop. */ + if (vi) + XFree(vi); + + vi = glXGetVisualFromFBConfig(pState->display, paConfigs[i]); + if (!vi) + continue; + + LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: %p vid %lu screen %d depth %d r %lu g %lu b %lu clrmap %d bitsperrgb %d\n", + (void *)vi->visual, vi->visualid, vi->screen, vi->depth, + vi->red_mask, vi->green_mask, vi->blue_mask, vi->colormap_size, vi->bits_per_rgb)); + + /* Same screen as the parent window. */ + if (vi->screen != idxParentScreen) + continue; + + /* Search for 32 bits per pixel. */ + if (vi->depth != 32) + continue; + + /* 8 bits per color component is enough. */ + if (vi->bits_per_rgb != 8) + continue; + + /* Render to pixmap. */ + int value = 0; + glXGetFBConfigAttrib(pState->display, paConfigs[i], GLX_DRAWABLE_TYPE, &value); + if (!(value & GLX_WINDOW_BIT)) + continue; + + /* This FB config can be used. */ + break; + } + + if (i < cConfigs) + { + /* Found a suitable config with index i. */ + + /* Create an overlay window. */ + XSetWindowAttributes swa; + RT_ZERO(swa); + + swa.colormap = XCreateColormap(pState->display, parentWindow, vi->visual, AllocNone); + AssertLogRelMsg(swa.colormap, ("XCreateColormap failed")); + swa.border_pixel = 0; + swa.background_pixel = 0; + swa.event_mask = StructureNotifyMask; + swa.override_redirect = 1; + unsigned long const swaAttrs = CWBorderPixel | CWBackPixel | CWColormap | CWEventMask | CWOverrideRedirect; + p->xwindow = XCreateWindow(pState->display, parentWindow, + 0, 0, cWidth, cHeight, 0, vi->depth, InputOutput, + vi->visual, swaAttrs, &swa); + LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: p->xwindow %ld\n", p->xwindow)); + if (p->xwindow) + { + + p->glxctx = glXCreateContext(pState->display, vi, pState->SharedCtx.glxContext, GL_TRUE); + LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: p->glxctx %p\n", (void *)p->glxctx)); + if (p->glxctx) + { + XMapWindow(pState->display, p->xwindow); + } + else + { + LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: glXCreateContext failed\n")); + rc = VERR_NOT_SUPPORTED; + } + } + else + { + LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: XCreateWindow failed\n")); + rc = VERR_NOT_SUPPORTED; + } + + XSync(pState->display, False); + } + else + { + /* A suitable config is not found. */ + LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: no FBConfig\n")); + rc = VERR_NOT_SUPPORTED; + } + + if (vi) + XFree(vi); + + /* "Use XFree to free the memory returned by glXChooseFBConfig." */ + XFree(paConfigs); + } + else + { + /* glXChooseFBConfig failed. */ + rc = VERR_NOT_SUPPORTED; + } + + XSetErrorHandler(oldHandler); + return rc; +} + +/* Destroy a HW accelerated screen. */ +static void vmsvga3dHwScreenDestroy(PVMSVGA3DSTATE pState, VMSVGAHWSCREEN *p) +{ + if (p) + { + LogRel4(("VMSVGA: vmsvga3dHwScreenDestroy: p->xwindow %ld, ctx %p\n", p->xwindow, (void *)p->glxctx)); + if (p->glxctx) + { + /* GLX context is changed here, so other code has to set the appropriate context again. */ + VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState); + + glXMakeCurrent(pState->display, p->xwindow, p->glxctx); + + /* Clean up OpenGL. */ + if (p->idReadFramebuffer != OPENGL_INVALID_ID) + pState->ext.glDeleteFramebuffers(1, &p->idReadFramebuffer); + if (p->idDrawFramebuffer != OPENGL_INVALID_ID) + pState->ext.glDeleteFramebuffers(1, &p->idDrawFramebuffer); + if (p->idScreenTexture != OPENGL_INVALID_ID) + glDeleteTextures(1, &p->idScreenTexture); + + glXMakeCurrent(pState->display, None, NULL); + + glXDestroyContext(pState->display, p->glxctx); + } + + if (p->xwindow) + XDestroyWindow(pState->display, p->xwindow); + + RT_ZERO(*p); + } +} + +#define GLCHECK() \ + do { \ + int glErr = glGetError(); \ + if (glErr != GL_NO_ERROR) LogRel4(("VMSVGA: GL error 0x%x @%d\n", glErr, __LINE__)); \ + } while(0) + +static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: screen %u\n", pScreen->idScreen)); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NOT_SUPPORTED); + + if (!pThis->svga.f3DOverlayEnabled) + return VERR_NOT_SUPPORTED; + + Assert(pScreen->pHwScreen == NULL); + + VMSVGAHWSCREEN *p = (VMSVGAHWSCREEN *)RTMemAllocZ(sizeof(VMSVGAHWSCREEN)); + AssertPtrReturn(p, VERR_NO_MEMORY); + + /* Query the parent window ID from the UI framebuffer. + * If it is there then + * the device will create a texture for the screen content and an overlay window to present the screen content. + * otherwise + * the device will use the guest VRAM system memory for the screen content. + */ + Window parentWindow; + int rc = vmsvga3dDrvQueryWindow(pThisCC, pScreen->idScreen, &parentWindow); + if (RT_SUCCESS(rc)) + { + /* Create the hardware accelerated screen. */ + rc = vmsvga3dHwScreenCreate(pState, parentWindow, pScreen->cWidth, pScreen->cHeight, p); + if (RT_SUCCESS(rc)) + { + /* + * Setup the OpenGL context of the screen. The context will be used to draw on the screen. + */ + + /* GLX context is changed here, so other code has to set the appropriate context again. */ + VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState); + + Bool const fSuccess = glXMakeCurrent(pState->display, p->xwindow, p->glxctx); + if (fSuccess) + { + /* Set GL state. */ + glClearColor(0, 0, 0, 1); + glEnable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + /* The RGBA texture which hold the screen content. */ + glGenTextures(1, &p->idScreenTexture); GLCHECK(); + glBindTexture(GL_TEXTURE_2D, p->idScreenTexture); GLCHECK(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GLCHECK(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GLCHECK(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, pScreen->cWidth, pScreen->cHeight, 0, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); GLCHECK(); + + /* Create read and draw framebuffer objects for this screen. */ + pState->ext.glGenFramebuffers(1, &p->idReadFramebuffer); GLCHECK(); + pState->ext.glGenFramebuffers(1, &p->idDrawFramebuffer); GLCHECK(); + + /* Work in screen coordinates. */ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glOrtho(0, pScreen->cWidth, 0, pScreen->cHeight, -1, 1); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + /* Clear the texture. */ + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p->idDrawFramebuffer); GLCHECK(); + pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + p->idScreenTexture, 0); GLCHECK(); + + glClear(GL_COLOR_BUFFER_BIT); + + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); GLCHECK(); + + glXMakeCurrent(pState->display, None, NULL); + + XSync(pState->display, False); + + vmsvga3dDrvNotifyHwOverlay(pThisCC, VBOX3D_NOTIFY_TYPE_HW_OVERLAY_CREATED, pScreen->idScreen); + } + else + { + LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: failed to set current context\n")); + rc = VERR_NOT_SUPPORTED; + } + } + } + else + { + LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: no framebuffer\n")); + } + + if (RT_SUCCESS(rc)) + { + LogRel(("VMSVGA: Using HW accelerated screen %u\n", pScreen->idScreen)); + pScreen->pHwScreen = p; + } + else + { + LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: %Rrc\n", rc)); + vmsvga3dHwScreenDestroy(pState, p); + RTMemFree(p); + } + + return rc; +} + +static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + LogRel4(("VMSVGA: vmsvga3dBackDestroyScreen: screen %u\n", pScreen->idScreen)); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NOT_SUPPORTED); + + int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); + + VMSVGAHWSCREEN *p = pScreen->pHwScreen; + if (p) + { + pScreen->pHwScreen = NULL; + + vmsvga3dDrvNotifyHwOverlay(pThisCC, VBOX3D_NOTIFY_TYPE_HW_OVERLAY_DESTROYED, pScreen->idScreen); + + vmsvga3dHwScreenDestroy(pState, p); + RTMemFree(p); + } + + XSetErrorHandler(oldHandler); + + return VINF_SUCCESS; +} + +/* Blit a surface to the GLX pixmap. */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, + SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage, + SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NOT_SUPPORTED); + + VMSVGAHWSCREEN *p = pScreen->pHwScreen; + AssertReturn(p, VERR_NOT_SUPPORTED); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, srcImage.sid, &pSurface); + AssertRCReturn(rc, rc); + + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + LogFunc(("src sid=%u flags=0x%x format=%d -> create texture\n", srcImage.sid, pSurface->f.s.surface1Flags, pSurface->format)); + rc = vmsvga3dBackCreateTexture(pThisCC, &pState->SharedCtx, VMSVGA3D_SHARED_CTX_ID, pSurface); + AssertRCReturn(rc, rc); + } + + AssertReturn(pSurface->enmOGLResType == VMSVGA3D_OGLRESTYPE_TEXTURE, VERR_NOT_SUPPORTED); + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, srcImage.face, srcImage.mipmap, &pMipLevel); + AssertRCReturn(rc, rc); + + /** @todo Implement. */ + RT_NOREF(cRects, paRects); + + /* GLX context is changed here, so other code has to set appropriate context again. */ + VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState); + + int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); + + Bool fSuccess = glXMakeCurrent(pState->display, p->xwindow, p->glxctx); + if (fSuccess) + { + /* Activate the read and draw framebuffer objects. */ + pState->ext.glBindFramebuffer(GL_READ_FRAMEBUFFER, p->idReadFramebuffer); GLCHECK(); + pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p->idDrawFramebuffer); GLCHECK(); + + /* Bind the source and destination objects to the right place. */ + pState->ext.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + pSurface->oglId.texture, 0); GLCHECK(); + pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + p->idScreenTexture, 0); GLCHECK(); + + pState->ext.glBlitFramebuffer(srcRect.left, + srcRect.top, + srcRect.right, + srcRect.bottom, + destRect.left, + destRect.top, + destRect.right, + destRect.bottom, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); GLCHECK(); + + /* Reset the frame buffer association */ + pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, 0); GLCHECK(); + + /* Update the overlay window. */ + glClear(GL_COLOR_BUFFER_BIT); + + glBindTexture(GL_TEXTURE_2D, p->idScreenTexture); GLCHECK(); + + GLint const w = pScreen->cWidth; + GLint const h = pScreen->cHeight; + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2i(0, h); + glTexCoord2f(0.0f, 1.0f); glVertex2i(0, 0); + glTexCoord2f(1.0f, 1.0f); glVertex2i(w, 0); + glTexCoord2f(1.0f, 0.0f); glVertex2i(w, h); + glEnd(); GLCHECK(); + + glBindTexture(GL_TEXTURE_2D, 0); GLCHECK(); + + glXMakeCurrent(pState->display, None, NULL); + } + else + { + LogRel4(("VMSVGA: vmsvga3dBackSurfaceBlitToScreen: screen %u, glXMakeCurrent for pixmap failed\n", pScreen->idScreen)); + } + + XSetErrorHandler(oldHandler); + + return VINF_SUCCESS; +} + +#else /* !RT_OS_LINUX */ + +static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + RT_NOREF(pThis, pThisCC, pScreen); + return VERR_NOT_IMPLEMENTED; +} + +static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + RT_NOREF(pThisCC, pScreen); + return VERR_NOT_IMPLEMENTED; +} + +static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, + SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage, + SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects) +{ + RT_NOREF(pThisCC, pScreen, destRect, srcImage, srcRect, cRects, paRects); + return VERR_NOT_IMPLEMENTED; +} +#endif + +/** + * Create a new 3d context + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param cid Context id + */ +static DECLCALLBACK(int) vmsvga3dBackContextDefine(PVGASTATECC pThisCC, uint32_t cid) +{ + return vmsvga3dContextDefineOgl(pThisCC, cid, 0/*fFlags*/); +} + +/** + * Destroys a 3d context. + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pContext The context to destroy. + * @param cid Context id + */ +static int vmsvga3dContextDestroyOgl(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + AssertReturn(pContext, VERR_INVALID_PARAMETER); + AssertReturn(pContext->id == cid, VERR_INVALID_PARAMETER); + Log(("vmsvga3dContextDestroyOgl id %x\n", cid)); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + if (pContext->id == VMSVGA3D_SHARED_CTX_ID) + { + /* Delete resources which use the shared context. */ + vmsvga3dOnSharedContextDestroy(pState); + } + + /* Destroy all leftover pixel shaders. */ + for (uint32_t i = 0; i < pContext->cPixelShaders; i++) + { + if (pContext->paPixelShader[i].id != SVGA3D_INVALID_ID) + vmsvga3dBackShaderDestroy(pThisCC, pContext->paPixelShader[i].cid, pContext->paPixelShader[i].id, pContext->paPixelShader[i].type); + } + if (pContext->paPixelShader) + RTMemFree(pContext->paPixelShader); + + /* Destroy all leftover vertex shaders. */ + for (uint32_t i = 0; i < pContext->cVertexShaders; i++) + { + if (pContext->paVertexShader[i].id != SVGA3D_INVALID_ID) + vmsvga3dBackShaderDestroy(pThisCC, pContext->paVertexShader[i].cid, pContext->paVertexShader[i].id, pContext->paVertexShader[i].type); + } + if (pContext->paVertexShader) + RTMemFree(pContext->paVertexShader); + + if (pContext->state.paVertexShaderConst) + RTMemFree(pContext->state.paVertexShaderConst); + if (pContext->state.paPixelShaderConst) + RTMemFree(pContext->state.paPixelShaderConst); + + if (pContext->pShaderContext) + { + int rc = ShaderContextDestroy(pContext->pShaderContext); + AssertRC(rc); + } + + if (pContext->idFramebuffer != OPENGL_INVALID_ID) + { + /* Unbind the object from the framebuffer target. */ + pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, 0 /* back buffer */); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + pState->ext.glDeleteFramebuffers(1, &pContext->idFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + if (pContext->idReadFramebuffer != OPENGL_INVALID_ID) + { + pState->ext.glDeleteFramebuffers(1, &pContext->idReadFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + if (pContext->idDrawFramebuffer != OPENGL_INVALID_ID) + { + pState->ext.glDeleteFramebuffers(1, &pContext->idDrawFramebuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + } + + vmsvga3dBackOcclusionQueryDelete(pThisCC, pContext); + +#ifdef RT_OS_WINDOWS + wglMakeCurrent(pContext->hdc, NULL); + wglDeleteContext(pContext->hglrc); + ReleaseDC(pContext->hwnd, pContext->hdc); + + /* Destroy the window we've created. */ + int rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_DESTROYWINDOW, (WPARAM)pContext->hwnd, 0); + AssertRC(rc); +#elif defined(RT_OS_DARWIN) + vmsvga3dCocoaDestroyViewAndContext(pContext->cocoaView, pContext->cocoaContext); +#elif defined(RT_OS_LINUX) + glXMakeCurrent(pState->display, None, NULL); + glXDestroyContext(pState->display, pContext->glxContext); + XDestroyWindow(pState->display, pContext->window); +#endif + + memset(pContext, 0, sizeof(*pContext)); + pContext->id = SVGA3D_INVALID_ID; + + VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState); + return VINF_SUCCESS; +} + +/** + * Destroy an existing 3d context + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param cid Context id + */ +static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_WRONG_ORDER); + + /* + * Resolve the context and hand it to the common worker function. + */ + if ( cid < pState->cContexts + && pState->papContexts[cid]->id == cid) + return vmsvga3dContextDestroyOgl(pThisCC, pState->papContexts[cid], cid); + + AssertReturn(cid < SVGA3D_MAX_CONTEXT_IDS, VERR_INVALID_PARAMETER); + return VINF_SUCCESS; +} + +/** + * Worker for vmsvga3dBackChangeMode that resizes a context. + * + * @param pState The VMSVGA3d state. + * @param pContext The context. + */ +static void vmsvga3dChangeModeOneContext(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pState, pContext); + /* Do nothing. The window is not used for presenting. */ +} + +/* Handle resize */ +static DECLCALLBACK(int) vmsvga3dBackChangeMode(PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + /* Resize the shared context too. */ + if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) + vmsvga3dChangeModeOneContext(pState, &pState->SharedCtx); + + /* Resize all active contexts. */ + for (uint32_t i = 0; i < pState->cContexts; i++) + { + PVMSVGA3DCONTEXT pContext = pState->papContexts[i]; + if (pContext->id != SVGA3D_INVALID_ID) + vmsvga3dChangeModeOneContext(pState, pContext); + } + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16]) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + bool fModelViewChanged = false; + + Log(("vmsvga3dSetTransform cid=%u %s\n", cid, vmsvgaTransformToString(type))); + + ASSERT_GUEST_RETURN((unsigned)type < SVGA3D_TRANSFORM_MAX, VERR_INVALID_PARAMETER); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Save this matrix for vm state save/restore. */ + pContext->state.aTransformState[type].fValid = true; + memcpy(pContext->state.aTransformState[type].matrix, matrix, sizeof(pContext->state.aTransformState[type].matrix)); + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_TRANSFORM; + + Log(("Matrix [%d %d %d %d]\n", (int)(matrix[0] * 10.0), (int)(matrix[1] * 10.0), (int)(matrix[2] * 10.0), (int)(matrix[3] * 10.0))); + Log((" [%d %d %d %d]\n", (int)(matrix[4] * 10.0), (int)(matrix[5] * 10.0), (int)(matrix[6] * 10.0), (int)(matrix[7] * 10.0))); + Log((" [%d %d %d %d]\n", (int)(matrix[8] * 10.0), (int)(matrix[9] * 10.0), (int)(matrix[10] * 10.0), (int)(matrix[11] * 10.0))); + Log((" [%d %d %d %d]\n", (int)(matrix[12] * 10.0), (int)(matrix[13] * 10.0), (int)(matrix[14] * 10.0), (int)(matrix[15] * 10.0))); + + switch (type) + { + case SVGA3D_TRANSFORM_VIEW: + /* View * World = Model View */ + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(matrix); + if (pContext->state.aTransformState[SVGA3D_TRANSFORM_WORLD].fValid) + glMultMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_WORLD].matrix); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + fModelViewChanged = true; + break; + + case SVGA3D_TRANSFORM_PROJECTION: + { + rc = ShaderTransformProjection(pContext->state.RectViewPort.w, pContext->state.RectViewPort.h, matrix, false /* fPretransformed */); + AssertRCReturn(rc, rc); + break; + } + + case SVGA3D_TRANSFORM_TEXTURE0: + glMatrixMode(GL_TEXTURE); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glLoadMatrixf(matrix); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_TRANSFORM_TEXTURE1: + case SVGA3D_TRANSFORM_TEXTURE2: + case SVGA3D_TRANSFORM_TEXTURE3: + case SVGA3D_TRANSFORM_TEXTURE4: + case SVGA3D_TRANSFORM_TEXTURE5: + case SVGA3D_TRANSFORM_TEXTURE6: + case SVGA3D_TRANSFORM_TEXTURE7: + Log(("vmsvga3dSetTransform: unsupported SVGA3D_TRANSFORM_TEXTUREx transform!!\n")); + return VERR_INVALID_PARAMETER; + + case SVGA3D_TRANSFORM_WORLD: + /* View * World = Model View */ + glMatrixMode(GL_MODELVIEW); + if (pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].fValid) + glLoadMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix); + else + glLoadIdentity(); + glMultMatrixf(matrix); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + fModelViewChanged = true; + break; + + case SVGA3D_TRANSFORM_WORLD1: + case SVGA3D_TRANSFORM_WORLD2: + case SVGA3D_TRANSFORM_WORLD3: + Log(("vmsvga3dSetTransform: unsupported SVGA3D_TRANSFORM_WORLDx transform!!\n")); + return VERR_INVALID_PARAMETER; + + default: + Log(("vmsvga3dSetTransform: unknown type!!\n")); + return VERR_INVALID_PARAMETER; + } + + /* Apparently we need to reset the light and clip data after modifying the modelview matrix. */ + if (fModelViewChanged) + { + /* Reprogram the clip planes. */ + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aClipPlane); j++) + { + if (pContext->state.aClipPlane[j].fValid == true) + vmsvga3dBackSetClipPlane(pThisCC, cid, j, pContext->state.aClipPlane[j].plane); + } + + /* Reprogram the light data. */ + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aLightData); j++) + { + if (pContext->state.aLightData[j].fValidData == true) + vmsvga3dBackSetLightData(pThisCC, cid, j, &pContext->state.aLightData[j].data); + } + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetZRange cid=%u min=%d max=%d\n", cid, (uint32_t)(zRange.min * 100.0), (uint32_t)(zRange.max * 100.0))); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + pContext->state.zRange = zRange; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_ZRANGE; + + if (zRange.min < -1.0) + zRange.min = -1.0; + if (zRange.max > 1.0) + zRange.max = 1.0; + + glDepthRange((GLdouble)zRange.min, (GLdouble)zRange.max); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + return VINF_SUCCESS; +} + +/** + * Convert SVGA blend op value to its OpenGL equivalent + */ +static GLenum vmsvga3dBlendOp2GL(uint32_t blendOp) +{ + switch (blendOp) + { + case SVGA3D_BLENDOP_ZERO: + return GL_ZERO; + case SVGA3D_BLENDOP_ONE: + return GL_ONE; + case SVGA3D_BLENDOP_SRCCOLOR: + return GL_SRC_COLOR; + case SVGA3D_BLENDOP_INVSRCCOLOR: + return GL_ONE_MINUS_SRC_COLOR; + case SVGA3D_BLENDOP_SRCALPHA: + return GL_SRC_ALPHA; + case SVGA3D_BLENDOP_INVSRCALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + case SVGA3D_BLENDOP_DESTALPHA: + return GL_DST_ALPHA; + case SVGA3D_BLENDOP_INVDESTALPHA: + return GL_ONE_MINUS_DST_ALPHA; + case SVGA3D_BLENDOP_DESTCOLOR: + return GL_DST_COLOR; + case SVGA3D_BLENDOP_INVDESTCOLOR: + return GL_ONE_MINUS_DST_COLOR; + case SVGA3D_BLENDOP_SRCALPHASAT: + return GL_SRC_ALPHA_SATURATE; + case SVGA3D_BLENDOP_BLENDFACTOR: + return GL_CONSTANT_COLOR; + case SVGA3D_BLENDOP_INVBLENDFACTOR: + return GL_ONE_MINUS_CONSTANT_COLOR; + default: + AssertFailed(); + return GL_ONE; + } +} + +static GLenum vmsvga3dBlendEquation2GL(uint32_t blendEq) +{ + switch (blendEq) + { + case SVGA3D_BLENDEQ_ADD: + return GL_FUNC_ADD; + case SVGA3D_BLENDEQ_SUBTRACT: + return GL_FUNC_SUBTRACT; + case SVGA3D_BLENDEQ_REVSUBTRACT: + return GL_FUNC_REVERSE_SUBTRACT; + case SVGA3D_BLENDEQ_MINIMUM: + return GL_MIN; + case SVGA3D_BLENDEQ_MAXIMUM: + return GL_MAX; + default: + /* SVGA3D_BLENDEQ_INVALID means that the render state has not been set, therefore use default. */ + AssertMsg(blendEq == SVGA3D_BLENDEQ_INVALID, ("blendEq=%d (%#x)\n", blendEq, blendEq)); + return GL_FUNC_ADD; + } +} + +static GLenum vmsvgaCmpFunc2GL(uint32_t cmpFunc) +{ + switch (cmpFunc) + { + case SVGA3D_CMP_NEVER: + return GL_NEVER; + case SVGA3D_CMP_LESS: + return GL_LESS; + case SVGA3D_CMP_EQUAL: + return GL_EQUAL; + case SVGA3D_CMP_LESSEQUAL: + return GL_LEQUAL; + case SVGA3D_CMP_GREATER: + return GL_GREATER; + case SVGA3D_CMP_NOTEQUAL: + return GL_NOTEQUAL; + case SVGA3D_CMP_GREATEREQUAL: + return GL_GEQUAL; + case SVGA3D_CMP_ALWAYS: + return GL_ALWAYS; + default: + Assert(cmpFunc == SVGA3D_CMP_INVALID); + return GL_LESS; + } +} + +static GLenum vmsvgaStencipOp2GL(uint32_t stencilOp) +{ + switch (stencilOp) + { + case SVGA3D_STENCILOP_KEEP: + return GL_KEEP; + case SVGA3D_STENCILOP_ZERO: + return GL_ZERO; + case SVGA3D_STENCILOP_REPLACE: + return GL_REPLACE; + case SVGA3D_STENCILOP_INCRSAT: + return GL_INCR_WRAP; + case SVGA3D_STENCILOP_DECRSAT: + return GL_DECR_WRAP; + case SVGA3D_STENCILOP_INVERT: + return GL_INVERT; + case SVGA3D_STENCILOP_INCR: + return GL_INCR; + case SVGA3D_STENCILOP_DECR: + return GL_DECR; + default: + Assert(stencilOp == SVGA3D_STENCILOP_INVALID); + return GL_KEEP; + } +} + +static DECLCALLBACK(int) vmsvga3dBackSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState) +{ + uint32_t val = UINT32_MAX; /* Shut up MSC. */ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetRenderState cid=%u cRenderStates=%d\n", cid, cRenderStates)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + for (unsigned i = 0; i < cRenderStates; i++) + { + GLenum enableCap = ~(GLenum)0; + Log(("vmsvga3dSetRenderState: cid=%u state=%s (%d) val=%x\n", cid, vmsvga3dGetRenderStateName(pRenderState[i].state), pRenderState[i].state, pRenderState[i].uintValue)); + /* Save the render state for vm state saving. */ + ASSERT_GUEST_RETURN((unsigned)pRenderState[i].state < SVGA3D_RS_MAX, VERR_INVALID_PARAMETER); + pContext->state.aRenderState[pRenderState[i].state] = pRenderState[i]; + + switch (pRenderState[i].state) + { + case SVGA3D_RS_ZENABLE: /* SVGA3dBool */ + enableCap = GL_DEPTH_TEST; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_ZWRITEENABLE: /* SVGA3dBool */ + glDepthMask(!!pRenderState[i].uintValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_ALPHATESTENABLE: /* SVGA3dBool */ + enableCap = GL_ALPHA_TEST; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_DITHERENABLE: /* SVGA3dBool */ + enableCap = GL_DITHER; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_FOGENABLE: /* SVGA3dBool */ + enableCap = GL_FOG; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_SPECULARENABLE: /* SVGA3dBool */ + Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n")); + break; + + case SVGA3D_RS_LIGHTINGENABLE: /* SVGA3dBool */ + enableCap = GL_LIGHTING; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_NORMALIZENORMALS: /* SVGA3dBool */ + /* not applicable */ + Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n")); + break; + + case SVGA3D_RS_POINTSPRITEENABLE: /* SVGA3dBool */ + enableCap = GL_POINT_SPRITE_ARB; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_POINTSIZE: /* float */ + /** @todo we need to apply scaling for point sizes below the min or above the max; see Wine) */ + if (pRenderState[i].floatValue < pState->caps.flPointSize[0]) + pRenderState[i].floatValue = pState->caps.flPointSize[0]; + if (pRenderState[i].floatValue > pState->caps.flPointSize[1]) + pRenderState[i].floatValue = pState->caps.flPointSize[1]; + + glPointSize(pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + Log(("SVGA3D_RS_POINTSIZE: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0))); + break; + + case SVGA3D_RS_POINTSIZEMIN: /* float */ + pState->ext.glPointParameterf(GL_POINT_SIZE_MIN, pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + Log(("SVGA3D_RS_POINTSIZEMIN: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0))); + break; + + case SVGA3D_RS_POINTSIZEMAX: /* float */ + pState->ext.glPointParameterf(GL_POINT_SIZE_MAX, pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + Log(("SVGA3D_RS_POINTSIZEMAX: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0))); + break; + + case SVGA3D_RS_POINTSCALEENABLE: /* SVGA3dBool */ + case SVGA3D_RS_POINTSCALE_A: /* float */ + case SVGA3D_RS_POINTSCALE_B: /* float */ + case SVGA3D_RS_POINTSCALE_C: /* float */ + Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n")); + break; + + case SVGA3D_RS_AMBIENT: /* SVGA3dColor */ + { + GLfloat color[4]; /* red, green, blue, alpha */ + + vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &color[0], &color[1], &color[2], &color[3]); + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_CLIPPLANEENABLE: /* SVGA3dClipPlanes */ + { + for (uint32_t j = 0; j < SVGA3D_NUM_CLIPPLANES; j++) + { + if (pRenderState[i].uintValue & RT_BIT(j)) + glEnable(GL_CLIP_PLANE0 + j); + else + glDisable(GL_CLIP_PLANE0 + j); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + break; + } + + case SVGA3D_RS_FOGCOLOR: /* SVGA3dColor */ + { + GLfloat color[4]; /* red, green, blue, alpha */ + + vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &color[0], &color[1], &color[2], &color[3]); + + glFogfv(GL_FOG_COLOR, color); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_FOGSTART: /* float */ + glFogf(GL_FOG_START, pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_FOGEND: /* float */ + glFogf(GL_FOG_END, pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_FOGDENSITY: /* float */ + glFogf(GL_FOG_DENSITY, pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_RANGEFOGENABLE: /* SVGA3dBool */ + glFogi(GL_FOG_COORD_SRC, (pRenderState[i].uintValue) ? GL_FOG_COORD : GL_FRAGMENT_DEPTH); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_FOGMODE: /* SVGA3dFogMode */ + { + SVGA3dFogMode mode; + mode.uintValue = pRenderState[i].uintValue; + + enableCap = GL_FOG_MODE; + switch (mode.function) + { + case SVGA3D_FOGFUNC_EXP: + val = GL_EXP; + break; + case SVGA3D_FOGFUNC_EXP2: + val = GL_EXP2; + break; + case SVGA3D_FOGFUNC_LINEAR: + val = GL_LINEAR; + break; + default: + AssertMsgFailedReturn(("Unexpected fog function %d\n", mode.function), VERR_INTERNAL_ERROR); + break; + } + + /** @todo how to switch between vertex and pixel fog modes??? */ + Assert(mode.type == SVGA3D_FOGTYPE_PIXEL); +#if 0 + /* The fog type determines the render state. */ + switch (mode.type) + { + case SVGA3D_FOGTYPE_VERTEX: + renderState = D3DRS_FOGVERTEXMODE; + break; + case SVGA3D_FOGTYPE_PIXEL: + renderState = D3DRS_FOGTABLEMODE; + break; + default: + AssertMsgFailedReturn(("Unexpected fog type %d\n", mode.type), VERR_INTERNAL_ERROR); + break; + } +#endif + + /* Set the fog base to depth or range. */ + switch (mode.base) + { + case SVGA3D_FOGBASE_DEPTHBASED: + glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_FOGBASE_RANGEBASED: + glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + default: + /* ignore */ + AssertMsgFailed(("Unexpected fog base %d\n", mode.base)); + break; + } + break; + } + + case SVGA3D_RS_FILLMODE: /* SVGA3dFillMode */ + { + SVGA3dFillMode mode; + + mode.uintValue = pRenderState[i].uintValue; + + switch (mode.mode) + { + case SVGA3D_FILLMODE_POINT: + val = GL_POINT; + break; + case SVGA3D_FILLMODE_LINE: + val = GL_LINE; + break; + case SVGA3D_FILLMODE_FILL: + val = GL_FILL; + break; + default: + AssertMsgFailedReturn(("Unexpected fill mode %d\n", mode.mode), VERR_INTERNAL_ERROR); + break; + } + /* Only front and back faces. Also recent Mesa guest drivers initialize the 'face' to zero. */ + ASSERT_GUEST(mode.face == SVGA3D_FACE_FRONT_BACK || mode.face == SVGA3D_FACE_INVALID); + glPolygonMode(GL_FRONT_AND_BACK, val); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_SHADEMODE: /* SVGA3dShadeMode */ + switch (pRenderState[i].uintValue) + { + case SVGA3D_SHADEMODE_FLAT: + val = GL_FLAT; + break; + + case SVGA3D_SHADEMODE_SMOOTH: + val = GL_SMOOTH; + break; + + default: + AssertMsgFailedReturn(("Unexpected shade mode %d\n", pRenderState[i].uintValue), VERR_INTERNAL_ERROR); + break; + } + + glShadeModel(val); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_LINEPATTERN: /* SVGA3dLinePattern */ + /* No longer supported by d3d; mesagl comments suggest not all backends support it */ + /** @todo */ + Log(("WARNING: SVGA3D_RS_LINEPATTERN %x not supported!!\n", pRenderState[i].uintValue)); + /* + renderState = D3DRS_LINEPATTERN; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_ANTIALIASEDLINEENABLE: /* SVGA3dBool */ + enableCap = GL_LINE_SMOOTH; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_LINEWIDTH: /* float */ + glLineWidth(pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */ + { + /* Refresh the blending state based on the new enable setting. + * This will take existing states and set them using either glBlend* or glBlend*Separate. + */ + static SVGA3dRenderStateName const saRefreshState[] = + { + SVGA3D_RS_SRCBLEND, + SVGA3D_RS_BLENDEQUATION + }; + SVGA3dRenderState renderstate[RT_ELEMENTS(saRefreshState)]; + for (uint32_t j = 0; j < RT_ELEMENTS(saRefreshState); ++j) + { + renderstate[j].state = saRefreshState[j]; + renderstate[j].uintValue = pContext->state.aRenderState[saRefreshState[j]].uintValue; + } + + rc = vmsvga3dBackSetRenderState(pThisCC, cid, 2, renderstate); + AssertRCReturn(rc, rc); + + if (pContext->state.aRenderState[SVGA3D_RS_BLENDENABLE].uintValue != 0) + continue; /* Ignore if blend is enabled */ + /* Apply SVGA3D_RS_SEPARATEALPHABLENDENABLE as SVGA3D_RS_BLENDENABLE */ + } RT_FALL_THRU(); + + case SVGA3D_RS_BLENDENABLE: /* SVGA3dBool */ + enableCap = GL_BLEND; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_SRCBLENDALPHA: /* SVGA3dBlendOp */ + case SVGA3D_RS_DSTBLENDALPHA: /* SVGA3dBlendOp */ + case SVGA3D_RS_SRCBLEND: /* SVGA3dBlendOp */ + case SVGA3D_RS_DSTBLEND: /* SVGA3dBlendOp */ + { + GLint srcRGB, srcAlpha, dstRGB, dstAlpha; + GLint blendop = vmsvga3dBlendOp2GL(pRenderState[i].uintValue); + + glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_BLEND_DST_ALPHA, &dstAlpha); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcAlpha); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + switch (pRenderState[i].state) + { + case SVGA3D_RS_SRCBLEND: + srcRGB = blendop; + break; + case SVGA3D_RS_DSTBLEND: + dstRGB = blendop; + break; + case SVGA3D_RS_SRCBLENDALPHA: + srcAlpha = blendop; + break; + case SVGA3D_RS_DSTBLENDALPHA: + dstAlpha = blendop; + break; + default: + /* not possible; shut up gcc */ + AssertFailed(); + break; + } + + if (pContext->state.aRenderState[SVGA3D_RS_SEPARATEALPHABLENDENABLE].uintValue != 0) + pState->ext.glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); + else + glBlendFunc(srcRGB, dstRGB); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation */ + case SVGA3D_RS_BLENDEQUATION: /* SVGA3dBlendEquation */ + if (pContext->state.aRenderState[SVGA3D_RS_SEPARATEALPHABLENDENABLE].uintValue != 0) + { + GLenum const modeRGB = vmsvga3dBlendEquation2GL(pContext->state.aRenderState[SVGA3D_RS_BLENDEQUATION].uintValue); + GLenum const modeAlpha = vmsvga3dBlendEquation2GL(pContext->state.aRenderState[SVGA3D_RS_BLENDEQUATIONALPHA].uintValue); + pState->ext.glBlendEquationSeparate(modeRGB, modeAlpha); + } + else + { +#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x102 + glBlendEquation(vmsvga3dBlendEquation2GL(pRenderState[i].uintValue)); +#else + pState->ext.glBlendEquation(vmsvga3dBlendEquation2GL(pRenderState[i].uintValue)); +#endif + } + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_BLENDCOLOR: /* SVGA3dColor */ + { + GLfloat red, green, blue, alpha; + + vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &red, &green, &blue, &alpha); + +#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x102 + glBlendColor(red, green, blue, alpha); +#else + pState->ext.glBlendColor(red, green, blue, alpha); +#endif + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_CULLMODE: /* SVGA3dFace */ + { + GLenum mode = GL_BACK; /* default for OpenGL */ + + switch (pRenderState[i].uintValue) + { + case SVGA3D_FACE_NONE: + break; + case SVGA3D_FACE_FRONT: + mode = GL_FRONT; + break; + case SVGA3D_FACE_BACK: + mode = GL_BACK; + break; + case SVGA3D_FACE_FRONT_BACK: + mode = GL_FRONT_AND_BACK; + break; + default: + AssertMsgFailedReturn(("Unexpected cull mode %d\n", pRenderState[i].uintValue), VERR_INTERNAL_ERROR); + break; + } + enableCap = GL_CULL_FACE; + if (pRenderState[i].uintValue != SVGA3D_FACE_NONE) + { + glCullFace(mode); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + val = 1; + } + else + val = 0; + break; + } + + case SVGA3D_RS_ZFUNC: /* SVGA3dCmpFunc */ + glDepthFunc(vmsvgaCmpFunc2GL(pRenderState[i].uintValue)); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_ALPHAFUNC: /* SVGA3dCmpFunc */ + { + GLclampf ref; + + glGetFloatv(GL_ALPHA_TEST_REF, &ref); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glAlphaFunc(vmsvgaCmpFunc2GL(pRenderState[i].uintValue), ref); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_ALPHAREF: /* float (0.0 .. 1.0) */ + { + GLint func; + + glGetIntegerv(GL_ALPHA_TEST_FUNC, &func); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glAlphaFunc(func, pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_STENCILENABLE2SIDED: /* SVGA3dBool */ + { + /* Refresh the stencil state based on the new enable setting. + * This will take existing states and set them using either glStencil or glStencil*Separate. + */ + static SVGA3dRenderStateName const saRefreshState[] = + { + SVGA3D_RS_STENCILFUNC, + SVGA3D_RS_STENCILFAIL, + SVGA3D_RS_CCWSTENCILFUNC, + SVGA3D_RS_CCWSTENCILFAIL + }; + SVGA3dRenderState renderstate[RT_ELEMENTS(saRefreshState)]; + for (uint32_t j = 0; j < RT_ELEMENTS(saRefreshState); ++j) + { + renderstate[j].state = saRefreshState[j]; + renderstate[j].uintValue = pContext->state.aRenderState[saRefreshState[j]].uintValue; + } + + rc = vmsvga3dBackSetRenderState(pThisCC, cid, RT_ELEMENTS(renderstate), renderstate); + AssertRCReturn(rc, rc); + + if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE].uintValue != 0) + continue; /* Ignore if stencil is enabled */ + /* Apply SVGA3D_RS_STENCILENABLE2SIDED as SVGA3D_RS_STENCILENABLE. */ + } RT_FALL_THRU(); + + case SVGA3D_RS_STENCILENABLE: /* SVGA3dBool */ + enableCap = GL_STENCIL_TEST; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc */ + case SVGA3D_RS_STENCILREF: /* uint32_t */ + case SVGA3D_RS_STENCILMASK: /* uint32_t */ + { + GLint func, ref; + GLuint mask; + + /* Query current values to have all parameters for glStencilFunc[Separate]. */ + glGetIntegerv(GL_STENCIL_FUNC, &func); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&mask); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_STENCIL_REF, &ref); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Update the changed value. */ + switch (pRenderState[i].state) + { + case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc */ + func = vmsvgaCmpFunc2GL(pRenderState[i].uintValue); + break; + + case SVGA3D_RS_STENCILREF: /* uint32_t */ + ref = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILMASK: /* uint32_t */ + mask = pRenderState[i].uintValue; + break; + + default: + /* not possible; shut up gcc */ + AssertFailed(); + break; + } + + if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE2SIDED].uintValue != 0) + { + pState->ext.glStencilFuncSeparate(GL_FRONT, func, ref, mask); + } + else + { + glStencilFunc(func, ref, mask); + } + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_STENCILWRITEMASK: /* uint32_t */ + glStencilMask(pRenderState[i].uintValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp */ + case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp */ + case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp */ + { + GLint sfail, dpfail, dppass; + GLenum const stencilop = vmsvgaStencipOp2GL(pRenderState[i].uintValue); + + glGetIntegerv(GL_STENCIL_FAIL, &sfail); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &dpfail); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &dppass); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + switch (pRenderState[i].state) + { + case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp */ + sfail = stencilop; + break; + case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp */ + dpfail = stencilop; + break; + case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp */ + dppass = stencilop; + break; + default: + /* not possible; shut up gcc */ + AssertFailed(); + break; + } + if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE2SIDED].uintValue != 0) + { + pState->ext.glStencilOpSeparate(GL_FRONT, sfail, dpfail, dppass); + } + else + { + glStencilOp(sfail, dpfail, dppass); + } + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_CCWSTENCILFUNC: /* SVGA3dCmpFunc */ + { + GLint ref; + GLuint mask; + GLint const func = vmsvgaCmpFunc2GL(pRenderState[i].uintValue); + + /* GL_STENCIL_VALUE_MASK and GL_STENCIL_REF are the same for both GL_FRONT and GL_BACK. */ + glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&mask); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_STENCIL_REF, &ref); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pState->ext.glStencilFuncSeparate(GL_BACK, func, ref, mask); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp */ + case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp */ + case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp */ + { + GLint sfail, dpfail, dppass; + GLenum const stencilop = vmsvgaStencipOp2GL(pRenderState[i].uintValue); + + glGetIntegerv(GL_STENCIL_BACK_FAIL, &sfail); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &dpfail); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &dppass); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + switch (pRenderState[i].state) + { + case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp */ + sfail = stencilop; + break; + case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp */ + dpfail = stencilop; + break; + case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp */ + dppass = stencilop; + break; + default: + /* not possible; shut up gcc */ + AssertFailed(); + break; + } + pState->ext.glStencilOpSeparate(GL_BACK, sfail, dpfail, dppass); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_ZBIAS: /* float */ + /** @todo unknown meaning; depth bias is not identical + renderState = D3DRS_DEPTHBIAS; + val = pRenderState[i].uintValue; + */ + Log(("vmsvga3dSetRenderState: WARNING unsupported SVGA3D_RS_ZBIAS\n")); + break; + + case SVGA3D_RS_DEPTHBIAS: /* float */ + { + GLfloat factor; + + /** @todo not sure if the d3d & ogl definitions are identical. */ + + /* Do not change the factor part. */ + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &factor); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + glPolygonOffset(factor, pRenderState[i].floatValue); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_SLOPESCALEDEPTHBIAS: /* float */ + { + GLfloat units; + + /** @todo not sure if the d3d & ogl definitions are identical. */ + + /* Do not change the factor part. */ + glGetFloatv(GL_POLYGON_OFFSET_UNITS, &units); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + glPolygonOffset(pRenderState[i].floatValue, units); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_COLORWRITEENABLE: /* SVGA3dColorMask */ + { + GLboolean red, green, blue, alpha; + SVGA3dColorMask mask; + + mask.uintValue = pRenderState[i].uintValue; + + red = mask.red; + green = mask.green; + blue = mask.blue; + alpha = mask.alpha; + + glColorMask(red, green, blue, alpha); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_RS_COLORWRITEENABLE1: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */ + case SVGA3D_RS_COLORWRITEENABLE2: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */ + case SVGA3D_RS_COLORWRITEENABLE3: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */ + Log(("vmsvga3dSetRenderState: WARNING SVGA3D_RS_COLORWRITEENABLEx not supported!!\n")); + break; + + case SVGA3D_RS_SCISSORTESTENABLE: /* SVGA3dBool */ + enableCap = GL_SCISSOR_TEST; + val = pRenderState[i].uintValue; + break; + +#if 0 + case SVGA3D_RS_DIFFUSEMATERIALSOURCE: /* SVGA3dVertexMaterial */ + AssertCompile(D3DMCS_COLOR2 == SVGA3D_VERTEXMATERIAL_SPECULAR); + renderState = D3DRS_DIFFUSEMATERIALSOURCE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_SPECULARMATERIALSOURCE: /* SVGA3dVertexMaterial */ + renderState = D3DRS_SPECULARMATERIALSOURCE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_AMBIENTMATERIALSOURCE: /* SVGA3dVertexMaterial */ + renderState = D3DRS_AMBIENTMATERIALSOURCE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_EMISSIVEMATERIALSOURCE: /* SVGA3dVertexMaterial */ + renderState = D3DRS_EMISSIVEMATERIALSOURCE; + val = pRenderState[i].uintValue; + break; +#endif + + case SVGA3D_RS_WRAP3: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP4: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP5: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP6: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP7: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP8: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP9: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP10: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP11: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP12: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP13: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP14: /* SVGA3dWrapFlags */ + case SVGA3D_RS_WRAP15: /* SVGA3dWrapFlags */ + Log(("vmsvga3dSetRenderState: WARNING unsupported SVGA3D_WRAPx (x >= 3)\n")); + break; + + case SVGA3D_RS_LASTPIXEL: /* SVGA3dBool */ + case SVGA3D_RS_TWEENFACTOR: /* float */ + case SVGA3D_RS_INDEXEDVERTEXBLENDENABLE: /* SVGA3dBool */ + case SVGA3D_RS_VERTEXBLEND: /* SVGA3dVertexBlendFlags */ + Log(("vmsvga3dSetRenderState: WARNING not applicable!!\n")); + break; + + case SVGA3D_RS_MULTISAMPLEANTIALIAS: /* SVGA3dBool */ + enableCap = GL_MULTISAMPLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_MULTISAMPLEMASK: /* uint32_t */ + Log(("vmsvga3dSetRenderState: WARNING not applicable??!!\n")); + break; + + case SVGA3D_RS_COORDINATETYPE: /* SVGA3dCoordinateType */ + Assert(pRenderState[i].uintValue == SVGA3D_COORDINATE_LEFTHANDED); + /** @todo setup a view matrix to scale the world space by -1 in the z-direction for right handed coordinates. */ + /* + renderState = D3DRS_COORDINATETYPE; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_FRONTWINDING: /* SVGA3dFrontWinding */ + Assert(pRenderState[i].uintValue == SVGA3D_FRONTWINDING_CW); + /* Invert the selected mode because of y-inversion (?) */ + glFrontFace((pRenderState[i].uintValue != SVGA3D_FRONTWINDING_CW) ? GL_CW : GL_CCW); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RS_OUTPUTGAMMA: /* float */ + //AssertFailed(); + /* + D3DRS_SRGBWRITEENABLE ?? + renderState = D3DRS_OUTPUTGAMMA; + val = pRenderState[i].uintValue; + */ + break; + +#if 0 + + case SVGA3D_RS_VERTEXMATERIALENABLE: /* SVGA3dBool */ + //AssertFailed(); + renderState = D3DRS_INDEXEDVERTEXBLENDENABLE; /* correct?? */ + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_TEXTUREFACTOR: /* SVGA3dColor */ + renderState = D3DRS_TEXTUREFACTOR; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_LOCALVIEWER: /* SVGA3dBool */ + renderState = D3DRS_LOCALVIEWER; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_ZVISIBLE: /* SVGA3dBool */ + AssertFailed(); + /* + renderState = D3DRS_ZVISIBLE; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_CLIPPING: /* SVGA3dBool */ + renderState = D3DRS_CLIPPING; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP0: /* SVGA3dWrapFlags */ + glTexParameter GL_TEXTURE_WRAP_S + Assert(SVGA3D_WRAPCOORD_3 == D3DWRAPCOORD_3); + renderState = D3DRS_WRAP0; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP1: /* SVGA3dWrapFlags */ + glTexParameter GL_TEXTURE_WRAP_T + renderState = D3DRS_WRAP1; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP2: /* SVGA3dWrapFlags */ + glTexParameter GL_TEXTURE_WRAP_R + renderState = D3DRS_WRAP2; + val = pRenderState[i].uintValue; + break; + + + case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */ + renderState = D3DRS_SEPARATEALPHABLENDENABLE; + val = pRenderState[i].uintValue; + break; + + + case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation */ + renderState = D3DRS_BLENDOPALPHA; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_TRANSPARENCYANTIALIAS: /* SVGA3dTransparencyAntialiasType */ + AssertFailed(); + /* + renderState = D3DRS_TRANSPARENCYANTIALIAS; + val = pRenderState[i].uintValue; + */ + break; + +#endif + default: + AssertFailed(); + break; + } + + if (enableCap != ~(GLenum)0) + { + if (val) + glEnable(enableCap); + else + glDisable(enableCap); + } + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + + AssertReturn(pState, VERR_NO_MEMORY); + AssertReturn((unsigned)type < SVGA3D_RT_MAX, VERR_INVALID_PARAMETER); + + LogFunc(("cid=%u type=%x sid=%u\n", cid, type, target.sid)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Save for vm state save/restore. */ + pContext->state.aRenderTargets[type] = target.sid; + + if (target.sid == SVGA3D_INVALID_ID) + { + /* Disable render target. */ + switch (type) + { + case SVGA3D_RT_DEPTH: + case SVGA3D_RT_STENCIL: + pState->ext.glFramebufferRenderbuffer(GL_FRAMEBUFFER, (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + case SVGA3D_RT_COLOR0: + case SVGA3D_RT_COLOR1: + case SVGA3D_RT_COLOR2: + case SVGA3D_RT_COLOR3: + case SVGA3D_RT_COLOR4: + case SVGA3D_RT_COLOR5: + case SVGA3D_RT_COLOR6: + case SVGA3D_RT_COLOR7: + pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + type - SVGA3D_RT_COLOR0, 0, 0, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + return VINF_SUCCESS; + } + + PVMSVGA3DSURFACE pRenderTarget; + rc = vmsvga3dSurfaceFromSid(pState, target.sid, &pRenderTarget); + AssertRCReturn(rc, rc); + + switch (type) + { + case SVGA3D_RT_DEPTH: + case SVGA3D_RT_STENCIL: +#if 1 + /* A texture surface can be used as a render target to fill it and later on used as a texture. */ + if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID) + { + LogFunc(("create depth texture to be used as render target; surface id=%x type=%d format=%d -> create texture\n", + target.sid, pRenderTarget->f.s.surface1Flags, pRenderTarget->format)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pRenderTarget); + AssertRCReturn(rc, rc); + } + + AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER); + Assert(!pRenderTarget->fDirty); + + pRenderTarget->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL; + + pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER, + (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT, + GL_TEXTURE_2D, pRenderTarget->oglId.texture, target.mipmap); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); +#else + AssertReturn(target.mipmap == 0, VERR_INVALID_PARAMETER); + if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID) + { + Log(("vmsvga3dSetRenderTarget: create renderbuffer to be used as render target; surface id=%x type=%d format=%d\n", target.sid, pRenderTarget->f.s.surface1Flags, pRenderTarget->internalFormatGL)); + pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + pState->ext.glGenRenderbuffers(1, &pRenderTarget->oglId.renderbuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + pSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_RENDERBUFFER; + + pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pState->ext.glRenderbufferStorage(GL_RENDERBUFFER, + pRenderTarget->internalFormatGL, + pRenderTarget->paMipmapLevels[0].mipmapSize.width, + pRenderTarget->paMipmapLevels[0].mipmapSize.height); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, OPENGL_INVALID_ID); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pContext = pState->papContexts[cid]; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + } + + pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + Assert(!pRenderTarget->fDirty); + AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER); + + pRenderTarget->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL; + + pState->ext.glFramebufferRenderbuffer(GL_FRAMEBUFFER, + (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); +#endif + break; + + case SVGA3D_RT_COLOR0: + case SVGA3D_RT_COLOR1: + case SVGA3D_RT_COLOR2: + case SVGA3D_RT_COLOR3: + case SVGA3D_RT_COLOR4: + case SVGA3D_RT_COLOR5: + case SVGA3D_RT_COLOR6: + case SVGA3D_RT_COLOR7: + { + /* A texture surface can be used as a render target to fill it and later on used as a texture. */ + if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID) + { + Log(("vmsvga3dSetRenderTarget: create texture to be used as render target; surface id=%x type=%d format=%d -> create texture\n", target.sid, pRenderTarget->f.s.surface1Flags, pRenderTarget->format)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pRenderTarget); + AssertRCReturn(rc, rc); + } + + AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER); + Assert(!pRenderTarget->fDirty); + + pRenderTarget->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_RENDERTARGET; + + GLenum textarget; + if (pRenderTarget->f.s.surface1Flags & SVGA3D_SURFACE_CUBEMAP) + textarget = vmsvga3dCubemapFaceFromIndex(target.face); + else + textarget = GL_TEXTURE_2D; + pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + type - SVGA3D_RT_COLOR0, + textarget, pRenderTarget->oglId.texture, target.mipmap); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + +#ifdef DEBUG + GLenum status = pState->ext.glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + Log(("vmsvga3dSetRenderTarget: WARNING: glCheckFramebufferStatus returned %x\n", status)); +#endif + /** @todo use glDrawBuffers too? */ + break; + } + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + + return VINF_SUCCESS; +} + +#if 0 +/** + * Convert SVGA texture combiner value to its D3D equivalent + */ +static DWORD vmsvga3dTextureCombiner2D3D(uint32_t value) +{ + switch (value) + { + case SVGA3D_TC_DISABLE: + return D3DTOP_DISABLE; + case SVGA3D_TC_SELECTARG1: + return D3DTOP_SELECTARG1; + case SVGA3D_TC_SELECTARG2: + return D3DTOP_SELECTARG2; + case SVGA3D_TC_MODULATE: + return D3DTOP_MODULATE; + case SVGA3D_TC_ADD: + return D3DTOP_ADD; + case SVGA3D_TC_ADDSIGNED: + return D3DTOP_ADDSIGNED; + case SVGA3D_TC_SUBTRACT: + return D3DTOP_SUBTRACT; + case SVGA3D_TC_BLENDTEXTUREALPHA: + return D3DTOP_BLENDTEXTUREALPHA; + case SVGA3D_TC_BLENDDIFFUSEALPHA: + return D3DTOP_BLENDDIFFUSEALPHA; + case SVGA3D_TC_BLENDCURRENTALPHA: + return D3DTOP_BLENDCURRENTALPHA; + case SVGA3D_TC_BLENDFACTORALPHA: + return D3DTOP_BLENDFACTORALPHA; + case SVGA3D_TC_MODULATE2X: + return D3DTOP_MODULATE2X; + case SVGA3D_TC_MODULATE4X: + return D3DTOP_MODULATE4X; + case SVGA3D_TC_DSDT: + AssertFailed(); /** @todo ??? */ + return D3DTOP_DISABLE; + case SVGA3D_TC_DOTPRODUCT3: + return D3DTOP_DOTPRODUCT3; + case SVGA3D_TC_BLENDTEXTUREALPHAPM: + return D3DTOP_BLENDTEXTUREALPHAPM; + case SVGA3D_TC_ADDSIGNED2X: + return D3DTOP_ADDSIGNED2X; + case SVGA3D_TC_ADDSMOOTH: + return D3DTOP_ADDSMOOTH; + case SVGA3D_TC_PREMODULATE: + return D3DTOP_PREMODULATE; + case SVGA3D_TC_MODULATEALPHA_ADDCOLOR: + return D3DTOP_MODULATEALPHA_ADDCOLOR; + case SVGA3D_TC_MODULATECOLOR_ADDALPHA: + return D3DTOP_MODULATECOLOR_ADDALPHA; + case SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR: + return D3DTOP_MODULATEINVALPHA_ADDCOLOR; + case SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA: + return D3DTOP_MODULATEINVCOLOR_ADDALPHA; + case SVGA3D_TC_BUMPENVMAPLUMINANCE: + return D3DTOP_BUMPENVMAPLUMINANCE; + case SVGA3D_TC_MULTIPLYADD: + return D3DTOP_MULTIPLYADD; + case SVGA3D_TC_LERP: + return D3DTOP_LERP; + default: + AssertFailed(); + return D3DTOP_DISABLE; + } +} + +/** + * Convert SVGA texture arg data value to its D3D equivalent + */ +static DWORD vmsvga3dTextureArgData2D3D(uint32_t value) +{ + switch (value) + { + case SVGA3D_TA_CONSTANT: + return D3DTA_CONSTANT; + case SVGA3D_TA_PREVIOUS: + return D3DTA_CURRENT; /* current = previous */ + case SVGA3D_TA_DIFFUSE: + return D3DTA_DIFFUSE; + case SVGA3D_TA_TEXTURE: + return D3DTA_TEXTURE; + case SVGA3D_TA_SPECULAR: + return D3DTA_SPECULAR; + default: + AssertFailed(); + return 0; + } +} + +/** + * Convert SVGA texture transform flag value to its D3D equivalent + */ +static DWORD vmsvga3dTextTransformFlags2D3D(uint32_t value) +{ + switch (value) + { + case SVGA3D_TEX_TRANSFORM_OFF: + return D3DTTFF_DISABLE; + case SVGA3D_TEX_TRANSFORM_S: + return D3DTTFF_COUNT1; /** @todo correct? */ + case SVGA3D_TEX_TRANSFORM_T: + return D3DTTFF_COUNT2; /** @todo correct? */ + case SVGA3D_TEX_TRANSFORM_R: + return D3DTTFF_COUNT3; /** @todo correct? */ + case SVGA3D_TEX_TRANSFORM_Q: + return D3DTTFF_COUNT4; /** @todo correct? */ + case SVGA3D_TEX_PROJECTED: + return D3DTTFF_PROJECTED; + default: + AssertFailed(); + return 0; + } +} +#endif + +static GLenum vmsvga3dTextureAddress2OGL(SVGA3dTextureAddress value) +{ + switch (value) + { + case SVGA3D_TEX_ADDRESS_WRAP: + return GL_REPEAT; + case SVGA3D_TEX_ADDRESS_MIRROR: + return GL_MIRRORED_REPEAT; + case SVGA3D_TEX_ADDRESS_CLAMP: + return GL_CLAMP_TO_EDGE; + case SVGA3D_TEX_ADDRESS_BORDER: + return GL_CLAMP_TO_BORDER; + case SVGA3D_TEX_ADDRESS_MIRRORONCE: + AssertFailed(); + return GL_CLAMP_TO_EDGE_SGIS; /** @todo correct? */ + + case SVGA3D_TEX_ADDRESS_EDGE: + case SVGA3D_TEX_ADDRESS_INVALID: + default: + AssertFailed(); + return GL_REPEAT; /* default */ + } +} + +static GLenum vmsvga3dTextureFilter2OGL(SVGA3dTextureFilter value) +{ + switch (value) + { + case SVGA3D_TEX_FILTER_NONE: + case SVGA3D_TEX_FILTER_LINEAR: + case SVGA3D_TEX_FILTER_ANISOTROPIC: /* Anisotropic filtering is controlled by SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL */ + return GL_LINEAR; + case SVGA3D_TEX_FILTER_NEAREST: + return GL_NEAREST; + case SVGA3D_TEX_FILTER_FLATCUBIC: // Deprecated, not implemented + case SVGA3D_TEX_FILTER_GAUSSIANCUBIC: // Deprecated, not implemented + case SVGA3D_TEX_FILTER_PYRAMIDALQUAD: // Not currently implemented + case SVGA3D_TEX_FILTER_GAUSSIANQUAD: // Not currently implemented + default: + AssertFailed(); + return GL_LINEAR; /* default */ + } +} + +uint32_t vmsvga3dSVGA3dColor2RGBA(SVGA3dColor value) +{ + /* flip the red and blue bytes */ + uint8_t blue = value & 0xff; + uint8_t red = (value >> 16) & 0xff; + return (value & 0xff00ff00) | red | (blue << 16); +} + +static DECLCALLBACK(int) vmsvga3dBackSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState) +{ + GLenum val = ~(GLenum)0; /* Shut up MSC. */ + GLenum currentStage = ~(GLenum)0; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetTextureState %x cTextureState=%d\n", cid, cTextureStates)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Which texture is active for the current stage. Needed to use right OpenGL target when setting parameters. */ + PVMSVGA3DSURFACE pCurrentTextureSurface = NULL; + + for (uint32_t i = 0; i < cTextureStates; ++i) + { + GLenum textureType = ~(GLenum)0; +#if 0 + GLenum samplerType = ~(GLenum)0; +#endif + + LogFunc(("cid=%u stage=%d type=%s (%x) val=%x\n", + cid, pTextureState[i].stage, vmsvga3dTextureStateToString(pTextureState[i].name), pTextureState[i].name, pTextureState[i].value)); + + /* Record the texture state for vm state saving. */ + if ( pTextureState[i].stage < RT_ELEMENTS(pContext->state.aTextureStates) + && (unsigned)pTextureState[i].name < RT_ELEMENTS(pContext->state.aTextureStates[0])) + { + pContext->state.aTextureStates[pTextureState[i].stage][pTextureState[i].name] = pTextureState[i]; + } + + /* Activate the right texture unit for subsequent texture state changes. */ + if (pTextureState[i].stage != currentStage || i == 0) + { + /** @todo Is this the appropriate limit for all kinds of textures? It is the + * size of aSidActiveTextures and for binding/unbinding we cannot exceed it. */ + if (pTextureState[i].stage < RT_ELEMENTS(pContext->state.aTextureStates)) + { + pState->ext.glActiveTexture(GL_TEXTURE0 + pTextureState[i].stage); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + currentStage = pTextureState[i].stage; + } + else + { + AssertMsgFailed(("pTextureState[%d].stage=%#x name=%#x\n", i, pTextureState[i].stage, pTextureState[i].name)); + continue; + } + + if (pContext->aSidActiveTextures[currentStage] != SVGA3D_INVALID_ID) + { + rc = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[currentStage], &pCurrentTextureSurface); + AssertRCReturn(rc, rc); + } + else + pCurrentTextureSurface = NULL; /* Make sure that no stale pointer is used. */ + } + + switch (pTextureState[i].name) + { + case SVGA3D_TS_BUMPENVMAT00: /* float */ + case SVGA3D_TS_BUMPENVMAT01: /* float */ + case SVGA3D_TS_BUMPENVMAT10: /* float */ + case SVGA3D_TS_BUMPENVMAT11: /* float */ + case SVGA3D_TS_BUMPENVLSCALE: /* float */ + case SVGA3D_TS_BUMPENVLOFFSET: /* float */ + Log(("vmsvga3dSetTextureState: bump mapping texture options not supported!!\n")); + break; + + case SVGA3D_TS_COLOROP: /* SVGA3dTextureCombiner */ + case SVGA3D_TS_COLORARG0: /* SVGA3dTextureArgData */ + case SVGA3D_TS_COLORARG1: /* SVGA3dTextureArgData */ + case SVGA3D_TS_COLORARG2: /* SVGA3dTextureArgData */ + case SVGA3D_TS_ALPHAOP: /* SVGA3dTextureCombiner */ + case SVGA3D_TS_ALPHAARG0: /* SVGA3dTextureArgData */ + case SVGA3D_TS_ALPHAARG1: /* SVGA3dTextureArgData */ + case SVGA3D_TS_ALPHAARG2: /* SVGA3dTextureArgData */ + /** @todo not used by MesaGL */ + Log(("vmsvga3dSetTextureState: colorop/alphaop not yet supported!!\n")); + break; +#if 0 + + case SVGA3D_TS_TEXCOORDINDEX: /* uint32_t */ + textureType = D3DTSS_TEXCOORDINDEX; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_TEXTURETRANSFORMFLAGS: /* SVGA3dTexTransformFlags */ + textureType = D3DTSS_TEXTURETRANSFORMFLAGS; + val = vmsvga3dTextTransformFlags2D3D(pTextureState[i].value); + break; +#endif + + case SVGA3D_TS_BIND_TEXTURE: /* SVGA3dSurfaceId */ + { + uint32_t const sid = pTextureState[i].value; + + Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%u replacing sid=%u\n", + currentStage, sid, pContext->aSidActiveTextures[currentStage])); + + /* Only if texture actually changed. */ /// @todo needs testing. + if (pContext->aSidActiveTextures[currentStage] != sid) + { + if (pCurrentTextureSurface) + { + /* Unselect the currently associated texture. */ + glBindTexture(pCurrentTextureSurface->targetGL, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + if (currentStage < 8) + { + /* Necessary for the fixed pipeline. */ + glDisable(pCurrentTextureSurface->targetGL); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + + pCurrentTextureSurface = NULL; + } + + if (sid == SVGA3D_INVALID_ID) + { + Assert(pCurrentTextureSurface == NULL); + } + else + { + PVMSVGA3DSURFACE pSurface; + rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + + Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%u (%d,%d) replacing sid=%u\n", + currentStage, sid, pSurface->paMipmapLevels[0].mipmapSize.width, + pSurface->paMipmapLevels[0].mipmapSize.height, pContext->aSidActiveTextures[currentStage])); + + if (pSurface->oglId.texture == OPENGL_INVALID_ID) + { + Log(("CreateTexture (%d,%d) levels=%d\n", + pSurface->paMipmapLevels[0].mipmapSize.width, pSurface->paMipmapLevels[0].mipmapSize.height, pSurface->cLevels)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pSurface); + AssertRCReturn(rc, rc); + } + + glBindTexture(pSurface->targetGL, pSurface->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + if (currentStage < 8) + { + /* Necessary for the fixed pipeline. */ + glEnable(pSurface->targetGL); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + + /* Remember the currently active texture. */ + pCurrentTextureSurface = pSurface; + + /* Recreate the texture state as glBindTexture resets them all (sigh). */ + for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); iStage++) + { + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); j++) + { + SVGA3dTextureState *pTextureStateIter = &pContext->state.aTextureStates[iStage][j]; + + if ( pTextureStateIter->name != SVGA3D_TS_INVALID + && pTextureStateIter->name != SVGA3D_TS_BIND_TEXTURE) + vmsvga3dBackSetTextureState(pThisCC, pContext->id, 1, pTextureStateIter); + } + } + } + + pContext->aSidActiveTextures[currentStage] = sid; + } + + /* Finished; continue with the next one. */ + continue; + } + + case SVGA3D_TS_ADDRESSW: /* SVGA3dTextureAddress */ + textureType = GL_TEXTURE_WRAP_R; /* R = W */ + val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value); + break; + + case SVGA3D_TS_ADDRESSU: /* SVGA3dTextureAddress */ + textureType = GL_TEXTURE_WRAP_S; /* S = U */ + val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value); + break; + + case SVGA3D_TS_ADDRESSV: /* SVGA3dTextureAddress */ + textureType = GL_TEXTURE_WRAP_T; /* T = V */ + val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value); + break; + + case SVGA3D_TS_MIPFILTER: /* SVGA3dTextureFilter */ + case SVGA3D_TS_MINFILTER: /* SVGA3dTextureFilter */ + { + uint32_t mipFilter = pContext->state.aTextureStates[currentStage][SVGA3D_TS_MIPFILTER].value; + uint32_t minFilter = pContext->state.aTextureStates[currentStage][SVGA3D_TS_MINFILTER].value; + + /* If SVGA3D_TS_MIPFILTER is set to NONE, then use SVGA3D_TS_MIPFILTER, otherwise SVGA3D_TS_MIPFILTER enables mipmap minification. */ + textureType = GL_TEXTURE_MIN_FILTER; + if (mipFilter != SVGA3D_TEX_FILTER_NONE) + { + if (minFilter == SVGA3D_TEX_FILTER_NEAREST) + { + if (mipFilter == SVGA3D_TEX_FILTER_LINEAR) + val = GL_NEAREST_MIPMAP_LINEAR; + else + val = GL_NEAREST_MIPMAP_NEAREST; + } + else + { + if (mipFilter == SVGA3D_TEX_FILTER_LINEAR) + val = GL_LINEAR_MIPMAP_LINEAR; + else + val = GL_LINEAR_MIPMAP_NEAREST; + } + } + else + val = vmsvga3dTextureFilter2OGL((SVGA3dTextureFilter)minFilter); + break; + } + + case SVGA3D_TS_MAGFILTER: /* SVGA3dTextureFilter */ + textureType = GL_TEXTURE_MAG_FILTER; + val = vmsvga3dTextureFilter2OGL((SVGA3dTextureFilter)pTextureState[i].value); + Assert(val == GL_NEAREST || val == GL_LINEAR); + break; + + case SVGA3D_TS_BORDERCOLOR: /* SVGA3dColor */ + { + GLfloat color[4]; /* red, green, blue, alpha */ + vmsvgaColor2GLFloatArray(pTextureState[i].value, &color[0], &color[1], &color[2], &color[3]); + + GLenum targetGL; + if (pCurrentTextureSurface) + targetGL = pCurrentTextureSurface->targetGL; + else + { + /* No texture bound, assume 2D. */ + targetGL = GL_TEXTURE_2D; + } + + glTexParameterfv(targetGL, GL_TEXTURE_BORDER_COLOR, color); /* Identical; default 0.0 identical too */ + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_TS_TEXTURE_LOD_BIAS: /* float */ + { + GLenum targetGL; + if (pCurrentTextureSurface) + targetGL = pCurrentTextureSurface->targetGL; + else + { + /* No texture bound, assume 2D. */ + targetGL = GL_TEXTURE_2D; + } + + glTexParameterf(targetGL, GL_TEXTURE_LOD_BIAS, pTextureState[i].floatValue); /* Identical; default 0.0 identical too */ + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + case SVGA3D_TS_TEXTURE_MIPMAP_LEVEL: /* uint32_t */ + textureType = GL_TEXTURE_BASE_LEVEL; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL: /* uint32_t */ + if (pState->caps.fTextureFilterAnisotropicSupported) + { + textureType = GL_TEXTURE_MAX_ANISOTROPY_EXT; + val = RT_MIN((GLint)pTextureState[i].value, pState->caps.maxTextureAnisotropy); + } /* otherwise ignore. */ + break; + +#if 0 + case SVGA3D_TS_GAMMA: /* float */ + samplerType = D3DSAMP_SRGBTEXTURE; + /* Boolean in D3D */ + if (pTextureState[i].floatValue == 1.0f) + val = FALSE; + else + val = TRUE; + break; +#endif + /* Internal commands, that don't map directly to the SetTextureStageState API. */ + case SVGA3D_TS_TEXCOORDGEN: /* SVGA3dTextureCoordGen */ + AssertFailed(); + break; + + default: + //AssertFailed(); + break; + } + + if (textureType != ~(GLenum)0) + { + GLenum targetGL; + if (pCurrentTextureSurface) + targetGL = pCurrentTextureSurface->targetGL; + else + { + /* No texture bound, assume 2D. */ + targetGL = GL_TEXTURE_2D; + } + + switch (pTextureState[i].name) + { + case SVGA3D_TS_MINFILTER: + case SVGA3D_TS_MAGFILTER: + { + if (pState->caps.fTextureFilterAnisotropicSupported) + { + uint32_t const anisotropyLevel = (SVGA3dTextureFilter)pTextureState[i].value == SVGA3D_TEX_FILTER_ANISOTROPIC + ? RT_MAX(1, pContext->state.aTextureStates[currentStage][SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL].value) + : 1; + glTexParameteri(targetGL, GL_TEXTURE_MAX_ANISOTROPY_EXT, RT_MIN((GLint)anisotropyLevel, pState->caps.maxTextureAnisotropy)); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + } break; + + default: break; + } + + glTexParameteri(targetGL, textureType, val); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("cid=%u face %d\n", cid, face)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + GLenum oglFace; + switch (face) + { + case SVGA3D_FACE_NONE: + case SVGA3D_FACE_FRONT: + oglFace = GL_FRONT; + break; + + case SVGA3D_FACE_BACK: + oglFace = GL_BACK; + break; + + case SVGA3D_FACE_FRONT_BACK: + oglFace = GL_FRONT_AND_BACK; + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + + /* Save for vm state save/restore. */ + pContext->state.aMaterial[face].fValid = true; + pContext->state.aMaterial[face].material = *pMaterial; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_MATERIAL; + + glMaterialfv(oglFace, GL_DIFFUSE, pMaterial->diffuse); + glMaterialfv(oglFace, GL_AMBIENT, pMaterial->ambient); + glMaterialfv(oglFace, GL_SPECULAR, pMaterial->specular); + glMaterialfv(oglFace, GL_EMISSION, pMaterial->emissive); + glMaterialfv(oglFace, GL_SHININESS, &pMaterial->shininess); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + return VINF_SUCCESS; +} + +/** @todo Move into separate library as we are using logic from Wine here. */ +static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("vmsvga3dSetLightData cid=%u index=%d type=%d\n", cid, index, pData->type)); + ASSERT_GUEST_RETURN(index < SVGA3D_MAX_LIGHTS, VERR_INVALID_PARAMETER); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Store for vm state save/restore */ + pContext->state.aLightData[index].fValidData = true; + pContext->state.aLightData[index].data = *pData; + + if ( pData->attenuation0 < 0.0f + || pData->attenuation1 < 0.0f + || pData->attenuation2 < 0.0f) + { + Log(("vmsvga3dSetLightData: invalid negative attenuation values!!\n")); + return VINF_SUCCESS; /* ignore; could crash the GL driver */ + } + + /* Light settings are affected by the model view in OpenGL, the View transform in direct3d */ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix); + + glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, pData->diffuse); + glLightfv(GL_LIGHT0 + index, GL_SPECULAR, pData->specular); + glLightfv(GL_LIGHT0 + index, GL_AMBIENT, pData->ambient); + + float QuadAttenuation; + if (pData->range * pData->range >= FLT_MIN) + QuadAttenuation = 1.4f / (pData->range * pData->range); + else + QuadAttenuation = 0.0f; + + switch (pData->type) + { + case SVGA3D_LIGHTTYPE_POINT: + { + GLfloat position[4]; + + position[0] = pData->position[0]; + position[1] = pData->position[1]; + position[2] = pData->position[2]; + position[3] = 1.0f; + + glLightfv(GL_LIGHT0 + index, GL_POSITION, position); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /* Attenuation - Are these right? guessing... */ + glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, pData->attenuation0); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, pData->attenuation1); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, (QuadAttenuation < pData->attenuation2) ? pData->attenuation2 : QuadAttenuation); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /** @todo range */ + break; + } + + case SVGA3D_LIGHTTYPE_SPOT1: + { + GLfloat exponent; + GLfloat position[4]; + const GLfloat pi = 4.0f * atanf(1.0f); + + position[0] = pData->position[0]; + position[1] = pData->position[1]; + position[2] = pData->position[2]; + position[3] = 1.0f; + + glLightfv(GL_LIGHT0 + index, GL_POSITION, position); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + position[0] = pData->direction[0]; + position[1] = pData->direction[1]; + position[2] = pData->direction[2]; + position[3] = 1.0f; + + glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, position); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /* + * opengl-ish and d3d-ish spot lights use too different models for the + * light "intensity" as a function of the angle towards the main light direction, + * so we only can approximate very roughly. + * however spot lights are rather rarely used in games (if ever used at all). + * furthermore if still used, probably nobody pays attention to such details. + */ + if (pData->falloff == 0) + { + /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the + * falloff resp. exponent parameter as an exponent, so the spot light lighting + * will always be 1.0 for both of them, and we don't have to care for the + * rest of the rather complex calculation + */ + exponent = 0.0f; + } + else + { + float rho = pData->theta + (pData->phi - pData->theta) / (2 * pData->falloff); + if (rho < 0.0001f) + rho = 0.0001f; + exponent = -0.3f/log(cos(rho/2)); + } + if (exponent > 128.0f) + exponent = 128.0f; + + glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, exponent); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, pData->phi * 90.0 / pi); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /* Attenuation - Are these right? guessing... */ + glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, pData->attenuation0); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, pData->attenuation1); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, (QuadAttenuation < pData->attenuation2) ? pData->attenuation2 : QuadAttenuation); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /** @todo range */ + break; + } + + case SVGA3D_LIGHTTYPE_DIRECTIONAL: + { + GLfloat position[4]; + + position[0] = -pData->direction[0]; + position[1] = -pData->direction[1]; + position[2] = -pData->direction[2]; + position[3] = 0.0f; + + glLightfv(GL_LIGHT0 + index, GL_POSITION, position); /* Note gl uses w position of 0 for direction! */ + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, 0.0f); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + break; + } + + case SVGA3D_LIGHTTYPE_SPOT2: + default: + Log(("Unsupported light type!!\n")); + rc = VERR_INVALID_PARAMETER; + break; + } + + /* Restore the modelview matrix */ + glPopMatrix(); + + return rc; +} + +static DECLCALLBACK(int) vmsvga3dBackSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("cid=%u %d -> %d\n", cid, index, enabled)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Store for vm state save/restore */ + if (index < SVGA3D_MAX_LIGHTS) + pContext->state.aLightData[index].fEnabled = !!enabled; + else + AssertFailed(); + + if (enabled) + { + if (index < SVGA3D_MAX_LIGHTS) + { + /* Load the default settings if none have been set yet. */ + if (!pContext->state.aLightData[index].fValidData) + vmsvga3dBackSetLightData(pThisCC, cid, index, (SVGA3dLightData *)&vmsvga3d_default_light); + } + glEnable(GL_LIGHT0 + index); + } + else + glDisable(GL_LIGHT0 + index); + + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetViewPort cid=%u (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Save for vm state save/restore. */ + pContext->state.RectViewPort = *pRect; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VIEWPORT; + + /** @todo y-inversion for partial viewport coordinates? */ + glViewport(pRect->x, pRect->y, pRect->w, pRect->h); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Reset the projection matrix as that relies on the viewport setting. */ + if (pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].fValid == true) + vmsvga3dBackSetTransform(pThisCC, cid, SVGA3D_TRANSFORM_PROJECTION, + pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].matrix); + else + { + float matrix[16]; + + /* identity matrix if no matrix set. */ + memset(matrix, 0, sizeof(matrix)); + matrix[0] = 1.0; + matrix[5] = 1.0; + matrix[10] = 1.0; + matrix[15] = 1.0; + vmsvga3dBackSetTransform(pThisCC, cid, SVGA3D_TRANSFORM_PROJECTION, matrix); + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + double oglPlane[4]; + + Log(("vmsvga3dSetClipPlane cid=%u %d (%d,%d)(%d,%d)\n", cid, index, (unsigned)(plane[0] * 100.0), (unsigned)(plane[1] * 100.0), (unsigned)(plane[2] * 100.0), (unsigned)(plane[3] * 100.0))); + AssertReturn(index < SVGA3D_NUM_CLIPPLANES, VERR_INVALID_PARAMETER); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Store for vm state save/restore. */ + pContext->state.aClipPlane[index].fValid = true; + memcpy(pContext->state.aClipPlane[index].plane, plane, sizeof(pContext->state.aClipPlane[index].plane)); + + /** @todo clip plane affected by model view in OpenGL & view in D3D + vertex shader -> not transformed (see Wine; state.c clipplane) */ + oglPlane[0] = (double)plane[0]; + oglPlane[1] = (double)plane[1]; + oglPlane[2] = (double)plane[2]; + oglPlane[3] = (double)plane[3]; + + glClipPlane(GL_CLIP_PLANE0 + index, oglPlane); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetScissorRect cid=%u (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Store for vm state save/restore. */ + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_SCISSORRECT; + pContext->state.RectScissor = *pRect; + + glScissor(pRect->x, pRect->y, pRect->w, pRect->h); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + return VINF_SUCCESS; +} + +static void vmsvgaColor2GLFloatArray(uint32_t color, GLfloat *pRed, GLfloat *pGreen, GLfloat *pBlue, GLfloat *pAlpha) +{ + /* Convert byte color components to float (0-1.0) */ + *pAlpha = (GLfloat)(color >> 24) / 255.0; + *pRed = (GLfloat)((color >> 16) & 0xff) / 255.0; + *pGreen = (GLfloat)((color >> 8) & 0xff) / 255.0; + *pBlue = (GLfloat)(color & 0xff) / 255.0; +} + +static DECLCALLBACK(int) vmsvga3dBackCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil, + uint32_t cRects, SVGA3dRect *pRect) +{ + GLbitfield mask = 0; + GLbitfield restoreMask = 0; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + GLboolean fDepthWriteEnabled = GL_FALSE; + GLboolean afColorWriteEnabled[4] = { GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE }; + + Log(("vmsvga3dCommandClear cid=%u clearFlag=%x color=%x depth=%d stencil=%x cRects=%d\n", cid, clearFlag, color, (uint32_t)(depth * 100.0), stencil, cRects)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + if (clearFlag & SVGA3D_CLEAR_COLOR) + { + GLfloat red, green, blue, alpha; + vmsvgaColor2GLFloatArray(color, &red, &green, &blue, &alpha); + + /* Set the color clear value. */ + glClearColor(red, green, blue, alpha); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + mask |= GL_COLOR_BUFFER_BIT; + + /* glClear will not clear the color buffer if writing is disabled. */ + glGetBooleanv(GL_COLOR_WRITEMASK, afColorWriteEnabled); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + if ( afColorWriteEnabled[0] == GL_FALSE + || afColorWriteEnabled[1] == GL_FALSE + || afColorWriteEnabled[2] == GL_FALSE + || afColorWriteEnabled[3] == GL_FALSE) + { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + restoreMask |= GL_COLOR_BUFFER_BIT; + } + + } + + if (clearFlag & SVGA3D_CLEAR_STENCIL) + { + /** @todo possibly the same problem as with glDepthMask */ + glClearStencil(stencil); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + mask |= GL_STENCIL_BUFFER_BIT; + } + + if (clearFlag & SVGA3D_CLEAR_DEPTH) + { + glClearDepth((GLdouble)depth); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + mask |= GL_DEPTH_BUFFER_BIT; + + /* glClear will not clear the depth buffer if writing is disabled. */ + glGetBooleanv(GL_DEPTH_WRITEMASK, &fDepthWriteEnabled); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + if (fDepthWriteEnabled == GL_FALSE) + { + glDepthMask(GL_TRUE); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + restoreMask |= GL_DEPTH_BUFFER_BIT; + } + } + + /* Save the current scissor test bit and scissor box. */ + glPushAttrib(GL_SCISSOR_BIT); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + if (cRects) + { + glEnable(GL_SCISSOR_TEST); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + for (uint32_t i = 0; i < cRects; ++i) + { + LogFunc(("rect [%d] %d,%d %dx%d)\n", i, pRect[i].x, pRect[i].y, pRect[i].w, pRect[i].h)); + glScissor(pRect[i].x, pRect[i].y, pRect[i].w, pRect[i].h); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glClear(mask); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + } + else + { + glDisable(GL_SCISSOR_TEST); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glClear(mask); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + + /* Restore the old scissor test bit and box */ + glPopAttrib(); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /* Restore the write states. */ + if (restoreMask & GL_COLOR_BUFFER_BIT) + { + glColorMask(afColorWriteEnabled[0], + afColorWriteEnabled[1], + afColorWriteEnabled[2], + afColorWriteEnabled[3]); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + + if (restoreMask & GL_DEPTH_BUFFER_BIT) + { + glDepthMask(fDepthWriteEnabled); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + + return VINF_SUCCESS; +} + +/* Convert VMWare vertex declaration to its OpenGL equivalent. */ +int vmsvga3dVertexDecl2OGL(SVGA3dVertexArrayIdentity &identity, GLint &size, GLenum &type, GLboolean &normalized, uint32_t &cbAttrib) +{ + normalized = GL_FALSE; + switch (identity.type) + { + case SVGA3D_DECLTYPE_FLOAT1: + size = 1; + type = GL_FLOAT; + cbAttrib = sizeof(float); + break; + case SVGA3D_DECLTYPE_FLOAT2: + size = 2; + type = GL_FLOAT; + cbAttrib = 2 * sizeof(float); + break; + case SVGA3D_DECLTYPE_FLOAT3: + size = 3; + type = GL_FLOAT; + cbAttrib = 3 * sizeof(float); + break; + case SVGA3D_DECLTYPE_FLOAT4: + size = 4; + type = GL_FLOAT; + cbAttrib = 4 * sizeof(float); + break; + + case SVGA3D_DECLTYPE_D3DCOLOR: + size = GL_BGRA; /* @note requires GL_ARB_vertex_array_bgra */ + type = GL_UNSIGNED_BYTE; + normalized = GL_TRUE; /* glVertexAttribPointer fails otherwise */ + cbAttrib = sizeof(uint32_t); + break; + + case SVGA3D_DECLTYPE_UBYTE4N: + normalized = GL_TRUE; + RT_FALL_THRU(); + case SVGA3D_DECLTYPE_UBYTE4: + size = 4; + type = GL_UNSIGNED_BYTE; + cbAttrib = sizeof(uint32_t); + break; + + case SVGA3D_DECLTYPE_SHORT2N: + normalized = GL_TRUE; + RT_FALL_THRU(); + case SVGA3D_DECLTYPE_SHORT2: + size = 2; + type = GL_SHORT; + cbAttrib = 2 * sizeof(uint16_t); + break; + + case SVGA3D_DECLTYPE_SHORT4N: + normalized = GL_TRUE; + RT_FALL_THRU(); + case SVGA3D_DECLTYPE_SHORT4: + size = 4; + type = GL_SHORT; + cbAttrib = 4 * sizeof(uint16_t); + break; + + case SVGA3D_DECLTYPE_USHORT4N: + normalized = GL_TRUE; + size = 4; + type = GL_UNSIGNED_SHORT; + cbAttrib = 4 * sizeof(uint16_t); + break; + + case SVGA3D_DECLTYPE_USHORT2N: + normalized = GL_TRUE; + size = 2; + type = GL_UNSIGNED_SHORT; + cbAttrib = 2 * sizeof(uint16_t); + break; + + case SVGA3D_DECLTYPE_UDEC3: + size = 3; + type = GL_UNSIGNED_INT_2_10_10_10_REV; /** @todo correct? */ + cbAttrib = sizeof(uint32_t); + break; + + case SVGA3D_DECLTYPE_DEC3N: + normalized = true; + size = 3; + type = GL_INT_2_10_10_10_REV; /** @todo correct? */ + cbAttrib = sizeof(uint32_t); + break; + + case SVGA3D_DECLTYPE_FLOAT16_2: + size = 2; + type = GL_HALF_FLOAT; + cbAttrib = 2 * sizeof(uint16_t); + break; + case SVGA3D_DECLTYPE_FLOAT16_4: + size = 4; + type = GL_HALF_FLOAT; + cbAttrib = 4 * sizeof(uint16_t); + break; + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + + //pVertexElement->Method = identity.method; + //pVertexElement->Usage = identity.usage; + + return VINF_SUCCESS; +} + +static float vmsvga3dFloat16To32(uint16_t f16) +{ + /* From Wiki */ +#ifndef INFINITY + static uint32_t const sBitsINFINITY = UINT32_C(0x7f800000); + #define INFINITY (*(float const *)&sBitsINFINITY) +#endif +#ifndef NAN + static uint32_t const sBitsNAN = UINT32_C(0x7fc00000); + #define NAN (*(float const *)&sBitsNAN) +#endif + + uint16_t const s = (f16 >> UINT16_C(15)) & UINT16_C(0x1); + uint16_t const e = (f16 >> UINT16_C(10)) & UINT16_C(0x1f); + uint16_t const m = (f16 ) & UINT16_C(0x3ff); + + float result = s ? 1.0f : -1.0f; + if (e == 0) + { + if (m == 0) + result *= 0.0f; /* zero, -0 */ + else + result *= (float)m / 1024.0f / 16384.0f; /* subnormal numbers: sign * 2^-14 * 0.m */ + } + else if (e == 0x1f) + { + if (m == 0) + result *= INFINITY; /* +-infinity */ + else + result = NAN; /* NAN */ + } + else + { + result *= powf(2.0f, (float)e - 15.0f) * (1.0f + (float)m / 1024.0f); /* sign * 2^(e-15) * 1.m */ + } + + return result; +} + +/* Set a vertex attribute according to VMSVGA vertex declaration. */ +static int vmsvga3dSetVertexAttrib(PVMSVGA3DSTATE pState, GLuint index, SVGA3dVertexArrayIdentity const *pIdentity, GLvoid const *pv) +{ + switch (pIdentity->type) + { + case SVGA3D_DECLTYPE_FLOAT1: + { + /* "One-component float expanded to (float, 0, 0, 1)." */ + GLfloat const *p = (GLfloat *)pv; + GLfloat const v[4] = { p[0], 0.0f, 0.0f, 1.0f }; + pState->ext.glVertexAttrib4fv(index, v); + break; + } + case SVGA3D_DECLTYPE_FLOAT2: + { + /* "Two-component float expanded to (float, float, 0, 1)." */ + GLfloat const *p = (GLfloat *)pv; + GLfloat const v[4] = { p[0], p[1], 0.0f, 1.0f }; + pState->ext.glVertexAttrib4fv(index, v); + break; + } + case SVGA3D_DECLTYPE_FLOAT3: + { + /* "Three-component float expanded to (float, float, float, 1)." */ + GLfloat const *p = (GLfloat *)pv; + GLfloat const v[4] = { p[0], p[1], p[2], 1.0f }; + pState->ext.glVertexAttrib4fv(index, v); + break; + } + case SVGA3D_DECLTYPE_FLOAT4: + pState->ext.glVertexAttrib4fv(index, (GLfloat const *)pv); + break; + case SVGA3D_DECLTYPE_D3DCOLOR: + /** @todo Need to swap bytes? */ + pState->ext.glVertexAttrib4Nubv(index, (GLubyte const *)pv); + break; + case SVGA3D_DECLTYPE_UBYTE4: + pState->ext.glVertexAttrib4ubv(index, (GLubyte const *)pv); + break; + case SVGA3D_DECLTYPE_SHORT2: + { + /* "Two-component, signed short expanded to (value, value, 0, 1)." */ + GLshort const *p = (GLshort const *)pv; + GLshort const v[4] = { p[0], p[1], 0, 1 }; + pState->ext.glVertexAttrib4sv(index, v); + break; + } + case SVGA3D_DECLTYPE_SHORT4: + pState->ext.glVertexAttrib4sv(index, (GLshort const *)pv); + break; + case SVGA3D_DECLTYPE_UBYTE4N: + pState->ext.glVertexAttrib4Nubv(index, (GLubyte const *)pv); + break; + case SVGA3D_DECLTYPE_SHORT2N: + { + /* "Normalized, two-component, signed short, expanded to (first short/32767.0, second short/32767.0, 0, 1)." */ + GLshort const *p = (GLshort const *)pv; + GLshort const v[4] = { p[0], p[1], 0, 1 }; + pState->ext.glVertexAttrib4Nsv(index, v); + break; + } + case SVGA3D_DECLTYPE_SHORT4N: + pState->ext.glVertexAttrib4Nsv(index, (GLshort const *)pv); + break; + case SVGA3D_DECLTYPE_USHORT2N: + { + GLushort const *p = (GLushort const *)pv; + GLushort const v[4] = { p[0], p[1], 0, 1 }; + pState->ext.glVertexAttrib4Nusv(index, v); + break; + } + case SVGA3D_DECLTYPE_USHORT4N: + pState->ext.glVertexAttrib4Nusv(index, (GLushort const *)pv); + break; + case SVGA3D_DECLTYPE_UDEC3: + { + /** @todo Test */ + /* "Three-component, unsigned, 10 10 10 format expanded to (value, value, value, 1)." */ + uint32_t const u32 = *(uint32_t *)pv; + GLfloat const v[4] = { (float)(u32 & 0x3ff), (float)((u32 >> 10) & 0x3ff), (float)((u32 >> 20) & 0x3ff), 1.0f }; + pState->ext.glVertexAttrib4fv(index, v); + break; + } + case SVGA3D_DECLTYPE_DEC3N: + { + /** @todo Test */ + /* "Three-component, signed, 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)." */ + uint32_t const u32 = *(uint32_t *)pv; + GLfloat const v[4] = { (float)(u32 & 0x3ff) / 511.0f, (float)((u32 >> 10) & 0x3ff) / 511.0f, (float)((u32 >> 20) & 0x3ff) / 511.0f, 1.0f }; + pState->ext.glVertexAttrib4fv(index, v); + break; + } + case SVGA3D_DECLTYPE_FLOAT16_2: + { + /** @todo Test */ + /* "Two-component, 16-bit, floating point expanded to (value, value, 0, 1)." */ + uint16_t const *p = (uint16_t *)pv; + GLfloat const v[4] = { vmsvga3dFloat16To32(p[0]), vmsvga3dFloat16To32(p[1]), 0.0f, 1.0f }; + pState->ext.glVertexAttrib4fv(index, v); + break; + } + case SVGA3D_DECLTYPE_FLOAT16_4: + { + /** @todo Test */ + uint16_t const *p = (uint16_t *)pv; + GLfloat const v[4] = { vmsvga3dFloat16To32(p[0]), vmsvga3dFloat16To32(p[1]), + vmsvga3dFloat16To32(p[2]), vmsvga3dFloat16To32(p[3]) }; + pState->ext.glVertexAttrib4fv(index, v); + break; + } + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + + return VINF_SUCCESS; +} + +/* Convert VMWare primitive type to its OpenGL equivalent. */ +/* Calculate the vertex count based on the primitive type and nr of primitives. */ +int vmsvga3dPrimitiveType2OGL(SVGA3dPrimitiveType PrimitiveType, GLenum *pMode, uint32_t cPrimitiveCount, uint32_t *pcVertices) +{ + switch (PrimitiveType) + { + case SVGA3D_PRIMITIVE_TRIANGLELIST: + *pMode = GL_TRIANGLES; + *pcVertices = cPrimitiveCount * 3; + break; + case SVGA3D_PRIMITIVE_POINTLIST: + *pMode = GL_POINTS; + *pcVertices = cPrimitiveCount; + break; + case SVGA3D_PRIMITIVE_LINELIST: + *pMode = GL_LINES; + *pcVertices = cPrimitiveCount * 2; + break; + case SVGA3D_PRIMITIVE_LINESTRIP: + *pMode = GL_LINE_STRIP; + *pcVertices = cPrimitiveCount + 1; + break; + case SVGA3D_PRIMITIVE_TRIANGLESTRIP: + *pMode = GL_TRIANGLE_STRIP; + *pcVertices = cPrimitiveCount + 2; + break; + case SVGA3D_PRIMITIVE_TRIANGLEFAN: + *pMode = GL_TRIANGLE_FAN; + *pcVertices = cPrimitiveCount + 2; + break; + default: + return VERR_INVALID_PARAMETER; + } + return VINF_SUCCESS; +} + +static int vmsvga3dResetTransformMatrices(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + int rc; + + /* Reset the view matrix (also takes the world matrix into account). */ + if (pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].fValid == true) + rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_VIEW, + pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix); + else + { + float matrix[16]; + + /* identity matrix if no matrix set. */ + memset(matrix, 0, sizeof(matrix)); + matrix[0] = 1.0; + matrix[5] = 1.0; + matrix[10] = 1.0; + matrix[15] = 1.0; + rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_VIEW, matrix); + } + + /* Reset the projection matrix. */ + if (pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].fValid == true) + { + rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_PROJECTION, pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].matrix); + } + else + { + float matrix[16]; + + /* identity matrix if no matrix set. */ + memset(matrix, 0, sizeof(matrix)); + matrix[0] = 1.0; + matrix[5] = 1.0; + matrix[10] = 1.0; + matrix[15] = 1.0; + rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_PROJECTION, matrix); + } + AssertRC(rc); + return rc; +} + +static int vmsvga3dDrawPrimitivesProcessVertexDecls(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, + uint32_t iVertexDeclBase, uint32_t numVertexDecls, + SVGA3dVertexDecl *pVertexDecl, + SVGA3dVertexDivisor const *paVertexDivisors) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + unsigned const sidVertex = pVertexDecl[0].array.surfaceId; + + PVMSVGA3DSURFACE pVertexSurface; + int rc = vmsvga3dSurfaceFromSid(pState, sidVertex, &pVertexSurface); + AssertRCReturn(rc, rc); + + Log(("vmsvga3dDrawPrimitives: vertex surface sid=%u\n", sidVertex)); + + /* Create and/or bind the vertex buffer. */ + if (pVertexSurface->oglId.buffer == OPENGL_INVALID_ID) + { + Log(("vmsvga3dDrawPrimitives: create vertex buffer fDirty=%d size=%x bytes\n", pVertexSurface->fDirty, pVertexSurface->paMipmapLevels[0].cbSurface)); + PVMSVGA3DCONTEXT pSavedCtx = pContext; + pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + pState->ext.glGenBuffers(1, &pVertexSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + pVertexSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_BUFFER; + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pVertexSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + Assert(pVertexSurface->fDirty); + /** @todo rethink usage dynamic/static */ + pState->ext.glBufferData(GL_ARRAY_BUFFER, pVertexSurface->paMipmapLevels[0].cbSurface, pVertexSurface->paMipmapLevels[0].pSurfaceData, GL_DYNAMIC_DRAW); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pVertexSurface->paMipmapLevels[0].fDirty = false; + pVertexSurface->fDirty = false; + + pVertexSurface->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER; + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, OPENGL_INVALID_ID); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pContext = pSavedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + } + + Assert(pVertexSurface->fDirty == false); + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pVertexSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Setup the vertex declarations. */ + for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++) + { + GLint size; + GLenum type; + GLboolean normalized; + uint32_t cbAttrib; + GLuint index = iVertexDeclBase + iVertex; + + Log(("vmsvga3dDrawPrimitives: array index %d type=%s (%d) method=%s (%d) usage=%s (%d) usageIndex=%d stride=%d offset=%d\n", index, vmsvgaDeclType2String(pVertexDecl[iVertex].identity.type), pVertexDecl[iVertex].identity.type, vmsvgaDeclMethod2String(pVertexDecl[iVertex].identity.method), pVertexDecl[iVertex].identity.method, vmsvgaDeclUsage2String(pVertexDecl[iVertex].identity.usage), pVertexDecl[iVertex].identity.usage, pVertexDecl[iVertex].identity.usageIndex, pVertexDecl[iVertex].array.stride, pVertexDecl[iVertex].array.offset)); + + rc = vmsvga3dVertexDecl2OGL(pVertexDecl[iVertex].identity, size, type, normalized, cbAttrib); + AssertRCReturn(rc, rc); + + ASSERT_GUEST_RETURN( pVertexSurface->paMipmapLevels[0].cbSurface >= pVertexDecl[iVertex].array.offset + && pVertexSurface->paMipmapLevels[0].cbSurface - pVertexDecl[iVertex].array.offset >= cbAttrib, + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + if (pContext->state.shidVertex != SVGA_ID_INVALID) + { + /* Use numbered vertex arrays (or attributes) when shaders are active. */ + if (pVertexDecl[iVertex].array.stride) + { + pState->ext.glEnableVertexAttribArray(index); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + pState->ext.glVertexAttribPointer(index, size, type, normalized, pVertexDecl[iVertex].array.stride, + (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + GLuint divisor = paVertexDivisors && paVertexDivisors[index].instanceData ? 1 : 0; + pState->ext.glVertexAttribDivisor(index, divisor); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /** @todo case SVGA3D_DECLUSAGE_COLOR: color component order not identical!! test GL_BGRA!! */ + } + else + { + /* + * D3D and OpenGL have a different meaning of value zero for the vertex array stride: + * - D3D (VMSVGA): "use a zero stride to tell the runtime not to increment the vertex buffer offset." + * - OpenGL: "If stride is 0, the generic vertex attributes are understood to be tightly packed in the array." + * VMSVGA uses the D3D semantics. + * + * Use glVertexAttrib in order to tell OpenGL to reuse the zero stride attributes for each vertex. + */ + pState->ext.glDisableVertexAttribArray(index); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + const GLvoid *v = (uint8_t *)pVertexSurface->paMipmapLevels[0].pSurfaceData + pVertexDecl[iVertex].array.offset; + vmsvga3dSetVertexAttrib(pState, index, &pVertexDecl[iVertex].identity, v); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + } + } + else + { + if (pVertexDecl[iVertex].array.stride == 0) + { + /* Zero stride means that the attribute pointer must not be increased. + * See comment about stride in vmsvga3dDrawPrimitives. + */ + LogRelMax(8, ("VMSVGA: Warning: zero stride array in fixed function pipeline\n")); + AssertFailed(); + } + + /* Use the predefined selection of vertex streams for the fixed pipeline. */ + switch (pVertexDecl[iVertex].identity.usage) + { + case SVGA3D_DECLUSAGE_POSITIONT: + case SVGA3D_DECLUSAGE_POSITION: + { + glEnableClientState(GL_VERTEX_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glVertexPointer(size, type, pVertexDecl[iVertex].array.stride, + (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + case SVGA3D_DECLUSAGE_BLENDWEIGHT: + AssertFailed(); + break; + case SVGA3D_DECLUSAGE_BLENDINDICES: + AssertFailed(); + break; + case SVGA3D_DECLUSAGE_NORMAL: + glEnableClientState(GL_NORMAL_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glNormalPointer(type, pVertexDecl[iVertex].array.stride, + (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_PSIZE: + AssertFailed(); + break; + case SVGA3D_DECLUSAGE_TEXCOORD: + /* Specify the affected texture unit. */ +#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x103 + glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex); +#else + pState->ext.glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex); +#endif + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glTexCoordPointer(size, type, pVertexDecl[iVertex].array.stride, + (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_TANGENT: + AssertFailed(); + break; + case SVGA3D_DECLUSAGE_BINORMAL: + AssertFailed(); + break; + case SVGA3D_DECLUSAGE_TESSFACTOR: + AssertFailed(); + break; + case SVGA3D_DECLUSAGE_COLOR: /** @todo color component order not identical!! test GL_BGRA!! */ + glEnableClientState(GL_COLOR_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + glColorPointer(size, type, pVertexDecl[iVertex].array.stride, + (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_FOG: + glEnableClientState(GL_FOG_COORD_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + pState->ext.glFogCoordPointer(type, pVertexDecl[iVertex].array.stride, + (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_DEPTH: + AssertFailed(); + break; + case SVGA3D_DECLUSAGE_SAMPLE: + AssertFailed(); + break; + case SVGA3D_DECLUSAGE_MAX: AssertFailed(); break; /* shut up gcc */ + } + } + +#ifdef LOG_ENABLED + if (pVertexDecl[iVertex].array.stride == 0) + Log(("vmsvga3dDrawPrimitives: stride == 0! Can be valid\n")); +#endif + } + + return VINF_SUCCESS; +} + +static int vmsvga3dDrawPrimitivesCleanupVertexDecls(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t iVertexDeclBase, + uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + + /* Clean up the vertex declarations. */ + for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++) + { + if (pVertexDecl[iVertex].identity.usage == SVGA3D_DECLUSAGE_POSITIONT) + { + /* Reset the transformation matrices in case of a switch back from pretransformed mode. */ + Log(("vmsvga3dDrawPrimitivesCleanupVertexDecls: reset world and projection matrices after transformation reset (pre-transformed -> transformed)\n")); + vmsvga3dResetTransformMatrices(pThisCC, pContext); + } + + if (pContext->state.shidVertex != SVGA_ID_INVALID) + { + /* Use numbered vertex arrays when shaders are active. */ + pState->ext.glVertexAttribDivisor(iVertexDeclBase + iVertex, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + pState->ext.glDisableVertexAttribArray(iVertexDeclBase + iVertex); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + else + { + /* Use the predefined selection of vertex streams for the fixed pipeline. */ + switch (pVertexDecl[iVertex].identity.usage) + { + case SVGA3D_DECLUSAGE_POSITION: + case SVGA3D_DECLUSAGE_POSITIONT: + glDisableClientState(GL_VERTEX_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_BLENDWEIGHT: + break; + case SVGA3D_DECLUSAGE_BLENDINDICES: + break; + case SVGA3D_DECLUSAGE_NORMAL: + glDisableClientState(GL_NORMAL_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_PSIZE: + break; + case SVGA3D_DECLUSAGE_TEXCOORD: + /* Specify the affected texture unit. */ +#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x103 + glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex); +#else + pState->ext.glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex); +#endif + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_TANGENT: + break; + case SVGA3D_DECLUSAGE_BINORMAL: + break; + case SVGA3D_DECLUSAGE_TESSFACTOR: + break; + case SVGA3D_DECLUSAGE_COLOR: /** @todo color component order not identical!! */ + glDisableClientState(GL_COLOR_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_FOG: + glDisableClientState(GL_FOG_COORD_ARRAY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + case SVGA3D_DECLUSAGE_DEPTH: + break; + case SVGA3D_DECLUSAGE_SAMPLE: + break; + case SVGA3D_DECLUSAGE_MAX: AssertFailed(); break; /* shut up gcc */ + } + } + } + /* Unbind the vertex buffer after usage. */ + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, + uint32_t numRanges, SVGA3dPrimitiveRange *pRange, uint32_t cVertexDivisor, + SVGA3dVertexDivisor *pVertexDivisor) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INTERNAL_ERROR); + uint32_t iCurrentVertex; + + Log(("vmsvga3dDrawPrimitives cid=%u numVertexDecls=%d numRanges=%d, cVertexDivisor=%d\n", cid, numVertexDecls, numRanges, cVertexDivisor)); + + /* Caller already check these, but it cannot hurt to check again... */ + AssertReturn(numVertexDecls && numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS, VERR_INVALID_PARAMETER); + AssertReturn(numRanges && numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES, VERR_INVALID_PARAMETER); + AssertReturn(!cVertexDivisor || cVertexDivisor == numVertexDecls, VERR_INVALID_PARAMETER); + + if (!cVertexDivisor) + pVertexDivisor = NULL; /* Be sure. */ + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* Check for pretransformed vertex declarations. */ + for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++) + { + switch (pVertexDecl[iVertex].identity.usage) + { + case SVGA3D_DECLUSAGE_POSITIONT: + Log(("ShaderSetPositionTransformed: (%d,%d)\n", pContext->state.RectViewPort.w, pContext->state.RectViewPort.h)); + RT_FALL_THRU(); + case SVGA3D_DECLUSAGE_POSITION: + ShaderSetPositionTransformed(pContext->pShaderContext, pContext->state.RectViewPort.w, + pContext->state.RectViewPort.h, + pVertexDecl[iVertex].identity.usage == SVGA3D_DECLUSAGE_POSITIONT); + break; + default: /* Shut up MSC. */ break; + } + } + + /* Flush any shader changes; after (!) checking the vertex declarations to deal with pre-transformed vertices. */ + if (pContext->pShaderContext) + { + uint32_t rtHeight = 0; + + if (pContext->state.aRenderTargets[SVGA3D_RT_COLOR0] != SVGA_ID_INVALID) + { + PVMSVGA3DSURFACE pRenderTarget; + rc = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pRenderTarget); + AssertRCReturn(rc, rc); + + rtHeight = pRenderTarget->paMipmapLevels[0].mipmapSize.height; + } + + ShaderUpdateState(pContext->pShaderContext, rtHeight); + } + + /* Try to figure out if instancing is used. + * Support simple instancing case with one set of indexed data and one set per-instance data. + */ + uint32_t cInstances = 0; + for (uint32_t iVertexDivisor = 0; iVertexDivisor < cVertexDivisor; ++iVertexDivisor) + { + if (pVertexDivisor[iVertexDivisor].indexedData) + { + if (cInstances == 0) + cInstances = pVertexDivisor[iVertexDivisor].count; + else + Assert(cInstances == pVertexDivisor[iVertexDivisor].count); + } + else if (pVertexDivisor[iVertexDivisor].instanceData) + { + Assert(pVertexDivisor[iVertexDivisor].count == 1); + } + } + + /* Process all vertex declarations. Each vertex buffer is represented by one stream. */ + iCurrentVertex = 0; + while (iCurrentVertex < numVertexDecls) + { + uint32_t sidVertex = SVGA_ID_INVALID; + uint32_t iVertex; + + for (iVertex = iCurrentVertex; iVertex < numVertexDecls; iVertex++) + { + if ( sidVertex != SVGA_ID_INVALID + && pVertexDecl[iVertex].array.surfaceId != sidVertex + ) + break; + sidVertex = pVertexDecl[iVertex].array.surfaceId; + } + + rc = vmsvga3dDrawPrimitivesProcessVertexDecls(pThisCC, pContext, iCurrentVertex, iVertex - iCurrentVertex, + &pVertexDecl[iCurrentVertex], pVertexDivisor); + AssertRCReturn(rc, rc); + + iCurrentVertex = iVertex; + } + + /* Now draw the primitives. */ + for (unsigned iPrimitive = 0; iPrimitive < numRanges; iPrimitive++) + { + GLenum modeDraw; + unsigned const sidIndex = pRange[iPrimitive].indexArray.surfaceId; + PVMSVGA3DSURFACE pIndexSurface = NULL; + unsigned cVertices; + + Log(("Primitive %d: type %s\n", iPrimitive, vmsvga3dPrimitiveType2String(pRange[iPrimitive].primType))); + rc = vmsvga3dPrimitiveType2OGL(pRange[iPrimitive].primType, &modeDraw, pRange[iPrimitive].primitiveCount, &cVertices); + if (RT_FAILURE(rc)) + { + AssertRC(rc); + goto internal_error; + } + + if (sidIndex != SVGA3D_INVALID_ID) + { + AssertMsg(pRange[iPrimitive].indexWidth == sizeof(uint32_t) || pRange[iPrimitive].indexWidth == sizeof(uint16_t), ("Unsupported primitive width %d\n", pRange[iPrimitive].indexWidth)); + + rc = vmsvga3dSurfaceFromSid(pState, sidIndex, &pIndexSurface); + if (RT_FAILURE(rc)) + { + AssertRC(rc); + goto internal_error; + } + + Log(("vmsvga3dDrawPrimitives: index surface sid=%u\n", sidIndex)); + + if (pIndexSurface->oglId.buffer == OPENGL_INVALID_ID) + { + Log(("vmsvga3dDrawPrimitives: create index buffer fDirty=%d size=%x bytes\n", pIndexSurface->fDirty, pIndexSurface->paMipmapLevels[0].cbSurface)); + pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + pState->ext.glGenBuffers(1, &pIndexSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + pIndexSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_BUFFER; + + pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + Assert(pIndexSurface->fDirty); + + /** @todo rethink usage dynamic/static */ + pState->ext.glBufferData(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->paMipmapLevels[0].cbSurface, pIndexSurface->paMipmapLevels[0].pSurfaceData, GL_DYNAMIC_DRAW); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pIndexSurface->paMipmapLevels[0].fDirty = false; + pIndexSurface->fDirty = false; + + pIndexSurface->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER; + + pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OPENGL_INVALID_ID); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pContext = pState->papContexts[cid]; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + } + Assert(pIndexSurface->fDirty == false); + + pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + + if (!pIndexSurface) + { + /* Render without an index buffer */ + Log(("DrawPrimitive %d cPrimitives=%d cVertices=%d index index bias=%d cInstances=%d\n", modeDraw, pRange[iPrimitive].primitiveCount, cVertices, pRange[iPrimitive].indexBias, cInstances)); + if (cInstances == 0) + { + glDrawArrays(modeDraw, pRange[iPrimitive].indexBias, cVertices); + } + else + { + pState->ext.glDrawArraysInstanced(modeDraw, pRange[iPrimitive].indexBias, cVertices, cInstances); + } + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + else + { + Assert(pRange[iPrimitive].indexWidth == pRange[iPrimitive].indexArray.stride); + + GLenum indexType; + switch (pRange[iPrimitive].indexWidth) + { + case 1: indexType = GL_UNSIGNED_BYTE; break; + case 2: indexType = GL_UNSIGNED_SHORT; break; + default: AssertMsgFailed(("indexWidth %d\n", pRange[iPrimitive].indexWidth)); + RT_FALL_THROUGH(); + case 4: indexType = GL_UNSIGNED_INT; break; + } + + Log(("DrawIndexedPrimitive %d cPrimitives=%d cVertices=%d hint.first=%d hint.last=%d index offset=%d primitivecount=%d index width=%d index bias=%d cInstances=%d\n", modeDraw, pRange[iPrimitive].primitiveCount, cVertices, pVertexDecl[0].rangeHint.first, pVertexDecl[0].rangeHint.last, pRange[iPrimitive].indexArray.offset, pRange[iPrimitive].primitiveCount, pRange[iPrimitive].indexWidth, pRange[iPrimitive].indexBias, cInstances)); + if (cInstances == 0) + { + /* Render with an index buffer */ + if (pRange[iPrimitive].indexBias == 0) + glDrawElements(modeDraw, + cVertices, + indexType, + (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset); /* byte offset in indices buffer */ + else + pState->ext.glDrawElementsBaseVertex(modeDraw, + cVertices, + indexType, + (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */ + pRange[iPrimitive].indexBias); /* basevertex */ + } + else + { + /* Render with an index buffer */ + if (pRange[iPrimitive].indexBias == 0) + pState->ext.glDrawElementsInstanced(modeDraw, + cVertices, + indexType, + (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */ + cInstances); + else + pState->ext.glDrawElementsInstancedBaseVertex(modeDraw, + cVertices, + indexType, + (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */ + cInstances, + pRange[iPrimitive].indexBias); /* basevertex */ + } + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + /* Unbind the index buffer after usage. */ + pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + } + } + +internal_error: + + /* Deactivate the vertex declarations. */ + iCurrentVertex = 0; + while (iCurrentVertex < numVertexDecls) + { + uint32_t sidVertex = SVGA_ID_INVALID; + uint32_t iVertex; + + for (iVertex = iCurrentVertex; iVertex < numVertexDecls; iVertex++) + { + if ( sidVertex != SVGA_ID_INVALID + && pVertexDecl[iVertex].array.surfaceId != sidVertex + ) + break; + sidVertex = pVertexDecl[iVertex].array.surfaceId; + } + + rc = vmsvga3dDrawPrimitivesCleanupVertexDecls(pThisCC, pContext, iCurrentVertex, + iVertex - iCurrentVertex, &pVertexDecl[iCurrentVertex]); + AssertRCReturn(rc, rc); + + iCurrentVertex = iVertex; + } + +#ifdef DEBUG + /* Check whether 'activeTexture' on texture unit 'i' matches what we expect. */ + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); ++i) + { + if (pContext->aSidActiveTextures[i] != SVGA3D_INVALID_ID) + { + PVMSVGA3DSURFACE pTexture; + int rc2 = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[i], &pTexture); + AssertContinue(RT_SUCCESS(rc2)); + + GLint activeTextureUnit = 0; + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureUnit); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + pState->ext.glActiveTexture(GL_TEXTURE0 + i); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + GLint activeTexture = 0; + glGetIntegerv(pTexture->bindingGL, &activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + pState->ext.glActiveTexture(activeTextureUnit); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + AssertMsg(pTexture->oglId.texture == (GLuint)activeTexture, + ("%d vs %d unit %d (active unit %d) sid=%u\n", pTexture->oglId.texture, activeTexture, i, + activeTextureUnit - GL_TEXTURE0, pContext->aSidActiveTextures[i])); + } + } +#endif + +#if 0 + /* Dump render target to a bitmap. */ + if (pContext->state.aRenderTargets[SVGA3D_RT_COLOR0] != SVGA3D_INVALID_ID) + { + vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0]); + PVMSVGA3DSURFACE pSurface; + int rc2 = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pSurface); + if (RT_SUCCESS(rc2)) + vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpgl", "rt", "-post"); +# if 0 + /* Stage 0 texture. */ + if (pContext->aSidActiveTextures[0] != SVGA3D_INVALID_ID) + { + vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->aSidActiveTextures[0]); + rc2 = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[0], &pSurface); + if (RT_SUCCESS(rc2)) + vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpgl", "rt", "-post-tx"); + } +# endif + } +#endif + + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData) +{ + PVMSVGA3DSHADER pShader; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dShaderDefine cid=%u shid=%d type=%s cbData=0x%x\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", cbData)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + AssertReturn(shid < SVGA3D_MAX_SHADER_IDS, VERR_INVALID_PARAMETER); + + rc = vmsvga3dShaderParse(type, cbData, pShaderData); + if (RT_FAILURE(rc)) + { + AssertRC(rc); + vmsvga3dShaderLogRel("Failed to parse", type, cbData, pShaderData); + return rc; + } + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + if (type == SVGA3D_SHADERTYPE_VS) + { + if (shid >= pContext->cVertexShaders) + { + void *pvNew = RTMemRealloc(pContext->paVertexShader, sizeof(VMSVGA3DSHADER) * (shid + 1)); + AssertReturn(pvNew, VERR_NO_MEMORY); + pContext->paVertexShader = (PVMSVGA3DSHADER)pvNew; + memset(&pContext->paVertexShader[pContext->cVertexShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cVertexShaders)); + for (uint32_t i = pContext->cVertexShaders; i < shid + 1; i++) + pContext->paVertexShader[i].id = SVGA3D_INVALID_ID; + pContext->cVertexShaders = shid + 1; + } + /* If one already exists with this id, then destroy it now. */ + if (pContext->paVertexShader[shid].id != SVGA3D_INVALID_ID) + vmsvga3dBackShaderDestroy(pThisCC, cid, shid, pContext->paVertexShader[shid].type); + + pShader = &pContext->paVertexShader[shid]; + } + else + { + Assert(type == SVGA3D_SHADERTYPE_PS); + if (shid >= pContext->cPixelShaders) + { + void *pvNew = RTMemRealloc(pContext->paPixelShader, sizeof(VMSVGA3DSHADER) * (shid + 1)); + AssertReturn(pvNew, VERR_NO_MEMORY); + pContext->paPixelShader = (PVMSVGA3DSHADER)pvNew; + memset(&pContext->paPixelShader[pContext->cPixelShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cPixelShaders)); + for (uint32_t i = pContext->cPixelShaders; i < shid + 1; i++) + pContext->paPixelShader[i].id = SVGA3D_INVALID_ID; + pContext->cPixelShaders = shid + 1; + } + /* If one already exists with this id, then destroy it now. */ + if (pContext->paPixelShader[shid].id != SVGA3D_INVALID_ID) + vmsvga3dBackShaderDestroy(pThisCC, cid, shid, pContext->paPixelShader[shid].type); + + pShader = &pContext->paPixelShader[shid]; + } + + memset(pShader, 0, sizeof(*pShader)); + pShader->id = shid; + pShader->cid = cid; + pShader->type = type; + pShader->cbData = cbData; + pShader->pShaderProgram = RTMemAllocZ(cbData); + AssertReturn(pShader->pShaderProgram, VERR_NO_MEMORY); + memcpy(pShader->pShaderProgram, pShaderData, cbData); + +#ifdef DUMP_SHADER_DISASSEMBLY + LPD3DXBUFFER pDisassembly; + HRESULT hr = D3DXDisassembleShader((const DWORD *)pShaderData, FALSE, NULL, &pDisassembly); + if (hr == D3D_OK) + { + Log(("Shader disassembly:\n%s\n", pDisassembly->GetBufferPointer())); + pDisassembly->Release(); + } +#endif + + switch (type) + { + case SVGA3D_SHADERTYPE_VS: + rc = ShaderCreateVertexShader(pContext->pShaderContext, (const uint32_t *)pShaderData, cbData, &pShader->u.pVertexShader); + AssertRC(rc); + break; + + case SVGA3D_SHADERTYPE_PS: + rc = ShaderCreatePixelShader(pContext->pShaderContext, (const uint32_t *)pShaderData, cbData, &pShader->u.pPixelShader); + AssertRC(rc); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + if (rc != VINF_SUCCESS) + { + vmsvga3dShaderLogRel("Failed to create", type, cbData, pShaderData); + + RTMemFree(pShader->pShaderProgram); + memset(pShader, 0, sizeof(*pShader)); + pShader->id = SVGA3D_INVALID_ID; + } + + return rc; +} + +static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + PVMSVGA3DSHADER pShader = NULL; + + Log(("vmsvga3dShaderDestroy cid=%u shid=%d type=%s\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL")); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + if (type == SVGA3D_SHADERTYPE_VS) + { + if ( shid < pContext->cVertexShaders + && pContext->paVertexShader[shid].id == shid) + { + pShader = &pContext->paVertexShader[shid]; + if (pContext->state.shidVertex == shid) + { + rc = ShaderSetVertexShader(pContext->pShaderContext, NULL); + AssertRC(rc); + } + + rc = ShaderDestroyVertexShader(pContext->pShaderContext, pShader->u.pVertexShader); + AssertRC(rc); + } + } + else + { + Assert(type == SVGA3D_SHADERTYPE_PS); + if ( shid < pContext->cPixelShaders + && pContext->paPixelShader[shid].id == shid) + { + pShader = &pContext->paPixelShader[shid]; + if (pContext->state.shidPixel == shid) + { + ShaderSetPixelShader(pContext->pShaderContext, NULL); + AssertRC(rc); + } + + rc = ShaderDestroyPixelShader(pContext->pShaderContext, pShader->u.pPixelShader); + AssertRC(rc); + } + } + + if (pShader) + { + if (pShader->pShaderProgram) + RTMemFree(pShader->pShaderProgram); + memset(pShader, 0, sizeof(*pShader)); + pShader->id = SVGA3D_INVALID_ID; + } + else + AssertFailedReturn(VERR_INVALID_PARAMETER); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackShaderSet(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + int rc; + + Log(("vmsvga3dShaderSet cid=%u type=%s shid=%d\n", cid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", shid)); + + if (!pContext) + { + rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + } + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + if (type == SVGA3D_SHADERTYPE_VS) + { + /* Save for vm state save/restore. */ + pContext->state.shidVertex = shid; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VERTEXSHADER; + + if ( shid < pContext->cVertexShaders + && pContext->paVertexShader[shid].id == shid) + { + PVMSVGA3DSHADER pShader = &pContext->paVertexShader[shid]; + Assert(type == pShader->type); + + rc = ShaderSetVertexShader(pContext->pShaderContext, pShader->u.pVertexShader); + AssertRCReturn(rc, rc); + } + else + if (shid == SVGA_ID_INVALID) + { + /* Unselect shader. */ + rc = ShaderSetVertexShader(pContext->pShaderContext, NULL); + AssertRCReturn(rc, rc); + } + else + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + else + { + /* Save for vm state save/restore. */ + pContext->state.shidPixel = shid; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_PIXELSHADER; + + Assert(type == SVGA3D_SHADERTYPE_PS); + if ( shid < pContext->cPixelShaders + && pContext->paPixelShader[shid].id == shid) + { + PVMSVGA3DSHADER pShader = &pContext->paPixelShader[shid]; + Assert(type == pShader->type); + + rc = ShaderSetPixelShader(pContext->pShaderContext, pShader->u.pPixelShader); + AssertRCReturn(rc, rc); + } + else + if (shid == SVGA_ID_INVALID) + { + /* Unselect shader. */ + rc = ShaderSetPixelShader(pContext->pShaderContext, NULL); + AssertRCReturn(rc, rc); + } + else + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dShaderSetConst cid=%u reg=%x type=%s cregs=%d ctype=%x\n", cid, reg, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", cRegisters, ctype)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + for (uint32_t i = 0; i < cRegisters; i++) + { +#ifdef LOG_ENABLED + switch (ctype) + { + case SVGA3D_CONST_TYPE_FLOAT: + { + float *pValuesF = (float *)pValues; + Log(("ConstantF %d: value=" FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR "\n", + reg + i, FLOAT_FMT_ARGS(pValuesF[i*4 + 0]), FLOAT_FMT_ARGS(pValuesF[i*4 + 1]), FLOAT_FMT_ARGS(pValuesF[i*4 + 2]), FLOAT_FMT_ARGS(pValuesF[i*4 + 3]))); + break; + } + + case SVGA3D_CONST_TYPE_INT: + Log(("ConstantI %d: value=%d, %d, %d, %d\n", reg + i, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3])); + break; + + case SVGA3D_CONST_TYPE_BOOL: + Log(("ConstantB %d: value=%d, %d, %d, %d\n", reg + i, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3])); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } +#endif + vmsvga3dSaveShaderConst(pContext, reg + i, type, ctype, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3]); + } + + switch (type) + { + case SVGA3D_SHADERTYPE_VS: + switch (ctype) + { + case SVGA3D_CONST_TYPE_FLOAT: + rc = ShaderSetVertexShaderConstantF(pContext->pShaderContext, reg, (const float *)pValues, cRegisters); + break; + + case SVGA3D_CONST_TYPE_INT: + rc = ShaderSetVertexShaderConstantI(pContext->pShaderContext, reg, (const int32_t *)pValues, cRegisters); + break; + + case SVGA3D_CONST_TYPE_BOOL: + rc = ShaderSetVertexShaderConstantB(pContext->pShaderContext, reg, (const uint8_t *)pValues, cRegisters); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + AssertRCReturn(rc, rc); + break; + + case SVGA3D_SHADERTYPE_PS: + switch (ctype) + { + case SVGA3D_CONST_TYPE_FLOAT: + rc = ShaderSetPixelShaderConstantF(pContext->pShaderContext, reg, (const float *)pValues, cRegisters); + break; + + case SVGA3D_CONST_TYPE_INT: + rc = ShaderSetPixelShaderConstantI(pContext->pShaderContext, reg, (const int32_t *)pValues, cRegisters); + break; + + case SVGA3D_CONST_TYPE_BOOL: + rc = ShaderSetPixelShaderConstantB(pContext->pShaderContext, reg, (const uint8_t *)pValues, cRegisters); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + AssertRCReturn(rc, rc); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryCreate(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState->ext.glGenQueries, VERR_NOT_SUPPORTED); + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + GLuint idQuery = 0; + pState->ext.glGenQueries(1, &idQuery); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + AssertReturn(idQuery, VERR_INTERNAL_ERROR); + pContext->occlusion.idQuery = idQuery; + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState->ext.glDeleteQueries, VERR_NOT_SUPPORTED); + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + if (pContext->occlusion.idQuery) + { + pState->ext.glDeleteQueries(1, &pContext->occlusion.idQuery); + } + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryBegin(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState->ext.glBeginQuery, VERR_NOT_SUPPORTED); + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + pState->ext.glBeginQuery(GL_ANY_SAMPLES_PASSED, pContext->occlusion.idQuery); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryEnd(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState->ext.glEndQuery, VERR_NOT_SUPPORTED); + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + pState->ext.glEndQuery(GL_ANY_SAMPLES_PASSED); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryGetData(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t *pu32Pixels) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState->ext.glGetQueryObjectuiv, VERR_NOT_SUPPORTED); + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + GLuint pixels = 0; + pState->ext.glGetQueryObjectuiv(pContext->occlusion.idQuery, GL_QUERY_RESULT, &pixels); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + *pu32Pixels = (uint32_t)pixels; + return VINF_SUCCESS; +} + +/** + * Worker for vmsvga3dUpdateHeapBuffersForSurfaces. + * + * This will allocate heap buffers if necessary, thus increasing the memory + * usage of the process. + * + * @todo Would be interesting to share this code with the saved state code. + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA context. + * @param pSurface The surface to refresh the heap buffers for. + */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceUpdateHeapBuffers(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + /* + * Currently we've got trouble retreving bit for DEPTHSTENCIL + * surfaces both for OpenGL and D3D, so skip these here (don't + * wast memory on them). + */ + uint32_t const fSwitchFlags = pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK; + if ( fSwitchFlags != SVGA3D_SURFACE_HINT_DEPTHSTENCIL + && fSwitchFlags != (SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE)) + { + /* + * Change OpenGL context to the one the surface is associated with. + */ + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + /* + * Work thru each mipmap level for each face. + */ + for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[iFace * pSurface->cLevels]; + for (uint32_t i = 0; i < pSurface->cLevels; i++, pMipmapLevel++) + { + if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + Assert(pMipmapLevel->cbSurface); + Assert(pMipmapLevel->cbSurface == pMipmapLevel->cbSurfacePlane * pMipmapLevel->mipmapSize.depth); + + /* + * Make sure we've got surface memory buffer. + */ + uint8_t *pbDst = (uint8_t *)pMipmapLevel->pSurfaceData; + if (!pbDst) + { + pMipmapLevel->pSurfaceData = pbDst = (uint8_t *)RTMemAllocZ(pMipmapLevel->cbSurface); + AssertReturn(pbDst, VERR_NO_MEMORY); + } + + /* + * OpenGL specifics. + */ + switch (pSurface->enmOGLResType) + { + case VMSVGA3D_OGLRESTYPE_TEXTURE: + { + GLint activeTexture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /* Set row length and alignment of the output data. */ + VMSVGAPACKPARAMS SavedParams; + vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams); + + glGetTexImage(GL_TEXTURE_2D, + i, + pSurface->formatGL, + pSurface->typeGL, + pbDst); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams); + + /* Restore the old active texture. */ + glBindTexture(GL_TEXTURE_2D, activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + break; + } + + case VMSVGA3D_OGLRESTYPE_BUFFER: + { + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + void *pvSrc = pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + if (RT_VALID_PTR(pvSrc)) + memcpy(pbDst, pvSrc, pMipmapLevel->cbSurface); + else + AssertPtr(pvSrc); + + pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + break; + } + + default: + AssertMsgFailed(("%#x\n", fSwitchFlags)); + } + } + /* else: There is no data in hardware yet, so whatever we got is already current. */ + } + } + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackQueryInterface(PVGASTATECC pThisCC, char const *pszInterfaceName, void *pvInterfaceFuncs, size_t cbInterfaceFuncs) +{ + RT_NOREF(pThisCC); + + int rc = VINF_SUCCESS; + if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_3D) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCS3D)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCS3D *p = (VMSVGA3DBACKENDFUNCS3D *)pvInterfaceFuncs; + p->pfnInit = vmsvga3dBackInit; + p->pfnPowerOn = vmsvga3dBackPowerOn; + p->pfnTerminate = vmsvga3dBackTerminate; + p->pfnReset = vmsvga3dBackReset; + p->pfnQueryCaps = vmsvga3dBackQueryCaps; + p->pfnChangeMode = vmsvga3dBackChangeMode; + p->pfnCreateTexture = vmsvga3dBackCreateTexture; + p->pfnSurfaceDestroy = vmsvga3dBackSurfaceDestroy; + p->pfnSurfaceInvalidateImage = vmsvga3dBackSurfaceInvalidateImage; + p->pfnSurfaceCopy = vmsvga3dBackSurfaceCopy; + p->pfnSurfaceDMACopyBox = vmsvga3dBackSurfaceDMACopyBox; + p->pfnSurfaceStretchBlt = vmsvga3dBackSurfaceStretchBlt; + p->pfnUpdateHostScreenViewport = vmsvga3dBackUpdateHostScreenViewport; + p->pfnDefineScreen = vmsvga3dBackDefineScreen; + p->pfnDestroyScreen = vmsvga3dBackDestroyScreen; + p->pfnSurfaceBlitToScreen = vmsvga3dBackSurfaceBlitToScreen; + p->pfnSurfaceUpdateHeapBuffers = vmsvga3dBackSurfaceUpdateHeapBuffers; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_VGPU9) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSVGPU9)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCSVGPU9 *p = (VMSVGA3DBACKENDFUNCSVGPU9 *)pvInterfaceFuncs; + p->pfnContextDefine = vmsvga3dBackContextDefine; + p->pfnContextDestroy = vmsvga3dBackContextDestroy; + p->pfnSetTransform = vmsvga3dBackSetTransform; + p->pfnSetZRange = vmsvga3dBackSetZRange; + p->pfnSetRenderState = vmsvga3dBackSetRenderState; + p->pfnSetRenderTarget = vmsvga3dBackSetRenderTarget; + p->pfnSetTextureState = vmsvga3dBackSetTextureState; + p->pfnSetMaterial = vmsvga3dBackSetMaterial; + p->pfnSetLightData = vmsvga3dBackSetLightData; + p->pfnSetLightEnabled = vmsvga3dBackSetLightEnabled; + p->pfnSetViewPort = vmsvga3dBackSetViewPort; + p->pfnSetClipPlane = vmsvga3dBackSetClipPlane; + p->pfnCommandClear = vmsvga3dBackCommandClear; + p->pfnDrawPrimitives = vmsvga3dBackDrawPrimitives; + p->pfnSetScissorRect = vmsvga3dBackSetScissorRect; + p->pfnGenerateMipmaps = vmsvga3dBackGenerateMipmaps; + p->pfnShaderDefine = vmsvga3dBackShaderDefine; + p->pfnShaderDestroy = vmsvga3dBackShaderDestroy; + p->pfnShaderSet = vmsvga3dBackShaderSet; + p->pfnShaderSetConst = vmsvga3dBackShaderSetConst; + p->pfnOcclusionQueryCreate = vmsvga3dBackOcclusionQueryCreate; + p->pfnOcclusionQueryDelete = vmsvga3dBackOcclusionQueryDelete; + p->pfnOcclusionQueryBegin = vmsvga3dBackOcclusionQueryBegin; + p->pfnOcclusionQueryEnd = vmsvga3dBackOcclusionQueryEnd; + p->pfnOcclusionQueryGetData = vmsvga3dBackOcclusionQueryGetData; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else + rc = VERR_NOT_IMPLEMENTED; + return rc; +} + + +extern VMSVGA3DBACKENDDESC const g_BackendLegacy = +{ + "LEGACY", + vmsvga3dBackQueryInterface +}; diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-savedstate.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-savedstate.cpp new file mode 100644 index 00000000..fcb47f42 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-savedstate.cpp @@ -0,0 +1,1290 @@ +/* $Id: DevVGA-SVGA3d-savedstate.cpp $ */ +/** @file + * DevSVGA3d - VMWare SVGA device, 3D parts - Saved state and assocated stuff. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include + +#include +#include + +#include /* required by DevVGA.h */ +#include /* required by DevVGA.h */ + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +#include "DevVGA-SVGA3d-internal.h" + + + +/** + * Reinitializes an active context. + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pContext The freshly loaded context to reinitialize. + */ +static int vmsvga3dLoadReinitContext(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + int rc; + uint32_t cid = pContext->id; + Assert(cid != SVGA3D_INVALID_ID); + + /* First set the render targets as they change the internal state (reset viewport etc) */ + Log(("vmsvga3dLoadReinitContext: Recreate render targets BEGIN [cid=%#x]\n", cid)); + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aRenderTargets); j++) + { + if (pContext->state.aRenderTargets[j] != SVGA3D_INVALID_ID) + { + SVGA3dSurfaceImageId target; + + target.sid = pContext->state.aRenderTargets[j]; + target.face = 0; + target.mipmap = 0; + rc = vmsvga3dSetRenderTarget(pThisCC, cid, (SVGA3dRenderTargetType)j, target); + AssertRCReturn(rc, rc); + } + } + Log(("vmsvga3dLoadReinitContext: Recreate render targets END\n")); + + /* Recreate the render state */ + Log(("vmsvga3dLoadReinitContext: Recreate render state BEGIN\n")); + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aRenderState); j++) + { + SVGA3dRenderState *pRenderState = &pContext->state.aRenderState[j]; + + if (pRenderState->state != SVGA3D_RS_INVALID) + vmsvga3dSetRenderState(pThisCC, pContext->id, 1, pRenderState); + } + Log(("vmsvga3dLoadReinitContext: Recreate render state END\n")); + + /* Recreate the texture state */ + Log(("vmsvga3dLoadReinitContext: Recreate texture state BEGIN\n")); + for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage) + { + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j) + { + SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j]; + + if (pTextureState->name != SVGA3D_TS_INVALID) + vmsvga3dSetTextureState(pThisCC, pContext->id, 1, pTextureState); + } + } + Log(("vmsvga3dLoadReinitContext: Recreate texture state END\n")); + + /* Reprogram the clip planes. */ + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aClipPlane); j++) + { + if (pContext->state.aClipPlane[j].fValid == true) + vmsvga3dSetClipPlane(pThisCC, cid, j, pContext->state.aClipPlane[j].plane); + } + + /* Reprogram the light data. */ + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aLightData); j++) + { + if (pContext->state.aLightData[j].fValidData == true) + vmsvga3dSetLightData(pThisCC, cid, j, &pContext->state.aLightData[j].data); + if (pContext->state.aLightData[j].fEnabled) + vmsvga3dSetLightEnabled(pThisCC, cid, j, true); + } + + /* Recreate the transform state. */ + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_TRANSFORM) + { + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTransformState); j++) + { + if (pContext->state.aTransformState[j].fValid == true) + vmsvga3dSetTransform(pThisCC, cid, (SVGA3dTransformType)j, pContext->state.aTransformState[j].matrix); + } + } + + /* Reprogram the material data. */ + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_MATERIAL) + { + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aMaterial); j++) + { + if (pContext->state.aMaterial[j].fValid == true) + vmsvga3dSetMaterial(pThisCC, cid, (SVGA3dFace)j, &pContext->state.aMaterial[j].material); + } + } + + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_SCISSORRECT) + vmsvga3dSetScissorRect(pThisCC, cid, &pContext->state.RectScissor); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_ZRANGE) + vmsvga3dSetZRange(pThisCC, cid, pContext->state.zRange); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VIEWPORT) + vmsvga3dSetViewPort(pThisCC, cid, &pContext->state.RectViewPort); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VERTEXSHADER) + vmsvga3dShaderSet(pThisCC, pContext, cid, SVGA3D_SHADERTYPE_VS, pContext->state.shidVertex); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_PIXELSHADER) + vmsvga3dShaderSet(pThisCC, pContext, cid, SVGA3D_SHADERTYPE_PS, pContext->state.shidPixel); + + Log(("vmsvga3dLoadReinitContext: returns [cid=%#x]\n", cid)); + return VINF_SUCCESS; +} + +static int vmsvga3dLoadVMSVGA3DSURFACEPreMipLevels(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, VMSVGA3DSURFACE *pSurface) +{ + struct VMSVGA3DSURFACEPreMipLevels + { + uint32_t id; + uint32_t idAssociatedContext; + uint32_t surfaceFlags; + SVGA3dSurfaceFormat format; +#ifdef VMSVGA3D_OPENGL + GLint internalFormatGL; + GLint formatGL; + GLint typeGL; +#endif + SVGA3dSurfaceFace faces[SVGA3D_MAX_SURFACE_FACES]; + uint32_t cFaces; + uint32_t multiSampleCount; + SVGA3dTextureFilter autogenFilter; + uint32_t cbBlock; + }; + + static SSMFIELD const s_aVMSVGA3DSURFACEFieldsPreMipLevels[] = + { + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, id), + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, idAssociatedContext), + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, surfaceFlags), + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, format), +#ifdef VMSVGA3D_OPENGL + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, internalFormatGL), + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, formatGL), + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, typeGL), +#endif + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, faces), + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, cFaces), + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, multiSampleCount), + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, autogenFilter), +#ifdef VMSVGA3D_DIRECT3D + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, format), /* Yes, the 'format' field is duplicated. */ +#endif + SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, cbBlock), + SSMFIELD_ENTRY_TERM() + }; + + struct VMSVGA3DSURFACEPreMipLevels surfacePreMipLevels; + int rc = pDevIns->pHlpR3->pfnSSMGetStructEx(pSSM, &surfacePreMipLevels, sizeof(surfacePreMipLevels), 0, s_aVMSVGA3DSURFACEFieldsPreMipLevels, NULL); + if (RT_SUCCESS(rc)) + { + pSurface->id = surfacePreMipLevels.id; + pSurface->idAssociatedContext = surfacePreMipLevels.idAssociatedContext; + pSurface->f.s.surface1Flags = surfacePreMipLevels.surfaceFlags; + pSurface->f.s.surface2Flags = 0; + pSurface->format = surfacePreMipLevels.format; +#ifdef VMSVGA3D_OPENGL + pSurface->internalFormatGL = surfacePreMipLevels.internalFormatGL; + pSurface->formatGL = surfacePreMipLevels.formatGL; + pSurface->typeGL = surfacePreMipLevels.typeGL; +#endif + pSurface->cLevels = surfacePreMipLevels.faces[0].numMipLevels; + pSurface->cFaces = surfacePreMipLevels.cFaces; + pSurface->multiSampleCount = surfacePreMipLevels.multiSampleCount; + pSurface->autogenFilter = surfacePreMipLevels.autogenFilter; + pSurface->cbBlock = surfacePreMipLevels.cbBlock; + } + return rc; +} + + +/* + * Load the legacy VMSVGA3DCONTEXT from saved state version VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS (23) + * or earlier, i.e. 6.1 or old trunk. + * + * The saved state incompatibility has been introduced in two revisions: + * + * - r140506: which makes sure that VMSVGA structures are tightly packed (pragma pack(1)). + * This caused all structures which have a member from VMSVGA headers (like VMSVGALIGHTSTATE) to be packed too. + * For example the size of aLightData element (VMSVGALIGHTSTATE) is 2 bytes smaller on trunk (118) than on 6.1 (120), + * which happens because SVGA3dLightData member offset is 2 on trunk and 4 on 6.1. + * + * - r141385: new VMSVGA device headers. + * SVGA3D_RS_MAX is 99 with new VMSVGA headers, but it was 100 with old headers. + * 6.1 always saved 100 entries; trunk before r141385 saved 100 entries; trunk at r141385 saves 99 entries. + * + * 6.1 saved state version is VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS (21). + * Trunk r141287 introduced VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS (23). + * + * Both issues has been solved by loading a compatible context structure for saved state + * version < VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS. + * This means that trunk will not be able to load states created from r140506 to r141385. + */ +static int vmsvga3dLoadVMSVGA3DCONTEXT23(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, VMSVGA3DCONTEXT *pContext) +{ +#pragma pack(1) + struct VMSVGA3DCONTEXT23 + { + uint32_t id; +#ifdef VMSVGA3D_OPENGL + uint32_t lastError; +#endif + uint32_t cPixelShaders; + uint32_t cVertexShaders; + struct + { + uint32_t u32UpdateFlags; + SVGA3dRenderState aRenderState[/*SVGA3D_RS_MAX=*/ 100]; + SVGA3dTextureState aTextureStates[/*SVGA3D_MAX_TEXTURE_STAGE=*/ 8][/*SVGA3D_TS_MAX=*/ 30]; + struct + { + bool fValid; + bool pad[3]; + float matrix[16]; + } aTransformState[SVGA3D_TRANSFORM_MAX]; + struct + { + bool fValid; + bool pad[3]; + SVGA3dMaterial material; + } aMaterial[SVGA3D_FACE_MAX]; + struct + { + bool fValid; + bool pad[3]; + float plane[4]; + } aClipPlane[SVGA3D_CLIPPLANE_5]; + struct + { + bool fEnabled; + bool fValidData; + bool pad[2]; + SVGA3dLightData data; + } aLightData[SVGA3D_MAX_LIGHTS]; + uint32_t aRenderTargets[SVGA3D_RT_MAX]; + SVGA3dRect RectScissor; + SVGA3dRect RectViewPort; + SVGA3dZRange zRange; + uint32_t shidPixel; + uint32_t shidVertex; + uint32_t cPixelShaderConst; + uint32_t cVertexShaderConst; + } state; + }; +#pragma pack() + + static SSMFIELD const g_aVMSVGA3DCONTEXT23Fields[] = + { + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, id), +#ifdef VMSVGA3D_OPENGL + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, lastError), +#endif + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, cPixelShaders), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, cVertexShaders), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.u32UpdateFlags), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aRenderState), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aTextureStates), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aTransformState), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aMaterial), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aClipPlane), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aLightData), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aRenderTargets), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.RectScissor), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.RectViewPort), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.zRange), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.shidPixel), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.shidVertex), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.cPixelShaderConst), + SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.cVertexShaderConst), + SSMFIELD_ENTRY_TERM() + }; + + struct VMSVGA3DCONTEXT23 ctx; + int rc = pDevIns->pHlpR3->pfnSSMGetStructEx(pSSM, &ctx, sizeof(ctx), 0, g_aVMSVGA3DCONTEXT23Fields, NULL); + AssertRCReturn(rc, rc); + + pContext->id = ctx.id; +#ifdef VMSVGA3D_OPENGL + pContext->lastError = (GLenum)ctx.lastError; +#endif + + pContext->cPixelShaders = ctx.cPixelShaders; + pContext->cVertexShaders = ctx.cVertexShaders; + pContext->state.u32UpdateFlags = ctx.state.u32UpdateFlags; + + AssertCompile(sizeof(SVGA3dRenderState) == 8); + AssertCompile(RT_ELEMENTS(pContext->state.aRenderState) == 99); + for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aRenderState); ++i) + pContext->state.aRenderState[i] = ctx.state.aRenderState[i]; + + // Skip pContext->state.aTextureStates + AssertCompile(sizeof(SVGA3dTextureState) == 12); + + AssertCompile(sizeof(VMSVGATRANSFORMSTATE) == 68); + AssertCompile(RT_ELEMENTS(pContext->state.aTransformState) == 15); + for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aTransformState); ++i) + { + pContext->state.aTransformState[i].fValid = ctx.state.aTransformState[i].fValid; + memcpy(pContext->state.aTransformState[i].matrix, ctx.state.aTransformState[i].matrix, sizeof(pContext->state.aTransformState[i].matrix)); + } + + AssertCompile(sizeof(SVGA3dMaterial) == 68); + AssertCompile(RT_ELEMENTS(pContext->state.aMaterial) == 5); + for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aMaterial); ++i) + { + pContext->state.aMaterial[i].fValid = ctx.state.aMaterial[i].fValid; + pContext->state.aMaterial[i].material = ctx.state.aMaterial[i].material; + } + + AssertCompile(sizeof(VMSVGACLIPPLANESTATE) == 20); + AssertCompile(RT_ELEMENTS(pContext->state.aClipPlane) == (1 << 5)); + for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aClipPlane); ++i) + { + pContext->state.aClipPlane[i].fValid = ctx.state.aClipPlane[i].fValid; + memcpy(pContext->state.aClipPlane[i].plane, ctx.state.aClipPlane[i].plane, sizeof(pContext->state.aClipPlane[i].plane)); + } + + AssertCompile(sizeof(SVGA3dLightData) == 116); + AssertCompile(RT_ELEMENTS(pContext->state.aLightData) == 32); + for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aLightData); ++i) + { + pContext->state.aLightData[i].fEnabled = ctx.state.aLightData[i].fEnabled; + pContext->state.aLightData[i].fValidData = ctx.state.aLightData[i].fValidData; + pContext->state.aLightData[i].data = ctx.state.aLightData[i].data; + } + + AssertCompile(RT_ELEMENTS(pContext->state.aRenderTargets) == 10); + memcpy(pContext->state.aRenderTargets, ctx.state.aRenderTargets, SVGA3D_RT_MAX * sizeof(uint32_t)); + + AssertCompile(sizeof(SVGA3dRect) == 16); + pContext->state.RectScissor = ctx.state.RectScissor; + pContext->state.RectViewPort = ctx.state.RectViewPort; + + AssertCompile(sizeof(SVGA3dZRange) == 8); + pContext->state.zRange = ctx.state.zRange; + + pContext->state.shidPixel = ctx.state.shidPixel; + pContext->state.shidVertex = ctx.state.shidVertex; + pContext->state.cPixelShaderConst = ctx.state.cPixelShaderConst; + pContext->state.cVertexShaderConst = ctx.state.cVertexShaderConst; + + return VINF_SUCCESS; +} + +int vmsvga3dLoadExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) +{ + RT_NOREF(pDevIns, pThis, uPass); + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc; + uint32_t cContexts, cSurfaces; + LogFlow(("vmsvga3dLoadExec:\n")); + + /* Get the generic 3d state first. */ + rc = pHlp->pfnSSMGetStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL); + AssertRCReturn(rc, rc); + + cContexts = pState->cContexts; + cSurfaces = pState->cSurfaces; + pState->cContexts = 0; + pState->cSurfaces = 0; + + /* Fetch all active contexts. */ + for (uint32_t i = 0; i < cContexts; i++) + { + PVMSVGA3DCONTEXT pContext; + uint32_t cid; + + /* Get the context id */ + rc = pHlp->pfnSSMGetU32(pSSM, &cid); + AssertRCReturn(rc, rc); + + if (cid != SVGA3D_INVALID_ID) + { + uint32_t cPixelShaderConst, cVertexShaderConst, cPixelShaders, cVertexShaders; + LogFlow(("vmsvga3dLoadExec: Loading cid=%#x\n", cid)); + +#ifdef VMSVGA3D_OPENGL + if (cid == VMSVGA3D_SHARED_CTX_ID) + { + i--; /* Not included in cContexts. */ + pContext = &pState->SharedCtx; + if (pContext->id != VMSVGA3D_SHARED_CTX_ID) + { + /** @todo Separate backend */ + rc = vmsvga3dContextDefineOgl(pThisCC, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX); + AssertRCReturn(rc, rc); + } + } + else +#endif + { + rc = vmsvga3dContextDefine(pThisCC, cid); + AssertRCReturn(rc, rc); + + pContext = pState->papContexts[i]; + } + AssertReturn(pContext->id == cid, VERR_INTERNAL_ERROR); + + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS) + rc = pHlp->pfnSSMGetStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL); + else + rc = vmsvga3dLoadVMSVGA3DCONTEXT23(pDevIns, pSSM, pContext); + AssertRCReturn(rc, rc); + + cPixelShaders = pContext->cPixelShaders; + cVertexShaders = pContext->cVertexShaders; + cPixelShaderConst = pContext->state.cPixelShaderConst; + cVertexShaderConst = pContext->state.cVertexShaderConst; + pContext->cPixelShaders = 0; + pContext->cVertexShaders = 0; + pContext->state.cPixelShaderConst = 0; + pContext->state.cVertexShaderConst = 0; + + /* Fetch all pixel shaders. */ + for (uint32_t j = 0; j < cPixelShaders; j++) + { + VMSVGA3DSHADER shader; + uint32_t shid; + + /* Fetch the id first. */ + rc = pHlp->pfnSSMGetU32(pSSM, &shid); + AssertRCReturn(rc, rc); + + if (shid != SVGA3D_INVALID_ID) + { + uint32_t *pData; + + /* Fetch a copy of the shader struct. */ + rc = pHlp->pfnSSMGetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL); + AssertRCReturn(rc, rc); + + pData = (uint32_t *)RTMemAlloc(shader.cbData); + AssertReturn(pData, VERR_NO_MEMORY); + + rc = pHlp->pfnSSMGetMem(pSSM, pData, shader.cbData); + AssertRCReturn(rc, rc); + + rc = vmsvga3dShaderDefine(pThisCC, cid, shid, shader.type, shader.cbData, pData); + AssertRCReturn(rc, rc); + + RTMemFree(pData); + } + } + + /* Fetch all vertex shaders. */ + for (uint32_t j = 0; j < cVertexShaders; j++) + { + VMSVGA3DSHADER shader; + uint32_t shid; + + /* Fetch the id first. */ + rc = pHlp->pfnSSMGetU32(pSSM, &shid); + AssertRCReturn(rc, rc); + + if (shid != SVGA3D_INVALID_ID) + { + uint32_t *pData; + + /* Fetch a copy of the shader struct. */ + rc = pHlp->pfnSSMGetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL); + AssertRCReturn(rc, rc); + + pData = (uint32_t *)RTMemAlloc(shader.cbData); + AssertReturn(pData, VERR_NO_MEMORY); + + rc = pHlp->pfnSSMGetMem(pSSM, pData, shader.cbData); + AssertRCReturn(rc, rc); + + rc = vmsvga3dShaderDefine(pThisCC, cid, shid, shader.type, shader.cbData, pData); + AssertRCReturn(rc, rc); + + RTMemFree(pData); + } + } + + /* Fetch pixel shader constants. */ + for (uint32_t j = 0; j < cPixelShaderConst; j++) + { + VMSVGASHADERCONST ShaderConst; + + rc = pHlp->pfnSSMGetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL); + AssertRCReturn(rc, rc); + + if (ShaderConst.fValid) + { + rc = vmsvga3dShaderSetConst(pThisCC, cid, j, SVGA3D_SHADERTYPE_PS, ShaderConst.ctype, 1, ShaderConst.value); + AssertRCReturn(rc, rc); + } + } + + /* Fetch vertex shader constants. */ + for (uint32_t j = 0; j < cVertexShaderConst; j++) + { + VMSVGASHADERCONST ShaderConst; + + rc = pHlp->pfnSSMGetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL); + AssertRCReturn(rc, rc); + + if (ShaderConst.fValid) + { + rc = vmsvga3dShaderSetConst(pThisCC, cid, j, SVGA3D_SHADERTYPE_VS, ShaderConst.ctype, 1, ShaderConst.value); + AssertRCReturn(rc, rc); + } + } + + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_TEX_STAGES) + { + /* Load texture stage and samplers state. */ + + /* Number of stages/samplers. */ + uint32_t cStages; + rc = pHlp->pfnSSMGetU32(pSSM, &cStages); + AssertRCReturn(rc, rc); + + /* Number of states. */ + uint32_t cTextureStates; + rc = pHlp->pfnSSMGetU32(pSSM, &cTextureStates); + AssertRCReturn(rc, rc); + + for (uint32_t iStage = 0; iStage < cStages; ++iStage) + { + for (uint32_t j = 0; j < cTextureStates; ++j) + { + SVGA3dTextureState textureState; + pHlp->pfnSSMGetU32(pSSM, &textureState.stage); + uint32_t u32Name; + pHlp->pfnSSMGetU32(pSSM, &u32Name); + textureState.name = (SVGA3dTextureStateName)u32Name; + rc = pHlp->pfnSSMGetU32(pSSM, &textureState.value); + AssertRCReturn(rc, rc); + + if ( iStage < RT_ELEMENTS(pContext->state.aTextureStates) + && j < RT_ELEMENTS(pContext->state.aTextureStates[0])) + { + pContext->state.aTextureStates[iStage][j] = textureState; + } + } + } + } + + if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA) + { + VMSVGA3DQUERY query; + RT_ZERO(query); + + rc = pHlp->pfnSSMGetStructEx(pSSM, &query, sizeof(query), 0, g_aVMSVGA3DQUERYFields, NULL); + AssertRCReturn(rc, rc); + + switch (query.enmQueryState) + { + case VMSVGA3DQUERYSTATE_BUILDING: + /* Start collecting data. */ + vmsvga3dQueryBegin(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION); + /* Partial result. */ + pContext->occlusion.u32QueryResult = query.u32QueryResult; + break; + + case VMSVGA3DQUERYSTATE_ISSUED: + /* Guest ended the query but did not read result. Result is restored. */ + query.enmQueryState = VMSVGA3DQUERYSTATE_SIGNALED; + RT_FALL_THRU(); + case VMSVGA3DQUERYSTATE_SIGNALED: + /* Create the query object. */ + vmsvga3dQueryCreate(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION); + + /* Update result and state. */ + pContext->occlusion.enmQueryState = query.enmQueryState; + pContext->occlusion.u32QueryResult = query.u32QueryResult; + break; + + default: + AssertFailed(); + RT_FALL_THRU(); + case VMSVGA3DQUERYSTATE_NULL: + RT_ZERO(pContext->occlusion); + break; + } + } + } + } + +#ifdef VMSVGA3D_OPENGL + /* Make the shared context the current one. */ + if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) + VMSVGA3D_SET_CURRENT_CONTEXT(pState, &pState->SharedCtx); +#endif + + /* Fetch all surfaces. */ + for (uint32_t i = 0; i < cSurfaces; i++) + { + uint32_t sid; + + /* Fetch the id first. */ + rc = pHlp->pfnSSMGetU32(pSSM, &sid); + AssertRCReturn(rc, rc); + + if (sid != SVGA3D_INVALID_ID) + { + VMSVGA3DSURFACE surface; + LogFlow(("vmsvga3dLoadExec: Loading sid=%#x\n", sid)); + + /* Fetch the surface structure first. */ + if (RT_LIKELY(uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS)) + rc = pHlp->pfnSSMGetStructEx(pSSM, &surface, sizeof(surface), 0, g_aVMSVGA3DSURFACEFields, NULL); + else + rc = vmsvga3dLoadVMSVGA3DSURFACEPreMipLevels(pDevIns, pSSM, &surface); + AssertRCReturn(rc, rc); + + { + uint32_t cMipLevels = surface.cLevels * surface.cFaces; + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = (PVMSVGA3DMIPMAPLEVEL)RTMemAlloc(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL)); + AssertReturn(pMipmapLevel, VERR_NO_MEMORY); + SVGA3dSize *pMipmapLevelSize = (SVGA3dSize *)RTMemAlloc(cMipLevels * sizeof(SVGA3dSize)); + AssertReturn(pMipmapLevelSize, VERR_NO_MEMORY); + + /* Load the mip map level info. */ + for (uint32_t face=0; face < surface.cFaces; face++) + { + for (uint32_t j = 0; j < surface.cLevels; j++) + { + uint32_t idx = j + face * surface.cLevels; + /* Load the mip map level struct. */ + rc = pHlp->pfnSSMGetStructEx(pSSM, &pMipmapLevel[idx], sizeof(pMipmapLevel[idx]), 0, + g_aVMSVGA3DMIPMAPLEVELFields, NULL); + AssertRCReturn(rc, rc); + + pMipmapLevelSize[idx] = pMipmapLevel[idx].mipmapSize; + } + } + + rc = vmsvga3dSurfaceDefine(pThisCC, sid, surface.f.surfaceFlags, surface.format, surface.multiSampleCount, + surface.autogenFilter, surface.cLevels, &pMipmapLevelSize[0], /* arraySize = */ 0, /* fAllocMipLevels = */ true); + AssertRCReturn(rc, rc); + + RTMemFree(pMipmapLevelSize); + RTMemFree(pMipmapLevel); + } + + PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; + Assert(pSurface->id == sid); + + pSurface->fDirty = false; + + /* Load the mip map level data. */ + for (uint32_t j = 0; j < pSurface->cLevels * pSurface->cFaces; j++) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j]; + bool fDataPresent = false; + + /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */ + Assert(pMipmapLevel->cbSurface); + AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR); + + /* Fetch the data present boolean first. */ + rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent); + AssertRCReturn(rc, rc); + + Log(("Surface sid=%u: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent)); + + if (fDataPresent) + { + rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface); + AssertRCReturn(rc, rc); + pMipmapLevel->fDirty = true; + pSurface->fDirty = true; + } + else + { + pMipmapLevel->fDirty = false; + } + } + } + } + +#ifdef VMSVGA3D_OPENGL + /* Reinitialize the shared context. */ + LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id)); + if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) + { + rc = vmsvga3dLoadReinitContext(pThisCC, &pState->SharedCtx); + AssertRCReturn(rc, rc); + } +#endif + + /* Reinitialize all active contexts. */ + for (uint32_t i = 0; i < pState->cContexts; i++) + { + PVMSVGA3DCONTEXT pContext = pState->papContexts[i]; + if (pContext->id != SVGA3D_INVALID_ID) + { + rc = vmsvga3dLoadReinitContext(pThisCC, pContext); + AssertRCReturn(rc, rc); + } + } + + LogFlow(("vmsvga3dLoadExec: return success\n")); + return VINF_SUCCESS; +} + + +static int vmsvga3dSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext) +{ + uint32_t cid = pContext->id; + + /* Save the id first. */ + int rc = pHlp->pfnSSMPutU32(pSSM, cid); + AssertRCReturn(rc, rc); + + if (cid != SVGA3D_INVALID_ID) + { + /* Save a copy of the context structure first. */ + rc = pHlp->pfnSSMPutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL); + AssertRCReturn(rc, rc); + + /* Save all pixel shaders. */ + for (uint32_t j = 0; j < pContext->cPixelShaders; j++) + { + PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j]; + + /* Save the id first. */ + rc = pHlp->pfnSSMPutU32(pSSM, pShader->id); + AssertRCReturn(rc, rc); + + if (pShader->id != SVGA3D_INVALID_ID) + { + uint32_t cbData = pShader->cbData; + + /* Save a copy of the shader struct. */ + rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL); + AssertRCReturn(rc, rc); + + Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData)); + rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData); + AssertRCReturn(rc, rc); + } + } + + /* Save all vertex shaders. */ + for (uint32_t j = 0; j < pContext->cVertexShaders; j++) + { + PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j]; + + /* Save the id first. */ + rc = pHlp->pfnSSMPutU32(pSSM, pShader->id); + AssertRCReturn(rc, rc); + + if (pShader->id != SVGA3D_INVALID_ID) + { + uint32_t cbData = pShader->cbData; + + /* Save a copy of the shader struct. */ + rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL); + AssertRCReturn(rc, rc); + + Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData)); + /* Fetch the shader code and save it. */ + rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData); + AssertRCReturn(rc, rc); + } + } + + /* Save pixel shader constants. */ + for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++) + { + rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL); + AssertRCReturn(rc, rc); + } + + /* Save vertex shader constants. */ + for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++) + { + rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL); + AssertRCReturn(rc, rc); + } + + /* Save texture stage and samplers state. */ + + /* Number of stages/samplers. */ + rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates)); + AssertRCReturn(rc, rc); + + /* Number of texture states. */ + rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates[0])); + AssertRCReturn(rc, rc); + + for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage) + { + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j) + { + SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j]; + + pHlp->pfnSSMPutU32(pSSM, pTextureState->stage); + pHlp->pfnSSMPutU32(pSSM, pTextureState->name); + rc = pHlp->pfnSSMPutU32(pSSM, pTextureState->value); + AssertRCReturn(rc, rc); + } + } + + /* Occlusion query. */ + if (!VMSVGA3DQUERY_EXISTS(&pContext->occlusion)) + { + pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL; + } + + /* Save the current query state, because code below can change it. */ + VMSVGA3DQUERYSTATE const enmQueryState = pContext->occlusion.enmQueryState; + switch (enmQueryState) + { + case VMSVGA3DQUERYSTATE_BUILDING: + /* Stop collecting data. Fetch partial result. Save result. */ + vmsvga3dQueryEnd(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION); + RT_FALL_THRU(); + case VMSVGA3DQUERYSTATE_ISSUED: + /* Fetch result. Save result. */ + pContext->occlusion.u32QueryResult = 0; + vmsvga3dQueryWait(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION, NULL, NULL); + RT_FALL_THRU(); + case VMSVGA3DQUERYSTATE_SIGNALED: + /* Save result. Nothing to do here. */ + break; + + default: + AssertFailed(); + RT_FALL_THRU(); + case VMSVGA3DQUERYSTATE_NULL: + pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL; + pContext->occlusion.u32QueryResult = 0; + break; + } + + /* Restore the current actual state. */ + pContext->occlusion.enmQueryState = enmQueryState; + + rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->occlusion, sizeof(pContext->occlusion), 0, g_aVMSVGA3DQUERYFields, NULL); + AssertRCReturn(rc, rc); + } + + return VINF_SUCCESS; +} + +int vmsvga3dSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc; + + /* Save a copy of the generic 3d state first. */ + rc = pHlp->pfnSSMPutStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL); + AssertRCReturn(rc, rc); + +#ifdef VMSVGA3D_OPENGL + /* Save the shared context. */ + if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) + { + rc = vmsvga3dSaveContext(pHlp, pThisCC, pSSM, &pState->SharedCtx); + AssertRCReturn(rc, rc); + } +#endif + + /* Save all active contexts. */ + for (uint32_t i = 0; i < pState->cContexts; i++) + { + rc = vmsvga3dSaveContext(pHlp, pThisCC, pSSM, pState->papContexts[i]); + AssertRCReturn(rc, rc); + } + + /* Save all active surfaces. */ + for (uint32_t sid = 0; sid < pState->cSurfaces; sid++) + { + PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; + + /* Save the id first. */ + rc = pHlp->pfnSSMPutU32(pSSM, pSurface->id); + AssertRCReturn(rc, rc); + + if (pSurface->id != SVGA3D_INVALID_ID) + { + /* Save a copy of the surface structure first. */ + rc = pHlp->pfnSSMPutStructEx(pSSM, pSurface, sizeof(*pSurface), 0, g_aVMSVGA3DSURFACEFields, NULL); + AssertRCReturn(rc, rc); + + /* Save the mip map level info. */ + for (uint32_t face=0; face < pSurface->cFaces; face++) + { + for (uint32_t i = 0; i < pSurface->cLevels; i++) + { + uint32_t idx = i + face * pSurface->cLevels; + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx]; + + /* Save a copy of the mip map level struct. */ + rc = pHlp->pfnSSMPutStructEx(pSSM, pMipmapLevel, sizeof(*pMipmapLevel), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL); + AssertRCReturn(rc, rc); + } + } + + /* Save the mip map level data. */ + for (uint32_t face=0; face < pSurface->cFaces; face++) + { + for (uint32_t i = 0; i < pSurface->cLevels; i++) + { + uint32_t idx = i + face * pSurface->cLevels; + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx]; + + Log(("Surface sid=%u: save mipmap level %d with %x bytes data.\n", sid, i, pMipmapLevel->cbSurface)); + + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + if (pMipmapLevel->fDirty) + { + /* Data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, true); + AssertRCReturn(rc, rc); + + Assert(pMipmapLevel->cbSurface); + rc = pHlp->pfnSSMPutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface); + AssertRCReturn(rc, rc); + } + else + { + /* No data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, false); + AssertRCReturn(rc, rc); + } + } + else if (vmsvga3dIsLegacyBackend(pThisCC)) + { +#ifdef VMSVGA3D_DIRECT3D + void *pData; + bool fRenderTargetTexture = false; + bool fTexture = false; + bool fSkipSave = false; + HRESULT hr; + + Assert(pMipmapLevel->cbSurface); + pData = RTMemAllocZ(pMipmapLevel->cbSurface); + AssertReturn(pData, VERR_NO_MEMORY); + + switch (pSurface->enmD3DResType) + { + case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE: + case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE: + AssertFailed(); /// @todo + fSkipSave = true; + break; + case VMSVGA3D_D3DRESTYPE_SURFACE: + case VMSVGA3D_D3DRESTYPE_TEXTURE: + { + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) + { + /** @todo unable to easily fetch depth surface data in d3d 9 */ + fSkipSave = true; + break; + } + + fTexture = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE); + fRenderTargetTexture = fTexture && (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET); + + D3DLOCKED_RECT LockedRect; + + if (fTexture) + { + if (pSurface->bounce.pTexture) + { + if ( !pSurface->fDirty + && fRenderTargetTexture + && i == 0 /* only the first time */) + { + IDirect3DSurface9 *pSrc, *pDest; + + /** @todo stricter checks for associated context */ + uint32_t cid = pSurface->idAssociatedContext; + + PVMSVGA3DCONTEXT pContext; + rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR); + + hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR); + + hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR); + + pSrc->Release(); + pDest->Release(); + } + + hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */ + &LockedRect, + NULL, + D3DLOCK_READONLY); + } + else + hr = pSurface->u.pTexture->LockRect(i, /* texture level */ + &LockedRect, + NULL, + D3DLOCK_READONLY); + } + else + hr = pSurface->u.pSurface->LockRect(&LockedRect, + NULL, + D3DLOCK_READONLY); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* Copy the data one line at a time in case the internal pitch is different. */ + for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; ++j) + { + uint8_t *pu8Dst = (uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch; + const uint8_t *pu8Src = (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch; + memcpy(pu8Dst, pu8Src, pMipmapLevel->cbSurfacePitch); + } + + if (fTexture) + { + if (pSurface->bounce.pTexture) + { + hr = pSurface->bounce.pTexture->UnlockRect(i); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else + hr = pSurface->u.pTexture->UnlockRect(i); + } + else + hr = pSurface->u.pSurface->UnlockRect(); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + break; + } + + case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER: + case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER: + { + /* Current type of the buffer. */ + const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER); + + uint8_t *pD3DData; + + if (fVertex) + hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY); + else + hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY); + AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr)); + + memcpy(pData, pD3DData, pMipmapLevel->cbSurface); + + if (fVertex) + hr = pSurface->u.pVertexBuffer->Unlock(); + else + hr = pSurface->u.pIndexBuffer->Unlock(); + AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr)); + break; + } + + default: + AssertFailed(); + break; + } + + if (!fSkipSave) + { + /* Data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, true); + AssertRCReturn(rc, rc); + + /* And write the surface data. */ + rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface); + AssertRCReturn(rc, rc); + } + else + { + /* No data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, false); + AssertRCReturn(rc, rc); + } + + RTMemFree(pData); + +#elif defined(VMSVGA3D_OPENGL) + void *pData = NULL; + + PVMSVGA3DCONTEXT pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); + + Assert(pMipmapLevel->cbSurface); + + switch (pSurface->enmOGLResType) + { + default: + AssertFailed(); + RT_FALL_THRU(); + case VMSVGA3D_OGLRESTYPE_RENDERBUFFER: + /** @todo fetch data from the renderbuffer. Not used currently. */ + /* No data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, false); + AssertRCReturn(rc, rc); + break; + + case VMSVGA3D_OGLRESTYPE_TEXTURE: + { + GLint activeTexture; + + pData = RTMemAllocZ(pMipmapLevel->cbSurface); + AssertReturn(pData, VERR_NO_MEMORY); + + glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + /* Set row length and alignment of the output data. */ + VMSVGAPACKPARAMS SavedParams; + vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams); + + glGetTexImage(GL_TEXTURE_2D, + i, + pSurface->formatGL, + pSurface->typeGL, + pData); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + + vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams); + + /* Data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, true); + AssertRCReturn(rc, rc); + + /* And write the surface data. */ + rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface); + AssertRCReturn(rc, rc); + + /* Restore the old active texture. */ + glBindTexture(GL_TEXTURE_2D, activeTexture); + VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext); + break; + } + + case VMSVGA3D_OGLRESTYPE_BUFFER: + { + uint8_t *pBufferData; + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + Assert(pBufferData); + + /* Data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, true); + AssertRCReturn(rc, rc); + + /* And write the surface data. */ + rc = pHlp->pfnSSMPutMem(pSSM, pBufferData, pMipmapLevel->cbSurface); + AssertRCReturn(rc, rc); + + pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0); + VMSVGA3D_CHECK_LAST_ERROR(pState, pContext); + + } + } + if (pData) + RTMemFree(pData); +#else +#error "Unexpected 3d backend" +#endif + } + else + { + /** @todo DX backend. */ + Assert(!vmsvga3dIsLegacyBackend(pThisCC)); + + /* No data follows */ + rc = pHlp->pfnSSMPutBool(pSSM, false); + AssertRCReturn(rc, rc); + } + } + } + } + } + return VINF_SUCCESS; +} + +int vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, + uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4) +{ + /* Choose a sane upper limit. */ + AssertReturn(reg < _32K, VERR_INVALID_PARAMETER); + + if (type == SVGA3D_SHADERTYPE_VS) + { + if (pContext->state.cVertexShaderConst <= reg) + { + pContext->state.paVertexShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paVertexShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1)); + AssertReturn(pContext->state.paVertexShaderConst, VERR_NO_MEMORY); + for (uint32_t i = pContext->state.cVertexShaderConst; i < reg + 1; i++) + pContext->state.paVertexShaderConst[i].fValid = false; + pContext->state.cVertexShaderConst = reg + 1; + } + + pContext->state.paVertexShaderConst[reg].fValid = true; + pContext->state.paVertexShaderConst[reg].ctype = ctype; + pContext->state.paVertexShaderConst[reg].value[0] = val1; + pContext->state.paVertexShaderConst[reg].value[1] = val2; + pContext->state.paVertexShaderConst[reg].value[2] = val3; + pContext->state.paVertexShaderConst[reg].value[3] = val4; + } + else + { + Assert(type == SVGA3D_SHADERTYPE_PS); + if (pContext->state.cPixelShaderConst <= reg) + { + pContext->state.paPixelShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paPixelShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1)); + AssertReturn(pContext->state.paPixelShaderConst, VERR_NO_MEMORY); + for (uint32_t i = pContext->state.cPixelShaderConst; i < reg + 1; i++) + pContext->state.paPixelShaderConst[i].fValid = false; + pContext->state.cPixelShaderConst = reg + 1; + } + + pContext->state.paPixelShaderConst[reg].fValid = true; + pContext->state.paPixelShaderConst[reg].ctype = ctype; + pContext->state.paPixelShaderConst[reg].value[0] = val1; + pContext->state.paPixelShaderConst[reg].value[1] = val2; + pContext->state.paPixelShaderConst[reg].value[2] = val3; + pContext->state.paPixelShaderConst[reg].value[3] = val4; + } + + return VINF_SUCCESS; +} + diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp new file mode 100644 index 00000000..c7c8e440 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp @@ -0,0 +1,1740 @@ +/* $Id: DevVGA-SVGA3d-shared.cpp $ */ +/** @file + * DevVMWare - VMWare SVGA device + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include /* required by DevVGA.h */ + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +#include "DevVGA-SVGA3d-internal.h" + + +#ifdef RT_OS_WINDOWS +# define VMSVGA3D_WNDCLASSNAME L"VMSVGA3DWNDCLS" + +static LONG WINAPI vmsvga3dWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + +/** + * Send a message to the async window thread and wait for a reply + * + * @returns VBox status code. + * @param pWindowThread Thread handle + * @param WndRequestSem Semaphore handle for waiting + * @param msg Message id + * @param wParam First parameter + * @param lParam Second parameter + */ +int vmsvga3dSendThreadMessage(RTTHREAD pWindowThread, RTSEMEVENT WndRequestSem, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int rc; + BOOL ret; + + ret = PostThreadMessage(RTThreadGetNative(pWindowThread), msg, wParam, lParam); + AssertMsgReturn(ret, ("PostThreadMessage %x failed with %d\n", RTThreadGetNative(pWindowThread), GetLastError()), VERR_INTERNAL_ERROR); + + rc = RTSemEventWait(WndRequestSem, RT_INDEFINITE_WAIT); + Assert(RT_SUCCESS(rc)); + + return rc; +} + +/** + * The async window handling thread + * + * @returns VBox status code. + * @param hThreadSelf This thread. + * @param pvUser Request sempahore handle. + */ +DECLCALLBACK(int) vmsvga3dWindowThread(RTTHREAD hThreadSelf, void *pvUser) +{ + RT_NOREF(hThreadSelf); + RTSEMEVENT WndRequestSem = (RTSEMEVENT)pvUser; + WNDCLASSEXW wc; + + /* Register our own window class. */ + wc.cbSize = sizeof(wc); + wc.style = CS_OWNDC; + wc.lpfnWndProc = (WNDPROC)vmsvga3dWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle("VBoxDD.dll"); /** @todo hardcoded name.. */ + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = VMSVGA3D_WNDCLASSNAME; + wc.hIconSm = NULL; + + if (!RegisterClassExW(&wc)) + { + Log(("RegisterClass failed with %x\n", GetLastError())); + return VERR_INTERNAL_ERROR; + } + + LogFlow(("vmsvga3dWindowThread: started loop\n")); + while (true) + { + MSG msg; + if (GetMessage(&msg, 0, 0, 0)) + { + if (msg.message == WM_VMSVGA3D_EXIT) + { + /* Signal to the caller that we're done. */ + RTSemEventSignal(WndRequestSem); + break; + } + + if (msg.message == WM_VMSVGA3D_WAKEUP) + { + continue; + } + + if (msg.message == WM_VMSVGA3D_CREATEWINDOW) + { + /* Create a context window with minimal 4x4 size. We will never use the swapchain + * to present the rendered image. Rendered images from the guest will be copied to + * the VMSVGA SCREEN object, which can be either an offscreen render target or + * system memory in the guest VRAM. */ + HWND *phWnd = (HWND *)msg.wParam; + HWND hWnd; + *phWnd = hWnd = CreateWindowExW(WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY, + VMSVGA3D_WNDCLASSNAME, + NULL /*pwszName*/, + WS_DISABLED, + 0 /*x*/, + 0 /*y*/, + 4 /*cx*/, + 4 /*cy*/, + HWND_DESKTOP /*hwndParent*/, + NULL /*hMenu*/, + (HINSTANCE)msg.lParam /*hInstance*/, + NULL /*WM_CREATE param*/); + AssertMsg(hWnd, ("CreateWindowEx %ls, WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY, WS_DISABLED, (0,0)(4,4), HWND_DESKTOP hInstance=%p -> error=%x\n", + VMSVGA3D_WNDCLASSNAME, msg.lParam, GetLastError())); + +#ifdef VBOX_STRICT + /* Must have a non-zero client rectangle! */ + RECT ClientRect; + GetClientRect(hWnd, &ClientRect); + Assert(ClientRect.right > ClientRect.left); + Assert(ClientRect.bottom > ClientRect.top); +#endif + + /* Signal to the caller that we're done. */ + RTSemEventSignal(WndRequestSem); + continue; + } + + if (msg.message == WM_VMSVGA3D_DESTROYWINDOW) + { + BOOL fRc = DestroyWindow((HWND)msg.wParam); + Assert(fRc); NOREF(fRc); + + /* Signal to the caller that we're done. */ + RTSemEventSignal(WndRequestSem); + continue; + } + +#if 0 /* in case CreateDeviceEx fails again and we want to eliminat wrong-thread. */ + if (msg.message == WM_VMSVGA3D_CREATE_DEVICE) + { + VMSVGA3DCREATEDEVICEPARAMS *pParams = (VMSVGA3DCREATEDEVICEPARAMS *)msg.lParam; + pParams->hrc = pParams->pState->pD3D9->CreateDeviceEx(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + pParams->pContext->hwnd, + D3DCREATE_MULTITHREADED | D3DCREATE_MIXED_VERTEXPROCESSING, //D3DCREATE_HARDWARE_VERTEXPROCESSING, + pParams->pPresParams, + NULL, + &pParams->pContext->pDevice); + AssertMsg(pParams->hrc == D3D_OK, ("WM_VMSVGA3D_CREATE_DEVICE: CreateDevice failed with %x\n", pParams->hrc)); + + RTSemEventSignal(WndRequestSem); + continue; + } +#endif + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + { + Log(("GetMessage failed with %x\n", GetLastError())); + break; + } + } + + Log(("vmsvga3dWindowThread: end loop\n")); + return VINF_SUCCESS; +} + +/* Window procedure for our top level window overlays. */ +static LONG WINAPI vmsvga3dWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_CREATE: + { + /* Ditch the title bar (caption) to avoid having a zero height + client area as that makes IDirect3D9Ex::CreateDeviceEx fail. + For the style adjustment to take place, we must apply the + SWP_FRAMECHANGED thru SetWindowPos. */ + LONG flStyle = GetWindowLongW(hwnd, GWL_STYLE); + flStyle &= ~(WS_CAPTION /* both titlebar and border. Some paranoia: */ | WS_THICKFRAME | WS_SYSMENU); + SetWindowLong(hwnd, GWL_STYLE, flStyle); + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER); + break; + } + + case WM_CLOSE: + Log7(("vmsvga3dWndProc(%p): WM_CLOSE\n", hwnd)); + break; + + case WM_DESTROY: + Log7(("vmsvga3dWndProc(%p): WM_DESTROY\n", hwnd)); + break; + + case WM_NCHITTEST: + Log7(("vmsvga3dWndProc(%p): WM_NCHITTEST\n", hwnd)); + return HTNOWHERE; + +# if 0 /* flicker experiment, no help here. */ + case WM_PAINT: + Log7(("vmsvga3dWndProc(%p): WM_PAINT %p %p\n", hwnd, wParam, lParam)); + ValidateRect(hwnd, NULL); + return 0; + case WM_ERASEBKGND: + Log7(("vmsvga3dWndProc(%p): WM_ERASEBKGND %p %p\n", hwnd, wParam, lParam)); + return TRUE; + case WM_NCPAINT: + Log7(("vmsvga3dWndProc(%p): WM_NCPAINT %p %p\n", hwnd, wParam, lParam)); + break; + case WM_WINDOWPOSCHANGING: + { + PWINDOWPOS pPos = (PWINDOWPOS)lParam; + Log7(("vmsvga3dWndProc(%p): WM_WINDOWPOSCHANGING %p %p pos=(%d,%d) size=(%d,%d) flags=%#x\n", + hwnd, wParam, lParam, pPos->x, pPos->y, pPos->cx, pPos->cy, pPos->flags)); + break; + } + case WM_WINDOWPOSCHANGED: + { + PWINDOWPOS pPos = (PWINDOWPOS)lParam; + Log7(("vmsvga3dWndProc(%p): WM_WINDOWPOSCHANGED %p %p pos=(%d,%d) size=(%d,%d) flags=%#x\n", + hwnd, wParam, lParam, pPos->x, pPos->y, pPos->cx, pPos->cy, pPos->flags)); + break; + } + case WM_MOVE: + Log7(("vmsvga3dWndProc(%p): WM_MOVE %p %p\n", hwnd, wParam, lParam)); + break; + case WM_SIZE: + Log7(("vmsvga3dWndProc(%p): WM_SIZE %p %p\n", hwnd, wParam, lParam)); + break; + + default: + Log7(("vmsvga3dWndProc(%p): %#x %p %p\n", hwnd, uMsg, wParam, lParam)); +# endif + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +int vmsvga3dContextWindowCreate(HINSTANCE hInstance, RTTHREAD pWindowThread, RTSEMEVENT WndRequestSem, HWND *pHwnd) +{ + return vmsvga3dSendThreadMessage(pWindowThread, WndRequestSem, WM_VMSVGA3D_CREATEWINDOW, (WPARAM)pHwnd, (LPARAM)hInstance); +} + +#endif /* RT_OS_WINDOWS */ + + +/** + * Calculate the size and dimensions of one block. + */ +uint32_t vmsvga3dSurfaceFormatSize(SVGA3dSurfaceFormat format, + uint32_t *pcxBlock, + uint32_t *pcyBlock) +{ + uint32_t u32 = 0; + if (!pcxBlock) pcxBlock = &u32; + if (!pcyBlock) pcyBlock = &u32; + + switch (format) + { + case SVGA3D_X8R8G8B8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_A8R8G8B8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R5G6B5: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_X1R5G5B5: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_A1R5G5B5: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_A4R4G4B4: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_Z_D32: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_Z_D16: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_Z_D24S8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_Z_D15S1: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_LUMINANCE8: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_LUMINANCE4_ALPHA4: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_LUMINANCE16: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_LUMINANCE8_ALPHA8: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_DXT1: + *pcxBlock = 4; + *pcyBlock = 4; + return 8; + + case SVGA3D_DXT2: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_DXT3: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_DXT4: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_DXT5: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BUMPU8V8: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_BUMPL6V5U5: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_BUMPX8L8V8U8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_FORMAT_DEAD1: + *pcxBlock = 1; + *pcyBlock = 1; + return 3; + + case SVGA3D_ARGB_S10E5: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_ARGB_S23E8: + *pcxBlock = 1; + *pcyBlock = 1; + return 16; + + case SVGA3D_A2R10G10B10: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_V8U8: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_Q8W8V8U8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_CxV8U8: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_X8L8V8U8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_A2W10V10U10: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_ALPHA8: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_R_S10E5: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R_S23E8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_RG_S10E5: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_RG_S23E8: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_BUFFER: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_Z_D24X8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_V16U16: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_G16R16: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_A16B16G16R16: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_UYVY: + *pcxBlock = 2; + *pcyBlock = 1; + return 4; + + case SVGA3D_YUY2: + *pcxBlock = 2; + *pcyBlock = 1; + return 4; + + case SVGA3D_NV12: + *pcxBlock = 2; + *pcyBlock = 2; + return 6; + + case SVGA3D_FORMAT_DEAD2: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R32G32B32A32_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 16; + + case SVGA3D_R32G32B32A32_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 16; + + case SVGA3D_R32G32B32A32_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 16; + + case SVGA3D_R32G32B32_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 12; + + case SVGA3D_R32G32B32_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 12; + + case SVGA3D_R32G32B32_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 12; + + case SVGA3D_R32G32B32_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 12; + + case SVGA3D_R16G16B16A16_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R16G16B16A16_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R16G16B16A16_SNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R16G16B16A16_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R32G32_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R32G32_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R32G32_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R32G8X24_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_D32_FLOAT_S8X24_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R32_FLOAT_X8X24: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_X32_G8X24_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R10G10B10A2_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R10G10B10A2_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R11G11B10_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8B8A8_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8B8A8_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8B8A8_UNORM_SRGB: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8B8A8_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8B8A8_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R16G16_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R16G16_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R16G16_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R32_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_D32_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R32_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R32_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R24G8_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_D24_UNORM_S8_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R24_UNORM_X8: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_X24_G8_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R8G8_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R8G8_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R8G8_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R16_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R16_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R16_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R16_SNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R16_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R8_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_R8_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_R8_UINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_R8_SNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_R8_SINT: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_P8: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_R9G9B9E5_SHAREDEXP: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8_B8G8_UNORM: + *pcxBlock = 2; + *pcyBlock = 1; + return 4; + + case SVGA3D_G8R8_G8B8_UNORM: + *pcxBlock = 2; + *pcyBlock = 1; + return 4; + + case SVGA3D_BC1_TYPELESS: + *pcxBlock = 4; + *pcyBlock = 4; + return 8; + + case SVGA3D_BC1_UNORM_SRGB: + *pcxBlock = 4; + *pcyBlock = 4; + return 8; + + case SVGA3D_BC2_TYPELESS: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC2_UNORM_SRGB: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC3_TYPELESS: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC3_UNORM_SRGB: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC4_TYPELESS: + *pcxBlock = 4; + *pcyBlock = 4; + return 8; + + case SVGA3D_ATI1: + *pcxBlock = 4; + *pcyBlock = 4; + return 8; + + case SVGA3D_BC4_SNORM: + *pcxBlock = 4; + *pcyBlock = 4; + return 8; + + case SVGA3D_BC5_TYPELESS: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_ATI2: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC5_SNORM: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_R10G10B10_XR_BIAS_A2_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_B8G8R8A8_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_B8G8R8A8_UNORM_SRGB: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_B8G8R8X8_TYPELESS: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_B8G8R8X8_UNORM_SRGB: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_Z_DF16: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_Z_DF24: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_Z_D24S8_INT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_YV12: + *pcxBlock = 2; + *pcyBlock = 2; + return 6; + + case SVGA3D_R32G32B32A32_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 16; + + case SVGA3D_R16G16B16A16_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R16G16B16A16_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R32G32_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 8; + + case SVGA3D_R10G10B10A2_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8B8A8_SNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R16G16_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R16G16_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R16G16_SNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R32_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_R8G8_SNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_R16_FLOAT: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_D16_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_A8_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 1; + + case SVGA3D_BC1_UNORM: + *pcxBlock = 4; + *pcyBlock = 4; + return 8; + + case SVGA3D_BC2_UNORM: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC3_UNORM: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_B5G6R5_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_B5G5R5A1_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_B8G8R8A8_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_B8G8R8X8_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + case SVGA3D_BC4_UNORM: + *pcxBlock = 4; + *pcyBlock = 4; + return 8; + + case SVGA3D_BC5_UNORM: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_B4G4R4A4_UNORM: + *pcxBlock = 1; + *pcyBlock = 1; + return 2; + + case SVGA3D_BC6H_TYPELESS: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC6H_UF16: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC6H_SF16: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC7_TYPELESS: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC7_UNORM: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_BC7_UNORM_SRGB: + *pcxBlock = 4; + *pcyBlock = 4; + return 16; + + case SVGA3D_AYUV: + *pcxBlock = 1; + *pcyBlock = 1; + return 4; + + default: + *pcxBlock = 1; + *pcyBlock = 1; + AssertFailedReturn(4); + } +} + +#ifdef LOG_ENABLED + +const char *vmsvga3dGetCapString(uint32_t idxCap) +{ + switch (idxCap) + { + case SVGA3D_DEVCAP_3D: + return "SVGA3D_DEVCAP_3D"; + case SVGA3D_DEVCAP_MAX_LIGHTS: + return "SVGA3D_DEVCAP_MAX_LIGHTS"; + case SVGA3D_DEVCAP_MAX_TEXTURES: + return "SVGA3D_DEVCAP_MAX_TEXTURES"; + case SVGA3D_DEVCAP_MAX_CLIP_PLANES: + return "SVGA3D_DEVCAP_MAX_CLIP_PLANES"; + case SVGA3D_DEVCAP_VERTEX_SHADER_VERSION: + return "SVGA3D_DEVCAP_VERTEX_SHADER_VERSION"; + case SVGA3D_DEVCAP_VERTEX_SHADER: + return "SVGA3D_DEVCAP_VERTEX_SHADER"; + case SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION: + return "SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION"; + case SVGA3D_DEVCAP_FRAGMENT_SHADER: + return "SVGA3D_DEVCAP_FRAGMENT_SHADER"; + case SVGA3D_DEVCAP_MAX_RENDER_TARGETS: + return "SVGA3D_DEVCAP_MAX_RENDER_TARGETS"; + case SVGA3D_DEVCAP_S23E8_TEXTURES: + return "SVGA3D_DEVCAP_S23E8_TEXTURES"; + case SVGA3D_DEVCAP_S10E5_TEXTURES: + return "SVGA3D_DEVCAP_S10E5_TEXTURES"; + case SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND: + return "SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND"; + case SVGA3D_DEVCAP_D16_BUFFER_FORMAT: + return "SVGA3D_DEVCAP_D16_BUFFER_FORMAT"; + case SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT: + return "SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT"; + case SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT: + return "SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT"; + case SVGA3D_DEVCAP_QUERY_TYPES: + return "SVGA3D_DEVCAP_QUERY_TYPES"; + case SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING: + return "SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING"; + case SVGA3D_DEVCAP_MAX_POINT_SIZE: + return "SVGA3D_DEVCAP_MAX_POINT_SIZE"; + case SVGA3D_DEVCAP_MAX_SHADER_TEXTURES: + return "SVGA3D_DEVCAP_MAX_SHADER_TEXTURES"; + case SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH: + return "SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH"; + case SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT: + return "SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT"; + case SVGA3D_DEVCAP_MAX_VOLUME_EXTENT: + return "SVGA3D_DEVCAP_MAX_VOLUME_EXTENT"; + case SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT: + return "SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT"; + case SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO: + return "SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO"; + case SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY: + return "SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY"; + case SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT: + return "SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT"; + case SVGA3D_DEVCAP_MAX_VERTEX_INDEX: + return "SVGA3D_DEVCAP_MAX_VERTEX_INDEX"; + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS: + return "SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS"; + case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS: + return "SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS"; + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS: + return "SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS"; + case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS: + return "SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS"; + case SVGA3D_DEVCAP_TEXTURE_OPS: + return "SVGA3D_DEVCAP_TEXTURE_OPS"; + case SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */ + return "SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES"; + case SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */ + return "SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES"; + case SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */ + return "SVGA3D_DEVCAP_ALPHATOCOVERAGE"; + case SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */ + return "SVGA3D_DEVCAP_SUPERSAMPLE"; + case SVGA3D_DEVCAP_AUTOGENMIPMAPS: + return "SVGA3D_DEVCAP_AUTOGENMIPMAPS"; + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES: + return "SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES"; + case SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS: + return "SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS"; + case SVGA3D_DEVCAP_MAX_CONTEXT_IDS: + return "SVGA3D_DEVCAP_MAX_CONTEXT_IDS"; + case SVGA3D_DEVCAP_MAX_SURFACE_IDS: + return "SVGA3D_DEVCAP_MAX_SURFACE_IDS"; + case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: + return "SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8"; + case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: + return "SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8"; + case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: + return "SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10"; + case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: + return "SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5"; + case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: + return "SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5"; + case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: + return "SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4"; + case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: + return "SVGA3D_DEVCAP_SURFACEFMT_R5G6B5"; + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: + return "SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16"; + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: + return "SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8"; + case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: + return "SVGA3D_DEVCAP_SURFACEFMT_ALPHA8"; + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: + return "SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8"; + case SVGA3D_DEVCAP_SURFACEFMT_Z_D16: + return "SVGA3D_DEVCAP_SURFACEFMT_Z_D16"; + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: + return "SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8"; + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: + return "SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8"; + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: + return "SVGA3D_DEVCAP_SURFACEFMT_Z_DF16"; + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: + return "SVGA3D_DEVCAP_SURFACEFMT_Z_DF24"; + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: + return "SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT"; + case SVGA3D_DEVCAP_SURFACEFMT_DXT1: + return "SVGA3D_DEVCAP_SURFACEFMT_DXT1"; + case SVGA3D_DEVCAP_SURFACEFMT_DXT2: + return "SVGA3D_DEVCAP_SURFACEFMT_DXT2"; + case SVGA3D_DEVCAP_SURFACEFMT_DXT3: + return "SVGA3D_DEVCAP_SURFACEFMT_DXT3"; + case SVGA3D_DEVCAP_SURFACEFMT_DXT4: + return "SVGA3D_DEVCAP_SURFACEFMT_DXT4"; + case SVGA3D_DEVCAP_SURFACEFMT_DXT5: + return "SVGA3D_DEVCAP_SURFACEFMT_DXT5"; + case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: + return "SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8"; + case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: + return "SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10"; + case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: + return "SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8"; + case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: + return "SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8"; + case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: + return "SVGA3D_DEVCAP_SURFACEFMT_CxV8U8"; + case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: + return "SVGA3D_DEVCAP_SURFACEFMT_R_S10E5"; + case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: + return "SVGA3D_DEVCAP_SURFACEFMT_R_S23E8"; + case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: + return "SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5"; + case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: + return "SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8"; + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: + return "SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5"; + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: + return "SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8"; + case SVGA3D_DEVCAP_SURFACEFMT_V16U16: + return "SVGA3D_DEVCAP_SURFACEFMT_V16U16"; + case SVGA3D_DEVCAP_SURFACEFMT_G16R16: + return "SVGA3D_DEVCAP_SURFACEFMT_G16R16"; + case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: + return "SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16"; + case SVGA3D_DEVCAP_SURFACEFMT_UYVY: + return "SVGA3D_DEVCAP_SURFACEFMT_UYVY"; + case SVGA3D_DEVCAP_SURFACEFMT_YUY2: + return "SVGA3D_DEVCAP_SURFACEFMT_YUY2"; + case SVGA3D_DEVCAP_SURFACEFMT_NV12: + return "SVGA3D_DEVCAP_SURFACEFMT_NV12"; + case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */ + return "SVGA3D_DEVCAP_SURFACEFMT_AYUV"; + case SVGA3D_DEVCAP_SURFACEFMT_ATI1: + return "SVGA3D_DEVCAP_SURFACEFMT_ATI1"; + case SVGA3D_DEVCAP_SURFACEFMT_ATI2: + return "SVGA3D_DEVCAP_SURFACEFMT_ATI2"; + default: + return "UNEXPECTED"; + } +} + +const char *vmsvga3dGet3dFormatString(uint32_t format) +{ + static char szFormat[1024]; + + szFormat[0] = 0; + + if (format & SVGA3DFORMAT_OP_TEXTURE) + strcat(szFormat, " - SVGA3DFORMAT_OP_TEXTURE\n"); + if (format & SVGA3DFORMAT_OP_VOLUMETEXTURE) + strcat(szFormat, " - SVGA3DFORMAT_OP_VOLUMETEXTURE\n"); + if (format & SVGA3DFORMAT_OP_CUBETEXTURE) + strcat(szFormat, " - SVGA3DFORMAT_OP_CUBETEXTURE\n"); + if (format & SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET) + strcat(szFormat, " - SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET\n"); + if (format & SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET) + strcat(szFormat, " - SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET\n"); + if (format & SVGA3DFORMAT_OP_ZSTENCIL) + strcat(szFormat, " - SVGA3DFORMAT_OP_ZSTENCIL\n"); + if (format & SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH) + strcat(szFormat, " - SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH\n"); + if (format & SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET) + strcat(szFormat, " - SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET\n"); + if (format & SVGA3DFORMAT_OP_DISPLAYMODE) + strcat(szFormat, " - SVGA3DFORMAT_OP_DISPLAYMODE\n"); + if (format & SVGA3DFORMAT_OP_3DACCELERATION) + strcat(szFormat, " - SVGA3DFORMAT_OP_3DACCELERATION\n"); + if (format & SVGA3DFORMAT_OP_PIXELSIZE) + strcat(szFormat, " - SVGA3DFORMAT_OP_PIXELSIZE\n"); + if (format & SVGA3DFORMAT_OP_CONVERT_TO_ARGB) + strcat(szFormat, " - SVGA3DFORMAT_OP_CONVERT_TO_ARGB\n"); + if (format & SVGA3DFORMAT_OP_OFFSCREENPLAIN) + strcat(szFormat, " - SVGA3DFORMAT_OP_OFFSCREENPLAIN\n"); + if (format & SVGA3DFORMAT_OP_SRGBREAD) + strcat(szFormat, " - SVGA3DFORMAT_OP_SRGBREAD\n"); + if (format & SVGA3DFORMAT_OP_BUMPMAP) + strcat(szFormat, " - SVGA3DFORMAT_OP_BUMPMAP\n"); + if (format & SVGA3DFORMAT_OP_DMAP) + strcat(szFormat, " - SVGA3DFORMAT_OP_DMAP\n"); + if (format & SVGA3DFORMAT_OP_NOFILTER) + strcat(szFormat, " - SVGA3DFORMAT_OP_NOFILTER\n"); + if (format & SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB) + strcat(szFormat, " - SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB\n"); + if (format & SVGA3DFORMAT_OP_SRGBWRITE) + strcat(szFormat, " - SVGA3DFORMAT_OP_SRGBWRITE\n"); + if (format & SVGA3DFORMAT_OP_NOALPHABLEND) + strcat(szFormat, " - SVGA3DFORMAT_OP_NOALPHABLEND\n"); + if (format & SVGA3DFORMAT_OP_AUTOGENMIPMAP) + strcat(szFormat, " - SVGA3DFORMAT_OP_AUTOGENMIPMAP\n"); + if (format & SVGA3DFORMAT_OP_VERTEXTEXTURE) + strcat(szFormat, " - SVGA3DFORMAT_OP_VERTEXTEXTURE\n"); + if (format & SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP) + strcat(szFormat, " - SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP\n"); + return szFormat; +} + +const char *vmsvga3dGetRenderStateName(uint32_t state) +{ + switch (state) + { + case SVGA3D_RS_ZENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_ZENABLE"; + case SVGA3D_RS_ZWRITEENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_ZWRITEENABLE"; + case SVGA3D_RS_ALPHATESTENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_ALPHATESTENABLE"; + case SVGA3D_RS_DITHERENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_DITHERENABLE"; + case SVGA3D_RS_BLENDENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_BLENDENABLE"; + case SVGA3D_RS_FOGENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_FOGENABLE"; + case SVGA3D_RS_SPECULARENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_SPECULARENABLE"; + case SVGA3D_RS_STENCILENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_STENCILENABLE"; + case SVGA3D_RS_LIGHTINGENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_LIGHTINGENABLE"; + case SVGA3D_RS_NORMALIZENORMALS: /* SVGA3dBool */ + return "SVGA3D_RS_NORMALIZENORMALS"; + case SVGA3D_RS_POINTSPRITEENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_POINTSPRITEENABLE"; + case SVGA3D_RS_POINTSCALEENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_POINTSCALEENABLE"; + case SVGA3D_RS_STENCILREF: /* uint32_t */ + return "SVGA3D_RS_STENCILREF"; + case SVGA3D_RS_STENCILMASK: /* uint32_t */ + return "SVGA3D_RS_STENCILMASK"; + case SVGA3D_RS_STENCILWRITEMASK: /* uint32_t */ + return "SVGA3D_RS_STENCILWRITEMASK"; + case SVGA3D_RS_POINTSIZE: /* float */ + return "SVGA3D_RS_POINTSIZE"; + case SVGA3D_RS_POINTSIZEMIN: /* float */ + return "SVGA3D_RS_POINTSIZEMIN"; + case SVGA3D_RS_POINTSIZEMAX: /* float */ + return "SVGA3D_RS_POINTSIZEMAX"; + case SVGA3D_RS_POINTSCALE_A: /* float */ + return "SVGA3D_RS_POINTSCALE_A"; + case SVGA3D_RS_POINTSCALE_B: /* float */ + return "SVGA3D_RS_POINTSCALE_B"; + case SVGA3D_RS_POINTSCALE_C: /* float */ + return "SVGA3D_RS_POINTSCALE_C"; + case SVGA3D_RS_AMBIENT: /* SVGA3dColor - identical */ + return "SVGA3D_RS_AMBIENT"; + case SVGA3D_RS_CLIPPLANEENABLE: /* SVGA3dClipPlanes - identical */ + return "SVGA3D_RS_CLIPPLANEENABLE"; + case SVGA3D_RS_FOGCOLOR: /* SVGA3dColor - identical */ + return "SVGA3D_RS_FOGCOLOR"; + case SVGA3D_RS_FOGSTART: /* float */ + return "SVGA3D_RS_FOGSTART"; + case SVGA3D_RS_FOGEND: /* float */ + return "SVGA3D_RS_FOGEND"; + case SVGA3D_RS_FOGDENSITY: /* float */ + return "SVGA3D_RS_FOGDENSITY"; + case SVGA3D_RS_RANGEFOGENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_RANGEFOGENABLE"; + case SVGA3D_RS_FOGMODE: /* SVGA3dFogMode */ + return "SVGA3D_RS_FOGMODE"; + case SVGA3D_RS_FILLMODE: /* SVGA3dFillMode */ + return "SVGA3D_RS_FILLMODE"; + case SVGA3D_RS_SHADEMODE: /* SVGA3dShadeMode */ + return "SVGA3D_RS_SHADEMODE"; + case SVGA3D_RS_LINEPATTERN: /* SVGA3dLinePattern */ + return "SVGA3D_RS_LINEPATTERN"; + case SVGA3D_RS_SRCBLEND: /* SVGA3dBlendOp */ + return "SVGA3D_RS_SRCBLEND"; + case SVGA3D_RS_DSTBLEND: /* SVGA3dBlendOp */ + return "SVGA3D_RS_DSTBLEND"; + case SVGA3D_RS_BLENDEQUATION: /* SVGA3dBlendEquation */ + return "SVGA3D_RS_BLENDEQUATION"; + case SVGA3D_RS_CULLMODE: /* SVGA3dFace */ + return "SVGA3D_RS_CULLMODE"; + case SVGA3D_RS_ZFUNC: /* SVGA3dCmpFunc */ + return "SVGA3D_RS_ZFUNC"; + case SVGA3D_RS_ALPHAFUNC: /* SVGA3dCmpFunc */ + return "SVGA3D_RS_ALPHAFUNC"; + case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc */ + return "SVGA3D_RS_STENCILFUNC"; + case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp */ + return "SVGA3D_RS_STENCILFAIL"; + case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp */ + return "SVGA3D_RS_STENCILZFAIL"; + case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp */ + return "SVGA3D_RS_STENCILPASS"; + case SVGA3D_RS_ALPHAREF: /* float (0.0 .. 1.0) */ + return "SVGA3D_RS_ALPHAREF"; + case SVGA3D_RS_FRONTWINDING: /* SVGA3dFrontWinding */ + return "SVGA3D_RS_FRONTWINDING"; + case SVGA3D_RS_COORDINATETYPE: /* SVGA3dCoordinateType */ + return "SVGA3D_RS_COORDINATETYPE"; + case SVGA3D_RS_ZBIAS: /* float */ + return "SVGA3D_RS_ZBIAS"; + case SVGA3D_RS_COLORWRITEENABLE: /* SVGA3dColorMask */ + return "SVGA3D_RS_COLORWRITEENABLE"; + case SVGA3D_RS_VERTEXMATERIALENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_VERTEXMATERIALENABLE"; + case SVGA3D_RS_DIFFUSEMATERIALSOURCE: /* SVGA3dVertexMaterial */ + return "SVGA3D_RS_DIFFUSEMATERIALSOURCE"; + case SVGA3D_RS_SPECULARMATERIALSOURCE: /* SVGA3dVertexMaterial */ + return "SVGA3D_RS_SPECULARMATERIALSOURCE"; + case SVGA3D_RS_AMBIENTMATERIALSOURCE: /* SVGA3dVertexMaterial */ + return "SVGA3D_RS_AMBIENTMATERIALSOURCE"; + case SVGA3D_RS_EMISSIVEMATERIALSOURCE: /* SVGA3dVertexMaterial */ + return "SVGA3D_RS_EMISSIVEMATERIALSOURCE"; + case SVGA3D_RS_TEXTUREFACTOR: /* SVGA3dColor */ + return "SVGA3D_RS_TEXTUREFACTOR"; + case SVGA3D_RS_LOCALVIEWER: /* SVGA3dBool */ + return "SVGA3D_RS_LOCALVIEWER"; + case SVGA3D_RS_SCISSORTESTENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_SCISSORTESTENABLE"; + case SVGA3D_RS_BLENDCOLOR: /* SVGA3dColor */ + return "SVGA3D_RS_BLENDCOLOR"; + case SVGA3D_RS_STENCILENABLE2SIDED: /* SVGA3dBool */ + return "SVGA3D_RS_STENCILENABLE2SIDED"; + case SVGA3D_RS_CCWSTENCILFUNC: /* SVGA3dCmpFunc */ + return "SVGA3D_RS_CCWSTENCILFUNC"; + case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp */ + return "SVGA3D_RS_CCWSTENCILFAIL"; + case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp */ + return "SVGA3D_RS_CCWSTENCILZFAIL"; + case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp */ + return "SVGA3D_RS_CCWSTENCILPASS"; + case SVGA3D_RS_VERTEXBLEND: /* SVGA3dVertexBlendFlags */ + return "SVGA3D_RS_VERTEXBLEND"; + case SVGA3D_RS_SLOPESCALEDEPTHBIAS: /* float */ + return "SVGA3D_RS_SLOPESCALEDEPTHBIAS"; + case SVGA3D_RS_DEPTHBIAS: /* float */ + return "SVGA3D_RS_DEPTHBIAS"; + case SVGA3D_RS_OUTPUTGAMMA: /* float */ + return "SVGA3D_RS_OUTPUTGAMMA"; + case SVGA3D_RS_ZVISIBLE: /* SVGA3dBool */ + return "SVGA3D_RS_ZVISIBLE"; + case SVGA3D_RS_LASTPIXEL: /* SVGA3dBool */ + return "SVGA3D_RS_LASTPIXEL"; + case SVGA3D_RS_CLIPPING: /* SVGA3dBool */ + return "SVGA3D_RS_CLIPPING"; + case SVGA3D_RS_WRAP0: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP0"; + case SVGA3D_RS_WRAP1: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP1"; + case SVGA3D_RS_WRAP2: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP2"; + case SVGA3D_RS_WRAP3: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP3"; + case SVGA3D_RS_WRAP4: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP4"; + case SVGA3D_RS_WRAP5: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP5"; + case SVGA3D_RS_WRAP6: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP6"; + case SVGA3D_RS_WRAP7: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP7"; + case SVGA3D_RS_WRAP8: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP8"; + case SVGA3D_RS_WRAP9: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP9"; + case SVGA3D_RS_WRAP10: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP10"; + case SVGA3D_RS_WRAP11: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP11"; + case SVGA3D_RS_WRAP12: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP12"; + case SVGA3D_RS_WRAP13: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP13"; + case SVGA3D_RS_WRAP14: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP14"; + case SVGA3D_RS_WRAP15: /* SVGA3dWrapFlags */ + return "SVGA3D_RS_WRAP15"; + case SVGA3D_RS_MULTISAMPLEANTIALIAS: /* SVGA3dBool */ + return "SVGA3D_RS_MULTISAMPLEANTIALIAS"; + case SVGA3D_RS_MULTISAMPLEMASK: /* uint32_t */ + return "SVGA3D_RS_MULTISAMPLEMASK"; + case SVGA3D_RS_INDEXEDVERTEXBLENDENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_INDEXEDVERTEXBLENDENABLE"; + case SVGA3D_RS_TWEENFACTOR: /* float */ + return "SVGA3D_RS_TWEENFACTOR"; + case SVGA3D_RS_ANTIALIASEDLINEENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_ANTIALIASEDLINEENABLE"; + case SVGA3D_RS_COLORWRITEENABLE1: /* SVGA3dColorMask */ + return "SVGA3D_RS_COLORWRITEENABLE1"; + case SVGA3D_RS_COLORWRITEENABLE2: /* SVGA3dColorMask */ + return "SVGA3D_RS_COLORWRITEENABLE2"; + case SVGA3D_RS_COLORWRITEENABLE3: /* SVGA3dColorMask */ + return "SVGA3D_RS_COLORWRITEENABLE3"; + case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */ + return "SVGA3D_RS_SEPARATEALPHABLENDENABLE"; + case SVGA3D_RS_SRCBLENDALPHA: /* SVGA3dBlendOp */ + return "SVGA3D_RS_SRCBLENDALPHA"; + case SVGA3D_RS_DSTBLENDALPHA: /* SVGA3dBlendOp */ + return "SVGA3D_RS_DSTBLENDALPHA"; + case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation */ + return "SVGA3D_RS_BLENDEQUATIONALPHA"; + case SVGA3D_RS_TRANSPARENCYANTIALIAS: /* SVGA3dTransparencyAntialiasType */ + return "SVGA3D_RS_TRANSPARENCYANTIALIAS"; + case SVGA3D_RS_LINEWIDTH: /* float */ + return "SVGA3D_RS_LINEWIDTH"; + default: + return "UNKNOWN"; + } +} + +const char *vmsvga3dTextureStateToString(SVGA3dTextureStateName textureState) +{ + switch (textureState) + { + case SVGA3D_TS_BIND_TEXTURE: + return "SVGA3D_TS_BIND_TEXTURE"; + case SVGA3D_TS_COLOROP: + return "SVGA3D_TS_COLOROP"; + case SVGA3D_TS_COLORARG1: + return "SVGA3D_TS_COLORARG1"; + case SVGA3D_TS_COLORARG2: + return "SVGA3D_TS_COLORARG2"; + case SVGA3D_TS_ALPHAOP: + return "SVGA3D_TS_ALPHAOP"; + case SVGA3D_TS_ALPHAARG1: + return "SVGA3D_TS_ALPHAARG1"; + case SVGA3D_TS_ALPHAARG2: + return "SVGA3D_TS_ALPHAARG2"; + case SVGA3D_TS_ADDRESSU: + return "SVGA3D_TS_ADDRESSU"; + case SVGA3D_TS_ADDRESSV: + return "SVGA3D_TS_ADDRESSV"; + case SVGA3D_TS_MIPFILTER: + return "SVGA3D_TS_MIPFILTER"; + case SVGA3D_TS_MAGFILTER: + return "SVGA3D_TS_MAGFILTER"; + case SVGA3D_TS_MINFILTER: + return "SVGA3D_TS_MINFILTER"; + case SVGA3D_TS_BORDERCOLOR: + return "SVGA3D_TS_BORDERCOLOR"; + case SVGA3D_TS_TEXCOORDINDEX: + return "SVGA3D_TS_TEXCOORDINDEX"; + case SVGA3D_TS_TEXTURETRANSFORMFLAGS: + return "SVGA3D_TS_TEXTURETRANSFORMFLAGS"; + case SVGA3D_TS_TEXCOORDGEN: + return "SVGA3D_TS_TEXCOORDGEN"; + case SVGA3D_TS_BUMPENVMAT00: + return "SVGA3D_TS_BUMPENVMAT00"; + case SVGA3D_TS_BUMPENVMAT01: + return "SVGA3D_TS_BUMPENVMAT01"; + case SVGA3D_TS_BUMPENVMAT10: + return "SVGA3D_TS_BUMPENVMAT10"; + case SVGA3D_TS_BUMPENVMAT11: + return "SVGA3D_TS_BUMPENVMAT11"; + case SVGA3D_TS_TEXTURE_MIPMAP_LEVEL: + return "SVGA3D_TS_TEXTURE_MIPMAP_LEVEL"; + case SVGA3D_TS_TEXTURE_LOD_BIAS: + return "SVGA3D_TS_TEXTURE_LOD_BIAS"; + case SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL: + return "SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL"; + case SVGA3D_TS_ADDRESSW: + return "SVGA3D_TS_ADDRESSW"; + case SVGA3D_TS_GAMMA: + return "SVGA3D_TS_GAMMA"; + case SVGA3D_TS_BUMPENVLSCALE: + return "SVGA3D_TS_BUMPENVLSCALE"; + case SVGA3D_TS_BUMPENVLOFFSET: + return "SVGA3D_TS_BUMPENVLOFFSET"; + case SVGA3D_TS_COLORARG0: + return "SVGA3D_TS_COLORARG0"; + case SVGA3D_TS_ALPHAARG0: + return "SVGA3D_TS_ALPHAARG0"; + default: + return "UNKNOWN"; + } +} + +const char *vmsvgaTransformToString(SVGA3dTransformType type) +{ + switch (type) + { + case SVGA3D_TRANSFORM_INVALID: + return "SVGA3D_TRANSFORM_INVALID"; + case SVGA3D_TRANSFORM_WORLD: + return "SVGA3D_TRANSFORM_WORLD"; + case SVGA3D_TRANSFORM_VIEW: + return "SVGA3D_TRANSFORM_VIEW"; + case SVGA3D_TRANSFORM_PROJECTION: + return "SVGA3D_TRANSFORM_PROJECTION"; + case SVGA3D_TRANSFORM_TEXTURE0: + return "SVGA3D_TRANSFORM_TEXTURE0"; + case SVGA3D_TRANSFORM_TEXTURE1: + return "SVGA3D_TRANSFORM_TEXTURE1"; + case SVGA3D_TRANSFORM_TEXTURE2: + return "SVGA3D_TRANSFORM_TEXTURE2"; + case SVGA3D_TRANSFORM_TEXTURE3: + return "SVGA3D_TRANSFORM_TEXTURE3"; + case SVGA3D_TRANSFORM_TEXTURE4: + return "SVGA3D_TRANSFORM_TEXTURE4"; + case SVGA3D_TRANSFORM_TEXTURE5: + return "SVGA3D_TRANSFORM_TEXTURE5"; + case SVGA3D_TRANSFORM_TEXTURE6: + return "SVGA3D_TRANSFORM_TEXTURE6"; + case SVGA3D_TRANSFORM_TEXTURE7: + return "SVGA3D_TRANSFORM_TEXTURE7"; + case SVGA3D_TRANSFORM_WORLD1: + return "SVGA3D_TRANSFORM_WORLD1"; + case SVGA3D_TRANSFORM_WORLD2: + return "SVGA3D_TRANSFORM_WORLD2"; + case SVGA3D_TRANSFORM_WORLD3: + return "SVGA3D_TRANSFORM_WORLD3"; + default: + return "UNKNOWN"; + } +} + +const char *vmsvgaDeclUsage2String(SVGA3dDeclUsage usage) +{ + switch (usage) + { + case SVGA3D_DECLUSAGE_POSITION: + return "SVGA3D_DECLUSAGE_POSITION"; + case SVGA3D_DECLUSAGE_BLENDWEIGHT: + return "SVGA3D_DECLUSAGE_BLENDWEIGHT"; + case SVGA3D_DECLUSAGE_BLENDINDICES: + return "SVGA3D_DECLUSAGE_BLENDINDICES"; + case SVGA3D_DECLUSAGE_NORMAL: + return "SVGA3D_DECLUSAGE_NORMAL"; + case SVGA3D_DECLUSAGE_PSIZE: + return "SVGA3D_DECLUSAGE_PSIZE"; + case SVGA3D_DECLUSAGE_TEXCOORD: + return "SVGA3D_DECLUSAGE_TEXCOORD"; + case SVGA3D_DECLUSAGE_TANGENT: + return "SVGA3D_DECLUSAGE_TANGENT"; + case SVGA3D_DECLUSAGE_BINORMAL: + return "SVGA3D_DECLUSAGE_BINORMAL"; + case SVGA3D_DECLUSAGE_TESSFACTOR: + return "SVGA3D_DECLUSAGE_TESSFACTOR"; + case SVGA3D_DECLUSAGE_POSITIONT: + return "SVGA3D_DECLUSAGE_POSITIONT"; + case SVGA3D_DECLUSAGE_COLOR: + return "SVGA3D_DECLUSAGE_COLOR"; + case SVGA3D_DECLUSAGE_FOG: + return "SVGA3D_DECLUSAGE_FOG"; + case SVGA3D_DECLUSAGE_DEPTH: + return "SVGA3D_DECLUSAGE_DEPTH"; + case SVGA3D_DECLUSAGE_SAMPLE: + return "SVGA3D_DECLUSAGE_SAMPLE"; + default: + return "UNKNOWN!!"; + } +} + +const char *vmsvgaDeclMethod2String(SVGA3dDeclMethod method) +{ + switch (method) + { + case SVGA3D_DECLMETHOD_DEFAULT: + return "SVGA3D_DECLMETHOD_DEFAULT"; + case SVGA3D_DECLMETHOD_PARTIALU: + return "SVGA3D_DECLMETHOD_PARTIALU"; + case SVGA3D_DECLMETHOD_PARTIALV: + return "SVGA3D_DECLMETHOD_PARTIALV"; + case SVGA3D_DECLMETHOD_CROSSUV: + return "SVGA3D_DECLMETHOD_CROSSUV"; + case SVGA3D_DECLMETHOD_UV: + return "SVGA3D_DECLMETHOD_UV"; + case SVGA3D_DECLMETHOD_LOOKUP: + return "SVGA3D_DECLMETHOD_LOOKUP"; + case SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED: + return "SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED"; + default: + return "UNKNOWN!!"; + } +} + +const char *vmsvgaDeclType2String(SVGA3dDeclType type) +{ + switch (type) + { + case SVGA3D_DECLTYPE_FLOAT1: + return "SVGA3D_DECLTYPE_FLOAT1"; + case SVGA3D_DECLTYPE_FLOAT2: + return "SVGA3D_DECLTYPE_FLOAT2"; + case SVGA3D_DECLTYPE_FLOAT3: + return "SVGA3D_DECLTYPE_FLOAT3"; + case SVGA3D_DECLTYPE_FLOAT4: + return "SVGA3D_DECLTYPE_FLOAT4"; + case SVGA3D_DECLTYPE_D3DCOLOR: + return "SVGA3D_DECLTYPE_D3DCOLOR"; + case SVGA3D_DECLTYPE_UBYTE4: + return "SVGA3D_DECLTYPE_UBYTE4"; + case SVGA3D_DECLTYPE_SHORT2: + return "SVGA3D_DECLTYPE_SHORT2"; + case SVGA3D_DECLTYPE_SHORT4: + return "SVGA3D_DECLTYPE_SHORT4"; + case SVGA3D_DECLTYPE_UBYTE4N: + return "SVGA3D_DECLTYPE_UBYTE4N"; + case SVGA3D_DECLTYPE_SHORT2N: + return "SVGA3D_DECLTYPE_SHORT2N"; + case SVGA3D_DECLTYPE_SHORT4N: + return "SVGA3D_DECLTYPE_SHORT4N"; + case SVGA3D_DECLTYPE_USHORT2N: + return "SVGA3D_DECLTYPE_USHORT2N"; + case SVGA3D_DECLTYPE_USHORT4N: + return "SVGA3D_DECLTYPE_USHORT4N"; + case SVGA3D_DECLTYPE_UDEC3: + return "SVGA3D_DECLTYPE_UDEC3"; + case SVGA3D_DECLTYPE_DEC3N: + return "SVGA3D_DECLTYPE_DEC3N"; + case SVGA3D_DECLTYPE_FLOAT16_2: + return "SVGA3D_DECLTYPE_FLOAT16_2"; + case SVGA3D_DECLTYPE_FLOAT16_4: + return "SVGA3D_DECLTYPE_FLOAT16_4"; + default: + return "UNKNOWN!!"; + } +} + +const char *vmsvga3dPrimitiveType2String(SVGA3dPrimitiveType PrimitiveType) +{ + switch (PrimitiveType) + { + case SVGA3D_PRIMITIVE_TRIANGLELIST: + return "SVGA3D_PRIMITIVE_TRIANGLELIST"; + case SVGA3D_PRIMITIVE_POINTLIST: + return "SVGA3D_PRIMITIVE_POINTLIST"; + case SVGA3D_PRIMITIVE_LINELIST: + return "SVGA3D_PRIMITIVE_LINELIST"; + case SVGA3D_PRIMITIVE_LINESTRIP: + return "SVGA3D_PRIMITIVE_LINESTRIP"; + case SVGA3D_PRIMITIVE_TRIANGLESTRIP: + return "SVGA3D_PRIMITIVE_TRIANGLESTRIP"; + case SVGA3D_PRIMITIVE_TRIANGLEFAN: + return "SVGA3D_PRIMITIVE_TRIANGLEFAN"; + default: + return "UNKNOWN"; + } +} + +#endif /* LOG_ENABLED */ diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win-d3d9.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win-d3d9.cpp new file mode 100644 index 00000000..305a793c --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win-d3d9.cpp @@ -0,0 +1,1247 @@ +/* $Id: DevVGA-SVGA3d-win-d3d9.cpp $ */ +/** @file + * DevVMWare - VMWare SVGA device Direct3D 9 backend. + */ + +/* + * Copyright (C) 2019-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include + +#include + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d-internal.h" + + +typedef enum D3D9TextureType +{ + D3D9TextureType_Texture, + D3D9TextureType_Bounce, + D3D9TextureType_Emulated +} D3D9TextureType; + +DECLINLINE(D3DCUBEMAP_FACES) vmsvga3dCubemapFaceFromIndex(uint32_t iFace) +{ + D3DCUBEMAP_FACES Face; + switch (iFace) + { + case 0: Face = D3DCUBEMAP_FACE_POSITIVE_X; break; + case 1: Face = D3DCUBEMAP_FACE_NEGATIVE_X; break; + case 2: Face = D3DCUBEMAP_FACE_POSITIVE_Y; break; + case 3: Face = D3DCUBEMAP_FACE_NEGATIVE_Y; break; + case 4: Face = D3DCUBEMAP_FACE_POSITIVE_Z; break; + default: + case 5: Face = D3DCUBEMAP_FACE_NEGATIVE_Z; break; + } + return Face; +} + +IDirect3DTexture9 *D3D9GetTexture(PVMSVGA3DSURFACE pSurface, + D3D9TextureType enmType) +{ + IDirect3DTexture9 *p; + switch (enmType) + { + default: AssertFailed(); + RT_FALL_THRU(); + case D3D9TextureType_Texture: p = pSurface->u.pTexture; break; + case D3D9TextureType_Bounce: p = pSurface->bounce.pTexture; break; + case D3D9TextureType_Emulated: p = pSurface->emulated.pTexture; break; + } + return p; +} + +IDirect3DCubeTexture9 *D3D9GetCubeTexture(PVMSVGA3DSURFACE pSurface, + D3D9TextureType enmType) +{ + IDirect3DCubeTexture9 *p; + switch (enmType) + { + default: AssertFailed(); + RT_FALL_THRU(); + case D3D9TextureType_Texture: p = pSurface->u.pCubeTexture; break; + case D3D9TextureType_Bounce: p = pSurface->bounce.pCubeTexture; break; + case D3D9TextureType_Emulated: p = pSurface->emulated.pCubeTexture; break; + } + return p; +} + +IDirect3DVolumeTexture9 *D3D9GetVolumeTexture(PVMSVGA3DSURFACE pSurface, + D3D9TextureType enmType) +{ + IDirect3DVolumeTexture9 *p; + switch (enmType) + { + default: AssertFailed(); + RT_FALL_THRU(); + case D3D9TextureType_Texture: p = pSurface->u.pVolumeTexture; break; + case D3D9TextureType_Bounce: p = pSurface->bounce.pVolumeTexture; break; + case D3D9TextureType_Emulated: p = pSurface->emulated.pVolumeTexture; break; + } + return p; +} + +HRESULT D3D9GetTextureLevel(PVMSVGA3DSURFACE pSurface, + D3D9TextureType enmType, + uint32_t uFace, + uint32_t uMipmap, + IDirect3DSurface9 **ppD3DSurface) +{ + HRESULT hr; + + if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE) + { + Assert(pSurface->cFaces == 6); + + IDirect3DCubeTexture9 *p = D3D9GetCubeTexture(pSurface, enmType); + if (p) + { + D3DCUBEMAP_FACES const FaceType = vmsvga3dCubemapFaceFromIndex(uFace); + hr = p->GetCubeMapSurface(FaceType, uMipmap, ppD3DSurface); + AssertMsg(hr == D3D_OK, ("GetCubeMapSurface failed with %x\n", hr)); + } + else + { + AssertFailed(); + hr = E_INVALIDARG; + } + } + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE) + { + Assert(pSurface->cFaces == 1); + Assert(uFace == 0); + + IDirect3DTexture9 *p = D3D9GetTexture(pSurface, enmType); + if (p) + { + hr = p->GetSurfaceLevel(uMipmap, ppD3DSurface); + AssertMsg(hr == D3D_OK, ("GetSurfaceLevel failed with %x\n", hr)); + } + else + { + AssertFailed(); + hr = E_INVALIDARG; + } + } + else + { + AssertMsgFailed(("No surface level for type %d\n", pSurface->enmD3DResType)); + hr = E_INVALIDARG; + } + + return hr; +} + + +static HRESULT d3dCopyToVertexBuffer(IDirect3DVertexBuffer9 *pVB, const void *pvSrc, int cbSrc) +{ + HRESULT hr = D3D_OK; + void *pvDst = 0; + hr = pVB->Lock(0, 0, &pvDst, 0); + if (SUCCEEDED(hr)) + { + memcpy(pvDst, pvSrc, cbSrc); + hr = pVB->Unlock(); + } + return hr; +} + +struct Vertex +{ + float x, y; /* The vertex position. */ + float u, v; /* Texture coordinates. */ +}; + +typedef struct D3D9ConversionParameters +{ + DWORD const *paVS; /* Vertex shader code. */ + DWORD const *paPS; /* Pixel shader code. */ +} D3D9ConversionParameters; + +/** Select conversion shaders. + * @param d3dfmtFrom Source texture format. + * @param d3dfmtTo Target texture format. + * @param pResult Where the tore pointers to the shader code. + */ +static HRESULT d3d9SelectConversion(D3DFORMAT d3dfmtFrom, D3DFORMAT d3dfmtTo, + D3D9ConversionParameters *pResult) +{ + /* + * The shader code has been obtained from the hex listing file (hexdump.txt) produced by fxc HLSL compiler: + * fxc.exe /Op /Tfx_2_0 /Fxhexdump.txt shader.fx + * + * The vertex shader code is the same for all convestion variants. + * + * For example here is the complete code for aPSCodeSwapRB: + + uniform extern float4 gTextureInfo; // .xy = (width, height) in pixels, .zw = (1/width, 1/height) + uniform extern texture gTexSource; + sampler sSource = sampler_state + { + Texture = ; + }; + + struct VS_INPUT + { + float2 Position : POSITION; // In pixels. + float2 TexCoord : TEXCOORD0; + }; + + struct VS_OUTPUT + { + float4 Position : POSITION; // Normalized. + float2 TexCoord : TEXCOORD0; + }; + + VS_OUTPUT VS(VS_INPUT In) + { + VS_OUTPUT Output; + + // Position is in pixels, i.e [0; width - 1]. Top, left is 0,0. + // Convert to the normalized coords in the -1;1 range + float4 Position; + Position.x = 2.0f * In.Position.x / (gTextureInfo.x - 1.0f) - 1.0f; + Position.y = -2.0f * In.Position.y / (gTextureInfo.y - 1.0f) + 1.0f; + Position.z = 0.0f; // Not used. + Position.w = 1.0f; // It is a point. + + Output.Position = Position; + Output.TexCoord = In.TexCoord; + + return Output; + } + + struct PS_OUTPUT + { + float4 Color : COLOR0; + }; + + PS_OUTPUT PS(VS_OUTPUT In) + { + PS_OUTPUT Output; + + float2 texCoord = In.TexCoord; + + float4 texColor = tex2D(sSource, texCoord); + + Output.Color = texColor.bgra; // Swizzle rgba -> bgra + + return Output; + } + + technique RenderScene + { + pass P0 + { + VertexShader = compile vs_2_0 VS(); + PixelShader = compile ps_2_0 PS(); + } + } + */ + + static DWORD const aVSCode[] = + { + 0xfffe0200, // vs_2_0 + 0x05000051, 0xa00f0001, 0xbf800000, 0xc0000000, 0x3f800000, 0x00000000, // def c1, -1, -2, 1, 0 + 0x0200001f, 0x80000000, 0x900f0000, // dcl_position v0 + 0x0200001f, 0x80000005, 0x900f0001, // dcl_texcoord v1 + 0x03000002, 0x80010000, 0x90000000, 0x90000000, // add r0.x, v0.x, v0.x + 0x02000001, 0x80010001, 0xa0000001, // mov r1.x, c1.x + 0x03000002, 0x80060000, 0x80000001, 0xa0d00000, // add r0.yz, r1.x, c0.xxyw + 0x02000006, 0x80020000, 0x80550000, // rcp r0.y, r0.y + 0x02000006, 0x80040000, 0x80aa0000, // rcp r0.z, r0.z + 0x04000004, 0xc0010000, 0x80000000, 0x80550000, 0xa0000001, // mad oPos.x, r0.x, r0.y, c1.x + 0x03000005, 0x80010000, 0x90550000, 0xa0550001, // mul r0.x, v0.y, c1.y + 0x04000004, 0xc0020000, 0x80000000, 0x80aa0000, 0xa0aa0001, // mad oPos.y, r0.x, r0.z, c1.z + 0x02000001, 0xc00c0000, 0xa0b40001, // mov oPos.zw, c1.xywz + 0x02000001, 0xe0030000, 0x90e40001, // mov oT0.xy, v1 + 0x0000ffff + }; + + /* + * Swap R and B components. Converts D3DFMT_A8R8G8B8 <-> D3DFMT_A8B8G8R8. + */ + static DWORD const aPSCodeSwapRB[] = + { + 0xffff0200, // ps_2_0 + 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy + 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0 + 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, // texld r0, t0, s0 + 0x02000001, 0x80090001, 0x80d20000, // mov r1.xw, r0.zxyw + 0x02000001, 0x80040001, 0x80000000, // mov r1.z, r0.x + 0x02000001, 0x80020001, 0x80550000, // mov r1.y, r0.y + 0x02000001, 0x800f0800, 0x80e40001, // mov oC0, r1 + 0x0000ffff + }; + + /* YUY2 to RGB: + + // YUY2 if not defined + // #define UYVY + + static const float3x3 yuvCoeffs = + { + 1.164383f, 1.164383f, 1.164383f, + 0.0f, -0.391762f, 2.017232f, + 1.596027f, -0.812968f, 0.0f + }; + + PS_OUTPUT PS(VS_OUTPUT In) + { + PS_OUTPUT Output; + + // 4 bytes of an YUV macropixel contain 2 pixels in X for the target. + // I.e. each YUV texture pixel is sampled twice: for both even and odd target pixels. + + // In.TexCoord are in [0;1] range for the target. + float2 texCoord = In.TexCoord; + + // Convert to the target coords in pixels: xPixel = TexCoord.x * Width. + float xTargetPixel = texCoord.x * gTextureInfo.x; + + // Source texture is half width, i.e. it contains data in pixels [0; width / 2 - 1]. + float xSourcePixel = xTargetPixel / 2.0f; + + // Remainder is about 0.25 for even pixels and about 0.75 for odd pixels. + float remainder = xSourcePixel - trunc(xSourcePixel); + + // Back to the normalized coords: texCoord.x = xPixel / Width. + texCoord.x = xSourcePixel * gTextureInfo.z; + + // Fetch YUV + float4 texColor = tex2D(sSource, texCoord); + + // Get YUV components. + #ifdef UYVY + float u = texColor.b; + float y0 = texColor.g; + float v = texColor.r; + float y1 = texColor.a; + #else // YUY2 + float y0 = texColor.b; + float u = texColor.g; + float y1 = texColor.r; + float v = texColor.a; + #endif + + // Get y0 for even x coordinates and y1 for odd ones. + float y = remainder < 0.5f ? y0 : y1; + + // Make a vector for easier calculation. + float3 yuv = float3(y, u, v); + + // Convert YUV to RGB: + // https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#converting-8-bit-yuv-to-rgb888 + // + // For 8bit [0;255] when Y = [16;235], U,V = [16;239]: + // + // C = Y - 16 + // D = U - 128 + // E = V - 128 + // + // R = 1.164383 * C + 1.596027 * E + // G = 1.164383 * C - 0.391762 * D - 0.812968 * E + // B = 1.164383 * C + 2.017232 * D + // + // For shader values [0;1.0] when Y = [16/255;235/255], U,V = [16/255;239/255]: + // + // C = Y - 0.0627 + // D = U - 0.5020 + // E = V - 0.5020 + // + // R = 1.164383 * C + 1.596027 * E + // G = 1.164383 * C - 0.391762 * D - 0.812968 * E + // B = 1.164383 * C + 2.017232 * D + // + yuv -= float3(0.0627f, 0.502f, 0.502f); + float3 bgr = mul(yuv, yuvCoeffs); + + // Clamp to [0;1] + bgr = saturate(bgr); + + // Return RGBA + Output.Color = float4(bgr, 1.0f); + + return Output; + } + */ + static DWORD const aPSCodeYUY2toRGB[] = + { + 0xffff0200, // ps_2_0 + 0x05000051, 0xa00f0001, 0x3f000000, 0x00000000, 0x3f800000, 0xbf000000, // def c1, 0.5, 0, 1, -0.5 + 0x05000051, 0xa00f0002, 0xbd8068dc, 0xbf008312, 0xbf008312, 0x00000000, // def c2, -0.0627000034, -0.501999974, -0.501999974, 0 + 0x05000051, 0xa00f0003, 0x3f950a81, 0x00000000, 0x3fcc4a9d, 0x00000000, // def c3, 1.16438305, 0, 1.59602702, 0 + 0x05000051, 0xa00f0004, 0x3f950a81, 0xbec89507, 0xbf501eac, 0x00000000, // def c4, 1.16438305, -0.391761988, -0.812968016, 0 + 0x05000051, 0xa00f0005, 0x3f950a81, 0x40011a54, 0x00000000, 0x00000000, // def c5, 1.16438305, 2.01723194, 0, 0 + 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy + 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0 + 0x03000005, 0x80080000, 0xb0000000, 0xa0000000, // mul r0.w, t0.x, c0.x + 0x03000005, 0x80010000, 0x80ff0000, 0xa0000001, // mul r0.x, r0.w, c1.x + 0x02000013, 0x80020000, 0x80000000, // frc r0.y, r0.x + 0x04000058, 0x80040000, 0x81550000, 0xa0550001, 0xa0aa0001, // cmp r0.z, -r0.y, c1.y, c1.z + 0x03000002, 0x80020000, 0x80000000, 0x81550000, // add r0.y, r0.x, -r0.y + 0x03000005, 0x80010001, 0x80000000, 0xa0aa0000, // mul r1.x, r0.x, c0.z + 0x04000058, 0x80010000, 0x80ff0000, 0xa0550001, 0x80aa0000, // cmp r0.x, r0.w, c1.y, r0.z + 0x03000002, 0x80010000, 0x80000000, 0x80550000, // add r0.x, r0.x, r0.y + 0x04000004, 0x80010000, 0x80ff0000, 0xa0000001, 0x81000000, // mad r0.x, r0.w, c1.x, -r0.x + 0x03000002, 0x80010000, 0x80000000, 0xa0ff0001, // add r0.x, r0.x, c1.w + 0x02000001, 0x80020001, 0xb0550000, // mov r1.y, t0.y + 0x03000042, 0x800f0001, 0x80e40001, 0xa0e40800, // texld r1, r1, s0 + 0x04000058, 0x80010001, 0x80000000, 0x80000001, 0x80aa0001, // cmp r1.x, r0.x, r1.x, r1.z + 0x02000001, 0x80040001, 0x80ff0001, // mov r1.z, r1.w + 0x03000002, 0x80070000, 0x80e40001, 0xa0e40002, // add r0.xyz, r1, c2 + 0x03000008, 0x80110001, 0x80e40000, 0xa0e40003, // dp3_sat r1.x, r0, c3 + 0x03000008, 0x80120001, 0x80e40000, 0xa0e40004, // dp3_sat r1.y, r0, c4 + 0x0400005a, 0x80140001, 0x80e40000, 0xa0e40005, 0xa0aa0005, // dp2add_sat r1.z, r0, c5, c5.z + 0x02000001, 0x80080001, 0xa0aa0001, // mov r1.w, c1.z + 0x02000001, 0x800f0800, 0x80e40001, // mov oC0, r1 + 0x0000ffff + }; + + /* UYVY to RGB is same as YUY2 above except for the order of yuv components: + + // YUY2 if not defined + #define UYVY + ... + */ + static DWORD const aPSCodeUYVYtoRGB[] = + { + 0xffff0200, // ps_2_0 + 0x05000051, 0xa00f0001, 0x3f000000, 0x00000000, 0x3f800000, 0xbf000000, // def c1, 0.5, 0, 1, -0.5 + 0x05000051, 0xa00f0002, 0xbd8068dc, 0xbf008312, 0xbf008312, 0x00000000, // def c2, -0.0627000034, -0.501999974, -0.501999974, 0 + 0x05000051, 0xa00f0003, 0x3f950a81, 0x00000000, 0x3fcc4a9d, 0x00000000, // def c3, 1.16438305, 0, 1.59602702, 0 + 0x05000051, 0xa00f0004, 0x3f950a81, 0xbec89507, 0xbf501eac, 0x00000000, // def c4, 1.16438305, -0.391761988, -0.812968016, 0 + 0x05000051, 0xa00f0005, 0x3f950a81, 0x40011a54, 0x00000000, 0x00000000, // def c5, 1.16438305, 2.01723194, 0, 0 + 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy + 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0 + 0x03000005, 0x80080000, 0xb0000000, 0xa0000000, // mul r0.w, t0.x, c0.x + 0x03000005, 0x80010000, 0x80ff0000, 0xa0000001, // mul r0.x, r0.w, c1.x + 0x02000013, 0x80020000, 0x80000000, // frc r0.y, r0.x + 0x04000058, 0x80040000, 0x81550000, 0xa0550001, 0xa0aa0001, // cmp r0.z, -r0.y, c1.y, c1.z + 0x03000002, 0x80020000, 0x80000000, 0x81550000, // add r0.y, r0.x, -r0.y + 0x03000005, 0x80010001, 0x80000000, 0xa0aa0000, // mul r1.x, r0.x, c0.z + 0x04000058, 0x80010000, 0x80ff0000, 0xa0550001, 0x80aa0000, // cmp r0.x, r0.w, c1.y, r0.z + 0x03000002, 0x80010000, 0x80000000, 0x80550000, // add r0.x, r0.x, r0.y + 0x04000004, 0x80010000, 0x80ff0000, 0xa0000001, 0x81000000, // mad r0.x, r0.w, c1.x, -r0.x + 0x03000002, 0x80010000, 0x80000000, 0xa0ff0001, // add r0.x, r0.x, c1.w + 0x02000001, 0x80020001, 0xb0550000, // mov r1.y, t0.y + 0x03000042, 0x800f0001, 0x80e40001, 0xa0e40800, // texld r1, r1, s0 + 0x04000058, 0x80010000, 0x80000000, 0x80ff0001, 0x80550001, // cmp r0.x, r0.x, r1.w, r1.y + 0x02000001, 0x80060000, 0x80c90001, // mov r0.yz, r1.yzxw + 0x03000002, 0x80070000, 0x80e40000, 0xa0e40002, // add r0.xyz, r0, c2 + 0x03000008, 0x80110001, 0x80e40000, 0xa0e40003, // dp3_sat r1.x, r0, c3 + 0x03000008, 0x80120001, 0x80e40000, 0xa0e40004, // dp3_sat r1.y, r0, c4 + 0x0400005a, 0x80140001, 0x80e40000, 0xa0e40005, 0xa0aa0005, // dp2add_sat r1.z, r0, c5, c5.z + 0x02000001, 0x80080001, 0xa0aa0001, // mov r1.w, c1.z + 0x02000001, 0x800f0800, 0x80e40001, // mov oC0, r1 + 0x0000ffff + }; + + /* RGB to YUY2. + * UYVY is not defined. + + static const float3x3 bgrCoeffs = + { + 0.0977f, 0.4375f, -0.0703f, + 0.5039f, -0.2891f, -0.3672f, + 0.2578f, -0.1484f, 0.4375f + }; + + static const float3 yuvShift = { 0.0647f, 0.5039f, 0.5039f }; + + PS_OUTPUT PS(VS_OUTPUT In) + { + PS_OUTPUT Output; + + // 4 bytes of an YUV macropixel contain 2 source pixels in X. + // I.e. each YUV texture target pixel is computed from 2 source pixels. + // The target texture pixels are located in the [0; width / 2 - 1] range. + + // In.TexCoord are in [0;1] range, applicable both to the source and the target textures. + float2 texCoordDst = In.TexCoord; + + // Convert to the target coords in pixels: xPixel = TexCoord.x * Width. + float xTargetPixel = texCoordDst.x * gTextureInfo.x; + + float4 bgraOutputPixel; + if (xTargetPixel < gTextureInfo.x / 2.0f) + { + // Target texture is half width, i.e. it contains data in pixels [0; width / 2 - 1]. + // Compute the source texture coords for the pixels which will be used to compute the target pixel. + float2 texCoordSrc = texCoordDst; + texCoordSrc.x *= 2.0f; + + // Even pixel. Fetch two BGRA source pixels. + float4 texColor0 = tex2D(sSource, texCoordSrc); + + // Advance one pixel (+ 1/Width) + texCoordSrc.x += gTextureInfo.z; + float4 texColor1 = tex2D(sSource, texCoordSrc); + + // Compute y0, u, y1, v components + // https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#converting-rgb888-to-yuv-444 + // + // For R,G,B and Y,U,V in [0;255] + // Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16 + // U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128 + // V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128 + // + // For r,g,b and y,u,v in [0;1.0] + // y = 0.2578 * r + 0.5039 * g + 0.0977 * b + 0.0647 + // u = -0.1484 * r - 0.2891 * g + 0.4375 * b + 0.5039 + // v = 0.4375 * r - 0.3672 * g - 0.0703 * b + 0.5039 + + float3 yuv0 = mul(texColor0.bgr, bgrCoeffs); + yuv0 -= yuvShift; + + float3 yuv1 = mul(texColor1.bgr, bgrCoeffs); + yuv1 -= yuvShift; + + float y0 = yuv0.b; + float u = (yuv0.g + yuv1.g) / 2.0f; + float y1 = yuv1.b; + float v = (yuv0.r + yuv1.r) / 2.0f; + + #ifdef UYVY + bgraOutputPixel = float4(u, y0, v, y1); + #else // YUY2 + bgraOutputPixel = float4(y0, u, y1, v); + #endif + } + else + { + // [width / 2; width - 1] pixels are not used. Set to something. + bgraOutputPixel = float4(0.0f, 0.0f, 0.0f, 0.0f); + } + + // Clamp to [0;1] + bgraOutputPixel = saturate(bgraOutputPixel); + + // Return RGBA + Output.Color = bgraOutputPixel; + + return Output; + } + */ + static DWORD const aPSCodeRGBtoYUY2[] = + { + 0xffff0200, // ps_2_0 + 0x05000051, 0xa00f0001, 0xbd84816f, 0xbf00ff97, 0xbf00ff97, 0x00000000, // def c1, -0.0647, -0.503899992, -0.503899992, 0 + 0x05000051, 0xa00f0002, 0xbe80ff97, 0x00000000, 0xbd04816f, 0x00000000, // def c2, -0.251949996, 0, -0.03235, 0 + 0x05000051, 0xa00f0003, 0x3dc816f0, 0x3f00ff97, 0x3e83fe5d, 0x00000000, // def c3, 0.0976999998, 0.503899992, 0.257800013, 0 + 0x05000051, 0xa00f0004, 0x3ee00000, 0xbe9404ea, 0xbe17f62b, 0x00000000, // def c4, 0.4375, -0.289099991, -0.148399994, 0 + 0x05000051, 0xa00f0005, 0xbd8ff972, 0xbebc01a3, 0x3ee00000, 0x00000000, // def c5, -0.0702999979, -0.367199987, 0.4375, 0 + 0x05000051, 0xa00f0006, 0x3f000000, 0x40000000, 0x3f800000, 0xbf00ff97, // def c6, 0.5, 2, 1, -0.503899992 + 0x05000051, 0xa00f0007, 0x3f000000, 0x3f800000, 0x3f000000, 0x00000000, // def c7, 0.5, 1, 0.5, 0 + 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy + 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0 + 0x03000005, 0x80030000, 0xb0e40000, 0xa0c90006, // mul r0.xy, t0, c6.yzxw + 0x02000001, 0x80030001, 0xa0e40006, // mov r1.xy, c6 + 0x04000004, 0x80010002, 0xb0000000, 0x80550001, 0xa0aa0000, // mad r2.x, t0.x, r1.y, c0.z + 0x02000001, 0x80020002, 0xb0550000, // mov r2.y, t0.y + 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40800, // texld r0, r0, s0 + 0x03000042, 0x800f0002, 0x80e40002, 0xa0e40800, // texld r2, r2, s0 + 0x03000005, 0x80080000, 0x80aa0000, 0xa0000003, // mul r0.w, r0.z, c3.x + 0x04000004, 0x80080000, 0x80550000, 0xa0550003, 0x80ff0000, // mad r0.w, r0.y, c3.y, r0.w + 0x04000004, 0x80010003, 0x80000000, 0xa0aa0003, 0x80ff0000, // mad r3.x, r0.x, c3.z, r0.w + 0x03000005, 0x80080000, 0x80aa0000, 0xa0000004, // mul r0.w, r0.z, c4.x + 0x04000004, 0x80080000, 0x80550000, 0xa0550004, 0x80ff0000, // mad r0.w, r0.y, c4.y, r0.w + 0x04000004, 0x80020003, 0x80000000, 0xa0aa0004, 0x80ff0000, // mad r3.y, r0.x, c4.z, r0.w + 0x03000005, 0x80080002, 0x80aa0000, 0xa0000005, // mul r2.w, r0.z, c5.x + 0x04000004, 0x80080002, 0x80550000, 0xa0550005, 0x80ff0002, // mad r2.w, r0.y, c5.y, r2.w + 0x04000004, 0x80040003, 0x80000000, 0xa0aa0005, 0x80ff0002, // mad r3.z, r0.x, c5.z, r2.w + 0x03000002, 0x80070000, 0x80e40003, 0xa0e40001, // add r0.xyz, r3, c1 + 0x02000001, 0x80080000, 0xa0ff0006, // mov r0.w, c6.w + 0x03000005, 0x80080002, 0x80aa0002, 0xa0000003, // mul r2.w, r2.z, c3.x + 0x04000004, 0x80080002, 0x80550002, 0xa0550003, 0x80ff0002, // mad r2.w, r2.y, c3.y, r2.w + 0x04000004, 0x80040003, 0x80000002, 0xa0aa0003, 0x80ff0002, // mad r3.z, r2.x, c3.z, r2.w + 0x03000005, 0x80080002, 0x80aa0002, 0xa0000004, // mul r2.w, r2.z, c4.x + 0x04000004, 0x80080002, 0x80550002, 0xa0550004, 0x80ff0002, // mad r2.w, r2.y, c4.y, r2.w + 0x04000004, 0x80010003, 0x80000002, 0xa0aa0004, 0x80ff0002, // mad r3.x, r2.x, c4.z, r2.w + 0x03000005, 0x80080003, 0x80aa0002, 0xa0000005, // mul r3.w, r2.z, c5.x + 0x04000004, 0x80080003, 0x80550002, 0xa0550005, 0x80ff0003, // mad r3.w, r2.y, c5.y, r3.w + 0x04000004, 0x80020003, 0x80000002, 0xa0aa0005, 0x80ff0003, // mad r3.y, r2.x, c5.z, r3.w + 0x03000002, 0x80050002, 0x80c90000, 0x80e40003, // add r2.xz, r0.yzxw, r3 + 0x03000002, 0x80020002, 0x80ff0000, 0x80550003, // add r2.y, r0.w, r3.y + 0x02000001, 0x80110000, 0x80aa0000, // mov_sat r0.x, r0.z + 0x02000001, 0x80070003, 0xa0e40007, // mov r3.xyz, c7 + 0x04000004, 0x80160000, 0x80d20002, 0x80d20003, 0xa0d20002, // mad_sat r0.yz, r2.zxyw, r3.zxyw, c2.zxyw + 0x04000004, 0x80180000, 0x80aa0002, 0x80aa0003, 0xa0aa0002, // mad_sat r0.w, r2.z, r3.z, c2.z + 0x03000005, 0x80010001, 0x80000001, 0xa0000000, // mul r1.x, r1.x, c0.x + 0x04000004, 0x80010001, 0xb0000000, 0xa0000000, 0x81000001, // mad r1.x, t0.x, c0.x, -r1.x + 0x04000058, 0x800f0000, 0x80000001, 0xa0ff0003, 0x80e40000, // cmp r0, r1.x, c3.w, r0 + 0x02000001, 0x800f0800, 0x80e40000, // mov oC0, r0 + 0x0000ffff + }; + + /* RGB to UYVY is same as YUY2 above except for the order of yuv components. + * UYVY is defined. + */ + static DWORD const aPSCodeRGBtoUYVY[] = + { + 0xffff0200, // ps_2_0 + 0x05000051, 0xa00f0001, 0xbd84816f, 0xbf00ff97, 0xbf00ff97, 0x00000000, // def c1, -0.0647, -0.503899992, -0.503899992, 0 + 0x05000051, 0xa00f0002, 0xbe80ff97, 0xbd04816f, 0x00000000, 0x00000000, // def c2, -0.251949996, -0.03235, 0, 0 + 0x05000051, 0xa00f0003, 0x3dc816f0, 0x3f00ff97, 0x3e83fe5d, 0x00000000, // def c3, 0.0976999998, 0.503899992, 0.257800013, 0 + 0x05000051, 0xa00f0004, 0x3ee00000, 0xbe9404ea, 0xbe17f62b, 0x00000000, // def c4, 0.4375, -0.289099991, -0.148399994, 0 + 0x05000051, 0xa00f0005, 0xbd8ff972, 0xbebc01a3, 0x3ee00000, 0x00000000, // def c5, -0.0702999979, -0.367199987, 0.4375, 0 + 0x05000051, 0xa00f0006, 0x3f000000, 0x40000000, 0x3f800000, 0xbf00ff97, // def c6, 0.5, 2, 1, -0.503899992 + 0x05000051, 0xa00f0007, 0x3f000000, 0x3f000000, 0x3f800000, 0x00000000, // def c7, 0.5, 0.5, 1, 0 + 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy + 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0 + 0x03000005, 0x80030000, 0xb0e40000, 0xa0c90006, // mul r0.xy, t0, c6.yzxw + 0x02000001, 0x80030001, 0xa0e40006, // mov r1.xy, c6 + 0x04000004, 0x80010002, 0xb0000000, 0x80550001, 0xa0aa0000, // mad r2.x, t0.x, r1.y, c0.z + 0x02000001, 0x80020002, 0xb0550000, // mov r2.y, t0.y + 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40800, // texld r0, r0, s0 + 0x03000042, 0x800f0002, 0x80e40002, 0xa0e40800, // texld r2, r2, s0 + 0x03000005, 0x80080000, 0x80aa0000, 0xa0000003, // mul r0.w, r0.z, c3.x + 0x04000004, 0x80080000, 0x80550000, 0xa0550003, 0x80ff0000, // mad r0.w, r0.y, c3.y, r0.w + 0x04000004, 0x80010003, 0x80000000, 0xa0aa0003, 0x80ff0000, // mad r3.x, r0.x, c3.z, r0.w + 0x03000005, 0x80080000, 0x80aa0000, 0xa0000004, // mul r0.w, r0.z, c4.x + 0x04000004, 0x80080000, 0x80550000, 0xa0550004, 0x80ff0000, // mad r0.w, r0.y, c4.y, r0.w + 0x04000004, 0x80020003, 0x80000000, 0xa0aa0004, 0x80ff0000, // mad r3.y, r0.x, c4.z, r0.w + 0x03000005, 0x80080002, 0x80aa0000, 0xa0000005, // mul r2.w, r0.z, c5.x + 0x04000004, 0x80080002, 0x80550000, 0xa0550005, 0x80ff0002, // mad r2.w, r0.y, c5.y, r2.w + 0x04000004, 0x80040003, 0x80000000, 0xa0aa0005, 0x80ff0002, // mad r3.z, r0.x, c5.z, r2.w + 0x03000002, 0x80070000, 0x80e40003, 0xa0e40001, // add r0.xyz, r3, c1 + 0x02000001, 0x80080000, 0xa0ff0006, // mov r0.w, c6.w + 0x03000005, 0x80080002, 0x80aa0002, 0xa0000003, // mul r2.w, r2.z, c3.x + 0x04000004, 0x80080002, 0x80550002, 0xa0550003, 0x80ff0002, // mad r2.w, r2.y, c3.y, r2.w + 0x04000004, 0x80020003, 0x80000002, 0xa0aa0003, 0x80ff0002, // mad r3.y, r2.x, c3.z, r2.w + 0x03000005, 0x80080002, 0x80aa0002, 0xa0000004, // mul r2.w, r2.z, c4.x + 0x04000004, 0x80080002, 0x80550002, 0xa0550004, 0x80ff0002, // mad r2.w, r2.y, c4.y, r2.w + 0x04000004, 0x80010003, 0x80000002, 0xa0aa0004, 0x80ff0002, // mad r3.x, r2.x, c4.z, r2.w + 0x03000005, 0x80080003, 0x80aa0002, 0xa0000005, // mul r3.w, r2.z, c5.x + 0x04000004, 0x80080003, 0x80550002, 0xa0550005, 0x80ff0003, // mad r3.w, r2.y, c5.y, r3.w + 0x04000004, 0x80040003, 0x80000002, 0xa0aa0005, 0x80ff0003, // mad r3.z, r2.x, c5.z, r3.w + 0x03000002, 0x80010002, 0x80550000, 0x80000003, // add r2.x, r0.y, r3.x + 0x03000002, 0x80020002, 0x80000000, 0x80550003, // add r2.y, r0.x, r3.y + 0x03000002, 0x80040002, 0x80ff0000, 0x80aa0003, // add r2.z, r0.w, r3.z + 0x02000001, 0x80120000, 0x80aa0000, // mov_sat r0.y, r0.z + 0x02000001, 0x80070003, 0xa0e40007, // mov r3.xyz, c7 + 0x04000004, 0x80110000, 0x80000002, 0x80000003, 0xa0000002, // mad_sat r0.x, r2.x, r3.x, c2.x + 0x04000004, 0x80140000, 0x80550002, 0x80550003, 0xa0550002, // mad_sat r0.z, r2.y, r3.y, c2.y + 0x04000004, 0x80180000, 0x80aa0002, 0x80aa0003, 0xa0aa0002, // mad_sat r0.w, r2.z, r3.z, c2.z + 0x03000005, 0x80010001, 0x80000001, 0xa0000000, // mul r1.x, r1.x, c0.x + 0x04000004, 0x80010001, 0xb0000000, 0xa0000000, 0x81000001, // mad r1.x, t0.x, c0.x, -r1.x + 0x04000058, 0x800f0000, 0x80000001, 0xa0ff0003, 0x80e40000, // cmp r0, r1.x, c3.w, r0 + 0x02000001, 0x800f0800, 0x80e40000, // mov oC0, r0 + 0x0000ffff + }; + + switch (d3dfmtFrom) + { + /* + * Emulated to ARGB + */ + case D3DFMT_A8B8G8R8: + { + if (d3dfmtTo == D3DFMT_A8R8G8B8) + { + pResult->paVS = aVSCode; + pResult->paPS = aPSCodeSwapRB; + + return D3D_OK; + } + } break; + case D3DFMT_UYVY: + { + if (d3dfmtTo == D3DFMT_A8R8G8B8) + { + pResult->paVS = aVSCode; + pResult->paPS = aPSCodeUYVYtoRGB; + + return D3D_OK; + } + } break; + case D3DFMT_YUY2: + { + if (d3dfmtTo == D3DFMT_A8R8G8B8) + { + pResult->paVS = aVSCode; + pResult->paPS = aPSCodeYUY2toRGB; + + return D3D_OK; + } + } break; + + /* + * ARGB to emulated. + */ + case D3DFMT_A8R8G8B8: + { + if (d3dfmtTo == D3DFMT_A8B8G8R8) + { + pResult->paVS = aVSCode; + pResult->paPS = aPSCodeSwapRB; + + return D3D_OK; + } + else if (d3dfmtTo == D3DFMT_UYVY) + { + pResult->paVS = aVSCode; + pResult->paPS = aPSCodeRGBtoUYVY; + + return D3D_OK; + } + else if (d3dfmtTo == D3DFMT_YUY2) + { + pResult->paVS = aVSCode; + pResult->paPS = aPSCodeRGBtoYUY2; + + return D3D_OK; + } + } break; + + default: + break; + } + + return E_NOTIMPL; +} + +class D3D9Conversion +{ + private: + IDirect3DDevice9Ex *mpDevice; + + /* State objects. */ + IDirect3DVertexBuffer9 *mpVB; + IDirect3DVertexDeclaration9 *mpVertexDecl; + IDirect3DVertexShader9 *mpVS; + IDirect3DPixelShader9 *mpPS; + + D3D9ConversionParameters mParameters; + + typedef struct D3DSamplerState + { + D3DSAMPLERSTATETYPE Type; + DWORD Value; + } D3DSamplerState; + + /* Saved context. */ + struct + { + DWORD dwCull; + DWORD dwZEnable; + IDirect3DSurface9 *pRT; + IDirect3DVertexShader9 *pVS; + IDirect3DPixelShader9 *pPS; + IDirect3DBaseTexture9 *pTexture; + float aVSConstantData[4]; + float aPSConstantData[4]; + D3DSamplerState aSamplerState[3]; + } mSaved; + + void destroyConversion(); + HRESULT saveContextState(); + HRESULT restoreContextState(PVMSVGA3DCONTEXT pContext); + HRESULT initConversion(); + HRESULT setConversionState(IDirect3DTexture9 *pSourceTexture, + uint32_t cWidth, + uint32_t cHeight); + + public: + enum Direction + { + FromEmulated, + ToEmulated, + }; + + D3D9Conversion(IDirect3DDevice9Ex *pDevice); + ~D3D9Conversion(); + + HRESULT SelectConversion(D3DFORMAT d3dfmtFrom, D3DFORMAT d3dfmtTo); + HRESULT ConvertTexture(PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pSurface, + Direction enmDirection); +}; + +D3D9Conversion::D3D9Conversion(IDirect3DDevice9Ex *pDevice) + : + mpDevice(pDevice), + mpVB(0), + mpVertexDecl(0), + mpVS(0), + mpPS(0) +{ + mParameters.paVS = 0; + mParameters.paPS = 0; + mSaved.dwCull = D3DCULL_NONE; + mSaved.dwZEnable = D3DZB_FALSE; + mSaved.pRT = 0; + mSaved.pVS = 0; + mSaved.pPS = 0; + mSaved.pTexture = 0; + RT_ZERO(mSaved.aVSConstantData); + RT_ZERO(mSaved.aPSConstantData); + mSaved.aSamplerState[0].Type = D3DSAMP_MAGFILTER; + mSaved.aSamplerState[0].Value = D3DTEXF_POINT; + mSaved.aSamplerState[1].Type = D3DSAMP_MINFILTER; + mSaved.aSamplerState[1].Value = D3DTEXF_POINT; + mSaved.aSamplerState[2].Type = D3DSAMP_MIPFILTER; + mSaved.aSamplerState[2].Value = D3DTEXF_NONE; +} + +D3D9Conversion::~D3D9Conversion() +{ + destroyConversion(); +} + +void D3D9Conversion::destroyConversion() +{ + D3D_RELEASE(mpVertexDecl); + D3D_RELEASE(mpVB); + D3D_RELEASE(mpVS); + D3D_RELEASE(mpPS); +} + +HRESULT D3D9Conversion::saveContextState() +{ + /* + * This is probably faster than + * IDirect3DStateBlock9 *mpStateBlock; + * mpDevice->CreateStateBlock(D3DSBT_ALL, &mpStateBlock); + */ + HRESULT hr = mpDevice->GetRenderState(D3DRS_CULLMODE, &mSaved.dwCull); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->GetRenderState(D3DRS_ZENABLE, &mSaved.dwZEnable); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->GetRenderTarget(0, &mSaved.pRT); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->GetVertexShader(&mSaved.pVS); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->GetPixelShader(&mSaved.pPS); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->GetTexture(0, &mSaved.pTexture); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->GetVertexShaderConstantF(0, mSaved.aVSConstantData, 1); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->GetPixelShaderConstantF(0, mSaved.aPSConstantData, 1); + AssertReturn(hr == D3D_OK, hr); + + for (uint32_t i = 0; i < RT_ELEMENTS(mSaved.aSamplerState); ++i) + { + hr = mpDevice->GetSamplerState(0, mSaved.aSamplerState[i].Type, &mSaved.aSamplerState[i].Value); + AssertReturn(hr == D3D_OK, hr); + } + + return hr; +} + +HRESULT D3D9Conversion::restoreContextState(PVMSVGA3DCONTEXT pContext) +{ + HRESULT hr = mpDevice->SetRenderState(D3DRS_CULLMODE, mSaved.dwCull); + Assert(hr == D3D_OK); + + hr = mpDevice->SetRenderState(D3DRS_ZENABLE, mSaved.dwZEnable); + Assert(hr == D3D_OK); + + hr = mpDevice->SetRenderTarget(0, mSaved.pRT); + D3D_RELEASE(mSaved.pRT); /* GetRenderTarget increases the internal reference count. */ + Assert(hr == D3D_OK); + + hr = mpDevice->SetVertexDeclaration(pContext->d3dState.pVertexDecl); + Assert(hr == D3D_OK); + + hr = mpDevice->SetVertexShader(mSaved.pVS); + Assert(hr == D3D_OK); + + hr = mpDevice->SetPixelShader(mSaved.pPS); + Assert(hr == D3D_OK); + + hr = mpDevice->SetTexture(0, mSaved.pTexture); + D3D_RELEASE(mSaved.pTexture); /* GetTexture increases the internal reference count. */ + Assert(hr == D3D_OK); + + hr = mpDevice->SetVertexShaderConstantF(0, mSaved.aVSConstantData, 1); + Assert(hr == D3D_OK); + + hr = mpDevice->SetPixelShaderConstantF(0, mSaved.aPSConstantData, 1); + Assert(hr == D3D_OK); + + for (uint32_t i = 0; i < RT_ELEMENTS(mSaved.aSamplerState); ++i) + { + hr = mpDevice->SetSamplerState(0, mSaved.aSamplerState[i].Type, mSaved.aSamplerState[i].Value); + Assert(hr == D3D_OK); + } + + return hr; +} + +HRESULT D3D9Conversion::initConversion() +{ + static D3DVERTEXELEMENT9 const aVertexElements[] = + { + {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + + HRESULT hr = mpDevice->CreateVertexDeclaration(aVertexElements, &mpVertexDecl); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->CreateVertexBuffer(6 * sizeof(Vertex), + 0, /* D3DUSAGE_* */ + 0, /* FVF */ + D3DPOOL_DEFAULT, + &mpVB, + 0); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->CreateVertexShader(mParameters.paVS, &mpVS); + AssertReturn(hr == D3D_OK, hr); + + hr = mpDevice->CreatePixelShader(mParameters.paPS, &mpPS); + AssertReturn(hr == D3D_OK, hr); + + return hr; +} + +HRESULT D3D9Conversion::setConversionState(IDirect3DTexture9 *pSourceTexture, + uint32_t cWidth, + uint32_t cHeight) +{ + /* Subtract 0.5 to line up the pixel centers with texels + * https://docs.microsoft.com/en-us/windows/win32/direct3d9/directly-mapping-texels-to-pixels + */ + float const xLeft = -0.5f; + float const xRight = (float)(cWidth - 1) - 0.5f; + float const yTop = -0.5f; + float const yBottom = (float)(cHeight - 1) - 0.5f; + + Vertex const aVertices[] = + { + { xLeft, yTop, 0.0f, 0.0f}, + { xRight, yTop, 1.0f, 0.0f}, + { xRight, yBottom, 1.0f, 1.0f}, + + { xLeft, yTop, 0.0f, 0.0f}, + { xRight, yBottom, 1.0f, 1.0f}, + { xLeft, yBottom, 0.0f, 1.0f}, + }; + + HRESULT hr = d3dCopyToVertexBuffer(mpVB, aVertices, sizeof(aVertices)); + AssertReturn(hr == D3D_OK, hr); + + /* No need to save the stream source, because vmsvga3dDrawPrimitives always sets it. */ + hr = mpDevice->SetStreamSource(0, mpVB, 0, sizeof(Vertex)); + AssertReturn(hr == D3D_OK, hr); + + /* Stored in pContext->d3dState.pVertexDecl. */ + hr = mpDevice->SetVertexDeclaration(mpVertexDecl); + AssertReturn(hr == D3D_OK, hr); + + /* Saved by saveContextState. */ + hr = mpDevice->SetVertexShader(mpVS); + AssertReturn(hr == D3D_OK, hr); + + /* Saved by saveContextState. */ + hr = mpDevice->SetPixelShader(mpPS); + AssertReturn(hr == D3D_OK, hr); + + /* Saved by saveContextState. */ + hr = mpDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + AssertReturn(hr == D3D_OK, hr); + + /* Saved by saveContextState. */ + hr = mpDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + AssertReturn(hr == D3D_OK, hr); + + /* Saved by saveContextState. */ + hr = mpDevice->SetTexture(0, pSourceTexture); + AssertReturn(hr == D3D_OK, hr); + + float aTextureInfo[4]; + aTextureInfo[0] = (float)cWidth; + aTextureInfo[1] = (float)cHeight; + aTextureInfo[2] = 1.0f / (float)cWidth; /* Pixel width in texture coords. */ + aTextureInfo[3] = 1.0f / (float)cHeight; /* Pixel height in texture coords. */ + + /* Saved by saveContextState. */ + hr = mpDevice->SetVertexShaderConstantF(0, aTextureInfo, 1); + AssertReturn(hr == D3D_OK, hr); + + /* Saved by saveContextState. */ + hr = mpDevice->SetPixelShaderConstantF(0, aTextureInfo, 1); + AssertReturn(hr == D3D_OK, hr); + + /* Saved by saveContextState. */ + hr = mpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + AssertReturn(hr == D3D_OK, hr); + hr = mpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + AssertReturn(hr == D3D_OK, hr); + hr = mpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); + AssertReturn(hr == D3D_OK, hr); + + return hr; +} + + +HRESULT D3D9Conversion::SelectConversion(D3DFORMAT d3dfmtFrom, D3DFORMAT d3dfmtTo) +{ + /** @todo d3d9SelectConversion should be a member. Move the code here? */ + HRESULT hr = d3d9SelectConversion(d3dfmtFrom, d3dfmtTo, &mParameters); + return hr; +} + +HRESULT D3D9Conversion::ConvertTexture(PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pSurface, + Direction enmDirection) +{ + IDirect3DTexture9 *pSourceTexture; + IDirect3DTexture9 *pTargetTexture; + D3D9TextureType enmTargetType; + + if (enmDirection == FromEmulated) + { + pSourceTexture = pSurface->emulated.pTexture; + pTargetTexture = pSurface->u.pTexture; + enmTargetType = D3D9TextureType_Texture; + } + else if (enmDirection == ToEmulated) + { + pSourceTexture = pSurface->u.pTexture; + pTargetTexture = pSurface->emulated.pTexture; + enmTargetType = D3D9TextureType_Emulated; + } + else + AssertFailedReturn(E_INVALIDARG); + + AssertPtrReturn(pSourceTexture, E_INVALIDARG); + AssertPtrReturn(pTargetTexture, E_INVALIDARG); + + HRESULT hr = saveContextState(); + if (hr == D3D_OK) + { + hr = initConversion(); + if (hr == D3D_OK) + { + uint32_t const cWidth = pSurface->paMipmapLevels[0].mipmapSize.width; + uint32_t const cHeight = pSurface->paMipmapLevels[0].mipmapSize.height; + + hr = setConversionState(pSourceTexture, cWidth, cHeight); + if (hr == D3D_OK) + { + hr = mpDevice->BeginScene(); + Assert(hr == D3D_OK); + if (hr == D3D_OK) + { + for (DWORD iFace = 0; iFace < pSurface->cFaces; ++iFace) + { + DWORD const cMipLevels = pTargetTexture->GetLevelCount(); + for (DWORD iMipmap = 0; iMipmap < cMipLevels && hr == D3D_OK; ++iMipmap) + { + IDirect3DSurface9 *pRT = NULL; + hr = D3D9GetTextureLevel(pSurface, enmTargetType, iFace, iMipmap, &pRT); + Assert(hr == D3D_OK); + if (hr == D3D_OK) + { + hr = mpDevice->SetRenderTarget(0, pRT); + Assert(hr == D3D_OK); + if (hr == D3D_OK) + { + hr = mpDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); + Assert(hr == D3D_OK); + } + + D3D_RELEASE(pRT); + } + } + } + + hr = mpDevice->EndScene(); + Assert(hr == D3D_OK); + } + } + } + + hr = restoreContextState(pContext); + } + + destroyConversion(); + + return hr; +} + + +HRESULT D3D9UpdateTexture(PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pSurface) +{ + HRESULT hr = S_OK; + + if (pSurface->formatD3D == pSurface->d3dfmtRequested) + { + hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->u.pTexture); + } + else + { + if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE) + { + hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->emulated.pTexture); + if (hr == D3D_OK) + { + D3D9Conversion conv(pContext->pDevice); + hr = conv.SelectConversion(pSurface->d3dfmtRequested, pSurface->formatD3D); + if (hr == D3D_OK) + { + hr = conv.ConvertTexture(pContext, pSurface, D3D9Conversion::FromEmulated); + } + } + } + else + { + /** @todo Cubemaps and maybe volume textures. */ + hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->u.pTexture); + } + } + + return hr; +} + +HRESULT D3D9GetSurfaceLevel(PVMSVGA3DSURFACE pSurface, + uint32_t uFace, + uint32_t uMipmap, + bool fBounce, + IDirect3DSurface9 **ppD3DSurface) +{ + HRESULT hr; + + if ( pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE + || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE) + { + D3D9TextureType enmType; + if (fBounce) + enmType = D3D9TextureType_Bounce; + else if (pSurface->formatD3D != pSurface->d3dfmtRequested) + enmType = D3D9TextureType_Emulated; + else + enmType = D3D9TextureType_Texture; + + hr = D3D9GetTextureLevel(pSurface, enmType, uFace, uMipmap, ppD3DSurface); + } + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_SURFACE) + { + pSurface->u.pSurface->AddRef(); + *ppD3DSurface = pSurface->u.pSurface; + hr = S_OK; + } + else + { + AssertMsgFailed(("No surface for type %d\n", pSurface->enmD3DResType)); + hr = E_INVALIDARG; + } + + return hr; +} + +/** Copy the texture content to the bounce texture. + */ +HRESULT D3D9GetRenderTargetData(PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pSurface, + uint32_t uFace, + uint32_t uMipmap) +{ + HRESULT hr; + + /* Get the corresponding bounce texture surface. */ + IDirect3DSurface9 *pDst = NULL; + hr = D3D9GetSurfaceLevel(pSurface, uFace, uMipmap, true, &pDst); + AssertReturn(hr == D3D_OK, hr); + + /* Get the actual texture surface, emulated or actual. */ + IDirect3DSurface9 *pSrc = NULL; + hr = D3D9GetSurfaceLevel(pSurface, uFace, uMipmap, false, &pSrc); + AssertReturnStmt(hr == D3D_OK, + D3D_RELEASE(pDst), hr); + + Assert(pDst != pSrc); + + if (pSurface->formatD3D == pSurface->d3dfmtRequested) + { + hr = pContext->pDevice->GetRenderTargetData(pSrc, pDst); + AssertMsg(hr == D3D_OK, ("GetRenderTargetData failed with %x\n", hr)); + } + else + { + D3D9Conversion conv(pContext->pDevice); + hr = conv.SelectConversion(pSurface->formatD3D, pSurface->d3dfmtRequested); + if (hr == D3D_OK) + { + hr = conv.ConvertTexture(pContext, pSurface, D3D9Conversion::ToEmulated); + } + + if (hr == D3D_OK) + { + hr = pContext->pDevice->GetRenderTargetData(pSrc, pDst); + AssertMsg(hr == D3D_OK, ("GetRenderTargetData failed with %x\n", hr)); + } + } + + D3D_RELEASE(pSrc); + D3D_RELEASE(pDst); + return hr; +} + +D3DFORMAT D3D9GetActualFormat(PVMSVGA3DSTATE pState, D3DFORMAT d3dfmtRequested) +{ + RT_NOREF(pState); + + switch (d3dfmtRequested) + { + case D3DFMT_UYVY: + if (!pState->fSupportedFormatUYVY) return D3DFMT_A8R8G8B8; + break; + case D3DFMT_YUY2: + if (!pState->fSupportedFormatYUY2) return D3DFMT_A8R8G8B8; + break; + case D3DFMT_A8B8G8R8: + if (!pState->fSupportedFormatA8B8G8R8) return D3DFMT_A8R8G8B8; + break; + default: + break; + } + + /* Use the requested format. No emulation required. */ + return d3dfmtRequested; +} + +bool D3D9CheckDeviceFormat(IDirect3D9 *pD3D9, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) +{ + HRESULT hr = pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */ + Usage, + RType, + CheckFormat); + return (hr == D3D_OK); +} diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp new file mode 100644 index 00000000..2fe5ae8f --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp @@ -0,0 +1,6453 @@ +/* $Id: DevVGA-SVGA3d-win.cpp $ */ +/** @file + * DevVMWare - VMWare SVGA device + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include /* required by DevVGA.h */ + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#include "DevVGA-SVGA3d-internal.h" + +/* Enable to disassemble defined shaders. */ +#if defined(DEBUG) && 0 /* Disabled as we don't have the DirectX SDK avaible atm. */ +#define DUMP_SHADER_DISASSEMBLY +#endif + +#ifdef DUMP_SHADER_DISASSEMBLY +#include +#endif + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ + +#define FOURCC_INTZ (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z') +#define FOURCC_NULL (D3DFORMAT)MAKEFOURCC('N', 'U', 'L', 'L') + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ + +typedef struct +{ + DWORD Usage; + D3DRESOURCETYPE ResourceType; + SVGA3dFormatOp FormatOp; +} VMSVGA3DFORMATSUPPORT; + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +static VMSVGA3DFORMATSUPPORT const g_aFormatSupport[] = +{ + { + 0, + D3DRTYPE_SURFACE, + SVGA3DFORMAT_OP_OFFSCREENPLAIN, + }, + { + D3DUSAGE_RENDERTARGET, + D3DRTYPE_SURFACE, + (SVGA3dFormatOp) (SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET | SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET), + }, + { + D3DUSAGE_AUTOGENMIPMAP, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_AUTOGENMIPMAP, + }, + { + D3DUSAGE_DMAP, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_DMAP, + }, + { + 0, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_TEXTURE, + }, + { + 0, + D3DRTYPE_CUBETEXTURE, + SVGA3DFORMAT_OP_CUBETEXTURE, + }, + { + 0, + D3DRTYPE_VOLUMETEXTURE, + SVGA3DFORMAT_OP_VOLUMETEXTURE, + }, + { + D3DUSAGE_QUERY_VERTEXTEXTURE, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_VERTEXTEXTURE, + }, + { + D3DUSAGE_QUERY_LEGACYBUMPMAP, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_BUMPMAP, + }, + { + D3DUSAGE_QUERY_SRGBREAD, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_SRGBREAD, + }, + { + D3DUSAGE_QUERY_SRGBWRITE, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_SRGBWRITE, + } +}; + +static VMSVGA3DFORMATSUPPORT const g_aFeatureReject[] = +{ + { + D3DUSAGE_QUERY_WRAPANDMIP, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP + }, + { + D3DUSAGE_QUERY_FILTER, + D3DRTYPE_TEXTURE, + SVGA3DFORMAT_OP_NOFILTER + }, + { + D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, + D3DRTYPE_TEXTURE, /* ?? */ + SVGA3DFORMAT_OP_NOALPHABLEND + }, +}; + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ +static void vmsvgaDumpD3DCaps(D3DCAPS9 *pCaps, D3DADAPTER_IDENTIFIER9 const *pai9); +static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid); +static DECLCALLBACK(int) vmsvga3dBackSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState); +static DECLCALLBACK(int) vmsvga3dBackSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target); +static DECLCALLBACK(int) vmsvga3dBackSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState); +static DECLCALLBACK(int) vmsvga3dBackSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect); +static DECLCALLBACK(int) vmsvga3dBackSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect); +static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type); +static DECLCALLBACK(int) vmsvga3dBackShaderSet(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid); +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext); +static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, PVMSVGA3DSURFACE pSurface); + + +DECLINLINE(D3DCUBEMAP_FACES) vmsvga3dCubemapFaceFromIndex(uint32_t iFace) +{ + D3DCUBEMAP_FACES Face; + switch (iFace) + { + case 0: Face = D3DCUBEMAP_FACE_POSITIVE_X; break; + case 1: Face = D3DCUBEMAP_FACE_NEGATIVE_X; break; + case 2: Face = D3DCUBEMAP_FACE_POSITIVE_Y; break; + case 3: Face = D3DCUBEMAP_FACE_NEGATIVE_Y; break; + case 4: Face = D3DCUBEMAP_FACE_POSITIVE_Z; break; + default: + case 5: Face = D3DCUBEMAP_FACE_NEGATIVE_Z; break; + } + return Face; +} + +static DECLCALLBACK(int) vmsvga3dBackInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + RT_NOREF(pDevIns, pThis); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + + /* Create event semaphore. */ + int rc = RTSemEventCreate(&pState->WndRequestSem); + if (RT_FAILURE(rc)) + { + Log(("%s: Failed to create event semaphore for window handling.\n", __FUNCTION__)); + return rc; + } + + /* Create the async IO thread. */ + rc = RTThreadCreate(&pState->pWindowThread, vmsvga3dWindowThread, pState->WndRequestSem, 0, RTTHREADTYPE_GUI, 0, "VMSVGA3DWND"); + if (RT_FAILURE(rc)) + { + AssertMsgFailed(("%s: Async IO Thread creation for 3d window handling failed rc=%d\n", __FUNCTION__, rc)); + return rc; + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackPowerOn(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY); + HRESULT hr; + RT_NOREF(pDevIns, pThis); + + if (pState->pD3D9) + return VINF_SUCCESS; /* already initialized (load state) */ + + /* Direct3DCreate9Ex was introduced in Vista, so resolve it dynamically. */ + typedef HRESULT (WINAPI *PFNDIRECT3DCREATE9EX)(UINT, IDirect3D9Ex **); + PFNDIRECT3DCREATE9EX pfnDirect3dCreate9Ex = (PFNDIRECT3DCREATE9EX)RTLdrGetSystemSymbol("d3d9.dll", "Direct3DCreate9Ex"); + if (!pfnDirect3dCreate9Ex) + return PDMDevHlpVMSetError(pDevIns, VERR_SYMBOL_NOT_FOUND, RT_SRC_POS, + "vmsvga3d: Unable to locate Direct3DCreate9Ex. This feature requires Vista and later."); + hr = pfnDirect3dCreate9Ex(D3D_SDK_VERSION, &pState->pD3D9); + AssertReturn(hr == D3D_OK, VERR_INTERNAL_ERROR); + + D3DADAPTER_IDENTIFIER9 ai9; + hr = pState->pD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &ai9); + AssertReturnStmt(hr == D3D_OK, D3D_RELEASE(pState->pD3D9), VERR_INTERNAL_ERROR); + + hr = pState->pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &pState->caps); + AssertReturnStmt(hr == D3D_OK, D3D_RELEASE(pState->pD3D9), VERR_INTERNAL_ERROR); + + vmsvgaDumpD3DCaps(&pState->caps, &ai9); + + if (!D3D9CheckDeviceFormat(pState->pD3D9, 0, D3DRTYPE_TEXTURE, FOURCC_INTZ)) + { + /* INTZ support is essential to support depth surfaces used as textures. */ + LogRel(("VMSVGA: texture format INTZ not supported!!!\n")); + } + else + pState->fSupportedSurfaceINTZ = true; + + if (!D3D9CheckDeviceFormat(pState->pD3D9, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, FOURCC_NULL)) + { + /* NULL is a dummy surface which can be used as a render target to save memory. */ + LogRel(("VMSVGA: surface format NULL not supported!!!\n")); + } + else + pState->fSupportedSurfaceNULL = true; + + /* Check if DX9 depth stencil textures are supported */ + if (!D3D9CheckDeviceFormat(pState->pD3D9, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_D16)) + { + LogRel(("VMSVGA: texture format D3DFMT_D16 not supported\n")); + } + + if (!D3D9CheckDeviceFormat(pState->pD3D9, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_D24X8)) + { + LogRel(("VMSVGA: texture format D3DFMT_D24X8 not supported\n")); + } + + if (!D3D9CheckDeviceFormat(pState->pD3D9, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_D24S8)) + { + LogRel(("VMSVGA: texture format D3DFMT_D24S8 not supported\n")); + } + + /* Check some formats must be emulated. */ + if (D3D9CheckDeviceFormat(pState->pD3D9, 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY)) + { + /* Native UYVY support has better performance. */ + LogRel(("VMSVGA: texture format D3DFMT_UYVY supported\n")); + pState->fSupportedFormatUYVY = true; + } + + if (D3D9CheckDeviceFormat(pState->pD3D9, 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2)) + { + /* Native YUY2 support has better performance. */ + LogRel(("VMSVGA: texture format D3DFMT_YUY2 supported\n")); + pState->fSupportedFormatYUY2 = true; + } + + if (D3D9CheckDeviceFormat(pState->pD3D9, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_A8B8G8R8)) + { + /* Native A8B8G8R8 support is good for OpenGL application in the guest. */ + LogRel(("VMSVGA: texture format D3DFMT_A8B8G8R8 supported\n")); + pState->fSupportedFormatA8B8G8R8 = true; + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackReset(PVGASTATECC pThisCC) +{ + RT_NOREF(pThisCC); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackTerminate(PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY); + + /* Terminate the window creation thread. */ + int rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_EXIT, 0, 0); + AssertRCReturn(rc, rc); + + RTSemEventDestroy(pState->WndRequestSem); + + D3D_RELEASE(pState->pD3D9); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(void) vmsvga3dBackUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport) +{ + /** @todo Scroll the screen content without requiring the guest to redraw. */ + RT_NOREF(pThisCC, idScreen, pOldViewport); +} + +static uint32_t vmsvga3dGetSurfaceFormatSupport(PVMSVGA3DSTATE pState3D, uint32_t idx3dCaps, D3DFORMAT format) +{ + NOREF(idx3dCaps); + HRESULT hr; + uint32_t result = 0; + + /* Try if the format can be used for the primary display. */ + hr = pState3D->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + format, + 0, + D3DRTYPE_SURFACE, + format); + + for (unsigned i = 0; i < RT_ELEMENTS(g_aFormatSupport); i++) + { + hr = pState3D->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */ + g_aFormatSupport[i].Usage, + g_aFormatSupport[i].ResourceType, + format); + if (hr == D3D_OK) + result |= g_aFormatSupport[i].FormatOp; + } + + /* Check for features only if the format is supported in any form. */ + if (result) + { + for (unsigned i = 0; i < RT_ELEMENTS(g_aFeatureReject); i++) + { + hr = pState3D->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */ + g_aFeatureReject[i].Usage, + g_aFeatureReject[i].ResourceType, + format); + if (hr != D3D_OK) + result |= g_aFeatureReject[i].FormatOp; + } + } + + /** @todo missing: + * + * SVGA3DFORMAT_OP_PIXELSIZE + */ + + switch (idx3dCaps) + { + case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: + result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB + | SVGA3DFORMAT_OP_CONVERT_TO_ARGB + | SVGA3DFORMAT_OP_DISPLAYMODE /* Should not be set for alpha formats. */ + | SVGA3DFORMAT_OP_3DACCELERATION; /* implies OP_DISPLAYMODE */ + break; + + case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: + case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: + case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: + case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: + result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB + | SVGA3DFORMAT_OP_CONVERT_TO_ARGB + | SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET; + break; + /* These formats can't be used as textures on AMD drivers (Intel works). + * Still report them as textures to the guest and emulate them in the device. + */ + case SVGA3D_DEVCAP_SURFACEFMT_UYVY: + case SVGA3D_DEVCAP_SURFACEFMT_YUY2: + result |= SVGA3DFORMAT_OP_TEXTURE; + break; + } + Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result))); + + return result; +} + +static uint32_t vmsvga3dGetDepthFormatSupport(PVMSVGA3DSTATE pState3D, uint32_t idx3dCaps, D3DFORMAT format) +{ + RT_NOREF(idx3dCaps); + HRESULT hr; + uint32_t result = 0; + + hr = pState3D->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */ + D3DUSAGE_DEPTHSTENCIL, + D3DRTYPE_SURFACE, + format); + if (hr == D3D_OK) + result = SVGA3DFORMAT_OP_ZSTENCIL + | SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH + | SVGA3DFORMAT_OP_TEXTURE /* Necessary for Ubuntu Unity */; + + Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result))); + return result; +} + + +static DECLCALLBACK(int) vmsvga3dBackQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + D3DCAPS9 *pCaps = &pState->caps; + int rc = VINF_SUCCESS; + + *pu32Val = 0; + + switch (idx3dCaps) + { + case SVGA3D_DEVCAP_3D: + *pu32Val = 1; /* boolean? */ + break; + + case SVGA3D_DEVCAP_MAX_LIGHTS: + *pu32Val = pCaps->MaxActiveLights; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURES: + *pu32Val = pCaps->MaxSimultaneousTextures; + break; + + case SVGA3D_DEVCAP_MAX_CLIP_PLANES: + *pu32Val = pCaps->MaxUserClipPlanes; + break; + + case SVGA3D_DEVCAP_VERTEX_SHADER_VERSION: + switch (pCaps->VertexShaderVersion) + { + case D3DVS_VERSION(1,1): + *pu32Val = SVGA3DVSVERSION_11; + break; + case D3DVS_VERSION(2,0): + *pu32Val = SVGA3DVSVERSION_20; + break; + case D3DVS_VERSION(3,0): + *pu32Val = SVGA3DVSVERSION_30; + break; + case D3DVS_VERSION(4,0): + *pu32Val = SVGA3DVSVERSION_40; + break; + default: + LogRel(("VMSVGA: Unsupported vertex shader version %x\n", pCaps->VertexShaderVersion)); + break; + } + break; + + case SVGA3D_DEVCAP_VERTEX_SHADER: + /* boolean? */ + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION: + switch (pCaps->PixelShaderVersion) + { + case D3DPS_VERSION(1,1): + *pu32Val = SVGA3DPSVERSION_11; + break; + case D3DPS_VERSION(1,2): + *pu32Val = SVGA3DPSVERSION_12; + break; + case D3DPS_VERSION(1,3): + *pu32Val = SVGA3DPSVERSION_13; + break; + case D3DPS_VERSION(1,4): + *pu32Val = SVGA3DPSVERSION_14; + break; + case D3DPS_VERSION(2,0): + *pu32Val = SVGA3DPSVERSION_20; + break; + case D3DPS_VERSION(3,0): + *pu32Val = SVGA3DPSVERSION_30; + break; + case D3DPS_VERSION(4,0): + *pu32Val = SVGA3DPSVERSION_40; + break; + default: + LogRel(("VMSVGA: Unsupported pixel shader version %x\n", pCaps->PixelShaderVersion)); + break; + } + break; + + case SVGA3D_DEVCAP_FRAGMENT_SHADER: + /* boolean? */ + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_S23E8_TEXTURES: + case SVGA3D_DEVCAP_S10E5_TEXTURES: + /* Must be obsolete by now; surface format caps specify the same thing. */ + rc = VERR_INVALID_PARAMETER; + break; + + case SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND: + break; + + /* + * 2. The BUFFER_FORMAT capabilities are deprecated, and they always + * return TRUE. Even on physical hardware that does not support + * these formats natively, the SVGA3D device will provide an emulation + * which should be invisible to the guest OS. + */ + case SVGA3D_DEVCAP_D16_BUFFER_FORMAT: + case SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT: + case SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT: + *pu32Val = 1; + break; + + case SVGA3D_DEVCAP_QUERY_TYPES: + break; + + case SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING: + break; + + case SVGA3D_DEVCAP_MAX_POINT_SIZE: + AssertCompile(sizeof(uint32_t) == sizeof(float)); + *(float *)pu32Val = pCaps->MaxPointSize; + break; + + case SVGA3D_DEVCAP_MAX_SHADER_TEXTURES: + /** @todo ?? */ + rc = VERR_INVALID_PARAMETER; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH: + *pu32Val = pCaps->MaxTextureWidth; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT: + *pu32Val = pCaps->MaxTextureHeight; + break; + + case SVGA3D_DEVCAP_MAX_VOLUME_EXTENT: + *pu32Val = pCaps->MaxVolumeExtent; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT: + *pu32Val = pCaps->MaxTextureRepeat; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO: + *pu32Val = pCaps->MaxTextureAspectRatio; + break; + + case SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY: + *pu32Val = pCaps->MaxAnisotropy; + break; + + case SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT: + *pu32Val = pCaps->MaxPrimitiveCount; + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_INDEX: + *pu32Val = pCaps->MaxVertexIndex; + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS: + *pu32Val = pCaps->MaxVertexShader30InstructionSlots; + break; + + case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS: + *pu32Val = pCaps->MaxPixelShader30InstructionSlots; + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS: + *pu32Val = pCaps->VS20Caps.NumTemps; + break; + + case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS: + *pu32Val = pCaps->PS20Caps.NumTemps; + break; + + case SVGA3D_DEVCAP_TEXTURE_OPS: + break; + + case SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */ + break; + + case SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */ + break; + + case SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */ + break; + + case SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */ + break; + + case SVGA3D_DEVCAP_AUTOGENMIPMAPS: + *pu32Val = !!(pCaps->Caps2 & D3DCAPS2_CANAUTOGENMIPMAP); + break; + + case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES: + break; + + case SVGA3D_DEVCAP_MAX_RENDER_TARGETS: /** @todo same thing? */ + case SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS: + *pu32Val = pCaps->NumSimultaneousRTs; + break; + + /* + * This is the maximum number of SVGA context IDs that the guest + * can define using SVGA_3D_CMD_CONTEXT_DEFINE. + */ + case SVGA3D_DEVCAP_MAX_CONTEXT_IDS: + *pu32Val = SVGA3D_MAX_CONTEXT_IDS; + break; + + /* + * This is the maximum number of SVGA surface IDs that the guest + * can define using SVGA_3D_CMD_SURFACE_DEFINE*. + */ + case SVGA3D_DEVCAP_MAX_SURFACE_IDS: + *pu32Val = SVGA3D_MAX_SURFACE_IDS; + break; + + /* Supported surface formats. */ + case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_X8R8G8B8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A8R8G8B8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A2R10G10B10); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_X1R5G5B5); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A1R5G5B5); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A4R4G4B4); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_R5G6B5); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_L16); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A8L8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_L8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_Z_D16: + *pu32Val = vmsvga3dGetDepthFormatSupport(pState, idx3dCaps, D3DFMT_D16); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: /** @todo not correct */ + *pu32Val = vmsvga3dGetDepthFormatSupport(pState, idx3dCaps, D3DFMT_D24S8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: + *pu32Val = vmsvga3dGetDepthFormatSupport(pState, idx3dCaps, D3DFMT_D24X8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: + /** @todo supposed to be floating-point, but unable to find a match for D3D9... */ + *pu32Val = 0; + break; + + case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: + *pu32Val = vmsvga3dGetDepthFormatSupport(pState, idx3dCaps, D3DFMT_D24FS8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_DXT1: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT1); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_DXT2: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT2); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_DXT3: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT3); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_DXT4: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT4); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_DXT5: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT5); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_X8L8V8U8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A2W10V10U10); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_V8U8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_Q8W8V8U8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_CxV8U8); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_R16F); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_R32F); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_G16R16F); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_G32R32F); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A16B16G16R16F); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A32B32G32R32F); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_V16U16: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_V16U16); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_G16R16: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_G16R16); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A16B16G16R16); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_UYVY: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_UYVY); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_YUY2: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_YUY2); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_NV12: + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2')); + break; + + case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */ + *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, (D3DFORMAT)MAKEFOURCC('A', 'Y', 'U', 'V')); + break; + + case SVGA3D_DEVCAP_SURFACEFMT_ATI1: + case SVGA3D_DEVCAP_SURFACEFMT_ATI2: + /* Unknown; only in DX10 & 11 */ + Log(("CAPS: Unknown CAP %s\n", vmsvga3dGetCapString(idx3dCaps))); + rc = VERR_INVALID_PARAMETER; + *pu32Val = 0; + break; + + default: + Log(("CAPS: Unexpected CAP %d\n", idx3dCaps)); + rc = VERR_INVALID_PARAMETER; + break; + } +#if 0 + /* Dump of VMWare Player caps (from their log); for debugging purposes */ + switch (idx3dCaps) + { + case 0: + *pu32Val = 0x00000001; + break; + case 1: + *pu32Val = 0x0000000a; + break; + case 2: + *pu32Val = 0x00000008; + break; + case 3: *pu32Val = 0x00000006; break; + case 4: *pu32Val = 0x00000007; break; + case 5: *pu32Val = 0x00000001; break; + case 6: *pu32Val = 0x0000000d; break; + case 7: *pu32Val = 0x00000001; break; + case 8: *pu32Val = 0x00000004; break; + case 9: *pu32Val = 0x00000001; break; + case 10: *pu32Val = 0x00000001; break; + case 11: *pu32Val = 0x00000004; break; + case 12: *pu32Val = 0x00000001; break; + case 13: *pu32Val = 0x00000001; break; + case 14: *pu32Val = 0x00000001; break; + case 15: *pu32Val = 0x00000001; break; + case 16: *pu32Val = 0x00000001; break; + case 17: *pu32Val = (uint32_t)256.000000; break; + case 18: *pu32Val = 0x00000014; break; + case 19: *pu32Val = 0x00001000; break; + case 20: *pu32Val = 0x00001000; break; + case 21: *pu32Val = 0x00000800; break; + case 22: *pu32Val = 0x00002000; break; + case 23: *pu32Val = 0x00000800; break; + case 24: *pu32Val = 0x00000010; break; + case 25: *pu32Val = 0x000fffff; break; + case 26: *pu32Val = 0x00ffffff; break; + case 27: *pu32Val = 0xffffffff; break; + case 28: *pu32Val = 0xffffffff; break; + case 29: *pu32Val = 0x00000020; break; + case 30: *pu32Val = 0x00000020; break; + case 31: *pu32Val = 0x03ffffff; break; + case 32: *pu32Val = 0x0098ec1f; break; + case 33: *pu32Val = 0x0098e11f; break; + case 34: *pu32Val = 0x0098e01f; break; + case 35: *pu32Val = 0x012c2000; break; + case 36: *pu32Val = 0x0098e11f; break; + case 37: *pu32Val = 0x0090c11f; break; + case 38: *pu32Val = 0x0098ec1f; break; + case 39: *pu32Val = 0x00804007; break; + case 40: *pu32Val = 0x0080c007; break; + case 41: *pu32Val = 0x00804007; break; + case 42: *pu32Val = 0x0080c007; break; + case 43: *pu32Val = 0x000000c1; break; + case 44: *pu32Val = 0x000000c1; break; + case 45: *pu32Val = 0x000000c1; break; + case 46: *pu32Val = 0x00808005; break; + case 47: *pu32Val = 0x00808005; break; + case 48: *pu32Val = 0x00808005; break; + case 49: *pu32Val = 0x00808005; break; + case 50: *pu32Val = 0x00808005; break; + case 51: *pu32Val = 0x01240000; break; + case 52: *pu32Val = 0x00814007; break; + case 53: *pu32Val = 0x00814007; break; + case 54: *pu32Val = 0x00814007; break; + case 55: *pu32Val = 0x01240000; break; + case 56: *pu32Val = 0x0080401f; break; + case 57: *pu32Val = 0x0080401f; break; + case 58: *pu32Val = 0x0080401f; break; + case 59: *pu32Val = 0x0080401f; break; + case 60: *pu32Val = 0x0080601f; break; + case 61: *pu32Val = 0x0080401f; break; + case 62: *pu32Val = 0x00000000; break; + case 63: *pu32Val = 0x00000004; break; + case 64: *pu32Val = 0x00000004; break; + case 65: *pu32Val = 0x00814005; break; + case 66: *pu32Val = 0x0080401f; break; + case 67: *pu32Val = 0x0080601f; break; + case 68: *pu32Val = 0x00006009; break; + case 69: *pu32Val = 0x00006001; break; + case 70: *pu32Val = 0x00000001; break; + case 71: *pu32Val = 0x0000000b; break; + case 72: *pu32Val = 0x00000001; break; + case 73: *pu32Val = 0x00000000; break; + case 74: *pu32Val = 0x00000000; break; + case 75: *pu32Val = 0x01246000; break; + case 76: *pu32Val = 0x00004009; break; + case 77: *pu32Val = 0x00000100; break; + case 78: *pu32Val = 0x00008000; break; + case 79: *pu32Val = 0x000000c1; break; + case 80: *pu32Val = 0x01240000; break; + case 81: *pu32Val = 0x000000c1; break; + case 82: *pu32Val = 0x00800005; break; + case 83: *pu32Val = 0x00800005; break; + case 84: *pu32Val = 0x00000000; break; + case 85: *pu32Val = 0x00000000; break; + case 86: *pu32Val = 0x00000000; break; + case 87: *pu32Val = 0x00000000; break; + case 88: *pu32Val = 0x00000000; break; + case 89: *pu32Val = (uint32_t) 0.000000; break; + case 90: *pu32Val = (uint32_t) 0.000000; break; + case 91: *pu32Val = 0x00006009; break; + default: +// Log(("CAPS: Unexpected CAP %d\n", idx3dCaps)); +// rc = VERR_INVALID_PARAMETER; + break; + } +#endif + Log(("CAPS: %d=%s - %x\n", idx3dCaps, vmsvga3dGetCapString(idx3dCaps), *pu32Val)); + return rc; +} + +/** + * Convert SVGA format value to its D3D equivalent + */ +D3DFORMAT vmsvga3dSurfaceFormat2D3D(SVGA3dSurfaceFormat format) +{ + switch (format) + { + case SVGA3D_X8R8G8B8: + return D3DFMT_X8R8G8B8; + case SVGA3D_A8R8G8B8: + return D3DFMT_A8R8G8B8; + case SVGA3D_R5G6B5: + return D3DFMT_R5G6B5; + case SVGA3D_X1R5G5B5: + return D3DFMT_X1R5G5B5; + case SVGA3D_A1R5G5B5: + return D3DFMT_A1R5G5B5; + case SVGA3D_A4R4G4B4: + return D3DFMT_A4R4G4B4; + + case SVGA3D_R8G8B8A8_UNORM: + return D3DFMT_A8B8G8R8; + + case SVGA3D_Z_D32: + return D3DFMT_D32; + case SVGA3D_Z_D16: + return D3DFMT_D16; + case SVGA3D_Z_D24S8_INT: /** @todo not correct */ + case SVGA3D_Z_D24S8: + return D3DFMT_D24S8; + case SVGA3D_Z_D15S1: + return D3DFMT_D15S1; + case SVGA3D_Z_D24X8: + return D3DFMT_D24X8; + /* Advanced D3D9 depth formats. */ + case SVGA3D_Z_DF16: + /** @todo supposed to be floating-point, but unable to find a match for D3D9... */ + AssertFailedReturn(D3DFMT_UNKNOWN); + case SVGA3D_Z_DF24: + return D3DFMT_D24FS8; + + case SVGA3D_LUMINANCE8: + return D3DFMT_L8; + case SVGA3D_LUMINANCE4_ALPHA4: + return D3DFMT_A4L4; + case SVGA3D_LUMINANCE16: + return D3DFMT_L16; + case SVGA3D_LUMINANCE8_ALPHA8: + return D3DFMT_A8L8; + + case SVGA3D_DXT1: + return D3DFMT_DXT1; + case SVGA3D_DXT2: + return D3DFMT_DXT2; + case SVGA3D_DXT3: + return D3DFMT_DXT3; + case SVGA3D_DXT4: + return D3DFMT_DXT4; + case SVGA3D_DXT5: + return D3DFMT_DXT5; + + /* Bump-map formats */ + case SVGA3D_BUMPU8V8: + return D3DFMT_V8U8; + case SVGA3D_BUMPL6V5U5: + return D3DFMT_L6V5U5; + case SVGA3D_BUMPX8L8V8U8: + return D3DFMT_X8L8V8U8; + case SVGA3D_FORMAT_DEAD1: + /* No corresponding D3D9 equivalent. */ + AssertFailedReturn(D3DFMT_UNKNOWN); + /* signed bump-map formats */ + case SVGA3D_V8U8: + return D3DFMT_V8U8; + case SVGA3D_Q8W8V8U8: + return D3DFMT_Q8W8V8U8; + case SVGA3D_CxV8U8: + return D3DFMT_CxV8U8; + /* mixed bump-map formats */ + case SVGA3D_X8L8V8U8: + return D3DFMT_X8L8V8U8; + case SVGA3D_A2W10V10U10: + return D3DFMT_A2W10V10U10; + + case SVGA3D_ARGB_S10E5: /* 16-bit floating-point ARGB */ + return D3DFMT_A16B16G16R16F; + case SVGA3D_ARGB_S23E8: /* 32-bit floating-point ARGB */ + return D3DFMT_A32B32G32R32F; + + case SVGA3D_A2R10G10B10: + return D3DFMT_A2R10G10B10; + + case SVGA3D_ALPHA8: + return D3DFMT_A8; + + /* Single- and dual-component floating point formats */ + case SVGA3D_R_S10E5: + return D3DFMT_R16F; + case SVGA3D_R_S23E8: + return D3DFMT_R32F; + case SVGA3D_RG_S10E5: + return D3DFMT_G16R16F; + case SVGA3D_RG_S23E8: + return D3DFMT_G32R32F; + + /* + * Any surface can be used as a buffer object, but SVGA3D_BUFFER is + * the most efficient format to use when creating new surfaces + * expressly for index or vertex data. + */ + case SVGA3D_BUFFER: + return D3DFMT_UNKNOWN; + + case SVGA3D_V16U16: + return D3DFMT_V16U16; + + case SVGA3D_G16R16: + return D3DFMT_G16R16; + case SVGA3D_A16B16G16R16: + return D3DFMT_A16B16G16R16; + + /* Packed Video formats */ + case SVGA3D_UYVY: + return D3DFMT_UYVY; + case SVGA3D_YUY2: + return D3DFMT_YUY2; + + /* Planar video formats */ + case SVGA3D_NV12: + return (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2'); + + /* Video format with alpha */ + case SVGA3D_FORMAT_DEAD2: /* Old SVGA3D_AYUV */ + return (D3DFORMAT)MAKEFOURCC('A', 'Y', 'U', 'V'); + + case SVGA3D_R8G8B8A8_SNORM: + return D3DFMT_Q8W8V8U8; + case SVGA3D_R16G16_UNORM: + return D3DFMT_G16R16; + + case SVGA3D_ATI1: + case SVGA3D_ATI2: + /* Unknown; only in DX10 & 11 */ + break; + + case SVGA3D_FORMAT_MAX: /* shut up MSC */ + case SVGA3D_FORMAT_INVALID: + break; + default: /** @todo Other formats. Avoid MSC warning for now. */ + break; + } + AssertFailedReturn(D3DFMT_UNKNOWN); +} + +/** + * Convert SVGA multi sample count value to its D3D equivalent + */ +D3DMULTISAMPLE_TYPE vmsvga3dMultipeSampleCount2D3D(uint32_t multisampleCount) +{ + AssertCompile(D3DMULTISAMPLE_2_SAMPLES == 2); + AssertCompile(D3DMULTISAMPLE_16_SAMPLES == 16); + + if (multisampleCount > 16) + return D3DMULTISAMPLE_NONE; + + /** @todo exact same mapping as d3d? */ + return (D3DMULTISAMPLE_TYPE)multisampleCount; +} + + +/** + * Destroy backend specific surface bits (part of SVGA_3D_CMD_SURFACE_DESTROY). + * + * @param pThisCC The device state. + * @param fClearCOTableEntry Not relevant for this backend. + * @param pSurface The surface being destroyed. + */ +static DECLCALLBACK(void) vmsvga3dBackSurfaceDestroy(PVGASTATECC pThisCC, bool fClearCOTableEntry, PVMSVGA3DSURFACE pSurface) +{ + RT_NOREF(pThisCC, fClearCOTableEntry); + + RTAvlU32Destroy(&pSurface->pSharedObjectTree, vmsvga3dSharedSurfaceDestroyTree, pSurface); + Assert(pSurface->pSharedObjectTree == NULL); + + switch (pSurface->enmD3DResType) + { + case VMSVGA3D_D3DRESTYPE_SURFACE: + D3D_RELEASE(pSurface->u.pSurface); + break; + + case VMSVGA3D_D3DRESTYPE_TEXTURE: + D3D_RELEASE(pSurface->u.pTexture); + D3D_RELEASE(pSurface->bounce.pTexture); + D3D_RELEASE(pSurface->emulated.pTexture); + break; + + case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE: + D3D_RELEASE(pSurface->u.pCubeTexture); + D3D_RELEASE(pSurface->bounce.pCubeTexture); + D3D_RELEASE(pSurface->emulated.pCubeTexture); + break; + + case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE: + D3D_RELEASE(pSurface->u.pVolumeTexture); + D3D_RELEASE(pSurface->bounce.pVolumeTexture); + D3D_RELEASE(pSurface->emulated.pVolumeTexture); + break; + + case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER: + D3D_RELEASE(pSurface->u.pVertexBuffer); + break; + + case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER: + D3D_RELEASE(pSurface->u.pIndexBuffer); + break; + + default: + AssertMsg(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface), + ("surfaceFlags=0x%x\n", (pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK))); + break; + } + + D3D_RELEASE(pSurface->pQuery); +} + + +static DECLCALLBACK(void) vmsvga3dBackSurfaceInvalidateImage(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface, uint32_t uFace, uint32_t uMipmap) +{ + RT_NOREF(pThisCC, pSurface, uFace, uMipmap); +} + + +/* + * Release all shared surface objects. + */ +DECLCALLBACK(int) vmsvga3dSharedSurfaceDestroyTree(PAVLU32NODECORE pNode, void *pvParam) +{ + PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)pNode; + PVMSVGA3DSURFACE pSurface = (PVMSVGA3DSURFACE)pvParam; + + switch (pSurface->enmD3DResType) + { + case VMSVGA3D_D3DRESTYPE_TEXTURE: + LogFunc(("release shared texture object for context %d\n", pNode->Key)); + Assert(pSharedSurface->u.pTexture); + D3D_RELEASE(pSharedSurface->u.pTexture); + break; + + case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE: + LogFunc(("release shared cube texture object for context %d\n", pNode->Key)); + Assert(pSharedSurface->u.pCubeTexture); + D3D_RELEASE(pSharedSurface->u.pCubeTexture); + break; + + case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE: + LogFunc(("release shared volume texture object for context %d\n", pNode->Key)); + Assert(pSharedSurface->u.pVolumeTexture); + D3D_RELEASE(pSharedSurface->u.pVolumeTexture); + break; + + default: + AssertFailed(); + break; + } + RTMemFree(pNode); + return 0; +} + +/* Get the shared surface copy or create a new one. */ +static PVMSVGA3DSHAREDSURFACE vmsvga3dSurfaceGetSharedCopy(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface) +{ + Assert(pSurface->hSharedObject); + + PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)RTAvlU32Get(&pSurface->pSharedObjectTree, pContext->id); + if (!pSharedSurface) + { + const uint32_t cWidth = pSurface->paMipmapLevels[0].mipmapSize.width; + const uint32_t cHeight = pSurface->paMipmapLevels[0].mipmapSize.height; + const uint32_t cDepth = pSurface->paMipmapLevels[0].mipmapSize.depth; + const uint32_t numMipLevels = pSurface->cLevels; + + LogFunc(("Create shared %stexture copy d3d (%d,%d,%d) cMip=%d usage %x format %x.\n", + pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE ? "volume " : + pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE ? "cube " : + pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE ? "" : "UNKNOWN!!!", + cWidth, + cHeight, + cDepth, + numMipLevels, + pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET, + pSurface->formatD3D)); + + pSharedSurface = (PVMSVGA3DSHAREDSURFACE)RTMemAllocZ(sizeof(*pSharedSurface)); + AssertReturn(pSharedSurface, NULL); + + pSharedSurface->Core.Key = pContext->id; + bool ret = RTAvlU32Insert(&pSurface->pSharedObjectTree, &pSharedSurface->Core); + AssertReturn(ret, NULL); + + /* Create shadow copy of the original shared texture. + * Shared d3d resources require Vista+ and have some restrictions. + * D3DUSAGE_RENDERTARGET is required for use as a StretchRect destination. + */ + HRESULT hr; + if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE) + hr = pContext->pDevice->CreateVolumeTexture(cWidth, + cHeight, + cDepth, + numMipLevels, + pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSharedSurface->u.pVolumeTexture, + &pSurface->hSharedObject); + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE) + hr = pContext->pDevice->CreateCubeTexture(cWidth, + numMipLevels, + pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSharedSurface->u.pCubeTexture, + &pSurface->hSharedObject); + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE) + { + if (pSurface->fStencilAsTexture) + { + /* Use the INTZ format for a depth/stencil surface that will be used as a texture */ + hr = pContext->pDevice->CreateTexture(cWidth, + cHeight, + 1, /* mip levels */ + D3DUSAGE_DEPTHSTENCIL, + FOURCC_INTZ, + D3DPOOL_DEFAULT, + &pSharedSurface->u.pTexture, + &pSurface->hSharedObject); + } + else + { + hr = pContext->pDevice->CreateTexture(cWidth, + cHeight, + numMipLevels, + pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSharedSurface->u.pTexture, + &pSurface->hSharedObject); + } + } + else + hr = E_FAIL; + + if (RT_LIKELY(hr == D3D_OK)) + { + /* Make sure that the created shared copy has the same content as the original. */ + PVMSVGA3DCONTEXT pAssociatedContext; + int rc = vmsvga3dContextFromCid(pState, pSurface->idAssociatedContext, &pAssociatedContext); + if (RT_SUCCESS(rc)) + AssertStmt(pAssociatedContext->pDevice, rc = VERR_INTERNAL_ERROR); + if (RT_SUCCESS(rc)) + { + IDirect3DQuery9 *pQuery; + hr = pAssociatedContext->pDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pQuery); + if (hr == D3D_OK) + { + hr = pQuery->Issue(D3DISSUE_END); + if (hr == D3D_OK) + { + do + { + hr = pQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); + } while (hr == S_FALSE); + } + + D3D_RELEASE(pQuery); + } + } + else + AssertMsgFailed(("idAssociatedContext cid=%u, sid=%u\n", pSurface->idAssociatedContext, pSurface->id)); + } + else + { + AssertMsgFailed(("CreateTexture type %d failed with %x\n", pSurface->enmD3DResType, hr)); + RTAvlU32Remove(&pSurface->pSharedObjectTree, pContext->id); + RTMemFree(pSharedSurface); + return NULL; + } + } + return pSharedSurface; +} + +/* Inject a query event into the D3D pipeline so we can check when usage of this surface has finished. + * (D3D does not synchronize shared surface usage) + */ +static int vmsvga3dSurfaceTrackUsage(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface) +{ + RT_NOREF(pState); + + Assert(pSurface->id != SVGA3D_INVALID_ID); + + /* Nothing to do if this surface hasn't been shared. */ + if (pSurface->pSharedObjectTree == NULL) + return VINF_SUCCESS; + + LogFunc(("track usage of sid=%u (cid=%u) for cid=%u, pQuery %p\n", pSurface->id, pSurface->idAssociatedContext, pContext->id, pSurface->pQuery)); + + if (pSurface->idQueryContext == pContext->id) + { + /* Release the previous query object, if any. */ + D3D_RELEASE(pSurface->pQuery); + } + else + { + /* Different context. There must be no pending drawing operations. If there are any, then a flush is missing. */ + if (pSurface->pQuery) + { + /* Should not happen. */ + AssertFailed(); + + /* Make sure that all drawing has completed. */ + vmsvga3dSurfaceFlush(pSurface); + } + pSurface->idQueryContext = pContext->id; + } + + HRESULT hr = pContext->pDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pSurface->pQuery); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceTrackUsage: CreateQuery failed with %x\n", hr), VERR_INTERNAL_ERROR); + + hr = pSurface->pQuery->Issue(D3DISSUE_END); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceTrackUsage: Issue failed with %x\n", hr), VERR_INTERNAL_ERROR); + + return VINF_SUCCESS; +} + + +/** + * Surface ID based version of vmsvga3dSurfaceTrackUsage. + * + * @returns VBox status code. + * @param pState The VMSVGA3d state. + * @param pContext The context. + * @param sid The surface ID. + */ +static int vmsvga3dSurfaceTrackUsageById(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, uint32_t sid) +{ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + + return vmsvga3dSurfaceTrackUsage(pState, pContext, pSurface); +} + + +/* Wait for all drawing, that uses this surface, to finish. */ +int vmsvga3dSurfaceFlush(PVMSVGA3DSURFACE pSurface) +{ + HRESULT hr; + + if (!pSurface->pQuery) + { + LogFlow(("vmsvga3dSurfaceFlush: no query object\n")); + return VINF_SUCCESS; /* nothing to wait for */ + } + Assert(pSurface->pSharedObjectTree); + + Log(("vmsvga3dSurfaceFlush: wait for draw to finish (sid=%u)\n", pSurface->id)); + while (true) + { + hr = pSurface->pQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); + if (hr != S_FALSE) break; + + RTThreadSleep(1); + } + + D3D_RELEASE(pSurface->pQuery); + + AssertMsgReturn(hr == S_OK, ("vmsvga3dSurfaceFinishDrawing: GetData failed with %x\n", hr), VERR_INTERNAL_ERROR); + + return VINF_SUCCESS; +} + +/** Get IDirect3DSurface9 for the given face and mipmap. + */ +int vmsvga3dGetD3DSurface(PVMSVGA3DSTATE pState, + PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pSurface, + uint32_t face, + uint32_t mipmap, + bool fLockable, + IDirect3DSurface9 **ppD3DSurf) +{ + AssertPtrReturn(pSurface->u.pSurface, VERR_INVALID_PARAMETER); + + IDirect3DBaseTexture9 *pTexture; + if (fLockable && pSurface->bounce.pTexture) + pTexture = pSurface->bounce.pTexture; + else + pTexture = pSurface->u.pTexture; + + if (pSurface->idAssociatedContext != pContext->id) + { + AssertMsgReturn(!fLockable, + ("Lockable surface must be from the same context (surface cid = %d, req cid = %d)", + pSurface->idAssociatedContext, pContext->id), + VERR_INVALID_PARAMETER); + + if ( pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE + || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE) + { + LogFunc(("using texture sid=%u created for another context (%d vs %d)\n", + pSurface->id, pSurface->idAssociatedContext, pContext->id)); + + PVMSVGA3DSHAREDSURFACE pSharedSurface = vmsvga3dSurfaceGetSharedCopy(pState, pContext, pSurface); + AssertReturn(pSharedSurface, VERR_INTERNAL_ERROR); + + pTexture = pSharedSurface->u.pTexture; + } + else + { + AssertMsgFailed(("surface sid=%u created for another context (%d vs %d)\n", + pSurface->id, pSurface->idAssociatedContext, pContext->id)); + } + } + + if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE) + { + Assert(pSurface->cFaces == 6); + + IDirect3DCubeTexture9 *p = (IDirect3DCubeTexture9 *)pTexture; + D3DCUBEMAP_FACES FaceType = vmsvga3dCubemapFaceFromIndex(face); + HRESULT hr = p->GetCubeMapSurface(FaceType, mipmap, ppD3DSurf); + AssertMsgReturn(hr == D3D_OK, ("GetCubeMapSurface failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE) + { + Assert(pSurface->cFaces == 1); + Assert(face == 0); + + IDirect3DTexture9 *p = (IDirect3DTexture9 *)pTexture; + HRESULT hr = p->GetSurfaceLevel(mipmap, ppD3DSurf); + AssertMsgReturn(hr == D3D_OK, ("GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_SURFACE) + { + pSurface->u.pSurface->AddRef(); + *ppD3DSurf = pSurface->u.pSurface; + } + else + { + AssertMsgFailedReturn(("No surface for type %d\n", pSurface->enmD3DResType), VERR_INTERNAL_ERROR); + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src, + uint32_t cCopyBoxes, SVGA3dCopyBox *pBox) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + const uint32_t sidSrc = src.sid; + const uint32_t sidDest = dest.sid; + int rc; + + PVMSVGA3DSURFACE pSurfaceSrc; + rc = vmsvga3dSurfaceFromSid(pState, sidSrc, &pSurfaceSrc); + AssertRCReturn(rc, rc); + + PVMSVGA3DSURFACE pSurfaceDest; + rc = vmsvga3dSurfaceFromSid(pState, sidDest, &pSurfaceDest); + AssertRCReturn(rc, rc); + + PVMSVGA3DMIPMAPLEVEL pMipmapLevelSrc; + rc = vmsvga3dMipmapLevel(pSurfaceSrc, src.face, src.mipmap, &pMipmapLevelSrc); + AssertRCReturn(rc, rc); + + PVMSVGA3DMIPMAPLEVEL pMipmapLevelDest; + rc = vmsvga3dMipmapLevel(pSurfaceDest, dest.face, dest.mipmap, &pMipmapLevelDest); + AssertRCReturn(rc, rc); + + /* If src is HW and dst is not, then create the dst texture. */ + if ( pSurfaceSrc->u.pSurface + && !pSurfaceDest->u.pSurface + && RT_BOOL(pSurfaceDest->f.surfaceFlags & SVGA3D_SURFACE_HINT_TEXTURE)) + { + /* Create the destination texture in the same context as the source texture. */ + uint32_t const cidSrc = pSurfaceSrc->idAssociatedContext; + + PVMSVGA3DCONTEXT pContextSrc; + rc = vmsvga3dContextFromCid(pState, cidSrc, &pContextSrc); + AssertRCReturn(rc, rc); + AssertReturn(pContextSrc->pDevice, VERR_INTERNAL_ERROR); + + LogFunc(("sid=%u type=%x format=%d -> create dest texture\n", sidDest, pSurfaceDest->f.s.surface1Flags, pSurfaceDest->format)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContextSrc, cidSrc, pSurfaceDest); + AssertRCReturn(rc, rc); + } + + AssertReturn(pSurfaceSrc->enmD3DResType != VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE, VERR_NOT_IMPLEMENTED); /// @todo + AssertReturn(pSurfaceDest->enmD3DResType != VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE, VERR_NOT_IMPLEMENTED); /// @todo + + /* Surface copy only makes sense between surfaces with identical layout. */ + AssertReturn(pSurfaceSrc->cbBlock == pSurfaceDest->cbBlock, VERR_INVALID_PARAMETER); + AssertReturn(pSurfaceSrc->cxBlock == pSurfaceDest->cxBlock, VERR_INVALID_PARAMETER); + AssertReturn(pSurfaceSrc->cyBlock == pSurfaceDest->cyBlock, VERR_INVALID_PARAMETER); + + if ( pSurfaceSrc->u.pSurface + && pSurfaceDest->u.pSurface) + { + /* Both surfaces in hardware. Use the src context to copy one to another, because the src context may be needed + * to copy data from source texture to the source bounce texture. while only the shared hardware surface is required + * from the dst context. + */ + uint32_t const cidSrc = pSurfaceSrc->idAssociatedContext; + + PVMSVGA3DCONTEXT pContextSrc; + rc = vmsvga3dContextFromCid(pState, cidSrc, &pContextSrc); + AssertRCReturn(rc, rc); + AssertReturn(pContextSrc->pDevice, VERR_INTERNAL_ERROR); + + /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */ + vmsvga3dSurfaceFlush(pSurfaceSrc); + vmsvga3dSurfaceFlush(pSurfaceDest); + + IDirect3DSurface9 *pSrc; + rc = vmsvga3dGetD3DSurface(pState, pContextSrc, pSurfaceSrc, src.face, src.mipmap, false, &pSrc); + AssertRCReturn(rc, rc); + + IDirect3DSurface9 *pDest; + rc = vmsvga3dGetD3DSurface(pState, pContextSrc, pSurfaceDest, dest.face, dest.mipmap, false, &pDest); + AssertRCReturnStmt(rc, D3D_RELEASE(pSrc), rc); + + for (uint32_t i = 0; i < cCopyBoxes; ++i) + { + SVGA3dCopyBox clipBox = pBox[i]; + vmsvgaR3ClipCopyBox(&pMipmapLevelSrc->mipmapSize, &pMipmapLevelDest->mipmapSize, &clipBox); + if ( !clipBox.w + || !clipBox.h + || !clipBox.d) + { + LogFunc(("Skipped empty box.\n")); + continue; + } + + RECT RectSrc; + RectSrc.left = clipBox.srcx; + RectSrc.top = clipBox.srcy; + RectSrc.right = clipBox.srcx + clipBox.w; /* exclusive */ + RectSrc.bottom = clipBox.srcy + clipBox.h; /* exclusive */ + + RECT RectDest; + RectDest.left = clipBox.x; + RectDest.top = clipBox.y; + RectDest.right = clipBox.x + clipBox.w; /* exclusive */ + RectDest.bottom = clipBox.y + clipBox.h; /* exclusive */ + + LogFunc(("StretchRect copy src sid=%u face=%d mipmap=%d (%d,%d)(%d,%d) to dest sid=%u face=%d mipmap=%d (%d,%d)\n", sidSrc, src.face, src.mipmap, RectSrc.left, RectSrc.top, RectSrc.right, RectSrc.bottom, sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y)); + + if ( sidSrc == sidDest + && clipBox.srcx == clipBox.x + && clipBox.srcy == clipBox.y) + { + LogFunc(("redundant copy to the same surface at the same coordinates. Ignore.\n")); + continue; + } + Assert(sidSrc != sidDest); + Assert(!clipBox.srcz && !clipBox.z); + + HRESULT hr = pContextSrc->pDevice->StretchRect(pSrc, &RectSrc, pDest, &RectDest, D3DTEXF_NONE); + if (hr != D3D_OK) + { + /* This can happen for compressed texture formats for example. */ + LogFunc(("StretchRect failed with %x. Try a slow path.\n", hr)); + if ( pSurfaceSrc->bounce.pTexture + && (pSurfaceSrc->fUsageD3D & D3DUSAGE_RENDERTARGET)) + { + /* Copy the source texture mipmap level to the source bounce texture. */ + hr = D3D9GetRenderTargetData(pContextSrc, pSurfaceSrc, src.face, src.mipmap); + AssertMsg(hr == D3D_OK, ("D3D9GetRenderTargetData failed with %x\n", hr)); + if (hr == D3D_OK) + { + /* Copy the source bounce texture to the destination surface. */ + IDirect3DSurface9 *pSrcBounce; + rc = vmsvga3dGetD3DSurface(pState, pContextSrc, pSurfaceSrc, src.face, src.mipmap, true, &pSrcBounce); + if (RT_SUCCESS(rc)) + { + POINT pointDest; + pointDest.x = clipBox.x; + pointDest.y = clipBox.y; + + hr = pContextSrc->pDevice->UpdateSurface(pSrcBounce, &RectSrc, pDest, &pointDest); + Assert(hr == D3D_OK); + + D3D_RELEASE(pSrcBounce); + } + else + { + AssertRC(rc); + hr = E_INVALIDARG; + } + } + } + else if ( (pSurfaceSrc->fUsageD3D & D3DUSAGE_RENDERTARGET) == 0 + && (pSurfaceDest->fUsageD3D & D3DUSAGE_RENDERTARGET) == 0) + { + /* Can lock both. */ + D3DLOCKED_RECT LockedSrcRect; + hr = pSrc->LockRect(&LockedSrcRect, &RectSrc, D3DLOCK_READONLY); + Assert(hr == D3D_OK); + if (SUCCEEDED(hr)) + { + D3DLOCKED_RECT LockedDestRect; + hr = pDest->LockRect(&LockedDestRect, &RectDest, 0); + Assert(hr == D3D_OK); + if (SUCCEEDED(hr)) + { + uint32_t cBlocksX = (clipBox.w + pSurfaceSrc->cxBlock - 1) / pSurfaceSrc->cxBlock; + uint32_t cBlocksY = (clipBox.h + pSurfaceSrc->cyBlock - 1) / pSurfaceSrc->cyBlock; + + uint32_t cbToCopy = cBlocksX * pSurfaceSrc->cbBlock; + cbToCopy = RT_MIN(cbToCopy, (uint32_t)RT_ABS(LockedDestRect.Pitch)); + cbToCopy = RT_MIN(cbToCopy, (uint32_t)RT_ABS(LockedSrcRect.Pitch)); + + uint8_t *pu8Dst = (uint8_t *)LockedDestRect.pBits; + const uint8_t *pu8Src = (uint8_t *)LockedSrcRect.pBits; + for (uint32_t j = 0; j < cBlocksY; ++j) + { + memcpy(pu8Dst, pu8Src, cbToCopy); + pu8Dst += LockedDestRect.Pitch; + pu8Src += LockedSrcRect.Pitch; + } + + hr = pDest->UnlockRect(); + Assert(hr == D3D_OK); + } + + hr = pSrc->UnlockRect(); + Assert(hr == D3D_OK); + } + } + } + AssertMsgReturnStmt(hr == D3D_OK, + ("StretchRect failed with %x\n", hr), + D3D_RELEASE(pDest); D3D_RELEASE(pSrc), + VERR_INTERNAL_ERROR); + } + + D3D_RELEASE(pDest); + D3D_RELEASE(pSrc); + + /* Track the StretchRect operation. */ + vmsvga3dSurfaceTrackUsage(pState, pContextSrc, pSurfaceSrc); + vmsvga3dSurfaceTrackUsage(pState, pContextSrc, pSurfaceDest); + } + else + { + /* One of the surfaces is in memory. + * + * Copy from/to memory to/from a HW surface. Or mem->mem. + * Use the context of the HW surface, if any. + */ + PVMSVGA3DCONTEXT pContext = NULL; + IDirect3DSurface9 *pD3DSurf = NULL; + + if (pSurfaceSrc->u.pSurface) + { + AssertReturn(!pSurfaceDest->u.pSurface, VERR_INTERNAL_ERROR); + + rc = vmsvga3dContextFromCid(pState, pSurfaceSrc->idAssociatedContext, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + rc = vmsvga3dGetD3DSurface(pState, pContext, pSurfaceSrc, src.face, src.mipmap, true, &pD3DSurf); + AssertRCReturn(rc, rc); + } + else if (pSurfaceDest->u.pSurface) + { + AssertReturn(!pSurfaceSrc->u.pSurface, VERR_INTERNAL_ERROR); + + rc = vmsvga3dContextFromCid(pState, pSurfaceDest->idAssociatedContext, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + rc = vmsvga3dGetD3DSurface(pState, pContext, pSurfaceDest, dest.face, dest.mipmap, true, &pD3DSurf); + AssertRCReturn(rc, rc); + } + + for (uint32_t i = 0; i < cCopyBoxes; ++i) + { + HRESULT hr; + + SVGA3dCopyBox clipBox = pBox[i]; + vmsvgaR3ClipCopyBox(&pMipmapLevelSrc->mipmapSize, &pMipmapLevelDest->mipmapSize, &clipBox); + if ( !clipBox.w + || !clipBox.h + || !clipBox.d) + { + LogFunc(("Skipped empty box.\n")); + continue; + } + + RECT RectSrc; + RectSrc.left = clipBox.srcx; + RectSrc.top = clipBox.srcy; + RectSrc.right = clipBox.srcx + clipBox.w; /* exclusive */ + RectSrc.bottom = clipBox.srcy + clipBox.h; /* exclusive */ + + RECT RectDest; + RectDest.left = clipBox.x; + RectDest.top = clipBox.y; + RectDest.right = clipBox.x + clipBox.w; /* exclusive */ + RectDest.bottom = clipBox.y + clipBox.h; /* exclusive */ + + LogFunc(("(manual) copy sid=%u face=%d mipmap=%d (%d,%d)(%d,%d) to sid=%u face=%d mipmap=%d (%d,%d)\n", + sidSrc, src.face, src.mipmap, RectSrc.left, RectSrc.top, RectSrc.right, RectSrc.bottom, + sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y)); + + Assert(!clipBox.srcz && !clipBox.z); + + uint32_t cBlocksX = (clipBox.w + pSurfaceSrc->cxBlock - 1) / pSurfaceSrc->cxBlock; + uint32_t cBlocksY = (clipBox.h + pSurfaceSrc->cyBlock - 1) / pSurfaceSrc->cyBlock; + + D3DLOCKED_RECT LockedSrcRect; + if (!pSurfaceSrc->u.pSurface) + { + uint32_t u32BlockX = clipBox.srcx / pSurfaceSrc->cxBlock; + uint32_t u32BlockY = clipBox.srcy / pSurfaceSrc->cyBlock; + Assert(u32BlockX * pSurfaceSrc->cxBlock == clipBox.srcx); + Assert(u32BlockY * pSurfaceSrc->cyBlock == clipBox.srcy); + + LockedSrcRect.pBits = (uint8_t *)pMipmapLevelSrc->pSurfaceData + + pMipmapLevelSrc->cbSurfacePitch * u32BlockY + pSurfaceSrc->cbBlock * u32BlockX; + LockedSrcRect.Pitch = pMipmapLevelSrc->cbSurfacePitch; + } + else + { + /* Must flush the context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */ + vmsvga3dSurfaceFlush(pSurfaceSrc); + + hr = pD3DSurf->LockRect(&LockedSrcRect, &RectSrc, D3DLOCK_READONLY); + AssertMsgReturnStmt(hr == D3D_OK, ("LockRect failed with %x\n", hr), D3D_RELEASE(pD3DSurf), VERR_INTERNAL_ERROR); + } + + D3DLOCKED_RECT LockedDestRect; + if (!pSurfaceDest->u.pSurface) + { + uint32_t u32BlockX = clipBox.x / pSurfaceDest->cxBlock; + uint32_t u32BlockY = clipBox.y / pSurfaceDest->cyBlock; + Assert(u32BlockX * pSurfaceDest->cxBlock == clipBox.x); + Assert(u32BlockY * pSurfaceDest->cyBlock == clipBox.y); + + LockedDestRect.pBits = (uint8_t *)pMipmapLevelDest->pSurfaceData + + pMipmapLevelDest->cbSurfacePitch * u32BlockY + pSurfaceDest->cbBlock * u32BlockX; + LockedDestRect.Pitch = pMipmapLevelDest->cbSurfacePitch; + pSurfaceDest->fDirty = true; + } + else + { + /* Must flush the context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */ + vmsvga3dSurfaceFlush(pSurfaceDest); + + hr = pD3DSurf->LockRect(&LockedDestRect, &RectDest, 0); + AssertMsgReturnStmt(hr == D3D_OK, ("LockRect failed with %x\n", hr), D3D_RELEASE(pD3DSurf), VERR_INTERNAL_ERROR); + } + + uint8_t *pDest = (uint8_t *)LockedDestRect.pBits; + const uint8_t *pSrc = (uint8_t *)LockedSrcRect.pBits; + for (uint32_t j = 0; j < cBlocksY; ++j) + { + memcpy(pDest, pSrc, cBlocksX * pSurfaceSrc->cbBlock); + pDest += LockedDestRect.Pitch; + pSrc += LockedSrcRect.Pitch; + } + + if (pD3DSurf) + { + hr = pD3DSurf->UnlockRect(); + AssertMsgReturnStmt(hr == D3D_OK, ("Unlock failed with %x\n", hr), D3D_RELEASE(pD3DSurf), VERR_INTERNAL_ERROR); + } + } + + D3D_RELEASE(pD3DSurf); + + /* If the destination bounce texture has been used, then update the actual destination texture. */ + if ( pSurfaceDest->u.pTexture + && pSurfaceDest->bounce.pTexture + && ( pSurfaceDest->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE + || pSurfaceDest->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE)) + { + AssertMsgReturn(pContext, ("Context is NULL\n"), VERR_INTERNAL_ERROR); + + /* Copy the new content to the actual texture object. */ + HRESULT hr2 = D3D9UpdateTexture(pContext, pSurfaceDest); + AssertMsg(hr2 == D3D_OK, ("UpdateTexture failed with %x\n", hr2)); RT_NOREF(hr2); + + /* Track the UpdateTexture operation. */ + vmsvga3dSurfaceTrackUsage(pState, pContext, pSurfaceDest); + } + } + + return VINF_SUCCESS; +} + + +/** + * Create D3D/OpenGL texture object for the specified surface. + * + * Surfaces are created when needed. + * + * @param pThisCC The device context. + * @param pContext The context. + * @param idAssociatedContext Probably the same as pContext->id. + * @param pSurface The surface to create the texture for. + */ +static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, + PVMSVGA3DSURFACE pSurface) + +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + HRESULT hr; + + LogFunc(("sid=%u\n", pSurface->id)); + + Assert(pSurface->hSharedObject == NULL); + Assert(pSurface->u.pTexture == NULL); + Assert(pSurface->bounce.pTexture == NULL); + Assert(pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_NONE); + + const uint32_t cWidth = pSurface->paMipmapLevels[0].mipmapSize.width; + const uint32_t cHeight = pSurface->paMipmapLevels[0].mipmapSize.height; + const uint32_t cDepth = pSurface->paMipmapLevels[0].mipmapSize.depth; + const uint32_t numMipLevels = pSurface->cLevels; + + /* + * Create D3D texture object. + */ + if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_CUBEMAP) + { + Assert(pSurface->cFaces == 6); + Assert(cWidth == cHeight); + Assert(cDepth == 1); + + hr = pContext->pDevice->CreateCubeTexture(cWidth, + numMipLevels, + pSurface->fUsageD3D, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSurface->u.pCubeTexture, + &pSurface->hSharedObject); + if (hr == D3D_OK) + { + /* Create another texture object to serve as a bounce buffer as the above texture surface can't be locked. */ + hr = pContext->pDevice->CreateCubeTexture(cWidth, + numMipLevels, + (pSurface->fUsageD3D & ~D3DUSAGE_RENDERTARGET) | D3DUSAGE_DYNAMIC /* Lockable */, + pSurface->formatD3D, + D3DPOOL_SYSTEMMEM, + &pSurface->bounce.pCubeTexture, + NULL); + AssertMsgReturnStmt(hr == D3D_OK, + ("CreateCubeTexture (systemmem) failed with %x\n", hr), + D3D_RELEASE(pSurface->u.pCubeTexture), + VERR_INTERNAL_ERROR); + } + else + { + Log(("Format not accepted -> try old method\n")); + /* The format was probably not accepted; fall back to our old mode. */ + hr = pContext->pDevice->CreateCubeTexture(cWidth, + numMipLevels, + (pSurface->fUsageD3D & ~D3DUSAGE_RENDERTARGET) | D3DUSAGE_DYNAMIC /* Lockable */, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSurface->u.pCubeTexture, + &pSurface->hSharedObject); + AssertMsgReturn(hr == D3D_OK, ("CreateCubeTexture (fallback) failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + + pSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE; + } + else if ( pSurface->formatD3D == D3DFMT_D24S8 + || pSurface->formatD3D == D3DFMT_D24X8 + || pSurface->formatD3D == D3DFMT_D32 + || pSurface->formatD3D == D3DFMT_D16) + { + Assert(pSurface->cFaces == 1); + Assert(pSurface->cLevels == 1); + Assert(cDepth == 1); + + /* Use the INTZ format for a depth/stencil surface that will be used as a texture */ + hr = pContext->pDevice->CreateTexture(cWidth, + cHeight, + 1, /* mip levels */ + D3DUSAGE_DEPTHSTENCIL, + FOURCC_INTZ, + D3DPOOL_DEFAULT, + &pSurface->u.pTexture, + &pSurface->hSharedObject /* might result in poor performance */); + if ( hr == D3D_OK + && ( pSurface->formatD3D == D3DFMT_D24S8 + || pSurface->formatD3D == D3DFMT_D24X8)) + { + /* Create another texture object to serve as a bounce buffer as the + * D3DFMT_D24S8 and D3DFMT_D24X8 surface can't be locked apparently (from testing). + */ + hr = pContext->pDevice->CreateTexture(cWidth, + cHeight, + 1, /* mip levels */ + D3DUSAGE_DYNAMIC /* Lockable */, + FOURCC_INTZ, + D3DPOOL_SYSTEMMEM, + &pSurface->bounce.pTexture, + NULL); + + AssertMsgReturnStmt(hr == D3D_OK, + ("CreateTexture (systemmem) failed with %x\n", hr), + D3D_RELEASE(pSurface->u.pTexture), + VERR_INTERNAL_ERROR); + } + + AssertMsgReturn(hr == D3D_OK, ("CreateTexture INTZ failed with %x\n", hr), VERR_INTERNAL_ERROR); + + pSurface->fStencilAsTexture = true; + pSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_TEXTURE; + } + else + { + if (cDepth > 1) + { + hr = pContext->pDevice->CreateVolumeTexture(cWidth, + cHeight, + cDepth, + numMipLevels, + pSurface->fUsageD3D, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSurface->u.pVolumeTexture, + &pSurface->hSharedObject); + if (hr == D3D_OK) + { + /* Create another texture object to serve as a bounce buffer as the above texture surface can't be locked. */ + hr = pContext->pDevice->CreateVolumeTexture(cWidth, + cHeight, + cDepth, + numMipLevels, + (pSurface->fUsageD3D & ~D3DUSAGE_RENDERTARGET) | D3DUSAGE_DYNAMIC /* Lockable */, + pSurface->formatD3D, + D3DPOOL_SYSTEMMEM, + &pSurface->bounce.pVolumeTexture, + NULL); + AssertMsgReturnStmt(hr == D3D_OK, + ("CreateVolumeTexture (systemmem) failed with %x\n", hr), + D3D_RELEASE(pSurface->u.pVolumeTexture), + VERR_INTERNAL_ERROR); + } + else + { + Log(("Format not accepted -> try old method\n")); + /* The format was probably not accepted; fall back to our old mode. */ + hr = pContext->pDevice->CreateVolumeTexture(cWidth, + cHeight, + cDepth, + numMipLevels, + (pSurface->fUsageD3D & ~D3DUSAGE_RENDERTARGET) | D3DUSAGE_DYNAMIC /* Lockable */, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSurface->u.pVolumeTexture, + &pSurface->hSharedObject); + AssertMsgReturn(hr == D3D_OK, ("CreateVolumeTexture (fallback) failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + + pSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE; + } + else + { + Assert(pSurface->cFaces == 1); + + hr = pContext->pDevice->CreateTexture(cWidth, + cHeight, + numMipLevels, + pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET /* required for use as a StretchRect destination */, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSurface->u.pTexture, + &pSurface->hSharedObject); + if (hr == D3D_OK) + { + /* Create another texture object to serve as a bounce buffer as the above texture surface can't be locked. */ + hr = pContext->pDevice->CreateTexture(cWidth, + cHeight, + numMipLevels, + (pSurface->fUsageD3D & ~D3DUSAGE_RENDERTARGET) | D3DUSAGE_DYNAMIC /* Lockable */, + pSurface->formatD3D, + D3DPOOL_SYSTEMMEM, + &pSurface->bounce.pTexture, + NULL); + + AssertMsgReturn(hr == D3D_OK, ("CreateTexture (systemmem) failed with %x\n", hr), VERR_INTERNAL_ERROR); + + if (pSurface->formatD3D != pSurface->d3dfmtRequested) + { + /* Create a staging texture/render target for format conversion. */ + hr = pContext->pDevice->CreateTexture(cWidth, + cHeight, + numMipLevels, + pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSurface->emulated.pTexture, + NULL); + AssertMsgReturn(hr == D3D_OK, ("CreateTexture (emulated) failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + } + else + { + Log(("Format not accepted (%x) -> try old method\n", hr)); + /* The format was probably not accepted; fall back to our old mode. */ + hr = pContext->pDevice->CreateTexture(cWidth, + cHeight, + numMipLevels, + (pSurface->fUsageD3D & ~D3DUSAGE_RENDERTARGET) | D3DUSAGE_DYNAMIC /* Lockable */, + pSurface->formatD3D, + D3DPOOL_DEFAULT, + &pSurface->u.pTexture, + &pSurface->hSharedObject /* might result in poor performance */); + AssertMsgReturn(hr == D3D_OK, ("CreateTexture failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + + pSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_TEXTURE; + } + } + + Assert(hr == D3D_OK); + + if (pSurface->autogenFilter != SVGA3D_TEX_FILTER_NONE) + { + /* Set the mip map generation filter settings. */ + IDirect3DBaseTexture9 *pBaseTexture; + if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE) + pBaseTexture = pSurface->u.pVolumeTexture; + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE) + pBaseTexture = pSurface->u.pCubeTexture; + else + pBaseTexture = pSurface->u.pTexture; + hr = pBaseTexture->SetAutoGenFilterType((D3DTEXTUREFILTERTYPE)pSurface->autogenFilter); + AssertMsg(hr == D3D_OK, ("vmsvga3dBackCreateTexture: SetAutoGenFilterType failed with %x\n", hr)); + } + + /* + * Always initialize all mipmap levels using the in memory data + * to make sure that the just created texture has the up-to-date content. + * The OpenGL backend does this too. + */ + Log(("vmsvga3dBackCreateTexture: sync texture\n")); + + if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE) + { + IDirect3DVolumeTexture9 *pVolumeTexture = pSurface->bounce.pVolumeTexture ? + pSurface->bounce.pVolumeTexture : + pSurface->u.pVolumeTexture; + + for (uint32_t i = 0; i < numMipLevels; ++i) + { + D3DLOCKED_BOX LockedVolume; + hr = pVolumeTexture->LockBox(i, &LockedVolume, NULL, D3DLOCK_DISCARD); + AssertMsgBreak(hr == D3D_OK, ("LockBox failed with %x\n", hr)); + + PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i]; + + LogFunc(("sync volume texture mipmap level %d (pitch row %x vs %x, slice %x vs %x)\n", + i, LockedVolume.RowPitch, pMipLevel->cbSurfacePitch, LockedVolume.SlicePitch, pMipLevel->cbSurfacePlane)); + + + uint8_t *pDst = (uint8_t *)LockedVolume.pBits; + const uint8_t *pSrc = (uint8_t *)pMipLevel->pSurfaceData; + for (uint32_t d = 0; d < cDepth; ++d) + { + uint8_t *pRowDst = pDst; + const uint8_t *pRowSrc = pSrc; + for (uint32_t h = 0; h < pMipLevel->cBlocksY; ++h) + { + memcpy(pRowDst, pRowSrc, pMipLevel->cbSurfacePitch); + pRowDst += LockedVolume.RowPitch; + pRowSrc += pMipLevel->cbSurfacePitch; + } + pDst += LockedVolume.SlicePitch; + pSrc += pMipLevel->cbSurfacePlane; + } + + hr = pVolumeTexture->UnlockBox(i); + AssertMsgBreak(hr == D3D_OK, ("UnlockBox failed with %x\n", hr)); + + pMipLevel->fDirty = false; + } + } + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE) + { + IDirect3DCubeTexture9 *pCubeTexture = pSurface->bounce.pCubeTexture ? + pSurface->bounce.pCubeTexture : + pSurface->u.pCubeTexture; + + for (uint32_t iFace = 0; iFace < 6; ++iFace) + { + const D3DCUBEMAP_FACES Face = vmsvga3dCubemapFaceFromIndex(iFace); + + for (uint32_t i = 0; i < numMipLevels; ++i) + { + D3DLOCKED_RECT LockedRect; + hr = pCubeTexture->LockRect(Face, + i, /* texture level */ + &LockedRect, + NULL, /* entire texture */ + 0); + AssertMsgBreak(hr == D3D_OK, ("LockRect failed with %x\n", hr)); + + PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[iFace * numMipLevels + i]; + + LogFunc(("sync texture face %d mipmap level %d (pitch %x vs %x)\n", + iFace, i, LockedRect.Pitch, pMipLevel->cbSurfacePitch)); + + uint8_t *pDest = (uint8_t *)LockedRect.pBits; + const uint8_t *pSrc = (uint8_t *)pMipLevel->pSurfaceData; + for (uint32_t j = 0; j < pMipLevel->cBlocksY; ++j) + { + memcpy(pDest, pSrc, pMipLevel->cbSurfacePitch); + + pDest += LockedRect.Pitch; + pSrc += pMipLevel->cbSurfacePitch; + } + + hr = pCubeTexture->UnlockRect(Face, i /* texture level */); + AssertMsgBreak(hr == D3D_OK, ("UnlockRect failed with %x\n", hr)); + + pMipLevel->fDirty = false; + } + + if (hr != D3D_OK) + break; + } + + if (hr != D3D_OK) + { + D3D_RELEASE(pSurface->bounce.pCubeTexture); + D3D_RELEASE(pSurface->u.pCubeTexture); + return VERR_INTERNAL_ERROR; + } + } + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE) + { + IDirect3DTexture9 *pTexture; + if (pSurface->bounce.pTexture) + pTexture = pSurface->bounce.pTexture; + else if (pSurface->formatD3D != pSurface->d3dfmtRequested) + pTexture = pSurface->emulated.pTexture; + else + pTexture = pSurface->u.pTexture; + + for (uint32_t i = 0; i < numMipLevels; ++i) + { + D3DLOCKED_RECT LockedRect; + + hr = pTexture->LockRect(i, /* texture level */ + &LockedRect, + NULL, /* entire texture */ + 0); + + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + LogFunc(("sync texture mipmap level %d (pitch %x vs %x)\n", i, LockedRect.Pitch, pSurface->paMipmapLevels[i].cbSurfacePitch)); + + uint8_t *pDest = (uint8_t *)LockedRect.pBits; + const uint8_t *pSrc = (uint8_t *)pSurface->paMipmapLevels[i].pSurfaceData; + for (uint32_t j = 0; j < pSurface->paMipmapLevels[i].cBlocksY; ++j) + { + memcpy(pDest, pSrc, pSurface->paMipmapLevels[i].cbSurfacePitch); + + pDest += LockedRect.Pitch; + pSrc += pSurface->paMipmapLevels[i].cbSurfacePitch; + } + + hr = pTexture->UnlockRect(i /* texture level */); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + pSurface->paMipmapLevels[i].fDirty = false; + } + } + else + { + AssertMsgFailedReturn(("enmD3DResType not expected %d\n", pSurface->enmD3DResType), VERR_INTERNAL_ERROR); + } + + if (pSurface->bounce.pTexture) + { + Log(("vmsvga3dBackCreateTexture: sync dirty texture from bounce buffer\n")); + if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE) + hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pVolumeTexture, pSurface->u.pVolumeTexture); + else + hr = D3D9UpdateTexture(pContext, pSurface); + AssertMsgReturn(hr == D3D_OK, ("UpdateTexture failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* We will now use the bounce texture for all memory accesses, so free our surface memory buffer. */ + for (uint32_t i = 0; i < pSurface->cLevels; i++) + { + RTMemFree(pSurface->paMipmapLevels[i].pSurfaceData); + pSurface->paMipmapLevels[i].pSurfaceData = NULL; + } + + /* Track the UpdateTexture operation. */ + vmsvga3dSurfaceTrackUsage(pState, pContext, pSurface); + } + pSurface->fDirty = false; + + Assert(pSurface->enmD3DResType != VMSVGA3D_D3DRESTYPE_NONE); + + pSurface->f.surfaceFlags |= SVGA3D_SURFACE_HINT_TEXTURE; + pSurface->idAssociatedContext = idAssociatedContext; + return VINF_SUCCESS; +} + + +/** + * Backend worker for implementing SVGA_3D_CMD_SURFACE_STRETCHBLT. + * + * @returns VBox status code. + * @param pThis The VGA device instance. + * @param pState The VMSVGA3d state. + * @param pDstSurface The destination host surface. + * @param uDstFace The destination face (valid). + * @param uDstMipmap The destination mipmap level (valid). + * @param pDstBox The destination box. + * @param pSrcSurface The source host surface. + * @param uSrcFace The destination face (valid). + * @param uSrcMipmap The source mimap level (valid). + * @param pSrcBox The source box. + * @param enmMode The strecht blt mode . + * @param pContext The VMSVGA3d context (already current for OGL). + */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceStretchBlt(PVGASTATE pThis, PVMSVGA3DSTATE pState, + PVMSVGA3DSURFACE pDstSurface, uint32_t uDstFace, uint32_t uDstMipmap, SVGA3dBox const *pDstBox, + PVMSVGA3DSURFACE pSrcSurface, uint32_t uSrcFace, uint32_t uSrcMipmap, SVGA3dBox const *pSrcBox, + SVGA3dStretchBltMode enmMode, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThis); + + HRESULT hr; + int rc; + + AssertReturn(pSrcSurface->enmD3DResType != VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE, VERR_NOT_IMPLEMENTED); + AssertReturn(pDstSurface->enmD3DResType != VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE, VERR_NOT_IMPLEMENTED); + + /* Flush the drawing pipeline for this surface as it could be used in a shared context. */ + vmsvga3dSurfaceFlush(pSrcSurface); + vmsvga3dSurfaceFlush(pDstSurface); + + RECT RectSrc; + RectSrc.left = pSrcBox->x; + RectSrc.top = pSrcBox->y; + RectSrc.right = pSrcBox->x + pSrcBox->w; /* exclusive */ + RectSrc.bottom = pSrcBox->y + pSrcBox->h; /* exclusive */ + Assert(!pSrcBox->z); + + RECT RectDst; + RectDst.left = pDstBox->x; + RectDst.top = pDstBox->y; + RectDst.right = pDstBox->x + pDstBox->w; /* exclusive */ + RectDst.bottom = pDstBox->y + pDstBox->h; /* exclusive */ + Assert(!pDstBox->z); + + IDirect3DSurface9 *pSrc; + rc = vmsvga3dGetD3DSurface(pState, pContext, pSrcSurface, uSrcFace, uSrcMipmap, false, &pSrc); + AssertRCReturn(rc, rc); + + IDirect3DSurface9 *pDst; + rc = vmsvga3dGetD3DSurface(pState, pContext, pDstSurface, uDstFace, uDstMipmap, false, &pDst); + AssertRCReturn(rc, rc); + + D3DTEXTUREFILTERTYPE moded3d; + switch (enmMode) + { + case SVGA3D_STRETCH_BLT_POINT: + moded3d = D3DTEXF_POINT; + break; + + case SVGA3D_STRETCH_BLT_LINEAR: + moded3d = D3DTEXF_LINEAR; + break; + + default: + AssertFailed(); + moded3d = D3DTEXF_NONE; + break; + } + + hr = pContext->pDevice->StretchRect(pSrc, &RectSrc, pDst, &RectDst, moded3d); + + D3D_RELEASE(pDst); + D3D_RELEASE(pSrc); + + AssertMsgReturn(hr == D3D_OK, ("StretchRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* Track the StretchRect operation. */ + vmsvga3dSurfaceTrackUsage(pState, pContext, pSrcSurface); + vmsvga3dSurfaceTrackUsage(pState, pContext, pDstSurface); + + return VINF_SUCCESS; +} + + +/** + * Backend worker for implementing SVGA_3D_CMD_SURFACE_DMA that copies one box. + * + * @returns Failure status code or @a rc. + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pState The VMSVGA3d state. + * @param pSurface The host surface. + * @param pMipLevel Mipmap level. The caller knows it already. + * @param uHostFace The host face (valid). + * @param uHostMipmap The host mipmap level (valid). + * @param GuestPtr The guest pointer. + * @param cbGuestPitch The guest pitch. + * @param transfer The transfer direction. + * @param pBox The box to copy (clipped, valid, except for guest's srcx, srcy, srcz). + * @param pContext The context (for OpenGL). + * @param rc The current rc for all boxes. + * @param iBox The current box number (for Direct 3D). + */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, + PVMSVGA3DMIPMAPLEVEL pMipLevel, uint32_t uHostFace, uint32_t uHostMipmap, + SVGAGuestPtr GuestPtr, uint32_t cbGuestPitch, SVGA3dTransferType transfer, + SVGA3dCopyBox const *pBox, PVMSVGA3DCONTEXT pContext, int rc, int iBox) +{ + HRESULT hr = D3D_OK; + const DWORD dwFlags = transfer == SVGA3D_READ_HOST_VRAM ? D3DLOCK_READONLY : 0; + + AssertReturn(pSurface->enmD3DResType != VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE, VERR_NOT_IMPLEMENTED); + + const bool fTexture = pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE + || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE; + if ( pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_SURFACE + || fTexture) + { + rc = vmsvga3dContextFromCid(pState, pSurface->idAssociatedContext, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + /* Get the surface involved in the transfer. */ + IDirect3DSurface9 *pSurf; + rc = vmsvga3dGetD3DSurface(pState, pContext, pSurface, uHostFace, uHostMipmap, true, &pSurf); + AssertRCReturn(rc, rc); + + if (transfer == SVGA3D_READ_HOST_VRAM) + { + /* Texture data is copied to the host VRAM. + * Update the 'bounce' texture if necessary. + */ + if ( fTexture + && pSurface->bounce.pTexture + && iBox == 0 /* only the first time */) + { + /** @todo inefficient for VRAM buffers!! */ + if (RT_BOOL(pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET)) + { + /* Copy the texture mipmap level to the bounce texture. */ + hr = D3D9GetRenderTargetData(pContext, pSurface, uHostFace, uHostMipmap); + AssertMsgReturn(hr == D3D_OK, ("D3D9GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + } + } + + uint32_t const u32GuestBlockX = pBox->srcx / pSurface->cxBlock; + uint32_t const u32GuestBlockY = pBox->srcy / pSurface->cyBlock; + Assert(u32GuestBlockX * pSurface->cxBlock == pBox->srcx); + Assert(u32GuestBlockY * pSurface->cyBlock == pBox->srcy); + uint32_t const cBlocksX = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock; + uint32_t const cBlocksY = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock; + AssertMsgReturn(cBlocksX && cBlocksY, ("Empty box %dx%d\n", pBox->w, pBox->h), VERR_INTERNAL_ERROR); + + /* vmsvgaR3GmrTransfer verifies uGuestOffset. + * srcx(u32GuestBlockX) and srcy(u32GuestBlockY) have been verified in vmsvga3dSurfaceDMA + * to not cause 32 bit overflow when multiplied by cbBlock and cbGuestPitch. + */ + uint64_t const uGuestOffset = u32GuestBlockX * pSurface->cbBlock + u32GuestBlockY * cbGuestPitch; + AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER); + + RECT Rect; + Rect.left = pBox->x; + Rect.top = pBox->y; + Rect.right = pBox->x + pBox->w; /* exclusive */ + Rect.bottom = pBox->y + pBox->h; /* exclusive */ + + D3DLOCKED_RECT LockedRect; + hr = pSurf->LockRect(&LockedRect, &Rect, dwFlags); + AssertMsgReturn(hr == D3D_OK, ("LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + LogFunc(("Lock sid=%u %s(bounce=%d) memory for rectangle (%d,%d)(%d,%d)\n", + pSurface->id, fTexture ? "TEXTURE " : "", RT_BOOL(pSurface->bounce.pTexture), + Rect.left, Rect.top, Rect.right, Rect.bottom)); + + /* Prepare parameters for vmsvgaR3GmrTransfer, which needs the host buffer address, size + * and offset of the first scanline. + */ + uint32_t const cbLockedBuf = RT_ABS(LockedRect.Pitch) * cBlocksY; + uint8_t *pu8LockedBuf = (uint8_t *)LockedRect.pBits; + if (LockedRect.Pitch < 0) + pu8LockedBuf -= cbLockedBuf + LockedRect.Pitch; + uint32_t const offLockedBuf = (uint32_t)((uintptr_t)LockedRect.pBits - (uintptr_t)pu8LockedBuf); + + rc = vmsvgaR3GmrTransfer(pThis, + pThisCC, + transfer, + pu8LockedBuf, + cbLockedBuf, + offLockedBuf, + LockedRect.Pitch, + GuestPtr, + (uint32_t)uGuestOffset, + cbGuestPitch, + cBlocksX * pSurface->cbBlock, + cBlocksY); + AssertRC(rc); + + Log4(("first line:\n%.*Rhxd\n", cBlocksX * pSurface->cbBlock, LockedRect.pBits)); + + hr = pSurf->UnlockRect(); + + D3D_RELEASE(pSurf); + + AssertMsgReturn(hr == D3D_OK, ("UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + if (transfer == SVGA3D_WRITE_HOST_VRAM) + { + /* Data is copied to the texture. Copy updated 'bounce' texture to the actual if necessary. + */ + /// @todo for the last iBox only. + if ( fTexture + && pSurface->bounce.pTexture) + { + LogFunc(("Sync texture from bounce buffer\n")); + + /* Copy the new contents to the actual texture object. */ + hr = D3D9UpdateTexture(pContext, pSurface); + AssertMsgReturn(hr == D3D_OK, ("UpdateTexture failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* Track the copy operation. */ + vmsvga3dSurfaceTrackUsage(pState, pContext, pSurface); + } + } + } + else if ( pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER + || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_INDEX_BUFFER) + { + /* + * Mesa SVGA driver can use the same buffer either for vertex or index data. + * But D3D distinguishes between index and vertex buffer objects. + * Therefore it should be possible to switch the buffer type on the fly. + * + * Always save the data to the memory buffer in pSurface->paMipmapLevels and, + * if necessary, recreate the corresponding D3D object with the data. + */ + + /* Buffers are uncompressed. */ + AssertReturn(pSurface->cxBlock == 1 && pSurface->cyBlock == 1, VERR_INTERNAL_ERROR); + + /* Caller already clipped pBox and buffers are 1-dimensional. */ + Assert(pBox->y == 0 && pBox->h == 1 && pBox->z == 0 && pBox->d == 1); + + /* The caller has already updated pMipLevel->pSurfaceData, see VMSVGA3DSURFACE_NEEDS_DATA. */ + +#ifdef LOG_ENABLED + uint32_t const offHst = pBox->x * pSurface->cbBlock; + uint32_t const cbWidth = pBox->w * pSurface->cbBlock; + Log4(("Buffer updated at [0x%x;0x%x):\n%.*Rhxd\n", offHst, offHst + cbWidth, cbWidth, (uint8_t *)pMipLevel->pSurfaceData + offHst)); +#endif + + /* Do not bother to copy the data to the D3D resource now. vmsvga3dDrawPrimitives will do that. + * The SVGA driver may use the same surface for both index and vertex data. + */ + + /* Make sure that vmsvga3dDrawPrimitives fetches the new data. */ + pMipLevel->fDirty = true; + pSurface->fDirty = true; + } + else + { + AssertMsgFailed(("Unsupported surface flags 0x%08X, type %d\n", pSurface->f.s.surface1Flags, pSurface->enmD3DResType)); + } + + return rc; +} + +static DECLCALLBACK(int) vmsvga3dBackGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + HRESULT hr; + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + AssertReturn(pSurface->idAssociatedContext != SVGA3D_INVALID_ID, VERR_INTERNAL_ERROR); + + Assert(filter != SVGA3D_TEX_FILTER_FLATCUBIC); + Assert(filter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC); + pSurface->autogenFilter = filter; + + Log(("vmsvga3dGenerateMipmaps: sid=%u filter=%d\n", sid, filter)); + + if (!pSurface->u.pSurface) + { + /** @todo stricter checks for associated context */ + uint32_t const cid = pSurface->idAssociatedContext; + + PVMSVGA3DCONTEXT pContext; + rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + /* Unknown surface type; turn it into a texture. */ + LogFunc(("unknown src surface sid=%u type=%d format=%d -> create texture\n", sid, pSurface->f.s.surface1Flags, pSurface->format)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pSurface); + AssertRCReturn(rc, rc); + } + + AssertReturn( pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE + || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE + || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE, + VERR_INVALID_PARAMETER); + + hr = pSurface->u.pTexture->SetAutoGenFilterType((D3DTEXTUREFILTERTYPE)filter); + AssertMsg(hr == D3D_OK, ("SetAutoGenFilterType failed with %x\n", hr)); + + /* Generate the mip maps. */ + pSurface->u.pTexture->GenerateMipSubLevels(); + + return VINF_SUCCESS; +} + + +/** + * Create a new 3d context + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param cid Context id + */ +static DECLCALLBACK(int) vmsvga3dBackContextDefine(PVGASTATECC pThisCC, uint32_t cid) +{ + int rc; + PVMSVGA3DCONTEXT pContext; + HRESULT hr; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + + Log(("vmsvga3dContextDefine id %x\n", cid)); + + AssertReturn(pState, VERR_NO_MEMORY); + AssertReturn(cid < SVGA3D_MAX_CONTEXT_IDS, VERR_INVALID_PARAMETER); + + if (cid >= pState->cContexts) + { + /* Grow the array. */ + uint32_t cNew = RT_ALIGN(cid + 15, 16); + void *pvNew = RTMemRealloc(pState->papContexts, sizeof(pState->papContexts[0]) * cNew); + AssertReturn(pvNew, VERR_NO_MEMORY); + pState->papContexts = (PVMSVGA3DCONTEXT *)pvNew; + while (pState->cContexts < cNew) + { + pContext = (PVMSVGA3DCONTEXT)RTMemAllocZ(sizeof(*pContext)); + AssertReturn(pContext, VERR_NO_MEMORY); + pContext->id = SVGA3D_INVALID_ID; + pState->papContexts[pState->cContexts++] = pContext; + } + } + /* If one already exists with this id, then destroy it now. */ + if (pState->papContexts[cid]->id != SVGA3D_INVALID_ID) + vmsvga3dBackContextDestroy(pThisCC, cid); + + pContext = pState->papContexts[cid]; + memset(pContext, 0, sizeof(*pContext)); + pContext->id = cid; + for (uint32_t i = 0; i< RT_ELEMENTS(pContext->aSidActiveTextures); i++) + pContext->aSidActiveTextures[i] = SVGA3D_INVALID_ID; + pContext->state.shidVertex = SVGA3D_INVALID_ID; + pContext->state.shidPixel = SVGA3D_INVALID_ID; + + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); i++) + pContext->state.aRenderTargets[i] = SVGA3D_INVALID_ID; + + /* Create a context window with minimal 4x4 size. We will never use the swapchain + * to present the rendered image. Rendered images from the guest will be copied to + * the VMSVGA SCREEN object, which can be either an offscreen render target or + * system memory in the guest VRAM. + */ + rc = vmsvga3dContextWindowCreate(pState->hInstance, pState->pWindowThread, pState->WndRequestSem, &pContext->hwnd); + AssertRCReturn(rc, rc); + + /* Changed when the function returns. */ + D3DPRESENT_PARAMETERS PresParam; + PresParam.BackBufferWidth = 0; + PresParam.BackBufferHeight = 0; + PresParam.BackBufferFormat = D3DFMT_UNKNOWN; + PresParam.BackBufferCount = 0; + + PresParam.MultiSampleType = D3DMULTISAMPLE_NONE; + PresParam.MultiSampleQuality = 0; + PresParam.SwapEffect = D3DSWAPEFFECT_DISCARD; + PresParam.hDeviceWindow = pContext->hwnd; + PresParam.Windowed = TRUE; + PresParam.EnableAutoDepthStencil = FALSE; + PresParam.AutoDepthStencilFormat = D3DFMT_UNKNOWN; /* not relevant */ + PresParam.Flags = 0; + PresParam.FullScreen_RefreshRateInHz = 0; /* windowed -> 0 */ + /** @todo consider using D3DPRESENT_DONOTWAIT so we don't wait for the GPU during Present calls. */ + PresParam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + +#if 0 + VMSVGA3DCREATEDEVICEPARAMS Params = { pState, pContext, &PresParam, 0 }; + rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_CREATE_DEVICE, 0, (LPARAM)&Params); + AssertRCReturn(rc, rc); + hr = Params.hrc; + +#else + /** @todo Docs indicates that we should be using + * D3DCREATE_HARDWARE_VERTEXPROCESSING with W10 1607 and higher. + * https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dcreate */ + hr = pState->pD3D9->CreateDeviceEx(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + pContext->hwnd, + D3DCREATE_MULTITHREADED | D3DCREATE_MIXED_VERTEXPROCESSING, //D3DCREATE_HARDWARE_VERTEXPROCESSING, + &PresParam, + NULL, + &pContext->pDevice); +#endif + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dContextDefine: CreateDevice failed with %x\n", hr), VERR_INTERNAL_ERROR); + + Log(("vmsvga3dContextDefine: Backbuffer (%d,%d) count=%d format=%x\n", PresParam.BackBufferWidth, PresParam.BackBufferHeight, PresParam.BackBufferCount, PresParam.BackBufferFormat)); + return VINF_SUCCESS; +} + +/** + * Destroy an existing 3d context + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param cid Context id + */ +static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + AssertReturn(cid < SVGA3D_MAX_CONTEXT_IDS, VERR_INVALID_PARAMETER); + + if ( cid < pState->cContexts + && pState->papContexts[cid]->id == cid) + { + PVMSVGA3DCONTEXT pContext = pState->papContexts[cid]; + + Log(("vmsvga3dContextDestroy id %x\n", cid)); + + /* Cleanup the device runtime state. */ + if (pContext->pDevice) + pContext->pDevice->SetVertexDeclaration(NULL); + D3D_RELEASE(pContext->d3dState.pVertexDecl); + + /* Check for all surfaces that are associated with this context to remove all dependencies */ + for (uint32_t sid = 0; sid < pState->cSurfaces; sid++) + { + PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; + if ( pSurface->id == sid + && pSurface->idAssociatedContext == cid) + { + int rc; + + LogFunc(("Remove all dependencies for surface sid=%u\n", sid)); + + SVGA3dSurfaceAllFlags const surfaceFlags = pSurface->f.surfaceFlags; + SVGA3dSurfaceFormat const format = pSurface->format; + uint32_t const multisampleCount = pSurface->multiSampleCount; + SVGA3dTextureFilter const autogenFilter = pSurface->autogenFilter; + uint32_t const cFaces = pSurface->cFaces; + uint32_t const cMipLevels = pSurface->cLevels; + + SVGA3dSize *pMipLevelSize = (SVGA3dSize *)RTMemAllocZ(cMipLevels * cFaces * sizeof(SVGA3dSize)); + AssertReturn(pMipLevelSize, VERR_NO_MEMORY); + + for (uint32_t face = 0; face < pSurface->cFaces; face++) + { + for (uint32_t i = 0; i < cMipLevels; i++) + { + uint32_t idx = i + face * cMipLevels; + memcpy(&pMipLevelSize[idx], &pSurface->paMipmapLevels[idx].mipmapSize, sizeof(SVGA3dSize)); + } + } + + /* Recreate the surface with the original settings; destroys the contents, but that seems fairly safe since the context is also destroyed. */ +#ifdef DEBUG_sunlover + /** @todo not safe with shared objects */ + Assert(pSurface->pSharedObjectTree == NULL); +#endif + + rc = vmsvga3dSurfaceDestroy(pThisCC, sid); + AssertRC(rc); + + rc = vmsvga3dSurfaceDefine(pThisCC, sid, surfaceFlags, format, multisampleCount, autogenFilter, + cMipLevels, &pMipLevelSize[0], /* arraySize = */ 0, /* fAllocMipLevels = */ true); + AssertRC(rc); + + Assert(!pSurface->u.pSurface); + } + else + { + /* Check for a shared surface object. */ + PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)RTAvlU32Get(&pSurface->pSharedObjectTree, cid); + if (pSharedSurface) + { + LogFunc(("Remove shared dependency for surface sid=%u\n", sid)); + + switch (pSurface->enmD3DResType) + { + case VMSVGA3D_D3DRESTYPE_TEXTURE: + Assert(pSharedSurface->u.pTexture); + D3D_RELEASE(pSharedSurface->u.pTexture); + break; + + case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE: + Assert(pSharedSurface->u.pCubeTexture); + D3D_RELEASE(pSharedSurface->u.pCubeTexture); + break; + + case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE: + Assert(pSharedSurface->u.pVolumeTexture); + D3D_RELEASE(pSharedSurface->u.pVolumeTexture); + break; + + default: + AssertFailed(); + break; + } + RTAvlU32Remove(&pSurface->pSharedObjectTree, cid); + RTMemFree(pSharedSurface); + } + } + } + + /* Destroy all leftover pixel shaders. */ + for (uint32_t i = 0; i < pContext->cPixelShaders; i++) + { + if (pContext->paPixelShader[i].id != SVGA3D_INVALID_ID) + vmsvga3dBackShaderDestroy(pThisCC, pContext->paPixelShader[i].cid, pContext->paPixelShader[i].id, pContext->paPixelShader[i].type); + } + if (pContext->paPixelShader) + RTMemFree(pContext->paPixelShader); + + /* Destroy all leftover vertex shaders. */ + for (uint32_t i = 0; i < pContext->cVertexShaders; i++) + { + if (pContext->paVertexShader[i].id != SVGA3D_INVALID_ID) + vmsvga3dBackShaderDestroy(pThisCC, pContext->paVertexShader[i].cid, pContext->paVertexShader[i].id, pContext->paVertexShader[i].type); + } + if (pContext->paVertexShader) + RTMemFree(pContext->paVertexShader); + + if (pContext->state.paVertexShaderConst) + RTMemFree(pContext->state.paVertexShaderConst); + if (pContext->state.paPixelShaderConst) + RTMemFree(pContext->state.paPixelShaderConst); + + vmsvga3dBackOcclusionQueryDelete(pThisCC, pContext); + + /* Release the D3D device object */ + D3D_RELEASE(pContext->pDevice); + + /* Destroy the window we've created. */ + int rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_DESTROYWINDOW, (WPARAM)pContext->hwnd, 0); + AssertRC(rc); + + memset(pContext, 0, sizeof(*pContext)); + pContext->id = SVGA3D_INVALID_ID; + } + else + AssertFailed(); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + RT_NOREF(pThis, pThisCC, pScreen); + return VERR_NOT_IMPLEMENTED; +} + +static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + RT_NOREF(pThisCC, pScreen); + return VERR_NOT_IMPLEMENTED; +} + +static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, + SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage, + SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects) +{ + RT_NOREF(pThisCC, pScreen, destRect, srcImage, srcRect, cRects, paRects); + return VERR_NOT_IMPLEMENTED; +} + +static int vmsvga3dContextTrackUsage(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + /* Inject fences to make sure we can track surface usage in case the client wants to reuse it in another context. */ + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); ++i) + { + if (pContext->aSidActiveTextures[i] != SVGA3D_INVALID_ID) + vmsvga3dSurfaceTrackUsageById(pState, pContext, pContext->aSidActiveTextures[i]); + } + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); ++i) + if (pContext->state.aRenderTargets[i] != SVGA3D_INVALID_ID) + vmsvga3dSurfaceTrackUsageById(pState, pContext, pContext->state.aRenderTargets[i]); + + return VINF_SUCCESS; +} + +/* Handle resize */ +static DECLCALLBACK(int) vmsvga3dBackChangeMode(PVGASTATECC pThisCC) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + /* Resize all active contexts. */ + for (uint32_t i = 0; i < pState->cContexts; i++) + { + PVMSVGA3DCONTEXT pContext = pState->papContexts[i]; + uint32_t cid = pContext->id; + + if (cid != SVGA3D_INVALID_ID) + { + D3DPRESENT_PARAMETERS PresParam; + D3DVIEWPORT9 viewportOrg; + HRESULT hr; + +#ifdef VMSVGA3D_DIRECT3D9_RESET + /* Sync back all surface data as everything is lost after the Reset. */ + for (uint32_t sid = 0; sid < pState->cSurfaces; sid++) + { + PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; + if ( pSurface->id == sid + && pSurface->idAssociatedContext == cid + && pSurface->u.pSurface) + { + Log(("vmsvga3dChangeMode: sync back data of surface sid=%u (fDirty=%d)\n", sid, pSurface->fDirty)); + + /* Reallocate our surface memory buffers. */ + for (uint32_t i = 0; i < pSurface->cMipLevels; i++) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i]; + + pMipmapLevel->pSurfaceData = RTMemAllocZ(pMipmapLevel->cbSurface); + AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY); + + if (!pSurface->fDirty) + { + D3DLOCKED_RECT LockedRect; + + if (pSurface->bounce.pTexture) + { + IDirect3DSurface9 *pSrc, *pDest; + + /** @todo only sync when something was actually rendered (since the last sync) */ + Log(("vmsvga3dChangeMode: sync bounce buffer (level %d)\n", i)); + hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR); + + hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR); + + hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR); + + D3D_RELEASE(pSrc); + D3D_RELEASE(pDest); + + hr = pSurface->bounce.pTexture->LockRect(i, + &LockedRect, + NULL, + D3DLOCK_READONLY); + } + else + hr = pSurface->u.pTexture->LockRect(i, + &LockedRect, + NULL, + D3DLOCK_READONLY); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* Copy the data one line at a time in case the internal pitch is different. */ + for (uint32_t j = 0; j < pMipmapLevel->size.height; j++) + { + memcpy((uint8_t *)pMipmapLevel->pSurfaceData + j * pMipmapLevel->cbSurfacePitch, (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch, pMipmapLevel->cbSurfacePitch); + } + + if (pSurface->bounce.pTexture) + hr = pSurface->bounce.pTexture->UnlockRect(i); + else + hr = pSurface->u.pTexture->UnlockRect(i); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + } + + + switch (pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) + { + case SVGA3D_SURFACE_CUBEMAP: + case SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_HINT_TEXTURE: + case SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET: + D3D_RELEASE(pSurface->u.pCubeTexture); + D3D_RELEASE(pSurface->bounce.pCubeTexture); + break; + + case SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER: + case SVGA3D_SURFACE_HINT_INDEXBUFFER: + case SVGA3D_SURFACE_HINT_VERTEXBUFFER: + if (pSurface->fu32ActualUsageFlags == SVGA3D_SURFACE_HINT_VERTEXBUFFER) + D3D_RELEASE(pSurface->u.pVertexBuffer); + else if (pSurface->fu32ActualUsageFlags == SVGA3D_SURFACE_HINT_INDEXBUFFER) + D3D_RELEASE(pSurface->u.pIndexBuffer); + else + AssertMsg(pSurface->u.pVertexBuffer == NULL, ("fu32ActualUsageFlags %x\n", pSurface->fu32ActualUsageFlags)); + break; + + case SVGA3D_SURFACE_HINT_TEXTURE: + case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET: + D3D_RELEASE(pSurface->u.pTexture); + D3D_RELEASE(pSurface->bounce.pTexture); + break; + + case SVGA3D_SURFACE_HINT_RENDERTARGET: + case SVGA3D_SURFACE_HINT_DEPTHSTENCIL: + if (pSurface->fStencilAsTexture) + D3D_RELEASE(pSurface->u.pTexture); + else + D3D_RELEASE(pSurface->u.pSurface); + break; + + default: + AssertFailed(); + break; + } + RTAvlU32Destroy(&pSurface->pSharedObjectTree, vmsvga3dSharedSurfaceDestroyTree, pSurface); + Assert(pSurface->pSharedObjectTree == NULL); + + pSurface->idAssociatedContext = SVGA3D_INVALID_ID; + pSurface->hSharedObject = 0; + } + } +#endif /* #ifdef VMSVGA3D_DIRECT3D9_RESET */ + + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + /* Cleanup the device runtime state. */ + pContext->pDevice->SetVertexDeclaration(NULL); + D3D_RELEASE(pContext->d3dState.pVertexDecl); + + hr = pContext->pDevice->GetViewport(&viewportOrg); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR); + + Log(("vmsvga3dChangeMode: old viewport settings (%d,%d)(%d,%d) z=%d/%d\n", viewportOrg.X, viewportOrg.Y, viewportOrg.Width, viewportOrg.Height, (uint32_t)(viewportOrg.MinZ * 100.0), (uint32_t)(viewportOrg.MaxZ * 100.0))); + + /* Changed when the function returns. */ + PresParam.BackBufferWidth = 0; + PresParam.BackBufferHeight = 0; + PresParam.BackBufferFormat = D3DFMT_UNKNOWN; + PresParam.BackBufferCount = 0; + + PresParam.MultiSampleType = D3DMULTISAMPLE_NONE; + PresParam.MultiSampleQuality = 0; + PresParam.SwapEffect = D3DSWAPEFFECT_DISCARD; + PresParam.hDeviceWindow = pContext->hwnd; + PresParam.Windowed = TRUE; + PresParam.EnableAutoDepthStencil = FALSE; + PresParam.AutoDepthStencilFormat = D3DFMT_UNKNOWN; /* not relevant */ + PresParam.Flags = 0; + PresParam.FullScreen_RefreshRateInHz = 0; /* windowed -> 0 */ + /** @todo consider using D3DPRESENT_DONOTWAIT so we don't wait for the GPU during Present calls. */ + PresParam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;; + + /* ResetEx does not trash the device state */ + hr = pContext->pDevice->ResetEx(&PresParam, NULL); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: Reset failed with %x\n", hr), VERR_INTERNAL_ERROR); + + Log(("vmsvga3dChangeMode: Backbuffer (%d,%d) count=%d format=%x\n", PresParam.BackBufferWidth, PresParam.BackBufferHeight, PresParam.BackBufferCount, PresParam.BackBufferFormat)); + + /* ResetEx changes the viewport; restore it again. */ + hr = pContext->pDevice->SetViewport(&viewportOrg); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: SetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR); + +#ifdef LOG_ENABLED + { + D3DVIEWPORT9 viewport; + hr = pContext->pDevice->GetViewport(&viewport); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR); + + Log(("vmsvga3dChangeMode: changed viewport settings (%d,%d)(%d,%d) z=%d/%d\n", viewport.X, viewport.Y, viewport.Width, viewport.Height, (uint32_t)(viewport.MinZ * 100.0), (uint32_t)(viewport.MaxZ * 100.0))); + } +#endif + + /* First set the render targets as they change the internal state (reset viewport etc) */ + Log(("vmsvga3dChangeMode: Recreate render targets BEGIN\n")); + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aRenderTargets); j++) + { + if (pContext->state.aRenderTargets[j] != SVGA3D_INVALID_ID) + { + SVGA3dSurfaceImageId target; + + target.sid = pContext->state.aRenderTargets[j]; + target.face = 0; + target.mipmap = 0; + int rc = vmsvga3dBackSetRenderTarget(pThisCC, cid, (SVGA3dRenderTargetType)j, target); + AssertRCReturn(rc, rc); + } + } + +#ifdef VMSVGA3D_DIRECT3D9_RESET + /* Recreate the render state */ + Log(("vmsvga3dChangeMode: Recreate render state BEGIN\n")); + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderState); i++) + { + SVGA3dRenderState *pRenderState = &pContext->state.aRenderState[i]; + + if (pRenderState->state != SVGA3D_RS_INVALID) + vmsvga3dBackSetRenderState(pThisCC, pContext->id, 1, pRenderState); + } + Log(("vmsvga3dChangeMode: Recreate render state END\n")); + + /* Recreate the texture state */ + Log(("vmsvga3dChangeMode: Recreate texture state BEGIN\n")); + for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); iStage++) + { + for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); j++) + { + SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j]; + + if (pTextureState->name != SVGA3D_RS_INVALID) + vmsvga3dBackSetTextureState(pThisCC, pContext->id, 1, pTextureState); + } + } + Log(("vmsvga3dChangeMode: Recreate texture state END\n")); + + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_SCISSORRECT) + vmsvga3dBackSetScissorRect(pThis, cid, &pContext->state.RectScissor); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_ZRANGE) + vmsvga3dBackSetZRange(pThisCC, cid, pContext->state.zRange); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VIEWPORT) + vmsvga3dBackSetViewPort(pThis, cid, &pContext->state.RectViewPort); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VERTEXSHADER) + vmsvga3dBackShaderSet(pThis, pContext, cid, SVGA3D_SHADERTYPE_VS, pContext->state.shidVertex); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_PIXELSHADER) + vmsvga3dBackShaderSet(pThis, pContext, cid, SVGA3D_SHADERTYPE_PS, pContext->state.shidPixel); + /** @todo restore more state data */ +#endif /* #ifdef VMSVGA3D_DIRECT3D9_RESET */ + } + } + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16]) +{ + D3DTRANSFORMSTATETYPE d3dState; + HRESULT hr; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetTransform %x %s\n", cid, vmsvgaTransformToString(type))); + + ASSERT_GUEST_RETURN((unsigned)type < SVGA3D_TRANSFORM_MAX, VERR_INVALID_PARAMETER); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + switch (type) + { + case SVGA3D_TRANSFORM_VIEW: + d3dState = D3DTS_VIEW; + break; + case SVGA3D_TRANSFORM_PROJECTION: + d3dState = D3DTS_PROJECTION; + break; + case SVGA3D_TRANSFORM_TEXTURE0: + d3dState = D3DTS_TEXTURE0; + break; + case SVGA3D_TRANSFORM_TEXTURE1: + d3dState = D3DTS_TEXTURE1; + break; + case SVGA3D_TRANSFORM_TEXTURE2: + d3dState = D3DTS_TEXTURE2; + break; + case SVGA3D_TRANSFORM_TEXTURE3: + d3dState = D3DTS_TEXTURE3; + break; + case SVGA3D_TRANSFORM_TEXTURE4: + d3dState = D3DTS_TEXTURE4; + break; + case SVGA3D_TRANSFORM_TEXTURE5: + d3dState = D3DTS_TEXTURE5; + break; + case SVGA3D_TRANSFORM_TEXTURE6: + d3dState = D3DTS_TEXTURE6; + break; + case SVGA3D_TRANSFORM_TEXTURE7: + d3dState = D3DTS_TEXTURE7; + break; + case SVGA3D_TRANSFORM_WORLD: + d3dState = D3DTS_WORLD; + break; + case SVGA3D_TRANSFORM_WORLD1: + d3dState = D3DTS_WORLD1; + break; + case SVGA3D_TRANSFORM_WORLD2: + d3dState = D3DTS_WORLD2; + break; + case SVGA3D_TRANSFORM_WORLD3: + d3dState = D3DTS_WORLD3; + break; + + default: + Log(("vmsvga3dSetTransform: unknown type!!\n")); + return VERR_INVALID_PARAMETER; + } + + /* Save this matrix for vm state save/restore. */ + pContext->state.aTransformState[type].fValid = true; + memcpy(pContext->state.aTransformState[type].matrix, matrix, sizeof(pContext->state.aTransformState[type].matrix)); + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_TRANSFORM; + + Log(("Matrix [%d %d %d %d]\n", (int)(matrix[0] * 10.0), (int)(matrix[1] * 10.0), (int)(matrix[2] * 10.0), (int)(matrix[3] * 10.0))); + Log((" [%d %d %d %d]\n", (int)(matrix[4] * 10.0), (int)(matrix[5] * 10.0), (int)(matrix[6] * 10.0), (int)(matrix[7] * 10.0))); + Log((" [%d %d %d %d]\n", (int)(matrix[8] * 10.0), (int)(matrix[9] * 10.0), (int)(matrix[10] * 10.0), (int)(matrix[11] * 10.0))); + Log((" [%d %d %d %d]\n", (int)(matrix[12] * 10.0), (int)(matrix[13] * 10.0), (int)(matrix[14] * 10.0), (int)(matrix[15] * 10.0))); + hr = pContext->pDevice->SetTransform(d3dState, (const D3DMATRIX *)matrix); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetTransform: SetTransform failed with %x\n", hr), VERR_INTERNAL_ERROR); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange) +{ + D3DVIEWPORT9 viewport; + HRESULT hr; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetZRange %x min=%d max=%d\n", cid, (uint32_t)(zRange.min * 100.0), (uint32_t)(zRange.max * 100.0))); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + pContext->state.zRange = zRange; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_ZRANGE; + + hr = pContext->pDevice->GetViewport(&viewport); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetZRange: GetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR); + + Log(("vmsvga3dSetZRange: old viewport settings (%d,%d)(%d,%d) z=%d/%d\n", viewport.X, viewport.Y, viewport.Width, viewport.Height, (uint32_t)(viewport.MinZ * 100.0), (uint32_t)(viewport.MaxZ * 100.0))); + /** @todo convert the depth range from -1-1 to 0-1 although we shouldn't be getting such values in the first place... */ + if (zRange.min < 0.0) + zRange.min = 0.0; + if (zRange.max > 1.0) + zRange.max = 1.0; + + viewport.MinZ = zRange.min; + viewport.MaxZ = zRange.max; + hr = pContext->pDevice->SetViewport(&viewport); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetZRange: SetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR); + return VINF_SUCCESS; +} + +/** + * Convert SVGA blend op value to its D3D equivalent + */ +static DWORD vmsvga3dBlendOp2D3D(uint32_t blendOp, DWORD defaultBlendOp) +{ + switch (blendOp) + { + case SVGA3D_BLENDOP_ZERO: + return D3DBLEND_ZERO; + case SVGA3D_BLENDOP_ONE: + return D3DBLEND_ONE; + case SVGA3D_BLENDOP_SRCCOLOR: + return D3DBLEND_SRCCOLOR; + case SVGA3D_BLENDOP_INVSRCCOLOR: + return D3DBLEND_INVSRCCOLOR; + case SVGA3D_BLENDOP_SRCALPHA: + return D3DBLEND_SRCALPHA; + case SVGA3D_BLENDOP_INVSRCALPHA: + return D3DBLEND_INVSRCALPHA; + case SVGA3D_BLENDOP_DESTALPHA: + return D3DBLEND_DESTALPHA; + case SVGA3D_BLENDOP_INVDESTALPHA: + return D3DBLEND_INVDESTALPHA; + case SVGA3D_BLENDOP_DESTCOLOR: + return D3DBLEND_DESTCOLOR; + case SVGA3D_BLENDOP_INVDESTCOLOR: + return D3DBLEND_INVDESTCOLOR; + case SVGA3D_BLENDOP_SRCALPHASAT: + return D3DBLEND_SRCALPHASAT; + case SVGA3D_BLENDOP_BLENDFACTOR: + return D3DBLEND_BLENDFACTOR; + case SVGA3D_BLENDOP_INVBLENDFACTOR: + return D3DBLEND_INVBLENDFACTOR; + default: + AssertFailed(); + return defaultBlendOp; + } +} + +static DECLCALLBACK(int) vmsvga3dBackSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState) +{ + DWORD val = 0; /* Shut up MSC */ + HRESULT hr; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetRenderState cid=%u cRenderStates=%d\n", cid, cRenderStates)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + for (unsigned i = 0; i < cRenderStates; i++) + { + D3DRENDERSTATETYPE renderState = D3DRS_FORCE_DWORD; + + Log(("vmsvga3dSetRenderState: state=%s (%d) val=%x\n", vmsvga3dGetRenderStateName(pRenderState[i].state), pRenderState[i].state, pRenderState[i].uintValue)); + /* Save the render state for vm state saving. */ + ASSERT_GUEST_RETURN((unsigned)pRenderState[i].state < SVGA3D_RS_MAX, VERR_INVALID_PARAMETER); + pContext->state.aRenderState[pRenderState[i].state] = pRenderState[i]; + + switch (pRenderState[i].state) + { + case SVGA3D_RS_ZENABLE: /* SVGA3dBool */ + renderState = D3DRS_ZENABLE; + val = pRenderState[i].uintValue; + Assert(val == D3DZB_FALSE || val == D3DZB_TRUE); + break; + + case SVGA3D_RS_ZWRITEENABLE: /* SVGA3dBool */ + renderState = D3DRS_ZWRITEENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_ALPHATESTENABLE: /* SVGA3dBool */ + renderState = D3DRS_ALPHATESTENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_DITHERENABLE: /* SVGA3dBool */ + renderState = D3DRS_DITHERENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_BLENDENABLE: /* SVGA3dBool */ + renderState = D3DRS_ALPHABLENDENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_FOGENABLE: /* SVGA3dBool */ + renderState = D3DRS_FOGENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_SPECULARENABLE: /* SVGA3dBool */ + renderState = D3DRS_SPECULARENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_LIGHTINGENABLE: /* SVGA3dBool */ + renderState = D3DRS_LIGHTING; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_NORMALIZENORMALS: /* SVGA3dBool */ + renderState = D3DRS_NORMALIZENORMALS; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_POINTSPRITEENABLE: /* SVGA3dBool */ + renderState = D3DRS_POINTSPRITEENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_POINTSCALEENABLE: /* SVGA3dBool */ + renderState = D3DRS_POINTSCALEENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_POINTSIZE: /* float */ + renderState = D3DRS_POINTSIZE; + val = pRenderState[i].uintValue; + Log(("SVGA3D_RS_POINTSIZE: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0))); + break; + + case SVGA3D_RS_POINTSIZEMIN: /* float */ + renderState = D3DRS_POINTSIZE_MIN; + val = pRenderState[i].uintValue; + Log(("SVGA3D_RS_POINTSIZEMIN: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0))); + break; + + case SVGA3D_RS_POINTSIZEMAX: /* float */ + renderState = D3DRS_POINTSIZE_MAX; + val = pRenderState[i].uintValue; + Log(("SVGA3D_RS_POINTSIZEMAX: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0))); + break; + + case SVGA3D_RS_POINTSCALE_A: /* float */ + renderState = D3DRS_POINTSCALE_A; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_POINTSCALE_B: /* float */ + renderState = D3DRS_POINTSCALE_B; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_POINTSCALE_C: /* float */ + renderState = D3DRS_POINTSCALE_C; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_AMBIENT: /* SVGA3dColor - identical */ + renderState = D3DRS_AMBIENT; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_CLIPPLANEENABLE: /* SVGA3dClipPlanes - identical */ + renderState = D3DRS_CLIPPLANEENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_FOGCOLOR: /* SVGA3dColor - identical */ + renderState = D3DRS_FOGCOLOR; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_FOGSTART: /* float */ + renderState = D3DRS_FOGSTART; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_FOGEND: /* float */ + renderState = D3DRS_FOGEND; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_FOGDENSITY: /* float */ + renderState = D3DRS_FOGDENSITY; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_RANGEFOGENABLE: /* SVGA3dBool */ + renderState = D3DRS_RANGEFOGENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_FOGMODE: /* SVGA3dFogMode */ + { + SVGA3dFogMode mode; + mode.uintValue = pRenderState[i].uintValue; + + switch (mode.function) + { + case SVGA3D_FOGFUNC_INVALID: + val = D3DFOG_NONE; + break; + case SVGA3D_FOGFUNC_EXP: + val = D3DFOG_EXP; + break; + case SVGA3D_FOGFUNC_EXP2: + val = D3DFOG_EXP2; + break; + case SVGA3D_FOGFUNC_LINEAR: + val = D3DFOG_LINEAR; + break; + case SVGA3D_FOGFUNC_PER_VERTEX: /* unable to find a d3d9 equivalent */ + AssertMsgFailedReturn(("Unsupported fog function SVGA3D_FOGFUNC_PER_VERTEX\n"), VERR_INTERNAL_ERROR); + break; + default: + AssertMsgFailedReturn(("Unexpected fog function %d\n", mode.function), VERR_INTERNAL_ERROR); + break; + } + + /* The fog type determines the render state. */ + switch (mode.type) + { + case SVGA3D_FOGTYPE_VERTEX: + renderState = D3DRS_FOGVERTEXMODE; + break; + case SVGA3D_FOGTYPE_PIXEL: + renderState = D3DRS_FOGTABLEMODE; + break; + default: + AssertMsgFailedReturn(("Unexpected fog type %d\n", mode.type), VERR_INTERNAL_ERROR); + break; + } + + /* Set the fog base to depth or range. */ + switch (mode.base) + { + case SVGA3D_FOGBASE_DEPTHBASED: + hr = pContext->pDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderState: SetRenderState SVGA3D_FOGBASE_DEPTHBASED failed with %x\n", hr), VERR_INTERNAL_ERROR); + break; + case SVGA3D_FOGBASE_RANGEBASED: + hr = pContext->pDevice->SetRenderState(D3DRS_RANGEFOGENABLE, TRUE); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderState: SetRenderState SVGA3D_FOGBASE_RANGEBASED failed with %x\n", hr), VERR_INTERNAL_ERROR); + break; + default: + /* ignore */ + AssertMsgFailed(("Unexpected fog base %d\n", mode.base)); + break; + } + break; + } + + case SVGA3D_RS_FILLMODE: /* SVGA3dFillMode */ + { + SVGA3dFillMode mode; + + mode.uintValue = pRenderState[i].uintValue; + + switch (mode.mode) + { + case SVGA3D_FILLMODE_POINT: + val = D3DFILL_POINT; + break; + case SVGA3D_FILLMODE_LINE: + val = D3DFILL_WIREFRAME; + break; + case SVGA3D_FILLMODE_FILL: + val = D3DFILL_SOLID; + break; + default: + AssertMsgFailedReturn(("Unexpected fill mode %d\n", mode.mode), VERR_INTERNAL_ERROR); + break; + } + /** @todo ignoring face for now. */ + renderState = D3DRS_FILLMODE; + break; + } + + case SVGA3D_RS_SHADEMODE: /* SVGA3dShadeMode */ + renderState = D3DRS_SHADEMODE; + AssertCompile(D3DSHADE_FLAT == SVGA3D_SHADEMODE_FLAT); + val = pRenderState[i].uintValue; /* SVGA3dShadeMode == D3DSHADEMODE */ + break; + + case SVGA3D_RS_LINEPATTERN: /* SVGA3dLinePattern */ + /* No longer supported by d3d; mesagl comments suggest not all backends support it */ + /** @todo */ + Log(("WARNING: SVGA3D_RS_LINEPATTERN %x not supported!!\n", pRenderState[i].uintValue)); + /* + renderState = D3DRS_LINEPATTERN; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_SRCBLEND: /* SVGA3dBlendOp */ + renderState = D3DRS_SRCBLEND; + val = vmsvga3dBlendOp2D3D(pRenderState[i].uintValue, D3DBLEND_ONE /* default */); + break; + + case SVGA3D_RS_DSTBLEND: /* SVGA3dBlendOp */ + renderState = D3DRS_DESTBLEND; + val = vmsvga3dBlendOp2D3D(pRenderState[i].uintValue, D3DBLEND_ZERO /* default */); + break; + + case SVGA3D_RS_BLENDEQUATION: /* SVGA3dBlendEquation - identical */ + AssertCompile(SVGA3D_BLENDEQ_MAXIMUM == D3DBLENDOP_MAX); + renderState = D3DRS_BLENDOP; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_CULLMODE: /* SVGA3dFace */ + { + switch (pRenderState[i].uintValue) + { + case SVGA3D_FACE_NONE: + val = D3DCULL_NONE; + break; + case SVGA3D_FACE_FRONT: + val = D3DCULL_CW; + break; + case SVGA3D_FACE_BACK: + val = D3DCULL_CCW; + break; + case SVGA3D_FACE_FRONT_BACK: + AssertFailed(); + val = D3DCULL_CW; + break; + default: + AssertMsgFailedReturn(("Unexpected cull mode %d\n", pRenderState[i].uintValue), VERR_INTERNAL_ERROR); + break; + } + renderState = D3DRS_CULLMODE; + break; + } + + case SVGA3D_RS_ZFUNC: /* SVGA3dCmpFunc - identical */ + AssertCompile(SVGA3D_CMP_ALWAYS == D3DCMP_ALWAYS); + renderState = D3DRS_ZFUNC; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_ALPHAFUNC: /* SVGA3dCmpFunc - identical */ + renderState = D3DRS_ALPHAFUNC; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILENABLE: /* SVGA3dBool */ + renderState = D3DRS_STENCILENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILREF: /* uint32_t */ + renderState = D3DRS_STENCILREF; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILMASK: /* uint32_t */ + renderState = D3DRS_STENCILMASK; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILWRITEMASK: /* uint32_t */ + renderState = D3DRS_STENCILWRITEMASK; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc - identical */ + renderState = D3DRS_STENCILFUNC; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp - identical */ + AssertCompile(D3DSTENCILOP_KEEP == SVGA3D_STENCILOP_KEEP); + AssertCompile(D3DSTENCILOP_DECR == SVGA3D_STENCILOP_DECR); + renderState = D3DRS_STENCILFAIL; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp - identical */ + renderState = D3DRS_STENCILZFAIL; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp - identical */ + renderState = D3DRS_STENCILPASS; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_ALPHAREF: /* float (0.0 .. 1.0) */ + renderState = D3DRS_ALPHAREF; + val = (uint8_t)(pRenderState[i].floatValue * 255.0f); /* D3DRS_ALPHAREF 0..255 */ + break; + + case SVGA3D_RS_FRONTWINDING: /* SVGA3dFrontWinding */ + Assert(pRenderState[i].uintValue == SVGA3D_FRONTWINDING_CW); + /* + renderState = D3DRS_FRONTWINDING; //D3DRS_TWOSIDEDSTENCILMODE + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_COORDINATETYPE: /* SVGA3dCoordinateType */ + Assert(pRenderState[i].uintValue == SVGA3D_COORDINATE_LEFTHANDED); + /** @todo setup a view matrix to scale the world space by -1 in the z-direction for right handed coordinates. */ + /* + renderState = D3DRS_COORDINATETYPE; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_ZBIAS: /* float */ + /** @todo unknown meaning; depth bias is not identical + renderState = D3DRS_DEPTHBIAS; + val = pRenderState[i].uintValue; + */ + Log(("vmsvga3dSetRenderState: WARNING unsupported SVGA3D_RS_ZBIAS\n")); + break; + + case SVGA3D_RS_SLOPESCALEDEPTHBIAS: /* float */ + renderState = D3DRS_SLOPESCALEDEPTHBIAS; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_DEPTHBIAS: /* float */ + renderState = D3DRS_DEPTHBIAS; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_COLORWRITEENABLE: /* SVGA3dColorMask - identical to D3DCOLORWRITEENABLE_* */ + renderState = D3DRS_COLORWRITEENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_VERTEXMATERIALENABLE: /* SVGA3dBool */ + //AssertFailed(); + renderState = D3DRS_INDEXEDVERTEXBLENDENABLE; /* correct?? */ + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_DIFFUSEMATERIALSOURCE: /* SVGA3dVertexMaterial - identical */ + AssertCompile(D3DMCS_COLOR2 == SVGA3D_VERTEXMATERIAL_SPECULAR); + renderState = D3DRS_DIFFUSEMATERIALSOURCE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_SPECULARMATERIALSOURCE: /* SVGA3dVertexMaterial - identical */ + renderState = D3DRS_SPECULARMATERIALSOURCE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_AMBIENTMATERIALSOURCE: /* SVGA3dVertexMaterial - identical */ + renderState = D3DRS_AMBIENTMATERIALSOURCE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_EMISSIVEMATERIALSOURCE: /* SVGA3dVertexMaterial - identical */ + renderState = D3DRS_EMISSIVEMATERIALSOURCE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_TEXTUREFACTOR: /* SVGA3dColor - identical */ + renderState = D3DRS_TEXTUREFACTOR; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_LOCALVIEWER: /* SVGA3dBool */ + renderState = D3DRS_LOCALVIEWER; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_SCISSORTESTENABLE: /* SVGA3dBool */ + renderState = D3DRS_SCISSORTESTENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_BLENDCOLOR: /* SVGA3dColor - identical */ + renderState = D3DRS_BLENDFACTOR; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_STENCILENABLE2SIDED: /* SVGA3dBool */ + renderState = D3DRS_TWOSIDEDSTENCILMODE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_CCWSTENCILFUNC: /* SVGA3dCmpFunc - identical */ + renderState = D3DRS_CCW_STENCILFUNC; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp - identical */ + renderState = D3DRS_CCW_STENCILFAIL; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp - identical */ + renderState = D3DRS_CCW_STENCILZFAIL; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp - identical */ + renderState = D3DRS_CCW_STENCILPASS; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_VERTEXBLEND: /* SVGA3dVertexBlendFlags - identical */ + AssertCompile(SVGA3D_VBLEND_DISABLE == D3DVBF_DISABLE); + renderState = D3DRS_VERTEXBLEND; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_OUTPUTGAMMA: /* float */ + //AssertFailed(); + /* + D3DRS_SRGBWRITEENABLE ?? + renderState = D3DRS_OUTPUTGAMMA; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_ZVISIBLE: /* SVGA3dBool */ + AssertFailed(); + /* + renderState = D3DRS_ZVISIBLE; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_LASTPIXEL: /* SVGA3dBool */ + renderState = D3DRS_LASTPIXEL; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_CLIPPING: /* SVGA3dBool */ + renderState = D3DRS_CLIPPING; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP0: /* SVGA3dWrapFlags - identical */ + Assert(SVGA3D_WRAPCOORD_3 == D3DWRAPCOORD_3); + renderState = D3DRS_WRAP0; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP1: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP1; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP2: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP2; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP3: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP3; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP4: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP4; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP5: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP5; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP6: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP6; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP7: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP7; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP8: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP8; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP9: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP9; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP10: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP10; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP11: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP11; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP12: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP12; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP13: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP13; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP14: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP14; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_WRAP15: /* SVGA3dWrapFlags - identical */ + renderState = D3DRS_WRAP15; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_MULTISAMPLEANTIALIAS: /* SVGA3dBool */ + renderState = D3DRS_MULTISAMPLEANTIALIAS; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_MULTISAMPLEMASK: /* uint32_t */ + renderState = D3DRS_MULTISAMPLEMASK; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_INDEXEDVERTEXBLENDENABLE: /* SVGA3dBool */ + renderState = D3DRS_INDEXEDVERTEXBLENDENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_TWEENFACTOR: /* float */ + renderState = D3DRS_TWEENFACTOR; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_ANTIALIASEDLINEENABLE: /* SVGA3dBool */ + renderState = D3DRS_ANTIALIASEDLINEENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_COLORWRITEENABLE1: /* SVGA3dColorMask - identical to D3DCOLORWRITEENABLE_* */ + renderState = D3DRS_COLORWRITEENABLE1; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_COLORWRITEENABLE2: /* SVGA3dColorMask - identical to D3DCOLORWRITEENABLE_* */ + renderState = D3DRS_COLORWRITEENABLE2; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_COLORWRITEENABLE3: /* SVGA3dColorMask - identical to D3DCOLORWRITEENABLE_* */ + renderState = D3DRS_COLORWRITEENABLE3; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */ + renderState = D3DRS_SEPARATEALPHABLENDENABLE; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_SRCBLENDALPHA: /* SVGA3dBlendOp */ + renderState = D3DRS_SRCBLENDALPHA; + val = vmsvga3dBlendOp2D3D(pRenderState[i].uintValue, D3DBLEND_ONE /* default */); + break; + + case SVGA3D_RS_DSTBLENDALPHA: /* SVGA3dBlendOp */ + renderState = D3DRS_DESTBLENDALPHA; + val = vmsvga3dBlendOp2D3D(pRenderState[i].uintValue, D3DBLEND_ZERO /* default */); + break; + + case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation - identical */ + renderState = D3DRS_BLENDOPALPHA; + val = pRenderState[i].uintValue; + break; + + case SVGA3D_RS_TRANSPARENCYANTIALIAS: /* SVGA3dTransparencyAntialiasType */ + AssertFailed(); + /* + renderState = D3DRS_TRANSPARENCYANTIALIAS; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_LINEWIDTH: /* float */ + AssertFailed(); + /* + renderState = D3DRS_LINEWIDTH; + val = pRenderState[i].uintValue; + */ + break; + + case SVGA3D_RS_MAX: /* shut up MSC */ + case SVGA3D_RS_INVALID: + AssertFailedBreak(); + } + + if (renderState != D3DRS_FORCE_DWORD) + { + hr = pContext->pDevice->SetRenderState(renderState, val); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderState: SetRenderState failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target) +{ + HRESULT hr; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + + AssertReturn(pState, VERR_NO_MEMORY); + AssertReturn((unsigned)type < SVGA3D_RT_MAX, VERR_INVALID_PARAMETER); + + LogFunc(("cid=%u type=%x sid=%u face=%u mipmap=%u\n", cid, type, target.sid, target.face, target.mipmap)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + /* Save for vm state save/restore. */ + pContext->state.aRenderTargets[type] = target.sid; + /** @todo Also save target.face and target.mipmap */ + + if (target.sid == SVGA3D_INVALID_ID) + { + /* Disable render target. */ + switch (type) + { + case SVGA3D_RT_DEPTH: + hr = pContext->pDevice->SetDepthStencilSurface(NULL); + AssertMsgReturn(hr == D3D_OK, ("SetDepthStencilSurface failed with %x\n", hr), VERR_INTERNAL_ERROR); + break; + + case SVGA3D_RT_STENCIL: + /* ignore; correct?? */ + break; + + case SVGA3D_RT_COLOR0: + case SVGA3D_RT_COLOR1: + case SVGA3D_RT_COLOR2: + case SVGA3D_RT_COLOR3: + case SVGA3D_RT_COLOR4: + case SVGA3D_RT_COLOR5: + case SVGA3D_RT_COLOR6: + case SVGA3D_RT_COLOR7: + if (pState->fSupportedSurfaceNULL) + { + /* Create a dummy render target to satisfy D3D. This path is usually taken only to render + * into a depth buffer without wishing to update an actual color render target. + * The dimensions of the render target must match the dimensions of the depth render target, + * which is usually equal to the viewport width and height. + */ + IDirect3DSurface9 *pDummyRenderTarget; + hr = pContext->pDevice->CreateRenderTarget(pContext->state.RectViewPort.w, + pContext->state.RectViewPort.h, + FOURCC_NULL, + D3DMULTISAMPLE_NONE, + 0, + FALSE, + &pDummyRenderTarget, + NULL); + + AssertMsgReturn(hr == D3D_OK, ("CreateRenderTarget failed with %x\n", hr), VERR_INTERNAL_ERROR); + + hr = pContext->pDevice->SetRenderTarget(type - SVGA3D_RT_COLOR0, pDummyRenderTarget); + D3D_RELEASE(pDummyRenderTarget); + } + else + hr = pContext->pDevice->SetRenderTarget(type - SVGA3D_RT_COLOR0, NULL); + + AssertMsgReturn(hr == D3D_OK, ("SetRenderTarget failed with %x\n", hr), VERR_INTERNAL_ERROR); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + return VINF_SUCCESS; + } + + PVMSVGA3DSURFACE pRenderTarget; + rc = vmsvga3dSurfaceFromSid(pState, target.sid, &pRenderTarget); + AssertRCReturn(rc, rc); + + switch (type) + { + case SVGA3D_RT_DEPTH: + case SVGA3D_RT_STENCIL: + AssertReturn(target.face == 0 && target.mipmap == 0, VERR_INVALID_PARAMETER); + if (!pRenderTarget->u.pSurface) + { + DWORD cQualityLevels = 0; + + /* Query the nr of quality levels for this particular format */ + if (pRenderTarget->multiSampleTypeD3D != D3DMULTISAMPLE_NONE) + { + hr = pState->pD3D9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + pRenderTarget->formatD3D, + TRUE, /* Windowed */ + pRenderTarget->multiSampleTypeD3D, + &cQualityLevels); + Assert(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE); + } + + if ( pState->fSupportedSurfaceINTZ + && pRenderTarget->multiSampleTypeD3D == D3DMULTISAMPLE_NONE + && ( pRenderTarget->formatD3D == D3DFMT_D24S8 + || pRenderTarget->formatD3D == D3DFMT_D24X8 + || pRenderTarget->formatD3D == D3DFMT_D32 + || pRenderTarget->formatD3D == D3DFMT_D16)) + { + LogFunc(("Creating stencil surface as texture!\n")); + int rc2 = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pRenderTarget); + AssertRC(rc2); /* non-fatal, will use CreateDepthStencilSurface */ + } + + if (!pRenderTarget->fStencilAsTexture) + { + Assert(!pRenderTarget->u.pSurface); + + LogFunc(("DEPTH/STENCIL; cQualityLevels=%d\n", cQualityLevels)); + hr = pContext->pDevice->CreateDepthStencilSurface(pRenderTarget->paMipmapLevels[0].mipmapSize.width, + pRenderTarget->paMipmapLevels[0].mipmapSize.height, + pRenderTarget->formatD3D, + pRenderTarget->multiSampleTypeD3D, + ((cQualityLevels >= 1) ? cQualityLevels - 1 : 0), /* 0 - (levels-1) */ + FALSE, /* not discardable */ + &pRenderTarget->u.pSurface, + NULL); + AssertMsgReturn(hr == D3D_OK, ("CreateDepthStencilSurface failed with %x\n", hr), VERR_INTERNAL_ERROR); + pRenderTarget->enmD3DResType = VMSVGA3D_D3DRESTYPE_SURFACE; + } + + pRenderTarget->idAssociatedContext = cid; + +#if 0 /* doesn't work */ + if ( !pRenderTarget->fStencilAsTexture + && pRenderTarget->fDirty) + { + Log(("vmsvga3dSetRenderTarget: sync dirty depth/stencil buffer\n")); + Assert(pRenderTarget->cLevels == 1); + + for (uint32_t i = 0; i < pRenderTarget->cLevels; i++) + { + if (pRenderTarget->paMipmapLevels[i].fDirty) + { + D3DLOCKED_RECT LockedRect; + + hr = pRenderTarget->u.pSurface->LockRect(&LockedRect, + NULL, /* entire surface */ + 0); + + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + Log(("vmsvga3dSetRenderTarget: sync dirty texture mipmap level %d (pitch %x vs %x)\n", i, LockedRect.Pitch, pRenderTarget->paMipmapLevels[i].cbSurfacePitch)); + + uint8_t *pDest = (uint8_t *)LockedRect.pBits; + uint8_t *pSrc = (uint8_t *)pRenderTarget->paMipmapLevels[i].pSurfaceData; + for (uint32_t j = 0; j < pRenderTarget->paMipmapLevels[i].size.height; j++) + { + memcpy(pDest, pSrc, pRenderTarget->paMipmapLevels[i].cbSurfacePitch); + + pDest += LockedRect.Pitch; + pSrc += pRenderTarget->paMipmapLevels[i].cbSurfacePitch; + } + + hr = pRenderTarget->u.pSurface->UnlockRect(); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + pRenderTarget->paMipmapLevels[i].fDirty = false; + } + } + } +#endif + } + + /** @todo Assert(!pRenderTarget->fDirty); */ + + AssertReturn(pRenderTarget->u.pSurface, VERR_INVALID_PARAMETER); + + pRenderTarget->fUsageD3D |= D3DUSAGE_DEPTHSTENCIL; + pRenderTarget->f.surfaceFlags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL; + + if (pRenderTarget->fStencilAsTexture) + { + IDirect3DSurface9 *pStencilSurface; + + rc = vmsvga3dGetD3DSurface(pState, pContext, pRenderTarget, target.face, target.mipmap, /*fLockable=*/ false, &pStencilSurface); + AssertRCReturn(rc, rc); + + hr = pContext->pDevice->SetDepthStencilSurface(pStencilSurface); + D3D_RELEASE(pStencilSurface); + AssertMsgReturn(hr == D3D_OK, ("SetDepthStencilSurface failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else + { + Assert(pRenderTarget->idAssociatedContext == cid); + AssertReturn(pRenderTarget->enmD3DResType == VMSVGA3D_D3DRESTYPE_SURFACE, VERR_INVALID_PARAMETER); + hr = pContext->pDevice->SetDepthStencilSurface(pRenderTarget->u.pSurface); + AssertMsgReturn(hr == D3D_OK, ("SetDepthStencilSurface failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + break; + + case SVGA3D_RT_COLOR0: + case SVGA3D_RT_COLOR1: + case SVGA3D_RT_COLOR2: + case SVGA3D_RT_COLOR3: + case SVGA3D_RT_COLOR4: + case SVGA3D_RT_COLOR5: + case SVGA3D_RT_COLOR6: + case SVGA3D_RT_COLOR7: + { + IDirect3DSurface9 *pSurface; + bool fTexture = false; + + /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */ + vmsvga3dSurfaceFlush(pRenderTarget); + + if (pRenderTarget->f.surfaceFlags & SVGA3D_SURFACE_HINT_TEXTURE) + { + fTexture = true; + + /* A texture surface can be used as a render target to fill it and later on used as a texture. */ + if (!pRenderTarget->u.pTexture) + { + LogFunc(("Create texture to be used as render target; sid=%u type=%d format=%d -> create texture\n", target.sid, pRenderTarget->f.s.surface1Flags, pRenderTarget->format)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pRenderTarget); + AssertRCReturn(rc, rc); + } + + rc = vmsvga3dGetD3DSurface(pState, pContext, pRenderTarget, target.face, target.mipmap, false, &pSurface); + AssertRCReturn(rc, rc); + } + else + { + AssertReturn(target.face == 0 && target.mipmap == 0, VERR_INVALID_PARAMETER); + if (!pRenderTarget->u.pSurface) + { + DWORD cQualityLevels = 0; + + /* Query the nr of quality levels for this particular format */ + if (pRenderTarget->multiSampleTypeD3D != D3DMULTISAMPLE_NONE) + { + hr = pState->pD3D9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + pRenderTarget->formatD3D, + TRUE, /* Windowed */ + pRenderTarget->multiSampleTypeD3D, + &cQualityLevels); + Assert(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE); + } + + LogFunc(("COLOR; cQualityLevels=%d\n", cQualityLevels)); + LogFunc(("Create rendertarget (%d,%d) formatD3D=%x multisample=%x\n", + pRenderTarget->paMipmapLevels[0].mipmapSize.width, pRenderTarget->paMipmapLevels[0].mipmapSize.height, pRenderTarget->formatD3D, pRenderTarget->multiSampleTypeD3D)); + + hr = pContext->pDevice->CreateRenderTarget(pRenderTarget->paMipmapLevels[0].mipmapSize.width, + pRenderTarget->paMipmapLevels[0].mipmapSize.height, + pRenderTarget->formatD3D, + pRenderTarget->multiSampleTypeD3D, + ((cQualityLevels >= 1) ? cQualityLevels - 1 : 0), /* 0 - (levels-1) */ + TRUE, /* lockable */ + &pRenderTarget->u.pSurface, + NULL); + AssertReturn(hr == D3D_OK, VERR_INTERNAL_ERROR); + + pRenderTarget->idAssociatedContext = cid; + pRenderTarget->enmD3DResType = VMSVGA3D_D3DRESTYPE_SURFACE; + } + else + AssertReturn(pRenderTarget->fUsageD3D & D3DUSAGE_RENDERTARGET, VERR_INVALID_PARAMETER); + + Assert(pRenderTarget->idAssociatedContext == cid); + AssertMsgReturn(pRenderTarget->enmD3DResType == VMSVGA3D_D3DRESTYPE_SURFACE, + ("Invalid render target %#x\n", pRenderTarget->enmD3DResType), + VERR_INVALID_PARAMETER); + pSurface = pRenderTarget->u.pSurface; + } + + AssertReturn(pSurface, VERR_INVALID_PARAMETER); + Assert(!pRenderTarget->fDirty); + + pRenderTarget->fUsageD3D |= D3DUSAGE_RENDERTARGET; + pRenderTarget->f.surfaceFlags |= SVGA3D_SURFACE_HINT_RENDERTARGET; + + hr = pContext->pDevice->SetRenderTarget(type - SVGA3D_RT_COLOR0, pSurface); + if (fTexture) + D3D_RELEASE(pSurface); /* Release reference to texture level 0 */ + AssertMsgReturn(hr == D3D_OK, ("SetRenderTarget failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* Changing the render target resets the viewport; restore it here. */ + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VIEWPORT) + vmsvga3dBackSetViewPort(pThisCC, cid, &pContext->state.RectViewPort); + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_ZRANGE) + vmsvga3dBackSetZRange(pThisCC, cid, pContext->state.zRange); + /* Changing the render target also resets the scissor rectangle; restore it as well. */ + if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_SCISSORRECT) + vmsvga3dBackSetScissorRect(pThisCC, cid, &pContext->state.RectScissor); + + break; + } + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + + return VINF_SUCCESS; +} + +/** + * Convert SVGA texture combiner value to its D3D equivalent + */ +static DWORD vmsvga3dTextureCombiner2D3D(uint32_t value) +{ + switch (value) + { + case SVGA3D_TC_DISABLE: + return D3DTOP_DISABLE; + case SVGA3D_TC_SELECTARG1: + return D3DTOP_SELECTARG1; + case SVGA3D_TC_SELECTARG2: + return D3DTOP_SELECTARG2; + case SVGA3D_TC_MODULATE: + return D3DTOP_MODULATE; + case SVGA3D_TC_ADD: + return D3DTOP_ADD; + case SVGA3D_TC_ADDSIGNED: + return D3DTOP_ADDSIGNED; + case SVGA3D_TC_SUBTRACT: + return D3DTOP_SUBTRACT; + case SVGA3D_TC_BLENDTEXTUREALPHA: + return D3DTOP_BLENDTEXTUREALPHA; + case SVGA3D_TC_BLENDDIFFUSEALPHA: + return D3DTOP_BLENDDIFFUSEALPHA; + case SVGA3D_TC_BLENDCURRENTALPHA: + return D3DTOP_BLENDCURRENTALPHA; + case SVGA3D_TC_BLENDFACTORALPHA: + return D3DTOP_BLENDFACTORALPHA; + case SVGA3D_TC_MODULATE2X: + return D3DTOP_MODULATE2X; + case SVGA3D_TC_MODULATE4X: + return D3DTOP_MODULATE4X; + case SVGA3D_TC_DSDT: + AssertFailed(); /** @todo ??? */ + return D3DTOP_DISABLE; + case SVGA3D_TC_DOTPRODUCT3: + return D3DTOP_DOTPRODUCT3; + case SVGA3D_TC_BLENDTEXTUREALPHAPM: + return D3DTOP_BLENDTEXTUREALPHAPM; + case SVGA3D_TC_ADDSIGNED2X: + return D3DTOP_ADDSIGNED2X; + case SVGA3D_TC_ADDSMOOTH: + return D3DTOP_ADDSMOOTH; + case SVGA3D_TC_PREMODULATE: + return D3DTOP_PREMODULATE; + case SVGA3D_TC_MODULATEALPHA_ADDCOLOR: + return D3DTOP_MODULATEALPHA_ADDCOLOR; + case SVGA3D_TC_MODULATECOLOR_ADDALPHA: + return D3DTOP_MODULATECOLOR_ADDALPHA; + case SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR: + return D3DTOP_MODULATEINVALPHA_ADDCOLOR; + case SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA: + return D3DTOP_MODULATEINVCOLOR_ADDALPHA; + case SVGA3D_TC_BUMPENVMAPLUMINANCE: + return D3DTOP_BUMPENVMAPLUMINANCE; + case SVGA3D_TC_MULTIPLYADD: + return D3DTOP_MULTIPLYADD; + case SVGA3D_TC_LERP: + return D3DTOP_LERP; + default: + AssertFailed(); + return D3DTOP_DISABLE; + } +} + +/** + * Convert SVGA texture arg data value to its D3D equivalent + */ +static DWORD vmsvga3dTextureArgData2D3D(uint32_t value) +{ + switch (value) + { + case SVGA3D_TA_CONSTANT: + return D3DTA_CONSTANT; + case SVGA3D_TA_PREVIOUS: + return D3DTA_CURRENT; /* current = previous */ + case SVGA3D_TA_DIFFUSE: + return D3DTA_DIFFUSE; + case SVGA3D_TA_TEXTURE: + return D3DTA_TEXTURE; + case SVGA3D_TA_SPECULAR: + return D3DTA_SPECULAR; + default: + AssertFailed(); + return D3DTA_DIFFUSE; + } +} + +/** + * Convert SVGA texture transform flag value to its D3D equivalent + */ +static DWORD vmsvga3dTextTransformFlags2D3D(uint32_t value) +{ + switch (value) + { + case SVGA3D_TEX_TRANSFORM_OFF: + return D3DTTFF_DISABLE; + case SVGA3D_TEX_TRANSFORM_S: + return D3DTTFF_COUNT1; /** @todo correct? */ + case SVGA3D_TEX_TRANSFORM_T: + return D3DTTFF_COUNT2; /** @todo correct? */ + case SVGA3D_TEX_TRANSFORM_R: + return D3DTTFF_COUNT3; /** @todo correct? */ + case SVGA3D_TEX_TRANSFORM_Q: + return D3DTTFF_COUNT4; /** @todo correct? */ + case SVGA3D_TEX_PROJECTED: + return D3DTTFF_PROJECTED; + default: + AssertFailed(); + return D3DTTFF_DISABLE; + } +} + +static DWORD vmsvga3dSamplerIndex2D3D(uint32_t idxSampler) +{ + if (idxSampler < SVGA3D_MAX_SAMPLERS_PS) + return idxSampler; + return (idxSampler - SVGA3D_MAX_SAMPLERS_PS) + D3DDMAPSAMPLER; +} + +static DECLCALLBACK(int) vmsvga3dBackSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState) +{ + DWORD val = 0; /* Shut up MSC */ + HRESULT hr; + PVMSVGA3DCONTEXT pContext; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("%x cTextureState=%d\n", cid, cTextureStates)); + + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + for (unsigned i = 0; i < cTextureStates; i++) + { + LogFunc(("cid=%u stage=%d type=%s (%x) val=%x\n", cid, pTextureState[i].stage, vmsvga3dTextureStateToString(pTextureState[i].name), pTextureState[i].name, pTextureState[i].value)); + + if (pTextureState[i].name == SVGA3D_TS_BIND_TEXTURE) + { + /* Special case: binding a texture to a sampler. Stage is the sampler index. */ + const uint32_t sid = pTextureState[i].value; + const uint32_t idxSampler = pTextureState[i].stage; + + if (RT_UNLIKELY(idxSampler >= SVGA3D_MAX_SAMPLERS)) + { + AssertMsgFailed(("pTextureState[%d]: SVGA3D_TS_BIND_TEXTURE idxSampler=%d, sid=%u\n", i, idxSampler, sid)); + continue; + } + + const DWORD d3dSampler = vmsvga3dSamplerIndex2D3D(idxSampler); + if (sid == SVGA3D_INVALID_ID) + { + LogFunc(("SVGA3D_TS_BIND_TEXTURE: unbind sampler=%d\n", idxSampler)); + + pContext->aSidActiveTextures[idxSampler] = SVGA3D_INVALID_ID; + + /* Unselect the currently associated texture. */ + hr = pContext->pDevice->SetTexture(d3dSampler, NULL); + AssertMsgReturn(hr == D3D_OK, ("SetTexture failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else + { + PVMSVGA3DSURFACE pSurface; + rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + + LogFunc(("SVGA3D_TS_BIND_TEXTURE: bind idxSampler=%d, texture sid=%u (%d,%d)\n", idxSampler, sid, pSurface->paMipmapLevels[0].mipmapSize.width, pSurface->paMipmapLevels[0].mipmapSize.height)); + + if (!pSurface->u.pTexture) + { + Assert(pSurface->idAssociatedContext == SVGA3D_INVALID_ID); + LogFunc(("CreateTexture (%d,%d) level=%d fUsage=%x format=%x\n", pSurface->paMipmapLevels[0].mipmapSize.width, pSurface->paMipmapLevels[0].mipmapSize.height, pSurface->cLevels, pSurface->fUsageD3D, pSurface->formatD3D)); + rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pSurface); + AssertRCReturn(rc, rc); + } + else + { + /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */ + vmsvga3dSurfaceFlush(pSurface); + } + + AssertReturn( pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE + || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE + || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE, + VERR_INVALID_PARAMETER); + + if (pSurface->idAssociatedContext != cid) + { + LogFunc(("Using texture sid=%u created for another context (%d vs %d)\n", sid, pSurface->idAssociatedContext, cid)); + + PVMSVGA3DSHAREDSURFACE pSharedSurface = vmsvga3dSurfaceGetSharedCopy(pState, pContext, pSurface); + AssertReturn(pSharedSurface, VERR_INTERNAL_ERROR); + + hr = pContext->pDevice->SetTexture(d3dSampler, pSharedSurface->u.pTexture); + } + else + hr = pContext->pDevice->SetTexture(d3dSampler, pSurface->u.pTexture); + + AssertMsgReturn(hr == D3D_OK, ("SetTexture failed with %x\n", hr), VERR_INTERNAL_ERROR); + + pContext->aSidActiveTextures[idxSampler] = sid; + } + /* Finished; continue with the next one. */ + continue; + } + + D3DTEXTURESTAGESTATETYPE textureType = D3DTSS_FORCE_DWORD; + D3DSAMPLERSTATETYPE samplerType = D3DSAMP_FORCE_DWORD; + switch (pTextureState[i].name) + { + case SVGA3D_TS_COLOROP: /* SVGA3dTextureCombiner */ + textureType = D3DTSS_COLOROP; + val = vmsvga3dTextureCombiner2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_COLORARG0: /* SVGA3dTextureArgData */ + textureType = D3DTSS_COLORARG0; + val = vmsvga3dTextureArgData2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_COLORARG1: /* SVGA3dTextureArgData */ + textureType = D3DTSS_COLORARG1; + val = vmsvga3dTextureArgData2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_COLORARG2: /* SVGA3dTextureArgData */ + textureType = D3DTSS_COLORARG2; + val = vmsvga3dTextureArgData2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_ALPHAOP: /* SVGA3dTextureCombiner */ + textureType = D3DTSS_ALPHAOP; + val = vmsvga3dTextureCombiner2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_ALPHAARG0: /* SVGA3dTextureArgData */ + textureType = D3DTSS_ALPHAARG0; + val = vmsvga3dTextureArgData2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_ALPHAARG1: /* SVGA3dTextureArgData */ + textureType = D3DTSS_ALPHAARG1; + val = vmsvga3dTextureArgData2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_ALPHAARG2: /* SVGA3dTextureArgData */ + textureType = D3DTSS_ALPHAARG2; + val = vmsvga3dTextureArgData2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_BUMPENVMAT00: /* float */ + textureType = D3DTSS_BUMPENVMAT00; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_BUMPENVMAT01: /* float */ + textureType = D3DTSS_BUMPENVMAT01; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_BUMPENVMAT10: /* float */ + textureType = D3DTSS_BUMPENVMAT10; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_BUMPENVMAT11: /* float */ + textureType = D3DTSS_BUMPENVMAT11; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_TEXCOORDINDEX: /* uint32_t */ + textureType = D3DTSS_TEXCOORDINDEX; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_BUMPENVLSCALE: /* float */ + textureType = D3DTSS_BUMPENVLSCALE; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_BUMPENVLOFFSET: /* float */ + textureType = D3DTSS_BUMPENVLOFFSET; + val = pTextureState[i].value; + break; + + case SVGA3D_TS_TEXTURETRANSFORMFLAGS: /* SVGA3dTexTransformFlags */ + textureType = D3DTSS_TEXTURETRANSFORMFLAGS; + val = vmsvga3dTextTransformFlags2D3D(pTextureState[i].value); + break; + + case SVGA3D_TS_ADDRESSW: /* SVGA3dTextureAddress */ + samplerType = D3DSAMP_ADDRESSW; + val = pTextureState[i].value; /* Identical otherwise */ + Assert(pTextureState[i].value != SVGA3D_TEX_ADDRESS_EDGE); + break; + + case SVGA3D_TS_ADDRESSU: /* SVGA3dTextureAddress */ + samplerType = D3DSAMP_ADDRESSU; + val = pTextureState[i].value; /* Identical otherwise */ + Assert(pTextureState[i].value != SVGA3D_TEX_ADDRESS_EDGE); + break; + + case SVGA3D_TS_ADDRESSV: /* SVGA3dTextureAddress */ + samplerType = D3DSAMP_ADDRESSV; + val = pTextureState[i].value; /* Identical otherwise */ + Assert(pTextureState[i].value != SVGA3D_TEX_ADDRESS_EDGE); + break; + + case SVGA3D_TS_MIPFILTER: /* SVGA3dTextureFilter */ + samplerType = D3DSAMP_MIPFILTER; + val = pTextureState[i].value; /* Identical otherwise */ + Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_FLATCUBIC); + Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_GAUSSIANCUBIC); + break; + + case SVGA3D_TS_MAGFILTER: /* SVGA3dTextureFilter */ + samplerType = D3DSAMP_MAGFILTER; + val = pTextureState[i].value; /* Identical otherwise */ + Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_FLATCUBIC); + Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_GAUSSIANCUBIC); + break; + + case SVGA3D_TS_MINFILTER: /* SVGA3dTextureFilter */ + samplerType = D3DSAMP_MINFILTER; + val = pTextureState[i].value; /* Identical otherwise */ + Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_FLATCUBIC); + Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_GAUSSIANCUBIC); + break; + + case SVGA3D_TS_BORDERCOLOR: /* SVGA3dColor */ + samplerType = D3DSAMP_BORDERCOLOR; + val = pTextureState[i].value; /* Identical */ + break; + + case SVGA3D_TS_TEXTURE_LOD_BIAS: /* float */ + samplerType = D3DSAMP_MIPMAPLODBIAS; + val = pTextureState[i].value; /* Identical */ + break; + + case SVGA3D_TS_TEXTURE_MIPMAP_LEVEL: /* uint32_t */ + samplerType = D3DSAMP_MAXMIPLEVEL; + val = pTextureState[i].value; /* Identical?? */ + break; + + case SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL: /* uint32_t */ + samplerType = D3DSAMP_MAXANISOTROPY; + val = pTextureState[i].value; /* Identical?? */ + break; + + case SVGA3D_TS_GAMMA: /* float */ + samplerType = D3DSAMP_SRGBTEXTURE; + /* Boolean in D3D */ + if (pTextureState[i].floatValue == 1.0f) + val = FALSE; + else + val = TRUE; + break; + + /* Internal commands, that don't map directly to the SetTextureStageState API. */ + case SVGA3D_TS_TEXCOORDGEN: /* SVGA3dTextureCoordGen */ + AssertFailed(); + break; + + case SVGA3D_TS_MAX: /* shut up MSC */ + case SVGA3D_TS_INVALID: + case SVGA3D_TS_BIND_TEXTURE: + AssertFailedBreak(); + default: /** @todo Remaining TSs. Avoid MSC warning for now. */ + break; + } + + const uint32_t currentStage = pTextureState[i].stage; + /* Record the texture state for vm state saving. */ + if ( currentStage < RT_ELEMENTS(pContext->state.aTextureStates) + && (unsigned)pTextureState[i].name < RT_ELEMENTS(pContext->state.aTextureStates[0])) + { + pContext->state.aTextureStates[currentStage][pTextureState[i].name] = pTextureState[i]; + } + + if (textureType != D3DTSS_FORCE_DWORD) + { + if (RT_UNLIKELY(currentStage >= SVGA3D_MAX_TEXTURE_STAGES)) + { + AssertMsgFailed(("pTextureState[%d].stage=%#x name=%#x value=%#x\n", i, pTextureState[i].stage, pTextureState[i].name, pTextureState[i].value)); + continue; + } + + hr = pContext->pDevice->SetTextureStageState(currentStage, textureType, val); + AssertMsg(hr == D3D_OK, ("SetTextureStageState failed with %x\n", hr)); + } + else if (samplerType != D3DSAMP_FORCE_DWORD) + { + if (RT_UNLIKELY(currentStage >= SVGA3D_MAX_SAMPLERS)) + { + AssertMsgFailed(("pTextureState[%d].stage=%#x name=%#x value=%#x\n", i, pTextureState[i].stage, pTextureState[i].name, pTextureState[i].value)); + continue; + } + + hr = pContext->pDevice->SetSamplerState(currentStage, samplerType, val); + AssertMsg(hr == D3D_OK, ("SetSamplerState failed with %x\n", hr)); + } + else + { + AssertFailed(); + } + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial) +{ + HRESULT hr; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("cid=%u face %d\n", cid, face)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + AssertReturn((unsigned)face < SVGA3D_FACE_MAX, VERR_INVALID_PARAMETER); + + /* Save for vm state save/restore. */ + pContext->state.aMaterial[face].fValid = true; + pContext->state.aMaterial[face].material = *pMaterial; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_MATERIAL; + + /* @note face not used for D3D9 */ + /** @todo ignore everything except SVGA3D_FACE_NONE? */ + //Assert(face == SVGA3D_FACE_NONE); + if (face != SVGA3D_FACE_NONE) + Log(("Unsupported face %d!!\n", face)); + + D3DMATERIAL9 material; + material.Diffuse.r = pMaterial->diffuse[0]; + material.Diffuse.g = pMaterial->diffuse[1]; + material.Diffuse.b = pMaterial->diffuse[2]; + material.Diffuse.a = pMaterial->diffuse[3]; + material.Ambient.r = pMaterial->ambient[0]; + material.Ambient.g = pMaterial->ambient[1]; + material.Ambient.b = pMaterial->ambient[2]; + material.Ambient.a = pMaterial->ambient[3]; + material.Specular.r = pMaterial->specular[0]; + material.Specular.g = pMaterial->specular[1]; + material.Specular.b = pMaterial->specular[2]; + material.Specular.a = pMaterial->specular[3]; + material.Emissive.r = pMaterial->emissive[0]; + material.Emissive.g = pMaterial->emissive[1]; + material.Emissive.b = pMaterial->emissive[2]; + material.Emissive.a = pMaterial->emissive[3]; + material.Power = pMaterial->shininess; + + hr = pContext->pDevice->SetMaterial(&material); + AssertMsgReturn(hr == D3D_OK, ("SetMaterial failed with %x\n", hr), VERR_INTERNAL_ERROR); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData) +{ + HRESULT hr; + D3DLIGHT9 light; + PVMSVGA3DCONTEXT pContext; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetLightData %x index=%d\n", cid, index)); + ASSERT_GUEST_RETURN(index < SVGA3D_MAX_LIGHTS, VERR_INVALID_PARAMETER); + + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + switch (pData->type) + { + case SVGA3D_LIGHTTYPE_POINT: + light.Type = D3DLIGHT_POINT; + break; + + case SVGA3D_LIGHTTYPE_SPOT1: /* 1-cone, in degrees */ + light.Type = D3DLIGHT_SPOT; + break; + + case SVGA3D_LIGHTTYPE_DIRECTIONAL: + light.Type = D3DLIGHT_DIRECTIONAL; + break; + + case SVGA3D_LIGHTTYPE_SPOT2: /* 2-cone, in radians */ + default: + Log(("Unsupported light type!!\n")); + return VERR_INVALID_PARAMETER; + } + + /* Store for vm state save/restore */ + pContext->state.aLightData[index].fValidData = true; + pContext->state.aLightData[index].data = *pData; + + light.Diffuse.r = pData->diffuse[0]; + light.Diffuse.g = pData->diffuse[1]; + light.Diffuse.b = pData->diffuse[2]; + light.Diffuse.a = pData->diffuse[3]; + light.Specular.r = pData->specular[0]; + light.Specular.g = pData->specular[1]; + light.Specular.b = pData->specular[2]; + light.Specular.a = pData->specular[3]; + light.Ambient.r = pData->ambient[0]; + light.Ambient.g = pData->ambient[1]; + light.Ambient.b = pData->ambient[2]; + light.Ambient.a = pData->ambient[3]; + light.Position.x = pData->position[0]; + light.Position.y = pData->position[1]; + light.Position.z = pData->position[2]; /* @note 4th position not available in D3D9 */ + light.Direction.x = pData->direction[0]; + light.Direction.y = pData->direction[1]; + light.Direction.z = pData->direction[2]; /* @note 4th position not available in D3D9 */ + light.Range = pData->range; + light.Falloff = pData->falloff; + light.Attenuation0 = pData->attenuation0; + light.Attenuation1 = pData->attenuation1; + light.Attenuation2 = pData->attenuation2; + light.Theta = pData->theta; + light.Phi = pData->phi; + + hr = pContext->pDevice->SetLight(index, &light); + AssertMsgReturn(hr == D3D_OK, ("SetLight failed with %x\n", hr), VERR_INTERNAL_ERROR); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled) +{ + HRESULT hr; + PVMSVGA3DCONTEXT pContext; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetLightEnabled %x %d -> %d\n", cid, index, enabled)); + AssertReturn(index < SVGA3D_MAX_LIGHTS, VERR_INVALID_PARAMETER); + + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + /* Store for vm state save/restore */ + pContext->state.aLightData[index].fEnabled = !!enabled; + + hr = pContext->pDevice->LightEnable(index, (BOOL)enabled); + AssertMsgReturn(hr == D3D_OK, ("LightEnable failed with %x\n", hr), VERR_INTERNAL_ERROR); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) +{ + HRESULT hr; + D3DVIEWPORT9 viewPort; + PVMSVGA3DCONTEXT pContext; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetViewPort %x (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h)); + + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + /* Save for vm state save/restore. */ + pContext->state.RectViewPort = *pRect; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VIEWPORT; + + hr = pContext->pDevice->GetViewport(&viewPort); + AssertMsgReturn(hr == D3D_OK, ("GetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR); + + viewPort.X = pRect->x; + viewPort.Y = pRect->y; + viewPort.Width = pRect->w; + viewPort.Height = pRect->h; + /* viewPort.MinZ & MaxZ are not changed from the current setting. */ + + hr = pContext->pDevice->SetViewport(&viewPort); + AssertMsgReturn(hr == D3D_OK, ("SetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]) +{ + HRESULT hr; + PVMSVGA3DCONTEXT pContext; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetClipPlane %x %d (%d,%d)(%d,%d)\n", cid, index, (unsigned)(plane[0] * 100.0), (unsigned)(plane[1] * 100.0), (unsigned)(plane[2] * 100.0), (unsigned)(plane[3] * 100.0))); + AssertReturn(index < SVGA3D_NUM_CLIPPLANES, VERR_INVALID_PARAMETER); + + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + /* Store for vm state save/restore. */ + pContext->state.aClipPlane[index].fValid = true; + memcpy(pContext->state.aClipPlane[index].plane, plane, sizeof(pContext->state.aClipPlane[index].plane)); + + hr = pContext->pDevice->SetClipPlane(index, plane); + AssertMsgReturn(hr == D3D_OK, ("SetClipPlane failed with %x\n", hr), VERR_INTERNAL_ERROR); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, + uint32_t stencil, uint32_t cRects, SVGA3dRect *pRect) +{ + /* From SVGA3D_BeginClear comments: + * + * Clear is not affected by clipping, depth test, or other + * render state which affects the fragment pipeline. + * + * Therefore this code must ignore the current scissor rect. + */ + + DWORD clearFlagD3D = 0; + D3DRECT *pRectD3D = NULL; + HRESULT hr; + PVMSVGA3DCONTEXT pContext; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dCommandClear %x clearFlag=%x color=%x depth=%d stencil=%x cRects=%d\n", cid, clearFlag, color, (uint32_t)(depth * 100.0), stencil, cRects)); + + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + PVMSVGA3DSURFACE pRT; + rc = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pRT); + AssertRCReturn(rc, rc); + + if (clearFlag & SVGA3D_CLEAR_COLOR) + clearFlagD3D |= D3DCLEAR_TARGET; + if (clearFlag & SVGA3D_CLEAR_STENCIL) + clearFlagD3D |= D3DCLEAR_STENCIL; + if (clearFlag & SVGA3D_CLEAR_DEPTH) + clearFlagD3D |= D3DCLEAR_ZBUFFER; + + if (cRects) + { + pRectD3D = (D3DRECT *)RTMemAlloc(sizeof(D3DRECT) * cRects); + AssertReturn(pRectD3D, VERR_NO_MEMORY); + + for (unsigned i=0; i < cRects; i++) + { + Log(("vmsvga3dCommandClear: rect %d (%d,%d)(%d,%d)\n", i, pRect[i].x, pRect[i].y, pRect[i].x + pRect[i].w, pRect[i].y + pRect[i].h)); + pRectD3D[i].x1 = pRect[i].x; + pRectD3D[i].y1 = pRect[i].y; + pRectD3D[i].x2 = pRect[i].x + pRect[i].w; /* exclusive */ + pRectD3D[i].y2 = pRect[i].y + pRect[i].h; /* exclusive */ + } + } + + RECT currentScissorRect; + pContext->pDevice->GetScissorRect(¤tScissorRect); + + RECT clearScissorRect; + clearScissorRect.left = 0; + clearScissorRect.top = 0; + clearScissorRect.right = pRT->paMipmapLevels[0].mipmapSize.width; + clearScissorRect.bottom = pRT->paMipmapLevels[0].mipmapSize.height; + pContext->pDevice->SetScissorRect(&clearScissorRect); + + hr = pContext->pDevice->Clear(cRects, pRectD3D, clearFlagD3D, (D3DCOLOR)color, depth, stencil); + + if (pRectD3D) + RTMemFree(pRectD3D); + + pContext->pDevice->SetScissorRect(¤tScissorRect); + + AssertMsgReturn(hr == D3D_OK, ("Clear failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* Make sure we can track drawing usage of active render targets. */ + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); ++i) + if (pContext->state.aRenderTargets[i] != SVGA3D_INVALID_ID) + vmsvga3dSurfaceTrackUsageById(pState, pContext, pContext->state.aRenderTargets[i]); + + return VINF_SUCCESS; +} + +/* Convert VMWare vertex declaration to its D3D equivalent. */ +static int vmsvga3dVertexDecl2D3D(const SVGA3dVertexArrayIdentity &identity, D3DVERTEXELEMENT9 *pVertexElement) +{ + /* usage, method and type are identical; make sure. */ + AssertCompile(SVGA3D_DECLTYPE_FLOAT1 == D3DDECLTYPE_FLOAT1); + AssertCompile(SVGA3D_DECLTYPE_FLOAT16_4 == D3DDECLTYPE_FLOAT16_4); + AssertCompile(SVGA3D_DECLMETHOD_DEFAULT == D3DDECLMETHOD_DEFAULT); + AssertCompile(SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED == D3DDECLMETHOD_LOOKUPPRESAMPLED); + AssertCompile(D3DDECLUSAGE_POSITION == SVGA3D_DECLUSAGE_POSITION); + AssertCompile(D3DDECLUSAGE_SAMPLE == SVGA3D_DECLUSAGE_SAMPLE); + + pVertexElement->Stream = 0; + pVertexElement->Offset = 0; + pVertexElement->Type = identity.type; + pVertexElement->Method = identity.method; + pVertexElement->Usage = identity.usage; + pVertexElement->UsageIndex = identity.usageIndex; + return VINF_SUCCESS; +} + +/* Convert VMWare primitive type to its D3D equivalent. */ +static int vmsvga3dPrimitiveType2D3D(SVGA3dPrimitiveType PrimitiveType, D3DPRIMITIVETYPE *pPrimitiveTypeD3D) +{ + switch (PrimitiveType) + { + case SVGA3D_PRIMITIVE_TRIANGLELIST: + *pPrimitiveTypeD3D = D3DPT_TRIANGLELIST; + break; + case SVGA3D_PRIMITIVE_POINTLIST: + *pPrimitiveTypeD3D = D3DPT_POINTLIST; + break; + case SVGA3D_PRIMITIVE_LINELIST: + *pPrimitiveTypeD3D = D3DPT_LINELIST; + break; + case SVGA3D_PRIMITIVE_LINESTRIP: + *pPrimitiveTypeD3D = D3DPT_LINESTRIP; + break; + case SVGA3D_PRIMITIVE_TRIANGLESTRIP: + *pPrimitiveTypeD3D = D3DPT_TRIANGLESTRIP; + break; + case SVGA3D_PRIMITIVE_TRIANGLEFAN: + *pPrimitiveTypeD3D = D3DPT_TRIANGLEFAN; + break; + default: + return VERR_INVALID_PARAMETER; + } + return VINF_SUCCESS; +} + + +static int vmsvga3dDrawPrimitivesSyncVertexBuffer(PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pVertexSurface) +{ + HRESULT hr; + if ( pVertexSurface->u.pSurface + && pVertexSurface->enmD3DResType != VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER) + { + /* The buffer object is not an vertex one. Recreate the D3D resource. */ + AssertReturn(pVertexSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_INDEX_BUFFER, VERR_INVALID_PARAMETER); + D3D_RELEASE(pVertexSurface->u.pIndexBuffer); + pVertexSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_NONE; + + LogFunc(("index -> vertex buffer sid=%u\n", pVertexSurface->id)); + } + + bool fSync = pVertexSurface->fDirty; + if (!pVertexSurface->u.pVertexBuffer) + { + LogFunc(("Create vertex buffer sid=%u fDirty=%d\n", pVertexSurface->id, pVertexSurface->fDirty)); + + const DWORD Usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY; /* possible severe performance penalty otherwise (according to d3d debug output */ + hr = pContext->pDevice->CreateVertexBuffer(pVertexSurface->paMipmapLevels[0].cbSurface, + Usage, + 0, /* non-FVF */ + D3DPOOL_DEFAULT, + &pVertexSurface->u.pVertexBuffer, + NULL); + AssertMsgReturn(hr == D3D_OK, ("CreateVertexBuffer failed with %x\n", hr), VERR_INTERNAL_ERROR); + + pVertexSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER; + pVertexSurface->idAssociatedContext = pContext->id; + pVertexSurface->f.surfaceFlags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER; + fSync = true; + } + + if (fSync) + { + LogFunc(("sync vertex buffer\n")); + Assert(pVertexSurface->u.pVertexBuffer); + + void *pvData; + hr = pVertexSurface->u.pVertexBuffer->Lock(0, 0, &pvData, D3DLOCK_DISCARD); + AssertMsgReturn(hr == D3D_OK, ("Lock vertex failed with %x\n", hr), VERR_INTERNAL_ERROR); + + memcpy(pvData, pVertexSurface->paMipmapLevels[0].pSurfaceData, pVertexSurface->paMipmapLevels[0].cbSurface); + + hr = pVertexSurface->u.pVertexBuffer->Unlock(); + AssertMsgReturn(hr == D3D_OK, ("Unlock vertex failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + + return VINF_SUCCESS; +} + + +static int vmsvga3dDrawPrimitivesSyncIndexBuffer(PVMSVGA3DCONTEXT pContext, + PVMSVGA3DSURFACE pIndexSurface, + uint32_t indexWidth) +{ + HRESULT hr; + if ( pIndexSurface->u.pSurface + && pIndexSurface->enmD3DResType != VMSVGA3D_D3DRESTYPE_INDEX_BUFFER) + { + /* The buffer object is not an index one. Must recreate the D3D resource. */ + AssertReturn(pIndexSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER, VERR_INVALID_PARAMETER); + D3D_RELEASE(pIndexSurface->u.pVertexBuffer); + pIndexSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_NONE; + + LogFunc(("vertex -> index buffer sid=%u\n", pIndexSurface->id)); + } + + bool fSync = pIndexSurface->fDirty; + if (!pIndexSurface->u.pIndexBuffer) + { + LogFunc(("Create index buffer fDirty=%d\n", pIndexSurface->fDirty)); + + const DWORD Usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY; /* possible severe performance penalty otherwise (according to d3d debug output */ + const D3DFORMAT Format = (indexWidth == sizeof(uint16_t)) ? D3DFMT_INDEX16 : D3DFMT_INDEX32; + hr = pContext->pDevice->CreateIndexBuffer(pIndexSurface->paMipmapLevels[0].cbSurface, + Usage, + Format, + D3DPOOL_DEFAULT, + &pIndexSurface->u.pIndexBuffer, + NULL); + AssertMsgReturn(hr == D3D_OK, ("CreateIndexBuffer failed with %x\n", hr), VERR_INTERNAL_ERROR); + + pIndexSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_INDEX_BUFFER; + pIndexSurface->idAssociatedContext = pContext->id; + pIndexSurface->f.surfaceFlags |= SVGA3D_SURFACE_HINT_INDEXBUFFER; + fSync = true; + } + + if (fSync) + { + LogFunc(("sync index buffer\n")); + Assert(pIndexSurface->u.pIndexBuffer); + + void *pvData; + hr = pIndexSurface->u.pIndexBuffer->Lock(0, 0, &pvData, D3DLOCK_DISCARD); + AssertMsgReturn(hr == D3D_OK, ("Lock index failed with %x\n", hr), VERR_INTERNAL_ERROR); + + memcpy(pvData, pIndexSurface->paMipmapLevels[0].pSurfaceData, pIndexSurface->paMipmapLevels[0].cbSurface); + + hr = pIndexSurface->u.pIndexBuffer->Unlock(); + AssertMsgReturn(hr == D3D_OK, ("Unlock index failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + + return VINF_SUCCESS; +} + +static int vmsvga3dDrawPrimitivesProcessVertexDecls(const uint32_t numVertexDecls, + const SVGA3dVertexDecl *pVertexDecl, + const uint32_t idStream, + const uint32_t uVertexMinOffset, + const uint32_t uVertexMaxOffset, + D3DVERTEXELEMENT9 *pVertexElement) +{ + RT_NOREF(uVertexMaxOffset); /* Logging only. */ + Assert(numVertexDecls); + + /* Create a vertex declaration array */ + for (uint32_t iVertex = 0; iVertex < numVertexDecls; ++iVertex) + { + LogFunc(("vertex %d type=%s (%d) method=%s (%d) usage=%s (%d) usageIndex=%d stride=%d offset=%d (%d min=%d max=%d)\n", + iVertex, + vmsvgaDeclType2String(pVertexDecl[iVertex].identity.type), pVertexDecl[iVertex].identity.type, + vmsvgaDeclMethod2String(pVertexDecl[iVertex].identity.method), pVertexDecl[iVertex].identity.method, + vmsvgaDeclUsage2String(pVertexDecl[iVertex].identity.usage), pVertexDecl[iVertex].identity.usage, + pVertexDecl[iVertex].identity.usageIndex, + pVertexDecl[iVertex].array.stride, + pVertexDecl[iVertex].array.offset - uVertexMinOffset, + pVertexDecl[iVertex].array.offset, + uVertexMinOffset, uVertexMaxOffset)); + + int rc = vmsvga3dVertexDecl2D3D(pVertexDecl[iVertex].identity, &pVertexElement[iVertex]); + AssertRCReturn(rc, rc); + + pVertexElement[iVertex].Stream = idStream; + pVertexElement[iVertex].Offset = pVertexDecl[iVertex].array.offset - uVertexMinOffset; + +#ifdef LOG_ENABLED + if (pVertexDecl[iVertex].array.stride == 0) + LogFunc(("stride == 0! Can be valid\n")); + + if (pVertexElement[iVertex].Offset >= pVertexDecl[0].array.stride) + LogFunc(("WARNING: offset > stride!!\n")); +#endif + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, + uint32_t numRanges, SVGA3dPrimitiveRange *pRange, + uint32_t cVertexDivisor, SVGA3dVertexDivisor *pVertexDivisor) +{ + static const D3DVERTEXELEMENT9 sVertexEnd = D3DDECL_END(); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INTERNAL_ERROR); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + HRESULT hr; + + /* SVGA driver may use the same surface for both index and vertex data. So we can not clear fDirty flag, + * after updating a vertex buffer for example, because the same surface might be used for index buffer later. + * So keep pointers to all used surfaces in the following two arrays and clear fDirty flag at the end. + */ + PVMSVGA3DSURFACE aVertexSurfaces[SVGA3D_MAX_VERTEX_ARRAYS]; + PVMSVGA3DSURFACE aIndexSurfaces[SVGA3D_MAX_DRAW_PRIMITIVE_RANGES]; + RT_ZERO(aVertexSurfaces); + RT_ZERO(aIndexSurfaces); + + LogFunc(("cid=%u numVertexDecls=%d numRanges=%d, cVertexDivisor=%d\n", cid, numVertexDecls, numRanges, cVertexDivisor)); + + AssertReturn(numVertexDecls && numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS, VERR_INVALID_PARAMETER); + AssertReturn(numRanges && numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES, VERR_INVALID_PARAMETER); + AssertReturn(!cVertexDivisor || cVertexDivisor == numVertexDecls, VERR_INVALID_PARAMETER); + +#if 0 + /* Dump render target to a bitmap. */ + if (pContext->state.aRenderTargets[SVGA3D_RT_COLOR0] != SVGA3D_INVALID_ID) + { + vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0]); + PVMSVGA3DSURFACE pSurface; + int rc2 = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pSurface); + if (RT_SUCCESS(rc2)) + vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpd3d", "rt", "-pre"); + } + for (int iTex = 0; iTex < SVGA3D_MAX_SAMPLERS_PS; ++iTex) + { + IDirect3DBaseTexture9 *pBaseTexture = 0; + hr = pContext->pDevice->GetTexture(iTex, &pBaseTexture); + if (hr == S_OK && pBaseTexture) + { + D3DSURFACE_DESC surfDesc; + RT_ZERO(surfDesc); + + IDirect3DTexture9 *pTexture = (IDirect3DTexture9 *)pBaseTexture; + pTexture->GetLevelDesc(0, &surfDesc); + + Log(("Texture[%d]: %dx%d\n", + iTex, surfDesc.Width, surfDesc.Height)); + D3D_RELEASE(pBaseTexture); + } + } +#endif + + /* + * Process all vertex declarations. Each vertex buffer surface is represented by one stream source id. + */ + D3DVERTEXELEMENT9 aVertexElements[SVGA3D_MAX_VERTEX_ARRAYS + 1]; + + uint32_t iCurrentVertex = 0; + uint32_t iCurrentStreamId = 0; + while (iCurrentVertex < numVertexDecls) + { + const uint32_t sidVertex = pVertexDecl[iCurrentVertex].array.surfaceId; + const uint32_t strideVertex = pVertexDecl[iCurrentVertex].array.stride; + + PVMSVGA3DSURFACE pVertexSurface; + rc = vmsvga3dSurfaceFromSid(pState, sidVertex, &pVertexSurface); + AssertRCBreak(rc); + + rc = vmsvga3dDrawPrimitivesSyncVertexBuffer(pContext, pVertexSurface); + AssertRCBreak(rc); + + uint32_t uVertexMinOffset = UINT32_MAX; + uint32_t uVertexMaxOffset = 0; + + uint32_t iVertex; + for (iVertex = iCurrentVertex; iVertex < numVertexDecls; ++iVertex) + { + /* Remember, so we can mark it as not dirty later. */ + aVertexSurfaces[iVertex] = pVertexSurface; + + /* New surface id -> new stream id. */ + if (pVertexDecl[iVertex].array.surfaceId != sidVertex) + break; + + const uint32_t uVertexOffset = pVertexDecl[iVertex].array.offset; + const uint32_t uNewVertexMinOffset = RT_MIN(uVertexMinOffset, uVertexOffset); + const uint32_t uNewVertexMaxOffset = RT_MAX(uVertexMaxOffset, uVertexOffset); + + /* We must put vertex declarations that start at a different element in another stream as d3d only handles offsets < stride. */ + if ( uNewVertexMaxOffset - uNewVertexMinOffset >= strideVertex + && strideVertex != 0) + break; + + uVertexMinOffset = uNewVertexMinOffset; + uVertexMaxOffset = uNewVertexMaxOffset; + } + + rc = vmsvga3dDrawPrimitivesProcessVertexDecls(iVertex - iCurrentVertex, + &pVertexDecl[iCurrentVertex], + iCurrentStreamId, + uVertexMinOffset, + uVertexMaxOffset, + &aVertexElements[iCurrentVertex]); + AssertRCBreak(rc); + + LogFunc(("SetStreamSource vertex sid=%u stream %d min offset=%d stride=%d\n", + pVertexSurface->id, iCurrentStreamId, uVertexMinOffset, strideVertex)); + + hr = pContext->pDevice->SetStreamSource(iCurrentStreamId, + pVertexSurface->u.pVertexBuffer, + uVertexMinOffset, + strideVertex); + AssertMsgBreakStmt(hr == D3D_OK, ("SetStreamSource failed with %x\n", hr), rc = VERR_INTERNAL_ERROR); + + if (cVertexDivisor) + { + LogFunc(("SetStreamSourceFreq[%d]=%x\n", iCurrentStreamId, pVertexDivisor[iCurrentVertex].value)); + HRESULT hr2 = pContext->pDevice->SetStreamSourceFreq(iCurrentStreamId, + pVertexDivisor[iCurrentVertex].value); + Assert(SUCCEEDED(hr2)); RT_NOREF(hr2); + } + + iCurrentVertex = iVertex; + ++iCurrentStreamId; + } + + /* iCurrentStreamId is equal to the total number of streams and the value is used for cleanup at the function end. */ + + AssertRCReturn(rc, rc); + + /* Mark the end. */ + memcpy(&aVertexElements[numVertexDecls], &sVertexEnd, sizeof(sVertexEnd)); + + /* Check if this context already has the same vertex declaration. */ + if ( pContext->d3dState.pVertexDecl + && pContext->d3dState.cVertexElements == numVertexDecls + 1 + && memcmp(pContext->d3dState.aVertexElements, + aVertexElements, + pContext->d3dState.cVertexElements * sizeof(aVertexElements[0])) == 0) + { + /* Same. */ + } + else + { + /* Create and set the vertex declaration. */ + IDirect3DVertexDeclaration9 *pVertexDecl0; + hr = pContext->pDevice->CreateVertexDeclaration(&aVertexElements[0], &pVertexDecl0); + AssertMsgReturn(hr == D3D_OK, ("CreateVertexDeclaration failed with %x\n", hr), VERR_INTERNAL_ERROR); + + hr = pContext->pDevice->SetVertexDeclaration(pVertexDecl0); + AssertMsgReturnStmt(hr == D3D_OK, ("SetVertexDeclaration failed with %x\n", hr), + D3D_RELEASE(pVertexDecl0), + VERR_INTERNAL_ERROR); + + /* The new vertex declaration has been successfully set. Delete the old one. */ + D3D_RELEASE(pContext->d3dState.pVertexDecl); + + /* Remember the new vertext declaration. */ + pContext->d3dState.pVertexDecl = pVertexDecl0; + pContext->d3dState.cVertexElements = numVertexDecls + 1; + memcpy(pContext->d3dState.aVertexElements, + aVertexElements, + pContext->d3dState.cVertexElements * sizeof(aVertexElements[0])); + } + + /* Begin a scene before rendering anything. */ + hr = pContext->pDevice->BeginScene(); + AssertMsgReturn(hr == D3D_OK, ("BeginScene failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* Now draw the primitives. */ + for (uint32_t iPrimitive = 0; iPrimitive < numRanges; ++iPrimitive) + { + Log(("Primitive %d: type %s\n", iPrimitive, vmsvga3dPrimitiveType2String(pRange[iPrimitive].primType))); + + const uint32_t sidIndex = pRange[iPrimitive].indexArray.surfaceId; + PVMSVGA3DSURFACE pIndexSurface = NULL; + + D3DPRIMITIVETYPE PrimitiveTypeD3D; + rc = vmsvga3dPrimitiveType2D3D(pRange[iPrimitive].primType, &PrimitiveTypeD3D); + AssertRCBreak(rc); + + /* Triangle strips or fans with just one primitive don't make much sense and are identical to triangle lists. + * Workaround for NVidia driver crash when encountering some of these. + */ + if ( pRange[iPrimitive].primitiveCount == 1 + && ( PrimitiveTypeD3D == D3DPT_TRIANGLESTRIP + || PrimitiveTypeD3D == D3DPT_TRIANGLEFAN)) + PrimitiveTypeD3D = D3DPT_TRIANGLELIST; + + if (sidIndex != SVGA3D_INVALID_ID) + { + AssertMsg(pRange[iPrimitive].indexWidth == sizeof(uint32_t) || pRange[iPrimitive].indexWidth == sizeof(uint16_t), + ("Unsupported primitive width %d\n", pRange[iPrimitive].indexWidth)); + + rc = vmsvga3dSurfaceFromSid(pState, sidIndex, &pIndexSurface); + AssertRCBreak(rc); + + aIndexSurfaces[iPrimitive] = pIndexSurface; + + Log(("vmsvga3dDrawPrimitives: index sid=%u\n", sidIndex)); + + rc = vmsvga3dDrawPrimitivesSyncIndexBuffer(pContext, pIndexSurface, pRange[iPrimitive].indexWidth); + AssertRCBreak(rc); + + hr = pContext->pDevice->SetIndices(pIndexSurface->u.pIndexBuffer); + AssertMsg(hr == D3D_OK, ("SetIndices vertex failed with %x\n", hr)); + } + else + { + hr = pContext->pDevice->SetIndices(NULL); + AssertMsg(hr == D3D_OK, ("SetIndices vertex (NULL) failed with %x\n", hr)); + } + + const uint32_t strideVertex = pVertexDecl[0].array.stride; + + if (!pIndexSurface) + { + /* Render without an index buffer */ + Log(("DrawPrimitive %x primitivecount=%d index index bias=%d stride=%d\n", + PrimitiveTypeD3D, pRange[iPrimitive].primitiveCount, pRange[iPrimitive].indexBias, strideVertex)); + + hr = pContext->pDevice->DrawPrimitive(PrimitiveTypeD3D, + pRange[iPrimitive].indexBias, + pRange[iPrimitive].primitiveCount); + AssertMsgBreakStmt(hr == D3D_OK, ("DrawPrimitive failed with %x\n", hr), rc = VERR_INTERNAL_ERROR); + } + else + { + UINT numVertices; + if (pVertexDecl[0].rangeHint.last) + { + /* Both SVGA3dArrayRangeHint definition and the SVGA driver code imply that 'last' is exclusive, + * hence compute the difference. + */ + numVertices = pVertexDecl[0].rangeHint.last - pVertexDecl[0].rangeHint.first; + } + else + { + /* Range hint is not provided. */ + PVMSVGA3DSURFACE pVertexSurface = aVertexSurfaces[0]; + numVertices = pVertexSurface->paMipmapLevels[0].cbSurface / strideVertex + - pVertexDecl[0].array.offset / strideVertex + - pVertexDecl[0].rangeHint.first + - pRange[iPrimitive].indexBias; + } + + /* Render with an index buffer */ + Log(("DrawIndexedPrimitive %x startindex=%d (indexArray.offset 0x%x) range [%d:%d) numVertices=%d, primitivecount=%d index format=%s index bias=%d stride=%d\n", + PrimitiveTypeD3D, pRange[iPrimitive].indexArray.offset / pRange[iPrimitive].indexWidth, pRange[iPrimitive].indexArray.offset, + pVertexDecl[0].rangeHint.first, pVertexDecl[0].rangeHint.last, numVertices, pRange[iPrimitive].primitiveCount, + (pRange[iPrimitive].indexWidth == sizeof(uint16_t)) ? "D3DFMT_INDEX16" : "D3DFMT_INDEX32", + pRange[iPrimitive].indexBias, strideVertex)); + + hr = pContext->pDevice->DrawIndexedPrimitive(PrimitiveTypeD3D, + pRange[iPrimitive].indexBias, /* BaseVertexIndex */ + 0, /* MinVertexIndex */ + numVertices, + pRange[iPrimitive].indexArray.offset / pRange[iPrimitive].indexWidth, /* StartIndex */ + pRange[iPrimitive].primitiveCount); + AssertMsgBreakStmt(hr == D3D_OK, ("DrawIndexedPrimitive failed with %x\n", hr), rc = VERR_INTERNAL_ERROR); + } + } + + /* End the scene and do some cleanup regardless of the rc. */ + hr = pContext->pDevice->EndScene(); + AssertMsgReturn(hr == D3D_OK, ("EndScene failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* Cleanup. */ + uint32_t i; + /* Clear all streams, because they are set at the beginning of this function anyway. + * Now the vertex buffers can be safely deleted/recreated if necessary. + */ + for (i = 0; i < iCurrentStreamId; ++i) + { + LogFunc(("clear stream %d\n", i)); + HRESULT hr2 = pContext->pDevice->SetStreamSource(i, NULL, 0, 0); + AssertMsg(hr2 == D3D_OK, ("SetStreamSource(%d, NULL) failed with %x\n", i, hr2)); RT_NOREF(hr2); + } + + if (cVertexDivisor) + { + /* "When you are finished rendering the instance data, be sure to reset the vertex stream frequency back..." */ + for (i = 0; i < iCurrentStreamId; ++i) + { + LogFunc(("reset stream freq %d\n", i)); + HRESULT hr2 = pContext->pDevice->SetStreamSourceFreq(i, 1); + AssertMsg(hr2 == D3D_OK, ("SetStreamSourceFreq(%d, 1) failed with %x\n", i, hr2)); RT_NOREF(hr2); + } + } + + if (RT_SUCCESS(rc)) + { + for (i = 0; i < numVertexDecls; ++i) + { + if (aVertexSurfaces[i]) + { + aVertexSurfaces[i]->paMipmapLevels[0].fDirty = false; + aVertexSurfaces[i]->fDirty = false; + } + } + + for (i = 0; i < numRanges; ++i) + { + if (aIndexSurfaces[i]) + { + aIndexSurfaces[i]->paMipmapLevels[0].fDirty = false; + aIndexSurfaces[i]->fDirty = false; + } + } + + /* Make sure we can track drawing usage of active render targets and textures. */ + vmsvga3dContextTrackUsage(pThisCC, pContext); + } + +#if 0 + /* Dump render target to a bitmap. */ + if (pContext->state.aRenderTargets[SVGA3D_RT_COLOR0] != SVGA3D_INVALID_ID) + { + vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0]); + PVMSVGA3DSURFACE pSurface; + int rc2 = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pSurface); + if (RT_SUCCESS(rc2)) + vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpd3d", "rt", "-post"); +# if 0 + for (i = 0; i < SVGA3D_MAX_SAMPLERS_PS; ++i) + { + if (pContext->aSidActiveTextures[i] != SVGA3D_INVALID_ID) + { + char szSuffix[32]; + RTStrPrintf2(szSuffix, sizeof(szSuffix), "-tx%d", i); + vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->aSidActiveTextures[i]); + rc2 = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[i], &pSurface); + if (RT_SUCCESS(rc2)) + vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpd3d", "rt", szSuffix); + } + } +# endif + } +#endif + + return rc; +} + + +static DECLCALLBACK(int) vmsvga3dBackSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) +{ + HRESULT hr; + RECT rect; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dSetScissorRect %x (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + /* Store for vm state save/restore. */ + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_SCISSORRECT; + pContext->state.RectScissor = *pRect; + + rect.left = pRect->x; + rect.top = pRect->y; + rect.right = rect.left + pRect->w; /* exclusive */ + rect.bottom = rect.top + pRect->h; /* exclusive */ + + hr = pContext->pDevice->SetScissorRect(&rect); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetScissorRect: SetScissorRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, + uint32_t cbData, uint32_t *pShaderData) +{ + HRESULT hr; + PVMSVGA3DSHADER pShader; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dShaderDefine %x shid=%d type=%s cbData=%d\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", cbData)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + AssertReturn(shid < SVGA3D_MAX_SHADER_IDS, VERR_INVALID_PARAMETER); + + rc = vmsvga3dShaderParse(type, cbData, pShaderData); + if (RT_FAILURE(rc)) + { + AssertRC(rc); + vmsvga3dShaderLogRel("Failed to parse", type, cbData, pShaderData); + return rc; + } + + if (type == SVGA3D_SHADERTYPE_VS) + { + if (shid >= pContext->cVertexShaders) + { + void *pvNew = RTMemRealloc(pContext->paVertexShader, sizeof(VMSVGA3DSHADER) * (shid + 1)); + AssertReturn(pvNew, VERR_NO_MEMORY); + pContext->paVertexShader = (PVMSVGA3DSHADER)pvNew; + memset(&pContext->paVertexShader[pContext->cVertexShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cVertexShaders)); + for (uint32_t i = pContext->cVertexShaders; i < shid + 1; i++) + pContext->paVertexShader[i].id = SVGA3D_INVALID_ID; + pContext->cVertexShaders = shid + 1; + } + /* If one already exists with this id, then destroy it now. */ + if (pContext->paVertexShader[shid].id != SVGA3D_INVALID_ID) + vmsvga3dBackShaderDestroy(pThisCC, cid, shid, pContext->paVertexShader[shid].type); + + pShader = &pContext->paVertexShader[shid]; + } + else + { + Assert(type == SVGA3D_SHADERTYPE_PS); + if (shid >= pContext->cPixelShaders) + { + void *pvNew = RTMemRealloc(pContext->paPixelShader, sizeof(VMSVGA3DSHADER) * (shid + 1)); + AssertReturn(pvNew, VERR_NO_MEMORY); + pContext->paPixelShader = (PVMSVGA3DSHADER)pvNew; + memset(&pContext->paPixelShader[pContext->cPixelShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cPixelShaders)); + for (uint32_t i = pContext->cPixelShaders; i < shid + 1; i++) + pContext->paPixelShader[i].id = SVGA3D_INVALID_ID; + pContext->cPixelShaders = shid + 1; + } + /* If one already exists with this id, then destroy it now. */ + if (pContext->paPixelShader[shid].id != SVGA3D_INVALID_ID) + vmsvga3dBackShaderDestroy(pThisCC, cid, shid, pContext->paPixelShader[shid].type); + + pShader = &pContext->paPixelShader[shid]; + } + + memset(pShader, 0, sizeof(*pShader)); + pShader->id = shid; + pShader->cid = cid; + pShader->type = type; + pShader->cbData = cbData; + pShader->pShaderProgram = RTMemAllocZ(cbData); + AssertReturn(pShader->pShaderProgram, VERR_NO_MEMORY); + memcpy(pShader->pShaderProgram, pShaderData, cbData); + +#ifdef DUMP_SHADER_DISASSEMBLY + LPD3DXBUFFER pDisassembly; + hr = D3DXDisassembleShader((const DWORD *)pShaderData, FALSE, NULL, &pDisassembly); + if (hr == D3D_OK) + { + Log(("Shader disassembly:\n%s\n", pDisassembly->GetBufferPointer())); + D3D_RELEASE(pDisassembly); + } +#endif + + switch (type) + { + case SVGA3D_SHADERTYPE_VS: + hr = pContext->pDevice->CreateVertexShader((const DWORD *)pShaderData, &pShader->u.pVertexShader); + break; + + case SVGA3D_SHADERTYPE_PS: + hr = pContext->pDevice->CreatePixelShader((const DWORD *)pShaderData, &pShader->u.pPixelShader); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + if (hr != D3D_OK) + { + /* Dump the shader code. */ + vmsvga3dShaderLogRel("Failed to create", type, cbData, pShaderData); + + RTMemFree(pShader->pShaderProgram); + memset(pShader, 0, sizeof(*pShader)); + pShader->id = SVGA3D_INVALID_ID; + } + + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderDefine: CreateVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + PVMSVGA3DSHADER pShader = NULL; + + Log(("vmsvga3dShaderDestroy %x shid=%d type=%s\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL")); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + if (type == SVGA3D_SHADERTYPE_VS) + { + if ( shid < pContext->cVertexShaders + && pContext->paVertexShader[shid].id == shid) + { + pShader = &pContext->paVertexShader[shid]; + D3D_RELEASE(pShader->u.pVertexShader); + } + } + else + { + Assert(type == SVGA3D_SHADERTYPE_PS); + if ( shid < pContext->cPixelShaders + && pContext->paPixelShader[shid].id == shid) + { + pShader = &pContext->paPixelShader[shid]; + D3D_RELEASE(pShader->u.pPixelShader); + } + } + + if (pShader) + { + if (pShader->pShaderProgram) + RTMemFree(pShader->pShaderProgram); + + memset(pShader, 0, sizeof(*pShader)); + pShader->id = SVGA3D_INVALID_ID; + } + else + AssertFailedReturn(VERR_INVALID_PARAMETER); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackShaderSet(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + HRESULT hr; + + Log(("vmsvga3dShaderSet %x type=%s shid=%d\n", cid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", shid)); + + NOREF(pContext); + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + if (type == SVGA3D_SHADERTYPE_VS) + { + /* Save for vm state save/restore. */ + pContext->state.shidVertex = shid; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VERTEXSHADER; + + if ( shid < pContext->cVertexShaders + && pContext->paVertexShader[shid].id == shid) + { + PVMSVGA3DSHADER pShader = &pContext->paVertexShader[shid]; + Assert(type == pShader->type); + + hr = pContext->pDevice->SetVertexShader(pShader->u.pVertexShader); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSet: SetVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else + if (shid == SVGA_ID_INVALID) + { + /* Unselect shader. */ + hr = pContext->pDevice->SetVertexShader(NULL); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSet: SetVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + else + { + /* Save for vm state save/restore. */ + pContext->state.shidPixel = shid; + pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_PIXELSHADER; + + Assert(type == SVGA3D_SHADERTYPE_PS); + if ( shid < pContext->cPixelShaders + && pContext->paPixelShader[shid].id == shid) + { + PVMSVGA3DSHADER pShader = &pContext->paPixelShader[shid]; + Assert(type == pShader->type); + + hr = pContext->pDevice->SetPixelShader(pShader->u.pPixelShader); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSet: SetVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else + if (shid == SVGA_ID_INVALID) + { + /* Unselect shader. */ + hr = pContext->pDevice->SetPixelShader(NULL); + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSet: SetVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR); + } + else + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, + SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues) +{ + HRESULT hr; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + Log(("vmsvga3dShaderSetConst %x reg=%x type=%s ctype=%x\n", cid, reg, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", ctype)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR); + + for (uint32_t i = 0; i < cRegisters; i++) + { +#ifdef LOG_ENABLED + switch (ctype) + { + case SVGA3D_CONST_TYPE_FLOAT: + { + float *pValuesF = (float *)pValues; + Log(("ConstantF %d: value=" FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR "\n", + reg + i, FLOAT_FMT_ARGS(pValuesF[i*4 + 0]), FLOAT_FMT_ARGS(pValuesF[i*4 + 1]), FLOAT_FMT_ARGS(pValuesF[i*4 + 2]), FLOAT_FMT_ARGS(pValuesF[i*4 + 3]))); + break; + } + + case SVGA3D_CONST_TYPE_INT: + Log(("ConstantI %d: value=%d, %d, %d, %d\n", reg + i, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3])); + break; + + case SVGA3D_CONST_TYPE_BOOL: + Log(("ConstantB %d: value=%d, %d, %d, %d\n", reg + i, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3])); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } +#endif + vmsvga3dSaveShaderConst(pContext, reg + i, type, ctype, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3]); + } + + switch (type) + { + case SVGA3D_SHADERTYPE_VS: + switch (ctype) + { + case SVGA3D_CONST_TYPE_FLOAT: + hr = pContext->pDevice->SetVertexShaderConstantF(reg, (const float *)pValues, cRegisters); + break; + + case SVGA3D_CONST_TYPE_INT: + hr = pContext->pDevice->SetVertexShaderConstantI(reg, (const int *)pValues, cRegisters); + break; + + case SVGA3D_CONST_TYPE_BOOL: + hr = pContext->pDevice->SetVertexShaderConstantB(reg, (const BOOL *)pValues, cRegisters); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSetConst: SetVertexShader failed with %x\n", hr), VERR_INTERNAL_ERROR); + break; + + case SVGA3D_SHADERTYPE_PS: + switch (ctype) + { + case SVGA3D_CONST_TYPE_FLOAT: + { + hr = pContext->pDevice->SetPixelShaderConstantF(reg, (const float *)pValues, cRegisters); + break; + } + + case SVGA3D_CONST_TYPE_INT: + hr = pContext->pDevice->SetPixelShaderConstantI(reg, (const int *)pValues, cRegisters); + break; + + case SVGA3D_CONST_TYPE_BOOL: + hr = pContext->pDevice->SetPixelShaderConstantB(reg, (const BOOL *)pValues, cRegisters); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSetConst: SetPixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR); + break; + + default: + AssertFailedReturn(VERR_INVALID_PARAMETER); + } + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryCreate(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThisCC); + HRESULT hr = pContext->pDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pContext->occlusion.pQuery); + AssertMsgReturn(hr == D3D_OK, ("CreateQuery(D3DQUERYTYPE_OCCLUSION) failed with %x\n", hr), VERR_INTERNAL_ERROR); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThisCC); + D3D_RELEASE(pContext->occlusion.pQuery); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryBegin(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThisCC); + HRESULT hr = pContext->occlusion.pQuery->Issue(D3DISSUE_BEGIN); + AssertMsgReturnStmt(hr == D3D_OK, ("D3DISSUE_BEGIN(D3DQUERYTYPE_OCCLUSION) failed with %x\n", hr), + D3D_RELEASE(pContext->occlusion.pQuery), VERR_INTERNAL_ERROR); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryEnd(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) +{ + RT_NOREF(pThisCC); + HRESULT hr = pContext->occlusion.pQuery->Issue(D3DISSUE_END); + AssertMsgReturnStmt(hr == D3D_OK, ("D3DISSUE_END(D3DQUERYTYPE_OCCLUSION) failed with %x\n", hr), + D3D_RELEASE(pContext->occlusion.pQuery), VERR_INTERNAL_ERROR); + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryGetData(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t *pu32Pixels) +{ + RT_NOREF(pThisCC); + HRESULT hr = D3D_OK; + /* Wait until the data becomes available. */ + DWORD dwPixels = 0; + do + { + hr = pContext->occlusion.pQuery->GetData((void *)&dwPixels, sizeof(DWORD), D3DGETDATA_FLUSH); + } while (hr == S_FALSE); + + AssertMsgReturnStmt(hr == D3D_OK, ("GetData(D3DQUERYTYPE_OCCLUSION) failed with %x\n", hr), + D3D_RELEASE(pContext->occlusion.pQuery), VERR_INTERNAL_ERROR); + + LogFunc(("Query result: dwPixels %d\n", dwPixels)); + *pu32Pixels = dwPixels; + return VINF_SUCCESS; +} + +static void vmsvgaDumpD3DCaps(D3DCAPS9 *pCaps, D3DADAPTER_IDENTIFIER9 const *pai9) +{ + bool const fBufferingSaved = RTLogRelSetBuffering(true /*fBuffered*/); + + LogRel(("\nD3D9 adapter: %s %RX16:%RX16 [%s, version %d.%d.%d.%d]\n", + pai9->Description, pai9->VendorId, pai9->DeviceId, pai9->Driver, + RT_HI_U16(pai9->DriverVersion.HighPart), RT_LO_U16(pai9->DriverVersion.HighPart), + RT_HI_U16(pai9->DriverVersion.LowPart), RT_LO_U16(pai9->DriverVersion.LowPart))); + + LogRel(("\nD3D device caps: DevCaps2:\n")); + if (pCaps->DevCaps2 & D3DDEVCAPS2_ADAPTIVETESSRTPATCH) + LogRel((" - D3DDEVCAPS2_ADAPTIVETESSRTPATCH\n")); + if (pCaps->DevCaps2 & D3DDEVCAPS2_ADAPTIVETESSNPATCH) + LogRel((" - D3DDEVCAPS2_ADAPTIVETESSNPATCH\n")); + if (pCaps->DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) + LogRel((" - D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES\n")); + if (pCaps->DevCaps2 & D3DDEVCAPS2_DMAPNPATCH) + LogRel((" - D3DDEVCAPS2_DMAPNPATCH\n")); + if (pCaps->DevCaps2 & D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH) + LogRel((" - D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH\n")); + if (pCaps->DevCaps2 & D3DDEVCAPS2_STREAMOFFSET) + LogRel((" - D3DDEVCAPS2_STREAMOFFSET\n")); + if (pCaps->DevCaps2 & D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET) + LogRel((" - D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET\n")); + + LogRel(("\nCaps2:\n")); + if (pCaps->Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) + LogRel((" - D3DCAPS2_CANAUTOGENMIPMAP\n")); + if (pCaps->Caps2 & D3DCAPS2_CANCALIBRATEGAMMA) + LogRel((" - D3DCAPS2_CANCALIBRATEGAMMA\n")); + if (pCaps->Caps2 & D3DCAPS2_CANSHARERESOURCE) + LogRel((" - D3DCAPS2_CANSHARERESOURCE\n")); + if (pCaps->Caps2 & D3DCAPS2_CANMANAGERESOURCE) + LogRel((" - D3DCAPS2_CANMANAGERESOURCE\n")); + if (pCaps->Caps2 & D3DCAPS2_DYNAMICTEXTURES) + LogRel((" - D3DCAPS2_DYNAMICTEXTURES\n")); + if (pCaps->Caps2 & D3DCAPS2_FULLSCREENGAMMA) + LogRel((" - D3DCAPS2_FULLSCREENGAMMA\n")); + + LogRel(("\nCaps3:\n")); + if (pCaps->Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD) + LogRel((" - D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD\n")); + if (pCaps->Caps3 & D3DCAPS3_COPY_TO_VIDMEM) + LogRel((" - D3DCAPS3_COPY_TO_VIDMEM\n")); + if (pCaps->Caps3 & D3DCAPS3_COPY_TO_SYSTEMMEM) + LogRel((" - D3DCAPS3_COPY_TO_SYSTEMMEM\n")); + if (pCaps->Caps3 & D3DCAPS3_DXVAHD) + LogRel((" - D3DCAPS3_DXVAHD\n")); + if (pCaps->Caps3 & D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION) + LogRel((" - D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION\n")); + + LogRel(("\nPresentationIntervals:\n")); + if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + LogRel((" - D3DPRESENT_INTERVAL_IMMEDIATE\n")); + if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + LogRel((" - D3DPRESENT_INTERVAL_ONE\n")); + if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_TWO) + LogRel((" - D3DPRESENT_INTERVAL_TWO\n")); + if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_THREE) + LogRel((" - D3DPRESENT_INTERVAL_THREE\n")); + if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) + LogRel((" - D3DPRESENT_INTERVAL_FOUR\n")); + + LogRel(("\nDevcaps:\n")); + if (pCaps->DevCaps & D3DDEVCAPS_CANBLTSYSTONONLOCAL) + LogRel((" - D3DDEVCAPS_CANBLTSYSTONONLOCAL\n")); + if (pCaps->DevCaps & D3DDEVCAPS_CANRENDERAFTERFLIP) + LogRel((" - D3DDEVCAPS_CANRENDERAFTERFLIP\n")); + if (pCaps->DevCaps & D3DDEVCAPS_DRAWPRIMITIVES2) + LogRel((" - D3DDEVCAPS_DRAWPRIMITIVES2\n")); + if (pCaps->DevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) + LogRel((" - D3DDEVCAPS_DRAWPRIMITIVES2EX\n")); + if (pCaps->DevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX) + LogRel((" - D3DDEVCAPS_DRAWPRIMTLVERTEX\n")); + if (pCaps->DevCaps & D3DDEVCAPS_EXECUTESYSTEMMEMORY) + LogRel((" - D3DDEVCAPS_EXECUTESYSTEMMEMORY\n")); + if (pCaps->DevCaps & D3DDEVCAPS_EXECUTEVIDEOMEMORY) + LogRel((" - D3DDEVCAPS_EXECUTEVIDEOMEMORY\n")); + if (pCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION) + LogRel((" - D3DDEVCAPS_HWRASTERIZATION\n")); + if (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) + LogRel((" - D3DDEVCAPS_HWTRANSFORMANDLIGHT\n")); + if (pCaps->DevCaps & D3DDEVCAPS_NPATCHES) + LogRel((" - D3DDEVCAPS_NPATCHES\n")); + if (pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) + LogRel((" - D3DDEVCAPS_PUREDEVICE\n")); + if (pCaps->DevCaps & D3DDEVCAPS_QUINTICRTPATCHES) + LogRel((" - D3DDEVCAPS_QUINTICRTPATCHES\n")); + if (pCaps->DevCaps & D3DDEVCAPS_RTPATCHES) + LogRel((" - D3DDEVCAPS_RTPATCHES\n")); + if (pCaps->DevCaps & D3DDEVCAPS_RTPATCHHANDLEZERO) + LogRel((" - D3DDEVCAPS_RTPATCHHANDLEZERO\n")); + if (pCaps->DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) + LogRel((" - D3DDEVCAPS_SEPARATETEXTUREMEMORIES\n")); + if (pCaps->DevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM) + LogRel((" - D3DDEVCAPS_TEXTURENONLOCALVIDMEM\n")); + if (pCaps->DevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY) + LogRel((" - D3DDEVCAPS_TEXTURESYSTEMMEMORY\n")); + if (pCaps->DevCaps & D3DDEVCAPS_TEXTUREVIDEOMEMORY) + LogRel((" - D3DDEVCAPS_TEXTUREVIDEOMEMORY\n")); + if (pCaps->DevCaps & D3DDEVCAPS_TLVERTEXSYSTEMMEMORY) + LogRel((" - D3DDEVCAPS_TLVERTEXSYSTEMMEMORY\n")); + if (pCaps->DevCaps & D3DDEVCAPS_TLVERTEXVIDEOMEMORY) + LogRel((" - D3DDEVCAPS_TLVERTEXVIDEOMEMORY\n")); + + LogRel(("\nTextureCaps:\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_ALPHA) + LogRel((" - D3DPTEXTURECAPS_ALPHA\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE) + LogRel((" - D3DPTEXTURECAPS_ALPHAPALETTE\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP) + LogRel((" - D3DPTEXTURECAPS_CUBEMAP\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) + LogRel((" - D3DPTEXTURECAPS_CUBEMAP_POW2\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP) + LogRel((" - D3DPTEXTURECAPS_MIPCUBEMAP\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_MIPMAP) + LogRel((" - D3DPTEXTURECAPS_MIPMAP\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP) + LogRel((" - D3DPTEXTURECAPS_MIPVOLUMEMAP\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) + LogRel((" - D3DPTEXTURECAPS_NONPOW2CONDITIONAL\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_POW2) + LogRel((" - D3DPTEXTURECAPS_POW2\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_NOPROJECTEDBUMPENV) + LogRel((" - D3DPTEXTURECAPS_NOPROJECTEDBUMPENV\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) + LogRel((" - D3DPTEXTURECAPS_PERSPECTIVE\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_POW2) + LogRel((" - D3DPTEXTURECAPS_POW2\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_PROJECTED) + LogRel((" - D3DPTEXTURECAPS_PROJECTED\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) + LogRel((" - D3DPTEXTURECAPS_SQUAREONLY\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE) + LogRel((" - D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) + LogRel((" - D3DPTEXTURECAPS_VOLUMEMAP\n")); + if (pCaps->TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) + LogRel((" - D3DPTEXTURECAPS_VOLUMEMAP_POW2\n")); + + LogRel(("\nTextureFilterCaps\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_CONVOLUTIONMONO) + LogRel((" - D3DPTFILTERCAPS_CONVOLUTIONMONO\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) + LogRel((" - D3DPTFILTERCAPS_MAGFPOINT\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MAGFLINEAR\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) + LogRel((" - D3DPTFILTERCAPS_MAGFANISOTROPIC\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD) + LogRel((" - D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFGAUSSIANQUAD) + LogRel((" - D3DPTFILTERCAPS_MAGFGAUSSIANQUAD\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT) + LogRel((" - D3DPTFILTERCAPS_MINFPOINT\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MINFLINEAR\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) + LogRel((" - D3DPTFILTERCAPS_MINFANISOTROPIC\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD) + LogRel((" - D3DPTFILTERCAPS_MINFPYRAMIDALQUAD\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD) + LogRel((" - D3DPTFILTERCAPS_MINFGAUSSIANQUAD\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT) + LogRel((" - D3DPTFILTERCAPS_MIPFPOINT\n")); + if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MIPFLINEAR\n")); + + LogRel(("\nCubeTextureFilterCaps\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_CONVOLUTIONMONO) + LogRel((" - D3DPTFILTERCAPS_CONVOLUTIONMONO\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) + LogRel((" - D3DPTFILTERCAPS_MAGFPOINT\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MAGFLINEAR\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) + LogRel((" - D3DPTFILTERCAPS_MAGFANISOTROPIC\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD) + LogRel((" - D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFGAUSSIANQUAD) + LogRel((" - D3DPTFILTERCAPS_MAGFGAUSSIANQUAD\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT) + LogRel((" - D3DPTFILTERCAPS_MINFPOINT\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MINFLINEAR\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) + LogRel((" - D3DPTFILTERCAPS_MINFANISOTROPIC\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD) + LogRel((" - D3DPTFILTERCAPS_MINFPYRAMIDALQUAD\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD) + LogRel((" - D3DPTFILTERCAPS_MINFGAUSSIANQUAD\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT) + LogRel((" - D3DPTFILTERCAPS_MIPFPOINT\n")); + if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MIPFLINEAR\n")); + + LogRel(("\nVolumeTextureFilterCaps\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_CONVOLUTIONMONO) + LogRel((" - D3DPTFILTERCAPS_CONVOLUTIONMONO\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) + LogRel((" - D3DPTFILTERCAPS_MAGFPOINT\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MAGFLINEAR\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) + LogRel((" - D3DPTFILTERCAPS_MAGFANISOTROPIC\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD) + LogRel((" - D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFGAUSSIANQUAD) + LogRel((" - D3DPTFILTERCAPS_MAGFGAUSSIANQUAD\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT) + LogRel((" - D3DPTFILTERCAPS_MINFPOINT\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MINFLINEAR\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) + LogRel((" - D3DPTFILTERCAPS_MINFANISOTROPIC\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD) + LogRel((" - D3DPTFILTERCAPS_MINFPYRAMIDALQUAD\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD) + LogRel((" - D3DPTFILTERCAPS_MINFGAUSSIANQUAD\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT) + LogRel((" - D3DPTFILTERCAPS_MIPFPOINT\n")); + if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR) + LogRel((" - D3DPTFILTERCAPS_MIPFLINEAR\n")); + + LogRel(("\nTextureAddressCaps:\n")); + if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_BORDER) + LogRel((" - D3DPTADDRESSCAPS_BORDER\n")); + if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP) + LogRel((" - D3DPTADDRESSCAPS_CLAMP\n")); + if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV) + LogRel((" - D3DPTADDRESSCAPS_INDEPENDENTUV\n")); + if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR) + LogRel((" - D3DPTADDRESSCAPS_MIRROR\n")); + if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE) + LogRel((" - D3DPTADDRESSCAPS_MIRRORONCE\n")); + if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_WRAP) + LogRel((" - D3DPTADDRESSCAPS_WRAP\n")); + + LogRel(("\nTextureOpCaps:\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_DISABLE) + LogRel((" - D3DTEXOPCAPS_DISABLE\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_SELECTARG1) + LogRel((" - D3DTEXOPCAPS_SELECTARG1\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_SELECTARG2) + LogRel((" - D3DTEXOPCAPS_SELECTARG2\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATE) + LogRel((" - D3DTEXOPCAPS_MODULATE\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATE2X) + LogRel((" - D3DTEXOPCAPS_MODULATE2X\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATE4X) + LogRel((" - D3DTEXOPCAPS_MODULATE4X\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_ADD) + LogRel((" - D3DTEXOPCAPS_ADD\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_ADDSIGNED) + LogRel((" - D3DTEXOPCAPS_ADDSIGNED\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_ADDSIGNED2X) + LogRel((" - D3DTEXOPCAPS_ADDSIGNED2X\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_SUBTRACT) + LogRel((" - D3DTEXOPCAPS_SUBTRACT\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_ADDSMOOTH) + LogRel((" - D3DTEXOPCAPS_ADDSMOOTH\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDDIFFUSEALPHA) + LogRel((" - D3DTEXOPCAPS_BLENDDIFFUSEALPHA\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDTEXTUREALPHA) + LogRel((" - D3DTEXOPCAPS_BLENDTEXTUREALPHA\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA) + LogRel((" - D3DTEXOPCAPS_BLENDFACTORALPHA\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDTEXTUREALPHAPM) + LogRel((" - D3DTEXOPCAPS_BLENDTEXTUREALPHAPM\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDCURRENTALPHA) + LogRel((" - D3DTEXOPCAPS_BLENDCURRENTALPHA\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_PREMODULATE) + LogRel((" - D3DTEXOPCAPS_PREMODULATE\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR) + LogRel((" - D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA) + LogRel((" - D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR) + LogRel((" - D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA) + LogRel((" - D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP) + LogRel((" - D3DTEXOPCAPS_BUMPENVMAP\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAPLUMINANCE) + LogRel((" - D3DTEXOPCAPS_BUMPENVMAPLUMINANCE\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) + LogRel((" - D3DTEXOPCAPS_DOTPRODUCT3\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) + LogRel((" - D3DTEXOPCAPS_MULTIPLYADD\n")); + if (pCaps->TextureOpCaps & D3DTEXOPCAPS_LERP) + LogRel((" - D3DTEXOPCAPS_LERP\n")); + + + LogRel(("\n")); + LogRel(("PixelShaderVersion: %#x (%u.%u)\n", pCaps->PixelShaderVersion, + D3DSHADER_VERSION_MAJOR(pCaps->PixelShaderVersion), D3DSHADER_VERSION_MINOR(pCaps->PixelShaderVersion))); + LogRel(("VertexShaderVersion: %#x (%u.%u)\n", pCaps->VertexShaderVersion, + D3DSHADER_VERSION_MAJOR(pCaps->VertexShaderVersion), D3DSHADER_VERSION_MINOR(pCaps->VertexShaderVersion))); + + LogRel(("\n")); + RTLogRelSetBuffering(fBufferingSaved); +} + +/** + * Worker for vmsvga3dUpdateHeapBuffersForSurfaces. + * + * This will allocate heap buffers if necessary, thus increasing the memory + * usage of the process. + * + * @todo Would be interesting to share this code with the saved state code. + * + * @returns VBox status code. + * @param pThisCC The VGA/VMSVGA context. + * @param pSurface The surface to refresh the heap buffers for. + */ +static DECLCALLBACK(int) vmsvga3dBackSurfaceUpdateHeapBuffers(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + /* + * Currently we've got trouble retreving bit for DEPTHSTENCIL + * surfaces both for OpenGL and D3D, so skip these here (don't + * wast memory on them). + */ + uint32_t const fSwitchFlags = pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK; + if ( fSwitchFlags != SVGA3D_SURFACE_HINT_DEPTHSTENCIL + && fSwitchFlags != (SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE)) + { + + /* + * Work thru each mipmap level for each face. + */ + for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[iFace * pSurface->cLevels]; + for (uint32_t i = 0; i < pSurface->cLevels; i++, pMipmapLevel++) + { + if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + Assert(pMipmapLevel->cbSurface); + Assert(pMipmapLevel->cbSurface == pMipmapLevel->cbSurfacePlane * pMipmapLevel->mipmapSize.depth); + + /* + * Make sure we've got surface memory buffer. + */ + uint8_t *pbDst = (uint8_t *)pMipmapLevel->pSurfaceData; + if (!pbDst) + { + pMipmapLevel->pSurfaceData = pbDst = (uint8_t *)RTMemAllocZ(pMipmapLevel->cbSurface); + AssertReturn(pbDst, VERR_NO_MEMORY); + } + + /* + * D3D specifics. + */ + Assert(pSurface->enmD3DResType != VMSVGA3D_D3DRESTYPE_NONE); + + HRESULT hr; + switch (pSurface->enmD3DResType) + { + case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE: + AssertFailed(); /// @todo + break; + + case VMSVGA3D_D3DRESTYPE_SURFACE: + case VMSVGA3D_D3DRESTYPE_TEXTURE: + case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE: + { + /* + * Lock the buffer and make it accessible to memcpy. + */ + D3DLOCKED_RECT LockedRect; + if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE) + { + hr = pSurface->u.pCubeTexture->LockRect(vmsvga3dCubemapFaceFromIndex(iFace), + i, /* texture level */ + &LockedRect, + NULL, + D3DLOCK_READONLY); + } + else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE) + { + if (pSurface->bounce.pTexture) + { + if ( !pSurface->fDirty + && RT_BOOL(fSwitchFlags & SVGA3D_SURFACE_HINT_RENDERTARGET)) + { + /** @todo stricter checks for associated context */ + uint32_t cid = pSurface->idAssociatedContext; + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + IDirect3DSurface9 *pDst = NULL; + hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDst); + AssertMsgReturn(hr == D3D_OK, ("GetSurfaceLevel failed with %#x\n", hr), VERR_INTERNAL_ERROR); + + IDirect3DSurface9 *pSrc = NULL; + hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc); + AssertMsgReturn(hr == D3D_OK, ("GetSurfaceLevel failed with %#x\n", hr), VERR_INTERNAL_ERROR); + + hr = pContext->pDevice->GetRenderTargetData(pSrc, pDst); + AssertMsgReturn(hr == D3D_OK, ("GetRenderTargetData failed with %#x\n", hr), VERR_INTERNAL_ERROR); + + pSrc->Release(); + pDst->Release(); + } + + hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */ + &LockedRect, + NULL, + D3DLOCK_READONLY); + } + else + hr = pSurface->u.pTexture->LockRect(i, /* texture level */ + &LockedRect, + NULL, + D3DLOCK_READONLY); + } + else + hr = pSurface->u.pSurface->LockRect(&LockedRect, + NULL, + D3DLOCK_READONLY); + AssertMsgReturn(hr == D3D_OK, ("LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR); + + /* + * Copy the data. Take care in case the pitch differs. + */ + if (pMipmapLevel->cbSurfacePitch == (uint32_t)LockedRect.Pitch) + memcpy(pbDst, LockedRect.pBits, pMipmapLevel->cbSurface); + else + for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; j++) + memcpy(pbDst + j * pMipmapLevel->cbSurfacePitch, + (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch, + pMipmapLevel->cbSurfacePitch); + + /* + * Release the buffer. + */ + if (fSwitchFlags & SVGA3D_SURFACE_HINT_TEXTURE) + { + if (pSurface->bounce.pTexture) + { + hr = pSurface->bounce.pTexture->UnlockRect(i); + AssertMsgReturn(hr == D3D_OK, ("UnlockRect failed with %#x\n", hr), VERR_INTERNAL_ERROR); + } + else + hr = pSurface->u.pTexture->UnlockRect(i); + } + else + hr = pSurface->u.pSurface->UnlockRect(); + AssertMsgReturn(hr == D3D_OK, ("UnlockRect failed with %#x\n", hr), VERR_INTERNAL_ERROR); + break; + } + + case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER: + case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER: + { + /* Current type of the buffer. */ + const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER); + + void *pvD3DData = NULL; + if (fVertex) + hr = pSurface->u.pVertexBuffer->Lock(0, 0, &pvD3DData, D3DLOCK_READONLY); + else + hr = pSurface->u.pIndexBuffer->Lock(0, 0, &pvD3DData, D3DLOCK_READONLY); + AssertMsgReturn(hr == D3D_OK, ("Lock %s failed with %x\n", fVertex ? "vertex" : "index", hr), VERR_INTERNAL_ERROR); + + memcpy(pbDst, pvD3DData, pMipmapLevel->cbSurface); + + if (fVertex) + hr = pSurface->u.pVertexBuffer->Unlock(); + else + hr = pSurface->u.pIndexBuffer->Unlock(); + AssertMsg(hr == D3D_OK, ("Unlock %s failed with %x\n", fVertex ? "vertex" : "index", hr)); + break; + } + + default: + AssertMsgFailed(("flags %#x, type %d\n", fSwitchFlags, pSurface->enmD3DResType)); + } + + } + /* else: There is no data in hardware yet, so whatever we got is already current. */ + } + } + } + + return VINF_SUCCESS; +} + + +static DECLCALLBACK(int) vmsvga3dBackQueryInterface(PVGASTATECC pThisCC, char const *pszInterfaceName, void *pvInterfaceFuncs, size_t cbInterfaceFuncs) +{ + RT_NOREF(pThisCC); + + int rc = VINF_SUCCESS; + if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_3D) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCS3D)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCS3D *p = (VMSVGA3DBACKENDFUNCS3D *)pvInterfaceFuncs; + p->pfnInit = vmsvga3dBackInit; + p->pfnPowerOn = vmsvga3dBackPowerOn; + p->pfnTerminate = vmsvga3dBackTerminate; + p->pfnReset = vmsvga3dBackReset; + p->pfnQueryCaps = vmsvga3dBackQueryCaps; + p->pfnChangeMode = vmsvga3dBackChangeMode; + p->pfnCreateTexture = vmsvga3dBackCreateTexture; + p->pfnSurfaceDestroy = vmsvga3dBackSurfaceDestroy; + p->pfnSurfaceInvalidateImage = vmsvga3dBackSurfaceInvalidateImage; + p->pfnSurfaceCopy = vmsvga3dBackSurfaceCopy; + p->pfnSurfaceDMACopyBox = vmsvga3dBackSurfaceDMACopyBox; + p->pfnSurfaceStretchBlt = vmsvga3dBackSurfaceStretchBlt; + p->pfnUpdateHostScreenViewport = vmsvga3dBackUpdateHostScreenViewport; + p->pfnDefineScreen = vmsvga3dBackDefineScreen; + p->pfnDestroyScreen = vmsvga3dBackDestroyScreen; + p->pfnSurfaceBlitToScreen = vmsvga3dBackSurfaceBlitToScreen; + p->pfnSurfaceUpdateHeapBuffers = vmsvga3dBackSurfaceUpdateHeapBuffers; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_VGPU9) == 0) + { + if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSVGPU9)) + { + if (pvInterfaceFuncs) + { + VMSVGA3DBACKENDFUNCSVGPU9 *p = (VMSVGA3DBACKENDFUNCSVGPU9 *)pvInterfaceFuncs; + p->pfnContextDefine = vmsvga3dBackContextDefine; + p->pfnContextDestroy = vmsvga3dBackContextDestroy; + p->pfnSetTransform = vmsvga3dBackSetTransform; + p->pfnSetZRange = vmsvga3dBackSetZRange; + p->pfnSetRenderState = vmsvga3dBackSetRenderState; + p->pfnSetRenderTarget = vmsvga3dBackSetRenderTarget; + p->pfnSetTextureState = vmsvga3dBackSetTextureState; + p->pfnSetMaterial = vmsvga3dBackSetMaterial; + p->pfnSetLightData = vmsvga3dBackSetLightData; + p->pfnSetLightEnabled = vmsvga3dBackSetLightEnabled; + p->pfnSetViewPort = vmsvga3dBackSetViewPort; + p->pfnSetClipPlane = vmsvga3dBackSetClipPlane; + p->pfnCommandClear = vmsvga3dBackCommandClear; + p->pfnDrawPrimitives = vmsvga3dBackDrawPrimitives; + p->pfnSetScissorRect = vmsvga3dBackSetScissorRect; + p->pfnGenerateMipmaps = vmsvga3dBackGenerateMipmaps; + p->pfnShaderDefine = vmsvga3dBackShaderDefine; + p->pfnShaderDestroy = vmsvga3dBackShaderDestroy; + p->pfnShaderSet = vmsvga3dBackShaderSet; + p->pfnShaderSetConst = vmsvga3dBackShaderSetConst; + p->pfnOcclusionQueryCreate = vmsvga3dBackOcclusionQueryCreate; + p->pfnOcclusionQueryDelete = vmsvga3dBackOcclusionQueryDelete; + p->pfnOcclusionQueryBegin = vmsvga3dBackOcclusionQueryBegin; + p->pfnOcclusionQueryEnd = vmsvga3dBackOcclusionQueryEnd; + p->pfnOcclusionQueryGetData = vmsvga3dBackOcclusionQueryGetData; + } + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else + rc = VERR_NOT_IMPLEMENTED; + return rc; +} + + +extern VMSVGA3DBACKENDDESC const g_BackendLegacy = +{ + "LEGACY", + vmsvga3dBackQueryInterface +}; diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp new file mode 100644 index 00000000..3689aeb5 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp @@ -0,0 +1,1913 @@ +/* $Id: DevVGA-SVGA3d.cpp $ */ +/** @file + * DevSVGA3d - VMWare SVGA device, 3D parts - Common core code. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#include +#include + +#include +#include + +#include /* required by DevVGA.h */ +#include /* required by DevVGA.h */ + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#include "DevVGA-SVGA.h" +#include "DevVGA-SVGA3d.h" +#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS +#include "DevVGA-SVGA3d-internal.h" +#include "DevVGA-SVGA-internal.h" + + +static int vmsvga3dSurfaceAllocMipLevels(PVMSVGA3DSURFACE pSurface) +{ + /* Allocate buffer to hold the surface data until we can move it into a D3D object */ + for (uint32_t i = 0; i < pSurface->cLevels * pSurface->surfaceDesc.numArrayElements; ++i) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i]; + AssertReturn(pMipmapLevel->pSurfaceData == NULL, VERR_INVALID_STATE); + pMipmapLevel->pSurfaceData = RTMemAllocZ(pMipmapLevel->cbSurface); + AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY); + } + return VINF_SUCCESS; +} + + +static void vmsvga3dSurfaceFreeMipLevels(PVMSVGA3DSURFACE pSurface) +{ + for (uint32_t i = 0; i < pSurface->cLevels * pSurface->surfaceDesc.numArrayElements; ++i) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i]; + RTMemFreeZ(pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface); + pMipmapLevel->pSurfaceData = NULL; + } +} + + +/** + * Implements the SVGA_3D_CMD_SURFACE_DEFINE_V2 and SVGA_3D_CMD_SURFACE_DEFINE + * commands (fifo). + * + * @returns VBox status code (currently ignored). + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param sid The ID of the surface to (re-)define. + * @param surfaceFlags . + * @param format . + * @param multisampleCount . + * @param autogenFilter . + * @param numMipLevels . + * @param pMipLevel0Size . + * @param arraySize Number of elements in a texture array. + * @param fAllocMipLevels . + */ +int vmsvga3dSurfaceDefine(PVGASTATECC pThisCC, uint32_t sid, SVGA3dSurfaceAllFlags surfaceFlags, SVGA3dSurfaceFormat format, + uint32_t multisampleCount, SVGA3dTextureFilter autogenFilter, + uint32_t numMipLevels, SVGA3dSize const *pMipLevel0Size, uint32_t arraySize, bool fAllocMipLevels) +{ + PVMSVGA3DSURFACE pSurface; + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + LogFunc(("sid=%u surfaceFlags=0x%RX64 format=%s (%#x) multiSampleCount=%d autogenFilter=%d, numMipLevels=%d size=(%dx%dx%d)\n", + sid, surfaceFlags, vmsvgaLookupEnum((int)format, &g_SVGA3dSurfaceFormat2String), format, multisampleCount, autogenFilter, + numMipLevels, pMipLevel0Size->width, pMipLevel0Size->height, pMipLevel0Size->depth)); + + ASSERT_GUEST_RETURN(sid < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(numMipLevels >= 1 && numMipLevels <= SVGA3D_MAX_MIP_LEVELS, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(arraySize <= SVGA3D_MAX_SURFACE_ARRAYSIZE, VERR_INVALID_PARAMETER); + + if (sid >= pState->cSurfaces) + { + /* Grow the array. */ + uint32_t cNew = RT_ALIGN(sid + 15, 16); + void *pvNew = RTMemRealloc(pState->papSurfaces, sizeof(pState->papSurfaces[0]) * cNew); + AssertReturn(pvNew, VERR_NO_MEMORY); + pState->papSurfaces = (PVMSVGA3DSURFACE *)pvNew; + while (pState->cSurfaces < cNew) + { + pSurface = (PVMSVGA3DSURFACE)RTMemAllocZ(sizeof(*pSurface)); + AssertReturn(pSurface, VERR_NO_MEMORY); + pSurface->id = SVGA3D_INVALID_ID; + pState->papSurfaces[pState->cSurfaces++] = pSurface; + } + } + pSurface = pState->papSurfaces[sid]; + + /* If one already exists with this id, then destroy it now. */ + if (pSurface->id != SVGA3D_INVALID_ID) + vmsvga3dSurfaceDestroy(pThisCC, sid); + + RT_ZERO(*pSurface); + // pSurface->pBackendSurface = NULL; + pSurface->id = SVGA3D_INVALID_ID; /* Keep this value until the surface init completes */ + pSurface->idAssociatedContext = SVGA3D_INVALID_ID; + + if (arraySize) + pSurface->surfaceDesc.numArrayElements = arraySize; /* Also for an array of cubemaps where arraySize = 6 * numCubes. */ + else if (surfaceFlags & SVGA3D_SURFACE_CUBEMAP) + pSurface->surfaceDesc.numArrayElements = SVGA3D_MAX_SURFACE_FACES; + else + pSurface->surfaceDesc.numArrayElements = 1; + + /** @todo This 'switch' and the surfaceFlags tweaks should not be necessary. + * The actual surface type will be figured out when the surface is actually used later. + * The backends code must be reviewed for unnecessary dependencies on the surfaceFlags value. + */ + /* The surface type is sort of undefined now, even though the hints and format can help to clear that up. + * In some case we'll have to wait until the surface is used to create the D3D object. + */ + switch (format) + { + case SVGA3D_Z_D32: + case SVGA3D_Z_D16: + case SVGA3D_Z_D24S8: + case SVGA3D_Z_D15S1: + case SVGA3D_Z_D24X8: + case SVGA3D_Z_DF16: + case SVGA3D_Z_DF24: + case SVGA3D_Z_D24S8_INT: + Assert(surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL); + surfaceFlags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL; + break; + + /* Texture compression formats */ + case SVGA3D_DXT1: + case SVGA3D_DXT2: + case SVGA3D_DXT3: + case SVGA3D_DXT4: + case SVGA3D_DXT5: + /* Bump-map formats */ + case SVGA3D_BUMPU8V8: + case SVGA3D_BUMPL6V5U5: + case SVGA3D_BUMPX8L8V8U8: + case SVGA3D_V8U8: + case SVGA3D_Q8W8V8U8: + case SVGA3D_CxV8U8: + case SVGA3D_X8L8V8U8: + case SVGA3D_A2W10V10U10: + case SVGA3D_V16U16: + /* Typical render target formats; we should allow render target buffers to be used as textures. */ + case SVGA3D_X8R8G8B8: + case SVGA3D_A8R8G8B8: + case SVGA3D_R5G6B5: + case SVGA3D_X1R5G5B5: + case SVGA3D_A1R5G5B5: + case SVGA3D_A4R4G4B4: + Assert(surfaceFlags & (SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_SCREENTARGET)); + surfaceFlags |= SVGA3D_SURFACE_HINT_TEXTURE; + break; + + case SVGA3D_LUMINANCE8: + case SVGA3D_LUMINANCE4_ALPHA4: + case SVGA3D_LUMINANCE16: + case SVGA3D_LUMINANCE8_ALPHA8: + case SVGA3D_ARGB_S10E5: /* 16-bit floating-point ARGB */ + case SVGA3D_ARGB_S23E8: /* 32-bit floating-point ARGB */ + case SVGA3D_A2R10G10B10: + case SVGA3D_ALPHA8: + case SVGA3D_R_S10E5: + case SVGA3D_R_S23E8: + case SVGA3D_RG_S10E5: + case SVGA3D_RG_S23E8: + case SVGA3D_G16R16: + case SVGA3D_A16B16G16R16: + case SVGA3D_UYVY: + case SVGA3D_YUY2: + case SVGA3D_NV12: + case SVGA3D_FORMAT_DEAD2: /* Old SVGA3D_AYUV */ + case SVGA3D_ATI1: + case SVGA3D_ATI2: + break; + + /* + * Any surface can be used as a buffer object, but SVGA3D_BUFFER is + * the most efficient format to use when creating new surfaces + * expressly for index or vertex data. + */ + case SVGA3D_BUFFER: + break; + + default: + break; + } + + pSurface->f.surfaceFlags = surfaceFlags; + pSurface->format = format; + /* cFaces is 6 for a cubemaps and 1 otherwise. */ + pSurface->cFaces = (uint32_t)((surfaceFlags & SVGA3D_SURFACE_CUBEMAP) ? 6 : 1); + pSurface->cLevels = numMipLevels; + pSurface->multiSampleCount = multisampleCount; + pSurface->autogenFilter = autogenFilter; + Assert(autogenFilter != SVGA3D_TEX_FILTER_FLATCUBIC); + Assert(autogenFilter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC); + pSurface->paMipmapLevels = (PVMSVGA3DMIPMAPLEVEL)RTMemAllocZ(numMipLevels * pSurface->surfaceDesc.numArrayElements * sizeof(VMSVGA3DMIPMAPLEVEL)); + AssertReturn(pSurface->paMipmapLevels, VERR_NO_MEMORY); + + pSurface->cbBlock = vmsvga3dSurfaceFormatSize(format, &pSurface->cxBlock, &pSurface->cyBlock); + AssertReturn(pSurface->cbBlock, VERR_INVALID_PARAMETER); + + /** @todo cbMemRemaining = value of SVGA_REG_MOB_MAX_SIZE */ + uint32_t cbMemRemaining = SVGA3D_MAX_SURFACE_MEM_SIZE; /* Do not allow more than this for a surface. */ + SVGA3dSize mipmapSize = *pMipLevel0Size; + int rc = VINF_SUCCESS; + + for (uint32_t i = 0; i < numMipLevels; ++i) + { + for (uint32_t iArray = 0; iArray < pSurface->surfaceDesc.numArrayElements; ++iArray) + { + uint32_t const iMipmap = vmsvga3dCalcSubresource(i, iArray, numMipLevels); + LogFunc(("[%d] array %d mip level %d (%d,%d,%d) cbBlock=%#x block %dx%d\n", + iMipmap, iArray, i, mipmapSize.width, mipmapSize.height, mipmapSize.depth, + pSurface->cbBlock, pSurface->cxBlock, pSurface->cyBlock)); + + uint32_t cBlocksX; + uint32_t cBlocksY; + if (RT_LIKELY(pSurface->cxBlock == 1 && pSurface->cyBlock == 1)) + { + cBlocksX = mipmapSize.width; + cBlocksY = mipmapSize.height; + } + else + { + cBlocksX = mipmapSize.width / pSurface->cxBlock; + if (mipmapSize.width % pSurface->cxBlock) + ++cBlocksX; + cBlocksY = mipmapSize.height / pSurface->cyBlock; + if (mipmapSize.height % pSurface->cyBlock) + ++cBlocksY; + } + + AssertBreakStmt(cBlocksX > 0 && cBlocksY > 0 && mipmapSize.depth > 0, rc = VERR_INVALID_PARAMETER); + + const uint32_t cMaxBlocksX = cbMemRemaining / pSurface->cbBlock; + AssertBreakStmt(cBlocksX < cMaxBlocksX, rc = VERR_INVALID_PARAMETER); + + const uint32_t cbSurfacePitch = pSurface->cbBlock * cBlocksX; + LogFunc(("cbSurfacePitch=0x%x\n", cbSurfacePitch)); + + const uint32_t cMaxBlocksY = cbMemRemaining / cbSurfacePitch; + AssertBreakStmt(cBlocksY < cMaxBlocksY, rc = VERR_INVALID_PARAMETER); + + const uint32_t cbSurfacePlane = cbSurfacePitch * cBlocksY; + + const uint32_t cMaxDepth = cbMemRemaining / cbSurfacePlane; + AssertBreakStmt(mipmapSize.depth < cMaxDepth, rc = VERR_INVALID_PARAMETER); + + const uint32_t cbSurface = cbSurfacePlane * mipmapSize.depth; + + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[iMipmap]; + pMipmapLevel->mipmapSize = mipmapSize; + pMipmapLevel->cBlocksX = cBlocksX; + pMipmapLevel->cBlocksY = cBlocksY; + pMipmapLevel->cBlocks = cBlocksX * cBlocksY * mipmapSize.depth; + pMipmapLevel->cbSurfacePitch = cbSurfacePitch; + pMipmapLevel->cbSurfacePlane = cbSurfacePlane; + pMipmapLevel->cbSurface = cbSurface; + pMipmapLevel->pSurfaceData = NULL; + + cbMemRemaining -= cbSurface; + } + + AssertRCBreak(rc); + + mipmapSize.width >>= 1; + if (mipmapSize.width == 0) mipmapSize.width = 1; + mipmapSize.height >>= 1; + if (mipmapSize.height == 0) mipmapSize.height = 1; + mipmapSize.depth >>= 1; + if (mipmapSize.depth == 0) mipmapSize.depth = 1; + } + + AssertLogRelRCReturnStmt(rc, RTMemFree(pSurface->paMipmapLevels), rc); + + /* Compute the size of one array element. */ + pSurface->surfaceDesc.cbArrayElement = 0; + for (uint32_t i = 0; i < pSurface->cLevels; ++i) + { + PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i]; + pSurface->surfaceDesc.cbArrayElement += pMipLevel->cbSurface; + } + + if (vmsvga3dIsLegacyBackend(pThisCC)) + { +#ifdef VMSVGA3D_DIRECT3D + /* pSurface->hSharedObject = NULL; */ + /* pSurface->pSharedObjectTree = NULL; */ + /* Translate the format and usage flags to D3D. */ + pSurface->d3dfmtRequested = vmsvga3dSurfaceFormat2D3D(format); + pSurface->formatD3D = D3D9GetActualFormat(pState, pSurface->d3dfmtRequested); + pSurface->multiSampleTypeD3D= vmsvga3dMultipeSampleCount2D3D(multisampleCount); + pSurface->fUsageD3D = 0; + if (surfaceFlags & SVGA3D_SURFACE_HINT_DYNAMIC) + pSurface->fUsageD3D |= D3DUSAGE_DYNAMIC; + if (surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET) + pSurface->fUsageD3D |= D3DUSAGE_RENDERTARGET; + if (surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) + pSurface->fUsageD3D |= D3DUSAGE_DEPTHSTENCIL; + if (surfaceFlags & SVGA3D_SURFACE_HINT_WRITEONLY) + pSurface->fUsageD3D |= D3DUSAGE_WRITEONLY; + if (surfaceFlags & SVGA3D_SURFACE_AUTOGENMIPMAPS) + pSurface->fUsageD3D |= D3DUSAGE_AUTOGENMIPMAP; + pSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_NONE; + /* pSurface->u.pSurface = NULL; */ + /* pSurface->bounce.pTexture = NULL; */ + /* pSurface->emulated.pTexture = NULL; */ +#else + /* pSurface->oglId.buffer = OPENGL_INVALID_ID; */ + /* pSurface->fEmulated = false; */ + /* pSurface->idEmulated = OPENGL_INVALID_ID; */ + vmsvga3dSurfaceFormat2OGL(pSurface, format); +#endif + } + +#ifdef LOG_ENABLED + SVGA3dSurfaceAllFlags const f = surfaceFlags; + LogFunc(("surface flags:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s 0x%RX64\n", + (f & SVGA3D_SURFACE_CUBEMAP) ? " CUBEMAP" : "", + (f & SVGA3D_SURFACE_HINT_STATIC) ? " HINT_STATIC" : "", + (f & SVGA3D_SURFACE_HINT_DYNAMIC) ? " HINT_DYNAMIC" : "", + (f & SVGA3D_SURFACE_HINT_INDEXBUFFER) ? " HINT_INDEXBUFFER" : "", + (f & SVGA3D_SURFACE_HINT_VERTEXBUFFER) ? " HINT_VERTEXBUFFER" : "", + (f & SVGA3D_SURFACE_HINT_TEXTURE) ? " HINT_TEXTURE" : "", + (f & SVGA3D_SURFACE_HINT_RENDERTARGET) ? " HINT_RENDERTARGET" : "", + (f & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) ? " HINT_DEPTHSTENCIL" : "", + (f & SVGA3D_SURFACE_HINT_WRITEONLY) ? " HINT_WRITEONLY" : "", + (f & SVGA3D_SURFACE_DEAD2) ? " DEAD2" : "", + (f & SVGA3D_SURFACE_AUTOGENMIPMAPS) ? " AUTOGENMIPMAPS" : "", + (f & SVGA3D_SURFACE_DEAD1) ? " DEAD1" : "", + (f & SVGA3D_SURFACE_MOB_PITCH) ? " MOB_PITCH" : "", + (f & SVGA3D_SURFACE_INACTIVE) ? " INACTIVE" : "", + (f & SVGA3D_SURFACE_HINT_RT_LOCKABLE) ? " HINT_RT_LOCKABLE" : "", + (f & SVGA3D_SURFACE_VOLUME) ? " VOLUME" : "", + (f & SVGA3D_SURFACE_SCREENTARGET) ? " SCREENTARGET" : "", + (f & SVGA3D_SURFACE_ALIGN16) ? " ALIGN16" : "", + (f & SVGA3D_SURFACE_1D) ? " 1D" : "", + (f & SVGA3D_SURFACE_ARRAY) ? " ARRAY" : "", + (f & SVGA3D_SURFACE_BIND_VERTEX_BUFFER) ? " BIND_VERTEX_BUFFER" : "", + (f & SVGA3D_SURFACE_BIND_INDEX_BUFFER) ? " BIND_INDEX_BUFFER" : "", + (f & SVGA3D_SURFACE_BIND_CONSTANT_BUFFER) ? " BIND_CONSTANT_BUFFER" : "", + (f & SVGA3D_SURFACE_BIND_SHADER_RESOURCE) ? " BIND_SHADER_RESOURCE" : "", + (f & SVGA3D_SURFACE_BIND_RENDER_TARGET) ? " BIND_RENDER_TARGET" : "", + (f & SVGA3D_SURFACE_BIND_DEPTH_STENCIL) ? " BIND_DEPTH_STENCIL" : "", + (f & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) ? " BIND_STREAM_OUTPUT" : "", + (f & SVGA3D_SURFACE_STAGING_UPLOAD) ? " STAGING_UPLOAD" : "", + (f & SVGA3D_SURFACE_STAGING_DOWNLOAD) ? " STAGING_DOWNLOAD" : "", + (f & SVGA3D_SURFACE_HINT_INDIRECT_UPDATE) ? " HINT_INDIRECT_UPDATE" : "", + (f & SVGA3D_SURFACE_TRANSFER_FROM_BUFFER) ? " TRANSFER_FROM_BUFFER" : "", + (f & SVGA3D_SURFACE_RESERVED1) ? " RESERVED1" : "", + (f & SVGA3D_SURFACE_MULTISAMPLE) ? " MULTISAMPLE" : "", + (f & SVGA3D_SURFACE_BIND_UAVIEW) ? " BIND_UAVIEW" : "", + (f & SVGA3D_SURFACE_TRANSFER_TO_BUFFER) ? " TRANSFER_TO_BUFFER" : "", + (f & SVGA3D_SURFACE_BIND_LOGICOPS) ? " BIND_LOGICOPS" : "", + (f & SVGA3D_SURFACE_BIND_RAW_VIEWS) ? " BIND_RAW_VIEWS" : "", + (f & SVGA3D_SURFACE_BUFFER_STRUCTURED) ? " BUFFER_STRUCTURED" : "", + (f & SVGA3D_SURFACE_DRAWINDIRECT_ARGS) ? " DRAWINDIRECT_ARGS" : "", + (f & SVGA3D_SURFACE_RESOURCE_CLAMP) ? " RESOURCE_CLAMP" : "", + (f & SVGA3D_SURFACE_FLAG_MAX) ? " FLAG_MAX" : "", + f & ~(SVGA3D_SURFACE_FLAG_MAX - 1ULL) + )); +#endif + + Assert(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)); + + if (fAllocMipLevels) + { + rc = vmsvga3dSurfaceAllocMipLevels(pSurface); + AssertRCReturn(rc, rc); + } + + pSurface->id = sid; + return VINF_SUCCESS; +} + + +/** + * Implements the SVGA_3D_CMD_SURFACE_DESTROY command (fifo). + * + * @returns VBox status code (currently ignored). + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param sid The ID of the surface to destroy. + */ +int vmsvga3dSurfaceDestroy(PVGASTATECC pThisCC, uint32_t sid) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + + LogFunc(("sid=%u\n", sid)); + + /* Check all contexts if this surface is used as a render target or active texture. */ + for (uint32_t cid = 0; cid < pState->cContexts; cid++) + { + PVMSVGA3DCONTEXT pContext = pState->papContexts[cid]; + if (pContext->id == cid) + { + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); ++i) + if (pContext->aSidActiveTextures[i] == sid) + pContext->aSidActiveTextures[i] = SVGA3D_INVALID_ID; + for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); ++i) + if (pContext->state.aRenderTargets[i] == sid) + pContext->state.aRenderTargets[i] = SVGA3D_INVALID_ID; + } + } + + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + if (pSvgaR3State->pFuncs3D) + pSvgaR3State->pFuncs3D->pfnSurfaceDestroy(pThisCC, true, pSurface); + + if (pSurface->paMipmapLevels) + { + vmsvga3dSurfaceFreeMipLevels(pSurface); + RTMemFree(pSurface->paMipmapLevels); + } + + memset(pSurface, 0, sizeof(*pSurface)); + pSurface->id = SVGA3D_INVALID_ID; + + return VINF_SUCCESS; +} + + +/** + * Implements the SVGA_3D_CMD_SURFACE_STRETCHBLT command (fifo). + * + * @returns VBox status code (currently ignored). + * @param pThis The shared VGA/VMSVGA state. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param pDstSfcImg + * @param pDstBox + * @param pSrcSfcImg + * @param pSrcBox + * @param enmMode + */ +int vmsvga3dSurfaceStretchBlt(PVGASTATE pThis, PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pDstSfcImg, SVGA3dBox const *pDstBox, + SVGA3dSurfaceImageId const *pSrcSfcImg, SVGA3dBox const *pSrcBox, SVGA3dStretchBltMode enmMode) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + int rc; + + uint32_t const sidSrc = pSrcSfcImg->sid; + PVMSVGA3DSURFACE pSrcSurface; + rc = vmsvga3dSurfaceFromSid(pState, sidSrc, &pSrcSurface); + AssertRCReturn(rc, rc); + + uint32_t const sidDst = pDstSfcImg->sid; + PVMSVGA3DSURFACE pDstSurface; + rc = vmsvga3dSurfaceFromSid(pState, sidDst, &pDstSurface); + AssertRCReturn(rc, rc); + + AssertReturn(pSrcSfcImg->face < pSrcSurface->cFaces, VERR_INVALID_PARAMETER); + AssertReturn(pSrcSfcImg->mipmap < pSrcSurface->cLevels, VERR_INVALID_PARAMETER); + AssertReturn(pDstSfcImg->face < pDstSurface->cFaces, VERR_INVALID_PARAMETER); + AssertReturn(pDstSfcImg->mipmap < pDstSurface->cLevels, VERR_INVALID_PARAMETER); + + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED); + + PVMSVGA3DCONTEXT pContext; +#ifdef VMSVGA3D_OPENGL + LogFunc(("src sid=%u (%d,%d)(%d,%d) dest sid=%u (%d,%d)(%d,%d) mode=%x\n", + sidSrc, pSrcBox->x, pSrcBox->y, pSrcBox->x + pSrcBox->w, pSrcBox->y + pSrcBox->h, + sidDst, pDstBox->x, pDstBox->y, pDstBox->x + pDstBox->w, pDstBox->y + pDstBox->h, enmMode)); + pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); +#else + LogFunc(("src sid=%u cid=%u (%d,%d)(%d,%d) dest sid=%u cid=%u (%d,%d)(%d,%d) mode=%x\n", + sidSrc, pSrcSurface->idAssociatedContext, pSrcBox->x, pSrcBox->y, pSrcBox->x + pSrcBox->w, pSrcBox->y + pSrcBox->h, + sidDst, pDstSurface->idAssociatedContext, pDstBox->x, pDstBox->y, pDstBox->x + pDstBox->w, pDstBox->y + pDstBox->h, enmMode)); + + uint32_t cid = pDstSurface->idAssociatedContext; + if (cid == SVGA3D_INVALID_ID) + cid = pSrcSurface->idAssociatedContext; + + /* At least one of surfaces must be in hardware. */ + AssertReturn(cid != SVGA3D_INVALID_ID, VERR_INVALID_PARAMETER); + + rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); +#endif + + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSrcSurface)) + { + /* Unknown surface type; turn it into a texture, which can be used for other purposes too. */ + LogFunc(("unknown src sid=%u type=%d format=%d -> create texture\n", sidSrc, pSrcSurface->f.s.surface1Flags, pSrcSurface->format)); + rc = pSvgaR3State->pFuncs3D->pfnCreateTexture(pThisCC, pContext, pContext->id, pSrcSurface); + AssertRCReturn(rc, rc); + } + + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pDstSurface)) + { + /* Unknown surface type; turn it into a texture, which can be used for other purposes too. */ + LogFunc(("unknown dest sid=%u type=%d format=%d -> create texture\n", sidDst, pDstSurface->f.s.surface1Flags, pDstSurface->format)); + rc = pSvgaR3State->pFuncs3D->pfnCreateTexture(pThisCC, pContext, pContext->id, pDstSurface); + AssertRCReturn(rc, rc); + } + + PVMSVGA3DMIPMAPLEVEL pSrcMipmapLevel; + rc = vmsvga3dMipmapLevel(pSrcSurface, pSrcSfcImg->face, pSrcSfcImg->mipmap, &pSrcMipmapLevel); + AssertRCReturn(rc, rc); + + PVMSVGA3DMIPMAPLEVEL pDstMipmapLevel; + rc = vmsvga3dMipmapLevel(pDstSurface, pDstSfcImg->face, pDstSfcImg->mipmap, &pDstMipmapLevel); + AssertRCReturn(rc, rc); + + SVGA3dBox clipSrcBox = *pSrcBox; + SVGA3dBox clipDstBox = *pDstBox; + vmsvgaR3ClipBox(&pSrcMipmapLevel->mipmapSize, &clipSrcBox); + vmsvgaR3ClipBox(&pDstMipmapLevel->mipmapSize, &clipDstBox); + + return pSvgaR3State->pFuncs3D->pfnSurfaceStretchBlt(pThis, pState, + pDstSurface, pDstSfcImg->face, pDstSfcImg->mipmap, &clipDstBox, + pSrcSurface, pSrcSfcImg->face, pSrcSfcImg->mipmap, &clipSrcBox, + enmMode, pContext); +} + +/** + * Implements the SVGA_3D_CMD_SURFACE_DMA command (fifo). + * + * @returns VBox status code (currently ignored). + * @param pThis The shared VGA/VMSVGA instance data. + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param guest . + * @param host . + * @param transfer . + * @param cCopyBoxes . + * @param paBoxes . + */ +int vmsvga3dSurfaceDMA(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAGuestImage guest, SVGA3dSurfaceImageId host, + SVGA3dTransferType transfer, uint32_t cCopyBoxes, SVGA3dCopyBox *paBoxes) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, host.sid, &pSurface); + AssertRCReturn(rc, rc); + + LogFunc(("%sguestptr gmr=%x offset=%x pitch=%x host sid=%u face=%d mipmap=%d transfer=%s cCopyBoxes=%d\n", + (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_TEXTURE) ? "TEXTURE " : "", + guest.ptr.gmrId, guest.ptr.offset, guest.pitch, + host.sid, host.face, host.mipmap, (transfer == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", cCopyBoxes)); + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, host.face, host.mipmap, &pMipLevel); + AssertRCReturn(rc, rc); + + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED); + + PVMSVGA3DCONTEXT pContext = NULL; + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + /* + * Not realized in host hardware/library yet, we have to work with + * the copy of the data we've got in VMSVGA3DMIMAPLEVEL::pSurfaceData. + */ + if (!pMipLevel->pSurfaceData) + { + rc = vmsvga3dSurfaceAllocMipLevels(pSurface); + AssertRCReturn(rc, rc); + } + } + else if (vmsvga3dIsLegacyBackend(pThisCC)) + { +#ifdef VMSVGA3D_DIRECT3D + /* Flush the drawing pipeline for this surface as it could be used in a shared context. */ + vmsvga3dSurfaceFlush(pSurface); +#else /* VMSVGA3D_OPENGL */ + pContext = &pState->SharedCtx; + VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext); +#endif + } + + /* SVGA_3D_CMD_SURFACE_DMA: + * "define the 'source' in each copyBox as the guest image and the + * 'destination' as the host image, regardless of transfer direction." + */ + for (uint32_t i = 0; i < cCopyBoxes; ++i) + { + Log(("Copy box (%s) %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n", + VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface) ? "hw" : "mem", + i, paBoxes[i].srcx, paBoxes[i].srcy, paBoxes[i].srcz, paBoxes[i].w, paBoxes[i].h, paBoxes[i].d, paBoxes[i].x, paBoxes[i].y)); + + /* Apparently we're supposed to clip it (gmr test sample) */ + + /* The copybox's "dest" is coords in the host surface. Verify them against the surface's mipmap size. */ + SVGA3dBox hostBox; + hostBox.x = paBoxes[i].x; + hostBox.y = paBoxes[i].y; + hostBox.z = paBoxes[i].z; + hostBox.w = paBoxes[i].w; + hostBox.h = paBoxes[i].h; + hostBox.d = paBoxes[i].d; + vmsvgaR3ClipBox(&pMipLevel->mipmapSize, &hostBox); + + if ( !hostBox.w + || !hostBox.h + || !hostBox.d) + { + Log(("Skip empty box\n")); + continue; + } + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* Adjust the guest, i.e. "src", point. + * Do not try to verify them here because vmsvgaR3GmrTransfer takes care of this. + */ + uint32_t const srcx = paBoxes[i].srcx + (hostBox.x - paBoxes[i].x); + uint32_t const srcy = paBoxes[i].srcy + (hostBox.y - paBoxes[i].y); + uint32_t const srcz = paBoxes[i].srcz + (hostBox.z - paBoxes[i].z); + + /* Calculate offsets of the image blocks for the transfer. */ + uint32_t u32HostBlockX; + uint32_t u32HostBlockY; + uint32_t u32GuestBlockX; + uint32_t u32GuestBlockY; + uint32_t cBlocksX; + uint32_t cBlocksY; + if (RT_LIKELY(pSurface->cxBlock == 1 && pSurface->cyBlock == 1)) + { + u32HostBlockX = hostBox.x; + u32HostBlockY = hostBox.y; + + u32GuestBlockX = srcx; + u32GuestBlockY = srcy; + + cBlocksX = hostBox.w; + cBlocksY = hostBox.h; + } + else + { + /* Pixels to blocks. */ + u32HostBlockX = hostBox.x / pSurface->cxBlock; + u32HostBlockY = hostBox.y / pSurface->cyBlock; + Assert(u32HostBlockX * pSurface->cxBlock == hostBox.x); + Assert(u32HostBlockY * pSurface->cyBlock == hostBox.y); + + u32GuestBlockX = srcx / pSurface->cxBlock; + u32GuestBlockY = srcy / pSurface->cyBlock; + Assert(u32GuestBlockX * pSurface->cxBlock == srcx); + Assert(u32GuestBlockY * pSurface->cyBlock == srcy); + + cBlocksX = (hostBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock; + cBlocksY = (hostBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock; + } + + uint32_t cbGuestPitch = guest.pitch; + if (cbGuestPitch == 0) + { + /* Host must "assume image is tightly packed". Our surfaces are. */ + cbGuestPitch = pMipLevel->cbSurfacePitch; + } + else + { + /* vmsvgaR3GmrTransfer will verify the value, just check it is sane. */ + AssertReturn(cbGuestPitch <= SVGA3D_MAX_SURFACE_MEM_SIZE, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + } + + /* srcx, srcy and srcz values are used to calculate the guest offset. + * The offset will be verified by vmsvgaR3GmrTransfer, so just check for overflows here. + */ + AssertReturn(srcz < UINT32_MAX / pMipLevel->mipmapSize.height / cbGuestPitch, VERR_INVALID_PARAMETER); + AssertReturn(u32GuestBlockY < UINT32_MAX / cbGuestPitch, VERR_INVALID_PARAMETER); + AssertReturn(u32GuestBlockX < UINT32_MAX / pSurface->cbBlock, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + if ( !VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface) + || VMSVGA3DSURFACE_NEEDS_DATA(pSurface)) + { + uint64_t uGuestOffset = u32GuestBlockX * pSurface->cbBlock + + u32GuestBlockY * cbGuestPitch + + srcz * pMipLevel->mipmapSize.height * cbGuestPitch; + AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER); + + /* vmsvga3dSurfaceDefine verifies the surface dimensions and clipBox is within them. */ + uint32_t uHostOffset = u32HostBlockX * pSurface->cbBlock + + u32HostBlockY * pMipLevel->cbSurfacePitch + + hostBox.z * pMipLevel->cbSurfacePlane; + AssertReturn(uHostOffset < pMipLevel->cbSurface, VERR_INTERNAL_ERROR); + + for (uint32_t z = 0; z < hostBox.d; ++z) + { + rc = vmsvgaR3GmrTransfer(pThis, + pThisCC, + transfer, + (uint8_t *)pMipLevel->pSurfaceData, + pMipLevel->cbSurface, + uHostOffset, + (int32_t)pMipLevel->cbSurfacePitch, + guest.ptr, + (uint32_t)uGuestOffset, + cbGuestPitch, + cBlocksX * pSurface->cbBlock, + cBlocksY); + AssertRC(rc); + + Log4(("first line [z=%d] (updated at offset 0x%x):\n%.*Rhxd\n", + z, uHostOffset, pMipLevel->cbSurfacePitch, pMipLevel->pSurfaceData)); + + uHostOffset += pMipLevel->cbSurfacePlane; + uGuestOffset += pMipLevel->mipmapSize.height * cbGuestPitch; + AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER); + } + } + + if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + SVGA3dCopyBox clipBox; + clipBox.x = hostBox.x; + clipBox.y = hostBox.y; + clipBox.z = hostBox.z; + clipBox.w = hostBox.w; + clipBox.h = hostBox.h; + clipBox.d = hostBox.d; + clipBox.srcx = srcx; + clipBox.srcy = srcy; + clipBox.srcz = srcz; + rc = pSvgaR3State->pFuncs3D->pfnSurfaceDMACopyBox(pThis, pThisCC, pState, pSurface, pMipLevel, host.face, host.mipmap, + guest.ptr, cbGuestPitch, transfer, + &clipBox, pContext, rc, i); + AssertRC(rc); + } + } + + if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + pMipLevel->fDirty = true; + pSurface->fDirty = true; + } + + return rc; +} + +static int vmsvga3dQueryWriteResult(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAGuestPtr const *pGuestResult, + SVGA3dQueryState enmState, uint32_t u32Result) +{ + SVGA3dQueryResult queryResult; + queryResult.totalSize = sizeof(queryResult); /* Set by guest before query is ended. */ + queryResult.state = enmState; /* Set by host or guest. See SVGA3dQueryState. */ + queryResult.result32 = u32Result; + + int rc = vmsvgaR3GmrTransfer(pThis, pThisCC, SVGA3D_READ_HOST_VRAM, + (uint8_t *)&queryResult, sizeof(queryResult), 0, sizeof(queryResult), + *pGuestResult, 0, sizeof(queryResult), sizeof(queryResult), 1); + AssertRC(rc); + return rc; +} + +/* Used with saved state. */ +int vmsvga3dQueryCreate(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("cid=%u type=%d\n", cid, type)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + if (type == SVGA3D_QUERYTYPE_OCCLUSION) + { + VMSVGA3DQUERY *p = &pContext->occlusion; + if (!VMSVGA3DQUERY_EXISTS(p)) + { + rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryCreate(pThisCC, pContext); + AssertRCReturn(rc, rc); + } + + return VINF_SUCCESS; + } + + /* Nothing else for VGPU9. */ + AssertFailedReturn(VERR_NOT_IMPLEMENTED); +} + +int vmsvga3dQueryBegin(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("cid=%u type=%d\n", cid, type)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + if (type == SVGA3D_QUERYTYPE_OCCLUSION) + { + VMSVGA3DQUERY *p = &pContext->occlusion; + if (!VMSVGA3DQUERY_EXISTS(p)) + { + /* Lazy creation of the query object. */ + rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryCreate(pThisCC, pContext); + AssertRCReturn(rc, rc); + } + + rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryBegin(pThisCC, pContext); + AssertRCReturn(rc, rc); + + p->enmQueryState = VMSVGA3DQUERYSTATE_BUILDING; + p->u32QueryResult = 0; + + return VINF_SUCCESS; + } + + /* Nothing else for VGPU9. */ + AssertFailedReturn(VERR_NOT_IMPLEMENTED); +} + +int vmsvga3dQueryEnd(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("cid=%u type=%d\n", cid, type)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + if (type == SVGA3D_QUERYTYPE_OCCLUSION) + { + VMSVGA3DQUERY *p = &pContext->occlusion; + Assert(p->enmQueryState == VMSVGA3DQUERYSTATE_BUILDING); + AssertMsgReturn(VMSVGA3DQUERY_EXISTS(p), ("Query is NULL\n"), VERR_INTERNAL_ERROR); + + rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryEnd(pThisCC, pContext); + AssertRCReturn(rc, rc); + + p->enmQueryState = VMSVGA3DQUERYSTATE_ISSUED; + return VINF_SUCCESS; + } + + /* Nothing else for VGPU9. */ + AssertFailedReturn(VERR_NOT_IMPLEMENTED); +} + +int vmsvga3dQueryWait(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type, PVGASTATE pThis, SVGAGuestPtr const *pGuestResult) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + LogFunc(("cid=%u type=%d guestResult GMR%d:0x%x\n", cid, type, pGuestResult->gmrId, pGuestResult->offset)); + + PVMSVGA3DCONTEXT pContext; + int rc = vmsvga3dContextFromCid(pState, cid, &pContext); + AssertRCReturn(rc, rc); + + if (type == SVGA3D_QUERYTYPE_OCCLUSION) + { + VMSVGA3DQUERY *p = &pContext->occlusion; + if (VMSVGA3DQUERY_EXISTS(p)) + { + if (p->enmQueryState == VMSVGA3DQUERYSTATE_ISSUED) + { + /* Only if not already in SIGNALED state, + * i.e. not a second read from the guest or after restoring saved state. + */ + uint32_t u32Pixels = 0; + rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryGetData(pThisCC, pContext, &u32Pixels); + if (RT_SUCCESS(rc)) + { + p->enmQueryState = VMSVGA3DQUERYSTATE_SIGNALED; + p->u32QueryResult += u32Pixels; /* += because it might contain partial result from saved state. */ + } + } + + if (RT_SUCCESS(rc)) + { + /* pGuestResult can be NULL when saving the state. */ + if (pGuestResult) + { + /* Return data to the guest. */ + vmsvga3dQueryWriteResult(pThis, pThisCC, pGuestResult, SVGA3D_QUERYSTATE_SUCCEEDED, p->u32QueryResult); + } + return VINF_SUCCESS; + } + } + else + { + AssertMsgFailed(("GetData Query is NULL\n")); + } + + rc = VERR_INTERNAL_ERROR; + } + else + { + rc = VERR_NOT_IMPLEMENTED; + } + + if (pGuestResult) + vmsvga3dQueryWriteResult(pThis, pThisCC, pGuestResult, SVGA3D_QUERYSTATE_FAILED, 0); + AssertFailedReturn(rc); +} + +int vmsvga3dSurfaceBlitToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t idDstScreen, SVGASignedRect destRect, + SVGA3dSurfaceImageId srcImage, SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *pRect) +{ + /* Requires SVGA_FIFO_CAP_SCREEN_OBJECT support */ + LogFunc(("dest=%d (%d,%d)(%d,%d) sid=%u (face=%d, mipmap=%d) (%d,%d)(%d,%d) cRects=%d\n", + idDstScreen, destRect.left, destRect.top, destRect.right, destRect.bottom, srcImage.sid, srcImage.face, srcImage.mipmap, + srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, cRects)); + for (uint32_t i = 0; i < cRects; i++) + { + LogFunc(("clipping rect[%d] (%d,%d)(%d,%d)\n", i, pRect[i].left, pRect[i].top, pRect[i].right, pRect[i].bottom)); + } + + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idDstScreen); + AssertReturn(pScreen, VERR_INTERNAL_ERROR); + + /* vmwgfx driver does not always initialize srcImage.mipmap and srcImage.face. They are assumed to be zero. */ + SVGA3dSurfaceImageId src; + src.sid = srcImage.sid; + src.mipmap = 0; + src.face = 0; + + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + if (pScreen->pHwScreen) + { + /* Use the backend accelerated method, if available. */ + if (pSvgaR3State->pFuncs3D) + { + int rc = pSvgaR3State->pFuncs3D->pfnSurfaceBlitToScreen(pThisCC, pScreen, destRect, src, srcRect, cRects, pRect); + if (rc == VINF_SUCCESS) + { + return VINF_SUCCESS; + } + } + } + + if (pSvgaR3State->pFuncsMap) + return vmsvga3dScreenUpdate(pThisCC, idDstScreen, destRect, src, srcRect, cRects, pRect); + + /** @todo scaling */ + AssertReturn(destRect.right - destRect.left == srcRect.right - srcRect.left && destRect.bottom - destRect.top == srcRect.bottom - srcRect.top, VERR_INVALID_PARAMETER); + + SVGA3dCopyBox box; + SVGAGuestImage dest; + + box.srcz = 0; + box.z = 0; + box.d = 1; + + dest.ptr.gmrId = SVGA_GMR_FRAMEBUFFER; + dest.ptr.offset = pScreen->offVRAM; + dest.pitch = pScreen->cbPitch; + + if (cRects == 0) + { + /* easy case; no clipping */ + + /* SVGA_3D_CMD_SURFACE_DMA: + * 'define the "source" in each copyBox as the guest image and the + * "destination" as the host image, regardless of transfer direction.' + * + * Since the BlitToScreen operation transfers from a host surface to the guest VRAM, + * it must set the copyBox "source" to the guest destination coords and + * the copyBox "destination" to the host surface source coords. + */ + /* Host image. */ + box.x = srcRect.left; + box.y = srcRect.top; + box.w = srcRect.right - srcRect.left; + box.h = srcRect.bottom - srcRect.top; + /* Guest image. */ + box.srcx = destRect.left; + box.srcy = destRect.top; + + int rc = vmsvga3dSurfaceDMA(pThis, pThisCC, dest, src, SVGA3D_READ_HOST_VRAM, 1, &box); + AssertRCReturn(rc, rc); + + /* Update the guest image, which is at box.src. */ + vmsvgaR3UpdateScreen(pThisCC, pScreen, box.srcx, box.srcy, box.w, box.h); + } + else + { + /** @todo merge into one SurfaceDMA call */ + for (uint32_t i = 0; i < cRects; i++) + { + /* "The clip rectangle coordinates are measured + * relative to the top-left corner of destRect." + * Therefore they are relative to the top-left corner of srcRect as well. + */ + + /* Host image. See 'SVGA_3D_CMD_SURFACE_DMA:' comment in the 'if' branch. */ + box.x = srcRect.left + pRect[i].left; + box.y = srcRect.top + pRect[i].top; + box.w = pRect[i].right - pRect[i].left; + box.h = pRect[i].bottom - pRect[i].top; + /* Guest image. The target screen memory is currently in the guest VRAM. */ + box.srcx = destRect.left + pRect[i].left; + box.srcy = destRect.top + pRect[i].top; + + int rc = vmsvga3dSurfaceDMA(pThis, pThisCC, dest, src, SVGA3D_READ_HOST_VRAM, 1, &box); + AssertRCReturn(rc, rc); + + /* Update the guest image, which is at box.src. */ + vmsvgaR3UpdateScreen(pThisCC, pScreen, box.srcx, box.srcy, box.w, box.h); + } + } + + return VINF_SUCCESS; +} + +int vmsvga3dScreenUpdate(PVGASTATECC pThisCC, uint32_t idDstScreen, SVGASignedRect const &dstRect, + SVGA3dSurfaceImageId const &srcImage, SVGASignedRect const &srcRect, + uint32_t cDstClipRects, SVGASignedRect *paDstClipRect) +{ + //DEBUG_BREAKPOINT_TEST(); + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + +#ifdef LOG_ENABLED + LogFunc(("[%u] %d,%d %d,%d (%dx%d) -> %d,%d %d,%d (%dx%d), %u clip rects\n", + idDstScreen, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, + srcRect.right - srcRect.left, srcRect.bottom - srcRect.top, + dstRect.left, dstRect.top, dstRect.right, dstRect.bottom, + dstRect.right - dstRect.left, dstRect.bottom - dstRect.top, cDstClipRects)); + for (uint32_t i = 0; i < cDstClipRects; i++) + { + LogFunc((" [%u] %d,%d %d,%d (%dx%d)\n", + i, paDstClipRect[i].left, paDstClipRect[i].top, paDstClipRect[i].right, paDstClipRect[i].bottom, + paDstClipRect[i].right - paDstClipRect[i].left, paDstClipRect[i].bottom - paDstClipRect[i].top)); + } +#endif + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, srcImage.sid, &pSurface); + AssertRCReturn(rc, rc); + + /* Update the screen from a surface. */ + ASSERT_GUEST_RETURN(idDstScreen < RT_ELEMENTS(pSvgaR3State->aScreens), VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[idDstScreen]; + + uint32_t const cbScreenPixel = (pScreen->cBpp + 7) / 8; + ASSERT_GUEST_RETURN(cbScreenPixel == pSurface->cbBlock, + VERR_INVALID_PARAMETER); /* Format conversion is not supported. */ + + if ( srcRect.right <= srcRect.left + || srcRect.bottom <= srcRect.top) + return VINF_SUCCESS; /* Empty src rect. */ + + if ( dstRect.right <= dstRect.left + || dstRect.bottom <= dstRect.top) + return VINF_SUCCESS; /* Empty dst rect. */ + RT_UNTRUSTED_VALIDATED_FENCE(); + + ASSERT_GUEST_RETURN( srcRect.right - srcRect.left == dstRect.right - dstRect.left + && srcRect.bottom - srcRect.top == dstRect.bottom - dstRect.top, + VERR_INVALID_PARAMETER); /* Stretch is not supported. */ + + /* Destination box should be within the screen rectangle. */ + SVGA3dBox dstBox; + dstBox.x = dstRect.left; + dstBox.y = dstRect.top; + dstBox.z = 0; + dstBox.w = dstRect.right - dstRect.left; + dstBox.h = dstRect.bottom - dstRect.top; + dstBox.d = 1; + + SVGA3dSize dstClippingSize; + dstClippingSize.width = pScreen->cWidth; + dstClippingSize.height = pScreen->cHeight; + dstClippingSize.depth = 1; + + vmsvgaR3ClipBox(&dstClippingSize, &dstBox); + ASSERT_GUEST_RETURN(dstBox.w > 0 && dstBox.h > 0, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* All dst clip rects will be clipped by the dst box because + * "The clip rectangle coordinates are measured relative to the top-left corner of destRect." + */ + dstClippingSize.width = dstBox.w; + dstClippingSize.height = dstBox.h; + dstClippingSize.depth = 1; + + SVGA3dBox srcBox; /* SurfaceMap will clip the box as necessary (srcMap.box). */ + srcBox.x = srcRect.left; + srcBox.y = srcRect.top; + srcBox.z = 0; + srcBox.w = srcRect.right - srcRect.left; + srcBox.h = srcRect.bottom - srcRect.top; + srcBox.d = 1; + + VMSVGA3D_MAPPED_SURFACE srcMap; + rc = vmsvga3dSurfaceMap(pThisCC, &srcImage, &srcBox, VMSVGA3D_SURFACE_MAP_READ, &srcMap); + if (RT_SUCCESS(rc)) + { + /* Clipping rectangle. */ + SVGASignedRect srcBoundRect; + srcBoundRect.left = srcMap.box.x; + srcBoundRect.top = srcMap.box.y; + srcBoundRect.right = srcMap.box.x + srcMap.box.w; + srcBoundRect.bottom = srcMap.box.y + srcMap.box.h; + + /* Clipping rectangle relative to the original srcRect. */ + srcBoundRect.left -= srcRect.left; + srcBoundRect.top -= srcRect.top; + srcBoundRect.right -= srcRect.left; + srcBoundRect.bottom -= srcRect.top; + + uint8_t const *pu8Src = (uint8_t *)srcMap.pvData; + + uint32_t const cbDst = pScreen->cHeight * pScreen->cbPitch; + uint8_t *pu8Dst; + if (pScreen->pvScreenBitmap) + pu8Dst = (uint8_t *)pScreen->pvScreenBitmap; + else + pu8Dst = (uint8_t *)pThisCC->pbVRam + pScreen->offVRAM; + + SVGASignedRect dstClipRect; + if (cDstClipRects == 0) + { + /* Entire source rect "relative to the top-left corner of destRect." */ + dstClipRect.left = 0; + dstClipRect.top = 0; + dstClipRect.right = dstBox.w; + dstClipRect.bottom = dstBox.h; + + cDstClipRects = 1; + paDstClipRect = &dstClipRect; + } + + for (uint32_t i = 0; i < cDstClipRects; i++) + { + /* Clip rects are relative to corners of src and dst rectangles. */ + SVGASignedRect clipRect = paDstClipRect[i]; + + /* Clip the rectangle by mapped source box. */ + vmsvgaR3ClipRect(&srcBoundRect, &clipRect); + + SVGA3dBox clipBox; + clipBox.x = clipRect.left; + clipBox.y = clipRect.top; + clipBox.z = 0; + clipBox.w = clipRect.right - clipRect.left; + clipBox.h = clipRect.bottom - clipRect.top; + clipBox.d = 1; + + vmsvgaR3ClipBox(&dstClippingSize, &clipBox); + ASSERT_GUEST_CONTINUE(clipBox.w > 0 && clipBox.h > 0); + + /* 'pu8Src' points to the mapped 'srcRect'. Take the clipping box into account. */ + uint8_t const *pu8SrcBox = pu8Src + + ((clipBox.x + pSurface->cxBlock - 1) / pSurface->cxBlock) * pSurface->cxBlock * pSurface->cbBlock + + ((clipBox.y + pSurface->cyBlock - 1) / pSurface->cyBlock) * pSurface->cyBlock * srcMap.cbRowPitch; + + /* Calculate the offset of destination box in the screen buffer. */ + uint32_t const offDstBox = (dstBox.x + clipBox.x) * cbScreenPixel + (dstBox.y + clipBox.y) * pScreen->cbPitch; + + ASSERT_GUEST_BREAK( offDstBox <= cbDst + && pScreen->cbPitch * (clipBox.h - 1) + cbScreenPixel * clipBox.w <= cbDst - offDstBox); + RT_UNTRUSTED_VALIDATED_FENCE(); + + uint8_t *pu8DstBox = pu8Dst + offDstBox; + + if ( pSurface->format == SVGA3D_R8G8B8A8_UNORM + || pSurface->format == SVGA3D_R8G8B8A8_UNORM_SRGB) + { + for (uint32_t iRow = 0; iRow < clipBox.h; ++iRow) + { + for (uint32_t x = 0; x < clipBox.w * 4; x += 4) /* 'x' is a byte index. */ + { + pu8DstBox[x ] = pu8SrcBox[x + 2]; + pu8DstBox[x + 1] = pu8SrcBox[x + 1]; + pu8DstBox[x + 2] = pu8SrcBox[x ]; + pu8DstBox[x + 3] = pu8SrcBox[x + 3]; + } + + pu8SrcBox += srcMap.cbRowPitch; + pu8DstBox += pScreen->cbPitch; + } + } + else + { + for (uint32_t iRow = 0; iRow < clipBox.h; ++iRow) + { + memcpy(pu8DstBox, pu8SrcBox, cbScreenPixel * clipBox.w); + + pu8SrcBox += srcMap.cbRowPitch; + pu8DstBox += pScreen->cbPitch; + } + } + } + + vmsvga3dSurfaceUnmap(pThisCC, &srcImage, &srcMap, /* fWritten = */ false); + + vmsvgaR3UpdateScreen(pThisCC, pScreen, dstBox.x, dstBox.y, dstBox.w, dstBox.h); + } + + return rc; +} + +int vmsvga3dCommandPresent(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid, uint32_t cRects, SVGA3dCopyRect *pRect) +{ + /* Deprecated according to svga3d_reg.h. */ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_NO_MEMORY); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + + /** @todo Detect screen from coords? Or split rect to screens? */ + VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0); + AssertReturn(pScreen, VERR_INTERNAL_ERROR); + + /* If there are no recangles specified, just grab a screenful. */ + SVGA3dCopyRect DummyRect; + if (cRects != 0) + { /* likely */ } + else + { + /** @todo Find the usecase for this or check what the original device does. + * The original code was doing some scaling based on the surface + * size... */ + AssertMsgFailed(("No rects to present. Who is doing that and what do they actually expect?\n")); + DummyRect.x = DummyRect.srcx = 0; + DummyRect.y = DummyRect.srcy = 0; + DummyRect.w = pScreen->cWidth; + DummyRect.h = pScreen->cHeight; + cRects = 1; + pRect = &DummyRect; + } + + uint32_t i; + for (i = 0; i < cRects; ++i) + { + uint32_t idDstScreen = 0; /** @todo Use virtual coords: SVGA_ID_INVALID. */ + SVGASignedRect destRect; + destRect.left = pRect[i].x; + destRect.top = pRect[i].y; + destRect.right = pRect[i].x + pRect[i].w; + destRect.bottom = pRect[i].y + pRect[i].h; + + SVGA3dSurfaceImageId src; + src.sid = sid; + src.face = 0; + src.mipmap = 0; + + SVGASignedRect srcRect; + srcRect.left = pRect[i].srcx; + srcRect.top = pRect[i].srcy; + srcRect.right = pRect[i].srcx + pRect[i].w; + srcRect.bottom = pRect[i].srcy + pRect[i].h; + + /* Entire rect. */ + rc = vmsvga3dSurfaceBlitToScreen(pThis, pThisCC, idDstScreen, destRect, src, srcRect, 0, NULL); + AssertRCReturn(rc, rc); + } + + return VINF_SUCCESS; +} + +int vmsvga3dDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED); + + if (pScreen->pHwScreen) + { + pSvgaR3State->pFuncs3D->pfnDestroyScreen(pThisCC, pScreen); + } + + int rc = pSvgaR3State->pFuncs3D->pfnDefineScreen(pThis, pThisCC, pScreen); + if (RT_SUCCESS(rc)) + { + LogRelMax(1, ("VMSVGA: using accelerated graphics output\n")); + } + return rc; +} + +int vmsvga3dDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED); + + return pSvgaR3State->pFuncs3D->pfnDestroyScreen(pThisCC, pScreen); +} + +int vmsvga3dSurfaceInvalidate(PVGASTATECC pThisCC, uint32_t sid, uint32_t face, uint32_t mipmap) +{ + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturn(pState, VERR_INVALID_STATE); + + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); + AssertRCReturn(rc, rc); + + if (face == SVGA_ID_INVALID && mipmap == SVGA_ID_INVALID) + { + /* This is a notification that "All images can be lost", i.e. the backend surface is not needed anymore. */ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + if (pSvgaR3State->pFuncs3D) + pSvgaR3State->pFuncs3D->pfnSurfaceDestroy(pThisCC, false, pSurface); + + for (uint32_t i = 0; i < pSurface->cLevels * pSurface->surfaceDesc.numArrayElements; ++i) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i]; + pMipmapLevel->fDirty = true; + } + } + else + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel; + rc = vmsvga3dMipmapLevel(pSurface, face, mipmap, &pMipmapLevel); + AssertRCReturn(rc, rc); + + /* Invalidate views, etc. */ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + if (pSvgaR3State->pFuncs3D) + pSvgaR3State->pFuncs3D->pfnSurfaceInvalidateImage(pThisCC, pSurface, face, mipmap); + + pMipmapLevel->fDirty = true; + } + pSurface->fDirty = true; + + return rc; +} + + +/* + * + * 3D + * + */ + +int vmsvga3dQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncs3D->pfnQueryCaps(pThisCC, idx3dCaps, pu32Val); +} + +int vmsvga3dChangeMode(PVGASTATECC pThisCC) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncs3D->pfnChangeMode(pThisCC); +} + +int vmsvga3dSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src, uint32_t cCopyBoxes, SVGA3dCopyBox *pBox) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncs3D->pfnSurfaceCopy(pThisCC, dest, src, cCopyBoxes, pBox); +} + +void vmsvga3dUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturnVoid(pSvgaR3State->pFuncs3D); + pSvgaR3State->pFuncs3D->pfnUpdateHostScreenViewport(pThisCC, idScreen, pOldViewport); +} + +/** + * Updates the heap buffers for all surfaces or one specific one. + * + * @param pThisCC The VGA/VMSVGA state for ring-3. + * @param sid The surface ID, UINT32_MAX if all. + * @thread VMSVGAFIFO + */ +void vmsvga3dUpdateHeapBuffersForSurfaces(PVGASTATECC pThisCC, uint32_t sid) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturnVoid(pSvgaR3State->pFuncs3D); + + PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; + AssertReturnVoid(pState); + + if (sid == UINT32_MAX) + { + uint32_t cSurfaces = pState->cSurfaces; + for (sid = 0; sid < cSurfaces; sid++) + { + PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; + if (pSurface && pSurface->id == sid) + pSvgaR3State->pFuncs3D->pfnSurfaceUpdateHeapBuffers(pThisCC, pSurface); + } + } + else if (sid < pState->cSurfaces) + { + PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; + if (pSurface && pSurface->id == sid) + pSvgaR3State->pFuncs3D->pfnSurfaceUpdateHeapBuffers(pThisCC, pSurface); + } +} + + +/* + * + * VGPU9 + * + */ + +int vmsvga3dContextDefine(PVGASTATECC pThisCC, uint32_t cid) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnContextDefine(pThisCC, cid); +} + +int vmsvga3dContextDestroy(PVGASTATECC pThisCC, uint32_t cid) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnContextDestroy(pThisCC, cid); +} + +int vmsvga3dSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16]) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetTransform(pThisCC, cid, type, matrix); +} + +int vmsvga3dSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetZRange(pThisCC, cid, zRange); +} + +int vmsvga3dSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetRenderState(pThisCC, cid, cRenderStates, pRenderState); +} + +int vmsvga3dSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetRenderTarget(pThisCC, cid, type, target); +} + +int vmsvga3dSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetTextureState(pThisCC, cid, cTextureStates, pTextureState); +} + +int vmsvga3dSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetMaterial(pThisCC, cid, face, pMaterial); +} + +int vmsvga3dSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetLightData(pThisCC, cid, index, pData); +} + +int vmsvga3dSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetLightEnabled(pThisCC, cid, index, enabled); +} + +int vmsvga3dSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetViewPort(pThisCC, cid, pRect); +} + +int vmsvga3dSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetClipPlane(pThisCC, cid, index, plane); +} + +int vmsvga3dCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil, uint32_t cRects, SVGA3dRect *pRect) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnCommandClear(pThisCC, cid, clearFlag, color, depth, stencil, cRects, pRect); +} + +int vmsvga3dDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, uint32_t numRanges, SVGA3dPrimitiveRange *pNumRange, uint32_t cVertexDivisor, SVGA3dVertexDivisor *pVertexDivisor) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnDrawPrimitives(pThisCC, cid, numVertexDecls, pVertexDecl, numRanges, pNumRange, cVertexDivisor, pVertexDivisor); +} + +int vmsvga3dSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnSetScissorRect(pThisCC, cid, pRect); +} + +int vmsvga3dGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnGenerateMipmaps(pThisCC, sid, filter); +} + +int vmsvga3dShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnShaderDefine(pThisCC, cid, shid, type, cbData, pShaderData); +} + +int vmsvga3dShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnShaderDestroy(pThisCC, cid, shid, type); +} + +int vmsvga3dShaderSet(PVGASTATECC pThisCC, struct VMSVGA3DCONTEXT *pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnShaderSet(pThisCC, pContext, cid, type, shid); +} + +int vmsvga3dShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsVGPU9->pfnShaderSetConst(pThisCC, cid, reg, type, ctype, cRegisters, pValues); +} + + +/* + * + * Map + * + */ + +void vmsvga3dSurfaceMapInit(VMSVGA3D_MAPPED_SURFACE *pMap, VMSVGA3D_SURFACE_MAP enmMapType, SVGA3dBox const *pBox, + PVMSVGA3DSURFACE pSurface, void *pvData, uint32_t cbRowPitch, uint32_t cbDepthPitch) +{ + uint32_t const cxBlocks = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock; + uint32_t const cyBlocks = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock; + + pMap->enmMapType = enmMapType; + pMap->format = pSurface->format; + pMap->box = *pBox; + pMap->cbBlock = pSurface->cbBlock; + pMap->cbRow = cxBlocks * pSurface->cbBlock; + pMap->cbRowPitch = cbRowPitch; + pMap->cRows = cyBlocks; + pMap->cbDepthPitch = cbDepthPitch; + pMap->pvData = (uint8_t *)pvData + + (pBox->x / pSurface->cxBlock) * pSurface->cbBlock + + (pBox->y / pSurface->cyBlock) * cbRowPitch + + pBox->z * cbDepthPitch; +} + + +int vmsvga3dSurfaceMap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox, + VMSVGA3D_SURFACE_MAP enmMapType, VMSVGA3D_MAPPED_SURFACE *pMap) +{ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pImage->sid, &pSurface); + AssertRCReturn(rc, rc); + + if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsMap, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsMap->pfnSurfaceMap(pThisCC, pImage, pBox, enmMapType, pMap); + } + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + if (!pMipLevel->pSurfaceData) + { + rc = vmsvga3dSurfaceAllocMipLevels(pSurface); + AssertRCReturn(rc, rc); + } + + SVGA3dBox clipBox; + if (pBox) + { + clipBox = *pBox; + vmsvgaR3ClipBox(&pMipLevel->mipmapSize, &clipBox); + ASSERT_GUEST_RETURN(clipBox.w && clipBox.h && clipBox.d, VERR_INVALID_PARAMETER); + } + else + { + clipBox.x = 0; + clipBox.y = 0; + clipBox.z = 0; + clipBox.w = pMipLevel->mipmapSize.width; + clipBox.h = pMipLevel->mipmapSize.height; + clipBox.d = pMipLevel->mipmapSize.depth; + } + + /// @todo Zero the box? + //if (enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD) + // RT_BZERO(.); + + vmsvga3dSurfaceMapInit(pMap, enmMapType, &clipBox, pSurface, + pMipLevel->pSurfaceData, pMipLevel->cbSurfacePitch, pMipLevel->cbSurfacePlane); + + LogFunc(("SysMem: sid = %u, pvData %p\n", pImage->sid, pMap->pvData)); + return VINF_SUCCESS; +} + +int vmsvga3dSurfaceUnmap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, VMSVGA3D_MAPPED_SURFACE *pMap, bool fWritten) +{ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pImage->sid, &pSurface); + AssertRCReturn(rc, rc); + + if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) + { + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + AssertReturn(pSvgaR3State->pFuncsMap, VERR_NOT_IMPLEMENTED); + return pSvgaR3State->pFuncsMap->pfnSurfaceUnmap(pThisCC, pImage, pMap, fWritten); + } + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + if ( fWritten + && ( pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE + || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ_WRITE + || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD)) + { + pMipLevel->fDirty = true; + pSurface->fDirty = true; + } + + return VINF_SUCCESS; +} + + +int vmsvga3dCalcSurfaceMipmapAndFace(PVGASTATECC pThisCC, uint32_t sid, uint32_t iSubresource, uint32_t *piMipmap, uint32_t *piFace) +{ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + AssertRCReturn(rc, rc); + + vmsvga3dCalcMipmapAndFace(pSurface->cLevels, iSubresource, piMipmap, piFace); + return VINF_SUCCESS; +} + + +uint32_t vmsvga3dCalcSubresourceOffset(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage) +{ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pImage->sid, &pSurface); + AssertRCReturn(rc, 0); + + ASSERT_GUEST_RETURN(pImage->face < pSurface->surfaceDesc.numArrayElements, 0); + + uint32_t offMipLevel = 0; + for (uint32_t i = 0; i < pImage->mipmap; ++i) + { + PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i]; + offMipLevel += pMipmapLevel->cbSurface; + } + + uint32_t offSubresource = pSurface->surfaceDesc.cbArrayElement * pImage->face + offMipLevel; + /** @todo Multisample? */ + return offSubresource; +} + + +uint32_t vmsvga3dGetArrayElements(PVGASTATECC pThisCC, SVGA3dSurfaceId sid) +{ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + AssertRCReturn(rc, 0); + + return pSurface->surfaceDesc.numArrayElements; +} + + +uint32_t vmsvga3dGetSubresourceCount(PVGASTATECC pThisCC, SVGA3dSurfaceId sid) +{ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); + AssertRCReturn(rc, 0); + + return pSurface->surfaceDesc.numArrayElements * pSurface->cLevels; +} + + +/* + * Calculates memory layout of a surface box for memcpy: + */ +int vmsvga3dGetBoxDimensions(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox, + VMSGA3D_BOX_DIMENSIONS *pResult) +{ + PVMSVGA3DSURFACE pSurface; + int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pImage->sid, &pSurface); + AssertRCReturn(rc, rc); + + PVMSVGA3DMIPMAPLEVEL pMipLevel; + rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel); + ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); + + /* Clip the box. */ + SVGA3dBox clipBox; + if (pBox) + { + clipBox = *pBox; + vmsvgaR3ClipBox(&pMipLevel->mipmapSize, &clipBox); + ASSERT_GUEST_RETURN(clipBox.w && clipBox.h && clipBox.d, VERR_INVALID_PARAMETER); + } + else + { + clipBox.x = 0; + clipBox.y = 0; + clipBox.z = 0; + clipBox.w = pMipLevel->mipmapSize.width; + clipBox.h = pMipLevel->mipmapSize.height; + clipBox.d = pMipLevel->mipmapSize.depth; + } + + uint32_t const cBlocksX = (clipBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock; + uint32_t const cBlocksY = (clipBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock; + + pResult->offSubresource = vmsvga3dCalcSubresourceOffset(pThisCC, pImage); + pResult->offBox = (clipBox.x / pSurface->cxBlock) * pSurface->cbBlock + + (clipBox.y / pSurface->cyBlock) * pMipLevel->cbSurfacePitch + + clipBox.z * pMipLevel->cbSurfacePlane; + pResult->cbRow = cBlocksX * pSurface->cbBlock; + pResult->cbPitch = pMipLevel->cbSurfacePitch; + pResult->cyBlocks = cBlocksY; + pResult->cbDepthPitch = pMipLevel->cbSurfacePlane; + + return VINF_SUCCESS; +} + + +/* + * Whether a legacy 3D backend is used. + * The new DX context can be built together with the legacy D3D9 or OpenGL backend. + * The actual backend is selected at the VM startup. + */ +bool vmsvga3dIsLegacyBackend(PVGASTATECC pThisCC) +{ + PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; + return pSvgaR3State->pFuncsDX == NULL; +} + + +void vmsvga3dReset(PVGASTATECC pThisCC) +{ + /* Deal with data from PVMSVGA3DSTATE */ + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + Assert(pThisCC->svga.p3dState); + + if ((pThisCC->svga.p3dState)) + { + /* Destroy all leftover surfaces. */ + for (uint32_t i = 0; i < p3dState->cSurfaces; i++) + { + if (p3dState->papSurfaces[i]->id != SVGA3D_INVALID_ID) + vmsvga3dSurfaceDestroy(pThisCC, p3dState->papSurfaces[i]->id); + RTMemFree(p3dState->papSurfaces[i]); + p3dState->papSurfaces[i] = NULL; + } + RTMemFree(p3dState->papSurfaces); + p3dState->papSurfaces = NULL; + p3dState->cSurfaces = 0; + + /* Destroy all leftover contexts. */ + for (uint32_t i = 0; i < p3dState->cContexts; i++) + { + if (p3dState->papContexts[i]->id != SVGA3D_INVALID_ID) + vmsvga3dContextDestroy(pThisCC, p3dState->papContexts[i]->id); + RTMemFree(p3dState->papContexts[i]); + p3dState->papContexts[i] = NULL; + } + RTMemFree(p3dState->papContexts); + p3dState->papContexts = NULL; + p3dState->cContexts = 0; + + if (!vmsvga3dIsLegacyBackend(pThisCC)) + { + /* Destroy all leftover DX contexts. */ + for (uint32_t i = 0; i < p3dState->cDXContexts; i++) + { + if (p3dState->papDXContexts[i]->cid != SVGA3D_INVALID_ID) + vmsvga3dDXDestroyContext(pThisCC, p3dState->papDXContexts[i]->cid); + RTMemFree(p3dState->papDXContexts[i]); + p3dState->papDXContexts[i] = NULL; + } + RTMemFree(p3dState->papDXContexts); + p3dState->papDXContexts = NULL; + p3dState->cDXContexts = 0; + } + } + + /* Reset the backend. */ + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + if (pSvgaR3State->pFuncs3D && pSvgaR3State->pFuncs3D->pfnReset) + pSvgaR3State->pFuncs3D->pfnReset(pThisCC); +} + + +void vmsvga3dTerminate(PVGASTATECC pThisCC) +{ + /* Clean up backend. */ + vmsvga3dReset(pThisCC); + + /* Deal with data from PVMSVGA3DSTATE */ + PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; + AssertReturnVoid(p3dState); + + /* Terminate the backend. */ + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + if (pSvgaR3State->pFuncs3D && pSvgaR3State->pFuncs3D->pfnTerminate) + pSvgaR3State->pFuncs3D->pfnTerminate(pThisCC); + + RTMemFree(p3dState->pBackend); + p3dState->pBackend = NULL; + + RTMemFree(p3dState); + pThisCC->svga.p3dState = NULL; +} + + +int vmsvga3dInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State; + + /* 3D interface is required. */ + AssertReturn(pSvgaR3State->pFuncs3D && pSvgaR3State->pFuncs3D->pfnInit, VERR_NOT_SUPPORTED); + + PVMSVGA3DSTATE p3dState = (PVMSVGA3DSTATE)RTMemAllocZ(sizeof(VMSVGA3DSTATE)); + AssertReturn(p3dState, VERR_NO_MEMORY); + pThisCC->svga.p3dState = p3dState; + + int rc = pSvgaR3State->pFuncs3D->pfnInit(pDevIns, pThis, pThisCC); + if (RT_SUCCESS(rc)) + return VINF_SUCCESS; + + pThisCC->svga.p3dState = NULL; + RTMemFree(p3dState); + return rc; +} diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h new file mode 100644 index 00000000..86fa4bc2 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h @@ -0,0 +1,686 @@ +/* $Id: DevVGA-SVGA3d.h $ */ +/** @file + * DevVMWare - VMWare SVGA device - 3D part. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include + +#include "DevVGA-SVGA.h" + + +/** Arbitrary limit */ +#define SVGA3D_MAX_SHADER_IDS 0x800 +/** D3D allows up to 8 texture stages. */ +#define SVGA3D_MAX_TEXTURE_STAGES 8 +/** Samplers: 16 Pixel Shader + 1 Displacement Map + 4 Vertex Shader */ +#define SVGA3D_MAX_SAMPLERS_PS 16 +#define SVGA3D_MAX_SAMPLERS_DMAP 1 +#define SVGA3D_MAX_SAMPLERS_VS 4 +#define SVGA3D_MAX_SAMPLERS (SVGA3D_MAX_SAMPLERS_PS + SVGA3D_MAX_SAMPLERS_DMAP + SVGA3D_MAX_SAMPLERS_VS) +/** Arbitrary upper limit; seen 8 so far. */ +#define SVGA3D_MAX_LIGHTS 32 +/** Arbitrary upper limit; 2GB enough for 32768x16384*4. */ +#define SVGA3D_MAX_SURFACE_MEM_SIZE 0x80000000 +/** Arbitrary upper limit. [0,15] is enough for 2^15=32768x32768. */ +#define SVGA3D_MAX_MIP_LEVELS 16 + + +/** @todo Use this as a parameter for vmsvga3dSurfaceDefine and a field in VMSVGA3DSURFACE instead of a multiple values. */ +/* A surface description provided by the guest. Mostly mirrors SVGA3dCmdDefineGBSurface_v4 */ +typedef struct VMSVGA3D_SURFACE_DESC +{ + SVGA3dSurface1Flags surface1Flags; + SVGA3dSurface2Flags surface2Flags; + SVGA3dSurfaceFormat format; + uint32 numMipLevels; + uint32 multisampleCount; + SVGA3dMSPattern multisamplePattern; + SVGA3dMSQualityLevel qualityLevel; + SVGA3dTextureFilter autogenFilter; + SVGA3dSize size; + uint32 numArrayElements; /* "Number of array elements for a 1D/2D texture. For cubemap + * texture number of faces * array_size." + */ + uint32 cbArrayElement; /* Size of one array element. */ + uint32 bufferByteStride; +} VMSVGA3D_SURFACE_DESC; + +typedef enum VMSVGA3D_SURFACE_MAP +{ + VMSVGA3D_SURFACE_MAP_READ, + VMSVGA3D_SURFACE_MAP_WRITE, + VMSVGA3D_SURFACE_MAP_READ_WRITE, + VMSVGA3D_SURFACE_MAP_WRITE_DISCARD, +} VMSVGA3D_SURFACE_MAP; + +typedef struct VMSVGA3D_MAPPED_SURFACE +{ + VMSVGA3D_SURFACE_MAP enmMapType; + SVGA3dSurfaceFormat format; + SVGA3dBox box; + uint32_t cbBlock; /* Size of pixel block, usualy of 1 pixel for uncompressed formats. */ + uint32_t cbRow; /* Bytes per row. */ + uint32_t cbRowPitch; /* Bytes between rows. */ + uint32_t cRows; /* Number of rows. */ + uint32_t cbDepthPitch; /* Bytes between planes. */ + void *pvData; +} VMSVGA3D_MAPPED_SURFACE; + +void vmsvga3dReset(PVGASTATECC pThisCC); +void vmsvga3dTerminate(PVGASTATECC pThisCC); + +int vmsvga3dInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC); + +/* Write render targets to bitmaps. */ +//#define DUMP_BITMAPS +void vmsvga3dMapWriteBmpFile(VMSVGA3D_MAPPED_SURFACE const *pMap, char const *pszPrefix); + +/* DevVGA-SVGA.cpp: */ +void vmsvgaR33dSurfaceUpdateHeapBuffersOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid); + + +/* DevVGA-SVGA3d-ogl.cpp & DevVGA-SVGA3d-win.cpp: */ +int vmsvga3dLoadExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); +int vmsvga3dSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM); +void vmsvga3dUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport); +int vmsvga3dQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val); + +int vmsvga3dSurfaceDefine(PVGASTATECC pThisCC, uint32_t sid, SVGA3dSurfaceAllFlags surfaceFlags, SVGA3dSurfaceFormat format, + uint32_t multisampleCount, SVGA3dTextureFilter autogenFilter, + uint32_t cMipLevels, SVGA3dSize const *pMipLevel0Size, uint32_t arraySize, bool fAllocMipLevels); +int vmsvga3dSurfaceDestroy(PVGASTATECC pThisCC, uint32_t sid); +int vmsvga3dSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src, + uint32_t cCopyBoxes, SVGA3dCopyBox *pBox); +int vmsvga3dSurfaceStretchBlt(PVGASTATE pThis, PVGASTATECC pThisCC, + SVGA3dSurfaceImageId const *pDstSfcImg, SVGA3dBox const *pDstBox, + SVGA3dSurfaceImageId const *pSrcSfcImg, SVGA3dBox const *pSrcBox, SVGA3dStretchBltMode enmMode); +int vmsvga3dSurfaceDMA(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAGuestImage guest, SVGA3dSurfaceImageId host, SVGA3dTransferType transfer, uint32_t cCopyBoxes, SVGA3dCopyBox *pBoxes); +int vmsvga3dSurfaceBlitToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t dest, SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage, SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *pRect); + +int vmsvga3dContextDefine(PVGASTATECC pThisCC, uint32_t cid); +int vmsvga3dContextDestroy(PVGASTATECC pThisCC, uint32_t cid); + +int vmsvga3dChangeMode(PVGASTATECC pThisCC); + +int vmsvga3dDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen); +int vmsvga3dDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen); + +int vmsvga3dScreenUpdate(PVGASTATECC pThisCC, uint32_t idDstScreen, SVGASignedRect const &dstRect, + SVGA3dSurfaceImageId const &srcImage, SVGASignedRect const &srcRect, + uint32_t cDstClipRects, SVGASignedRect *paDstClipRect); + +int vmsvga3dSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16]); +int vmsvga3dSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange); +int vmsvga3dSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState); +int vmsvga3dSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target); +int vmsvga3dSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState); +int vmsvga3dSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial); +int vmsvga3dSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData); +int vmsvga3dSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled); +int vmsvga3dSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect); +int vmsvga3dSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]); +int vmsvga3dCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil, uint32_t cRects, SVGA3dRect *pRect); +int vmsvga3dCommandPresent(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid, uint32_t cRects, SVGA3dCopyRect *pRect); +int vmsvga3dDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, uint32_t numRanges, SVGA3dPrimitiveRange *pNumRange, uint32_t cVertexDivisor, SVGA3dVertexDivisor *pVertexDivisor); +int vmsvga3dSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect); +int vmsvga3dGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter); + +int vmsvga3dShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData); +int vmsvga3dShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type); +int vmsvga3dShaderSet(PVGASTATECC pThisCC, struct VMSVGA3DCONTEXT *pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid); +int vmsvga3dShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues); + +int vmsvga3dQueryCreate(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type); +int vmsvga3dQueryBegin(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type); +int vmsvga3dQueryEnd(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type); +int vmsvga3dQueryWait(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type, PVGASTATE pThis, SVGAGuestPtr const *pGuestResult); + +int vmsvga3dSurfaceInvalidate(PVGASTATECC pThisCC, uint32_t sid, uint32_t face, uint32_t mipmap); + +int vmsvga3dSurfaceMap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox, + VMSVGA3D_SURFACE_MAP enmMapType, VMSVGA3D_MAPPED_SURFACE *pMap); +int vmsvga3dSurfaceUnmap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, VMSVGA3D_MAPPED_SURFACE *pMap, bool fWritten); + +uint32_t vmsvga3dCalcSubresourceOffset(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage); + +typedef struct VMSGA3D_BOX_DIMENSIONS +{ + uint32_t offSubresource; /* Offset of the miplevel. */ + uint32_t offBox; /* Offset of the box in the miplevel. */ + uint32_t cbRow; /* Bytes per row. */ + int32_t cbPitch; /* Bytes between rows. */ + uint32_t cyBlocks; /* Number of rows. */ + uint32_t cbDepthPitch; /* Number of bytes between planes. */ +} VMSGA3D_BOX_DIMENSIONS; + +int vmsvga3dGetBoxDimensions(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox, + VMSGA3D_BOX_DIMENSIONS *pResult); + +DECLINLINE(void) vmsvga3dCalcMipmapSize(SVGA3dSize const *pSize0, uint32_t iMipmap, SVGA3dSize *pSize) +{ + pSize->width = RT_MAX(pSize0->width >> iMipmap, 1); + pSize->height = RT_MAX(pSize0->height >> iMipmap, 1); + pSize->depth = RT_MAX(pSize0->depth >> iMipmap, 1); +} + +uint32_t vmsvga3dGetArrayElements(PVGASTATECC pThisCC, SVGA3dSurfaceId sid); +uint32_t vmsvga3dGetSubresourceCount(PVGASTATECC pThisCC, SVGA3dSurfaceId sid); + +DECLINLINE(uint32_t) vmsvga3dCalcSubresource(uint32_t iMipLevel, uint32_t iArray, uint32_t cMipLevels) +{ + /* Same as in D3D */ + return iMipLevel + iArray * cMipLevels; +} + +DECLINLINE(void) vmsvga3dCalcMipmapAndFace(uint32_t cMipLevels, uint32_t iSubresource, uint32_t *piMipmap, uint32_t *piFace) +{ + if (RT_LIKELY(cMipLevels)) + { + *piFace = iSubresource / cMipLevels; + *piMipmap = iSubresource % cMipLevels; + } + else + { + ASSERT_GUEST_FAILED(); + *piFace = 0; + *piMipmap = 0; + } +} + +int vmsvga3dCalcSurfaceMipmapAndFace(PVGASTATECC pThisCC, uint32_t sid, uint32_t iSubresource, uint32_t *piMipmap, uint32_t *piFace); + + +/* DevVGA-SVGA3d-shared.h: */ +#if defined(RT_OS_WINDOWS) && defined(IN_RING3) +# include + +# define WM_VMSVGA3D_WAKEUP (WM_APP+1) +# define WM_VMSVGA3D_CREATEWINDOW (WM_APP+2) +# define WM_VMSVGA3D_DESTROYWINDOW (WM_APP+3) +# define WM_VMSVGA3D_EXIT (WM_APP+5) +# if 0 +# define WM_VMSVGA3D_CREATE_DEVICE (WM_APP+6) +typedef struct VMSVGA3DCREATEDEVICEPARAMS +{ + struct VMSVGA3DSTATE *pState; + struct VMSVGA3DCONTEXT *pContext; + struct _D3DPRESENT_PARAMETERS_ *pPresParams; + HRESULT hrc; +} VMSVGA3DCREATEDEVICEPARAMS; +# endif + +DECLCALLBACK(int) vmsvga3dWindowThread(RTTHREAD ThreadSelf, void *pvUser); +int vmsvga3dSendThreadMessage(RTTHREAD pWindowThread, RTSEMEVENT WndRequestSem, UINT msg, WPARAM wParam, LPARAM lParam); +int vmsvga3dContextWindowCreate(HINSTANCE hInstance, RTTHREAD pWindowThread, RTSEMEVENT WndRequestSem, HWND *pHwnd); + +#endif + +void vmsvga3dUpdateHeapBuffersForSurfaces(PVGASTATECC pThisCC, uint32_t sid); +void vmsvga3dInfoContextWorker(PVGASTATECC pThisCC, PCDBGFINFOHLP pHlp, uint32_t cid, bool fVerbose); +void vmsvga3dInfoSurfaceWorker(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PCDBGFINFOHLP pHlp, uint32_t sid, + bool fVerbose, uint32_t cxAscii, bool fInvY, const char *pszBitmapPath); + +/* DevVGA-SVGA3d-shared.cpp: */ + +/** + * Structure for use with vmsvga3dInfoU32Flags. + */ +typedef struct VMSVGAINFOFLAGS32 +{ + /** The flags. */ + uint32_t fFlags; + /** The corresponding mnemonic. */ + const char *pszJohnny; +} VMSVGAINFOFLAGS32; +/** Pointer to a read-only flag translation entry. */ +typedef VMSVGAINFOFLAGS32 const *PCVMSVGAINFOFLAGS32; +void vmsvga3dInfoU32Flags(PCDBGFINFOHLP pHlp, uint32_t fFlags, const char *pszPrefix, PCVMSVGAINFOFLAGS32 paFlags, uint32_t cFlags); + +/** + * Structure for use with vmsvgaFormatEnumValueEx and vmsvgaFormatEnumValue. + */ +typedef struct VMSVGAINFOENUM +{ + /** The enum value. */ + int32_t iValue; + /** The corresponding value name. */ + const char *pszName; +} VMSVGAINFOENUM; +/** Pointer to a read-only enum value translation entry. */ +typedef VMSVGAINFOENUM const *PCVMSVGAINFOENUM; +/** + * Structure for use with vmsvgaFormatEnumValueEx and vmsvgaFormatEnumValue. + */ +typedef struct VMSVGAINFOENUMMAP +{ + /** Pointer to the value mapping array. */ + PCVMSVGAINFOENUM paValues; + /** The number of value mappings. */ + size_t cValues; + /** The prefix. */ + const char *pszPrefix; +#ifdef RT_STRICT + /** Indicates whether we've checked that it's sorted or not. */ + bool *pfAsserted; +#endif +} VMSVGAINFOENUMMAP; +typedef VMSVGAINFOENUMMAP const *PCVMSVGAINFOENUMMAP; +/** @def VMSVGAINFOENUMMAP_MAKE + * Macro for defining a VMSVGAINFOENUMMAP, silently dealing with pfAsserted. + * + * @param a_Scope The scope. RT_NOTHING or static. + * @param a_VarName The variable name for this map. + * @param a_aValues The variable name of the value mapping array. + * @param a_pszPrefix The value name prefix. + */ +#ifdef VBOX_STRICT +# define VMSVGAINFOENUMMAP_MAKE(a_Scope, a_VarName, a_aValues, a_pszPrefix) \ + static bool RT_CONCAT(a_VarName,_AssertedSorted) = false; \ + a_Scope VMSVGAINFOENUMMAP const a_VarName = { \ + a_aValues, RT_ELEMENTS(a_aValues), a_pszPrefix, &RT_CONCAT(a_VarName,_AssertedSorted) \ + } +#else +# define VMSVGAINFOENUMMAP_MAKE(a_Scope, a_VarName, a_aValues, a_pszPrefix) \ + a_Scope VMSVGAINFOENUMMAP const a_VarName = { a_aValues, RT_ELEMENTS(a_aValues), a_pszPrefix } +#endif +extern VMSVGAINFOENUMMAP const g_SVGA3dSurfaceFormat2String; +const char *vmsvgaLookupEnum(int32_t iValue, PCVMSVGAINFOENUMMAP pEnumMap); +char *vmsvgaFormatEnumValueEx(char *pszBuffer, size_t cbBuffer, const char *pszName, int32_t iValue, + bool fPrefix, PCVMSVGAINFOENUMMAP pEnumMap); +char *vmsvgaFormatEnumValue(char *pszBuffer, size_t cbBuffer, const char *pszName, uint32_t uValue, + const char *pszPrefix, const char * const *papszValues, size_t cValues); + +/** + * ASCII "art" scanline printer callback. + * + * @param pszLine The line to output. + * @param pvUser The user argument. + */ +typedef DECLCALLBACKTYPE(void, FNVMSVGAASCIIPRINTLN,(const char *pszLine, void *pvUser)); +/** Pointer to an ASCII "art" print line callback. */ +typedef FNVMSVGAASCIIPRINTLN *PFNVMSVGAASCIIPRINTLN; +void vmsvga3dAsciiPrint(PFNVMSVGAASCIIPRINTLN pfnPrintLine, void *pvUser, void const *pvImage, size_t cbImage, + uint32_t cx, uint32_t cy, uint32_t cbScanline, SVGA3dSurfaceFormat enmFormat, bool fInvY, + uint32_t cchMaxX, uint32_t cchMaxY); +DECLCALLBACK(void) vmsvga3dAsciiPrintlnInfo(const char *pszLine, void *pvUser); +DECLCALLBACK(void) vmsvga3dAsciiPrintlnLog(const char *pszLine, void *pvUser); + +char *vmsvga3dFormatRenderState(char *pszBuffer, size_t cbBuffer, SVGA3dRenderState const *pRenderState); +char *vmsvga3dFormatTextureState(char *pszBuffer, size_t cbBuffer, SVGA3dTextureState const *pTextureState); +void vmsvga3dInfoHostWindow(PCDBGFINFOHLP pHlp, uint64_t idHostWindow); + +uint32_t vmsvga3dSurfaceFormatSize(SVGA3dSurfaceFormat format, + uint32_t *pu32BlockWidth, + uint32_t *pu32BlockHeight); + +#ifdef LOG_ENABLED +const char *vmsvga3dGetCapString(uint32_t idxCap); +const char *vmsvga3dGet3dFormatString(uint32_t format); +const char *vmsvga3dGetRenderStateName(uint32_t state); +const char *vmsvga3dTextureStateToString(SVGA3dTextureStateName textureState); +const char *vmsvgaTransformToString(SVGA3dTransformType type); +const char *vmsvgaDeclUsage2String(SVGA3dDeclUsage usage); +const char *vmsvgaDeclType2String(SVGA3dDeclType type); +const char *vmsvgaDeclMethod2String(SVGA3dDeclMethod method); +const char *vmsvgaSurfaceType2String(SVGA3dSurfaceFormat format); +const char *vmsvga3dPrimitiveType2String(SVGA3dPrimitiveType PrimitiveType); +#endif + + +/* + * Backend interfaces. + */ +bool vmsvga3dIsLegacyBackend(PVGASTATECC pThisCC); + +typedef struct VMSVGA3DSURFACE *PVMSVGA3DSURFACE; +typedef struct VMSVGA3DMIPMAPLEVEL *PVMSVGA3DMIPMAPLEVEL; +typedef struct VMSVGA3DCONTEXT *PVMSVGA3DCONTEXT; + +/* Essential 3D backend function. */ +#define VMSVGA3D_BACKEND_INTERFACE_NAME_3D "3D" +typedef struct +{ + DECLCALLBACKMEMBER(int, pfnInit, (PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)); + DECLCALLBACKMEMBER(int, pfnPowerOn, (PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)); + DECLCALLBACKMEMBER(int, pfnTerminate, (PVGASTATECC pThisCC)); + DECLCALLBACKMEMBER(int, pfnReset, (PVGASTATECC pThisCC)); + DECLCALLBACKMEMBER(int, pfnQueryCaps, (PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val)); + DECLCALLBACKMEMBER(int, pfnChangeMode, (PVGASTATECC pThisCC)); + DECLCALLBACKMEMBER(int, pfnCreateTexture, (PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, PVMSVGA3DSURFACE pSurface)); + DECLCALLBACKMEMBER(void, pfnSurfaceDestroy, (PVGASTATECC pThisCC, bool fClearCOTableEntry, PVMSVGA3DSURFACE pSurface)); + DECLCALLBACKMEMBER(void, pfnSurfaceInvalidateImage, (PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface, uint32_t uFace, uint32_t uMipmap)); + DECLCALLBACKMEMBER(int, pfnSurfaceCopy, (PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src, uint32_t cCopyBoxes, SVGA3dCopyBox *pBox)); + DECLCALLBACKMEMBER(int, pfnSurfaceDMACopyBox, (PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, + PVMSVGA3DMIPMAPLEVEL pMipLevel, uint32_t uHostFace, uint32_t uHostMipmap, + SVGAGuestPtr GuestPtr, uint32_t cbGuestPitch, SVGA3dTransferType transfer, + SVGA3dCopyBox const *pBox, PVMSVGA3DCONTEXT pContext, int rc, int iBox)); + DECLCALLBACKMEMBER(int, pfnSurfaceStretchBlt, (PVGASTATE pThis, PVMSVGA3DSTATE pState, + PVMSVGA3DSURFACE pDstSurface, uint32_t uDstFace, uint32_t uDstMipmap, SVGA3dBox const *pDstBox, + PVMSVGA3DSURFACE pSrcSurface, uint32_t uSrcFace, uint32_t uSrcMipmap, SVGA3dBox const *pSrcBox, + SVGA3dStretchBltMode enmMode, PVMSVGA3DCONTEXT pContext)); + DECLCALLBACKMEMBER(void, pfnUpdateHostScreenViewport, (PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport)); + /** @todo HW accelerated screen output probably needs a separate interface. */ + DECLCALLBACKMEMBER(int, pfnDefineScreen, (PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)); + DECLCALLBACKMEMBER(int, pfnDestroyScreen, (PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)); + DECLCALLBACKMEMBER(int, pfnSurfaceBlitToScreen, (PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, + SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage, + SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects)); + /* Various helpers. */ + DECLCALLBACKMEMBER(int, pfnSurfaceUpdateHeapBuffers, (PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface)); +} VMSVGA3DBACKENDFUNCS3D; + +/* VGPU9 3D */ +#define VMSVGA3D_BACKEND_INTERFACE_NAME_VGPU9 "VGPU9" +typedef struct +{ + DECLCALLBACKMEMBER(int, pfnContextDefine, (PVGASTATECC pThisCC, uint32_t cid)); + DECLCALLBACKMEMBER(int, pfnContextDestroy, (PVGASTATECC pThisCC, uint32_t cid)); + DECLCALLBACKMEMBER(int, pfnSetTransform, (PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16])); + DECLCALLBACKMEMBER(int, pfnSetZRange, (PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange)); + DECLCALLBACKMEMBER(int, pfnSetRenderState, (PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState)); + DECLCALLBACKMEMBER(int, pfnSetRenderTarget, (PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target)); + DECLCALLBACKMEMBER(int, pfnSetTextureState, (PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState)); + DECLCALLBACKMEMBER(int, pfnSetMaterial, (PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial)); + DECLCALLBACKMEMBER(int, pfnSetLightData, (PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData)); + DECLCALLBACKMEMBER(int, pfnSetLightEnabled, (PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled)); + DECLCALLBACKMEMBER(int, pfnSetViewPort, (PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect)); + DECLCALLBACKMEMBER(int, pfnSetClipPlane, (PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4])); + DECLCALLBACKMEMBER(int, pfnCommandClear, (PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil, uint32_t cRects, SVGA3dRect *pRect)); + DECLCALLBACKMEMBER(int, pfnDrawPrimitives, (PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, uint32_t numRanges, SVGA3dPrimitiveRange *pNumRange, uint32_t cVertexDivisor, SVGA3dVertexDivisor *pVertexDivisor)); + DECLCALLBACKMEMBER(int, pfnSetScissorRect, (PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect)); + DECLCALLBACKMEMBER(int, pfnGenerateMipmaps, (PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter)); + DECLCALLBACKMEMBER(int, pfnShaderDefine, (PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData)); + DECLCALLBACKMEMBER(int, pfnShaderDestroy, (PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type)); + DECLCALLBACKMEMBER(int, pfnShaderSet, (PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid)); + DECLCALLBACKMEMBER(int, pfnShaderSetConst, (PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues)); + DECLCALLBACKMEMBER(int, pfnOcclusionQueryCreate, (PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)); + DECLCALLBACKMEMBER(int, pfnOcclusionQueryDelete, (PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)); + DECLCALLBACKMEMBER(int, pfnOcclusionQueryBegin, (PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)); + DECLCALLBACKMEMBER(int, pfnOcclusionQueryEnd, (PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)); + DECLCALLBACKMEMBER(int, pfnOcclusionQueryGetData, (PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t *pu32Pixels)); +} VMSVGA3DBACKENDFUNCSVGPU9; + +/* Support for Guest-Backed Objects. */ +#define VMSVGA3D_BACKEND_INTERFACE_NAME_GBO "GBO" +typedef struct +{ + DECLCALLBACKMEMBER(int, pfnScreenTargetBind, (PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, uint32_t sid)); + DECLCALLBACKMEMBER(int, pfnScreenTargetUpdate, (PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, SVGA3dRect const *pRect)); +} VMSVGA3DBACKENDFUNCSGBO; + +#define VMSVGA3D_BACKEND_INTERFACE_NAME_MAP "MAP" +typedef struct +{ + DECLCALLBACKMEMBER(int, pfnSurfaceMap, (PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox, VMSVGA3D_SURFACE_MAP enmMapType, VMSVGA3D_MAPPED_SURFACE *pMap)); + DECLCALLBACKMEMBER(int, pfnSurfaceUnmap, (PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, VMSVGA3D_MAPPED_SURFACE *pMap, bool fWritten)); +} VMSVGA3DBACKENDFUNCSMAP; + +typedef struct VMSVGA3DSHADER *PVMSVGA3DSHADER; +typedef struct VMSVGA3DDXCONTEXT *PVMSVGA3DDXCONTEXT; +struct DXShaderInfo; +#define VMSVGA3D_BACKEND_INTERFACE_NAME_DX "DX" +typedef struct +{ + DECLCALLBACKMEMBER(int, pfnDXSaveState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM)); + DECLCALLBACKMEMBER(int, pfnDXLoadState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM)); + DECLCALLBACKMEMBER(int, pfnDXDefineContext, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXDestroyContext, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXBindContext, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXSwitchContext, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXReadbackContext, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXInvalidateContext, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXSetSingleConstantBuffer, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t slot, SVGA3dShaderType type, SVGA3dSurfaceId sid, uint32_t offsetInBytes, uint32_t sizeInBytes)); + DECLCALLBACKMEMBER(int, pfnDXSetShaderResources, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startView, SVGA3dShaderType type, uint32_t cShaderResourceViewId, SVGA3dShaderResourceViewId const *paShaderResourceViewId)); + DECLCALLBACKMEMBER(int, pfnDXSetShader, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, SVGA3dShaderType type)); + DECLCALLBACKMEMBER(int, pfnDXSetSamplers, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startSampler, SVGA3dShaderType type, uint32_t cSamplerId, SVGA3dSamplerId const *paSamplerId)); + DECLCALLBACKMEMBER(int, pfnDXDraw, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCount, uint32_t startVertexLocation)); + DECLCALLBACKMEMBER(int, pfnDXDrawIndexed, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCount, uint32_t startIndexLocation, int32_t baseVertexLocation)); + DECLCALLBACKMEMBER(int, pfnDXDrawInstanced, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation)); + DECLCALLBACKMEMBER(int, pfnDXDrawIndexedInstanced, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndexLocation, int32_t baseVertexLocation, uint32_t startInstanceLocation)); + DECLCALLBACKMEMBER(int, pfnDXDrawAuto, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXSetInputLayout, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId)); + DECLCALLBACKMEMBER(int, pfnDXSetVertexBuffers, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startBuffer, uint32_t cVertexBuffer, SVGA3dVertexBuffer const *paVertexBuffer)); + DECLCALLBACKMEMBER(int, pfnDXSetIndexBuffer, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId sid, SVGA3dSurfaceFormat format, uint32_t offset)); + DECLCALLBACKMEMBER(int, pfnDXSetTopology, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dPrimitiveType topology)); + DECLCALLBACKMEMBER(int, pfnDXSetRenderTargets, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, uint32_t cRenderTargetViewId, SVGA3dRenderTargetViewId const *paRenderTargetViewId)); + DECLCALLBACKMEMBER(int, pfnDXSetBlendState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId, float const blendFactor[4], uint32_t sampleMask)); + DECLCALLBACKMEMBER(int, pfnDXSetDepthStencilState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId, uint32_t stencilRef)); + DECLCALLBACKMEMBER(int, pfnDXSetRasterizerState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId)); + DECLCALLBACKMEMBER(int, pfnDXDefineQuery, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGACOTableDXQueryEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyQuery, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId)); + DECLCALLBACKMEMBER(int, pfnDXBeginQuery, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId)); + DECLCALLBACKMEMBER(int, pfnDXEndQuery, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGADXQueryResultUnion *pQueryResult, uint32_t *pcbOut)); + DECLCALLBACKMEMBER(int, pfnDXSetPredication, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, uint32_t predicateValue)); + DECLCALLBACKMEMBER(int, pfnDXSetSOTargets, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cSoTarget, SVGA3dSoTarget const *paSoTarget)); + DECLCALLBACKMEMBER(int, pfnDXSetViewports, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cViewport, SVGA3dViewport const *paViewport)); + DECLCALLBACKMEMBER(int, pfnDXSetScissorRects, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cRect, SVGASignedRect const *paRect)); + DECLCALLBACKMEMBER(int, pfnDXClearRenderTargetView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGA3dRGBAFloat const *pRGBA)); + DECLCALLBACKMEMBER(int, pfnDXClearDepthStencilView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t flags, SVGA3dDepthStencilViewId depthStencilViewId, float depth, uint8_t stencil)); + DECLCALLBACKMEMBER(int, pfnDXPredCopyRegion, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId dstSid, uint32_t dstSubResource, SVGA3dSurfaceId srcSid, uint32_t srcSubResource, SVGA3dCopyBox const *pBox)); + DECLCALLBACKMEMBER(int, pfnDXPredCopy, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId dstSid, SVGA3dSurfaceId srcSid)); + DECLCALLBACKMEMBER(int, pfnDXPresentBlt, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId dstSid, uint32_t dstSubResource, SVGA3dBox const *pBoxDst, SVGA3dSurfaceId srcSid, uint32_t srcSubResource, SVGA3dBox const *pBoxSrc, SVGA3dDXPresentBltMode mode)); + DECLCALLBACKMEMBER(int, pfnDXGenMips, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId)); + DECLCALLBACKMEMBER(int, pfnDXDefineShaderResourceView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId, SVGACOTableDXSRViewEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyShaderResourceView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId)); + DECLCALLBACKMEMBER(int, pfnDXDefineRenderTargetView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGACOTableDXRTViewEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyRenderTargetView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId)); + DECLCALLBACKMEMBER(int, pfnDXDefineDepthStencilView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, SVGACOTableDXDSViewEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyDepthStencilView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId)); + DECLCALLBACKMEMBER(int, pfnDXDefineElementLayout, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId, SVGACOTableDXElementLayoutEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyElementLayout, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId)); + DECLCALLBACKMEMBER(int, pfnDXDefineBlendState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId, SVGACOTableDXBlendStateEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyBlendState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId)); + DECLCALLBACKMEMBER(int, pfnDXDefineDepthStencilState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId, SVGACOTableDXDepthStencilEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyDepthStencilState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId)); + DECLCALLBACKMEMBER(int, pfnDXDefineRasterizerState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId, SVGACOTableDXRasterizerStateEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyRasterizerState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId)); + DECLCALLBACKMEMBER(int, pfnDXDefineSamplerState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSamplerId samplerId, SVGACOTableDXSamplerEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroySamplerState, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSamplerId samplerId)); + DECLCALLBACKMEMBER(int, pfnDXDefineShader, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, SVGACOTableDXShaderEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyShader, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId)); + DECLCALLBACKMEMBER(int, pfnDXBindShader, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, DXShaderInfo const *pShaderInfo)); + DECLCALLBACKMEMBER(int, pfnDXDefineStreamOutput, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid, SVGACOTableDXStreamOutputEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyStreamOutput, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid)); + DECLCALLBACKMEMBER(int, pfnDXSetStreamOutput, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid)); + DECLCALLBACKMEMBER(int, pfnDXSetCOTable, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableType type, uint32_t cValidEntries)); + DECLCALLBACKMEMBER(int, pfnDXBufferCopy, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXSurfaceCopyAndReadback, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXMoveQuery, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXBindAllShader, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXHint, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXBufferUpdate, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXCondBindAllShader, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnScreenCopy, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnIntraSurfaceCopy, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceImageId const &surface, SVGA3dCopyBox const &box)); + DECLCALLBACKMEMBER(int, pfnDXResolveCopy, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXPredResolveCopy, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXPredConvertRegion, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXPredConvert, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnWholeSurfaceCopy, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXDefineUAView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, SVGACOTableDXUAViewEntry const *pEntry)); + DECLCALLBACKMEMBER(int, pfnDXDestroyUAView, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId)); + DECLCALLBACKMEMBER(int, pfnDXClearUAViewUint, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, uint32_t const aValues[4])); + DECLCALLBACKMEMBER(int, pfnDXClearUAViewFloat, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, float const aValues[4])); + DECLCALLBACKMEMBER(int, pfnDXCopyStructureCount, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId srcUAViewId, SVGA3dSurfaceId destSid, uint32_t destByteOffset)); + DECLCALLBACKMEMBER(int, pfnDXSetUAViews, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t uavSpliceIndex, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId)); + DECLCALLBACKMEMBER(int, pfnDXDrawIndexedInstancedIndirect, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId argsBufferSid, uint32_t byteOffsetForArgs)); + DECLCALLBACKMEMBER(int, pfnDXDrawInstancedIndirect, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId argsBufferSid, uint32_t byteOffsetForArgs)); + DECLCALLBACKMEMBER(int, pfnDXDispatch, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ)); + DECLCALLBACKMEMBER(int, pfnDXDispatchIndirect, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnWriteZeroSurface, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnHintZeroSurface, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXTransferToBuffer, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnLogicOpsBitBlt, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnLogicOpsTransBlt, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnLogicOpsStretchBlt, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnLogicOpsColorFill, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnLogicOpsAlphaBlend, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnLogicOpsClearTypeBlend, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXSetCSUAViews, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startIndex, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId)); + DECLCALLBACKMEMBER(int, pfnDXSetMinLOD, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXSetShaderIface, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnSurfaceStretchBltNonMSToMS, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnDXBindShaderIface, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext)); + DECLCALLBACKMEMBER(int, pfnVBDXClearRenderTargetViewRegion, (PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGA3dRGBAFloat const *pColor, uint32_t cRect, SVGASignedRect const *paRect)); +} VMSVGA3DBACKENDFUNCSDX; + +typedef struct VMSVGA3DBACKENDDESC +{ + char const *pszName; + DECLCALLBACKMEMBER(int, pfnQueryInterface, (PVGASTATECC pThisCC, char const *pszInterfaceName, void *pvInterfaceFuncs, size_t cbInterfaceFuncs)); +} VMSVGA3DBACKENDDESC; + +#ifdef VMSVGA3D_DX +/* Helpers. */ +int vmsvga3dDXUnbindContext(PVGASTATECC pThisCC, uint32_t cid, SVGADXContextMobFormat *pSvgaDXContext); +int vmsvga3dDXSwitchContext(PVGASTATECC pThisCC, uint32_t cid); + +/* Command handlers. */ +int vmsvga3dDXDefineContext(PVGASTATECC pThisCC, uint32_t cid); +int vmsvga3dDXDestroyContext(PVGASTATECC pThisCC, uint32_t cid); +int vmsvga3dDXBindContext(PVGASTATECC pThisCC, uint32_t cid, SVGADXContextMobFormat *pSvgaDXContext); +int vmsvga3dDXReadbackContext(PVGASTATECC pThisCC, uint32_t idDXContext, SVGADXContextMobFormat *pSvgaDXContext); +int vmsvga3dDXInvalidateContext(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXSetSingleConstantBuffer(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetSingleConstantBuffer const *pCmd); +int vmsvga3dDXSetShaderResources(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetShaderResources const *pCmd, uint32_t cShaderResourceViewId, SVGA3dShaderResourceViewId const *paShaderResourceViewId); +int vmsvga3dDXSetShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetShader const *pCmd); +int vmsvga3dDXSetSamplers(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetSamplers const *pCmd, uint32_t cSamplerId, SVGA3dSamplerId const *paSamplerId); +int vmsvga3dDXDraw(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDraw const *pCmd); +int vmsvga3dDXDrawIndexed(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexed const *pCmd); +int vmsvga3dDXDrawInstanced(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawInstanced const *pCmd); +int vmsvga3dDXDrawIndexedInstanced(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexedInstanced const *pCmd); +int vmsvga3dDXDrawAuto(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXSetInputLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dElementLayoutId elementLayoutId); +int vmsvga3dDXSetVertexBuffers(PVGASTATECC pThisCC, uint32_t idDXContext, uint32_t startBuffer, uint32_t cVertexBuffer, SVGA3dVertexBuffer const *paVertexBuffer); +int vmsvga3dDXSetIndexBuffer(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetIndexBuffer const *pCmd); +int vmsvga3dDXSetTopology(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dPrimitiveType topology); +int vmsvga3dDXSetRenderTargets(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dDepthStencilViewId depthStencilViewId, uint32_t cRenderTargetViewId, SVGA3dRenderTargetViewId const *paRenderTargetViewId); +int vmsvga3dDXSetBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetBlendState const *pCmd); +int vmsvga3dDXSetDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetDepthStencilState const *pCmd); +int vmsvga3dDXSetRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dRasterizerStateId rasterizerId); +int vmsvga3dDXDefineQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineQuery const *pCmd); +int vmsvga3dDXDestroyQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyQuery const *pCmd); +int vmsvga3dDXBindQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindQuery const *pCmd, PVMSVGAMOB pMob); +int vmsvga3dDXSetQueryOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetQueryOffset const *pCmd); +int vmsvga3dDXBeginQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBeginQuery const *pCmd); +int vmsvga3dDXEndQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXEndQuery const *pCmd); +int vmsvga3dDXReadbackQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXReadbackQuery const *pCmd); +int vmsvga3dDXSetPredication(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetPredication const *pCmd); +int vmsvga3dDXSetSOTargets(PVGASTATECC pThisCC, uint32_t idDXContext, uint32_t cSoTarget, SVGA3dSoTarget const *paSoTarget); +int vmsvga3dDXSetViewports(PVGASTATECC pThisCC, uint32_t idDXContext, uint32_t cViewport, SVGA3dViewport const *paViewport); +int vmsvga3dDXSetScissorRects(PVGASTATECC pThisCC, uint32_t idDXContext, uint32_t cRect, SVGASignedRect const *paRect); +int vmsvga3dDXClearRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearRenderTargetView const *pCmd); +int vmsvga3dDXClearDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearDepthStencilView const *pCmd); +int vmsvga3dDXPredCopyRegion(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredCopyRegion const *pCmd); +int vmsvga3dDXPredCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPredCopy const *pCmd); +int vmsvga3dDXPresentBlt(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXPresentBlt const *pCmd); +int vmsvga3dDXGenMips(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXGenMips const *pCmd); +int vmsvga3dDXDefineShaderResourceView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineShaderResourceView const *pCmd); +int vmsvga3dDXDestroyShaderResourceView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyShaderResourceView const *pCmd); +int vmsvga3dDXDefineRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineRenderTargetView const *pCmd); +int vmsvga3dDXDestroyRenderTargetView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyRenderTargetView const *pCmd); +int vmsvga3dDXDefineDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineDepthStencilView_v2 const *pCmd); +int vmsvga3dDXDestroyDepthStencilView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyDepthStencilView const *pCmd); +int vmsvga3dDXDefineElementLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dElementLayoutId elementLayoutId, uint32_t cDesc, SVGA3dInputElementDesc const *paDesc); +int vmsvga3dDXDestroyElementLayout(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyElementLayout const *pCmd); +int vmsvga3dDXDefineBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineBlendState const *pCmd); +int vmsvga3dDXDestroyBlendState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyBlendState const *pCmd); +int vmsvga3dDXDefineDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineDepthStencilState const *pCmd); +int vmsvga3dDXDestroyDepthStencilState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyDepthStencilState const *pCmd); +int vmsvga3dDXDefineRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineRasterizerState const *pCmd); +int vmsvga3dDXDestroyRasterizerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyRasterizerState const *pCmd); +int vmsvga3dDXDefineSamplerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineSamplerState const *pCmd); +int vmsvga3dDXDestroySamplerState(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroySamplerState const *pCmd); +int vmsvga3dDXDefineShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineShader const *pCmd); +int vmsvga3dDXDestroyShader(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyShader const *pCmd); +int vmsvga3dDXBindShader(PVGASTATECC pThisCC, SVGA3dCmdDXBindShader const *pCmd, PVMSVGAMOB pMob); +int vmsvga3dDXDefineStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineStreamOutput const *pCmd); +int vmsvga3dDXDestroyStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyStreamOutput const *pCmd); +int vmsvga3dDXSetStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetStreamOutput const *pCmd); +int vmsvga3dDXSetCOTable(PVGASTATECC pThisCC, SVGA3dCmdDXSetCOTable const *pCmd, PVMSVGAMOB pMob); +int vmsvga3dDXReadbackCOTable(PVGASTATECC pThisCC, SVGA3dCmdDXReadbackCOTable const *pCmd); +int vmsvga3dDXBufferCopy(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXSurfaceCopyAndReadback(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXMoveQuery(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXBindAllQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindAllQuery const *pCmd); +int vmsvga3dDXReadbackAllQuery(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXReadbackAllQuery const *pCmd); +int vmsvga3dDXBindAllShader(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXHint(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXBufferUpdate(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXSetConstantBufferOffset(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetConstantBufferOffset const *pCmd, SVGA3dShaderType type); +int vmsvga3dDXCondBindAllShader(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dScreenCopy(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXGrowCOTable(PVGASTATECC pThisCC, SVGA3dCmdDXGrowCOTable const *pCmd); +int vmsvga3dIntraSurfaceCopy(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdIntraSurfaceCopy const *pCmd); +int vmsvga3dDXResolveCopy(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXPredResolveCopy(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXPredConvertRegion(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXPredConvert(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dWholeSurfaceCopy(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXDefineUAView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineUAView const *pCmd); +int vmsvga3dDXDestroyUAView(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDestroyUAView const *pCmd); +int vmsvga3dDXClearUAViewUint(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearUAViewUint const *pCmd); +int vmsvga3dDXClearUAViewFloat(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXClearUAViewFloat const *pCmd); +int vmsvga3dDXCopyStructureCount(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXCopyStructureCount const *pCmd); +int vmsvga3dDXSetUAViews(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetUAViews const *pCmd, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId); +int vmsvga3dDXDrawIndexedInstancedIndirect(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawIndexedInstancedIndirect const *pCmd); +int vmsvga3dDXDrawInstancedIndirect(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDrawInstancedIndirect const *pCmd); +int vmsvga3dDXDispatch(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDispatch const *pCmd); +int vmsvga3dDXDispatchIndirect(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dWriteZeroSurface(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dHintZeroSurface(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXTransferToBuffer(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXSetStructureCount(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetStructureCount const *pCmd); +int vmsvga3dLogicOpsBitBlt(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dLogicOpsTransBlt(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dLogicOpsStretchBlt(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dLogicOpsColorFill(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dLogicOpsAlphaBlend(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dLogicOpsClearTypeBlend(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXSetCSUAViews(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXSetCSUAViews const *pCmd, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId); +int vmsvga3dDXSetMinLOD(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXDefineStreamOutputWithMob(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXDefineStreamOutputWithMob const *pCmd); +int vmsvga3dDXSetShaderIface(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXBindStreamOutput(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdDXBindStreamOutput const *pCmd); +int vmsvga3dSurfaceStretchBltNonMSToMS(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXBindShaderIface(PVGASTATECC pThisCC, uint32_t idDXContext); +int vmsvga3dDXLoadExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); +int vmsvga3dDXSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM); + +int vmsvga3dVBDXClearRenderTargetViewRegion(PVGASTATECC pThisCC, uint32_t idDXContext, SVGA3dCmdVBDXClearRenderTargetViewRegion const *pCmd, uint32_t cRect, SVGASignedRect const *paRect); +#endif /* VMSVGA3D_DX */ + + +float float16ToFloat(uint16_t f16); + + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA3d_h */ + diff --git a/src/VBox/Devices/Graphics/DevVGA.cpp b/src/VBox/Devices/Graphics/DevVGA.cpp new file mode 100644 index 00000000..a2ce3b39 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA.cpp @@ -0,0 +1,7504 @@ +/* $Id: DevVGA.cpp $ */ +/** @file + * DevVGA - VBox VGA/VESA device. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + * -------------------------------------------------------------------- + * + * This code is based on: + * + * QEMU VGA Emulator. + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ + +/* WARNING!!! All defines that affect VGAState should be placed in DevVGA.h !!! + * NEVER place them here as this would lead to VGASTATE inconsistency + * across different .cpp files !!! + */ + +#ifdef VBOX_WITH_HGSMI +#define PCIDEV_2_VGASTATE(pPciDev) ((PVGASTATE)((uintptr_t)pPciDev - RT_OFFSETOF(VGASTATE, Dev))) +#endif /* VBOX_WITH_HGSMI */ + +/* VGA text mode blinking constants (cursor and blinking chars). */ +#define VGA_BLINK_PERIOD_FULL (RT_NS_100MS * 4) /**< Blink cycle length. */ +#define VGA_BLINK_PERIOD_ON (RT_NS_100MS * 2) /**< How long cursor/text is visible. */ + +/* EGA compatible switch values (in high nibble). + * XENIX 2.1.x/2.2.x is known to rely on the switch values. + */ +#define EGA_SWITCHES 0x90 /* Off-on-on-off, high-res color EGA display. */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VGA +#include +#include +#include +#ifdef IN_RING3 +# include +# include +#endif /* IN_RING3 */ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ +#include "DevVGA.h" + +#if defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE) +# include "DevVGAModes.h" +# include /* sscan */ +#endif + +#include "VBoxDD.h" +#include "VBoxDD2.h" + +#ifdef VBOX_WITH_VMSVGA +#include "DevVGA-SVGA.h" +#endif + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ + +/** The BIOS boot menu text position, X. */ +#define LOGO_F12TEXT_X 304 +/** The BIOS boot menu text position, Y. */ +#define LOGO_F12TEXT_Y 460 + +/** Width of the "Press F12 to select boot device." bitmap. + Anything that exceeds the limit of F12BootText below is filled with + background. */ +#define LOGO_F12TEXT_WIDTH 286 +/** Height of the boot device selection bitmap, see LOGO_F12TEXT_WIDTH. */ +#define LOGO_F12TEXT_HEIGHT 12 + +/** The BIOS logo delay time (msec). */ +#define LOGO_DELAY_TIME 2000 + +#define LOGO_MAX_WIDTH 640 +#define LOGO_MAX_HEIGHT 480 +#define LOGO_MAX_SIZE LOGO_MAX_WIDTH * LOGO_MAX_HEIGHT * 4 + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#ifdef IN_RING3 +/* "Press F12 to select boot device." bitmap. */ +static const uint8_t g_abLogoF12BootText[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x0F, 0x7C, + 0xF8, 0xF0, 0x01, 0xE0, 0x81, 0x9F, 0x3F, 0x00, 0x70, 0xF8, 0x00, 0xE0, 0xC3, + 0x07, 0x0F, 0x1F, 0x3E, 0x70, 0x00, 0xF0, 0xE1, 0xC3, 0x07, 0x0E, 0x00, 0x6E, + 0x7C, 0x60, 0xE0, 0xE1, 0xC3, 0x07, 0xC6, 0x80, 0x81, 0x31, 0x63, 0xC6, 0x00, + 0x30, 0x80, 0x61, 0x0C, 0x00, 0x36, 0x63, 0x00, 0x8C, 0x19, 0x83, 0x61, 0xCC, + 0x18, 0x36, 0x00, 0xCC, 0x8C, 0x19, 0xC3, 0x06, 0xC0, 0x8C, 0x31, 0x3C, 0x30, + 0x8C, 0x19, 0x83, 0x31, 0x60, 0x60, 0x00, 0x0C, 0x18, 0x00, 0x0C, 0x60, 0x18, + 0x00, 0x80, 0xC1, 0x18, 0x00, 0x30, 0x06, 0x60, 0x18, 0x30, 0x80, 0x01, 0x00, + 0x33, 0x63, 0xC6, 0x30, 0x00, 0x30, 0x63, 0x80, 0x19, 0x0C, 0x03, 0x06, 0x00, + 0x0C, 0x18, 0x18, 0xC0, 0x81, 0x03, 0x00, 0x03, 0x18, 0x0C, 0x00, 0x60, 0x30, + 0x06, 0x00, 0x87, 0x01, 0x18, 0x06, 0x0C, 0x60, 0x00, 0xC0, 0xCC, 0x98, 0x31, + 0x0C, 0x00, 0xCC, 0x18, 0x30, 0x0C, 0xC3, 0x80, 0x01, 0x00, 0x03, 0x66, 0xFE, + 0x18, 0x30, 0x00, 0xC0, 0x02, 0x06, 0x06, 0x00, 0x18, 0x8C, 0x01, 0x60, 0xE0, + 0x0F, 0x86, 0x3F, 0x03, 0x18, 0x00, 0x30, 0x33, 0x66, 0x0C, 0x03, 0x00, 0x33, + 0xFE, 0x0C, 0xC3, 0x30, 0xE0, 0x0F, 0xC0, 0x87, 0x9B, 0x31, 0x63, 0xC6, 0x00, + 0xF0, 0x80, 0x01, 0x03, 0x00, 0x06, 0x63, 0x00, 0x8C, 0x19, 0x83, 0x61, 0xCC, + 0x18, 0x06, 0x00, 0x6C, 0x8C, 0x19, 0xC3, 0x00, 0x80, 0x8D, 0x31, 0xC3, 0x30, + 0x8C, 0x19, 0x03, 0x30, 0xB3, 0xC3, 0x87, 0x0F, 0x1F, 0x00, 0x2C, 0x60, 0x80, + 0x01, 0xE0, 0x87, 0x0F, 0x00, 0x3E, 0x7C, 0x60, 0xF0, 0xE1, 0xE3, 0x07, 0x00, + 0x0F, 0x3E, 0x7C, 0xFC, 0x00, 0xC0, 0xC3, 0xC7, 0x30, 0x0E, 0x3E, 0x7C, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x1E, 0xC0, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x87, 0x31, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x18, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x30, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF8, 0x83, 0xC1, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, + 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif /* IN_RING3 */ + +#ifndef VBOX_DEVICE_STRUCT_TESTCASE /* Till the end of the file - doesn't count indent wise. */ + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4310 4245) /* Buggy warnings: cast truncates constant value; conversion from 'int' to 'const uint8_t', signed/unsigned mismatch */ +#endif + +/* force some bits to zero */ +static const uint8_t sr_mask[8] = { + (uint8_t)~0xfc, + (uint8_t)~0xc2, + (uint8_t)~0xf0, + (uint8_t)~0xc0, + (uint8_t)~0xf1, + (uint8_t)~0xff, + (uint8_t)~0xff, + (uint8_t)~0x01, +}; + +static const uint8_t gr_mask[16] = { + (uint8_t)~0xf0, /* 0x00 */ + (uint8_t)~0xf0, /* 0x01 */ + (uint8_t)~0xf0, /* 0x02 */ + (uint8_t)~0xe0, /* 0x03 */ + (uint8_t)~0xfc, /* 0x04 */ + (uint8_t)~0x84, /* 0x05 */ + (uint8_t)~0xf0, /* 0x06 */ + (uint8_t)~0xf0, /* 0x07 */ + (uint8_t)~0x00, /* 0x08 */ + (uint8_t)~0xff, /* 0x09 */ + (uint8_t)~0xff, /* 0x0a */ + (uint8_t)~0xff, /* 0x0b */ + (uint8_t)~0xff, /* 0x0c */ + (uint8_t)~0xff, /* 0x0d */ + (uint8_t)~0xff, /* 0x0e */ + (uint8_t)~0xff, /* 0x0f */ +}; + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#define cbswap_32(__x) \ + ((uint32_t)((((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) + +#ifdef WORDS_BIGENDIAN +# define PAT(x) cbswap_32(x) +#else +# define PAT(x) (x) +#endif + +#ifdef WORDS_BIGENDIAN +# define BIG 1 +#else +# define BIG 0 +#endif + +#ifdef WORDS_BIGENDIAN +#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) +#else +#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff) +#endif + +static const uint32_t mask16[16] = { + PAT(0x00000000), + PAT(0x000000ff), + PAT(0x0000ff00), + PAT(0x0000ffff), + PAT(0x00ff0000), + PAT(0x00ff00ff), + PAT(0x00ffff00), + PAT(0x00ffffff), + PAT(0xff000000), + PAT(0xff0000ff), + PAT(0xff00ff00), + PAT(0xff00ffff), + PAT(0xffff0000), + PAT(0xffff00ff), + PAT(0xffffff00), + PAT(0xffffffff), +}; + +#undef PAT + +#ifdef WORDS_BIGENDIAN +# define PAT(x) (x) +#else +# define PAT(x) cbswap_32(x) +#endif + +#ifdef IN_RING3 + +static const uint32_t dmask16[16] = { + PAT(0x00000000), + PAT(0x000000ff), + PAT(0x0000ff00), + PAT(0x0000ffff), + PAT(0x00ff0000), + PAT(0x00ff00ff), + PAT(0x00ffff00), + PAT(0x00ffffff), + PAT(0xff000000), + PAT(0xff0000ff), + PAT(0xff00ff00), + PAT(0xff00ffff), + PAT(0xffff0000), + PAT(0xffff00ff), + PAT(0xffffff00), + PAT(0xffffffff), +}; + +static const uint32_t dmask4[4] = { + PAT(0x00000000), + PAT(0x0000ffff), + PAT(0xffff0000), + PAT(0xffffffff), +}; + +static uint32_t expand4[256]; +static uint16_t expand2[256]; +static uint8_t expand4to8[16]; + +#endif /* IN_RING3 */ + + +/** + * Mark a page in VGA A0000-BFFFF range as remapped. + * + * @param pThis VGA instance data. + * @param offVGAMem The offset within VGA memory. + */ +DECLINLINE(void) vgaMarkRemapped(PVGASTATE pThis, RTGCPHYS offVGAMem) +{ + AssertMsg(offVGAMem < _128K, ("offVGAMem = %RGp\n", offVGAMem)); + pThis->bmPageRemappedVGA |= RT_BIT_32((uint32_t)offVGAMem >> GUEST_PAGE_SHIFT); +} + + +/** + * Checks if a page in VGA A0000-BFFFF range is remapped. + * + * @returns true if remapped. + * @returns false if not remapped (accesses will trap). + * @param pThis VGA instance data. + * @param offVGAMem The offset within VGA memory. + */ +DECLINLINE(bool) vgaIsRemapped(PVGASTATE pThis, RTGCPHYS offVGAMem) +{ + AssertMsg(offVGAMem < _128K, ("offVGAMem = %RGp\n", offVGAMem)); + return pThis->bmPageRemappedVGA & RT_BIT_32((uint32_t)offVGAMem >> GUEST_PAGE_SHIFT); +} + + +/** + * Reset page remap tracking bits. + * + * @param pThis VGA instance data. + */ +DECLINLINE(void) vgaResetRemapped(PVGASTATE pThis) +{ + pThis->bmPageRemappedVGA = 0; +} + + +/** + * Set a VRAM page dirty. + * + * @param pThis VGA instance data. + * @param offVRAM The VRAM offset of the page to set. + */ +DECLINLINE(void) vgaR3MarkDirty(PVGASTATE pThis, RTGCPHYS offVRAM) +{ + AssertMsg(offVRAM < pThis->vram_size, ("offVRAM = %p, pThis->vram_size = %p\n", offVRAM, pThis->vram_size)); + ASMBitSet(&pThis->bmDirtyBitmap[0], offVRAM >> GUEST_PAGE_SHIFT); + pThis->fHasDirtyBits = true; +} + +#ifdef IN_RING3 + +/** + * Tests if a VRAM page is dirty. + * + * @returns true if dirty. + * @returns false if clean. + * @param pThis VGA instance data. + * @param offVRAM The VRAM offset of the page to check. + */ +DECLINLINE(bool) vgaR3IsDirty(PVGASTATE pThis, RTGCPHYS offVRAM) +{ + AssertMsg(offVRAM < pThis->vram_size, ("offVRAM = %p, pThis->vram_size = %p\n", offVRAM, pThis->vram_size)); + return ASMBitTest(&pThis->bmDirtyBitmap[0], offVRAM >> GUEST_PAGE_SHIFT); +} + + +/** + * Reset dirty flags in a give range. + * + * @param pThis VGA instance data. + * @param offVRAMStart Offset into the VRAM buffer of the first page. + * @param offVRAMEnd Offset into the VRAM buffer of the last page - exclusive. + */ +DECLINLINE(void) vgaR3ResetDirty(PVGASTATE pThis, RTGCPHYS offVRAMStart, RTGCPHYS offVRAMEnd) +{ + Assert(offVRAMStart < pThis->vram_size); + Assert(offVRAMEnd <= pThis->vram_size); + Assert(offVRAMStart < offVRAMEnd); + ASMBitClearRange(&pThis->bmDirtyBitmap[0], offVRAMStart >> GUEST_PAGE_SHIFT, offVRAMEnd >> GUEST_PAGE_SHIFT); +} + + +/** + * Queries the VRAM dirty bits and resets the monitoring. + */ +static void vgaR3UpdateDirtyBitsAndResetMonitoring(PPDMDEVINS pDevIns, PVGASTATE pThis) +{ + size_t const cbBitmap = RT_ALIGN_Z(RT_MIN(pThis->vram_size, VGA_VRAM_MAX), GUEST_PAGE_SIZE * 64) / GUEST_PAGE_SIZE / 8; + + /* + * If we don't have any dirty bits from MMIO accesses, we can just query + * straight into the dirty buffer. + */ + if (!pThis->fHasDirtyBits) + { + int rc = PDMDevHlpMmio2QueryAndResetDirtyBitmap(pDevIns, pThis->hMmio2VRam, pThis->bmDirtyBitmap, cbBitmap); + AssertRC(rc); + } + /* + * Otherwise we'll have to query and merge the two. + */ + else + { + uint64_t bmDirtyPages[VGA_VRAM_MAX / GUEST_PAGE_SIZE / 64]; /* (256 MB VRAM -> 8KB bitmap) */ + int rc = PDMDevHlpMmio2QueryAndResetDirtyBitmap(pDevIns, pThis->hMmio2VRam, bmDirtyPages, cbBitmap); + if (RT_SUCCESS(rc)) + { + /** @todo could use ORPS or VORPS here, I think. */ + uint64_t *pbmDst = pThis->bmDirtyBitmap; + size_t const cTodo = cbBitmap / sizeof(uint64_t); + + /* Do 64 bytes at a time first. */ + size_t const cTodoFirst = cTodo & ~(size_t)7; + size_t idx; + for (idx = 0; idx < cTodoFirst; idx += 8) + { + pbmDst[idx + 0] |= bmDirtyPages[idx + 0]; + pbmDst[idx + 1] |= bmDirtyPages[idx + 1]; + pbmDst[idx + 2] |= bmDirtyPages[idx + 2]; + pbmDst[idx + 3] |= bmDirtyPages[idx + 3]; + pbmDst[idx + 4] |= bmDirtyPages[idx + 4]; + pbmDst[idx + 5] |= bmDirtyPages[idx + 5]; + pbmDst[idx + 6] |= bmDirtyPages[idx + 6]; + pbmDst[idx + 7] |= bmDirtyPages[idx + 7]; + } + + /* Then do a mopup of anything remaining. */ + switch (cTodo - idx) + { + case 7: pbmDst[idx + 6] |= bmDirtyPages[idx + 6]; RT_FALL_THRU(); + case 6: pbmDst[idx + 5] |= bmDirtyPages[idx + 5]; RT_FALL_THRU(); + case 5: pbmDst[idx + 4] |= bmDirtyPages[idx + 4]; RT_FALL_THRU(); + case 4: pbmDst[idx + 3] |= bmDirtyPages[idx + 3]; RT_FALL_THRU(); + case 3: pbmDst[idx + 2] |= bmDirtyPages[idx + 2]; RT_FALL_THRU(); + case 2: pbmDst[idx + 1] |= bmDirtyPages[idx + 1]; RT_FALL_THRU(); + case 1: pbmDst[idx] |= bmDirtyPages[idx]; break; + case 0: break; + default: AssertFailedBreak(); + } + + pThis->fHasDirtyBits = false; + } + } +} + +#endif /* IN_RING3 */ + +/* Update the values needed for calculating Vertical Retrace and + * Display Enable status bits more or less accurately. The Display Enable + * bit is set (indicating *disabled* display signal) when either the + * horizontal (hblank) or vertical (vblank) blanking is active. The + * Vertical Retrace bit is set when vertical retrace (vsync) is active. + * Unless the CRTC is horribly misprogrammed, vsync implies vblank. + */ +static void vga_update_retrace_state(PVGASTATE pThis) +{ + unsigned htotal_cclks, vtotal_lines, chars_per_sec; + unsigned hblank_start_cclk, hblank_end_cclk, hblank_width, hblank_skew_cclks; + unsigned vsync_start_line, vsync_end, vsync_width; + unsigned vblank_start_line, vblank_end, vblank_width; + unsigned char_dots, clock_doubled, clock_index; + const int clocks[] = {25175000, 28322000, 25175000, 25175000}; + vga_retrace_s *r = &pThis->retrace_state; + + /* For horizontal timings, we only care about the blanking start/end. */ + htotal_cclks = pThis->cr[0x00] + 5; + hblank_start_cclk = pThis->cr[0x02]; + hblank_end_cclk = (pThis->cr[0x03] & 0x1f) + ((pThis->cr[0x05] & 0x80) >> 2); + hblank_skew_cclks = (pThis->cr[0x03] >> 5) & 3; + + /* For vertical timings, we need both the blanking start/end... */ + vtotal_lines = pThis->cr[0x06] + ((pThis->cr[0x07] & 1) << 8) + ((pThis->cr[0x07] & 0x20) << 4) + 2; + vblank_start_line = pThis->cr[0x15] + ((pThis->cr[0x07] & 8) << 5) + ((pThis->cr[0x09] & 0x20) << 4); + vblank_end = pThis->cr[0x16]; + /* ... and the vertical retrace (vsync) start/end. */ + vsync_start_line = pThis->cr[0x10] + ((pThis->cr[0x07] & 4) << 6) + ((pThis->cr[0x07] & 0x80) << 2); + vsync_end = pThis->cr[0x11] & 0xf; + + /* Calculate the blanking and sync widths. The way it's implemented in + * the VGA with limited-width compare counters is quite a piece of work. + */ + hblank_width = (hblank_end_cclk - hblank_start_cclk) & 0x3f;/* 6 bits */ + vblank_width = (vblank_end - vblank_start_line) & 0xff; /* 8 bits */ + vsync_width = (vsync_end - vsync_start_line) & 0xf; /* 4 bits */ + + /* Calculate the dot and character clock rates. */ + clock_doubled = (pThis->sr[0x01] >> 3) & 1; /* Clock doubling bit. */ + clock_index = (pThis->msr >> 2) & 3; + char_dots = (pThis->sr[0x01] & 1) ? 8 : 9; /* 8 or 9 dots per cclk. */ + + chars_per_sec = clocks[clock_index] / char_dots; + Assert(chars_per_sec); /* Can't possibly be zero. */ + + htotal_cclks <<= clock_doubled; + + /* Calculate the number of cclks per entire frame. */ + r->frame_cclks = vtotal_lines * htotal_cclks; + Assert(r->frame_cclks); /* Can't possibly be zero. */ + + if (r->v_freq_hz) { /* Could be set to emulate a specific rate. */ + r->cclk_ns = 1000000000 / (r->frame_cclks * r->v_freq_hz); + } else { + r->cclk_ns = 1000000000 / chars_per_sec; + } + Assert(r->cclk_ns); + r->frame_ns = r->frame_cclks * r->cclk_ns; + + /* Calculate timings in cclks/lines. Stored but not directly used. */ + r->hb_start = hblank_start_cclk + hblank_skew_cclks; + r->hb_end = hblank_start_cclk + hblank_width + hblank_skew_cclks; + r->h_total = htotal_cclks; + Assert(r->h_total); /* Can't possibly be zero. */ + + r->vb_start = vblank_start_line; + r->vb_end = vblank_start_line + vblank_width + 1; + r->vs_start = vsync_start_line; + r->vs_end = vsync_start_line + vsync_width + 1; + + /* Calculate timings in nanoseconds. For easier comparisons, the frame + * is considered to start at the beginning of the vertical and horizontal + * blanking period. + */ + r->h_total_ns = htotal_cclks * r->cclk_ns; + r->hb_end_ns = hblank_width * r->cclk_ns; + r->vb_end_ns = vblank_width * r->h_total_ns; + r->vs_start_ns = (r->vs_start - r->vb_start) * r->h_total_ns; + r->vs_end_ns = (r->vs_end - r->vb_start) * r->h_total_ns; + Assert(r->h_total_ns); /* See h_total. */ +} + +static uint8_t vga_retrace(PPDMDEVINS pDevIns, PVGASTATE pThis) +{ + vga_retrace_s *r = &pThis->retrace_state; + + if (r->frame_ns) { + uint8_t val = pThis->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE); + unsigned cur_frame_ns, cur_line_ns; + uint64_t time_ns; + + time_ns = PDMDevHlpTMTimeVirtGetNano(pDevIns); + + /* Determine the time within the frame. */ + cur_frame_ns = time_ns % r->frame_ns; + + /* See if we're in the vertical blanking period... */ + if (cur_frame_ns < r->vb_end_ns) { + val |= ST01_DISP_ENABLE; + /* ... and additionally in the vertical sync period. */ + if (cur_frame_ns >= r->vs_start_ns && cur_frame_ns <= r->vs_end_ns) + val |= ST01_V_RETRACE; + } else { + /* Determine the time within the current scanline. */ + cur_line_ns = cur_frame_ns % r->h_total_ns; + /* See if we're in the horizontal blanking period. */ + if (cur_line_ns < r->hb_end_ns) + val |= ST01_DISP_ENABLE; + } + return val; + } else { + return pThis->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE); + } +} + +int vga_ioport_invalid(PVGASTATE pThis, uint32_t addr) +{ + if (pThis->msr & MSR_COLOR_EMULATION) { + /* Color */ + return (addr >= 0x3b0 && addr <= 0x3bf); + } else { + /* Monochrome */ + return (addr >= 0x3d0 && addr <= 0x3df); + } +} + +static uint32_t vga_ioport_read(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t addr) +{ + int val, index; + + /* check port range access depending on color/monochrome mode */ + if (vga_ioport_invalid(pThis, addr)) { + val = 0xff; + Log(("VGA: following read ignored\n")); + } else { + switch(addr) { + case 0x3c0: + if (pThis->ar_flip_flop == 0) { + val = pThis->ar_index; + } else { + val = 0; + } + break; + case 0x3c1: + index = pThis->ar_index & 0x1f; + if (index < 21) + val = pThis->ar[index]; + else + val = 0; + break; + case 0x3c2: + val = pThis->st00; + break; + case 0x3c4: + val = pThis->sr_index; + break; + case 0x3c5: + val = pThis->sr[pThis->sr_index]; + Log2(("vga: read SR%x = 0x%02x\n", pThis->sr_index, val)); + break; + case 0x3c7: + val = pThis->dac_state; + break; + case 0x3c8: + val = pThis->dac_write_index; + break; + case 0x3c9: + Assert(pThis->dac_sub_index < 3); + val = pThis->palette[pThis->dac_read_index * 3 + pThis->dac_sub_index]; + if (++pThis->dac_sub_index == 3) { + pThis->dac_sub_index = 0; + pThis->dac_read_index++; + } + break; + case 0x3ca: + val = pThis->fcr; + break; + case 0x3cc: + val = pThis->msr; + break; + case 0x3ce: + val = pThis->gr_index; + break; + case 0x3cf: + val = pThis->gr[pThis->gr_index]; + Log2(("vga: read GR%x = 0x%02x\n", pThis->gr_index, val)); + break; + case 0x3b4: + case 0x3d4: + val = pThis->cr_index; + break; + case 0x3b5: + case 0x3d5: + val = pThis->cr[pThis->cr_index]; + Log2(("vga: read CR%x = 0x%02x\n", pThis->cr_index, val)); + break; + case 0x3ba: + case 0x3da: + val = pThis->st01 = vga_retrace(pDevIns, pThis); + pThis->ar_flip_flop = 0; + break; + default: + val = 0x00; + break; + } + } + Log(("VGA: read addr=0x%04x data=0x%02x\n", addr, val)); + return val; +} + +static void vga_ioport_write(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t addr, uint32_t val) +{ + int index; + + Log(("VGA: write addr=0x%04x data=0x%02x\n", addr, val)); + + /* check port range access depending on color/monochrome mode */ + if (vga_ioport_invalid(pThis, addr)) { + Log(("VGA: previous write ignored\n")); + return; + } + + switch(addr) { + case 0x3c0: + case 0x3c1: + if (pThis->ar_flip_flop == 0) { + val &= 0x3f; + pThis->ar_index = val; + } else { + index = pThis->ar_index & 0x1f; + switch(index) { + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + pThis->ar[index] = val & 0x3f; + break; + case 0x10: + pThis->ar[index] = val & ~0x10; + break; + case 0x11: + pThis->ar[index] = val; + break; + case 0x12: + pThis->ar[index] = val & ~0xc0; + break; + case 0x13: + pThis->ar[index] = val & ~0xf0; + break; + case 0x14: + pThis->ar[index] = val & ~0xf0; + break; + default: + break; + } + } + pThis->ar_flip_flop ^= 1; + break; + case 0x3c2: + pThis->msr = val & ~0x10; + if (pThis->fRealRetrace) + vga_update_retrace_state(pThis); + /* The two clock select bits also determine which of the four switches + * is reflected in bit 4 of Input Status Register 0. + * This is EGA compatible behavior. See the IBM EGA Tech Ref. + */ + pThis->st00 = (pThis->st00 & ~0x10) | ((EGA_SWITCHES >> ((val >> 2) & 0x3) & 0x10)); + break; + case 0x3c4: + pThis->sr_index = val & 7; + break; + case 0x3c5: + Log2(("vga: write SR%x = 0x%02x\n", pThis->sr_index, val)); + pThis->sr[pThis->sr_index] = val & sr_mask[pThis->sr_index]; + /* Allow SR07 to disable VBE. */ + if (pThis->sr_index == 0x07 && !(val & 1)) + { + pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] = VBE_DISPI_DISABLED; + pThis->bank_offset = 0; + } + if (pThis->fRealRetrace && pThis->sr_index == 0x01) + vga_update_retrace_state(pThis); +#ifndef IN_RC + /* The VGA region is (could be) affected by this change; reset all aliases we've created. */ + if ( pThis->sr_index == 4 /* mode */ + || pThis->sr_index == 2 /* plane mask */) + { + if (pThis->bmPageRemappedVGA != 0) + { + PDMDevHlpMmioResetRegion(pDevIns, pThis->hMmioLegacy); + STAM_COUNTER_INC(&pThis->StatMapReset); + vgaResetRemapped(pThis); + } + } +#endif + break; + case 0x3c7: + pThis->dac_read_index = val; + pThis->dac_sub_index = 0; + pThis->dac_state = 3; + break; + case 0x3c8: + pThis->dac_write_index = val; + pThis->dac_sub_index = 0; + pThis->dac_state = 0; + break; + case 0x3c9: + Assert(pThis->dac_sub_index < 3); + pThis->dac_cache[pThis->dac_sub_index] = val; + if (++pThis->dac_sub_index == 3) { + memcpy(&pThis->palette[pThis->dac_write_index * 3], pThis->dac_cache, 3); + pThis->dac_sub_index = 0; + pThis->dac_write_index++; + } + break; + case 0x3ce: + pThis->gr_index = val & 0x0f; + break; + case 0x3cf: + Log2(("vga: write GR%x = 0x%02x\n", pThis->gr_index, val)); + Assert(pThis->gr_index < RT_ELEMENTS(gr_mask)); + pThis->gr[pThis->gr_index] = val & gr_mask[pThis->gr_index]; + +#ifndef IN_RC + /* The VGA region is (could be) affected by this change; reset all aliases we've created. */ + if (pThis->gr_index == 6 /* memory map mode */) + { + if (pThis->bmPageRemappedVGA != 0) + { + PDMDevHlpMmioResetRegion(pDevIns, pThis->hMmioLegacy); + STAM_COUNTER_INC(&pThis->StatMapReset); + vgaResetRemapped(pThis); + } + } +#endif + break; + + case 0x3b4: + case 0x3d4: + pThis->cr_index = val; + break; + case 0x3b5: + case 0x3d5: + Log2(("vga: write CR%x = 0x%02x\n", pThis->cr_index, val)); + /* handle CR0-7 protection */ + if ((pThis->cr[0x11] & 0x80) && pThis->cr_index <= 7) { + /* can always write bit 4 of CR7 */ + if (pThis->cr_index == 7) + pThis->cr[7] = (pThis->cr[7] & ~0x10) | (val & 0x10); + return; + } + pThis->cr[pThis->cr_index] = val; + + if (pThis->fRealRetrace) { + /* The following registers are only updated during a mode set. */ + switch(pThis->cr_index) { + case 0x00: + case 0x02: + case 0x03: + case 0x05: + case 0x06: + case 0x07: + case 0x09: + case 0x10: + case 0x11: + case 0x15: + case 0x16: + vga_update_retrace_state(pThis); + break; + } + } + break; + case 0x3ba: + case 0x3da: + pThis->fcr = val & 0x10; + break; + } +} + +#ifdef CONFIG_BOCHS_VBE + +static uint32_t vbe_read_cfg(PVGASTATE pThis) +{ + const uint16_t u16Cfg = pThis->vbe_regs[VBE_DISPI_INDEX_CFG]; + const uint16_t u16Id = u16Cfg & VBE_DISPI_CFG_MASK_ID; + const bool fQuerySupport = RT_BOOL(u16Cfg & VBE_DISPI_CFG_MASK_SUPPORT); + + uint32_t val = 0; + switch (u16Id) + { + case VBE_DISPI_CFG_ID_VERSION: val = 1; break; + case VBE_DISPI_CFG_ID_VRAM_SIZE: val = pThis->vram_size; break; + case VBE_DISPI_CFG_ID_3D: val = pThis->f3DEnabled; break; +# ifdef VBOX_WITH_VMSVGA + case VBE_DISPI_CFG_ID_VMSVGA: val = pThis->fVMSVGAEnabled; break; + case VBE_DISPI_CFG_ID_VMSVGA_DX: val = pThis->fVMSVGA10; break; +# endif + default: + return 0; /* Not supported. */ + } + + return fQuerySupport ? 1 : val; +} + +static uint32_t vbe_ioport_read_index(PVGASTATE pThis, uint32_t addr) +{ + uint32_t val = pThis->vbe_index; + NOREF(addr); + return val; +} + +static uint32_t vbe_ioport_read_data(PVGASTATE pThis, uint32_t addr) +{ + uint32_t val; + NOREF(addr); + + uint16_t const idxVbe = pThis->vbe_index; + if (idxVbe < VBE_DISPI_INDEX_NB) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + if (pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) + { + switch (idxVbe) + { + /* XXX: do not hardcode ? */ + case VBE_DISPI_INDEX_XRES: + val = VBE_DISPI_MAX_XRES; + break; + case VBE_DISPI_INDEX_YRES: + val = VBE_DISPI_MAX_YRES; + break; + case VBE_DISPI_INDEX_BPP: + val = VBE_DISPI_MAX_BPP; + break; + default: + Assert(idxVbe < VBE_DISPI_INDEX_NB); + val = pThis->vbe_regs[idxVbe]; + break; + } + } + else + { + switch (idxVbe) + { + case VBE_DISPI_INDEX_VBOX_VIDEO: + /* Reading from the port means that the old additions are requesting the number of monitors. */ + val = 1; + break; + case VBE_DISPI_INDEX_CFG: + val = vbe_read_cfg(pThis); + break; + default: + Assert(idxVbe < VBE_DISPI_INDEX_NB); + val = pThis->vbe_regs[idxVbe]; + break; + } + } + } + else + val = 0; + Log(("VBE: read index=0x%x val=0x%x\n", idxVbe, val)); + return val; +} + +# define VBE_PITCH_ALIGN 4 /* Align pitch to 32 bits - Qt requires that. */ + +/* Calculate scanline pitch based on bit depth and width in pixels. */ +static uint32_t calc_line_pitch(uint16_t bpp, uint16_t width) +{ + uint32_t pitch, aligned_pitch; + + if (bpp <= 4) + pitch = width >> 1; + else + pitch = width * ((bpp + 7) >> 3); + + /* Align the pitch to some sensible value. */ + aligned_pitch = (pitch + (VBE_PITCH_ALIGN - 1)) & ~(VBE_PITCH_ALIGN - 1); + if (aligned_pitch != pitch) + Log(("VBE: Line pitch %d aligned to %d bytes\n", pitch, aligned_pitch)); + + return aligned_pitch; +} + +static void recalculate_data(PVGASTATE pThis) +{ + uint16_t cBPP = pThis->vbe_regs[VBE_DISPI_INDEX_BPP]; + uint16_t cVirtWidth = pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH]; + uint16_t cX = pThis->vbe_regs[VBE_DISPI_INDEX_XRES]; + if (!cBPP || !cX) + return; /* Not enough data has been set yet. */ + uint32_t cbLinePitch = calc_line_pitch(cBPP, cVirtWidth); + if (!cbLinePitch) + cbLinePitch = calc_line_pitch(cBPP, cX); + if (!cbLinePitch) + return; + uint32_t cVirtHeight = pThis->vram_size / cbLinePitch; + uint16_t offX = pThis->vbe_regs[VBE_DISPI_INDEX_X_OFFSET]; + uint16_t offY = pThis->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET]; + uint32_t offStart = cbLinePitch * offY; + if (cBPP == 4) + offStart += offX >> 1; + else + offStart += offX * ((cBPP + 7) >> 3); + offStart >>= 2; + pThis->vbe_line_offset = RT_MIN(cbLinePitch, pThis->vram_size); + pThis->vbe_start_addr = RT_MIN(offStart, pThis->vram_size); + + /* The VBE_DISPI_INDEX_VIRT_HEIGHT is used to prevent setting resolution bigger than + * the VRAM size permits. It is used instead of VBE_DISPI_INDEX_YRES *only* in case + * pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] < pThis->vbe_regs[VBE_DISPI_INDEX_YRES]. + * Note that VBE_DISPI_INDEX_VIRT_HEIGHT has to be clipped to UINT16_MAX, which happens + * with small resolutions and big VRAM. */ + pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = cVirtHeight >= UINT16_MAX ? UINT16_MAX : (uint16_t)cVirtHeight; +} + +static void vbe_ioport_write_index(PVGASTATE pThis, uint32_t addr, uint32_t val) +{ + pThis->vbe_index = val; + NOREF(addr); +} + +static VBOXSTRICTRC vbe_ioport_write_data(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t addr, uint32_t val) +{ + uint32_t max_bank; + RT_NOREF(pThisCC, addr); + + if (pThis->vbe_index <= VBE_DISPI_INDEX_NB) { + bool fRecalculate = false; + Log(("VBE: write index=0x%x val=0x%x\n", pThis->vbe_index, val)); + switch(pThis->vbe_index) { + 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 || + /* VBox extensions. */ + val == VBE_DISPI_ID_VBOX_VIDEO || + val == VBE_DISPI_ID_ANYX || +# ifdef VBOX_WITH_HGSMI + val == VBE_DISPI_ID_HGSMI || +# endif + val == VBE_DISPI_ID_CFG) + { + pThis->vbe_regs[pThis->vbe_index] = val; + } + break; + case VBE_DISPI_INDEX_XRES: + if (val <= VBE_DISPI_MAX_XRES) + { + pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = val; + fRecalculate = true; + } + break; + case VBE_DISPI_INDEX_YRES: + if (val <= VBE_DISPI_MAX_YRES) + pThis->vbe_regs[pThis->vbe_index] = val; + break; + case VBE_DISPI_INDEX_BPP: + if (val == 0) + val = 8; + if (val == 4 || val == 8 || val == 15 || + val == 16 || val == 24 || val == 32) { + pThis->vbe_regs[pThis->vbe_index] = val; + fRecalculate = true; + } + break; + case VBE_DISPI_INDEX_BANK: + if (pThis->vbe_regs[VBE_DISPI_INDEX_BPP] <= 4) + max_bank = pThis->vbe_bank_max >> 2; /* Each bank really covers 256K */ + else + max_bank = pThis->vbe_bank_max; + /* Old software may pass garbage in the high byte of bank. If the maximum + * bank fits into a single byte, toss the high byte the user supplied. + */ + if (max_bank < 0x100) + val &= 0xff; + if (val > max_bank) + val = max_bank; + pThis->vbe_regs[pThis->vbe_index] = val; + pThis->bank_offset = (val << 16); + +# ifndef IN_RC + /* The VGA region is (could be) affected by this change; reset all aliases we've created. */ + if (pThis->bmPageRemappedVGA != 0) + { + PDMDevHlpMmioResetRegion(pDevIns, pThis->hMmioLegacy); + STAM_COUNTER_INC(&pThis->StatMapReset); + vgaResetRemapped(pThis); + } +# endif + break; + + case VBE_DISPI_INDEX_ENABLE: +# ifndef IN_RING3 + return VINF_IOM_R3_IOPORT_WRITE; +# else + { + if ((val & VBE_DISPI_ENABLED) && + !(pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) { + int h, shift_control; + /* Check the values before we screw up with a resolution which is too big or small. */ + size_t cb = pThis->vbe_regs[VBE_DISPI_INDEX_XRES]; + if (pThis->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) + cb = pThis->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1; + else + cb = pThis->vbe_regs[VBE_DISPI_INDEX_XRES] * ((pThis->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); + cb *= pThis->vbe_regs[VBE_DISPI_INDEX_YRES]; + uint16_t cVirtWidth = pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH]; + if (!cVirtWidth) + cVirtWidth = pThis->vbe_regs[VBE_DISPI_INDEX_XRES]; + if ( !cVirtWidth + || !pThis->vbe_regs[VBE_DISPI_INDEX_YRES] + || cb > pThis->vram_size) + { + AssertMsgFailed(("VIRT WIDTH=%d YRES=%d cb=%d vram_size=%d\n", + pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH], pThis->vbe_regs[VBE_DISPI_INDEX_YRES], cb, pThis->vram_size)); + return VINF_SUCCESS; /* Note: silent failure like before */ + } + + /* When VBE interface is enabled, it is reset. */ + pThis->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0; + pThis->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0; + fRecalculate = true; + + /* clear the screen (should be done in BIOS) */ + if (!(val & VBE_DISPI_NOCLEARMEM)) { + uint16_t cY = RT_MIN(pThis->vbe_regs[VBE_DISPI_INDEX_YRES], + pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT]); + uint16_t cbLinePitch = pThis->vbe_line_offset; + memset(pThisCC->pbVRam, 0, + cY * cbLinePitch); + } + + /* we initialize the VGA graphic mode (should be done + in BIOS) */ + pThis->gr[0x06] = (pThis->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */ + pThis->cr[0x17] |= 3; /* no CGA modes */ + pThis->cr[0x13] = pThis->vbe_line_offset >> 3; + /* width */ + pThis->cr[0x01] = (cVirtWidth >> 3) - 1; + /* height (only meaningful if < 1024) */ + h = pThis->vbe_regs[VBE_DISPI_INDEX_YRES] - 1; + pThis->cr[0x12] = h; + pThis->cr[0x07] = (pThis->cr[0x07] & ~0x42) | + ((h >> 7) & 0x02) | ((h >> 3) & 0x40); + /* line compare to 1023 */ + pThis->cr[0x18] = 0xff; + pThis->cr[0x07] |= 0x10; + pThis->cr[0x09] |= 0x40; + + if (pThis->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { + shift_control = 0; + pThis->sr[0x01] &= ~8; /* no double line */ + } else { + shift_control = 2; + pThis->sr[4] |= 0x08; /* set chain 4 mode */ + pThis->sr[2] |= 0x0f; /* activate all planes */ + /* Indicate non-VGA mode in SR07. */ + pThis->sr[7] |= 1; + } + pThis->gr[0x05] = (pThis->gr[0x05] & ~0x60) | (shift_control << 5); + pThis->cr[0x09] &= ~0x9f; /* no double scan */ + /* sunlover 30.05.2007 + * The ar_index remains with bit 0x20 cleared after a switch from fullscreen + * DOS mode on Windows XP guest. That leads to GMODE_BLANK in vgaR3UpdateDisplay. + * But the VBE mode is graphics, so not a blank anymore. + */ + pThis->ar_index |= 0x20; + } else { + /* XXX: the bios should do that */ + /* sunlover 21.12.2006 + * Here is probably more to reset. When this was executed in GC + * then the *update* functions could not detect a mode change. + * Or may be these update function should take the pThis->vbe_regs[pThis->vbe_index] + * into account when detecting a mode change. + * + * The 'mode reset not detected' problem is now fixed by executing the + * VBE_DISPI_INDEX_ENABLE case always in RING3 in order to call the + * LFBChange callback. + */ + pThis->bank_offset = 0; + } + pThis->vbe_regs[pThis->vbe_index] = val; + /* + * LFB video mode is either disabled or changed. Notify the display + * and reset VBVA. + */ + pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, (val & VBE_DISPI_ENABLED) != 0); +# ifdef VBOX_WITH_HGSMI + VBVAOnVBEChanged(pThis, pThisCC); +# endif + + /* The VGA region is (could be) affected by this change; reset all aliases we've created. */ + if (pThis->bmPageRemappedVGA != 0) + { + PDMDevHlpMmioResetRegion(pDevIns, pThis->hMmioLegacy); + STAM_COUNTER_INC(&pThis->StatMapReset); + vgaResetRemapped(pThis); + } + break; + } +# endif /* IN_RING3 */ + case VBE_DISPI_INDEX_VIRT_WIDTH: + case VBE_DISPI_INDEX_X_OFFSET: + case VBE_DISPI_INDEX_Y_OFFSET: + { + pThis->vbe_regs[pThis->vbe_index] = val; + fRecalculate = true; + } + break; + case VBE_DISPI_INDEX_VBOX_VIDEO: +# ifndef IN_RING3 + return VINF_IOM_R3_IOPORT_WRITE; +# else + /* Changes in the VGA device are minimal. The device is bypassed. The driver does all work. */ + if (val == VBOX_VIDEO_DISABLE_ADAPTER_MEMORY) + pThisCC->pDrv->pfnProcessAdapterData(pThisCC->pDrv, NULL, 0); + else if (val == VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY) + pThisCC->pDrv->pfnProcessAdapterData(pThisCC->pDrv, pThisCC->pbVRam, pThis->vram_size); + else if ((val & 0xFFFF0000) == VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE) + pThisCC->pDrv->pfnProcessDisplayData(pThisCC->pDrv, pThisCC->pbVRam, val & 0xFFFF); +# endif /* IN_RING3 */ + break; + case VBE_DISPI_INDEX_CFG: + pThis->vbe_regs[pThis->vbe_index] = val; + break; + default: + break; + } + + if (fRecalculate) + recalculate_data(pThis); + } + return VINF_SUCCESS; +} + +#endif /* CONFIG_BOCHS_VBE */ + +/* called for accesses between 0xa0000 and 0xc0000 */ +static uint32_t vga_mem_readb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS addr, int *prc) +{ + int plane; + uint32_t ret; + + Log3(("vga: read [0x%x] -> ", addr)); + +#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ + /* VMSVGA keeps the VGA and SVGA framebuffers separate unlike this boch-based + VGA implementation, so we fake it by going to ring-3 and using a heap buffer. */ + if (!pThis->svga.fEnabled) + { /*likely*/ } + else + { + *prc = VINF_IOM_R3_MMIO_READ; + return 0; + } +#endif + + + /* convert to VGA memory offset */ + addr &= 0x1ffff; +#ifndef IN_RC + RTGCPHYS const offMmio = addr; /* save original MMIO range offset */ +#endif + + int const memory_map_mode = (pThis->gr[6] >> 2) & 3; + switch(memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return 0xff; + addr += pThis->bank_offset; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return 0xff; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return 0xff; + break; + } + + if (pThis->sr[4] & 0x08) { + /* chain 4 mode : simplest access */ +#ifndef IN_RC + /* If all planes are accessible, then map the page to the frame buffer and make it writable. */ + if ( (pThis->sr[2] & 3) == 3 + && !vgaIsRemapped(pThis, offMmio) + && pThis->GCPhysVRAM) + { + /** @todo only allow read access (doesn't work now) */ + STAM_COUNTER_INC(&pThis->StatMapPage); + PDMDevHlpMmioMapMmio2Page(pDevIns, pThis->hMmioLegacy, offMmio, pThis->hMmio2VRam, addr, X86_PTE_RW | X86_PTE_P); + /* Set as dirty as write accesses won't be noticed now. */ + vgaR3MarkDirty(pThis, addr); + vgaMarkRemapped(pThis, offMmio); + } +#endif /* !IN_RC */ + VERIFY_VRAM_READ_OFF_RETURN(pThis, addr, *prc); +#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 + ret = !pThis->svga.fEnabled ? pThisCC->pbVRam[addr] + : addr < VMSVGA_VGA_FB_BACKUP_SIZE ? pThisCC->svga.pbVgaFrameBufferR3[addr] : 0xff; +#else + ret = pThisCC->pbVRam[addr]; +#endif + } else if (!(pThis->sr[4] & 0x04)) { /* Host access is controlled by SR4, not GR5! */ + /* odd/even mode (aka text mode mapping) */ + plane = (pThis->gr[4] & 2) | (addr & 1); + /* See the comment for a similar line in vga_mem_writeb. */ + RTGCPHYS off = ((addr & ~1) * 4) | plane; + VERIFY_VRAM_READ_OFF_RETURN(pThis, off, *prc); +#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 + ret = !pThis->svga.fEnabled ? pThisCC->pbVRam[off] + : off < VMSVGA_VGA_FB_BACKUP_SIZE ? pThisCC->svga.pbVgaFrameBufferR3[off] : 0xff; +#else + ret = pThisCC->pbVRam[off]; +#endif + } else { + /* standard VGA latched access */ + VERIFY_VRAM_READ_OFF_RETURN(pThis, addr * 4 + 3, *prc); +#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 + pThis->latch = !pThis->svga.fEnabled ? ((uint32_t *)pThisCC->pbVRam)[addr] + : addr * 4 + 3 < VMSVGA_VGA_FB_BACKUP_SIZE ? ((uint32_t *)pThisCC->svga.pbVgaFrameBufferR3)[addr] : UINT32_MAX; +#else + pThis->latch = ((uint32_t *)pThisCC->pbVRam)[addr]; +#endif + if (!(pThis->gr[5] & 0x08)) { + /* read mode 0 */ + plane = pThis->gr[4]; + ret = GET_PLANE(pThis->latch, plane); + } else { + /* read mode 1 */ + ret = (pThis->latch ^ mask16[pThis->gr[2]]) & mask16[pThis->gr[7]]; + ret |= ret >> 16; + ret |= ret >> 8; + ret = (~ret) & 0xff; + } + } + Log3((" 0x%02x\n", ret)); + return ret; +} + +/** + * called for accesses between 0xa0000 and 0xc0000 + */ +static VBOXSTRICTRC vga_mem_writeb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS addr, uint32_t val) +{ + int plane, write_mode, b, func_select, mask; + uint32_t write_mask, bit_mask, set_mask; + + Log3(("vga: [0x%x] = 0x%02x\n", addr, val)); + +#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ + /* VMSVGA keeps the VGA and SVGA framebuffers separate unlike this boch-based + VGA implementation, so we fake it by going to ring-3 and using a heap buffer. */ + if (!pThis->svga.fEnabled) { /*likely*/ } + else return VINF_IOM_R3_MMIO_WRITE; +#endif + + /* convert to VGA memory offset */ + addr &= 0x1ffff; +#ifndef IN_RC + RTGCPHYS const offMmio = addr; /* save original MMIO range offset */ +#endif + + int const memory_map_mode = (pThis->gr[6] >> 2) & 3; + switch(memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return VINF_SUCCESS; + addr += pThis->bank_offset; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return VINF_SUCCESS; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return VINF_SUCCESS; + break; + } + + if (pThis->sr[4] & 0x08) { + /* chain 4 mode : simplest access */ + plane = addr & 3; + mask = (1 << plane); + if (pThis->sr[2] & mask) { +#ifndef IN_RC + /* If all planes are accessible, then map the page to the frame buffer and make it writable. */ + if ( (pThis->sr[2] & 3) == 3 + && !vgaIsRemapped(pThis, offMmio) + && pThis->GCPhysVRAM) + { + STAM_COUNTER_INC(&pThis->StatMapPage); + PDMDevHlpMmioMapMmio2Page(pDevIns, pThis->hMmioLegacy, offMmio, pThis->hMmio2VRam, addr, X86_PTE_RW | X86_PTE_P); + vgaMarkRemapped(pThis, offMmio); + } +#endif /* !IN_RC */ + + VERIFY_VRAM_WRITE_OFF_RETURN(pThis, addr); +#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 + if (!pThis->svga.fEnabled) + pThisCC->pbVRam[addr] = val; + else if (addr < VMSVGA_VGA_FB_BACKUP_SIZE) + pThisCC->svga.pbVgaFrameBufferR3[addr] = val; + else + { + Log(("vga: chain4: out of vmsvga VGA framebuffer bounds! addr=%#x\n", addr)); + return VINF_SUCCESS; + } +#else + pThisCC->pbVRam[addr] = val; +#endif + Log3(("vga: chain4: [0x%x]\n", addr)); + pThis->plane_updated |= mask; /* only used to detect font change */ + vgaR3MarkDirty(pThis, addr); + } + } else if (!(pThis->sr[4] & 0x04)) { /* Host access is controlled by SR4, not GR5! */ + /* odd/even mode (aka text mode mapping); GR4 does not affect writes! */ + plane = addr & 1; + mask = (1 << plane); + if (pThis->sr[2] & mask) { + /* 'addr' is offset in a plane, bit 0 selects the plane. + * Mask the bit 0, convert plane index to vram offset, + * that is multiply by the number of planes, + * and select the plane byte in the vram offset. + */ + addr = ((addr & ~1) * 4) | plane; + VERIFY_VRAM_WRITE_OFF_RETURN(pThis, addr); +#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 + if (!pThis->svga.fEnabled) + pThisCC->pbVRam[addr] = val; + else if (addr < VMSVGA_VGA_FB_BACKUP_SIZE) + pThisCC->svga.pbVgaFrameBufferR3[addr] = val; + else + { + Log(("vga: odd/even: out of vmsvga VGA framebuffer bounds! addr=%#x\n", addr)); + return VINF_SUCCESS; + } +#else + pThisCC->pbVRam[addr] = val; +#endif + Log3(("vga: odd/even: [0x%x]\n", addr)); + pThis->plane_updated |= mask; /* only used to detect font change */ + vgaR3MarkDirty(pThis, addr); + } + } else { + /* standard VGA latched access */ + VERIFY_VRAM_WRITE_OFF_RETURN(pThis, addr * 4 + 3); + + write_mode = pThis->gr[5] & 3; + switch(write_mode) { + default: + case 0: + /* rotate */ + b = pThis->gr[3] & 7; + val = ((val >> b) | (val << (8 - b))) & 0xff; + val |= val << 8; + val |= val << 16; + + /* apply set/reset mask */ + set_mask = mask16[pThis->gr[1]]; + val = (val & ~set_mask) | (mask16[pThis->gr[0]] & set_mask); + bit_mask = pThis->gr[8]; + break; + case 1: + val = pThis->latch; + goto do_write; + case 2: + val = mask16[val & 0x0f]; + bit_mask = pThis->gr[8]; + break; + case 3: + /* rotate */ + b = pThis->gr[3] & 7; + val = (val >> b) | (val << (8 - b)); + + bit_mask = pThis->gr[8] & val; + val = mask16[pThis->gr[0]]; + break; + } + + /* apply logical operation */ + func_select = pThis->gr[3] >> 3; + switch(func_select) { + case 0: + default: + /* nothing to do */ + break; + case 1: + /* and */ + val &= pThis->latch; + break; + case 2: + /* or */ + val |= pThis->latch; + break; + case 3: + /* xor */ + val ^= pThis->latch; + break; + } + + /* apply bit mask */ + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + val = (val & bit_mask) | (pThis->latch & ~bit_mask); + + do_write: + /* mask data according to sr[2] */ + mask = pThis->sr[2]; + pThis->plane_updated |= mask; /* only used to detect font change */ + write_mask = mask16[mask]; +#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3 + uint32_t *pu32Dst; + if (!pThis->svga.fEnabled) + pu32Dst = &((uint32_t *)pThisCC->pbVRam)[addr]; + else if (addr * 4 + 3 < VMSVGA_VGA_FB_BACKUP_SIZE) + pu32Dst = &((uint32_t *)pThisCC->svga.pbVgaFrameBufferR3)[addr]; + else + { + Log(("vga: latch: out of vmsvga VGA framebuffer bounds! addr=%#x\n", addr)); + return VINF_SUCCESS; + } + *pu32Dst = (*pu32Dst & ~write_mask) | (val & write_mask); +#else + ((uint32_t *)pThisCC->pbVRam)[addr] = (((uint32_t *)pThisCC->pbVRam)[addr] & ~write_mask) + | (val & write_mask); +#endif + Log3(("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", addr * 4, write_mask, val)); + vgaR3MarkDirty(pThis, (addr * 4)); + } + + return VINF_SUCCESS; +} + +#ifdef IN_RING3 + +typedef void vga_draw_glyph8_func(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol, + int dscan); +typedef void vga_draw_glyph9_func(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol, int dup9); +typedef void vga_draw_line_func(PVGASTATE pThis, PVGASTATECC pThisCC, uint8_t *pbDst, const uint8_t *pbSrc, int width); + +static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6); +} + +static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); +} + +static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); +} + +static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b) +{ + return (r << 16) | (g << 8) | b; +} + +#define DEPTH 8 +#include "DevVGATmpl.h" + +#define DEPTH 15 +#include "DevVGATmpl.h" + +#define DEPTH 16 +#include "DevVGATmpl.h" + +#define DEPTH 32 +#include "DevVGATmpl.h" + +static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel8(r, g, b); + col |= col << 8; + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel15(r, g, b); + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel16(r, g, b); + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b) +{ + return rgb_to_pixel32(r, g, b); +} + +/** return true if the palette was modified */ +static bool vgaR3UpdatePalette16(PVGASTATE pThis, PVGASTATER3 pThisCC) +{ + bool full_update = false; + int i; + uint32_t v, col, *palette; + + palette = pThis->last_palette; + for(i = 0; i < 16; i++) { + v = pThis->ar[i]; + if (pThis->ar[0x10] & 0x80) + v = ((pThis->ar[0x14] & 0xf) << 4) | (v & 0xf); + else + v = ((pThis->ar[0x14] & 0xc) << 4) | (v & 0x3f); + v = v * 3; + col = pThisCC->rgb_to_pixel(c6_to_8(pThis->palette[v]), + c6_to_8(pThis->palette[v + 1]), + c6_to_8(pThis->palette[v + 2])); + if (col != palette[i]) { + full_update = true; + palette[i] = col; + } + } + return full_update; +} + +/** return true if the palette was modified */ +static bool vgaR3UpdatePalette256(PVGASTATE pThis, PVGASTATER3 pThisCC) +{ + bool full_update = false; + int i; + uint32_t v, col, *palette; + int wide_dac; + + palette = pThis->last_palette; + v = 0; + wide_dac = (pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & (VBE_DISPI_ENABLED | VBE_DISPI_8BIT_DAC)) + == (VBE_DISPI_ENABLED | VBE_DISPI_8BIT_DAC); + for(i = 0; i < 256; i++) { + if (wide_dac) + col = pThisCC->rgb_to_pixel(pThis->palette[v], + pThis->palette[v + 1], + pThis->palette[v + 2]); + else + col = pThisCC->rgb_to_pixel(c6_to_8(pThis->palette[v]), + c6_to_8(pThis->palette[v + 1]), + c6_to_8(pThis->palette[v + 2])); + if (col != palette[i]) { + full_update = true; + palette[i] = col; + } + v += 3; + } + return full_update; +} + +static void vgaR3GetOffsets(PVGASTATE pThis, + uint32_t *pline_offset, + uint32_t *pstart_addr, + uint32_t *pline_compare) +{ + uint32_t start_addr, line_offset, line_compare; +#ifdef CONFIG_BOCHS_VBE + if (pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { + line_offset = pThis->vbe_line_offset; + start_addr = pThis->vbe_start_addr; + line_compare = 65535; + } else +#endif + { + /* compute line_offset in bytes */ + line_offset = pThis->cr[0x13]; + line_offset <<= 3; + if (!(pThis->cr[0x14] & 0x40) && !(pThis->cr[0x17] & 0x40)) + { + /* Word mode. Used for odd/even modes. */ + line_offset *= 2; + } + + /* starting address */ + start_addr = pThis->cr[0x0d] | (pThis->cr[0x0c] << 8); + + /* line compare */ + line_compare = pThis->cr[0x18] | + ((pThis->cr[0x07] & 0x10) << 4) | + ((pThis->cr[0x09] & 0x40) << 3); + } + *pline_offset = line_offset; + *pstart_addr = start_addr; + *pline_compare = line_compare; +} + +/** update start_addr and line_offset. Return TRUE if modified */ +static bool vgaR3UpdateBasicParams(PVGASTATE pThis, PVGASTATER3 pThisCC) +{ + bool full_update = false; + uint32_t start_addr, line_offset, line_compare; + + pThisCC->get_offsets(pThis, &line_offset, &start_addr, &line_compare); + + if (line_offset != pThis->line_offset || + start_addr != pThis->start_addr || + line_compare != pThis->line_compare) { + pThis->line_offset = line_offset; + pThis->start_addr = start_addr; + pThis->line_compare = line_compare; + full_update = true; + } + return full_update; +} + +static inline int vgaR3GetDepthIndex(int depth) +{ + switch(depth) { + default: + case 8: + return 0; + case 15: + return 1; + case 16: + return 2; + case 32: + return 3; + } +} + +static vga_draw_glyph8_func * const vga_draw_glyph8_table[4] = { + vga_draw_glyph8_8, + vga_draw_glyph8_16, + vga_draw_glyph8_16, + vga_draw_glyph8_32, +}; + +static vga_draw_glyph8_func * const vga_draw_glyph16_table[4] = { + vga_draw_glyph16_8, + vga_draw_glyph16_16, + vga_draw_glyph16_16, + vga_draw_glyph16_32, +}; + +static vga_draw_glyph9_func * const vga_draw_glyph9_table[4] = { + vga_draw_glyph9_8, + vga_draw_glyph9_16, + vga_draw_glyph9_16, + vga_draw_glyph9_32, +}; + +static const uint8_t cursor_glyph[32 * 4] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static const uint8_t empty_glyph[32 * 4] = { 0 }; + +/** + * Text mode update + */ +static int vgaR3DrawText(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATER3 pThisCC, bool full_update, + bool fFailOnResize, bool reset_dirty, PDMIDISPLAYCONNECTOR *pDrv) +{ + int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr; + int cx_min, cx_max, linesize, x_incr; + int cx_min_upd, cx_max_upd, cy_start; + uint32_t offset, fgcol, bgcol, v, cursor_offset; + uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr; + const uint8_t *font_ptr, *font_base[2]; + int dup9, line_offset, depth_index, dscan; + uint32_t *palette; + uint32_t *ch_attr_ptr; + vga_draw_glyph8_func *vga_draw_glyph8; + vga_draw_glyph9_func *vga_draw_glyph9; + uint64_t time_ns; + bool blink_on, chr_blink_flip, cur_blink_flip; + bool blink_enabled, blink_do_redraw; + int uline_pos; + int s_incr; + + full_update |= vgaR3UpdatePalette16(pThis, pThisCC); + palette = pThis->last_palette; + + /* compute font data address (in plane 2) */ + v = pThis->sr[3]; + offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2; + if (offset != pThis->font_offsets[0]) { + pThis->font_offsets[0] = offset; + full_update = true; + } + font_base[0] = pThisCC->pbVRam + offset; + + offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2; + font_base[1] = pThisCC->pbVRam + offset; + if (offset != pThis->font_offsets[1]) { + pThis->font_offsets[1] = offset; + full_update = true; + } + if (pThis->plane_updated & (1 << 2)) { + /* if the plane 2 was modified since the last display, it + indicates the font may have been modified */ + pThis->plane_updated = 0; + full_update = true; + } + + /* Underline position */ + uline_pos = pThis->cr[0x14] & 0x1f; + if (uline_pos != pThis->last_uline) { + pThis->last_uline = uline_pos; + full_update = true; + } + + blink_enabled = !!(pThis->ar[0x10] & 0x08); /* Attribute controller blink enable. */ + if (blink_enabled != pThis->last_blink) { + pThis->last_blink = blink_enabled; + full_update = true; + } + + full_update |= vgaR3UpdateBasicParams(pThis, pThisCC); + + /* Evaluate word/byte mode. Need to count by 4 because text is only in plane 0. */ + s_incr = pThis->cr[0x17] & 0x40 ? 4 : 8; + + unsigned addr_mask; + if (!(pThis->cr[0x17] & 0x40) && !(pThis->cr[0x17] & 0x20)) + addr_mask = 0xffff; /* Wrap at 64K, for CGA and 64K EGA compatibility. */ + else + addr_mask = 0x3ffff; /* Wrap at 256K, standard VGA. */ + + line_offset = pThis->line_offset; + s1 = pThisCC->pbVRam + ((pThis->start_addr * s_incr) & addr_mask); + + /* double scanning - not for 9-wide modes */ + dscan = (pThis->cr[9] >> 7) & 1; + + /* total width & height */ + cheight = (pThis->cr[9] & 0x1f) + 1; + cw = 8; + if (!(pThis->sr[1] & 0x01)) + cw = 9; + if (pThis->sr[1] & 0x08) + cw = 16; /* NOTE: no 18 pixel wide */ + x_incr = cw * ((pDrv->cBits + 7) >> 3); + width = (pThis->cr[0x01] + 1); + if (pThis->cr[0x06] == 100) { + /* ugly hack for CGA 160x100x16 - explain me the logic */ + height = 100; + } else { + height = pThis->cr[0x12] | + ((pThis->cr[0x07] & 0x02) << 7) | + ((pThis->cr[0x07] & 0x40) << 3); + height = (height + 1) / cheight; + } + /** @todo r=michaln This conditional is questionable; we should be able + * to draw whatver the guest asks for. */ + if ((height * width) > CH_ATTR_SIZE) { + /* better than nothing: exit if transient size is too big */ + return VINF_SUCCESS; + } + + if (width != (int)pThis->last_width || height != (int)pThis->last_height || + cw != pThis->last_cw || cheight != pThis->last_ch) { + if (fFailOnResize) + { + /* The caller does not want to call the pfnResize. */ + return VERR_TRY_AGAIN; + } + pThis->last_scr_width = width * cw; + pThis->last_scr_height = height * cheight; + /* For text modes the direct use of guest VRAM is not implemented, so bpp and cbLine are 0 here. */ + int rc = pDrv->pfnResize(pDrv, 0, NULL, 0, pThis->last_scr_width, pThis->last_scr_height); + pThis->last_width = width; + pThis->last_height = height; + pThis->last_ch = cheight; + pThis->last_cw = cw; + full_update = true; + if (rc == VINF_VGA_RESIZE_IN_PROGRESS) + return rc; + AssertRC(rc); + } + cursor_offset = ((pThis->cr[0x0e] << 8) | pThis->cr[0x0f]) - pThis->start_addr; + if (cursor_offset != pThis->cursor_offset || + pThis->cr[0xa] != pThis->cursor_start || + pThis->cr[0xb] != pThis->cursor_end) { + /* if the cursor position changed, we update the old and new + chars */ + if (pThis->cursor_offset < CH_ATTR_SIZE) + pThis->last_ch_attr[pThis->cursor_offset] = UINT32_MAX; + if (cursor_offset < CH_ATTR_SIZE) + pThis->last_ch_attr[cursor_offset] = UINT32_MAX; + pThis->cursor_offset = cursor_offset; + pThis->cursor_start = pThis->cr[0xa]; + pThis->cursor_end = pThis->cr[0xb]; + } + cursor_ptr = pThisCC->pbVRam + (((pThis->start_addr + cursor_offset) * s_incr) & addr_mask); + depth_index = vgaR3GetDepthIndex(pDrv->cBits); + if (cw == 16) + vga_draw_glyph8 = vga_draw_glyph16_table[depth_index]; + else + vga_draw_glyph8 = vga_draw_glyph8_table[depth_index]; + vga_draw_glyph9 = vga_draw_glyph9_table[depth_index]; + + dest = pDrv->pbData; + linesize = pDrv->cbScanline; + ch_attr_ptr = pThis->last_ch_attr; + cy_start = -1; + cx_max_upd = -1; + cx_min_upd = width; + + /* Figure out if we're in the visible period of the blink cycle. */ + time_ns = PDMDevHlpTMTimeVirtGetNano(pDevIns); + blink_on = (time_ns % VGA_BLINK_PERIOD_FULL) < VGA_BLINK_PERIOD_ON; + chr_blink_flip = false; + cur_blink_flip = false; + if (pThis->last_chr_blink != blink_on) + { + /* Currently cursor and characters blink at the same rate, but they might not. */ + pThis->last_chr_blink = blink_on; + pThis->last_cur_blink = blink_on; + chr_blink_flip = true; + cur_blink_flip = true; + } + + for(cy = 0; cy < (height - dscan); cy = cy + (1 << dscan)) { + d1 = dest; + src = s1; + cx_min = width; + cx_max = -1; + for(cx = 0; cx < width; cx++) { + ch_attr = *(uint16_t *)src; + /* Figure out if character needs redrawing due to blink state change. */ + blink_do_redraw = blink_enabled && chr_blink_flip && (ch_attr & 0x8000); + if (full_update || ch_attr != (int)*ch_attr_ptr || blink_do_redraw || (src == cursor_ptr && cur_blink_flip)) { + if (cx < cx_min) + cx_min = cx; + if (cx > cx_max) + cx_max = cx; + if (reset_dirty) + *ch_attr_ptr = ch_attr; +#ifdef WORDS_BIGENDIAN + ch = ch_attr >> 8; + cattr = ch_attr & 0xff; +#else + ch = ch_attr & 0xff; + cattr = ch_attr >> 8; +#endif + font_ptr = font_base[(cattr >> 3) & 1]; + font_ptr += 32 * 4 * ch; + bgcol = palette[cattr >> 4]; + fgcol = palette[cattr & 0x0f]; + + if (blink_enabled && (cattr & 0x80)) + { + bgcol = palette[(cattr >> 4) & 7]; + if (!blink_on) + font_ptr = empty_glyph; + } + + if (cw != 9) { + if (pThis->fRenderVRAM) + vga_draw_glyph8(d1, linesize, font_ptr, cheight, fgcol, bgcol, dscan); + } else { + dup9 = 0; + if (ch >= 0xb0 && ch <= 0xdf && (pThis->ar[0x10] & 0x04)) + dup9 = 1; + if (pThis->fRenderVRAM) + vga_draw_glyph9(d1, linesize, font_ptr, cheight, fgcol, bgcol, dup9); + } + + /* Underline. Typically turned off by setting it past cell height. */ + if (((cattr & 0x03) == 1) && (uline_pos < cheight)) + { + int h; + + d = d1 + (linesize * uline_pos << dscan); + h = 1; + + if (cw != 9) { + if (pThis->fRenderVRAM) + vga_draw_glyph8(d, linesize, cursor_glyph, h, fgcol, bgcol, dscan); + } else { + if (pThis->fRenderVRAM) + vga_draw_glyph9(d, linesize, cursor_glyph, h, fgcol, bgcol, 1); + } + } + + /* Cursor. */ + if (src == cursor_ptr && + !(pThis->cr[0x0a] & 0x20)) { + int line_start, line_last, h; + + /* draw the cursor if within the visible period */ + if (blink_on) { + line_start = pThis->cr[0x0a] & 0x1f; + line_last = pThis->cr[0x0b] & 0x1f; + /* XXX: check that */ + if (line_last > cheight - 1) + line_last = cheight - 1; + if (line_last >= line_start && line_start < cheight) { + h = line_last - line_start + 1; + d = d1 + (linesize * line_start << dscan); + if (cw != 9) { + if (pThis->fRenderVRAM) + vga_draw_glyph8(d, linesize, cursor_glyph, h, fgcol, bgcol, dscan); + } else { + if (pThis->fRenderVRAM) + vga_draw_glyph9(d, linesize, cursor_glyph, h, fgcol, bgcol, 1); + } + } + } + } + } + d1 += x_incr; + src += s_incr; /* Even in text mode, word/byte mode matters. */ + if (src > (pThisCC->pbVRam + addr_mask)) + src = pThisCC->pbVRam; + ch_attr_ptr++; + } + if (cx_max != -1) { + /* Keep track of the bounding rectangle for updates. */ + if (cy_start == -1) + cy_start = cy; + if (cx_min_upd > cx_min) + cx_min_upd = cx_min; + if (cx_max_upd < cx_max) + cx_max_upd = cx_max; + } else if (cy_start >= 0) { + /* Flush updates to display. */ + pDrv->pfnUpdateRect(pDrv, cx_min_upd * cw, cy_start * cheight, + (cx_max_upd - cx_min_upd + 1) * cw, (cy - cy_start) * cheight); + cy_start = -1; + cx_max_upd = -1; + cx_min_upd = width; + } + + dest += linesize * cheight << dscan; + s1 += line_offset; + + /* Line compare works in text modes, too. */ + /** @todo r=michaln This is inaccurate; text should be rendered line by line + * and line compare checked after every line. */ + if ((uint32_t)cy == (pThis->line_compare / cheight)) + s1 = pThisCC->pbVRam; + + if (s1 > (pThisCC->pbVRam + addr_mask)) + s1 = s1 - (addr_mask + 1); + } + if (cy_start >= 0) + /* Flush any remaining changes to display. */ + pDrv->pfnUpdateRect(pDrv, cx_min_upd * cw, cy_start * cheight, + (cx_max_upd - cx_min_upd + 1) * cw, (cy - cy_start) * cheight); + return VINF_SUCCESS; +} + +enum { + VGA_DRAW_LINE2, + VGA_DRAW_LINE2D2, + VGA_DRAW_LINE4, + VGA_DRAW_LINE4D2, + VGA_DRAW_LINE8D2, + VGA_DRAW_LINE8, + VGA_DRAW_LINE15, + VGA_DRAW_LINE16, + VGA_DRAW_LINE24, + VGA_DRAW_LINE32, + VGA_DRAW_LINE_NB +}; + +static vga_draw_line_func * const vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = { + vga_draw_line2_8, + vga_draw_line2_16, + vga_draw_line2_16, + vga_draw_line2_32, + + vga_draw_line2d2_8, + vga_draw_line2d2_16, + vga_draw_line2d2_16, + vga_draw_line2d2_32, + + vga_draw_line4_8, + vga_draw_line4_16, + vga_draw_line4_16, + vga_draw_line4_32, + + vga_draw_line4d2_8, + vga_draw_line4d2_16, + vga_draw_line4d2_16, + vga_draw_line4d2_32, + + vga_draw_line8d2_8, + vga_draw_line8d2_16, + vga_draw_line8d2_16, + vga_draw_line8d2_32, + + vga_draw_line8_8, + vga_draw_line8_16, + vga_draw_line8_16, + vga_draw_line8_32, + + vga_draw_line15_8, + vga_draw_line15_15, + vga_draw_line15_16, + vga_draw_line15_32, + + vga_draw_line16_8, + vga_draw_line16_15, + vga_draw_line16_16, + vga_draw_line16_32, + + vga_draw_line24_8, + vga_draw_line24_15, + vga_draw_line24_16, + vga_draw_line24_32, + + vga_draw_line32_8, + vga_draw_line32_15, + vga_draw_line32_16, + vga_draw_line32_32, +}; + +static int vgaR3GetBpp(PVGASTATE pThis) +{ + int ret; +#ifdef CONFIG_BOCHS_VBE + if (pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { + ret = pThis->vbe_regs[VBE_DISPI_INDEX_BPP]; + } else +#endif + { + ret = 0; + } + return ret; +} + +static void vgaR3GetResolution(PVGASTATE pThis, int *pwidth, int *pheight) +{ + int width, height; +#ifdef CONFIG_BOCHS_VBE + if (pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { + width = pThis->vbe_regs[VBE_DISPI_INDEX_XRES]; + height = RT_MIN(pThis->vbe_regs[VBE_DISPI_INDEX_YRES], + pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT]); + } else +#endif + { + width = (pThis->cr[0x01] + 1) * 8; + height = pThis->cr[0x12] | + ((pThis->cr[0x07] & 0x02) << 7) | + ((pThis->cr[0x07] & 0x40) << 3); + height = (height + 1); + } + *pwidth = width; + *pheight = height; +} + + +/** + * Performs the display driver resizing when in graphics mode. + * + * This will recalc / update any status data depending on the driver + * properties (bit depth mostly). + * + * @returns VINF_SUCCESS on success. + * @returns VINF_VGA_RESIZE_IN_PROGRESS if the operation wasn't complete. + * @param pThis Pointer to the shared VGA state. + * @param pThisCC Pointer to the ring-3 VGA state. + * @param cx The width. + * @param cy The height. + * @param pDrv The display connector. + */ +static int vgaR3ResizeGraphic(PVGASTATE pThis, PVGASTATER3 pThisCC, int cx, int cy, PDMIDISPLAYCONNECTOR *pDrv) +{ + const unsigned cBits = pThisCC->get_bpp(pThis); + + int rc; + AssertReturn(cx, VERR_INVALID_PARAMETER); + AssertReturn(cy, VERR_INVALID_PARAMETER); + AssertPtrReturn(pThis, VERR_INVALID_POINTER); + + if (!pThis->line_offset) + return VERR_INTERNAL_ERROR; + +#if 0 //def VBOX_WITH_VDMA + /** @todo we get a second resize here when VBVA is on, while we actually should not */ + /* do not do pfnResize in case VBVA is on since all mode changes are performed over VBVA + * we are checking for VDMA state here to ensure this code works only for WDDM driver, + * although we should avoid calling pfnResize for XPDM as well, since pfnResize is actually an extra resize + * event and generally only pfnVBVAxxx calls should be used with HGSMI + VBVA + * + * The reason for doing this for WDDM driver only now is to avoid regressions of the current code */ + PVBOXVDMAHOST pVdma = pThisCC->pVdma; + if (pVdma && vboxVDMAIsEnabled(pVdma)) + rc = VINF_SUCCESS; + else +#endif + { + /* Skip the resize if the values are not valid. */ + if (pThis->start_addr * 4 + pThis->line_offset * cy < pThis->vram_size) + /* Take into account the programmed start address (in DWORDs) of the visible screen. */ + rc = pDrv->pfnResize(pDrv, cBits, pThisCC->pbVRam + pThis->start_addr * 4, pThis->line_offset, cx, cy); + else + { + /* Change nothing in the VGA state. Lets hope the guest will eventually programm correct values. */ + return VERR_TRY_AGAIN; + } + } + + /* last stuff */ + pThis->last_bpp = cBits; + pThis->last_scr_width = cx; + pThis->last_scr_height = cy; + pThis->last_width = cx; + pThis->last_height = cy; + + if (rc == VINF_VGA_RESIZE_IN_PROGRESS) + return rc; + AssertRC(rc); + + /* update palette */ + switch (pDrv->cBits) + { + case 32: pThisCC->rgb_to_pixel = rgb_to_pixel32_dup; break; + case 16: + default: pThisCC->rgb_to_pixel = rgb_to_pixel16_dup; break; + case 15: pThisCC->rgb_to_pixel = rgb_to_pixel15_dup; break; + case 8: pThisCC->rgb_to_pixel = rgb_to_pixel8_dup; break; + } + if (pThis->shift_control == 0) + vgaR3UpdatePalette16(pThis, pThisCC); + else if (pThis->shift_control == 1) + vgaR3UpdatePalette16(pThis, pThisCC); + return VINF_SUCCESS; +} + +# ifdef VBOX_WITH_VMSVGA + +# if 0 /* unused? */ +int vgaR3UpdateDisplay(PVGASTATE pThis, PVGASTATER3 pThisCC, unsigned xStart, unsigned yStart, unsigned cx, unsigned cy, PDMIDISPLAYCONNECTOR *pDrv) +{ + uint32_t v; + vga_draw_line_func *vga_draw_line; + + if (!pThis->fRenderVRAM) + { + pDrv->pfnUpdateRect(pDrv, xStart, yStart, cx, cy); + return VINF_SUCCESS; + } + /** @todo might crash if a blit follows a resolution change very quickly (seen this many times!) */ + + if ( pThis->svga.uWidth == VMSVGA_VAL_UNINITIALIZED + || pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED + || pThis->svga.uBpp == VMSVGA_VAL_UNINITIALIZED) + { + /* Intermediate state; skip redraws. */ + AssertFailed(); + return VINF_SUCCESS; + } + + uint32_t cBits; + switch (pThis->svga.uBpp) { + default: + case 0: + case 8: + AssertFailed(); + return VERR_NOT_IMPLEMENTED; + case 15: + v = VGA_DRAW_LINE15; + cBits = 16; + break; + case 16: + v = VGA_DRAW_LINE16; + cBits = 16; + break; + case 24: + v = VGA_DRAW_LINE24; + cBits = 24; + break; + case 32: + v = VGA_DRAW_LINE32; + cBits = 32; + break; + } + vga_draw_line = vga_draw_line_table[v * 4 + vgaR3GetDepthIndex(pDrv->cBits)]; + + uint32_t offSrc = (xStart * cBits) / 8 + pThis->svga.cbScanline * yStart; + uint32_t offDst = (xStart * RT_ALIGN(pDrv->cBits, 8)) / 8 + pDrv->cbScanline * yStart; + + uint8_t *pbDst = pDrv->pbData + offDst; + uint8_t const *pbSrc = pThisCC->pbVRam + offSrc; + + for (unsigned y = yStart; y < yStart + cy; y++) + { + vga_draw_line(pThis, pThisCC, pbDst, pbSrc, cx); + + pbDst += pDrv->cbScanline; + pbSrc += pThis->svga.cbScanline; + } + pDrv->pfnUpdateRect(pDrv, xStart, yStart, cx, cy); + + return VINF_SUCCESS; +} +# endif + +/** + * graphic modes + */ +static int vmsvgaR3DrawGraphic(PVGASTATE pThis, PVGASTATER3 pThisCC, bool fFullUpdate, + bool fFailOnResize, bool reset_dirty, PDMIDISPLAYCONNECTOR *pDrv) +{ + RT_NOREF1(fFailOnResize); + + uint32_t const cx = pThis->last_scr_width; + uint32_t const cxDisplay = cx; + uint32_t const cy = pThis->last_scr_height; + uint32_t cBits = pThis->last_bpp; + + if ( cx == VMSVGA_VAL_UNINITIALIZED + || cx == 0 + || cy == VMSVGA_VAL_UNINITIALIZED + || cy == 0 + || cBits == VMSVGA_VAL_UNINITIALIZED + || cBits == 0) + { + /* Intermediate state; skip redraws. */ + return VINF_SUCCESS; + } + + unsigned v; + switch (cBits) + { + case 8: + /* Note! experimental, not sure if this really works... */ + /** @todo fFullUpdate |= vgaR3UpdatePalette256(pThis); - need fFullUpdate but not + * copying anything to last_palette. */ + v = VGA_DRAW_LINE8; + break; + case 15: + v = VGA_DRAW_LINE15; + cBits = 16; + break; + case 16: + v = VGA_DRAW_LINE16; + break; + case 24: + v = VGA_DRAW_LINE24; + break; + case 32: + v = VGA_DRAW_LINE32; + break; + default: + case 0: + AssertFailed(); + return VERR_NOT_IMPLEMENTED; + } + vga_draw_line_func *pfnVgaDrawLine = vga_draw_line_table[v * 4 + vgaR3GetDepthIndex(pDrv->cBits)]; + + Assert(!pThisCC->cursor_invalidate); + Assert(!pThisCC->cursor_draw_line); + //not used// if (pThisCC->cursor_invalidate) + //not used// pThisCC->cursor_invalidate(pThis); + + uint8_t *pbDst = pDrv->pbData; + uint32_t cbDstScanline = pDrv->cbScanline; + uint32_t offSrcStart = 0; /* always start at the beginning of the framebuffer */ + uint32_t cbScanline = (cx * cBits + 7) / 8; /* The visible width of a scanline. */ + uint32_t yUpdateRectTop = UINT32_MAX; + uint32_t offPageMin = UINT32_MAX; + int32_t offPageMax = -1; + uint32_t y; + for (y = 0; y < cy; y++) + { + uint32_t offSrcLine = offSrcStart + y * cbScanline; + uint32_t offPage0 = offSrcLine & ~(uint32_t)GUEST_PAGE_OFFSET_MASK; + uint32_t offPage1 = (offSrcLine + cbScanline - 1) & ~(uint32_t)GUEST_PAGE_OFFSET_MASK; + /** @todo r=klaus this assumes that a line is fully covered by 3 pages, + * irrespective of alignment. Not guaranteed for high res modes, i.e. + * anything wider than 2050 pixels @32bpp. Need to check all pages + * between the first and last one. */ + bool fUpdate = fFullUpdate | vgaR3IsDirty(pThis, offPage0) | vgaR3IsDirty(pThis, offPage1); + if (offPage1 - offPage0 > GUEST_PAGE_SIZE) + /* if wide line, can use another page */ + fUpdate |= vgaR3IsDirty(pThis, offPage0 + GUEST_PAGE_SIZE); + /* explicit invalidation for the hardware cursor */ + fUpdate |= (pThis->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; + if (fUpdate) + { + if (yUpdateRectTop == UINT32_MAX) + yUpdateRectTop = y; + if (offPage0 < offPageMin) + offPageMin = offPage0; + if ((int32_t)offPage1 > offPageMax) + offPageMax = offPage1; + if (pThis->fRenderVRAM) + pfnVgaDrawLine(pThis, pThisCC, pbDst, pThisCC->pbVRam + offSrcLine, cx); + //not used// if (pThisCC->cursor_draw_line) + //not used// pThisCC->cursor_draw_line(pThis, pbDst, y); + } + else if (yUpdateRectTop != UINT32_MAX) + { + /* flush to display */ + Log(("Flush to display (%d,%d)(%d,%d)\n", 0, yUpdateRectTop, cxDisplay, y - yUpdateRectTop)); + pDrv->pfnUpdateRect(pDrv, 0, yUpdateRectTop, cxDisplay, y - yUpdateRectTop); + yUpdateRectTop = UINT32_MAX; + } + pbDst += cbDstScanline; + } + if (yUpdateRectTop != UINT32_MAX) + { + /* flush to display */ + Log(("Flush to display (%d,%d)(%d,%d)\n", 0, yUpdateRectTop, cxDisplay, y - yUpdateRectTop)); + pDrv->pfnUpdateRect(pDrv, 0, yUpdateRectTop, cxDisplay, y - yUpdateRectTop); + } + + /* reset modified pages */ + if (offPageMax != -1 && reset_dirty) + vgaR3ResetDirty(pThis, offPageMin, offPageMax + GUEST_PAGE_SIZE); + memset(pThis->invalidated_y_table, 0, ((cy + 31) >> 5) * 4); + + return VINF_SUCCESS; +} + +# endif /* VBOX_WITH_VMSVGA */ + +/** + * graphic modes + */ +static int vgaR3DrawGraphic(PVGASTATE pThis, PVGASTATER3 pThisCC, bool full_update, bool fFailOnResize, bool reset_dirty, + PDMIDISPLAYCONNECTOR *pDrv) +{ + int y1, y2, y, page_min, page_max, linesize, y_start, double_scan; + int width, height, shift_control, line_offset, page0, page1, bwidth, bits; + int disp_width, multi_run; + uint8_t *d; + uint32_t v, addr1, addr; + vga_draw_line_func *pfnVgaDrawLine; + + bool offsets_changed = vgaR3UpdateBasicParams(pThis, pThisCC); + + full_update |= offsets_changed; + + pThisCC->get_resolution(pThis, &width, &height); + disp_width = width; + + shift_control = (pThis->gr[0x05] >> 5) & 3; + double_scan = (pThis->cr[0x09] >> 7); + multi_run = double_scan; + if (shift_control != pThis->shift_control || + double_scan != pThis->double_scan) { + full_update = true; + pThis->shift_control = shift_control; + pThis->double_scan = double_scan; + } + + if (shift_control == 0) { + full_update |= vgaR3UpdatePalette16(pThis, pThisCC); + if (pThis->sr[0x01] & 8) { + v = VGA_DRAW_LINE4D2; + disp_width <<= 1; + } else { + v = VGA_DRAW_LINE4; + } + bits = 4; + } else if (shift_control == 1) { + full_update |= vgaR3UpdatePalette16(pThis, pThisCC); + if (pThis->sr[0x01] & 8) { + v = VGA_DRAW_LINE2D2; + disp_width <<= 1; + } else { + v = VGA_DRAW_LINE2; + } + bits = 4; + } else { + switch(pThisCC->get_bpp(pThis)) { + default: + case 0: + full_update |= vgaR3UpdatePalette256(pThis, pThisCC); + v = VGA_DRAW_LINE8D2; + bits = 4; + break; + case 8: + full_update |= vgaR3UpdatePalette256(pThis, pThisCC); + v = VGA_DRAW_LINE8; + bits = 8; + break; + case 15: + v = VGA_DRAW_LINE15; + bits = 16; + break; + case 16: + v = VGA_DRAW_LINE16; + bits = 16; + break; + case 24: + v = VGA_DRAW_LINE24; + bits = 24; + break; + case 32: + v = VGA_DRAW_LINE32; + bits = 32; + break; + } + } + if ( disp_width != (int)pThis->last_width + || height != (int)pThis->last_height + || pThisCC->get_bpp(pThis) != (int)pThis->last_bpp + || (offsets_changed && !pThis->fRenderVRAM)) + { + if (fFailOnResize) + { + /* The caller does not want to call the pfnResize. */ + return VERR_TRY_AGAIN; + } + int rc = vgaR3ResizeGraphic(pThis, pThisCC, disp_width, height, pDrv); + if (rc != VINF_SUCCESS) /* Return any rc, particularly VINF_VGA_RESIZE_IN_PROGRESS, to the caller. */ + return rc; + full_update = true; + } + + if (pThis->fRenderVRAM) + { + /* Do not update the destination buffer if it is not big enough. + * Can happen if the resize request was ignored by the driver. + * Compare with 'disp_width', because it is what the framebuffer has been resized to. + */ + if ( pDrv->cx != (uint32_t)disp_width + || pDrv->cy != (uint32_t)height) + { + LogRel(("Framebuffer mismatch: vga %dx%d, drv %dx%d!!!\n", + disp_width, height, + pDrv->cx, pDrv->cy)); + return VINF_SUCCESS; + } + } + + pfnVgaDrawLine = vga_draw_line_table[v * 4 + vgaR3GetDepthIndex(pDrv->cBits)]; + + if (pThisCC->cursor_invalidate) + pThisCC->cursor_invalidate(pThis); + + line_offset = pThis->line_offset; +#if 0 + Log(("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n", + width, height, v, line_offset, pThis->cr[9], pThis->cr[0x17], pThis->line_compare, pThis->sr[0x01])); +#endif + addr1 = (pThis->start_addr * 4); + bwidth = (width * bits + 7) / 8; /* The visible width of a scanline. */ + y_start = -1; + page_min = 0x7fffffff; + page_max = -1; + d = pDrv->pbData; + linesize = pDrv->cbScanline; + + if (!(pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) + pThis->vga_addr_mask = 0x3ffff; + else + pThis->vga_addr_mask = UINT32_MAX; + + y1 = 0; + y2 = pThis->cr[0x09] & 0x1F; /* starting row scan count */ + for(y = 0; y < height; y++) { + addr = addr1; + /* CGA/MDA compatibility. Note that these addresses are all + * shifted left by two compared to VGA specs. + */ + if (!(pThis->cr[0x17] & 1)) { + addr = (addr & ~(1 << 15)) | ((y1 & 1) << 15); + } + if (!(pThis->cr[0x17] & 2)) { + addr = (addr & ~(1 << 16)) | ((y1 & 2) << 15); + } + addr &= pThis->vga_addr_mask; + page0 = addr & ~(uint32_t)GUEST_PAGE_OFFSET_MASK; + page1 = (addr + bwidth - 1) & ~(uint32_t)GUEST_PAGE_OFFSET_MASK; + /** @todo r=klaus this assumes that a line is fully covered by 3 pages, + * irrespective of alignment. Not guaranteed for high res modes, i.e. + * anything wider than 2050 pixels @32bpp. Need to check all pages + * between the first and last one. */ + bool update = full_update | vgaR3IsDirty(pThis, page0) | vgaR3IsDirty(pThis, page1); + if (page1 - page0 > GUEST_PAGE_SIZE) { + /* if wide line, can use another page */ + update |= vgaR3IsDirty(pThis, page0 + GUEST_PAGE_SIZE); + } + /* explicit invalidation for the hardware cursor */ + update |= (pThis->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; + if (update) { + if (y_start < 0) + y_start = y; + if (page0 < page_min) + page_min = page0; + if (page1 > page_max) + page_max = page1; + if (pThis->fRenderVRAM) + pfnVgaDrawLine(pThis, pThisCC, d, pThisCC->pbVRam + addr, width); + if (pThisCC->cursor_draw_line) + pThisCC->cursor_draw_line(pThis, d, y); + } else { + if (y_start >= 0) { + /* flush to display */ + pDrv->pfnUpdateRect(pDrv, 0, y_start, disp_width, y - y_start); + y_start = -1; + } + } + if (!multi_run) { + y1++; + multi_run = double_scan; + + if (y2 == 0) { + y2 = pThis->cr[0x09] & 0x1F; + addr1 += line_offset; + } else { + --y2; + } + } else { + multi_run--; + } + /* line compare acts on the displayed lines */ + if ((uint32_t)y == pThis->line_compare) + addr1 = 0; + d += linesize; + } + if (y_start >= 0) { + /* flush to display */ + pDrv->pfnUpdateRect(pDrv, 0, y_start, disp_width, y - y_start); + } + /* reset modified pages */ + if (page_max != -1 && reset_dirty) { + vgaR3ResetDirty(pThis, page_min, page_max + GUEST_PAGE_SIZE); + } + memset(pThis->invalidated_y_table, 0, ((height + 31) >> 5) * 4); + return VINF_SUCCESS; +} + +/** + * blanked modes + */ +static int vgaR3DrawBlank(PVGASTATE pThis, PVGASTATER3 pThisCC, bool full_update, + bool fFailOnResize, bool reset_dirty, PDMIDISPLAYCONNECTOR *pDrv) +{ + int i, w, val; + uint8_t *d; + uint32_t cbScanline = pDrv->cbScanline; + uint32_t page_min, page_max; + + if (pThis->last_width != 0) + { + if (fFailOnResize) + { + /* The caller does not want to call the pfnResize. */ + return VERR_TRY_AGAIN; + } + pThis->last_width = 0; + pThis->last_height = 0; + /* For blanking signal width=0, height=0, bpp=0 and cbLine=0 here. + * There is no screen content, which distinguishes it from text mode. */ + pDrv->pfnResize(pDrv, 0, NULL, 0, 0, 0); + } + /* reset modified pages, i.e. everything */ + if (reset_dirty && pThis->last_scr_height > 0) + { + page_min = (pThis->start_addr * 4) & ~(uint32_t)GUEST_PAGE_OFFSET_MASK; + /* round up page_max by one page, as otherwise this can be -GUEST_PAGE_SIZE, + * which causes assertion trouble in vgaR3ResetDirty. */ + page_max = (pThis->start_addr * 4 + pThis->line_offset * pThis->last_scr_height - 1 + GUEST_PAGE_SIZE) + & ~(uint32_t)GUEST_PAGE_OFFSET_MASK; + vgaR3ResetDirty(pThis, page_min, page_max + GUEST_PAGE_SIZE); + } + if (pDrv->pbData == pThisCC->pbVRam) /* Do not clear the VRAM itself. */ + return VINF_SUCCESS; + if (!full_update) + return VINF_SUCCESS; + if (pThis->last_scr_width <= 0 || pThis->last_scr_height <= 0) + return VINF_SUCCESS; + if (pDrv->cBits == 8) + val = pThisCC->rgb_to_pixel(0, 0, 0); + else + val = 0; + w = pThis->last_scr_width * ((pDrv->cBits + 7) >> 3); + d = pDrv->pbData; + if (pThis->fRenderVRAM) + { + for(i = 0; i < (int)pThis->last_scr_height; i++) { + memset(d, val, w); + d += cbScanline; + } + } + pDrv->pfnUpdateRect(pDrv, 0, 0, pThis->last_scr_width, pThis->last_scr_height); + return VINF_SUCCESS; +} + + +#define GMODE_TEXT 0 +#define GMODE_GRAPH 1 +#define GMODE_BLANK 2 +#ifdef VBOX_WITH_VMSVGA +#define GMODE_SVGA 3 +#endif + +/** + * Worker for vgaR3PortUpdateDisplay(), vgaR3UpdateDisplayAllInternal() and + * vgaR3PortTakeScreenshot(). + */ +static int vgaR3UpdateDisplay(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATER3 pThisCC, bool fUpdateAll, + bool fFailOnResize, bool reset_dirty, PDMIDISPLAYCONNECTOR *pDrv, int32_t *pcur_graphic_mode) +{ + int rc = VINF_SUCCESS; + int graphic_mode; + + if (pDrv->cBits == 0) { + /* nothing to do */ + } else { + switch(pDrv->cBits) { + case 8: + pThisCC->rgb_to_pixel = rgb_to_pixel8_dup; + break; + case 15: + pThisCC->rgb_to_pixel = rgb_to_pixel15_dup; + break; + default: + case 16: + pThisCC->rgb_to_pixel = rgb_to_pixel16_dup; + break; + case 32: + pThisCC->rgb_to_pixel = rgb_to_pixel32_dup; + break; + } + +#ifdef VBOX_WITH_VMSVGA + if (pThis->svga.fEnabled) { + graphic_mode = GMODE_SVGA; + } + else +#endif + if (!(pThis->ar_index & 0x20) || (pThis->sr[0x01] & 0x20)) { + graphic_mode = GMODE_BLANK; + } else { + graphic_mode = pThis->gr[6] & 1 ? GMODE_GRAPH : GMODE_TEXT; + } + bool full_update = fUpdateAll || graphic_mode != *pcur_graphic_mode; + if (full_update) { + *pcur_graphic_mode = graphic_mode; + } + switch(graphic_mode) { + case GMODE_TEXT: + rc = vgaR3DrawText(pDevIns, pThis, pThisCC, full_update, fFailOnResize, reset_dirty, pDrv); + break; + case GMODE_GRAPH: + rc = vgaR3DrawGraphic(pThis, pThisCC, full_update, fFailOnResize, reset_dirty, pDrv); + break; +#ifdef VBOX_WITH_VMSVGA + case GMODE_SVGA: + rc = vmsvgaR3DrawGraphic(pThis, pThisCC, full_update, fFailOnResize, reset_dirty, pDrv); + break; +#endif + case GMODE_BLANK: + default: + rc = vgaR3DrawBlank(pThis, pThisCC, full_update, fFailOnResize, reset_dirty, pDrv); + break; + } + } + return rc; +} + +/** + * Worker for vgaR3SaveExec(). + */ +static void vga_save(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, PVGASTATE pThis) +{ + int i; + + pHlp->pfnSSMPutU32(pSSM, pThis->latch); + pHlp->pfnSSMPutU8(pSSM, pThis->sr_index); + pHlp->pfnSSMPutMem(pSSM, pThis->sr, 8); + pHlp->pfnSSMPutU8(pSSM, pThis->gr_index); + pHlp->pfnSSMPutMem(pSSM, pThis->gr, 16); + pHlp->pfnSSMPutU8(pSSM, pThis->ar_index); + pHlp->pfnSSMPutMem(pSSM, pThis->ar, 21); + pHlp->pfnSSMPutU32(pSSM, pThis->ar_flip_flop); + pHlp->pfnSSMPutU8(pSSM, pThis->cr_index); + pHlp->pfnSSMPutMem(pSSM, pThis->cr, 256); + pHlp->pfnSSMPutU8(pSSM, pThis->msr); + pHlp->pfnSSMPutU8(pSSM, pThis->fcr); + pHlp->pfnSSMPutU8(pSSM, pThis->st00); + pHlp->pfnSSMPutU8(pSSM, pThis->st01); + + pHlp->pfnSSMPutU8(pSSM, pThis->dac_state); + pHlp->pfnSSMPutU8(pSSM, pThis->dac_sub_index); + pHlp->pfnSSMPutU8(pSSM, pThis->dac_read_index); + pHlp->pfnSSMPutU8(pSSM, pThis->dac_write_index); + pHlp->pfnSSMPutMem(pSSM, pThis->dac_cache, 3); + pHlp->pfnSSMPutMem(pSSM, pThis->palette, 768); + + pHlp->pfnSSMPutU32(pSSM, pThis->bank_offset); +#ifdef CONFIG_BOCHS_VBE + AssertCompile(RT_ELEMENTS(pThis->vbe_regs) < 256); + pHlp->pfnSSMPutU8(pSSM, (uint8_t)RT_ELEMENTS(pThis->vbe_regs)); + pHlp->pfnSSMPutU16(pSSM, pThis->vbe_index); + for(i = 0; i < (int)RT_ELEMENTS(pThis->vbe_regs); i++) + pHlp->pfnSSMPutU16(pSSM, pThis->vbe_regs[i]); + pHlp->pfnSSMPutU32(pSSM, pThis->vbe_start_addr); + pHlp->pfnSSMPutU32(pSSM, pThis->vbe_line_offset); +#else + pHlp->pfnSSMPutU8(pSSM, 0); +#endif +} + + +/** + * Worker for vgaR3LoadExec(). + */ +static int vga_load(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, PVGASTATE pThis, int version_id) +{ + int is_vbe, i; + uint32_t u32Dummy; + uint8_t u8; + + pHlp->pfnSSMGetU32(pSSM, &pThis->latch); + pHlp->pfnSSMGetU8(pSSM, &pThis->sr_index); + pHlp->pfnSSMGetMem(pSSM, pThis->sr, 8); + pHlp->pfnSSMGetU8(pSSM, &pThis->gr_index); + pHlp->pfnSSMGetMem(pSSM, pThis->gr, 16); + pHlp->pfnSSMGetU8(pSSM, &pThis->ar_index); + pHlp->pfnSSMGetMem(pSSM, pThis->ar, 21); + pHlp->pfnSSMGetS32(pSSM, &pThis->ar_flip_flop); + pHlp->pfnSSMGetU8(pSSM, &pThis->cr_index); + pHlp->pfnSSMGetMem(pSSM, pThis->cr, 256); + pHlp->pfnSSMGetU8(pSSM, &pThis->msr); + pHlp->pfnSSMGetU8(pSSM, &pThis->fcr); + pHlp->pfnSSMGetU8(pSSM, &pThis->st00); + pHlp->pfnSSMGetU8(pSSM, &pThis->st01); + + pHlp->pfnSSMGetU8(pSSM, &pThis->dac_state); + pHlp->pfnSSMGetU8(pSSM, &pThis->dac_sub_index); + pHlp->pfnSSMGetU8(pSSM, &pThis->dac_read_index); + pHlp->pfnSSMGetU8(pSSM, &pThis->dac_write_index); + pHlp->pfnSSMGetMem(pSSM, pThis->dac_cache, 3); + pHlp->pfnSSMGetMem(pSSM, pThis->palette, 768); + + pHlp->pfnSSMGetS32(pSSM, &pThis->bank_offset); + pHlp->pfnSSMGetU8(pSSM, &u8); + is_vbe = !!u8; +#ifdef CONFIG_BOCHS_VBE + if (!is_vbe) + { + Log(("vga_load: !is_vbe !!\n")); + return VERR_SSM_DATA_UNIT_FORMAT_CHANGED; + } + + if (u8 == 1) + u8 = VBE_DISPI_INDEX_NB_SAVED; /* Used to save so many registers. */ + if (u8 > RT_ELEMENTS(pThis->vbe_regs)) + { + Log(("vga_load: saved %d, expected %d!!\n", u8, RT_ELEMENTS(pThis->vbe_regs))); + return VERR_SSM_DATA_UNIT_FORMAT_CHANGED; + } + + pHlp->pfnSSMGetU16(pSSM, &pThis->vbe_index); + for(i = 0; i < (int)u8; i++) + pHlp->pfnSSMGetU16(pSSM, &pThis->vbe_regs[i]); + if (version_id <= VGA_SAVEDSTATE_VERSION_INV_VHEIGHT) + recalculate_data(pThis); /* <- re-calculate the pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] since it might be invalid */ + pHlp->pfnSSMGetU32(pSSM, &pThis->vbe_start_addr); + pHlp->pfnSSMGetU32(pSSM, &pThis->vbe_line_offset); + if (version_id < 2) + pHlp->pfnSSMGetU32(pSSM, &u32Dummy); + pThis->vbe_bank_max = (pThis->vram_size >> 16) - 1; +#else + if (is_vbe) + { + Log(("vga_load: is_vbe !!\n")); + return VERR_SSM_DATA_UNIT_FORMAT_CHANGED; + } +#endif + + /* force refresh */ + pThis->graphic_mode = -1; + return 0; +} + + +/** + * Worker for vgaR3Construct(). + */ +static void vgaR3InitExpand(void) +{ + int i, j, v, b; + + for(i = 0;i < 256; i++) { + v = 0; + for(j = 0; j < 8; j++) { + v |= ((i >> j) & 1) << (j * 4); + } + expand4[i] = v; + + v = 0; + for(j = 0; j < 4; j++) { + v |= ((i >> (2 * j)) & 3) << (j * 4); + } + expand2[i] = v; + } + for(i = 0; i < 16; i++) { + v = 0; + for(j = 0; j < 4; j++) { + b = ((i >> j) & 1); + v |= b << (2 * j); + v |= b << (2 * j + 1); + } + expand4to8[i] = v; + } +} + +#endif /* IN_RING3 */ + + + +/* -=-=-=-=-=- all contexts -=-=-=-=-=- */ + +#define VGA_IOPORT_WRITE_PLACEHOLDER(a_uPort, a_cPorts) do {\ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); \ + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); \ + AssertCompile(RT_IS_POWER_OF_TWO(a_cPorts)); \ + Assert((unsigned)offPort - (unsigned)(a_uPort) < (unsigned)(a_cPorts)); \ + NOREF(pvUser); \ + if (cb == 1) \ + vga_ioport_write(pDevIns, pThis, offPort, u32); \ + else if (cb == 2) \ + { \ + vga_ioport_write(pDevIns, pThis, offPort, u32 & 0xff); \ + vga_ioport_write(pDevIns, pThis, offPort + 1, u32 >> 8); \ + } \ + return VINF_SUCCESS; \ + } while (0) + +#define VGA_IOPORT_READ_PLACEHOLDER(a_uPort, a_cPorts) do {\ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); \ + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); \ + AssertCompile(RT_IS_POWER_OF_TWO(a_cPorts)); \ + Assert((unsigned)offPort - (unsigned)(a_uPort) < (unsigned)(a_cPorts)); \ + NOREF(pvUser); \ + if (cb == 1) \ + *pu32 = vga_ioport_read(pDevIns, pThis, offPort); \ + else if (cb == 2) \ + { \ + uint32_t u32 = vga_ioport_read(pDevIns, pThis, offPort); \ + u32 |= vga_ioport_read(pDevIns, pThis, offPort + 1) << 8; \ + *pu32 = u32; \ + } \ + else \ + return VERR_IOM_IOPORT_UNUSED; \ + return VINF_SUCCESS; \ + } while (0) + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3c0-0x3c1 Attribute Controller.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortArWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3c0, 2); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3c0-0x3c1 Attribute Controller.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortArRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + VGA_IOPORT_READ_PLACEHOLDER(0x3c0, 2); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3c2 Miscellaneous Register.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortMsrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3c2, 1); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3c2 Status register 0.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortSt00Read(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + VGA_IOPORT_READ_PLACEHOLDER(0x3c2, 1); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3c3 Unused.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortUnusedWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3c3, 1); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3c3 Unused.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortUnusedRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + VGA_IOPORT_READ_PLACEHOLDER(0x3c3, 1); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3c4-0x3c5 Sequencer.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortSrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3c4, 2); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3c4-0x3c5 Sequencer.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortSrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + VGA_IOPORT_READ_PLACEHOLDER(0x3c4, 2); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3c6-0x3c9 DAC.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortDacWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3c6, 4); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3c6-0x3c9 DAC.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortDacRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + VGA_IOPORT_READ_PLACEHOLDER(0x3c6, 4); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3ca-0x3cd Graphics Position?} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortPosWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3ca, 4); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3ca-0x3cd Graphics Position?} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortPosRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + VGA_IOPORT_READ_PLACEHOLDER(0x3ca, 4); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3ce-0x3cf Graphics Controller.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortGrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3ce, 2); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3ca-0x3cf Graphics Controller.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortGrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + VGA_IOPORT_READ_PLACEHOLDER(0x3ce, 2); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3b4-0x3b5 MDA CRT control.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortMdaCrtWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + /** @todo do vga_ioport_invalid here */ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3b4, 2); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3b4-0x3b5 MDA CRT control.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortMdaCrtRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + /** @todo do vga_ioport_invalid here */ + VGA_IOPORT_READ_PLACEHOLDER(0x3b4, 2); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3ba MDA feature/status.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortMdaFcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + /** @todo do vga_ioport_invalid here */ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3ba, 1); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3ba MDA feature/status.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortMdaStRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + /** @todo do vga_ioport_invalid here */ + VGA_IOPORT_READ_PLACEHOLDER(0x3ba, 1); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3d4-0x3d5 CGA CRT control.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortCgaCrtWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + /** @todo do vga_ioport_invalid here */ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3d4, 2); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3d4-0x3d5 CGA CRT control.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortCgaCrtRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + /** @todo do vga_ioport_invalid here */ + VGA_IOPORT_READ_PLACEHOLDER(0x3d4, 2); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,0x3da CGA feature/status.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortCgaFcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + /** @todo do vga_ioport_invalid here */ + VGA_IOPORT_WRITE_PLACEHOLDER(0x3da, 1); +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN,0x3da CGA feature/status.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortCgaStRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + /** @todo do vga_ioport_invalid here */ + VGA_IOPORT_READ_PLACEHOLDER(0x3da, 1); +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,VBE Data Port OUT handler (0x1ce).} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vgaIoPortWriteVbeData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + + NOREF(pvUser); + +#ifndef IN_RING3 + /* + * This has to be done on the host in order to execute the connector callbacks. + */ + if ( pThis->vbe_index == VBE_DISPI_INDEX_ENABLE + || pThis->vbe_index == VBE_DISPI_INDEX_VBOX_VIDEO) + { + Log(("vgaIoPortWriteVbeData: VBE_DISPI_INDEX_ENABLE - Switching to host...\n")); + return VINF_IOM_R3_IOPORT_WRITE; + } +#endif +#ifdef VBE_BYTEWISE_IO + if (cb == 1) + { + if (!pThis->fWriteVBEData) + { + if ( (pThis->vbe_index == VBE_DISPI_INDEX_ENABLE) + && (u32 & VBE_DISPI_ENABLED)) + { + pThis->fWriteVBEData = false; + return vbe_ioport_write_data(pDevIns, pThis, pThisCC, offPort, u32 & 0xFF); + } + + pThis->cbWriteVBEData = u32 & 0xFF; + pThis->fWriteVBEData = true; + return VINF_SUCCESS; + } + + u32 = (pThis->cbWriteVBEData << 8) | (u32 & 0xFF); + pThis->fWriteVBEData = false; + cb = 2; + } +#endif + if (cb == 2 || cb == 4) + return vbe_ioport_write_data(pDevIns, pThis, pThisCC, offPort, u32); + AssertMsgFailed(("vgaIoPortWriteVbeData: offPort=%#x cb=%d u32=%#x\n", offPort, cb, u32)); + + return VINF_SUCCESS; +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,VBE Index Port OUT handler (0x1ce).} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vgaIoPortWriteVbeIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); NOREF(pvUser); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + +#ifdef VBE_BYTEWISE_IO + if (cb == 1) + { + if (!pThis->fWriteVBEIndex) + { + pThis->cbWriteVBEIndex = u32 & 0x00FF; + pThis->fWriteVBEIndex = true; + return VINF_SUCCESS; + } + pThis->fWriteVBEIndex = false; + vbe_ioport_write_index(pThis, offPort, (pThis->cbWriteVBEIndex << 8) | (u32 & 0x00FF)); + return VINF_SUCCESS; + } +#endif + + if (cb == 2) + vbe_ioport_write_index(pThis, offPort, u32); + else + ASSERT_GUEST_MSG_FAILED(("vgaIoPortWriteVbeIndex: offPort=%#x cb=%d u32=%#x\n", offPort, cb, u32)); + return VINF_SUCCESS; +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,VBE Data Port IN handler (0x1cf).} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vgaIoPortReadVbeData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); NOREF(pvUser); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + +#ifdef VBE_BYTEWISE_IO + if (cb == 1) + { + if (!pThis->fReadVBEData) + { + *pu32 = (vbe_ioport_read_data(pThis, offPort) >> 8) & 0xFF; + pThis->fReadVBEData = true; + return VINF_SUCCESS; + } + *pu32 = vbe_ioport_read_data(pThis, offPort) & 0xFF; + pThis->fReadVBEData = false; + return VINF_SUCCESS; + } +#endif + if (cb == 2) + { + *pu32 = vbe_ioport_read_data(pThis, offPort); + return VINF_SUCCESS; + } + if (cb == 4) + { + if (pThis->vbe_regs[VBE_DISPI_INDEX_ID] == VBE_DISPI_ID_CFG) + *pu32 = vbe_ioport_read_data(pThis, offPort); /* New interface. */ + else + *pu32 = pThis->vram_size; /* Quick hack for getting the vram size. */ + return VINF_SUCCESS; + } + AssertMsgFailed(("vgaIoPortReadVbeData: offPort=%#x cb=%d\n", offPort, cb)); + return VERR_IOM_IOPORT_UNUSED; +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,VBE Index Port IN handler (0x1cf).} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vgaIoPortReadVbeIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + NOREF(pvUser); + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + +#ifdef VBE_BYTEWISE_IO + if (cb == 1) + { + if (!pThis->fReadVBEIndex) + { + *pu32 = (vbe_ioport_read_index(pThis, offPort) >> 8) & 0xFF; + pThis->fReadVBEIndex = true; + return VINF_SUCCESS; + } + *pu32 = vbe_ioport_read_index(pThis, offPort) & 0xFF; + pThis->fReadVBEIndex = false; + return VINF_SUCCESS; + } +#endif + if (cb == 2) + { + *pu32 = vbe_ioport_read_index(pThis, offPort); + return VINF_SUCCESS; + } + AssertMsgFailed(("vgaIoPortReadVbeIndex: offPort=%#x cb=%d\n", offPort, cb)); + return VERR_IOM_IOPORT_UNUSED; +} + +#if defined(VBOX_WITH_HGSMI) && defined(IN_RING3) + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,HGSMI OUT handler.} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vgaR3IOPortHgsmiWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + LogFlowFunc(("offPort=0x%x u32=0x%x cb=%u\n", offPort, u32, cb)); + + NOREF(pvUser); + + if (cb == 4) + { + switch (offPort) + { + case VGA_PORT_HGSMI_HOST: /* Host */ + { +# if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_VDMA) || defined(VBOX_WITH_WDDM) + if (u32 == HGSMIOFFSET_VOID) + { + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSectIRQ, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSectIRQ, rcLock); + + if (pThis->fu32PendingGuestFlags == 0) + { + PDMDevHlpPCISetIrqNoWait(pDevIns, 0, PDM_IRQ_LEVEL_LOW); + HGSMIClearHostGuestFlags(pThisCC->pHGSMI, + HGSMIHOSTFLAGS_IRQ + | HGSMIHOSTFLAGS_VSYNC + | HGSMIHOSTFLAGS_HOTPLUG + | HGSMIHOSTFLAGS_CURSOR_CAPABILITIES); + } + else + { + HGSMISetHostGuestFlags(pThisCC->pHGSMI, HGSMIHOSTFLAGS_IRQ | pThis->fu32PendingGuestFlags); + pThis->fu32PendingGuestFlags = 0; + /* Keep the IRQ unchanged. */ + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSectIRQ); + } + else +# endif + { + HGSMIHostWrite(pThisCC->pHGSMI, u32); + } + break; + } + + case VGA_PORT_HGSMI_GUEST: /* Guest */ + HGSMIGuestWrite(pThisCC->pHGSMI, u32); + break; + + default: +# ifdef DEBUG_sunlover + AssertMsgFailed(("vgaR3IOPortHgsmiWrite: offPort=%#x cb=%d u32=%#x\n", offPort, cb, u32)); +# endif + break; + } + } + else + { + /** @todo r=bird: According to Ralf Brown, one and two byte accesses to the + * 0x3b0-0x3b1 and 0x3b2-0x3b3 I/O port pairs should work the same as + * 0x3b4-0x3b5 (MDA CRT control). */ + Log(("vgaR3IOPortHgsmiWrite: offPort=%#x cb=%d u32=%#x - possible valid MDA CRT access\n", offPort, cb, u32)); +# ifdef DEBUG_sunlover + AssertMsgFailed(("vgaR3IOPortHgsmiWrite: offPort=%#x cb=%d u32=%#x\n", offPort, cb, u32)); +# endif + STAM_REL_COUNTER_INC(&pThis->StatHgsmiMdaCgaAccesses); + } + + return VINF_SUCCESS; +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT,HGSMI IN handler.} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vgaR3IOPortHgmsiRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + LogFlowFunc(("offPort=0x%x cb=%d\n", offPort, cb)); + + NOREF(pvUser); + + VBOXSTRICTRC rc = VINF_SUCCESS; + if (cb == 4) + { + switch (offPort) + { + case VGA_PORT_HGSMI_HOST: /* Host */ + *pu32 = HGSMIHostRead(pThisCC->pHGSMI); + break; + case VGA_PORT_HGSMI_GUEST: /* Guest */ + *pu32 = HGSMIGuestRead(pThisCC->pHGSMI); + break; + default: + rc = VERR_IOM_IOPORT_UNUSED; + break; + } + } + else + { + /** @todo r=bird: According to Ralf Brown, one and two byte accesses to the + * 0x3b0-0x3b1 and 0x3b2-0x3b3 I/O port pairs should work the same as + * 0x3b4-0x3b5 (MDA CRT control). */ + Log(("vgaR3IOPortHgmsiRead: offPort=%#x cb=%d - possible valid MDA CRT access\n", offPort, cb)); + STAM_REL_COUNTER_INC(&pThis->StatHgsmiMdaCgaAccesses); + rc = VERR_IOM_IOPORT_UNUSED; + } + + return rc; +} + +#endif /* VBOX_WITH_HGSMI && IN_RING3*/ + + + + +/* -=-=-=-=-=- All Contexts -=-=-=-=-=- */ + +/** + * @internal. For use inside VGAGCMemoryFillWrite only. + * Macro for apply logical operation and bit mask. + */ +#define APPLY_LOGICAL_AND_MASK(pThis, val, bit_mask) \ + /* apply logical operation */ \ + switch (pThis->gr[3] >> 3)\ + { \ + case 0: \ + default:\ + /* nothing to do */ \ + break; \ + case 1: \ + /* and */ \ + val &= pThis->latch; \ + break; \ + case 2: \ + /* or */ \ + val |= pThis->latch; \ + break; \ + case 3: \ + /* xor */ \ + val ^= pThis->latch; \ + break; \ + } \ + /* apply bit mask */ \ + val = (val & bit_mask) | (pThis->latch & ~bit_mask) + +/** + * Legacy VGA memory (0xa0000 - 0xbffff) write hook, to be called from IOM and from the inside of VGADeviceGC.cpp. + * This is the advanced version of vga_mem_writeb function. + * + * @returns VBox status code. + * @param pThis The shared VGA instance data. + * @param pThisCC The VGA instance data for the current context. + * @param pvUser User argument - ignored. + * @param GCPhysAddr Physical address of memory to write. + * @param u32Item Data to write, up to 4 bytes. + * @param cbItem Size of data Item, only 1/2/4 bytes is allowed for now. + * @param cItems Number of data items to write. + */ +static int vgaInternalMMIOFill(PVGASTATE pThis, PVGASTATECC pThisCC, void *pvUser, RTGCPHYS GCPhysAddr, + uint32_t u32Item, unsigned cbItem, unsigned cItems) +{ + uint32_t b; + uint32_t write_mask, bit_mask, set_mask; + uint32_t aVal[4]; + unsigned i; + NOREF(pvUser); + + for (i = 0; i < cbItem; i++) + { + aVal[i] = u32Item & 0xff; + u32Item >>= 8; + } + + /* convert to VGA memory offset */ + /// @todo add check for the end of region + GCPhysAddr &= 0x1ffff; + switch((pThis->gr[6] >> 2) & 3) { + case 0: + break; + case 1: + if (GCPhysAddr >= 0x10000) + return VINF_SUCCESS; + GCPhysAddr += pThis->bank_offset; + break; + case 2: + GCPhysAddr -= 0x10000; + if (GCPhysAddr >= 0x8000) + return VINF_SUCCESS; + break; + default: + case 3: + GCPhysAddr -= 0x18000; + if (GCPhysAddr >= 0x8000) + return VINF_SUCCESS; + break; + } + + if (pThis->sr[4] & 0x08) { + /* chain 4 mode : simplest access */ + VERIFY_VRAM_WRITE_OFF_RETURN(pThis, GCPhysAddr + cItems * cbItem - 1); + + while (cItems-- > 0) + for (i = 0; i < cbItem; i++) + { + if (pThis->sr[2] & (1 << (GCPhysAddr & 3))) + { + pThisCC->pbVRam[GCPhysAddr] = aVal[i]; + vgaR3MarkDirty(pThis, GCPhysAddr); + } + GCPhysAddr++; + } + } else if (pThis->gr[5] & 0x10) { + /* odd/even mode (aka text mode mapping) */ + VERIFY_VRAM_WRITE_OFF_RETURN(pThis, (GCPhysAddr + cItems * cbItem) * 4 - 1); + while (cItems-- > 0) + for (i = 0; i < cbItem; i++) + { + unsigned plane = GCPhysAddr & 1; + if (pThis->sr[2] & (1 << plane)) { + RTGCPHYS PhysAddr2 = ((GCPhysAddr & ~1) * 4) | plane; + pThisCC->pbVRam[PhysAddr2] = aVal[i]; + vgaR3MarkDirty(pThis, PhysAddr2); + } + GCPhysAddr++; + } + } else { + /* standard VGA latched access */ + VERIFY_VRAM_WRITE_OFF_RETURN(pThis, (GCPhysAddr + cItems * cbItem) * 4 - 1); + + switch(pThis->gr[5] & 3) { + default: + case 0: + /* rotate */ + b = pThis->gr[3] & 7; + bit_mask = pThis->gr[8]; + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + set_mask = mask16[pThis->gr[1]]; + + for (i = 0; i < cbItem; i++) + { + aVal[i] = ((aVal[i] >> b) | (aVal[i] << (8 - b))) & 0xff; + aVal[i] |= aVal[i] << 8; + aVal[i] |= aVal[i] << 16; + + /* apply set/reset mask */ + aVal[i] = (aVal[i] & ~set_mask) | (mask16[pThis->gr[0]] & set_mask); + + APPLY_LOGICAL_AND_MASK(pThis, aVal[i], bit_mask); + } + break; + case 1: + for (i = 0; i < cbItem; i++) + aVal[i] = pThis->latch; + break; + case 2: + bit_mask = pThis->gr[8]; + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + for (i = 0; i < cbItem; i++) + { + aVal[i] = mask16[aVal[i] & 0x0f]; + + APPLY_LOGICAL_AND_MASK(pThis, aVal[i], bit_mask); + } + break; + case 3: + /* rotate */ + b = pThis->gr[3] & 7; + + for (i = 0; i < cbItem; i++) + { + aVal[i] = (aVal[i] >> b) | (aVal[i] << (8 - b)); + bit_mask = pThis->gr[8] & aVal[i]; + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + aVal[i] = mask16[pThis->gr[0]]; + + APPLY_LOGICAL_AND_MASK(pThis, aVal[i], bit_mask); + } + break; + } + + /* mask data according to sr[2] */ + write_mask = mask16[pThis->sr[2]]; + + /* actually write data */ + if (cbItem == 1) + { + /* The most frequently case is 1 byte I/O. */ + while (cItems-- > 0) + { + ((uint32_t *)pThisCC->pbVRam)[GCPhysAddr] = (((uint32_t *)pThisCC->pbVRam)[GCPhysAddr] & ~write_mask) | (aVal[0] & write_mask); + vgaR3MarkDirty(pThis, GCPhysAddr * 4); + GCPhysAddr++; + } + } + else if (cbItem == 2) + { + /* The second case is 2 bytes I/O. */ + while (cItems-- > 0) + { + ((uint32_t *)pThisCC->pbVRam)[GCPhysAddr] = (((uint32_t *)pThisCC->pbVRam)[GCPhysAddr] & ~write_mask) | (aVal[0] & write_mask); + vgaR3MarkDirty(pThis, GCPhysAddr * 4); + GCPhysAddr++; + + ((uint32_t *)pThisCC->pbVRam)[GCPhysAddr] = (((uint32_t *)pThisCC->pbVRam)[GCPhysAddr] & ~write_mask) | (aVal[1] & write_mask); + vgaR3MarkDirty(pThis, GCPhysAddr * 4); + GCPhysAddr++; + } + } + else + { + /* And the rest is 4 bytes. */ + Assert(cbItem == 4); + while (cItems-- > 0) + for (i = 0; i < cbItem; i++) + { + ((uint32_t *)pThisCC->pbVRam)[GCPhysAddr] = (((uint32_t *)pThisCC->pbVRam)[GCPhysAddr] & ~write_mask) | (aVal[i] & write_mask); + vgaR3MarkDirty(pThis, GCPhysAddr * 4); + GCPhysAddr++; + } + } + } + return VINF_SUCCESS; +} + +#undef APPLY_LOGICAL_AND_MASK + +/** + * @callback_method_impl{FNIOMMMIONEWFILL, + * Legacy VGA memory (0xa0000 - 0xbffff) write hook\, to be called from IOM and + * from the inside of VGADeviceGC.cpp. This is the advanced version of + * vga_mem_writeb function.} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vgaMmioFill(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, uint32_t u32Item, unsigned cbItem, unsigned cItems) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + + return vgaInternalMMIOFill(pThis, pThisCC, pvUser, off, u32Item, cbItem, cItems); +} + + +/** + * @callback_method_impl{FNIOMMMIONEWREAD, + * Legacy VGA memory (0xa0000 - 0xbffff) read hook\, to be called from IOM.} + * + * @note The @a off is an absolute address in the 0xa0000 - 0xbffff range, not + * an offset. + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + STAM_PROFILE_START(&pThis->CTX_MID_Z(Stat,MemoryRead), a); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + NOREF(pvUser); + + int rc = VINF_SUCCESS; + switch (cb) + { + case 1: + *(uint8_t *)pv = vga_mem_readb(pDevIns, pThis, pThisCC, off, &rc); + break; + case 2: +/** @todo This and the wider accesses maybe misbehave when accessing bytes + * crossing the 512KB VRAM boundrary if the access is handled in + * ring-0 and operating in latched mode. */ + *(uint16_t *)pv = vga_mem_readb(pDevIns, pThis, pThisCC, off, &rc) + | (vga_mem_readb(pDevIns, pThis, pThisCC, off + 1, &rc) << 8); + break; + case 4: + *(uint32_t *)pv = vga_mem_readb(pDevIns, pThis, pThisCC, off, &rc) + | (vga_mem_readb(pDevIns, pThis, pThisCC, off + 1, &rc) << 8) + | (vga_mem_readb(pDevIns, pThis, pThisCC, off + 2, &rc) << 16) + | (vga_mem_readb(pDevIns, pThis, pThisCC, off + 3, &rc) << 24); + break; + + case 8: + *(uint64_t *)pv = (uint64_t)vga_mem_readb(pDevIns, pThis, pThisCC, off, &rc) + | ((uint64_t)vga_mem_readb(pDevIns, pThis, pThisCC, off + 1, &rc) << 8) + | ((uint64_t)vga_mem_readb(pDevIns, pThis, pThisCC, off + 2, &rc) << 16) + | ((uint64_t)vga_mem_readb(pDevIns, pThis, pThisCC, off + 3, &rc) << 24) + | ((uint64_t)vga_mem_readb(pDevIns, pThis, pThisCC, off + 4, &rc) << 32) + | ((uint64_t)vga_mem_readb(pDevIns, pThis, pThisCC, off + 5, &rc) << 40) + | ((uint64_t)vga_mem_readb(pDevIns, pThis, pThisCC, off + 6, &rc) << 48) + | ((uint64_t)vga_mem_readb(pDevIns, pThis, pThisCC, off + 7, &rc) << 56); + break; + + default: + { + uint8_t *pbData = (uint8_t *)pv; + while (cb-- > 0) + { + *pbData++ = vga_mem_readb(pDevIns, pThis, pThisCC, off++, &rc); + if (RT_UNLIKELY(rc != VINF_SUCCESS)) + break; + } + } + } + + STAM_PROFILE_STOP(&pThis->CTX_MID_Z(Stat,MemoryRead), a); + return rc; +} + +/** + * @callback_method_impl{FNIOMMMIONEWWRITE, + * Legacy VGA memory (0xa0000 - 0xbffff) write hook\, to be called from IOM.} + * + * @note The @a off is an absolute address in the 0xa0000 - 0xbffff range, not + * an offset. + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + uint8_t const *pbSrc = (uint8_t const *)pv; + NOREF(pvUser); + STAM_PROFILE_START(&pThis->CTX_MID_Z(Stat,MemoryWrite), a); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + + VBOXSTRICTRC rc; + switch (cb) + { + case 1: + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off, *pbSrc); + break; +#if 1 + case 2: + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 0, pbSrc[0]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 1, pbSrc[1]); + break; + case 4: + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 0, pbSrc[0]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 1, pbSrc[1]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 2, pbSrc[2]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 3, pbSrc[3]); + break; + case 8: + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 0, pbSrc[0]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 1, pbSrc[1]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 2, pbSrc[2]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 3, pbSrc[3]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 4, pbSrc[4]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 5, pbSrc[5]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 6, pbSrc[6]); + if (RT_LIKELY(rc == VINF_SUCCESS)) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off + 7, pbSrc[7]); + break; +#else + case 2: + rc = vgaMmioFill(pDevIns, off, *(uint16_t *)pv, 2, 1); + break; + case 4: + rc = vgaMmioFill(pDevIns, off, *(uint32_t *)pv, 4, 1); + break; + case 8: + rc = vgaMmioFill(pDevIns, off, *(uint64_t *)pv, 8, 1); + break; +#endif + default: + rc = VINF_SUCCESS; + while (cb-- > 0 && rc == VINF_SUCCESS) + rc = vga_mem_writeb(pDevIns, pThis, pThisCC, off++, *pbSrc++); + break; + + } + STAM_PROFILE_STOP(&pThis->CTX_MID_Z(Stat,MemoryWrite), a); + return rc; +} + + +/* -=-=-=-=-=- All rings: VGA BIOS I/Os -=-=-=-=-=- */ + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN, + * Port I/O Handler for VGA BIOS IN operations.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortReadBios(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + RT_NOREF(pDevIns, pvUser, offPort, pu32, cb); + return VERR_IOM_IOPORT_UNUSED; +} + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT, + * Port I/O Handler for VGA BIOS IN operations.} + */ +static DECLCALLBACK(VBOXSTRICTRC) vgaIoPortWriteBios(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + RT_NOREF2(pDevIns, pvUser); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + Assert(offPort == 0); RT_NOREF(offPort); + + /* + * VGA BIOS char printing. + */ + if (cb == 1) + { +#if 0 + switch (u32) + { + case '\r': Log(("vgabios: \n")); break; + case '\n': Log(("vgabios: \n")); break; + case '\t': Log(("vgabios: \n")); break; + default: + Log(("vgabios: %c\n", u32)); + } +#else + static int s_fLastWasNotNewline = 0; /* We are only called in a single-threaded way */ + if (s_fLastWasNotNewline == 0) + Log(("vgabios: ")); + if (u32 != '\r') /* return - is only sent in conjunction with '\n' */ + Log(("%c", u32)); + if (u32 == '\n') + s_fLastWasNotNewline = 0; + else + s_fLastWasNotNewline = 1; +#endif + return VINF_SUCCESS; + } + + /* not in use. */ + return VERR_IOM_IOPORT_UNUSED; +} + + +/* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */ + +#ifdef IN_RING3 + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT, + * Port I/O Handler for VBE Extra OUT operations.} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vbeR3IOPortWriteVbeExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + RT_NOREF(offPort, pvUser); + + if (cb == 2) + { + Log(("vbeR3IOPortWriteVbeExtra: addr=%#RX32\n", u32)); + pThisCC->u16VBEExtraAddress = u32; + } + else + Log(("vbeR3IOPortWriteVbeExtra: Ignoring invalid cb=%d writes to the VBE Extra port!!!\n", cb)); + + return VINF_SUCCESS; +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWIN, + * Port I/O Handler for VBE Extra IN operations.} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vbeR3IoPortReadVbeExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo))); + RT_NOREF(offPort, pvUser); + + int rc = VINF_SUCCESS; + if (pThisCC->u16VBEExtraAddress == 0xffff) + { + Log(("vbeR3IoPortReadVbeExtra: Requested number of 64k video banks\n")); + *pu32 = pThis->vram_size / _64K; + } + else if ( pThisCC->u16VBEExtraAddress >= pThisCC->cbVBEExtraData + || pThisCC->u16VBEExtraAddress + cb > pThisCC->cbVBEExtraData) + { + *pu32 = 0; + Log(("vbeR3IoPortReadVbeExtra: Requested address is out of VBE data!!! Address=%#x(%d) cbVBEExtraData=%#x(%d)\n", + pThisCC->u16VBEExtraAddress, pThisCC->u16VBEExtraAddress, pThisCC->cbVBEExtraData, pThisCC->cbVBEExtraData)); + } + else + { + RT_UNTRUSTED_VALIDATED_FENCE(); + if (cb == 1) + { + *pu32 = pThisCC->pbVBEExtraData[pThisCC->u16VBEExtraAddress] & 0xFF; + + Log(("vbeR3IoPortReadVbeExtra: cb=%#x %.*Rhxs\n", cb, cb, pu32)); + } + else if (cb == 2) + { + *pu32 = pThisCC->pbVBEExtraData[pThisCC->u16VBEExtraAddress] + | (uint32_t)pThisCC->pbVBEExtraData[pThisCC->u16VBEExtraAddress + 1] << 8; + + Log(("vbeR3IoPortReadVbeExtra: cb=%#x %.*Rhxs\n", cb, cb, pu32)); + } + else + { + Log(("vbeR3IoPortReadVbeExtra: Invalid cb=%d read from the VBE Extra port!!!\n", cb)); + rc = VERR_IOM_IOPORT_UNUSED; + } + } + + return rc; +} + + +/** + * Parse the logo bitmap data at init time. + * + * @returns VBox status code. + * + * @param pThisCC The VGA instance data for ring-3. + */ +static int vbeR3ParseBitmap(PVGASTATECC pThisCC) +{ + /* + * Get bitmap header data + */ + PCLOGOHDR pLogoHdr = (PCLOGOHDR)pThisCC->pbLogo; + PBMPFILEHDR pFileHdr = (PBMPFILEHDR)(pThisCC->pbLogo + sizeof(LOGOHDR)); + PBMPWIN3XINFOHDR pCoreHdr = (PBMPWIN3XINFOHDR)(pThisCC->pbLogo + sizeof(LOGOHDR) + sizeof(BMPFILEHDR)); + + if (pFileHdr->uType == BMP_HDR_MAGIC) + { + switch (pCoreHdr->cbSize) + { + case BMP_HDR_SIZE_OS21: + { + PBMPOS2COREHDR pOs2Hdr = (PBMPOS2COREHDR)pCoreHdr; + pThisCC->cxLogo = pOs2Hdr->uWidth; + pThisCC->cyLogo = pOs2Hdr->uHeight; + pThisCC->cLogoPlanes = pOs2Hdr->cPlanes; + pThisCC->cLogoBits = pOs2Hdr->cBits; + pThisCC->LogoCompression = BMP_COMPRESSION_TYPE_NONE; + pThisCC->cLogoUsedColors = 0; + break; + } + + case BMP_HDR_SIZE_OS22: + { + PBMPOS2COREHDR2 pOs22Hdr = (PBMPOS2COREHDR2)pCoreHdr; + pThisCC->cxLogo = pOs22Hdr->uWidth; + pThisCC->cyLogo = pOs22Hdr->uHeight; + pThisCC->cLogoPlanes = pOs22Hdr->cPlanes; + pThisCC->cLogoBits = pOs22Hdr->cBits; + pThisCC->LogoCompression = pOs22Hdr->enmCompression; + pThisCC->cLogoUsedColors = pOs22Hdr->cClrUsed; + break; + } + + case BMP_HDR_SIZE_WIN3X: + pThisCC->cxLogo = pCoreHdr->uWidth; + pThisCC->cyLogo = pCoreHdr->uHeight; + pThisCC->cLogoPlanes = pCoreHdr->cPlanes; + pThisCC->cLogoBits = pCoreHdr->cBits; + pThisCC->LogoCompression = pCoreHdr->enmCompression; + pThisCC->cLogoUsedColors = pCoreHdr->cClrUsed; + break; + + default: + AssertLogRelMsgFailedReturn(("Unsupported bitmap header size %u.\n", pCoreHdr->cbSize), + VERR_INVALID_PARAMETER); + break; + } + + AssertLogRelMsgReturn(pThisCC->cxLogo <= LOGO_MAX_WIDTH && pThisCC->cyLogo <= LOGO_MAX_HEIGHT, + ("Bitmap %ux%u is too big.\n", pThisCC->cxLogo, pThisCC->cyLogo), + VERR_INVALID_PARAMETER); + + AssertLogRelMsgReturn(pThisCC->cLogoPlanes == 1, + ("Bitmap planes %u != 1.\n", pThisCC->cLogoPlanes), + VERR_INVALID_PARAMETER); + + AssertLogRelMsgReturn(pThisCC->cLogoBits == 4 || pThisCC->cLogoBits == 8 || pThisCC->cLogoBits == 24, + ("Unsupported %u depth.\n", pThisCC->cLogoBits), + VERR_INVALID_PARAMETER); + + AssertLogRelMsgReturn(pThisCC->cLogoUsedColors <= 256, + ("Unsupported %u colors.\n", pThisCC->cLogoUsedColors), + VERR_INVALID_PARAMETER); + + AssertLogRelMsgReturn(pThisCC->LogoCompression == BMP_COMPRESSION_TYPE_NONE, + ("Unsupported %u compression.\n", pThisCC->LogoCompression), + VERR_INVALID_PARAMETER); + + AssertLogRelMsgReturn(pLogoHdr->cbLogo > pFileHdr->offBits, + ("Wrong bitmap data offset %u, cbLogo=%u.\n", pFileHdr->offBits, pLogoHdr->cbLogo), + VERR_INVALID_PARAMETER); + + uint32_t const cbFileData = pLogoHdr->cbLogo - pFileHdr->offBits; + uint32_t cbImageData = (uint32_t)pThisCC->cxLogo * pThisCC->cyLogo * pThisCC->cLogoPlanes; + if (pThisCC->cLogoBits == 4) + cbImageData /= 2; + else if (pThisCC->cLogoBits == 24) + cbImageData *= 3; + AssertLogRelMsgReturn(cbImageData <= cbFileData, + ("Wrong BMP header data %u (cbLogo=%u offBits=%u)\n", cbImageData, pFileHdr->offBits, pLogoHdr->cbLogo), + VERR_INVALID_PARAMETER); + + AssertLogRelMsgReturn(pLogoHdr->cbLogo == pFileHdr->cbFileSize, + ("Wrong bitmap file size %u, cbLogo=%u.\n", pFileHdr->cbFileSize, pLogoHdr->cbLogo), + VERR_INVALID_PARAMETER); + + /* + * Read bitmap palette + */ + if (!pThisCC->cLogoUsedColors) + pThisCC->cLogoPalEntries = 1 << (pThisCC->cLogoPlanes * pThisCC->cLogoBits); + else + pThisCC->cLogoPalEntries = pThisCC->cLogoUsedColors; + + if (pThisCC->cLogoPalEntries) + { + const uint8_t *pbPal = pThisCC->pbLogo + sizeof(LOGOHDR) + sizeof(BMPFILEHDR) + pCoreHdr->cbSize; /* ASSUMES Size location (safe) */ + + for (uint16_t i = 0; i < pThisCC->cLogoPalEntries; i++) + { + uint16_t j; + uint32_t u32Pal = 0; + + for (j = 0; j < 3; j++) + { + uint8_t b = *pbPal++; + u32Pal <<= 8; + u32Pal |= b; + } + + pbPal++; /* skip unused byte */ + pThisCC->au32LogoPalette[i] = u32Pal; + } + } + + /* + * Bitmap data offset + */ + pThisCC->pbLogoBitmap = pThisCC->pbLogo + sizeof(LOGOHDR) + pFileHdr->offBits; + } + else + AssertLogRelMsgFailedReturn(("Not a BMP file.\n"), VERR_INVALID_PARAMETER); + + return VINF_SUCCESS; +} + + +/** + * Show logo bitmap data. + * + * @param cBits Logo depth. + * @param xLogo Logo X position. + * @param yLogo Logo Y position. + * @param cxLogo Logo width. + * @param cyLogo Logo height. + * @param fInverse True if the bitmask is black on white (only for 1bpp) + * @param iStep Fade in/fade out step. + * @param pu32Palette Palette data. + * @param pbSrc Source buffer. + * @param pbDst Destination buffer. + */ +static void vbeR3ShowBitmap(uint16_t cBits, uint16_t xLogo, uint16_t yLogo, uint16_t cxLogo, uint16_t cyLogo, + bool fInverse, uint8_t iStep, const uint32_t *pu32Palette, const uint8_t *pbSrc, uint8_t *pbDst) +{ + uint16_t i; + size_t cbPadBytes = 0; + size_t cbLineDst = LOGO_MAX_WIDTH * 4; + uint16_t cyLeft = cyLogo; + + pbDst += xLogo * 4 + yLogo * cbLineDst; + + switch (cBits) + { + case 1: + pbDst += cyLogo * cbLineDst; + cbPadBytes = 0; + break; + + case 4: + if (((cxLogo % 8) == 0) || ((cxLogo % 8) > 6)) + cbPadBytes = 0; + else if ((cxLogo % 8) <= 2) + cbPadBytes = 3; + else if ((cxLogo % 8) <= 4) + cbPadBytes = 2; + else + cbPadBytes = 1; + break; + + case 8: + cbPadBytes = ((cxLogo % 4) == 0) ? 0 : (4 - (cxLogo % 4)); + break; + + case 24: + cbPadBytes = cxLogo % 4; + break; + } + + uint8_t j = 0, c = 0; + + while (cyLeft-- > 0) + { + uint8_t *pbTmpDst = pbDst; + + if (cBits != 1) + j = 0; + + for (i = 0; i < cxLogo; i++) + { + switch (cBits) + { + case 1: + { + if (!j) + c = *pbSrc++; + + if (c & 1) + { + if (fInverse) + { + *pbTmpDst++ = 0; + *pbTmpDst++ = 0; + *pbTmpDst++ = 0; + pbTmpDst++; + } + else + { + uint8_t pix = 0xFF * iStep / LOGO_SHOW_STEPS; + *pbTmpDst++ = pix; + *pbTmpDst++ = pix; + *pbTmpDst++ = pix; + pbTmpDst++; + } + } + else + pbTmpDst += 4; + c >>= 1; + j = (j + 1) % 8; + break; + } + + case 4: + { + if (!j) + c = *pbSrc++; + + uint8_t pix = (c >> 4) & 0xF; + c <<= 4; + + uint32_t u32Pal = pu32Palette[pix]; + + pix = (u32Pal >> 16) & 0xFF; + *pbTmpDst++ = pix * iStep / LOGO_SHOW_STEPS; + pix = (u32Pal >> 8) & 0xFF; + *pbTmpDst++ = pix * iStep / LOGO_SHOW_STEPS; + pix = u32Pal & 0xFF; + *pbTmpDst++ = pix * iStep / LOGO_SHOW_STEPS; + pbTmpDst++; + + j = (j + 1) % 2; + break; + } + + case 8: + { + uint32_t u32Pal = pu32Palette[*pbSrc++]; + + uint8_t pix = (u32Pal >> 16) & 0xFF; + *pbTmpDst++ = pix * iStep / LOGO_SHOW_STEPS; + pix = (u32Pal >> 8) & 0xFF; + *pbTmpDst++ = pix * iStep / LOGO_SHOW_STEPS; + pix = u32Pal & 0xFF; + *pbTmpDst++ = pix * iStep / LOGO_SHOW_STEPS; + pbTmpDst++; + break; + } + + case 24: + *pbTmpDst++ = *pbSrc++ * iStep / LOGO_SHOW_STEPS; + *pbTmpDst++ = *pbSrc++ * iStep / LOGO_SHOW_STEPS; + *pbTmpDst++ = *pbSrc++ * iStep / LOGO_SHOW_STEPS; + pbTmpDst++; + break; + } + } + + pbDst -= cbLineDst; + pbSrc += cbPadBytes; + } +} + + +/** + * @callback_method_impl{FNIOMIOPORTNEWOUT, + * Port I/O Handler for BIOS Logo OUT operations.} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vbeR3IoPortWriteCmdLogo(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + RT_NOREF(pvUser, offPort); + + Log(("vbeR3IoPortWriteCmdLogo: cb=%d u32=%#04x(%#04d) (byte)\n", cb, u32, u32)); + + if (cb == 2) + { + /* Get the logo command */ + switch (u32 & 0xFF00) + { + case LOGO_CMD_SET_OFFSET: + pThisCC->offLogoData = u32 & 0xFF; + break; + + case LOGO_CMD_SHOW_BMP: + { + uint8_t iStep = u32 & 0xFF; + const uint8_t *pbSrc = pThisCC->pbLogoBitmap; + uint8_t *pbDst; + PCLOGOHDR pLogoHdr = (PCLOGOHDR)pThisCC->pbLogo; + uint32_t offDirty = 0; + uint16_t xLogo = (LOGO_MAX_WIDTH - pThisCC->cxLogo) / 2; + uint16_t yLogo = LOGO_MAX_HEIGHT - (LOGO_MAX_HEIGHT - pThisCC->cyLogo) / 2; + + /* Check VRAM size */ + if (pThis->vram_size < LOGO_MAX_SIZE) + break; + + if (pThis->vram_size >= LOGO_MAX_SIZE * 2) + pbDst = pThisCC->pbVRam + LOGO_MAX_SIZE; + else + pbDst = pThisCC->pbVRam; + + /* Clear screen - except on power on... */ + if (!pThisCC->fLogoClearScreen) + { + /* Clear vram */ + uint32_t *pu32Dst = (uint32_t *)pbDst; + for (int i = 0; i < LOGO_MAX_WIDTH; i++) + for (int j = 0; j < LOGO_MAX_HEIGHT; j++) + *pu32Dst++ = 0; + pThisCC->fLogoClearScreen = true; + } + + /* Show the bitmap. */ + vbeR3ShowBitmap(pThisCC->cLogoBits, xLogo, yLogo, + pThisCC->cxLogo, pThisCC->cyLogo, + false, iStep, &pThisCC->au32LogoPalette[0], + pbSrc, pbDst); + + /* Show the 'Press F12...' text. */ + if (pLogoHdr->fu8ShowBootMenu == 2) + vbeR3ShowBitmap(1, LOGO_F12TEXT_X, LOGO_F12TEXT_Y, + LOGO_F12TEXT_WIDTH, LOGO_F12TEXT_HEIGHT, + pThisCC->fBootMenuInverse, iStep, &pThisCC->au32LogoPalette[0], + &g_abLogoF12BootText[0], pbDst); + + /* Blit the offscreen buffer. */ + if (pThis->vram_size >= LOGO_MAX_SIZE * 2) + { + uint32_t *pu32TmpDst = (uint32_t *)pThisCC->pbVRam; + uint32_t *pu32TmpSrc = (uint32_t *)(pThisCC->pbVRam + LOGO_MAX_SIZE); + for (int i = 0; i < LOGO_MAX_WIDTH; i++) + { + for (int j = 0; j < LOGO_MAX_HEIGHT; j++) + *pu32TmpDst++ = *pu32TmpSrc++; + } + } + + /* Set the dirty flags. */ + while (offDirty <= LOGO_MAX_SIZE) + { + vgaR3MarkDirty(pThis, offDirty); + offDirty += GUEST_PAGE_SIZE; + } + break; + } + + default: + Log(("vbeR3IoPortWriteCmdLogo: invalid command %d\n", u32)); + pThisCC->LogoCommand = LOGO_CMD_NOP; + break; + } + + return VINF_SUCCESS; + } + + Log(("vbeR3IoPortWriteCmdLogo: Ignoring invalid cb=%d writes to the VBE Extra port!!!\n", cb)); + return VINF_SUCCESS; +} + + +/** + * @callback_method_impl{FNIOMIOPORTIN, + * Port I/O Handler for BIOS Logo IN operations.} + */ +static DECLCALLBACK(VBOXSTRICTRC) +vbeR3IoPortReadCmdLogo(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) +{ + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + RT_NOREF(pvUser, offPort); + + if (pThisCC->offLogoData + cb > pThisCC->cbLogo) + { + Log(("vbeR3IoPortReadCmdLogo: Requested address is out of Logo data!!! offLogoData=%#x(%d) cbLogo=%#x(%d)\n", + pThisCC->offLogoData, pThisCC->offLogoData, pThisCC->cbLogo, pThisCC->cbLogo)); + return VINF_SUCCESS; + } + RT_UNTRUSTED_VALIDATED_FENCE(); + + PCRTUINT64U p = (PCRTUINT64U)&pThisCC->pbLogo[pThisCC->offLogoData]; + switch (cb) + { + case 1: *pu32 = p->au8[0]; break; + case 2: *pu32 = p->au16[0]; break; + case 4: *pu32 = p->au32[0]; break; + //case 8: *pu32 = p->au64[0]; break; + default: AssertFailed(); break; + } + Log(("vbeR3IoPortReadCmdLogo: LogoOffset=%#x(%d) cb=%#x %.*Rhxs\n", pThisCC->offLogoData, pThisCC->offLogoData, cb, cb, pu32)); + + pThisCC->LogoCommand = LOGO_CMD_NOP; + pThisCC->offLogoData += cb; + + return VINF_SUCCESS; +} + + +/* -=-=-=-=-=- Ring 3: Debug Info Handlers -=-=-=-=-=- */ + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, + * Dumps several interesting bits of the VGA state that are difficult to + * decode from the registers.} + */ +static DECLCALLBACK(void) vgaR3InfoState(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + int is_graph, double_scan; + int w, h, char_height, char_dots; + int val, vfreq_hz, hfreq_hz; + vga_retrace_s *r = &pThis->retrace_state; + const char *clocks[] = { "25.175 MHz", "28.322 MHz", "External", "Reserved?!" }; + const char *mem_map[] = { "A000-BFFF", "A000-AFFF", "B000-B7FF", "B800-BFFF" }; + NOREF(pszArgs); + + is_graph = pThis->gr[6] & 1; + char_dots = (pThis->sr[0x01] & 1) ? 8 : 9; + double_scan = pThis->cr[9] >> 7; + pHlp->pfnPrintf(pHlp, "decoding memory at %s\n", mem_map[(pThis->gr[6] >> 2) & 3]); + pHlp->pfnPrintf(pHlp, "Misc status reg. MSR:%02X\n", pThis->msr); + pHlp->pfnPrintf(pHlp, "pixel clock: %s\n", clocks[(pThis->msr >> 2) & 3]); + pHlp->pfnPrintf(pHlp, "double scanning %s\n", double_scan ? "on" : "off"); + pHlp->pfnPrintf(pHlp, "double clocking %s\n", pThis->sr[1] & 0x08 ? "on" : "off"); + val = pThis->cr[0] + 5; + pHlp->pfnPrintf(pHlp, "htotal: %d px (%d cclk)\n", val * char_dots, val); + val = pThis->cr[6] + ((pThis->cr[7] & 1) << 8) + ((pThis->cr[7] & 0x20) << 4) + 2; + pHlp->pfnPrintf(pHlp, "vtotal: %d px\n", val); + val = pThis->cr[1] + 1; + w = val * char_dots; + pHlp->pfnPrintf(pHlp, "hdisp : %d px (%d cclk)\n", w, val); + val = pThis->cr[0x12] + ((pThis->cr[7] & 2) << 7) + ((pThis->cr[7] & 0x40) << 4) + 1; + h = val; + pHlp->pfnPrintf(pHlp, "vdisp : %d px\n", val); + val = ((pThis->cr[9] & 0x40) << 3) + ((pThis->cr[7] & 0x10) << 4) + pThis->cr[0x18]; + pHlp->pfnPrintf(pHlp, "split : %d ln\n", val); + val = (pThis->cr[0xc] << 8) + pThis->cr[0xd]; + pHlp->pfnPrintf(pHlp, "start : %#x\n", val); + if (!is_graph) + { + uint8_t ch_stride; + + ch_stride = pThis->cr[0x17] & 0x40 ? 4 : 8; + val = (pThis->cr[9] & 0x1f) + 1; + char_height = val; + pHlp->pfnPrintf(pHlp, "char height %d\n", val); + pHlp->pfnPrintf(pHlp, "text mode %dx%d\n", w / char_dots, h / (char_height << double_scan)); + + uint32_t cbLine; + uint32_t offStart; + uint32_t offCursr; + uint32_t uLineCompareIgn; + vgaR3GetOffsets(pThis, &cbLine, &offStart, &uLineCompareIgn); + if (!cbLine) + cbLine = 80 * ch_stride; + offStart *= ch_stride; + offCursr = ((pThis->cr[0x0e] << 8) | pThis->cr[0x0f]) * ch_stride; + pHlp->pfnPrintf(pHlp, "cbLine: %#x\n", cbLine); + pHlp->pfnPrintf(pHlp, "offStart: %#x (line %#x)\n", offStart, offStart / cbLine); + pHlp->pfnPrintf(pHlp, "offCursr: %#x\n", offCursr); + } + if (pThis->fRealRetrace) + { + val = r->hb_start; + pHlp->pfnPrintf(pHlp, "hblank start: %d px (%d cclk)\n", val * char_dots, val); + val = r->hb_end; + pHlp->pfnPrintf(pHlp, "hblank end : %d px (%d cclk)\n", val * char_dots, val); + pHlp->pfnPrintf(pHlp, "vblank start: %d px, end: %d px\n", r->vb_start, r->vb_end); + pHlp->pfnPrintf(pHlp, "vsync start : %d px, end: %d px\n", r->vs_start, r->vs_end); + pHlp->pfnPrintf(pHlp, "cclks per frame: %d\n", r->frame_cclks); + pHlp->pfnPrintf(pHlp, "cclk time (ns) : %d\n", r->cclk_ns); + if (r->frame_ns && r->h_total_ns) /* Careful in case state is temporarily invalid. */ + { + vfreq_hz = 1000000000 / r->frame_ns; + hfreq_hz = 1000000000 / r->h_total_ns; + pHlp->pfnPrintf(pHlp, "vfreq: %d Hz, hfreq: %d.%03d kHz\n", + vfreq_hz, hfreq_hz / 1000, hfreq_hz % 1000); + } + } + pHlp->pfnPrintf(pHlp, "display refresh interval: %u ms\n", pThis->cMilliesRefreshInterval); + +# ifdef VBOX_WITH_VMSVGA + if (pThis->svga.fEnabled) + pHlp->pfnPrintf(pHlp, pThis->svga.f3DEnabled ? "VMSVGA 3D enabled: %ux%ux%u\n" : "VMSVGA enabled: %ux%ux%u", + pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp); +# endif +} + + +/** + * Prints a separator line. + * + * @param pHlp Callback functions for doing output. + * @param cCols The number of columns. + * @param pszTitle The title text, NULL if none. + */ +static void vgaR3InfoTextPrintSeparatorLine(PCDBGFINFOHLP pHlp, size_t cCols, const char *pszTitle) +{ + if (pszTitle) + { + size_t cchTitle = strlen(pszTitle); + if (cchTitle + 6 >= cCols) + { + pHlp->pfnPrintf(pHlp, "-- %s --", pszTitle); + cCols = 0; + } + else + { + size_t cchLeft = (cCols - cchTitle - 2) / 2; + cCols -= cchLeft + cchTitle + 2; + while (cchLeft-- > 0) + pHlp->pfnPrintf(pHlp, "-"); + pHlp->pfnPrintf(pHlp, " %s ", pszTitle); + } + } + + while (cCols-- > 0) + pHlp->pfnPrintf(pHlp, "-"); + pHlp->pfnPrintf(pHlp, "\n"); +} + + +/** + * Worker for vgaR3InfoText. + * + * @param pThis The shared VGA state. + * @param pThisCC The VGA state for ring-3. + * @param pHlp Callback functions for doing output. + * @param offStart Where to start dumping (relative to the VRAM). + * @param cbLine The source line length (aka line_offset). + * @param cCols The number of columns on the screen. + * @param cRows The number of rows to dump. + * @param iScrBegin The row at which the current screen output starts. + * @param iScrEnd The row at which the current screen output end + * (exclusive). + */ +static void vgaR3InfoTextWorker(PVGASTATE pThis, PVGASTATER3 pThisCC, PCDBGFINFOHLP pHlp, + uint32_t offStart, uint32_t cbLine, + uint32_t cCols, uint32_t cRows, + uint32_t iScrBegin, uint32_t iScrEnd) +{ + /* Title, */ + char szTitle[32]; + if (iScrBegin || iScrEnd < cRows) + RTStrPrintf(szTitle, sizeof(szTitle), "%ux%u (+%u before, +%u after)", + cCols, iScrEnd - iScrBegin, iScrBegin, cRows - iScrEnd); + else + RTStrPrintf(szTitle, sizeof(szTitle), "%ux%u", cCols, iScrEnd - iScrBegin); + + /* Do the dumping. */ + uint8_t const *pbSrcOuter = pThisCC->pbVRam + offStart; + uint8_t const cStride = pThis->cr[0x17] & 0x40 ? 4 : 8; + uint32_t iRow; + for (iRow = 0; iRow < cRows; iRow++, pbSrcOuter += cbLine) + { + if ((uintptr_t)(pbSrcOuter + cbLine - pThisCC->pbVRam) > pThis->vram_size) { + pHlp->pfnPrintf(pHlp, "The last %u row/rows is/are outside the VRAM.\n", cRows - iRow); + break; + } + + if (iRow == 0) + vgaR3InfoTextPrintSeparatorLine(pHlp, cCols, szTitle); + else if (iRow == iScrBegin) + vgaR3InfoTextPrintSeparatorLine(pHlp, cCols, "screen start"); + else if (iRow == iScrEnd) + vgaR3InfoTextPrintSeparatorLine(pHlp, cCols, "screen end"); + + uint8_t const *pbSrc = pbSrcOuter; + for (uint32_t iCol = 0; iCol < cCols; ++iCol) + { + if (RT_C_IS_PRINT(*pbSrc)) + pHlp->pfnPrintf(pHlp, "%c", *pbSrc); + else + pHlp->pfnPrintf(pHlp, "."); + pbSrc += cStride; /* chars are spaced 8 or sometimes 4 bytes apart */ + } + pHlp->pfnPrintf(pHlp, "\n"); + } + + /* Final separator. */ + vgaR3InfoTextPrintSeparatorLine(pHlp, cCols, NULL); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, + * Dumps VGA memory formatted as ASCII text\, no attributes. Only looks at + * the first page.} + */ +static DECLCALLBACK(void) vgaR3InfoText(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + + /* + * Parse args. + */ + bool fAll = true; + if (pszArgs && *pszArgs) + { + if (!strcmp(pszArgs, "all")) + fAll = true; + else if (!strcmp(pszArgs, "scr") || !strcmp(pszArgs, "screen")) + fAll = false; + else + { + pHlp->pfnPrintf(pHlp, "Invalid argument: '%s'\n", pszArgs); + return; + } + } + + /* + * Check that we're in text mode and that the VRAM is accessible. + */ + if (!(pThis->gr[6] & 1)) + { + uint8_t *pbSrc = pThisCC->pbVRam; + if (pbSrc) + { + /* + * Figure out the display size and where the text is. + * + * Note! We're cutting quite a few corners here and this code could + * do with some brushing up. Dumping from the start of the + * frame buffer is done intentionally so that we're more + * likely to obtain the full scrollback of a linux panic. + * windbg> .printf "------ start -----\n"; .for (r $t0 = 0; @$t0 < 25; r $t0 = @$t0 + 1) { .for (r $t1 = 0; @$t1 < 80; r $t1 = @$t1 + 1) { .printf "%c", by( (@$t0 * 80 + @$t1) * 8 + 100f0000) }; .printf "\n" }; .printf "------ end -----\n"; + */ + uint32_t cbLine; + uint32_t offStart; + uint32_t uLineCompareIgn; + vgaR3GetOffsets(pThis, &cbLine, &offStart, &uLineCompareIgn); + if (!cbLine) + cbLine = 80 * 8; + offStart *= 8; + + uint32_t uVDisp = pThis->cr[0x12] + ((pThis->cr[7] & 2) << 7) + ((pThis->cr[7] & 0x40) << 4) + 1; + uint32_t uCharHeight = (pThis->cr[9] & 0x1f) + 1; + uint32_t uDblScan = pThis->cr[9] >> 7; + uint32_t cScrRows = uVDisp / (uCharHeight << uDblScan); + if (cScrRows < 25) + cScrRows = 25; + uint32_t iScrBegin = offStart / cbLine; + uint32_t cRows = iScrBegin + cScrRows; + uint32_t cCols = cbLine / 8; + + if (fAll) + vgaR3InfoTextWorker(pThis, pThisCC, pHlp, offStart - iScrBegin * cbLine, cbLine, + cCols, cRows, iScrBegin, iScrBegin + cScrRows); + else + vgaR3InfoTextWorker(pThis, pThisCC, pHlp, offStart, cbLine, cCols, cScrRows, 0, cScrRows); + } + else + pHlp->pfnPrintf(pHlp, "VGA memory not available!\n"); + } + else + pHlp->pfnPrintf(pHlp, "Not in text mode!\n"); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, Dumps VGA Sequencer registers.} + */ +static DECLCALLBACK(void) vgaR3InfoSR(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + NOREF(pszArgs); + + pHlp->pfnPrintf(pHlp, "VGA Sequencer (3C5): SR index 3C4:%02X\n", pThis->sr_index); + Assert(sizeof(pThis->sr) >= 8); + for (unsigned i = 0; i < 8; ++i) + pHlp->pfnPrintf(pHlp, " SR%02X:%02X", i, pThis->sr[i]); + pHlp->pfnPrintf(pHlp, "\n"); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, Dumps VGA CRTC registers.} + */ +static DECLCALLBACK(void) vgaR3InfoCR(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + unsigned i; + NOREF(pszArgs); + + pHlp->pfnPrintf(pHlp, "VGA CRTC (3D5): CRTC index 3D4:%02X\n", pThis->cr_index); + Assert(sizeof(pThis->cr) >= 24); + for (i = 0; i < 10; ++i) + pHlp->pfnPrintf(pHlp, " CR%02X:%02X", i, pThis->cr[i]); + pHlp->pfnPrintf(pHlp, "\n"); + for (i = 10; i < 20; ++i) + pHlp->pfnPrintf(pHlp, " CR%02X:%02X", i, pThis->cr[i]); + pHlp->pfnPrintf(pHlp, "\n"); + for (i = 20; i < 25; ++i) + pHlp->pfnPrintf(pHlp, " CR%02X:%02X", i, pThis->cr[i]); + pHlp->pfnPrintf(pHlp, "\n"); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, + * Dumps VGA Graphics Controller registers.} + */ +static DECLCALLBACK(void) vgaR3InfoGR(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + NOREF(pszArgs); + + pHlp->pfnPrintf(pHlp, "VGA Graphics Controller (3CF): GR index 3CE:%02X\n", pThis->gr_index); + Assert(sizeof(pThis->gr) >= 9); + for (unsigned i = 0; i < 9; ++i) + pHlp->pfnPrintf(pHlp, " GR%02X:%02X", i, pThis->gr[i]); + pHlp->pfnPrintf(pHlp, "\n"); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, + * Dumps VGA Attribute Controller registers.} + */ +static DECLCALLBACK(void) vgaR3InfoAR(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + unsigned i; + NOREF(pszArgs); + + pHlp->pfnPrintf(pHlp, "VGA Attribute Controller (3C0): index reg %02X, flip-flop: %d (%s)\n", + pThis->ar_index, pThis->ar_flip_flop, pThis->ar_flip_flop ? "data" : "index" ); + Assert(sizeof(pThis->ar) >= 0x14); + pHlp->pfnPrintf(pHlp, " Palette:"); + for (i = 0; i < 0x10; ++i) + pHlp->pfnPrintf(pHlp, " %02X", pThis->ar[i]); + pHlp->pfnPrintf(pHlp, "\n"); + for (i = 0x10; i <= 0x14; ++i) + pHlp->pfnPrintf(pHlp, " AR%02X:%02X", i, pThis->ar[i]); + pHlp->pfnPrintf(pHlp, "\n"); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, Dumps VGA DAC registers.} + */ +static DECLCALLBACK(void) vgaR3InfoDAC(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + NOREF(pszArgs); + + pHlp->pfnPrintf(pHlp, "VGA DAC contents:\n"); + for (unsigned i = 0; i < 0x100; ++i) + pHlp->pfnPrintf(pHlp, " %02X: %02X %02X %02X\n", + i, pThis->palette[i*3+0], pThis->palette[i*3+1], pThis->palette[i*3+2]); +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, Dumps VBE registers.} + */ +static DECLCALLBACK(void) vgaR3InfoVBE(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + NOREF(pszArgs); + + pHlp->pfnPrintf(pHlp, "LFB at %RGp\n", pThis->GCPhysVRAM); + if (!(pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) + pHlp->pfnPrintf(pHlp, "VBE disabled\n"); + else + { + pHlp->pfnPrintf(pHlp, "VBE state (chip ID 0x%04x):\n", pThis->vbe_regs[VBE_DISPI_INDEX_ID]); + pHlp->pfnPrintf(pHlp, " Display resolution: %d x %d @ %dbpp\n", + pThis->vbe_regs[VBE_DISPI_INDEX_XRES], pThis->vbe_regs[VBE_DISPI_INDEX_YRES], + pThis->vbe_regs[VBE_DISPI_INDEX_BPP]); + pHlp->pfnPrintf(pHlp, " Virtual resolution: %d x %d\n", + pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH], pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT]); + pHlp->pfnPrintf(pHlp, " Display start addr: %d, %d\n", + pThis->vbe_regs[VBE_DISPI_INDEX_X_OFFSET], pThis->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET]); + pHlp->pfnPrintf(pHlp, " Linear scanline pitch: 0x%04x\n", pThis->vbe_line_offset); + pHlp->pfnPrintf(pHlp, " Linear display start : 0x%04x\n", pThis->vbe_start_addr); + pHlp->pfnPrintf(pHlp, " Selected bank: 0x%04x\n", pThis->vbe_regs[VBE_DISPI_INDEX_BANK]); + pHlp->pfnPrintf(pHlp, " DAC: %d-bit\n", pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_8BIT_DAC ? 8 : 6); + } +} + + +/** + * @callback_method_impl{FNDBGFHANDLERDEV, + * Dumps register state relevant to 16-color planar graphics modes (GR/SR) + * in human-readable form.} + */ +static DECLCALLBACK(void) vgaR3InfoPlanar(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + NOREF(pszArgs); + + unsigned val1 = (pThis->gr[5] >> 3) & 1; + unsigned val2 = pThis->gr[5] & 3; + pHlp->pfnPrintf(pHlp, "read mode : %u write mode: %u\n", val1, val2); + val1 = pThis->gr[0]; + val2 = pThis->gr[1]; + pHlp->pfnPrintf(pHlp, "set/reset data: %02X S/R enable: %02X\n", val1, val2); + val1 = pThis->gr[2]; + val2 = pThis->gr[4] & 3; + pHlp->pfnPrintf(pHlp, "color compare : %02X read map : %u\n", val1, val2); + val1 = pThis->gr[3] & 7; + val2 = (pThis->gr[3] >> 3) & 3; + pHlp->pfnPrintf(pHlp, "rotate : %u function : %u\n", val1, val2); + val1 = pThis->gr[7]; + val2 = pThis->gr[8]; + pHlp->pfnPrintf(pHlp, "don't care : %02X bit mask : %02X\n", val1, val2); + val1 = pThis->sr[2]; + val2 = pThis->sr[4] & 8; + pHlp->pfnPrintf(pHlp, "seq plane mask: %02X chain-4 : %s\n", val1, val2 ? "on" : "off"); +} + + +/* -=-=-=-=-=- Ring 3: IBase -=-=-=-=-=- */ + +/** + * @interface_method_impl{PDMIBASE,pfnQueryInterface} + */ +static DECLCALLBACK(void *) vgaR3PortQueryInterface(PPDMIBASE pInterface, const char *pszIID) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IBase); + PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->IBase); + PDMIBASE_RETURN_INTERFACE(pszIID, PDMIDISPLAYPORT, &pThisCC->IPort); +# if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL) + PDMIBASE_RETURN_INTERFACE(pszIID, PDMIDISPLAYVBVACALLBACKS, &pThisCC->IVBVACallbacks); +# endif + PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThisCC->ILeds); + return NULL; +} + + +/* -=-=-=-=-=- Ring 3: ILeds -=-=-=-=-=- */ + +/** + * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed} + */ +static DECLCALLBACK(int) vgaR3PortQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, ILeds); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + switch (iLUN) + { + /* LUN #0 is the only one for which we have a status LED. */ + case 0: + { + *ppLed = &pThis->Led3D; + Assert((*ppLed)->u32Magic == PDMLED_MAGIC); + return VINF_SUCCESS; + } + + default: + AssertMsgFailed(("Invalid LUN #%u\n", iLUN)); + return VERR_PDM_NO_SUCH_LUN; + } +} + + +/* -=-=-=-=-=- Ring 3: Dummy IDisplayConnector -=-=-=-=-=- */ + +/** + * @interface_method_impl{PDMIDISPLAYCONNECTOR,pfnResize} + */ +static DECLCALLBACK(int) vgaR3DummyResize(PPDMIDISPLAYCONNECTOR pInterface, uint32_t cBits, void *pvVRAM, + uint32_t cbLine, uint32_t cx, uint32_t cy) +{ + RT_NOREF(pInterface, cBits, pvVRAM, cbLine, cx, cy); + return VINF_SUCCESS; +} + + +/** + * @interface_method_impl{PDMIDISPLAYCONNECTOR,pfnUpdateRect} + */ +static DECLCALLBACK(void) vgaR3DummyUpdateRect(PPDMIDISPLAYCONNECTOR pInterface, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy) +{ + RT_NOREF(pInterface, x, y, cx, cy); +} + + +/** + * @interface_method_impl{PDMIDISPLAYCONNECTOR,pfnRefresh} + */ +static DECLCALLBACK(void) vgaR3DummyRefresh(PPDMIDISPLAYCONNECTOR pInterface) +{ + NOREF(pInterface); +} + + +/* -=-=-=-=-=- Ring 3: IDisplayPort -=-=-=-=-=- */ + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnUpdateDisplay} + */ +static DECLCALLBACK(int) vgaR3PortUpdateDisplay(PPDMIDISPLAYPORT pInterface) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + + int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + AssertRCReturn(rc, rc); + +# ifdef VBOX_WITH_VMSVGA + if ( pThis->svga.fEnabled + && !pThis->svga.fTraces) + { + /* Nothing to do as the guest will explicitely update us about frame buffer changes. */ + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return VINF_SUCCESS; + } +#endif + +# ifndef VBOX_WITH_HGSMI + /* This should be called only in non VBVA mode. */ +# else + if (VBVAUpdateDisplay(pThis, pThisCC) == VINF_SUCCESS) + { + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return VINF_SUCCESS; + } +# endif /* VBOX_WITH_HGSMI */ + + STAM_COUNTER_INC(&pThis->StatUpdateDisp); + + if (pThis->GCPhysVRAM != 0 && pThis->GCPhysVRAM != NIL_RTGCPHYS) + vgaR3UpdateDirtyBitsAndResetMonitoring(pDevIns, pThis); + + if (pThis->bmPageRemappedVGA != 0) + { + PDMDevHlpMmioResetRegion(pDevIns, pThis->hMmioLegacy); + STAM_COUNTER_INC(&pThis->StatMapReset); + vgaResetRemapped(pThis); + } + + rc = vgaR3UpdateDisplay(pDevIns, pThis, pThisCC, false /*fUpdateAll*/, false /*fFailOnResize*/, true /*reset_dirty*/, + pThisCC->pDrv, &pThis->graphic_mode); + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return rc; +} + + +/** + * Internal vgaR3PortUpdateDisplayAll worker called under pThis->CritSect. + */ +static int vgaR3UpdateDisplayAllInternal(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, bool fFailOnResize) +{ +# ifdef VBOX_WITH_VMSVGA + if ( !pThis->svga.fEnabled + || pThis->svga.fTraces) +# endif + { + /* Update the dirty bits. */ + if (pThis->GCPhysVRAM != 0 && pThis->GCPhysVRAM != NIL_RTGCPHYS) + vgaR3UpdateDirtyBitsAndResetMonitoring(pDevIns, pThis); + } + + if (pThis->bmPageRemappedVGA != 0) + { + PDMDevHlpMmioResetRegion(pDevIns, pThis->hMmioLegacy); + STAM_COUNTER_INC(&pThis->StatMapReset); + vgaResetRemapped(pThis); + } + + pThis->graphic_mode = -1; /* force full update */ + + return vgaR3UpdateDisplay(pDevIns, pThis, pThisCC, true /*fUpdateAll*/, fFailOnResize, + true /*reset_dirty*/, pThisCC->pDrv, &pThis->graphic_mode); +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnUpdateDisplayAll} + */ +static DECLCALLBACK(int) vgaR3PortUpdateDisplayAll(PPDMIDISPLAYPORT pInterface, bool fFailOnResize) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + + /* This is called both in VBVA mode and normal modes. */ + +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortUpdateDisplayAll\n")); +# endif /* DEBUG_sunlover */ + + int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + AssertRCReturn(rc, rc); + + rc = vgaR3UpdateDisplayAllInternal(pDevIns, pThis, pThisCC, fFailOnResize); + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return rc; +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnSetRefreshRate} + */ +static DECLCALLBACK(int) vgaR3PortSetRefreshRate(PPDMIDISPLAYPORT pInterface, uint32_t cMilliesInterval) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + + /* + * Update the interval, notify the VMSVGA FIFO thread if sleeping, + * then restart or stop the timer. + */ + ASMAtomicWriteU32(&pThis->cMilliesRefreshInterval, cMilliesInterval); + +# ifdef VBOX_WITH_VMSVGA + if (pThis->svga.fFIFOThreadSleeping) + PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem); +# endif + + if (cMilliesInterval) + return PDMDevHlpTimerSetMillies(pDevIns, pThis->hRefreshTimer, cMilliesInterval); + return PDMDevHlpTimerStop(pDevIns, pThis->hRefreshTimer); +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnQueryVideoMode} + */ +static DECLCALLBACK(int) vgaR3PortQueryVideoMode(PPDMIDISPLAYPORT pInterface, uint32_t *pcBits, uint32_t *pcx, uint32_t *pcy) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + + AssertReturn(pcBits, VERR_INVALID_PARAMETER); + + *pcBits = vgaR3GetBpp(pThis); + if (pcx) + *pcx = pThis->last_scr_width; + if (pcy) + *pcy = pThis->last_scr_height; + return VINF_SUCCESS; +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnTakeScreenshot} + */ +static DECLCALLBACK(int) vgaR3PortTakeScreenshot(PPDMIDISPLAYPORT pInterface, uint8_t **ppbData, size_t *pcbData, + uint32_t *pcx, uint32_t *pcy) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PDMDEV_ASSERT_EMT(pDevIns); + + LogFlow(("vgaR3PortTakeScreenshot: ppbData=%p pcbData=%p pcx=%p pcy=%p\n", ppbData, pcbData, pcx, pcy)); + + /* + * Validate input. + */ + if (!RT_VALID_PTR(ppbData) || !RT_VALID_PTR(pcbData) || !RT_VALID_PTR(pcx) || !RT_VALID_PTR(pcy)) + return VERR_INVALID_PARAMETER; + + int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + AssertRCReturn(rc, rc); + + /* + * Get screenshot. This function will fail if a resize is required. + * So there is not need to do a 'vgaR3UpdateDisplayAllInternal' before taking screenshot. + */ + + /* + * Allocate the buffer for 32 bits per pixel bitmap + * + * Note! The size can't be zero or greater than the size of the VRAM. + * Inconsistent VGA device state can cause the incorrect size values. + */ + size_t cbRequired = pThis->last_scr_width * 4 * pThis->last_scr_height; + if (cbRequired && cbRequired <= pThis->vram_size) + { + uint8_t *pbData = (uint8_t *)RTMemAlloc(cbRequired); + if (pbData != NULL) + { + /* + * Only 3 methods, assigned below, will be called during the screenshot update. + * All other are already set to NULL. + */ + /* The display connector interface is temporarily replaced with the fake one. */ + PDMIDISPLAYCONNECTOR Connector; + RT_ZERO(Connector); + Connector.pbData = pbData; + Connector.cBits = 32; + Connector.cx = pThis->last_scr_width; + Connector.cy = pThis->last_scr_height; + Connector.cbScanline = Connector.cx * 4; + Connector.pfnRefresh = vgaR3DummyRefresh; + Connector.pfnResize = vgaR3DummyResize; + Connector.pfnUpdateRect = vgaR3DummyUpdateRect; + + int32_t cur_graphic_mode = -1; + + bool fSavedRenderVRAM = pThis->fRenderVRAM; + pThis->fRenderVRAM = true; + + /* + * Take the screenshot. + * + * The second parameter is 'false' because the current display state is being rendered to an + * external buffer using a fake connector. That is if display is blanked, we expect a black + * screen in the external buffer. + * If there is a pending resize, the function will fail. + */ + rc = vgaR3UpdateDisplay(pDevIns, pThis, pThisCC, false /*fUpdateAll*/, true /*fFailOnResize*/, + false /*reset_dirty*/, &Connector, &cur_graphic_mode); + + pThis->fRenderVRAM = fSavedRenderVRAM; + + if (rc == VINF_SUCCESS) + { + /* + * Return the result. + */ + *ppbData = pbData; + *pcbData = cbRequired; + *pcx = Connector.cx; + *pcy = Connector.cy; + } + else + { + /* If we do not return a success, then the data buffer must be freed. */ + RTMemFree(pbData); + if (RT_SUCCESS_NP(rc)) + { + AssertMsgFailed(("%Rrc\n", rc)); + rc = VERR_INTERNAL_ERROR_5; + } + } + } + else + rc = VERR_NO_MEMORY; + } + else + rc = VERR_NOT_SUPPORTED; + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + + LogFlow(("vgaR3PortTakeScreenshot: returns %Rrc (cbData=%d cx=%d cy=%d)\n", rc, *pcbData, *pcx, *pcy)); + return rc; +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnFreeScreenshot} + */ +static DECLCALLBACK(void) vgaR3PortFreeScreenshot(PPDMIDISPLAYPORT pInterface, uint8_t *pbData) +{ + NOREF(pInterface); + + LogFlow(("vgaR3PortFreeScreenshot: pbData=%p\n", pbData)); + + RTMemFree(pbData); +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnDisplayBlt} + */ +static DECLCALLBACK(int) vgaR3PortDisplayBlt(PPDMIDISPLAYPORT pInterface, const void *pvData, + uint32_t x, uint32_t y, uint32_t cx, uint32_t cy) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PDMDEV_ASSERT_EMT(pDevIns); + LogFlow(("vgaR3PortDisplayBlt: pvData=%p x=%d y=%d cx=%d cy=%d\n", pvData, x, y, cx, cy)); + + int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + AssertRCReturn(rc, rc); + + /* + * Validate input. + */ + if ( pvData + && x < pThisCC->pDrv->cx + && cx <= pThisCC->pDrv->cx + && cx + x <= pThisCC->pDrv->cx + && y < pThisCC->pDrv->cy + && cy <= pThisCC->pDrv->cy + && cy + y <= pThisCC->pDrv->cy) + { + /* + * Determine bytes per pixel in the destination buffer. + */ + size_t cbPixelDst = 0; + switch (pThisCC->pDrv->cBits) + { + case 8: + cbPixelDst = 1; + break; + case 15: + case 16: + cbPixelDst = 2; + break; + case 24: + cbPixelDst = 3; + break; + case 32: + cbPixelDst = 4; + break; + default: + rc = VERR_INVALID_PARAMETER; + break; + } + if (RT_SUCCESS(rc)) + { + /* + * The blitting loop. + */ + size_t cbLineSrc = cx * 4; /* 32 bits per pixel. */ + uint8_t *pbSrc = (uint8_t *)pvData; + size_t cbLineDst = pThisCC->pDrv->cbScanline; + uint8_t *pbDst = pThisCC->pDrv->pbData + y * cbLineDst + x * cbPixelDst; + uint32_t cyLeft = cy; + vga_draw_line_func *pfnVgaDrawLine = vga_draw_line_table[VGA_DRAW_LINE32 * 4 + vgaR3GetDepthIndex(pThisCC->pDrv->cBits)]; + Assert(pfnVgaDrawLine); + while (cyLeft-- > 0) + { + pfnVgaDrawLine(pThis, pThisCC, pbDst, pbSrc, cx); + pbDst += cbLineDst; + pbSrc += cbLineSrc; + } + + /* + * Invalidate the area. + */ + pThisCC->pDrv->pfnUpdateRect(pThisCC->pDrv, x, y, cx, cy); + } + } + else + rc = VERR_INVALID_PARAMETER; + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + + LogFlow(("vgaR3PortDisplayBlt: returns %Rrc\n", rc)); + return rc; +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnUpdateDisplayRect} + */ +static DECLCALLBACK(void) vgaR3PortUpdateDisplayRect(PPDMIDISPLAYPORT pInterface, int32_t x, int32_t y, uint32_t cx, uint32_t cy) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + uint32_t v; + + uint32_t cbPixelDst; + uint32_t cbLineDst; + uint8_t *pbDst; + + uint32_t cbPixelSrc; + uint32_t cbLineSrc; + uint8_t *pbSrc; + + +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortUpdateDisplayRect: %d,%d %dx%d\n", x, y, cx, cy)); +# endif /* DEBUG_sunlover */ + + Assert(pInterface); + + int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rc); + + /* Check if there is something to do at all. */ + if (!pThis->fRenderVRAM) + { + /* The framebuffer uses the guest VRAM directly. */ +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortUpdateDisplayRect: nothing to do fRender is false.\n")); +# endif /* DEBUG_sunlover */ + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return; + } + + Assert(pThisCC->pDrv); + Assert(pThisCC->pDrv->pbData); + + /* Correct negative x and y coordinates. */ + if (x < 0) + { + x += cx; /* Compute xRight which is also the new width. */ + cx = (x < 0) ? 0 : x; + x = 0; + } + + if (y < 0) + { + y += cy; /* Compute yBottom, which is also the new height. */ + cy = (y < 0) ? 0 : y; + y = 0; + } + + /* Also check if coords are greater than the display resolution. */ + if (x + cx > pThisCC->pDrv->cx) + { + // x < 0 is not possible here + cx = pThisCC->pDrv->cx > (uint32_t)x? pThisCC->pDrv->cx - x: 0; + } + + if (y + cy > pThisCC->pDrv->cy) + { + // y < 0 is not possible here + cy = pThisCC->pDrv->cy > (uint32_t)y? pThisCC->pDrv->cy - y: 0; + } + +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortUpdateDisplayRect: %d,%d %dx%d (corrected coords)\n", x, y, cx, cy)); +# endif + + /* Check if there is something to do at all. */ + if (cx == 0 || cy == 0) + { + /* Empty rectangle. */ +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortUpdateDisplayRect: nothing to do: %dx%d\n", cx, cy)); +#endif + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return; + } + + /** @todo This method should be made universal and not only for VBVA. + * VGA_DRAW_LINE* must be selected and src/dst address calculation + * changed. + */ + + /* Choose the rendering function. */ + switch(pThisCC->get_bpp(pThis)) + { + default: + case 0: + /* A LFB mode is already disabled, but the callback is still called + * by Display because VBVA buffer is being flushed. + * Nothing to do, just return. + */ + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return; + case 8: + v = VGA_DRAW_LINE8; + break; + case 15: + v = VGA_DRAW_LINE15; + break; + case 16: + v = VGA_DRAW_LINE16; + break; + case 24: + v = VGA_DRAW_LINE24; + break; + case 32: + v = VGA_DRAW_LINE32; + break; + } + + vga_draw_line_func *pfnVgaDrawLine = vga_draw_line_table[v * 4 + vgaR3GetDepthIndex(pThisCC->pDrv->cBits)]; + + /* Compute source and destination addresses and pitches. */ + cbPixelDst = (pThisCC->pDrv->cBits + 7) / 8; + cbLineDst = pThisCC->pDrv->cbScanline; + pbDst = pThisCC->pDrv->pbData + y * cbLineDst + x * cbPixelDst; + + cbPixelSrc = (pThisCC->get_bpp(pThis) + 7) / 8; + uint32_t offSrc, u32Dummy; + pThisCC->get_offsets(pThis, &cbLineSrc, &offSrc, &u32Dummy); + + /* Assume that rendering is performed only on visible part of VRAM. + * This is true because coordinates were verified. + */ + pbSrc = pThisCC->pbVRam; + pbSrc += offSrc * 4 + y * cbLineSrc + x * cbPixelSrc; + + /* Render VRAM to framebuffer. */ + +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortUpdateDisplayRect: dst: %p, %d, %d. src: %p, %d, %d\n", pbDst, cbLineDst, cbPixelDst, pbSrc, cbLineSrc, cbPixelSrc)); +# endif + + while (cy-- > 0) + { + pfnVgaDrawLine(pThis, pThisCC, pbDst, pbSrc, cx); + pbDst += cbLineDst; + pbSrc += cbLineSrc; + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortUpdateDisplayRect: completed.\n")); +# endif +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnCopyRect} + */ +static DECLCALLBACK(int) +vgaR3PortCopyRect(PPDMIDISPLAYPORT pInterface, + uint32_t cx, uint32_t cy, + const uint8_t *pbSrc, int32_t xSrc, int32_t ySrc, uint32_t cxSrc, uint32_t cySrc, + uint32_t cbSrcLine, uint32_t cSrcBitsPerPixel, + uint8_t *pbDst, int32_t xDst, int32_t yDst, uint32_t cxDst, uint32_t cyDst, + uint32_t cbDstLine, uint32_t cDstBitsPerPixel) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + uint32_t v; + +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortCopyRect: %d,%d %dx%d -> %d,%d\n", xSrc, ySrc, cx, cy, xDst, yDst)); +# endif + + Assert(pInterface); + Assert(pThisCC->pDrv); + + int32_t xSrcCorrected = xSrc; + int32_t ySrcCorrected = ySrc; + uint32_t cxCorrected = cx; + uint32_t cyCorrected = cy; + + /* Correct source coordinates to be within the source bitmap. */ + if (xSrcCorrected < 0) + { + xSrcCorrected += cxCorrected; /* Compute xRight which is also the new width. */ + cxCorrected = (xSrcCorrected < 0) ? 0 : xSrcCorrected; + xSrcCorrected = 0; + } + + if (ySrcCorrected < 0) + { + ySrcCorrected += cyCorrected; /* Compute yBottom, which is also the new height. */ + cyCorrected = (ySrcCorrected < 0) ? 0 : ySrcCorrected; + ySrcCorrected = 0; + } + + /* Also check if coords are greater than the display resolution. */ + if (xSrcCorrected + cxCorrected > cxSrc) + { + /* xSrcCorrected < 0 is not possible here */ + cxCorrected = cxSrc > (uint32_t)xSrcCorrected ? cxSrc - xSrcCorrected : 0; + } + + if (ySrcCorrected + cyCorrected > cySrc) + { + /* y < 0 is not possible here */ + cyCorrected = cySrc > (uint32_t)ySrcCorrected ? cySrc - ySrcCorrected : 0; + } + +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortCopyRect: %d,%d %dx%d (corrected coords)\n", xSrcCorrected, ySrcCorrected, cxCorrected, cyCorrected)); +# endif + + /* Check if there is something to do at all. */ + if (cxCorrected == 0 || cyCorrected == 0) + { + /* Empty rectangle. */ +# ifdef DEBUG_sunlover + LogFlow(("vgaPortUpdateDisplayRectEx: nothing to do: %dx%d\n", cxCorrected, cyCorrected)); +# endif + return VINF_SUCCESS; + } + + /* Check that the corrected source rectangle is within the destination. + * Note: source rectangle is adjusted, but the target must be large enough. + */ + if ( xDst < 0 + || yDst < 0 + || xDst + cxCorrected > cxDst + || yDst + cyCorrected > cyDst) + { + return VERR_INVALID_PARAMETER; + } + + int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + AssertRCReturn(rc, rc); + + /* This method only works if the VGA device is in a VBE mode or not paused VBVA mode. + * VGA modes are reported to the caller by returning VERR_INVALID_STATE. + * + * If VBE_DISPI_ENABLED is set, then it is a VBE or VBE compatible VBVA mode. Both of them can be handled. + * + * If VBE_DISPI_ENABLED is clear, then it is either a VGA mode or a VBVA mode set by guest additions + * which have VBVACAPS_USE_VBVA_ONLY capability. + * When VBE_DISPI_ENABLED is being cleared and VBVACAPS_USE_VBVA_ONLY is not set (i.e. guest wants a VGA mode), + * then VBVAOnVBEChanged makes sure that VBVA is paused. + * That is a not paused VBVA means that the video mode can be handled even if VBE_DISPI_ENABLED is clear. + */ + if ( (pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) == 0 + && VBVAIsPaused(pThisCC) +# ifdef VBOX_WITH_VMSVGA + && !pThis->svga.fEnabled +# endif + ) + { + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return VERR_INVALID_STATE; + } + + /* Choose the rendering function. */ + switch (cSrcBitsPerPixel) + { + default: + case 0: + /* Nothing to do, just return. */ + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return VINF_SUCCESS; + case 8: + v = VGA_DRAW_LINE8; + break; + case 15: + v = VGA_DRAW_LINE15; + break; + case 16: + v = VGA_DRAW_LINE16; + break; + case 24: + v = VGA_DRAW_LINE24; + break; + case 32: + v = VGA_DRAW_LINE32; + break; + } + + vga_draw_line_func *pfnVgaDrawLine = vga_draw_line_table[v * 4 + vgaR3GetDepthIndex(cDstBitsPerPixel)]; + + /* Compute source and destination addresses and pitches. */ + uint32_t cbPixelDst = (cDstBitsPerPixel + 7) / 8; + uint32_t cbLineDst = cbDstLine; + uint8_t *pbDstCur = pbDst + yDst * cbLineDst + xDst * cbPixelDst; + + uint32_t cbPixelSrc = (cSrcBitsPerPixel + 7) / 8; + uint32_t cbLineSrc = cbSrcLine; + const uint8_t *pbSrcCur = pbSrc + ySrcCorrected * cbLineSrc + xSrcCorrected * cbPixelSrc; + +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortCopyRect: dst: %p, %d, %d. src: %p, %d, %d\n", pbDstCur, cbLineDst, cbPixelDst, pbSrcCur, cbLineSrc, cbPixelSrc)); +# endif + + while (cyCorrected-- > 0) + { + pfnVgaDrawLine(pThis, pThisCC, pbDstCur, pbSrcCur, cxCorrected); + pbDstCur += cbLineDst; + pbSrcCur += cbLineSrc; + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); +# ifdef DEBUG_sunlover + LogFlow(("vgaR3PortCopyRect: completed.\n")); +# endif + return VINF_SUCCESS; +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnSetRenderVRAM} + */ +static DECLCALLBACK(void) vgaR3PortSetRenderVRAM(PPDMIDISPLAYPORT pInterface, bool fRender) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + + LogFlow(("vgaR3PortSetRenderVRAM: fRender = %d\n", fRender)); + + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + + pThis->fRenderVRAM = fRender; + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnReportHostCursorCapabilities} + */ +static DECLCALLBACK(void) vgaR3PortReportHostCursorCapabilities(PPDMIDISPLAYPORT pInterface, bool fSupportsRenderCursor, + bool fSupportsMoveCursor) +{ + RT_NOREF(pInterface, fSupportsRenderCursor, fSupportsMoveCursor); +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnReportHostCursorPosition} + */ +static DECLCALLBACK(void) vgaR3PortReportHostCursorPosition(PPDMIDISPLAYPORT pInterface, uint32_t x, uint32_t y, bool fOutOfRange) +{ + RT_NOREF(pInterface, x, y, fOutOfRange); +} + + +/** + * @callback_method_impl{FNTMTIMERDEV, VGA Refresh Timer} + */ +static DECLCALLBACK(void) vgaR3TimerRefresh(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, void *pvUser) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + RT_NOREF(pvUser); + + if (pThis->fScanLineCfg & VBVASCANLINECFG_ENABLE_VSYNC_IRQ) + VBVARaiseIrq(pDevIns, pThis, pThisCC, HGSMIHOSTFLAGS_VSYNC); + + if (pThisCC->pDrv) + pThisCC->pDrv->pfnRefresh(pThisCC->pDrv); + + if (pThis->cMilliesRefreshInterval) + PDMDevHlpTimerSetMillies(pDevIns, hTimer, pThis->cMilliesRefreshInterval); + +# ifdef VBOX_WITH_VIDEOHWACCEL + vbvaTimerCb(pDevIns, pThis, pThisCC); +# endif + +# ifdef VBOX_WITH_VMSVGA + /* + * Call the VMSVGA FIFO poller/watchdog so we can wake up the thread if + * there is work to be done. + */ + if (pThis->svga.fFIFOThreadSleeping && pThis->svga.fEnabled && pThis->svga.fConfigured) + vmsvgaR3FifoWatchdogTimer(pDevIns, pThis, pThisCC); +# endif +} + +# ifdef VBOX_WITH_VMSVGA + +/** + * Helper for VMSVGA. + */ +int vgaR3RegisterVRAMHandler(PPDMDEVINS pDevIns, PVGASTATE pThis, uint64_t cbFrameBuffer) +{ + Assert(pThis->GCPhysVRAM != 0 && pThis->GCPhysVRAM != NIL_RTGCPHYS); + int rc = PDMDevHlpMmio2ControlDirtyPageTracking(pDevIns, pThis->hMmio2VRam, true /*fEnabled*/); + RT_NOREF(cbFrameBuffer); + AssertRC(rc); + return rc; +} + + +/** + * Helper for VMSVGA. + */ +int vgaR3UnregisterVRAMHandler(PPDMDEVINS pDevIns, PVGASTATE pThis) +{ + Assert(pThis->GCPhysVRAM != 0 && pThis->GCPhysVRAM != NIL_RTGCPHYS); + int rc = PDMDevHlpMmio2ControlDirtyPageTracking(pDevIns, pThis->hMmio2VRam, false /*fEnabled*/); + AssertRC(rc); + return rc; +} + +# endif /* VBOX_WITH_VMSVGA */ + + +/* -=-=-=-=-=- Ring 3: PCI Device -=-=-=-=-=- */ + +/** + * @callback_method_impl{FNPCIIOREGIONMAP, Mapping/unmapping the VRAM MMI2 region} + */ +static DECLCALLBACK(int) vgaR3PciIORegionVRamMapUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, + RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + Log(("vgaR3PciIORegionVRamMapUnmap: iRegion=%d GCPhysAddress=%RGp cb=%RGp enmType=%d\n", iRegion, GCPhysAddress, cb, enmType)); + RT_NOREF(pPciDev, cb); + +# ifdef VBOX_WITH_VMSVGA + AssertReturn( iRegion == pThis->pciRegions.iVRAM + && ( enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH + || (enmType == PCI_ADDRESS_SPACE_MEM && pThis->fVMSVGAEnabled && pThis->fStateLoaded)), VERR_INTERNAL_ERROR); +# else + AssertReturn( iRegion == pThis->pciRegions.iVRAM + && enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH, VERR_INTERNAL_ERROR); +# endif + + Assert(pPciDev == pDevIns->apPciDevs[0]); + + /* Note! We cannot take the device lock here as that would create a lock order + problem as the caller has taken the PDM lock prior to calling us. If + we did, we will get trouble later when raising interrupts while owning + the device lock (e.g. vmsvgaR3FifoLoop). */ + + int rc; + if (GCPhysAddress != NIL_RTGCPHYS) + { + /* + * Make sure the dirty page tracking state is up to date before mapping it. + */ +# ifdef VBOX_WITH_VMSVGA + rc = PDMDevHlpMmio2ControlDirtyPageTracking(pDevIns, pThis->hMmio2VRam, + !pThis->svga.fEnabled ||(pThis->svga.fEnabled && pThis->svga.fVRAMTracking)); +# else + rc = PDMDevHlpMmio2ControlDirtyPageTracking(pDevIns, pThis->hMmio2VRam, true /*fEnabled*/); +# endif + AssertLogRelRC(rc); + + /* + * Map the VRAM. + */ + rc = PDMDevHlpMmio2Map(pDevIns, pThis->hMmio2VRam, GCPhysAddress); + AssertLogRelRC(rc); + if (RT_SUCCESS(rc)) + { + pThis->GCPhysVRAM = GCPhysAddress; + pThis->vbe_regs[VBE_DISPI_INDEX_FB_BASE_HI] = GCPhysAddress >> 16; + + rc = VINF_PCI_MAPPING_DONE; /* caller doesn't care about any other status, so no problem overwriting error here */ + } + } + else + { + /* + * Unmapping of the VRAM in progress (caller will do that). + */ + Assert(pThis->GCPhysVRAM); + pThis->GCPhysVRAM = 0; + rc = VINF_SUCCESS; + /* NB: VBE_DISPI_INDEX_FB_BASE_HI is left unchanged here. */ + } + return rc; +} + + +# ifdef VBOX_WITH_VMSVGA /* Currently not needed in the non-VMSVGA mode, but keeping it flexible for later. */ +/** + * @interface_method_impl{PDMPCIDEV,pfnRegionLoadChangeHookR3} + */ +static DECLCALLBACK(int) vgaR3PciRegionLoadChangeHook(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, + uint64_t cbRegion, PCIADDRESSSPACE enmType, + PFNPCIIOREGIONOLDSETTER pfnOldSetter, PFNPCIIOREGIONSWAP pfnSwapRegions) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + { + /* + * We messed up BAR order for the hybrid devices in 6.0 (see #9359). + * It should have been compatible with the VBox VGA device and had the + * VRAM region first and I/O second, but instead the I/O region ended + * up first and VRAM second like the VMSVGA device. + * + * So, we have to detect that here and reconfigure the memory regions. + * Region numbers are used in our (and the PCI bus') interfaction with + * PGM, so PGM needs to be informed too. + */ + if ( iRegion == 0 + && iRegion == pThis->pciRegions.iVRAM + && (enmType & PCI_ADDRESS_SPACE_IO)) + { + LogRel(("VGA: Detected old BAR config, making adjustments.\n")); + + /* Update the entries. */ + pThis->pciRegions.iIO = 0; + pThis->pciRegions.iVRAM = 1; + + /* Update PGM on the region number change so it won't barf when restoring state. */ + AssertLogRelReturn(pDevIns->CTX_SUFF(pHlp)->pfnMmio2ChangeRegionNo, VERR_VERSION_MISMATCH); + int rc = pDevIns->CTX_SUFF(pHlp)->pfnMmio2ChangeRegionNo(pDevIns, pThis->hMmio2VRam, 1); + AssertLogRelRCReturn(rc, rc); + /** @todo Update the I/O port too, only currently we don't give a hoot about + * the region number in the I/O port registrations so it can wait... + * (Only visible in the 'info ioport' output IIRC). */ + + /* Update the calling PCI device. */ + AssertLogRelReturn(pfnSwapRegions, VERR_INTERNAL_ERROR_2); + rc = pfnSwapRegions(pPciDev, 0, 1); + AssertLogRelRCReturn(rc, rc); + + return rc; + } + + /* + * The VMSVGA changed the default FIFO size from 128KB to 2MB after 5.1. + */ + if (iRegion == pThis->pciRegions.iFIFO) + { + /* Make sure it's still 32-bit memory. Ignore fluxtuations in the prefetch flag. */ + AssertLogRelMsgReturn(!(enmType & (PCI_ADDRESS_SPACE_IO | PCI_ADDRESS_SPACE_BAR64)), ("enmType=%#x\n", enmType), + VERR_VGA_UNEXPECTED_PCI_REGION_LOAD_CHANGE); + + /* If the size didn't change we're fine, so just return already. */ + if (cbRegion == pThis->svga.cbFIFO) + return VINF_SUCCESS; + + /* If the size is larger than the current configuration, refuse to load. */ + AssertLogRelMsgReturn(cbRegion <= pThis->svga.cbFIFOConfig, + ("cbRegion=%#RGp cbFIFOConfig=%#x cbFIFO=%#x\n", + cbRegion, pThis->svga.cbFIFOConfig, pThis->svga.cbFIFO), + VERR_SSM_LOAD_CONFIG_MISMATCH); + + /* Adjust the size down. */ + int rc = PDMDevHlpMmio2Reduce(pDevIns, pThis->hMmio2VmSvgaFifo, cbRegion); + AssertLogRelMsgRCReturn(rc, + ("cbRegion=%#RGp cbFIFOConfig=%#x cbFIFO=%#x: %Rrc\n", + cbRegion, pThis->svga.cbFIFOConfig, pThis->svga.cbFIFO, rc), + rc); + pThis->svga.cbFIFO = cbRegion; + return rc; + + } + + /* + * VRAM used to be non-prefetchable till 6.1.0, so we end up here when restoring + * states older than that with 6.1.0 and later. We just have to check that + * the size and basic type matches, then return VINF_SUCCESS to ACK it. + */ + if (iRegion == pThis->pciRegions.iVRAM) + { + /* Make sure it's still 32-bit memory. Ignore fluxtuations in the prefetch flag. */ + AssertLogRelMsgReturn(!(enmType & (PCI_ADDRESS_SPACE_IO | PCI_ADDRESS_SPACE_BAR64)), ("enmType=%#x\n", enmType), + VERR_VGA_UNEXPECTED_PCI_REGION_LOAD_CHANGE); + /* The size must be the same. */ + AssertLogRelMsgReturn(cbRegion == pThis->vram_size, + ("cbRegion=%#RGp vram_size=%#x\n", cbRegion, pThis->vram_size), + VERR_SSM_LOAD_CONFIG_MISMATCH); + return VINF_SUCCESS; + } + + /* Emulate callbacks for 5.1 and older saved states by recursion. */ + if (iRegion == UINT32_MAX) + { + int rc = vgaR3PciRegionLoadChangeHook(pDevIns, pPciDev, pThis->pciRegions.iFIFO, VMSVGA_FIFO_SIZE_OLD, + PCI_ADDRESS_SPACE_MEM, NULL, NULL); + if (RT_SUCCESS(rc)) + rc = pfnOldSetter(pPciDev, pThis->pciRegions.iFIFO, VMSVGA_FIFO_SIZE_OLD, PCI_ADDRESS_SPACE_MEM); + return rc; + } + } +# endif /* VBOX_WITH_VMSVGA */ + + return VERR_VGA_UNEXPECTED_PCI_REGION_LOAD_CHANGE; +} +# endif /* VBOX_WITH_VMSVGA */ + + +/* -=-=-=-=-=- Ring3: Misc Wrappers & Sidekicks -=-=-=-=-=- */ + +/** + * Saves a important bits of the VGA device config. + * + * @param pHlp The device helpers (for SSM functions). + * @param pThis The shared VGA instance data. + * @param pSSM The saved state handle. + */ +static void vgaR3SaveConfig(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PSSMHANDLE pSSM) +{ + pHlp->pfnSSMPutU32(pSSM, pThis->vram_size); + pHlp->pfnSSMPutU32(pSSM, pThis->cMonitors); +} + + +/** + * @callback_method_impl{FNSSMDEVLIVEEXEC} + */ +static DECLCALLBACK(int) vgaR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + Assert(uPass == 0); NOREF(uPass); + vgaR3SaveConfig(pDevIns->pHlpR3, pThis, pSSM); + return VINF_SSM_DONT_CALL_AGAIN; +} + + +/** + * @callback_method_impl{FNSSMDEVSAVEPREP} + */ +static DECLCALLBACK(int) vgaR3SavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) +{ +# ifdef VBOX_WITH_VIDEOHWACCEL + RT_NOREF(pSSM); + return vboxVBVASaveStatePrep(pDevIns); +# else + RT_NOREF(pDevIns, pSSM); + return VINF_SUCCESS; +# endif +} + + +/** + * @callback_method_impl{FNSSMDEVSAVEDONE} + */ +static DECLCALLBACK(int) vgaR3SaveDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) +{ +# ifdef VBOX_WITH_VIDEOHWACCEL + RT_NOREF(pSSM); + return vboxVBVASaveStateDone(pDevIns); +# else + RT_NOREF(pDevIns, pSSM); + return VINF_SUCCESS; +# endif +} + + +/** + * @callback_method_impl{FNSSMDEVSAVEEXEC} + */ +static DECLCALLBACK(int) vgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + +# ifdef VBOX_WITH_VDMA + vboxVDMASaveStateExecPrep(pThisCC->pVdma); +# endif + + vgaR3SaveConfig(pHlp, pThis, pSSM); + vga_save(pHlp, pSSM, PDMDEVINS_2_DATA(pDevIns, PVGASTATE)); + + VGA_SAVED_STATE_PUT_MARKER(pSSM, 1); +# ifdef VBOX_WITH_HGSMI + pHlp->pfnSSMPutBool(pSSM, true); + int rc = vboxVBVASaveStateExec(pDevIns, pSSM); +# else + int rc = pHlp->pfnSSMPutBool(pSSM, false); +# endif + + AssertRCReturn(rc, rc); + + VGA_SAVED_STATE_PUT_MARKER(pSSM, 3); +# ifdef VBOX_WITH_VDMA + rc = pHlp->pfnSSMPutU32(pSSM, 1); + AssertRCReturn(rc, rc); + rc = vboxVDMASaveStateExecPerform(pHlp, pThisCC->pVdma, pSSM); +# else + rc = pHlp->pfnSSMPutU32(pSSM, 0); +# endif + AssertRCReturn(rc, rc); + +# ifdef VBOX_WITH_VDMA + vboxVDMASaveStateExecDone(pThisCC->pVdma); +# endif + + VGA_SAVED_STATE_PUT_MARKER(pSSM, 5); +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + { + rc = vmsvgaR3SaveExec(pDevIns, pSSM); + AssertRCReturn(rc, rc); + } +# endif + VGA_SAVED_STATE_PUT_MARKER(pSSM, 6); + + return rc; +} + + +/** + * @callback_method_impl{FNSSMDEVLOADPREP} + */ +static DECLCALLBACK(int) vgaR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + RT_NOREF(pSSM); + pThis->fStateLoaded = true; + return VINF_SUCCESS; +} + + +/** + * @callback_method_impl{FNSSMDEVLOADEXEC} + */ +static DECLCALLBACK(int) vgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc; + + pThis->fStateLoaded = true; + + if (uVersion < VGA_SAVEDSTATE_VERSION_ANCIENT || uVersion > VGA_SAVEDSTATE_VERSION) + return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; + + if (uVersion > VGA_SAVEDSTATE_VERSION_HGSMI) + { + /* Check the config */ + uint32_t cbVRam; + rc = pHlp->pfnSSMGetU32(pSSM, &cbVRam); + AssertRCReturn(rc, rc); + if (pThis->vram_size != cbVRam) + return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("VRAM size changed: config=%#x state=%#x"), pThis->vram_size, cbVRam); + + uint32_t cMonitors; + rc = pHlp->pfnSSMGetU32(pSSM, &cMonitors); + AssertRCReturn(rc, rc); + if (pThis->cMonitors != cMonitors) + return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Monitor count changed: config=%u state=%u"), pThis->cMonitors, cMonitors); + } + + if (uPass == SSM_PASS_FINAL) + { + rc = vga_load(pHlp, pSSM, pThis, uVersion); + if (RT_FAILURE(rc)) + return rc; + + /* + * Restore the HGSMI state, if present. + */ + VGA_SAVED_STATE_GET_MARKER_RETURN_ON_MISMATCH(pSSM, uVersion, 1); + bool fWithHgsmi = uVersion == VGA_SAVEDSTATE_VERSION_HGSMI; + if (uVersion > VGA_SAVEDSTATE_VERSION_HGSMI) + { + rc = pHlp->pfnSSMGetBool(pSSM, &fWithHgsmi); + AssertRCReturn(rc, rc); + } + if (fWithHgsmi) + { +# ifdef VBOX_WITH_HGSMI + rc = vboxVBVALoadStateExec(pDevIns, pSSM, uVersion); + AssertRCReturn(rc, rc); +# else + return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("HGSMI is not compiled in, but it is present in the saved state")); +# endif + } + + VGA_SAVED_STATE_GET_MARKER_RETURN_ON_MISMATCH(pSSM, uVersion, 3); + if (uVersion >= VGA_SAVEDSTATE_VERSION_3D) + { + uint32_t u32; + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + if (u32) + { +# ifdef VBOX_WITH_VDMA + if (u32 == 1) + { + rc = vboxVDMASaveLoadExecPerform(pHlp, pThisCC->pVdma, pSSM, uVersion); + AssertRCReturn(rc, rc); + } + else +# endif + { + LogRel(("invalid CmdVbva version info\n")); + return VERR_VERSION_MISMATCH; + } + } + } + + VGA_SAVED_STATE_GET_MARKER_RETURN_ON_MISMATCH(pSSM, uVersion, 5); +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + { + rc = vmsvgaR3LoadExec(pDevIns, pSSM, uVersion, uPass); + AssertRCReturn(rc, rc); + } +# endif + VGA_SAVED_STATE_GET_MARKER_RETURN_ON_MISMATCH(pSSM, uVersion, 6); + } + return VINF_SUCCESS; +} + + +/** + * @@callback_method_impl{FNSSMDEVLOADDONE} + */ +static DECLCALLBACK(int) vgaR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) +{ + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + int rc; + RT_NOREF(pThisCC, pThis, pSSM); + +# ifdef VBOX_WITH_HGSMI + rc = vboxVBVALoadStateDone(pDevIns); + AssertRCReturn(rc, rc); +# ifdef VBOX_WITH_VDMA + rc = vboxVDMASaveLoadDone(pThisCC->pVdma); + AssertRCReturn(rc, rc); +# endif + /* Now update the current VBVA state which depends on VBE registers. vboxVBVALoadStateDone cleared the state. */ + VBVAOnVBEChanged(pThis, pThisCC); +# endif +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + { + rc = vmsvgaR3LoadDone(pDevIns); + AssertRCReturn(rc, rc); + } +# endif + return VINF_SUCCESS; +} + + +/* -=-=-=-=-=- Ring 3: Device callbacks -=-=-=-=-=- */ + +/** + * @interface_method_impl{PDMDEVREG,pfnResume} + */ +static DECLCALLBACK(void) vgaR3Resume(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + VBVAOnResume(pDevIns, pThis, pThisCC); +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnReset} + */ +static DECLCALLBACK(void) vgaR3Reset(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + char *pchStart; + char *pchEnd; + LogFlow(("vgaReset\n")); + + if (pThisCC->pVdma) + vboxVDMAReset(pThisCC->pVdma); + +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + vmsvgaR3Reset(pDevIns); +# endif + +# ifdef VBOX_WITH_HGSMI + VBVAReset(pDevIns, pThis, pThisCC); +# endif + + + /* Clear the VRAM ourselves. */ + if (pThisCC->pbVRam && pThis->vram_size) + memset(pThisCC->pbVRam, 0, pThis->vram_size); + + /* + * Zero most of it. + * + * Unlike vga_reset we're leaving out a few members which we believe + * must remain unchanged.... + */ + /* 1st part. */ + pchStart = (char *)&pThis->latch; + pchEnd = (char *)&pThis->invalidated_y_table; + memset(pchStart, 0, pchEnd - pchStart); + + /* 2nd part. */ + pchStart = (char *)&pThis->last_palette; + pchEnd = (char *)&pThis->u32Marker; + memset(pchStart, 0, pchEnd - pchStart); + + + /* + * Restore and re-init some bits. + */ + pThisCC->get_bpp = vgaR3GetBpp; + pThisCC->get_offsets = vgaR3GetOffsets; + pThisCC->get_resolution = vgaR3GetResolution; + pThis->graphic_mode = -1; /* Force full update. */ +# ifdef CONFIG_BOCHS_VBE + pThis->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0; + pThis->vbe_regs[VBE_DISPI_INDEX_VBOX_VIDEO] = 0; + pThis->vbe_regs[VBE_DISPI_INDEX_FB_BASE_HI] = pThis->GCPhysVRAM >> 16; + pThis->vbe_bank_max = (pThis->vram_size >> 16) - 1; +# endif /* CONFIG_BOCHS_VBE */ + pThis->st00 = 0x70; /* Static except for bit 4. */ + + /* + * Reset the LFB mapping. + */ + if ( ( pDevIns->fRCEnabled + || pDevIns->fR0Enabled) + && pThis->GCPhysVRAM != 0 + && pThis->GCPhysVRAM != NIL_RTGCPHYS) + { + /** @todo r=bird: This used to be a PDMDevHlpPGMHandlerPhysicalReset call. + * Not quite sure if it was/is needed. Besides, where do we reset the + * dirty bitmap (bmDirtyBitmap)? */ + int rc = PDMDevHlpMmio2ResetDirtyBitmap(pDevIns, pThis->hMmio2VRam); + AssertRC(rc); + } + if (pThis->bmPageRemappedVGA != 0) + { + PDMDevHlpMmioResetRegion(pDevIns, pThis->hMmioLegacy); + STAM_COUNTER_INC(&pThis->StatMapReset); + vgaResetRemapped(pThis); + } + + /* + * Reset the logo data. + */ + pThisCC->LogoCommand = LOGO_CMD_NOP; + pThisCC->offLogoData = 0; + + /* notify port handler */ + if (pThisCC->pDrv) + { + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */ + + pThisCC->pDrv->pfnReset(pThisCC->pDrv); + pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, false, false, 0, 0, 0, 0, NULL); + + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + } + + /* Reset latched access mask. */ + pThis->uMaskLatchAccess = 0x3ff; + pThis->cLatchAccesses = 0; + pThis->u64LastLatchedAccess = 0; + pThis->iMask = 0; + + /* Reset retrace emulation. */ + memset(&pThis->retrace_state, 0, sizeof(pThis->retrace_state)); +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnPowerOn} + */ +static DECLCALLBACK(void) vgaR3PowerOn(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + vmsvgaR3PowerOn(pDevIns); +# endif + VBVAOnResume(pDevIns, pThis, pThisCC); +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnPowerOff} + */ +static DECLCALLBACK(void) vgaR3PowerOff(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + RT_NOREF(pThis, pThisCC); +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + vmsvgaR3PowerOff(pDevIns); +# endif +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnRelocate} + */ +static DECLCALLBACK(void) vgaR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) +{ +# ifdef VBOX_WITH_RAW_MODE_KEEP + if (offDelta) + { + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + LogFlow(("vgaRelocate: offDelta = %08X\n", offDelta)); + + pThisRC->pbVRam += offDelta; + pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); + } +# else + RT_NOREF(pDevIns, offDelta); +# endif +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnAttach} + * + * This is like plugging in the monitor after turning on the PC. + */ +static DECLCALLBACK(int) vgaAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + + RT_NOREF(pThis); + + AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, + ("VGA device does not support hotplugging\n"), + VERR_INVALID_PARAMETER); + + switch (iLUN) + { + /* LUN #0: Display port. */ + case 0: + { + int rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pThisCC->IBase, &pThisCC->pDrvBase, "Display Port"); + if (RT_SUCCESS(rc)) + { + pThisCC->pDrv = PDMIBASE_QUERY_INTERFACE(pThisCC->pDrvBase, PDMIDISPLAYCONNECTOR); + if (pThisCC->pDrv) + { + /* pThisCC->pDrv->pbData can be NULL when there is no framebuffer. */ + if ( pThisCC->pDrv->pfnRefresh + && pThisCC->pDrv->pfnResize + && pThisCC->pDrv->pfnUpdateRect) + rc = VINF_SUCCESS; + else + { + Assert(pThisCC->pDrv->pfnRefresh); + Assert(pThisCC->pDrv->pfnResize); + Assert(pThisCC->pDrv->pfnUpdateRect); + pThisCC->pDrv = NULL; + pThisCC->pDrvBase = NULL; + rc = VERR_INTERNAL_ERROR; + } +# ifdef VBOX_WITH_VIDEOHWACCEL + if(rc == VINF_SUCCESS) + { + rc = vbvaVHWAConstruct(pDevIns, pThis, pThisCC); + if (rc != VERR_NOT_IMPLEMENTED) + AssertRC(rc); + } +# endif + } + else + { + AssertMsgFailed(("LUN #0 doesn't have a display connector interface! rc=%Rrc\n", rc)); + pThisCC->pDrvBase = NULL; + rc = VERR_PDM_MISSING_INTERFACE; + } + } + else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) + { + Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pReg->szName, pDevIns->iInstance)); + rc = VINF_SUCCESS; + } + else + AssertLogRelMsgFailed(("Failed to attach LUN #0! rc=%Rrc\n", rc)); + return rc; + } + + default: + AssertMsgFailed(("Invalid LUN #%d\n", iLUN)); + return VERR_PDM_NO_SUCH_LUN; + } +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnDetach} + * + * This is like unplugging the monitor while the PC is still running. + */ +static DECLCALLBACK(void) vgaDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) +{ + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, ("VGA device does not support hotplugging\n")); + RT_NOREF(fFlags); + + /* + * Reset the interfaces and update the controller state. + */ + switch (iLUN) + { + /* LUN #0: Display port. */ + case 0: + pThisCC->pDrv = NULL; + pThisCC->pDrvBase = NULL; + break; + + default: + AssertMsgFailed(("Invalid LUN #%d\n", iLUN)); + break; + } +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnDestruct} + */ +static DECLCALLBACK(int) vgaR3Destruct(PPDMDEVINS pDevIns) +{ + PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + LogFlow(("vgaR3Destruct:\n")); + +# ifdef VBOX_WITH_VDMA + if (pThisCC->pVdma) + vboxVDMADestruct(pThisCC->pVdma); +# endif + +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + vmsvgaR3Destruct(pDevIns); +# endif + +# ifdef VBOX_WITH_HGSMI + VBVADestroy(pThisCC); +# endif + + /* + * Free MM heap pointers. + */ + if (pThisCC->pbVBEExtraData) + { + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pbVBEExtraData); + pThisCC->pbVBEExtraData = NULL; + } + if (pThisCC->pbVgaBios) + { + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pbVgaBios); + pThisCC->pbVgaBios = NULL; + } + + if (pThisCC->pszVgaBiosFile) + { + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pszVgaBiosFile); + pThisCC->pszVgaBiosFile = NULL; + } + + if (pThisCC->pszLogoFile) + { + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pszLogoFile); + pThisCC->pszLogoFile = NULL; + } + + if (pThisCC->pbLogo) + { + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pbLogo); + pThisCC->pbLogo = NULL; + } + +# if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_VDMA) || defined(VBOX_WITH_WDDM) + PDMDevHlpCritSectDelete(pDevIns, &pThis->CritSectIRQ); +# endif + PDMDevHlpCritSectDelete(pDevIns, &pThis->CritSect); + return VINF_SUCCESS; +} + + +/** + * Adjust VBE mode information + * + * Depending on the configured VRAM size, certain parts of VBE mode + * information must be updated. + * + * @param pThis The device instance data. + * @param pMode The mode information structure. + */ +static void vgaR3AdjustModeInfo(PVGASTATE pThis, ModeInfoListItem *pMode) +{ + /* For 4bpp modes, the planes are "stacked" on top of each other. */ + unsigned bpl = pMode->info.BytesPerScanLine * pMode->info.NumberOfPlanes; + /* The "number of image pages" is really the max page index... */ + unsigned maxPage = pThis->vram_size / (pMode->info.YResolution * bpl) - 1; + if (maxPage > 255) + maxPage = 255; /* 8-bit value. */ + pMode->info.NumberOfImagePages = maxPage; + pMode->info.LinNumberOfPages = maxPage; +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnConstruct} + */ +static DECLCALLBACK(int) vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) +{ + PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc; + unsigned i; + uint32_t cCustomModes; + uint32_t cyReduction; + uint32_t cbPitch; + PVBEHEADER pVBEDataHdr; + ModeInfoListItem *pCurMode; + unsigned cb; + + Assert(iInstance == 0); + + /* + * Init static data. + */ + static bool s_fExpandDone = false; + if (!s_fExpandDone) + { + s_fExpandDone = true; + vgaR3InitExpand(); + } + + /* + * Validate configuration. + */ + static const char s_szMscWorkaround[] = "VRamSize" + "|MonitorCount" + "|FadeIn" + "|FadeOut" + "|LogoTime" + "|LogoFile" + "|ShowBootMenu" + "|BiosRom" + "|RealRetrace" + "|CustomVideoModes" + "|HeightReduction" + "|CustomVideoMode1" + "|CustomVideoMode2" + "|CustomVideoMode3" + "|CustomVideoMode4" + "|CustomVideoMode5" + "|CustomVideoMode6" + "|CustomVideoMode7" + "|CustomVideoMode8" + "|CustomVideoMode9" + "|CustomVideoMode10" + "|CustomVideoMode11" + "|CustomVideoMode12" + "|CustomVideoMode13" + "|CustomVideoMode14" + "|CustomVideoMode15" + "|CustomVideoMode16" + "|MaxBiosXRes" + "|MaxBiosYRes" +# ifdef VBOX_WITH_VMSVGA + "|VMSVGAEnabled" + "|VMSVGA10" + "|VMSVGAPciId" + "|VMSVGAPciBarLayout" + "|VMSVGAFifoSize" +# endif +# ifdef VBOX_WITH_VMSVGA3D + "|VMSVGA3dEnabled" + "|VMSVGA3dOverlayEnabled" +# endif + "|SuppressNewYearSplash" + "|3DEnabled"; + + PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, s_szMscWorkaround, ""); + + /* + * Init state data. + */ + rc = pHlp->pfnCFGMQueryU32Def(pCfg, "VRamSize", &pThis->vram_size, VGA_VRAM_DEFAULT); + AssertLogRelRCReturn(rc, rc); + if (pThis->vram_size > VGA_VRAM_MAX) + return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS, + "VRamSize is too large, %#x, max %#x", pThis->vram_size, VGA_VRAM_MAX); + if (pThis->vram_size < VGA_VRAM_MIN) + return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS, + "VRamSize is too small, %#x, max %#x", pThis->vram_size, VGA_VRAM_MIN); + if (pThis->vram_size & (_256K - 1)) /* Make sure there are no partial banks even in planar modes. */ + return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS, + "VRamSize is not a multiple of 256K (%#x)", pThis->vram_size); + + rc = pHlp->pfnCFGMQueryU32Def(pCfg, "MonitorCount", &pThis->cMonitors, 1); + AssertLogRelRCReturn(rc, rc); + + Log(("VGA: VRamSize=%#x fGCenabled=%RTbool fR0Enabled=%RTbool\n", pThis->vram_size, pDevIns->fRCEnabled, pDevIns->fR0Enabled)); + + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "3DEnabled", &pThis->f3DEnabled, false); + AssertLogRelRCReturn(rc, rc); + Log(("VGA: f3DEnabled=%RTbool\n", pThis->f3DEnabled)); + +# ifdef VBOX_WITH_VMSVGA + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "VMSVGAEnabled", &pThis->fVMSVGAEnabled, false); + AssertLogRelRCReturn(rc, rc); + Log(("VMSVGA: VMSVGAEnabled = %d\n", pThis->fVMSVGAEnabled)); + + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "VMSVGA10", &pThis->fVMSVGA10, true); + AssertLogRelRCReturn(rc, rc); + Log(("VMSVGA: VMSVGA10 = %d\n", pThis->fVMSVGA10)); + + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "VMSVGAPciId", &pThis->fVMSVGAPciId, false); + AssertLogRelRCReturn(rc, rc); + Log(("VMSVGA: VMSVGAPciId = %d\n", pThis->fVMSVGAPciId)); + + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "VMSVGAPciBarLayout", &pThis->fVMSVGAPciBarLayout, pThis->fVMSVGAPciId); + AssertLogRelRCReturn(rc, rc); + Log(("VMSVGA: VMSVGAPciBarLayout = %d\n", pThis->fVMSVGAPciBarLayout)); + + rc = pHlp->pfnCFGMQueryU32Def(pCfg, "VMSVGAFifoSize", &pThis->svga.cbFIFO, VMSVGA_FIFO_SIZE); + AssertLogRelRCReturn(rc, rc); + AssertLogRelMsgReturn(pThis->svga.cbFIFO >= _128K, ("cbFIFO=%#x\n", pThis->svga.cbFIFO), VERR_OUT_OF_RANGE); + AssertLogRelMsgReturn(pThis->svga.cbFIFO <= _16M, ("cbFIFO=%#x\n", pThis->svga.cbFIFO), VERR_OUT_OF_RANGE); + AssertLogRelMsgReturn(RT_IS_POWER_OF_TWO(pThis->svga.cbFIFO), ("cbFIFO=%#x\n", pThis->svga.cbFIFO), VERR_NOT_POWER_OF_TWO); + pThis->svga.cbFIFOConfig = pThis->svga.cbFIFO; + Log(("VMSVGA: VMSVGAFifoSize = %#x (%'u)\n", pThis->svga.cbFIFO, pThis->svga.cbFIFO)); +# endif +# ifdef VBOX_WITH_VMSVGA3D + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "VMSVGA3dEnabled", &pThis->svga.f3DEnabled, false); + AssertLogRelRCReturn(rc, rc); + Log(("VMSVGA: VMSVGA3dEnabled = %d\n", pThis->svga.f3DEnabled)); + + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "VMSVGA3dOverlayEnabled", &pThis->svga.f3DOverlayEnabled, false); + AssertLogRelRCReturn(rc, rc); + Log(("VMSVGA: VMSVGA3dOverlayEnabled = %d\n", pThis->svga.f3DOverlayEnabled)); +# endif + +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAPciBarLayout) + { + pThis->pciRegions.iIO = 0; + pThis->pciRegions.iVRAM = 1; + } + else + { + pThis->pciRegions.iVRAM = 0; + pThis->pciRegions.iIO = 1; + } + pThis->pciRegions.iFIFO = 2; +# else + pThis->pciRegions.iVRAM = 0; +# endif + + pThisCC->pDevIns = pDevIns; + + vgaR3Reset(pDevIns); + + /* The PCI devices configuration. */ + PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; + PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); + +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + { + /* Extend our VGA device with VMWare SVGA functionality. */ + if (pThis->fVMSVGAPciId) + { + PDMPciDevSetVendorId(pPciDev, PCI_VENDOR_ID_VMWARE); + PDMPciDevSetDeviceId(pPciDev, PCI_DEVICE_ID_VMWARE_SVGA2); + } + else + { + PDMPciDevSetVendorId(pPciDev, 0x80ee); /* PCI vendor, just a free bogus value */ + PDMPciDevSetDeviceId(pPciDev, 0xbeef); + } + PDMPciDevSetSubSystemVendorId(pPciDev, PCI_VENDOR_ID_VMWARE); + PDMPciDevSetSubSystemId(pPciDev, PCI_DEVICE_ID_VMWARE_SVGA2); + } + else +# endif /* VBOX_WITH_VMSVGA */ + { + PDMPciDevSetVendorId(pPciDev, 0x80ee); /* PCI vendor, just a free bogus value */ + PDMPciDevSetDeviceId(pPciDev, 0xbeef); + } + PDMPciDevSetClassSub(pPciDev, 0x00); /* VGA controller */ + PDMPciDevSetClassBase(pPciDev, 0x03); + PDMPciDevSetHeaderType(pPciDev, 0x00); +# if defined(VBOX_WITH_HGSMI) && (defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_VDMA) || defined(VBOX_WITH_WDDM)) + PDMPciDevSetInterruptPin(pPciDev, 1); +# endif + + /* the interfaces. */ + pThisCC->IBase.pfnQueryInterface = vgaR3PortQueryInterface; + + pThisCC->IPort.pfnUpdateDisplay = vgaR3PortUpdateDisplay; + pThisCC->IPort.pfnUpdateDisplayAll = vgaR3PortUpdateDisplayAll; + pThisCC->IPort.pfnQueryVideoMode = vgaR3PortQueryVideoMode; + pThisCC->IPort.pfnSetRefreshRate = vgaR3PortSetRefreshRate; + pThisCC->IPort.pfnTakeScreenshot = vgaR3PortTakeScreenshot; + pThisCC->IPort.pfnFreeScreenshot = vgaR3PortFreeScreenshot; + pThisCC->IPort.pfnDisplayBlt = vgaR3PortDisplayBlt; + pThisCC->IPort.pfnUpdateDisplayRect = vgaR3PortUpdateDisplayRect; + pThisCC->IPort.pfnCopyRect = vgaR3PortCopyRect; + pThisCC->IPort.pfnSetRenderVRAM = vgaR3PortSetRenderVRAM; + pThisCC->IPort.pfnSetViewport = NULL; + pThisCC->IPort.pfnReportMonitorPositions = NULL; +# ifdef VBOX_WITH_VMSVGA + if (pThis->fVMSVGAEnabled) + { + pThisCC->IPort.pfnSetViewport = vmsvgaR3PortSetViewport; + pThisCC->IPort.pfnReportMonitorPositions = vmsvgaR3PortReportMonitorPositions; + } +# endif + pThisCC->IPort.pfnSendModeHint = vbvaR3PortSendModeHint; + pThisCC->IPort.pfnReportHostCursorCapabilities = vgaR3PortReportHostCursorCapabilities; + pThisCC->IPort.pfnReportHostCursorPosition = vgaR3PortReportHostCursorPosition; + +# if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL) + pThisCC->IVBVACallbacks.pfnVHWACommandCompleteAsync = vbvaR3VHWACommandCompleteAsync; +# endif + + pThisCC->ILeds.pfnQueryStatusLed = vgaR3PortQueryStatusLed; + pThis->Led3D.u32Magic = PDMLED_MAGIC; + + /* + * We use our own critical section to avoid unncessary pointer indirections + * in interface methods (as well as for historical reasons). + */ + rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "VGA#%u", iInstance); + AssertRCReturn(rc, rc); + rc = PDMDevHlpSetDeviceCritSect(pDevIns, &pThis->CritSect); + AssertRCReturn(rc, rc); + +# ifdef VBOX_WITH_HGSMI + /* + * This critical section is used by vgaR3IOPortHgsmiWrite, VBVARaiseIrq and VBVAOnResume + * for some IRQ related synchronization. + */ + rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSectIRQ, RT_SRC_POS, "VGA#%u_IRQ", iInstance); + AssertRCReturn(rc, rc); +# endif + + /* + * PCI device registration. + */ + rc = PDMDevHlpPCIRegister(pDevIns, pPciDev); + if (RT_FAILURE(rc)) + return rc; + /*AssertMsg(pThis->Dev.uDevFn == 16 || iInstance != 0, ("pThis->Dev.uDevFn=%d\n", pThis->Dev.uDevFn));*/ + if (pPciDev->uDevFn != 16 && iInstance == 0) + Log(("!!WARNING!!: pThis->dev.uDevFn=%d (ignore if testcase or not started by Main)\n", pPciDev->uDevFn)); + +# ifdef VBOX_WITH_VMSVGA + pThis->hIoPortVmSvga = NIL_IOMIOPORTHANDLE; + pThis->hMmio2VmSvgaFifo = NIL_PGMMMIO2HANDLE; + if (pThis->fVMSVGAEnabled) + { + /* Register the io command ports. */ + rc = PDMDevHlpPCIIORegionCreateIo(pDevIns, pThis->pciRegions.iIO, 0x10, vmsvgaIOWrite, vmsvgaIORead, NULL /*pvUser*/, + "VMSVGA", NULL /*paExtDescs*/, &pThis->hIoPortVmSvga); + AssertRCReturn(rc, rc); + + rc = PDMDevHlpPCIIORegionCreateMmio2Ex(pDevIns, pThis->pciRegions.iFIFO, pThis->svga.cbFIFO, + PCI_ADDRESS_SPACE_MEM, 0 /*fFlags*/, vmsvgaR3PciIORegionFifoMapUnmap, + "VMSVGA-FIFO", (void **)&pThisCC->svga.pau32FIFO, &pThis->hMmio2VmSvgaFifo); + AssertRCReturn(rc, PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, + N_("Failed to create VMSVGA FIFO (%u bytes)"), pThis->svga.cbFIFO)); + + pPciDev->pfnRegionLoadChangeHookR3 = vgaR3PciRegionLoadChangeHook; + } +# endif /* VBOX_WITH_VMSVGA */ + + /* + * Allocate VRAM and create a PCI region for it. + */ + rc = PDMDevHlpPCIIORegionCreateMmio2Ex(pDevIns, pThis->pciRegions.iVRAM, pThis->vram_size, + PCI_ADDRESS_SPACE_MEM_PREFETCH, PGMPHYS_MMIO2_FLAGS_TRACK_DIRTY_PAGES, + vgaR3PciIORegionVRamMapUnmap, "VRam", (void **)&pThisCC->pbVRam, &pThis->hMmio2VRam); + AssertLogRelRCReturn(rc, PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, + N_("Failed to allocate %u bytes of VRAM"), pThis->vram_size)); + + /* + * Register I/O ports. + */ +# define REG_PORT(a_uPort, a_cPorts, a_pfnWrite, a_pfnRead, a_szDesc, a_phIoPort) do { \ + rc = PDMDevHlpIoPortCreateFlagsAndMap(pDevIns, a_uPort, a_cPorts, IOM_IOPORT_F_ABS, \ + a_pfnWrite, a_pfnRead, "VGA - " a_szDesc, NULL /*paExtDescs*/, a_phIoPort); \ + AssertRCReturn(rc, rc); \ + } while (0) + REG_PORT(0x3c0, 2, vgaIoPortArWrite, vgaIoPortArRead, "Attribute Controller", &pThis->hIoPortAr); + REG_PORT(0x3c2, 1, vgaIoPortMsrWrite, vgaIoPortSt00Read, "MSR / ST00", &pThis->hIoPortMsrSt00); + REG_PORT(0x3c3, 1, vgaIoPortUnusedWrite, vgaIoPortUnusedRead, "0x3c3", &pThis->hIoPort3c3); + REG_PORT(0x3c4, 2, vgaIoPortSrWrite, vgaIoPortSrRead, "Sequencer", &pThis->hIoPortSr); + REG_PORT(0x3c6, 4, vgaIoPortDacWrite, vgaIoPortDacRead, "DAC", &pThis->hIoPortDac); + REG_PORT(0x3ca, 4, vgaIoPortPosWrite, vgaIoPortPosRead, "Graphics Position", /*?*/ &pThis->hIoPortPos); + REG_PORT(0x3ce, 2, vgaIoPortGrWrite, vgaIoPortGrRead, "Graphics Controller", &pThis->hIoPortGr); + + /* Note! Ralf Brown lists 0x3b0-0x3b1, 0x3b2-0x3b3 and 0x3b6-0x3b7 as "the same as" 0x3b4-0x3b5. */ + REG_PORT(0x3b4, 2, vgaIoPortMdaCrtWrite, vgaIoPortMdaCrtRead, "MDA CRT control", &pThis->hIoPortMdaCrt); + REG_PORT(0x3ba, 1, vgaIoPortMdaFcrWrite, vgaIoPortMdaStRead, "MDA feature/status", &pThis->hIoPortMdaFcrSt); + REG_PORT(0x3d4, 2, vgaIoPortCgaCrtWrite, vgaIoPortCgaCrtRead, "CGA CRT control", &pThis->hIoPortCgaCrt); + REG_PORT(0x3da, 1, vgaIoPortCgaFcrWrite, vgaIoPortCgaStRead, "CGA Feature / status", &pThis->hIoPortCgaFcrSt); + +# ifdef CONFIG_BOCHS_VBE + REG_PORT(0x1ce, 1, vgaIoPortWriteVbeIndex, vgaIoPortReadVbeIndex, "VBE Index", &pThis->hIoPortVbeIndex); + REG_PORT(0x1cf, 1, vgaIoPortWriteVbeData, vgaIoPortReadVbeData, "VBE Data", &pThis->hIoPortVbeData); +# endif /* CONFIG_BOCHS_VBE */ + +# ifdef VBOX_WITH_HGSMI + /* Use reserved VGA IO ports for HGSMI. */ + REG_PORT(VGA_PORT_HGSMI_HOST, 4, vgaR3IOPortHgsmiWrite, vgaR3IOPortHgmsiRead, "HGSMI host (3b0-3b3)", &pThis->hIoPortHgsmiHost); + REG_PORT(VGA_PORT_HGSMI_GUEST, 4, vgaR3IOPortHgsmiWrite, vgaR3IOPortHgmsiRead, "HGSMI guest (3d0-3d3)", &pThis->hIoPortHgsmiGuest); +# endif /* VBOX_WITH_HGSMI */ + +# undef REG_PORT + + /* vga bios */ + rc = PDMDevHlpIoPortCreateAndMap(pDevIns, VBE_PRINTF_PORT, 1 /*cPorts*/, vgaIoPortWriteBios, vgaIoPortReadBios, + "VGA BIOS debug/panic", NULL /*paExtDescs*/, &pThis->hIoPortBios); + AssertRCReturn(rc, rc); + + /* + * The MDA/CGA/EGA/VGA/whatever fixed MMIO area. + */ + rc = PDMDevHlpMmioCreateExAndMap(pDevIns, 0x000a0000, 0x00020000, + IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU | IOMMMIO_FLAGS_ABS, + NULL /*pPciDev*/, UINT32_MAX /*iPciRegion*/, + vgaMmioWrite, vgaMmioRead, vgaMmioFill, NULL /*pvUser*/, + "VGA - VGA Video Buffer", &pThis->hMmioLegacy); + AssertRCReturn(rc, rc); + + /* + * Get the VGA BIOS ROM file name. + */ + rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "BiosRom", &pThisCC->pszVgaBiosFile); + if (rc == VERR_CFGM_VALUE_NOT_FOUND) + { + pThisCC->pszVgaBiosFile = NULL; + rc = VINF_SUCCESS; + } + else if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Querying \"BiosRom\" as a string failed")); + else if (!*pThisCC->pszVgaBiosFile) + { + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pszVgaBiosFile); + pThisCC->pszVgaBiosFile = NULL; + } + + /* + * Determine the VGA BIOS ROM size, open specified ROM file in the process. + */ + RTFILE FileVgaBios = NIL_RTFILE; + if (pThisCC->pszVgaBiosFile) + { + rc = RTFileOpen(&FileVgaBios, pThisCC->pszVgaBiosFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_SUCCESS(rc)) + { + rc = RTFileQuerySize(FileVgaBios, &pThisCC->cbVgaBios); + if (RT_SUCCESS(rc)) + { + if ( RT_ALIGN(pThisCC->cbVgaBios, _4K) != pThisCC->cbVgaBios + || pThisCC->cbVgaBios > _64K + || pThisCC->cbVgaBios < 16 * _1K) + rc = VERR_TOO_MUCH_DATA; + } + } + if (RT_FAILURE(rc)) + { + /* + * In case of failure simply fall back to the built-in VGA BIOS ROM. + */ + Log(("vgaConstruct: Failed to open VGA BIOS ROM file '%s', rc=%Rrc!\n", pThisCC->pszVgaBiosFile, rc)); + RTFileClose(FileVgaBios); + FileVgaBios = NIL_RTFILE; + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pszVgaBiosFile); + pThisCC->pszVgaBiosFile = NULL; + } + } + + /* + * Attempt to get the VGA BIOS ROM data from file. + */ + if (pThisCC->pszVgaBiosFile) + { + /* + * Allocate buffer for the VGA BIOS ROM data. + */ + pThisCC->pbVgaBios = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThisCC->cbVgaBios); + if (pThisCC->pbVgaBios) + { + rc = RTFileRead(FileVgaBios, pThisCC->pbVgaBios, pThisCC->cbVgaBios, NULL); + if (RT_FAILURE(rc)) + { + AssertMsgFailed(("RTFileRead(,,%d,NULL) -> %Rrc\n", pThisCC->cbVgaBios, rc)); + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pbVgaBios); + pThisCC->pbVgaBios = NULL; + } + rc = VINF_SUCCESS; + } + else + rc = VERR_NO_MEMORY; + } + else + pThisCC->pbVgaBios = NULL; + + /* cleanup */ + if (FileVgaBios != NIL_RTFILE) + RTFileClose(FileVgaBios); + + /* If we were unable to get the data from file for whatever reason, fall + back to the built-in ROM image. */ + const uint8_t *pbVgaBiosBinary; + uint64_t cbVgaBiosBinary; + uint32_t fFlags = 0; + if (pThisCC->pbVgaBios == NULL) + { + CPUMMICROARCH enmMicroarch = PDMDevHlpCpuGetGuestMicroarch(pDevIns); + if ( enmMicroarch == kCpumMicroarch_Intel_8086 + || enmMicroarch == kCpumMicroarch_Intel_80186 + || enmMicroarch == kCpumMicroarch_NEC_V20 + || enmMicroarch == kCpumMicroarch_NEC_V30) + { + pbVgaBiosBinary = g_abVgaBiosBinary8086; + cbVgaBiosBinary = g_cbVgaBiosBinary8086; + LogRel(("VGA: Using the 8086 BIOS image!\n")); + } + else if (enmMicroarch == kCpumMicroarch_Intel_80286) + { + pbVgaBiosBinary = g_abVgaBiosBinary286; + cbVgaBiosBinary = g_cbVgaBiosBinary286; + LogRel(("VGA: Using the 286 BIOS image!\n")); + } + else + { + pbVgaBiosBinary = g_abVgaBiosBinary386; + cbVgaBiosBinary = g_cbVgaBiosBinary386; + LogRel(("VGA: Using the 386+ BIOS image.\n")); + } + fFlags = PGMPHYS_ROM_FLAGS_PERMANENT_BINARY; + } + else + { + pbVgaBiosBinary = pThisCC->pbVgaBios; + cbVgaBiosBinary = pThisCC->cbVgaBios; + } + + AssertReleaseMsg(cbVgaBiosBinary <= _64K && cbVgaBiosBinary >= 32*_1K, ("cbVgaBiosBinary=%#x\n", cbVgaBiosBinary)); + AssertReleaseMsg(RT_ALIGN_Z(cbVgaBiosBinary, GUEST_PAGE_SIZE) == cbVgaBiosBinary, ("cbVgaBiosBinary=%#x\n", cbVgaBiosBinary)); + /* Note! Because of old saved states we'll always register at least 36KB of ROM. */ + rc = PDMDevHlpROMRegister(pDevIns, 0x000c0000, RT_MAX(cbVgaBiosBinary, 36*_1K), pbVgaBiosBinary, cbVgaBiosBinary, + fFlags, "VGA BIOS"); + AssertRCReturn(rc, rc); + + /* + * Saved state. + */ + rc = PDMDevHlpSSMRegisterEx(pDevIns, VGA_SAVEDSTATE_VERSION, sizeof(*pThis), NULL, + NULL, vgaR3LiveExec, NULL, + vgaR3SavePrep, vgaR3SaveExec, vgaR3SaveDone, + vgaR3LoadPrep, vgaR3LoadExec, vgaR3LoadDone); + AssertRCReturn(rc, rc); + + /* + * Create the refresh timer. + */ + rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_REAL, vgaR3TimerRefresh, NULL, + TMTIMER_FLAGS_NO_CRIT_SECT | TMTIMER_FLAGS_NO_RING0, "VGA Refresh", &pThis->hRefreshTimer); + AssertRCReturn(rc, rc); + + /* + * Attach to the display. + */ + rc = vgaAttach(pDevIns, 0 /* display LUN # */, PDM_TACH_FLAGS_NOT_HOT_PLUG); + AssertRCReturn(rc, rc); + + /* + * Initialize the retrace flag. + */ + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "RealRetrace", &pThis->fRealRetrace, false); + AssertLogRelRCReturn(rc, rc); + + uint16_t maxBiosXRes; + rc = pHlp->pfnCFGMQueryU16Def(pCfg, "MaxBiosXRes", &maxBiosXRes, UINT16_MAX); + AssertLogRelRCReturn(rc, rc); + uint16_t maxBiosYRes; + rc = pHlp->pfnCFGMQueryU16Def(pCfg, "MaxBiosYRes", &maxBiosYRes, UINT16_MAX); + AssertLogRelRCReturn(rc, rc); + + /* + * Compute buffer size for the VBE BIOS Extra Data. + */ + cb = sizeof(mode_info_list) + sizeof(ModeInfoListItem); + + rc = pHlp->pfnCFGMQueryU32(pCfg, "HeightReduction", &cyReduction); + if (RT_SUCCESS(rc) && cyReduction) + cb *= 2; /* Default mode list will be twice long */ + else + cyReduction = 0; + + rc = pHlp->pfnCFGMQueryU32(pCfg, "CustomVideoModes", &cCustomModes); + if (RT_SUCCESS(rc) && cCustomModes) + cb += sizeof(ModeInfoListItem) * cCustomModes; + else + cCustomModes = 0; + + /* + * Allocate and initialize buffer for the VBE BIOS Extra Data. + */ + AssertRelease(sizeof(VBEHEADER) + cb < 65536); + pThisCC->cbVBEExtraData = (uint16_t)(sizeof(VBEHEADER) + cb); + pThisCC->pbVBEExtraData = (uint8_t *)PDMDevHlpMMHeapAllocZ(pDevIns, pThisCC->cbVBEExtraData); + if (!pThisCC->pbVBEExtraData) + return VERR_NO_MEMORY; + + pVBEDataHdr = (PVBEHEADER)pThisCC->pbVBEExtraData; + pVBEDataHdr->u16Signature = VBEHEADER_MAGIC; + pVBEDataHdr->cbData = cb; + + pCurMode = (ModeInfoListItem *)(pVBEDataHdr + 1); + for (i = 0; i < MODE_INFO_SIZE; i++) + { + uint32_t pixelWidth, reqSize; + if (mode_info_list[i].info.MemoryModel == VBE_MEMORYMODEL_TEXT_MODE) + pixelWidth = 2; + else + pixelWidth = (mode_info_list[i].info.BitsPerPixel +7) / 8; + reqSize = mode_info_list[i].info.XResolution + * mode_info_list[i].info.YResolution + * pixelWidth; + if (reqSize >= pThis->vram_size) + continue; + if (!reqSize) + continue; + if ( mode_info_list[i].info.XResolution > maxBiosXRes + || mode_info_list[i].info.YResolution > maxBiosYRes) + continue; + *pCurMode = mode_info_list[i]; + vgaR3AdjustModeInfo(pThis, pCurMode); + pCurMode++; + } + + /* + * Copy default modes with subtracted YResolution. + */ + if (cyReduction) + { + ModeInfoListItem *pDefMode = mode_info_list; + Log(("vgaR3Construct: cyReduction=%u\n", cyReduction)); + for (i = 0; i < MODE_INFO_SIZE; i++, pDefMode++) + { + uint32_t pixelWidth, reqSize; + if (pDefMode->info.MemoryModel == VBE_MEMORYMODEL_TEXT_MODE) + pixelWidth = 2; + else + pixelWidth = (pDefMode->info.BitsPerPixel + 7) / 8; + reqSize = pDefMode->info.XResolution * pDefMode->info.YResolution * pixelWidth; + if (reqSize >= pThis->vram_size) + continue; + if ( pDefMode->info.XResolution > maxBiosXRes + || pDefMode->info.YResolution - cyReduction > maxBiosYRes) + continue; + *pCurMode = *pDefMode; + pCurMode->mode += 0x30; + pCurMode->info.YResolution -= cyReduction; + pCurMode++; + } + } + + + /* + * Add custom modes. + */ + if (cCustomModes) + { + uint16_t u16CurMode = VBE_VBOX_MODE_CUSTOM1; + for (i = 1; i <= cCustomModes; i++) + { + char szExtraDataKey[sizeof("CustomVideoModeXX")]; + char *pszExtraData = NULL; + + /* query and decode the custom mode string. */ + RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%d", i); + rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, szExtraDataKey, &pszExtraData); + if (RT_SUCCESS(rc)) + { + ModeInfoListItem *pDefMode = mode_info_list; + unsigned int cx, cy, cBits, cParams, j; + uint16_t u16DefMode; + + cParams = sscanf(pszExtraData, "%ux%ux%u", &cx, &cy, &cBits); + if ( cParams != 3 + || (cBits != 8 && cBits != 16 && cBits != 24 && cBits != 32)) + { + AssertMsgFailed(("Configuration error: Invalid mode data '%s' for '%s'! cBits=%d\n", pszExtraData, szExtraDataKey, cBits)); + return VERR_VGA_INVALID_CUSTOM_MODE; + } + if (!cx || !cy) + { + AssertMsgFailed(("Configuration error: Invalid mode data '%s' for '%s'! cx=%u, cy=%u\n", pszExtraData, szExtraDataKey, cx, cy)); + return VERR_VGA_INVALID_CUSTOM_MODE; + } + cbPitch = calc_line_pitch(cBits, cx); + if (cy * cbPitch >= pThis->vram_size) + { + AssertMsgFailed(("Configuration error: custom video mode %dx%dx%dbits is too large for the virtual video memory of %dMb. Please increase the video memory size.\n", + cx, cy, cBits, pThis->vram_size / _1M)); + return VERR_VGA_INVALID_CUSTOM_MODE; + } + PDMDevHlpMMHeapFree(pDevIns, pszExtraData); + + /* Use defaults from max@bpp mode. */ + switch (cBits) + { + case 8: + u16DefMode = VBE_VESA_MODE_1024X768X8; + break; + + case 16: + u16DefMode = VBE_VESA_MODE_1024X768X565; + break; + + case 24: + u16DefMode = VBE_VESA_MODE_1024X768X888; + break; + + case 32: + u16DefMode = VBE_OWN_MODE_1024X768X8888; + break; + + default: /* gcc, shut up! */ + AssertMsgFailed(("gone postal!\n")); + continue; + } + + /* mode_info_list is not terminated */ + for (j = 0; j < MODE_INFO_SIZE && pDefMode->mode != u16DefMode; j++) + pDefMode++; + Assert(j < MODE_INFO_SIZE); + + *pCurMode = *pDefMode; + pCurMode->mode = u16CurMode++; + + /* adjust defaults */ + pCurMode->info.XResolution = cx; + pCurMode->info.YResolution = cy; + pCurMode->info.BytesPerScanLine = cbPitch; + pCurMode->info.LinBytesPerScanLine = cbPitch; + vgaR3AdjustModeInfo(pThis, pCurMode); + + /* commit it */ + pCurMode++; + } + else if (rc != VERR_CFGM_VALUE_NOT_FOUND) + { + AssertMsgFailed(("pHlp->pfnCFGMQueryStringAlloc(,'%s',) -> %Rrc\n", szExtraDataKey, rc)); + return rc; + } + } /* foreach custom mode key */ + } + + /* + * Add the "End of list" mode. + */ + memset(pCurMode, 0, sizeof(*pCurMode)); + pCurMode->mode = VBE_VESA_MODE_END_OF_LIST; + + /* + * Register I/O Port for the VBE BIOS Extra Data. + */ + rc = PDMDevHlpIoPortCreateAndMap(pDevIns, VBE_EXTRA_PORT, 1 /*cPorts*/, vbeR3IOPortWriteVbeExtra, vbeR3IoPortReadVbeExtra, + "VBE BIOS Extra Data", NULL /*paExtDesc*/, &pThis->hIoPortVbeExtra); + AssertRCReturn(rc, rc); + + /* + * Register I/O Port for the BIOS Logo. + */ + rc = PDMDevHlpIoPortCreateAndMap(pDevIns, LOGO_IO_PORT, 1 /*cPorts*/, vbeR3IoPortWriteCmdLogo, vbeR3IoPortReadCmdLogo, + "BIOS Logo", NULL /*paExtDesc*/, &pThis->hIoPortCmdLogo); + AssertRCReturn(rc, rc); + + /* + * Register debugger info callbacks. + */ + PDMDevHlpDBGFInfoRegister(pDevIns, "vga", "Display basic VGA state.", vgaR3InfoState); + PDMDevHlpDBGFInfoRegister(pDevIns, "vgatext", "Display VGA memory formatted as text.", vgaR3InfoText); + PDMDevHlpDBGFInfoRegister(pDevIns, "vgacr", "Dump VGA CRTC registers.", vgaR3InfoCR); + PDMDevHlpDBGFInfoRegister(pDevIns, "vgagr", "Dump VGA Graphics Controller registers.", vgaR3InfoGR); + PDMDevHlpDBGFInfoRegister(pDevIns, "vgasr", "Dump VGA Sequencer registers.", vgaR3InfoSR); + PDMDevHlpDBGFInfoRegister(pDevIns, "vgaar", "Dump VGA Attribute Controller registers.", vgaR3InfoAR); + PDMDevHlpDBGFInfoRegister(pDevIns, "vgapl", "Dump planar graphics state.", vgaR3InfoPlanar); + PDMDevHlpDBGFInfoRegister(pDevIns, "vgadac", "Dump VGA DAC registers.", vgaR3InfoDAC); + PDMDevHlpDBGFInfoRegister(pDevIns, "vbe", "Dump VGA VBE registers.", vgaR3InfoVBE); + + /* + * Construct the logo header. + */ + LOGOHDR LogoHdr = { LOGO_HDR_MAGIC, 0, 0, 0, 0, 0, 0 }; + + rc = pHlp->pfnCFGMQueryU8(pCfg, "FadeIn", &LogoHdr.fu8FadeIn); + if (rc == VERR_CFGM_VALUE_NOT_FOUND) + LogoHdr.fu8FadeIn = 1; + else if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Querying \"FadeIn\" as integer failed")); + + rc = pHlp->pfnCFGMQueryU8(pCfg, "FadeOut", &LogoHdr.fu8FadeOut); + if (rc == VERR_CFGM_VALUE_NOT_FOUND) + LogoHdr.fu8FadeOut = 1; + else if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Querying \"FadeOut\" as integer failed")); + + rc = pHlp->pfnCFGMQueryU16(pCfg, "LogoTime", &LogoHdr.u16LogoMillies); + if (rc == VERR_CFGM_VALUE_NOT_FOUND) + LogoHdr.u16LogoMillies = 0; + else if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Querying \"LogoTime\" as integer failed")); + + rc = pHlp->pfnCFGMQueryU8(pCfg, "ShowBootMenu", &LogoHdr.fu8ShowBootMenu); + if (rc == VERR_CFGM_VALUE_NOT_FOUND) + LogoHdr.fu8ShowBootMenu = 0; + else if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Querying \"ShowBootMenu\" as integer failed")); + +# if defined(DEBUG) && !defined(DEBUG_sunlover) && !defined(DEBUG_michael) + /* Disable the logo abd menu if all default settings. */ + if ( LogoHdr.fu8FadeIn + && LogoHdr.fu8FadeOut + && LogoHdr.u16LogoMillies == 0 + && LogoHdr.fu8ShowBootMenu == 2) + { + LogoHdr.fu8FadeIn = LogoHdr.fu8FadeOut = 0; + LogoHdr.u16LogoMillies = 500; + } +# endif + + /* Delay the logo a little bit */ + if (LogoHdr.fu8FadeIn && LogoHdr.fu8FadeOut && !LogoHdr.u16LogoMillies) + LogoHdr.u16LogoMillies = RT_MAX(LogoHdr.u16LogoMillies, LOGO_DELAY_TIME); + + /* + * Get the Logo file name. + */ + rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "LogoFile", &pThisCC->pszLogoFile); + if (rc == VERR_CFGM_VALUE_NOT_FOUND) + pThisCC->pszLogoFile = NULL; + else if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Configuration error: Querying \"LogoFile\" as a string failed")); + else if (!*pThisCC->pszLogoFile) + { + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pszLogoFile); + pThisCC->pszLogoFile = NULL; + } + + /* + * Determine the logo size, open any specified logo file in the process. + */ + LogoHdr.cbLogo = g_cbVgaDefBiosLogo; + RTFILE FileLogo = NIL_RTFILE; + if (pThisCC->pszLogoFile) + { + rc = RTFileOpen(&FileLogo, pThisCC->pszLogoFile, + RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_SUCCESS(rc)) + { + uint64_t cbFile; + rc = RTFileQuerySize(FileLogo, &cbFile); + if (RT_SUCCESS(rc)) + { + if (cbFile > 0 && cbFile < 32*_1M) + LogoHdr.cbLogo = (uint32_t)cbFile; + else + rc = VERR_TOO_MUCH_DATA; + } + } + if (RT_FAILURE(rc)) + { + /* + * Ignore failure and fall back to the default logo. + */ + LogRel(("vgaR3Construct: Failed to open logo file '%s', rc=%Rrc!\n", pThisCC->pszLogoFile, rc)); + if (FileLogo != NIL_RTFILE) + RTFileClose(FileLogo); + FileLogo = NIL_RTFILE; + PDMDevHlpMMHeapFree(pDevIns, pThisCC->pszLogoFile); + pThisCC->pszLogoFile = NULL; + } + } + + /* + * Disable graphic splash screen if it doesn't fit into VRAM. + */ + if (pThis->vram_size < LOGO_MAX_SIZE) + LogoHdr.fu8FadeIn = LogoHdr.fu8FadeOut = LogoHdr.u16LogoMillies = 0; + + /* + * Allocate buffer for the logo data. + * Let us fall back to default logo on read failure. + */ + pThisCC->cbLogo = LogoHdr.cbLogo; + if (g_cbVgaDefBiosLogo) + pThisCC->cbLogo = RT_MAX(pThisCC->cbLogo, g_cbVgaDefBiosLogo); +# ifndef VBOX_OSE + if (g_cbVgaDefBiosLogoNY) + pThisCC->cbLogo = RT_MAX(pThisCC->cbLogo, g_cbVgaDefBiosLogoNY); +# endif + pThisCC->cbLogo += sizeof(LogoHdr); + + pThisCC->pbLogo = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThisCC->cbLogo); + if (pThisCC->pbLogo) + { + /* + * Write the logo header. + */ + PLOGOHDR pLogoHdr = (PLOGOHDR)pThisCC->pbLogo; + *pLogoHdr = LogoHdr; + + /* + * Write the logo bitmap. + */ + if (pThisCC->pszLogoFile) + { + rc = RTFileRead(FileLogo, pLogoHdr + 1, LogoHdr.cbLogo, NULL); + if (RT_SUCCESS(rc)) + rc = vbeR3ParseBitmap(pThisCC); + if (RT_FAILURE(rc)) + { + LogRel(("Error %Rrc reading logo file '%s', using internal logo\n", + rc, pThisCC->pszLogoFile)); + pLogoHdr->cbLogo = LogoHdr.cbLogo = g_cbVgaDefBiosLogo; + } + } + if ( !pThisCC->pszLogoFile + || RT_FAILURE(rc)) + { +# ifndef VBOX_OSE + RTTIMESPEC Now; + RTTimeLocalNow(&Now); + RTTIME T; + RTTimeLocalExplode(&T, &Now); + bool fSuppressNewYearSplash = false; + rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "SuppressNewYearSplash", &fSuppressNewYearSplash, true); + if ( !fSuppressNewYearSplash + && (T.u16YearDay > 353 || T.u16YearDay < 10)) + { + pLogoHdr->cbLogo = LogoHdr.cbLogo = g_cbVgaDefBiosLogoNY; + memcpy(pLogoHdr + 1, g_abVgaDefBiosLogoNY, LogoHdr.cbLogo); + pThisCC->fBootMenuInverse = true; + } + else +# endif + memcpy(pLogoHdr + 1, g_abVgaDefBiosLogo, LogoHdr.cbLogo); + rc = vbeR3ParseBitmap(pThisCC); + AssertLogRelMsgReturn(RT_SUCCESS(rc), ("Parsing of internal bitmap failed! vbeR3ParseBitmap() -> %Rrc\n", rc), rc); + } + + rc = VINF_SUCCESS; + } + else + rc = VERR_NO_MEMORY; + + /* + * Cleanup. + */ + if (FileLogo != NIL_RTFILE) + RTFileClose(FileLogo); + +# ifdef VBOX_WITH_HGSMI + VBVAInit(pDevIns, pThis, pThisCC); +# endif + +# ifdef VBOX_WITH_VDMA + if (rc == VINF_SUCCESS) + { + rc = vboxVDMAConstruct(pThis, pThisCC, 1024); + AssertRC(rc); + } +# endif + +# ifdef VBOX_WITH_VMSVGA + if ( rc == VINF_SUCCESS + && pThis->fVMSVGAEnabled) + rc = vmsvgaR3Init(pDevIns); +# endif + + /* + * Statistics. + */ +# ifdef VBOX_WITH_STATISTICS + PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRZMemoryRead, STAMTYPE_PROFILE, "RZ/MMIO-Read", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryRead() body."); + PDMDevHlpSTAMRegister(pDevIns, &pThis->StatR3MemoryRead, STAMTYPE_PROFILE, "R3/MMIO-Read", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryRead() body."); + PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRZMemoryWrite, STAMTYPE_PROFILE, "RZ/MMIO-Write", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryWrite() body."); + PDMDevHlpSTAMRegister(pDevIns, &pThis->StatR3MemoryWrite, STAMTYPE_PROFILE, "R3/MMIO-Write", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryWrite() body."); + PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMapPage, STAMTYPE_COUNTER, "MapPageCalls", STAMUNIT_OCCURENCES, "Calls to IOMMmioMapMmio2Page."); + PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMapReset, STAMTYPE_COUNTER, "MapPageReset", STAMUNIT_OCCURENCES, "Calls to IOMMmioResetRegion."); + PDMDevHlpSTAMRegister(pDevIns, &pThis->StatUpdateDisp, STAMTYPE_COUNTER, "UpdateDisplay", STAMUNIT_OCCURENCES, "Calls to vgaR3PortUpdateDisplay()."); +# endif +# ifdef VBOX_WITH_HGSMI + PDMDevHlpSTAMRegister(pDevIns, &pThis->StatHgsmiMdaCgaAccesses, STAMTYPE_COUNTER, "HgmsiMdaCgaAccesses", STAMUNIT_OCCURENCES, "Number of non-HGMSI accesses for 03b0-3b3 and 03d0-3d3."); +# endif + + /* Init latched access mask. */ + pThis->uMaskLatchAccess = 0x3ff; + + if (RT_SUCCESS(rc)) + { + PPDMIBASE pBase; + /* + * Attach status driver (optional). + */ + rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThisCC->IBase, &pBase, "Status Port"); + if (RT_SUCCESS(rc)) + pThisCC->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS); + else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) + { + Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pReg->szName, pDevIns->iInstance)); + rc = VINF_SUCCESS; + } + else + { + AssertMsgFailed(("Failed to attach to status driver. rc=%Rrc\n", rc)); + rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("VGA cannot attach to status driver")); + } + } + return rc; +} + +#else /* !IN_RING3 */ + +/** + * @callback_method_impl{PDMDEVREGR0,pfnConstruct} + */ +static DECLCALLBACK(int) vgaRZConstruct(PPDMDEVINS pDevIns) +{ + PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + + int rc = PDMDevHlpSetDeviceCritSect(pDevIns, &pThis->CritSect); + AssertRCReturn(rc, rc); + + /* + * Set I/O port callbacks for this context. + * We just copy the ring-3 registration bits and remove the '&' before the handle. + */ +# define REG_PORT(a_uPort, a_cPorts, a_pfnWrite, a_pfnRead, a_szDesc, a_hIoPort) do { \ + rc = PDMDevHlpIoPortSetUpContext(pDevIns, a_hIoPort, a_pfnWrite, a_pfnRead, NULL /*pvUser*/); \ + AssertRCReturn(rc, rc); \ + } while (0) + + REG_PORT(0x3c0, 2, vgaIoPortArWrite, vgaIoPortArRead, "Attribute Controller", pThis->hIoPortAr); + REG_PORT(0x3c2, 1, vgaIoPortMsrWrite, vgaIoPortSt00Read, "MSR / ST00", pThis->hIoPortMsrSt00); + REG_PORT(0x3c3, 1, vgaIoPortUnusedWrite, vgaIoPortUnusedRead, "0x3c3", pThis->hIoPort3c3); + REG_PORT(0x3c4, 2, vgaIoPortSrWrite, vgaIoPortSrRead, "Sequencer", pThis->hIoPortSr); + REG_PORT(0x3c6, 4, vgaIoPortDacWrite, vgaIoPortDacRead, "DAC", pThis->hIoPortDac); + REG_PORT(0x3ca, 4, vgaIoPortPosWrite, vgaIoPortPosRead, "Graphics Position", /*?*/ pThis->hIoPortPos); + REG_PORT(0x3ce, 2, vgaIoPortGrWrite, vgaIoPortGrRead, "Graphics Controller", pThis->hIoPortGr); + + REG_PORT(0x3b4, 2, vgaIoPortMdaCrtWrite, vgaIoPortMdaCrtRead, "MDA CRT control", pThis->hIoPortMdaCrt); + REG_PORT(0x3ba, 1, vgaIoPortMdaFcrWrite, vgaIoPortMdaStRead, "MDA feature/status", pThis->hIoPortMdaFcrSt); + REG_PORT(0x3d4, 2, vgaIoPortCgaCrtWrite, vgaIoPortCgaCrtRead, "CGA CRT control", pThis->hIoPortCgaCrt); + REG_PORT(0x3da, 1, vgaIoPortCgaFcrWrite, vgaIoPortCgaStRead, "CGA Feature / status", pThis->hIoPortCgaFcrSt); + +# ifdef CONFIG_BOCHS_VBE + REG_PORT(0x1ce, 1, vgaIoPortWriteVbeIndex, vgaIoPortReadVbeIndex, "VBE Index", pThis->hIoPortVbeIndex); + REG_PORT(0x1cf, 1, vgaIoPortWriteVbeData, vgaIoPortReadVbeData, "VBE Data", pThis->hIoPortVbeData); +# endif /* CONFIG_BOCHS_VBE */ + +# undef REG_PORT + + /* BIOS port: */ + rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPortBios, vgaIoPortWriteBios, vgaIoPortReadBios, NULL /*pvUser*/); + AssertRCReturn(rc, rc); + +# ifdef VBOX_WITH_VMSVGA + if (pThis->hIoPortVmSvga != NIL_IOMIOPORTHANDLE) + { + AssertReturn(pThis->fVMSVGAEnabled, VERR_INVALID_STATE); + rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPortVmSvga, vmsvgaIOWrite, vmsvgaIORead, NULL /*pvUser*/); + AssertRCReturn(rc, rc); + } + else + AssertReturn(!pThis->fVMSVGAEnabled, VERR_INVALID_STATE); +# endif + + /* + * MMIO. + */ + rc = PDMDevHlpMmioSetUpContextEx(pDevIns, pThis->hMmioLegacy, vgaMmioWrite, vgaMmioRead, vgaMmioFill, NULL /*pvUser*/); + AssertRCReturn(rc, rc); + + /* + * Map the start of the VRAM into this context. + */ +# if defined(VBOX_WITH_2X_4GB_ADDR_SPACE) || (defined(IN_RING0) && defined(VGA_WITH_PARTIAL_RING0_MAPPING)) + rc = PDMDevHlpMmio2SetUpContext(pDevIns, pThis->hMmio2VRam, 0 /* off */, VGA_MAPPING_SIZE, (void **)&pThisCC->pbVRam); + AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMmio2SetUpContext(,VRAM,0,%#x,) -> %Rrc\n", VGA_MAPPING_SIZE, rc), rc); +# endif + + /* + * Map the first page of the VMSVGA FIFO into this context (not raw-mode). + * We currently only access SVGA_FIFO_MIN, SVGA_FIFO_PITCHLOCK, and SVGA_FIFO_BUSY. + */ +# if defined(VBOX_WITH_VMSVGA) && !defined(IN_RC) + AssertCompile((RT_MAX(SVGA_FIFO_MIN, RT_MAX(SVGA_FIFO_PITCHLOCK, SVGA_FIFO_BUSY)) + 1) * sizeof(uint32_t) < GUEST_PAGE_SIZE); + if (pThis->fVMSVGAEnabled) + { + rc = PDMDevHlpMmio2SetUpContext(pDevIns, pThis->hMmio2VmSvgaFifo, 0 /* off */, GUEST_PAGE_SIZE, + (void **)&pThisCC->svga.pau32FIFO); + AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMapMMIO2IntoR0(%#x,) -> %Rrc\n", pThis->svga.cbFIFO, rc), rc); + } + else + AssertReturn(pThis->hMmio2VmSvgaFifo == NIL_PGMMMIO2HANDLE, VERR_INVALID_STATE); +# endif + + return VINF_SUCCESS; +} + +#endif /* !IN_RING3 */ + +/** + * The device registration structure. + */ +const PDMDEVREG g_DeviceVga = +{ + /* .u32Version = */ PDM_DEVREG_VERSION, + /* .uReserved0 = */ 0, + /* .szName = */ "vga", + /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE, + /* .fClass = */ PDM_DEVREG_CLASS_GRAPHICS, + /* .cMaxInstances = */ 1, + /* .uSharedVersion = */ 42, + /* .cbInstanceShared = */ sizeof(VGASTATE), + /* .cbInstanceCC = */ sizeof(VGASTATECC), + /* .cbInstanceRC = */ sizeof(VGASTATERC), + /* .cMaxPciDevices = */ 1, + /* .cMaxMsixVectors = */ 0, + /* .pszDescription = */ "VGA Adaptor with VESA extensions.", +#if defined(IN_RING3) + /* .pszRCMod = */ "VBoxDDRC.rc", + /* .pszR0Mod = */ "VBoxDDR0.r0", + /* .pfnConstruct = */ vgaR3Construct, + /* .pfnDestruct = */ vgaR3Destruct, + /* .pfnRelocate = */ vgaR3Relocate, + /* .pfnMemSetup = */ NULL, + /* .pfnPowerOn = */ vgaR3PowerOn, + /* .pfnReset = */ vgaR3Reset, + /* .pfnSuspend = */ NULL, + /* .pfnResume = */ vgaR3Resume, + /* .pfnAttach = */ vgaAttach, + /* .pfnDetach = */ vgaDetach, + /* .pfnQueryInterface = */ NULL, + /* .pfnInitComplete = */ NULL, + /* .pfnPowerOff = */ vgaR3PowerOff, + /* .pfnSoftReset = */ NULL, + /* .pfnReserved0 = */ NULL, + /* .pfnReserved1 = */ NULL, + /* .pfnReserved2 = */ NULL, + /* .pfnReserved3 = */ NULL, + /* .pfnReserved4 = */ NULL, + /* .pfnReserved5 = */ NULL, + /* .pfnReserved6 = */ NULL, + /* .pfnReserved7 = */ NULL, +#elif defined(IN_RING0) + /* .pfnEarlyConstruct = */ NULL, + /* .pfnConstruct = */ vgaRZConstruct, + /* .pfnDestruct = */ NULL, + /* .pfnFinalDestruct = */ NULL, + /* .pfnRequest = */ NULL, + /* .pfnReserved0 = */ NULL, + /* .pfnReserved1 = */ NULL, + /* .pfnReserved2 = */ NULL, + /* .pfnReserved3 = */ NULL, + /* .pfnReserved4 = */ NULL, + /* .pfnReserved5 = */ NULL, + /* .pfnReserved6 = */ NULL, + /* .pfnReserved7 = */ NULL, +#elif defined(IN_RC) + /* .pfnConstruct = */ vgaRZConstruct, + /* .pfnReserved0 = */ NULL, + /* .pfnReserved1 = */ NULL, + /* .pfnReserved2 = */ NULL, + /* .pfnReserved3 = */ NULL, + /* .pfnReserved4 = */ NULL, + /* .pfnReserved5 = */ NULL, + /* .pfnReserved6 = */ NULL, + /* .pfnReserved7 = */ NULL, +#else +# error "Not in IN_RING3, IN_RING0 or IN_RC!" +#endif + /* .u32VersionEnd = */ PDM_DEVREG_VERSION +}; + +#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */ + +/* + * Local Variables: + * nuke-trailing-whitespace-p:nil + * End: + */ diff --git a/src/VBox/Devices/Graphics/DevVGA.h b/src/VBox/Devices/Graphics/DevVGA.h new file mode 100644 index 00000000..444b5ddf --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA.h @@ -0,0 +1,796 @@ +/* $Id: DevVGA.h $ */ +/** @file + * DevVGA - VBox VGA/VESA device, internal header. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + * -------------------------------------------------------------------- + * + * This code is based on: + * + * QEMU internal VGA defines. + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGA_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include +#include + +#ifdef VBOX_WITH_HGSMI +# include "HGSMI/HGSMIHost.h" +#endif /* VBOX_WITH_HGSMI */ +#include "DevVGASavedState.h" + +#ifdef VBOX_WITH_VMSVGA +# include "DevVGA-SVGA.h" +#endif + +#include + + +/** Use VBE bytewise I/O. Only needed for Windows Longhorn/Vista betas and backwards compatibility. */ +#define VBE_BYTEWISE_IO + +#ifdef VBOX +/** The default amount of VRAM. */ +# define VGA_VRAM_DEFAULT (_4M) +/** The maximum amount of VRAM. Limited by VBOX_MAX_ALLOC_PAGE_COUNT. */ +# define VGA_VRAM_MAX (256 * _1M) +/** The minimum amount of VRAM. */ +# define VGA_VRAM_MIN (_1M) +#endif + + +/** @name Macros dealing with partial ring-0/raw-mode VRAM mappings. + * @{ */ +/** The size of the VGA ring-0 and raw-mode mapping. + * + * This is supposed to be all the VGA memory accessible to the guest. + * The initial value was 256KB but NTAllInOne.iso appears to access more + * thus the limit was upped to 512KB. + * + * @todo Someone with some VGA knowhow should make a better guess at this value. + */ +#define VGA_MAPPING_SIZE _512K +/** Enables partially mapping the VRAM into ring-0 rather than using the ring-3. + * The VGA_MAPPING_SIZE define sets the number of bytes that will be mapped. */ +#define VGA_WITH_PARTIAL_RING0_MAPPING + +/** + * Check buffer if an VRAM offset is within the right range or not. + */ +#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) || (defined(IN_RING0) && defined(VGA_WITH_PARTIAL_RING0_MAPPING)) +# define VERIFY_VRAM_WRITE_OFF_RETURN(pThis, off) \ + do { \ + if ((off) < VGA_MAPPING_SIZE) \ + RT_UNTRUSTED_VALIDATED_FENCE(); \ + else \ + { \ + AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), VINF_SUCCESS); \ + Log2(("%Rfn[%d]: %RX32 -> R3\n", __PRETTY_FUNCTION__, __LINE__, (off))); \ + return VINF_IOM_R3_MMIO_WRITE; \ + } \ + } while (0) +#else +# define VERIFY_VRAM_WRITE_OFF_RETURN(pThis, off) \ + do { \ + AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), VINF_SUCCESS); \ + RT_UNTRUSTED_VALIDATED_FENCE(); \ + } while (0) +#endif + +/** + * Check buffer if an VRAM offset is within the right range or not. + */ +#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) || (defined(IN_RING0) && defined(VGA_WITH_PARTIAL_RING0_MAPPING)) +# define VERIFY_VRAM_READ_OFF_RETURN(pThis, off, rcVar) \ + do { \ + if ((off) < VGA_MAPPING_SIZE) \ + RT_UNTRUSTED_VALIDATED_FENCE(); \ + else \ + { \ + AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), 0xff); \ + Log2(("%Rfn[%d]: %RX32 -> R3\n", __PRETTY_FUNCTION__, __LINE__, (off))); \ + (rcVar) = VINF_IOM_R3_MMIO_READ; \ + return 0; \ + } \ + } while (0) +#else +# define VERIFY_VRAM_READ_OFF_RETURN(pThis, off, rcVar) \ + do { \ + AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), 0xff); \ + RT_UNTRUSTED_VALIDATED_FENCE(); \ + NOREF(rcVar); \ + } while (0) +#endif +/** @} */ + + +#define MSR_COLOR_EMULATION 0x01 +#define MSR_PAGE_SELECT 0x20 + +#define ST01_V_RETRACE 0x08 +#define ST01_DISP_ENABLE 0x01 + +/* bochs VBE support */ +#define CONFIG_BOCHS_VBE + +#ifdef CONFIG_BOCHS_VBE + +/* Cross reference with */ +#define VBE_DISPI_INDEX_NB_SAVED 0xb /* Old number of saved registers (vbe_regs array, see vga_load) */ +#define VBE_DISPI_INDEX_NB 0xd /* Total number of VBE registers */ + +#define VGA_STATE_COMMON_BOCHS_VBE \ + uint16_t vbe_index; \ + uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; \ + uint16_t alignment[2]; /* pad to 64 bits */ \ + uint32_t vbe_start_addr; \ + uint32_t vbe_line_offset; \ + uint32_t vbe_bank_max; + +#else + +#define VGA_STATE_COMMON_BOCHS_VBE + +#endif /* !CONFIG_BOCHS_VBE */ + +#define CH_ATTR_SIZE (160 * 100) +#define VGA_MAX_HEIGHT VBE_DISPI_MAX_YRES + +typedef struct vga_retrace_s { + unsigned frame_cclks; /* Character clocks per frame. */ + unsigned frame_ns; /* Frame duration in ns. */ + unsigned cclk_ns; /* Character clock duration in ns. */ + unsigned vb_start; /* Vertical blanking start (scanline). */ + unsigned vb_end; /* Vertical blanking end (scanline). */ + unsigned vb_end_ns; /* Vertical blanking end time (length) in ns. */ + unsigned vs_start; /* Vertical sync start (scanline). */ + unsigned vs_end; /* Vertical sync end (scanline). */ + unsigned vs_start_ns; /* Vertical sync start time in ns. */ + unsigned vs_end_ns; /* Vertical sync end time in ns. */ + unsigned h_total; /* Horizontal total (cclks per scanline). */ + unsigned h_total_ns; /* Scanline duration in ns. */ + unsigned hb_start; /* Horizontal blanking start (cclk). */ + unsigned hb_end; /* Horizontal blanking end (cclk). */ + unsigned hb_end_ns; /* Horizontal blanking end time (length) in ns. */ + unsigned v_freq_hz; /* Vertical refresh rate to emulate. */ +} vga_retrace_s; + +#ifndef VBOX +#define VGA_STATE_COMMON \ + unsigned long vram_offset; \ + unsigned int vram_size; \ + uint32_t latch; \ + uint8_t sr_index; \ + uint8_t sr[256]; \ + uint8_t gr_index; \ + uint8_t gr[256]; \ + uint8_t ar_index; \ + uint8_t ar[21]; \ + int ar_flip_flop; \ + uint8_t cr_index; \ + uint8_t cr[256]; /* CRT registers */ \ + uint8_t msr; /* Misc Output Register */ \ + uint8_t fcr; /* Feature Control Register */ \ + uint8_t st00; /* status 0 */ \ + uint8_t st01; /* status 1 */ \ + uint8_t dac_state; \ + uint8_t dac_sub_index; \ + uint8_t dac_read_index; \ + uint8_t dac_write_index; \ + uint8_t dac_cache[3]; /* used when writing */ \ + uint8_t palette[768]; \ + int32_t bank_offset; \ + int (*get_bpp)(struct VGAState *s); \ + void (*get_offsets)(struct VGAState *s, \ + uint32_t *pline_offset, \ + uint32_t *pstart_addr, \ + uint32_t *pline_compare); \ + void (*get_resolution)(struct VGAState *s, \ + int *pwidth, \ + int *pheight); \ + VGA_STATE_COMMON_BOCHS_VBE \ + /* display refresh support */ \ + DisplayState *ds; \ + uint32_t font_offsets[2]; \ + int graphic_mode; \ + uint8_t shift_control; \ + uint8_t double_scan; \ + uint32_t line_offset; \ + uint32_t line_compare; \ + uint32_t start_addr; \ + uint32_t plane_updated; \ + uint8_t last_cw, last_ch; \ + uint32_t last_width, last_height; /* in chars or pixels */ \ + uint32_t last_scr_width, last_scr_height; /* in pixels */ \ + uint8_t cursor_start, cursor_end; \ + uint32_t cursor_offset; \ + unsigned int (*rgb_to_pixel)(unsigned int r, \ + unsigned int g, unsigned b); \ + /* hardware mouse cursor support */ \ + uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \ + void (*cursor_invalidate)(struct VGAState *s); \ + void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \ + /* tell for each page if it has been updated since the last time */ \ + uint32_t last_palette[256]; \ + uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ + +#else /* VBOX */ + +/* bird: Since we've changed types, reordered members, done alignment + paddings and more, VGA_STATE_COMMON was added directly to the + struct to make it more readable and easier to handle. */ + +struct VGAState; +typedef int FNGETBPP(struct VGAState *s); +typedef void FNGETOFFSETS(struct VGAState *s, uint32_t *pline_offset, uint32_t *pstart_addr, uint32_t *pline_compare); +typedef void FNGETRESOLUTION(struct VGAState *s, int *pwidth, int *pheight); +typedef unsigned int FNRGBTOPIXEL(unsigned int r, unsigned int g, unsigned b); +typedef void FNCURSORINVALIDATE(struct VGAState *s); +typedef void FNCURSORDRAWLINE(struct VGAState *s, uint8_t *d, int y); + +#endif /* VBOX */ + +#ifdef VBOX_WITH_VDMA +typedef struct VBOXVDMAHOST *PVBOXVDMAHOST; +#endif + +#ifdef VBOX_WITH_VIDEOHWACCEL +#define VBOX_VHWA_MAX_PENDING_COMMANDS 1000 + +typedef struct _VBOX_VHWA_PENDINGCMD +{ + RTLISTNODE Node; + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand; +} VBOX_VHWA_PENDINGCMD; +#endif + + +/** + * The shared VGA state data. + */ +typedef struct VGAState +{ + uint32_t vram_size; + uint32_t latch; + uint8_t sr_index; + uint8_t sr[256]; + uint8_t gr_index; + uint8_t gr[256]; + uint8_t ar_index; + uint8_t ar[21]; + int32_t ar_flip_flop; + uint8_t cr_index; + uint8_t cr[256]; /* CRT registers */ + uint8_t msr; /* Misc Output Register */ + uint8_t fcr; /* Feature Control Register */ + uint8_t st00; /* status 0 */ + uint8_t st01; /* status 1 */ + uint8_t dac_state; + uint8_t dac_sub_index; + uint8_t dac_read_index; + uint8_t dac_write_index; + uint8_t dac_cache[3]; /* used when writing */ + uint8_t palette[768]; + int32_t bank_offset; + VGA_STATE_COMMON_BOCHS_VBE + /* display refresh support */ + uint32_t font_offsets[2]; + int32_t graphic_mode; + uint8_t shift_control; + uint8_t double_scan; + uint8_t padding1[2]; + uint32_t line_offset; + uint32_t vga_addr_mask; + uint32_t padding1a; + uint32_t line_compare; + uint32_t start_addr; + uint32_t plane_updated; + uint8_t last_cw, last_ch; + uint8_t last_uline; \ + bool last_blink; \ + uint32_t last_width, last_height; /* in chars or pixels */ + uint32_t last_scr_width, last_scr_height; /* in pixels */ + uint32_t last_bpp; + uint8_t cursor_start, cursor_end; + bool last_cur_blink, last_chr_blink; + uint32_t cursor_offset; + /** hardware mouse cursor support */ + uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; + /** tell for each page if it has been updated since the last time */ + uint32_t last_palette[256]; + uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ + + /** end-of-common-state-marker */ + uint32_t u32Marker; + + /** Refresh timer handle - HC. */ + TMTIMERHANDLE hRefreshTimer; + +#ifdef VBOX_WITH_VMSVGA + VMSVGASTATE svga; +#endif + + /** The number of monitors. */ + uint32_t cMonitors; + /** Current refresh timer interval. */ + uint32_t cMilliesRefreshInterval; + /** Bitmap tracking dirty pages. */ + uint64_t bmDirtyBitmap[VGA_VRAM_MAX / GUEST_PAGE_SIZE / 64]; + /** Bitmap tracking which VGA memory pages in the 0xa0000-0xbffff region has + * been remapped to allow direct access. + * @note It's quite possible that mapping in the 0xb0000-0xbffff isn't possible, + * but we're playing safe and cover the whole VGA MMIO region here. */ + uint32_t bmPageRemappedVGA; + + /** Flag indicating that there are dirty bits. This is used to optimize the handler resetting. */ + bool fHasDirtyBits; + /** Flag indicating that the VGA memory in the 0xa0000-0xbffff region has been remapped to allow direct access. + * @todo This is just an unnecessary summmary of bmPageMapBitmap. */ + bool fRemappedVGA; + /** Whether to render the guest VRAM to the framebuffer memory. False only for some LFB modes. */ + bool fRenderVRAM; + /** Whether 3D is enabled for the VM. */ + bool f3DEnabled; + /** Set if state has been restored. */ + bool fStateLoaded; +#ifdef VBOX_WITH_VMSVGA + /* Whether the SVGA emulation is enabled or not. */ + bool fVMSVGAEnabled; + bool fVMSVGA10; + bool fVMSVGAPciId; + bool fVMSVGAPciBarLayout; +#else + bool afPadding4[4]; +#endif + + struct { + uint32_t u32Padding1; + uint32_t iVRAM; +#ifdef VBOX_WITH_VMSVGA + uint32_t iIO; + uint32_t iFIFO; +#endif + } pciRegions; + + /** The physical address the VRAM was assigned. */ + RTGCPHYS GCPhysVRAM; + /** The critical section protect the instance data. */ + PDMCRITSECT CritSect; + + /* Keep track of ring 0 latched accesses to the VGA MMIO memory. */ + uint64_t u64LastLatchedAccess; + uint32_t cLatchAccesses; + uint16_t uMaskLatchAccess; + uint16_t iMask; + +#ifdef VBE_BYTEWISE_IO + /** VBE read/write data/index flags */ + uint8_t fReadVBEData; + uint8_t fWriteVBEData; + uint8_t fReadVBEIndex; + uint8_t fWriteVBEIndex; + /** VBE write data/index one byte buffer */ + uint8_t cbWriteVBEData; + uint8_t cbWriteVBEIndex; + /** VBE Extra Data write address one byte buffer */ + uint8_t cbWriteVBEExtraAddress; + uint8_t Padding5; +#endif + + /** Retrace emulation state */ + bool fRealRetrace; + bool Padding6[HC_ARCH_BITS == 64 ? 7 : 3]; + vga_retrace_s retrace_state; + +#ifdef VBOX_WITH_HGSMI + /** Base port in the assigned PCI I/O space. */ + RTIOPORT IOPortBase; +# ifdef VBOX_WITH_WDDM + uint8_t Padding10[2]; + /** Specifies guest driver caps, i.e. whether it can handle IRQs from the + * adapter, the way it can handle async HGSMI command completion, etc. */ + uint32_t fGuestCaps; + uint32_t fScanLineCfg; + uint32_t Padding11; +# else + uint8_t Padding11[14]; +# endif + + /** The critical section serializes the HGSMI IRQ setting/clearing. */ + PDMCRITSECT CritSectIRQ; + /** VBVARaiseIRQ flags which were set when the guest was still processing previous IRQ. */ + uint32_t fu32PendingGuestFlags; + uint32_t Padding12; +#endif /* VBOX_WITH_HGSMI */ + + PDMLED Led3D; + + struct { + volatile uint32_t cPending; + uint32_t Padding1; + union + { + RTLISTNODE PendingList; + /* make sure the structure sized cross different contexts correctly */ + struct + { + R3PTRTYPE(void *) dummy1; + R3PTRTYPE(void *) dummy2; + } dummy; + }; + } pendingVhwaCommands; + + /** The MMIO handle of the legacy graphics buffer/regs at 0xa0000-0xbffff. */ + PGMMMIO2HANDLE hMmioLegacy; + + /** @name I/O ports for range 0x3c0-3cf. + * @{ */ + IOMIOPORTHANDLE hIoPortAr; + IOMIOPORTHANDLE hIoPortMsrSt00; + IOMIOPORTHANDLE hIoPort3c3; + IOMIOPORTHANDLE hIoPortSr; + IOMIOPORTHANDLE hIoPortDac; + IOMIOPORTHANDLE hIoPortPos; + IOMIOPORTHANDLE hIoPortGr; + /** @} */ + + /** @name I/O ports for MDA 0x3b0-0x3bf (sparse) + * @{ */ + IOMIOPORTHANDLE hIoPortMdaCrt; + IOMIOPORTHANDLE hIoPortMdaFcrSt; + /** @} */ + + /** @name I/O ports for CGA 0x3d0-0x3df (sparse) + * @{ */ + IOMIOPORTHANDLE hIoPortCgaCrt; + IOMIOPORTHANDLE hIoPortCgaFcrSt; + /** @} */ + +#ifdef VBOX_WITH_HGSMI + /** @name I/O ports for HGSMI 0x3b0-03b3 and 0x3d0-03d3 (ring-3 only) + * @{ */ + IOMIOPORTHANDLE hIoPortHgsmiHost; + IOMIOPORTHANDLE hIoPortHgsmiGuest; + /** @} */ +#endif + + /** @name I/O ports for Boch VBE 0x1ce-0x1cf + * @{ */ + IOMIOPORTHANDLE hIoPortVbeIndex; + IOMIOPORTHANDLE hIoPortVbeData; + /** @} */ + + /** The BIOS printf I/O port. */ + IOMIOPORTHANDLE hIoPortBios; + /** The VBE extra data I/O port. */ + IOMIOPORTHANDLE hIoPortVbeExtra; + /** The logo command I/O port. */ + IOMIOPORTHANDLE hIoPortCmdLogo; + +#ifdef VBOX_WITH_VMSVGA + /** VMSVGA: I/O port PCI region. */ + IOMIOPORTHANDLE hIoPortVmSvga; + /** VMSVGA: The MMIO2 handle of the FIFO PCI region. */ + PGMMMIO2HANDLE hMmio2VmSvgaFifo; +#endif + /** The MMIO2 handle of the VRAM. */ + PGMMMIO2HANDLE hMmio2VRam; + + STAMPROFILE StatRZMemoryRead; + STAMPROFILE StatR3MemoryRead; + STAMPROFILE StatRZMemoryWrite; + STAMPROFILE StatR3MemoryWrite; + STAMCOUNTER StatMapPage; /**< Counts IOMMmioMapMmio2Page calls. */ + STAMCOUNTER StatMapReset; /**< Counts IOMMmioResetRegion calls. */ + STAMCOUNTER StatUpdateDisp; /**< Counts vgaPortUpdateDisplay calls. */ +#ifdef VBOX_WITH_HGSMI + STAMCOUNTER StatHgsmiMdaCgaAccesses; +#endif +} VGAState; +#ifdef VBOX +/** VGA state. */ +typedef VGAState VGASTATE; +/** Pointer to the VGA state. */ +typedef VGASTATE *PVGASTATE; +AssertCompileMemberAlignment(VGASTATE, bank_offset, 8); +AssertCompileMemberAlignment(VGASTATE, font_offsets, 8); +AssertCompileMemberAlignment(VGASTATE, last_ch_attr, 8); +AssertCompileMemberAlignment(VGASTATE, u32Marker, 8); +AssertCompile(sizeof(uint64_t)/*bmPageMapBitmap*/ >= (_64K / GUEST_PAGE_SIZE / 8)); +#endif + + +/** + * The VGA state data for ring-3 context. + */ +typedef struct VGASTATER3 +{ + R3PTRTYPE(uint8_t *) pbVRam; + R3PTRTYPE(FNGETBPP *) get_bpp; + R3PTRTYPE(FNGETOFFSETS *) get_offsets; + R3PTRTYPE(FNGETRESOLUTION *) get_resolution; + R3PTRTYPE(FNRGBTOPIXEL *) rgb_to_pixel; + R3PTRTYPE(FNCURSORINVALIDATE *) cursor_invalidate; + R3PTRTYPE(FNCURSORDRAWLINE *) cursor_draw_line; + + /** Pointer to the device instance. + * @note Only for getting our bearings in interface methods. */ + PPDMDEVINSR3 pDevIns; +#ifdef VBOX_WITH_HGSMI + R3PTRTYPE(PHGSMIINSTANCE) pHGSMI; +#endif +#ifdef VBOX_WITH_VDMA + R3PTRTYPE(PVBOXVDMAHOST) pVdma; +#endif + + /** LUN\#0: The display port base interface. */ + PDMIBASE IBase; + /** LUN\#0: The display port interface. */ + PDMIDISPLAYPORT IPort; +#ifdef VBOX_WITH_HGSMI + /** LUN\#0: VBVA callbacks interface */ + PDMIDISPLAYVBVACALLBACKS IVBVACallbacks; +#endif + /** Status LUN: Leds interface. */ + PDMILEDPORTS ILeds; + + /** Pointer to base interface of the driver. */ + R3PTRTYPE(PPDMIBASE) pDrvBase; + /** Pointer to display connector interface of the driver. */ + R3PTRTYPE(PPDMIDISPLAYCONNECTOR) pDrv; + + /** Status LUN: Partner of ILeds. */ + R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector; + +#ifdef VBOX_WITH_VMSVGA + /** The VMSVGA ring-3 state. */ + VMSVGASTATER3 svga; +#endif + + /** The VGA BIOS ROM data. */ + R3PTRTYPE(uint8_t *) pbVgaBios; + /** The size of the VGA BIOS ROM. */ + uint64_t cbVgaBios; + /** The name of the VGA BIOS ROM file. */ + R3PTRTYPE(char *) pszVgaBiosFile; + + /** @name Logo data + * @{ */ + /** Current logo data offset. */ + uint32_t offLogoData; + /** The size of the BIOS logo data. */ + uint32_t cbLogo; + /** Current logo command. */ + uint16_t LogoCommand; + /** Bitmap width. */ + uint16_t cxLogo; + /** Bitmap height. */ + uint16_t cyLogo; + /** Bitmap planes. */ + uint16_t cLogoPlanes; + /** Bitmap depth. */ + uint16_t cLogoBits; + /** Bitmap compression. */ + uint16_t LogoCompression; + /** Bitmap colors used. */ + uint16_t cLogoUsedColors; + /** Palette size. */ + uint16_t cLogoPalEntries; + /** Clear screen flag. */ + uint8_t fLogoClearScreen; + bool fBootMenuInverse; + uint8_t Padding8[6]; + /** Palette data. */ + uint32_t au32LogoPalette[256]; + /** The BIOS logo data. */ + R3PTRTYPE(uint8_t *) pbLogo; + /** The name of the logo file. */ + R3PTRTYPE(char *) pszLogoFile; + /** Bitmap image data. */ + R3PTRTYPE(uint8_t *) pbLogoBitmap; + /** @} */ + + /** @name VBE extra data (modes) + * @{ */ + /** The VBE BIOS extra data. */ + R3PTRTYPE(uint8_t *) pbVBEExtraData; + /** The size of the VBE BIOS extra data. */ + uint16_t cbVBEExtraData; + /** The VBE BIOS current memory address. */ + uint16_t u16VBEExtraAddress; + uint16_t Padding7[2]; + /** @} */ + +} VGASTATER3; +/** Pointer to the ring-3 VGA state. */ +typedef VGASTATER3 *PVGASTATER3; + + +/** + * The VGA state data for ring-0 context. + */ +typedef struct VGASTATER0 +{ + /** The R0 vram pointer. */ + R0PTRTYPE(uint8_t *) pbVRam; +#ifdef VBOX_WITH_VMSVGA + /** The VMSVGA ring-0 state. */ + VMSVGASTATER0 svga; +#endif +} VGASTATER0; +/** Pointer to the ring-0 VGA state. */ +typedef VGASTATER0 *PVGASTATER0; + + +/** + * The VGA state data for raw-mode context. + */ +typedef struct VGASTATERC +{ + /** Pointer to the RC vram mapping. */ + RCPTRTYPE(uint8_t *) pbVRam; +} VGASTATERC; +/** Pointer to the raw-mode VGA state. */ +typedef VGASTATERC *PVGASTATERC; + + +/** The VGA state for the current context. */ +typedef CTX_SUFF(VGASTATE) VGASTATECC; +/** Pointer to the VGA state for the current context. */ +typedef CTX_SUFF(PVGASTATE) PVGASTATECC; + + + +/** VBE Extra Data. */ +typedef VBEHeader VBEHEADER; +/** Pointer to the VBE Extra Data. */ +typedef VBEHEADER *PVBEHEADER; + +#if !defined(VBOX) || defined(IN_RING3) +static inline int c6_to_8(int v) +{ + int b; + v &= 0x3f; + b = v & 1; + return (v << 2) | (b << 1) | b; +} +#endif /* !VBOX || IN_RING3 */ + + +#ifdef VBOX_WITH_HGSMI +int VBVAInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC); +void VBVADestroy(PVGASTATECC pThisCC); +int VBVAUpdateDisplay(PVGASTATE pThis, PVGASTATECC pThisCC); +void VBVAReset(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC); +void VBVAOnVBEChanged(PVGASTATE pThis, PVGASTATECC pThisCC); +void VBVAOnResume(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC); + +bool VBVAIsPaused(PVGASTATECC pThisCC); +#ifdef UNUSED_FUNCTION +bool VBVAIsEnabled(PVGASTATECC pThisCC); +#endif + +void VBVARaiseIrq(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t fFlags); + +int VBVAInfoScreen(PVGASTATE pThis, const VBVAINFOSCREEN RT_UNTRUSTED_VOLATILE_HOST *pScreen); +#ifdef UNUSED_FUNCTION +int VBVAGetInfoViewAndScreen(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32ViewIndex, + VBVAINFOVIEW *pView, VBVAINFOSCREEN *pScreen); +#endif + +/* @return host-guest flags that were set on reset + * this allows the caller to make further cleaning when needed, + * e.g. reset the IRQ */ +uint32_t HGSMIReset(PHGSMIINSTANCE pIns); + +# ifdef VBOX_WITH_VIDEOHWACCEL +DECLCALLBACK(int) vbvaR3VHWACommandCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd); +int vbvaVHWAConstruct(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC); + +void vbvaTimerCb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC); + +int vboxVBVASaveStatePrep(PPDMDEVINS pDevIns); +int vboxVBVASaveStateDone(PPDMDEVINS pDevIns); +# endif + +int vboxVBVASaveStateExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM); +int vboxVBVALoadStateExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t u32Version); +int vboxVBVALoadStateDone(PPDMDEVINS pDevIns); + +DECLCALLBACK(int) vbvaR3PortSendModeHint(PPDMIDISPLAYPORT pInterface, uint32_t cx, uint32_t cy, uint32_t cBPP, + uint32_t cDisplay, uint32_t dx, uint32_t dy, uint32_t fEnabled, uint32_t fNotifyGuest); + +# ifdef VBOX_WITH_VDMA +typedef struct VBOXVDMAHOST *PVBOXVDMAHOST; +int vboxVDMAConstruct(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t cPipeElements); +void vboxVDMADestruct(PVBOXVDMAHOST pVdma); +void vboxVDMAReset(PVBOXVDMAHOST pVdma); +void vboxVDMAControl(PVBOXVDMAHOST pVdma, VBOXVDMA_CTL RT_UNTRUSTED_VOLATILE_GUEST *pCmd, uint32_t cbCmd); +void vboxVDMACommand(PVBOXVDMAHOST pVdma, VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *pCmd, uint32_t cbCmd); +int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma); +int vboxVDMASaveStateExecDone(struct VBOXVDMAHOST *pVdma); +int vboxVDMASaveStateExecPerform(PCPDMDEVHLPR3 pHlp, struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM); +int vboxVDMASaveLoadExecPerform(PCPDMDEVHLPR3 pHlp, struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM, uint32_t u32Version); +int vboxVDMASaveLoadDone(struct VBOXVDMAHOST *pVdma); +# endif /* VBOX_WITH_VDMA */ + +#endif /* VBOX_WITH_HGSMI */ + +# ifdef VBOX_WITH_VMSVGA +int vgaR3UnregisterVRAMHandler(PPDMDEVINS pDevIns, PVGASTATE pThis); +int vgaR3RegisterVRAMHandler(PPDMDEVINS pDevIns, PVGASTATE pThis, uint64_t cbFrameBuffer); +int vgaR3UpdateDisplay(PVGASTATE pThis, unsigned xStart, unsigned yStart, unsigned width, unsigned height); +# endif + +#ifndef VBOX +void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); +uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr); +void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val); +void vga_invalidate_scanlines(VGAState *s, int y1, int y2); + +void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); +void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); +void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); + +extern const uint8_t sr_mask[8]; +extern const uint8_t gr_mask[16]; +#endif /* !VBOX */ + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_h */ + diff --git a/src/VBox/Devices/Graphics/DevVGAModes.h b/src/VBox/Devices/Graphics/DevVGAModes.h new file mode 100644 index 00000000..9ac57c16 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGAModes.h @@ -0,0 +1,45 @@ +/* $Id: DevVGAModes.h $ */ +/** @file + * DevVGA - VBox VGA/VESA device, VBE modes. + * + * List of static mode information, containing all "supported" VBE + * modes and their 'settings'. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGAModes_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGAModes_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include +#include + +#include "vbetables.h" + +#define MODE_INFO_SIZE ( sizeof(mode_info_list) / sizeof(ModeInfoListItem) ) + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGAModes_h */ + diff --git a/src/VBox/Devices/Graphics/DevVGASavedState.h b/src/VBox/Devices/Graphics/DevVGASavedState.h new file mode 100644 index 00000000..5cb04f26 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGASavedState.h @@ -0,0 +1,89 @@ +/* $Id: DevVGASavedState.h $ */ +/** @file + * DevVGA - Saved state versions. + * + * @remarks HGSMI needs this but doesn't want to deal with DevVGA.h, thus this + * dedicated header. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGASavedState_h +#define VBOX_INCLUDED_SRC_Graphics_DevVGASavedState_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/** Creates an eyecatching marker in the VGA saved state ("Marker\n"). */ +#define VGA_SAVED_STATE_MAKE_MARKER(uSub) (UINT64_C(0x0a72656b72614d30) + (uint64_t)(uSub)) + +/** Puts a marker. Status code is not checked. */ +#define VGA_SAVED_STATE_PUT_MARKER(pSSM, uSub) \ + do { pHlp->pfnSSMPutU64(pSSM, VGA_SAVED_STATE_MAKE_MARKER(uSub)); } while (0) + +/** Retrieves a VGA saved state marker and checks that it matches, if it + * doesn't assert/LogRel and return. */ +#define VGA_SAVED_STATE_GET_MARKER_RETURN_ON_MISMATCH(pSSM, uVersion, uSub) \ + do { \ + if (uVersion >= VGA_SAVEDSTATE_VERSION_MARKERS) \ + { \ + uint64_t uMarker; \ + int rcMarker = pHlp->pfnSSMGetU64(pSSM, &uMarker); \ + AssertLogRelRCReturn(rcMarker, rcMarker); \ + AssertLogRelMsgReturn(uMarker == VGA_SAVED_STATE_MAKE_MARKER(uSub), \ + ("Bad VGA marker: expected %llx, got %llx\n", VGA_SAVED_STATE_MAKE_MARKER(uSub), uMarker), \ + VERR_SSM_DATA_UNIT_FORMAT_CHANGED); \ + } \ + } while (0) + +#define VGA_SAVEDSTATE_VERSION 27 +#define VGA_SAVEDSTATE_VERSION_VMSVGA_REG_CAP2 27 /* SVGA_REG_CAP2. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA_DX_SFLAGS 26 /* SVGA3dSurfaceAllFlags. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA_DX_CMDBUF 25 /* Command buffers capability is not tied to VGPU10 setting. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA_DX 24 /* VGPU10. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS 23 /* Surface struct with number of miplevels. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR 22 /* Legacy cursor registers. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS 21 /* Screen objects. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA 20 /* Multiple updates and fixes for VMSVGA saved state. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA_TEX_STAGES 19 +#define VGA_SAVEDSTATE_VERSION_VMSVGA_GMR_COUNT 18 +#define VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX 17 +#define VGA_SAVEDSTATE_VERSION_MARKERS 16 +#define VGA_SAVEDSTATE_VERSION_MODE_HINTS 15 +#define VGA_SAVEDSTATE_VERSION_FIXED_PENDVHWA 14 +#define VGA_SAVEDSTATE_VERSION_3D 13 +#define VGA_SAVEDSTATE_VERSION_HGSMIMA 12 /* HGSMI memory allocator. */ +#define VGA_SAVEDSTATE_VERSION_VMSVGA_2D 10 /* <- internal build with 2d state only */ +#define VGA_SAVEDSTATE_VERSION_WITH_PENDVHWA 10 +#define VGA_SAVEDSTATE_VERSION_INV_GCMDFIFO 8 /* <- states upto and including this version may contain invalid completed Guest Commands fifo entries */ +#define VGA_SAVEDSTATE_VERSION_INV_VHEIGHT 8 /* <- states upto and including this version may contain invalid vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] value */ +#define VGA_SAVEDSTATE_VERSION_WDDM 7 +#define VGA_SAVEDSTATE_VERSION_PRE_WDDM 6 +#define VGA_SAVEDSTATE_VERSION_HOST_HEAP 5 +#define VGA_SAVEDSTATE_VERSION_WITH_CONFIG 4 +#define VGA_SAVEDSTATE_VERSION_HGSMI 3 +#define VGA_SAVEDSTATE_VERSION_PRE_HGSMI 2 +#define VGA_SAVEDSTATE_VERSION_ANCIENT 1 + +#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGASavedState_h */ + diff --git a/src/VBox/Devices/Graphics/DevVGATmpl.h b/src/VBox/Devices/Graphics/DevVGATmpl.h new file mode 100644 index 00000000..9ec4bad9 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGATmpl.h @@ -0,0 +1,582 @@ +/* $Id: DevVGATmpl.h $ */ +/** @file + * DevVGA - VBox VGA/VESA device, code templates. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + * -------------------------------------------------------------------- + * + * This code is based on: + * + * QEMU VGA Emulator templates + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define BPP 1 +#define PIXEL_TYPE uint8_t +#elif DEPTH == 15 || DEPTH == 16 +#define BPP 2 +#define PIXEL_TYPE uint16_t +#elif DEPTH == 32 +#define BPP 4 +#define PIXEL_TYPE uint32_t +#else +#error unsupport depth +#endif + +#if DEPTH != 15 + +static inline void RT_CONCAT(vga_draw_glyph_line_, DEPTH)(uint8_t *d, + int font_data, + uint32_t xorcol, + uint32_t bgcol, + int dscan, + int linesize) +{ +#if BPP == 1 + ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; + if (dscan) { + uint8_t *c = d + linesize; + ((uint32_t *)c)[0] = ((uint32_t *)d)[0]; + ((uint32_t *)c)[1] = ((uint32_t *)d)[1]; + } +#elif BPP == 2 + ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; + if (dscan) + memcpy(d + linesize, d, 4 * sizeof(uint32_t)); +#else + ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; + if (dscan) + memcpy(d + linesize, d, 8 * sizeof(uint32_t)); +#endif +} + +static void RT_CONCAT(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol, int dscan) +{ + uint32_t xorcol; + int font_data; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; + RT_CONCAT(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol, dscan, linesize); + font_ptr += 4; + d += linesize << dscan; + } while (--h); +} + +static void RT_CONCAT(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol, int dscan) +{ + uint32_t xorcol; + int font_data; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; + RT_CONCAT(vga_draw_glyph_line_, DEPTH)(d, + expand4to8[font_data >> 4], + xorcol, bgcol, dscan, linesize); + RT_CONCAT(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP, + expand4to8[font_data & 0x0f], + xorcol, bgcol, dscan, linesize); + font_ptr += 4; + d += linesize << dscan; + } while (--h); +} + +static void RT_CONCAT(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol, int dup9) +{ + uint32_t xorcol, v; + int font_data; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; +#if BPP == 1 + ((uint32_t *)d)[0] = RT_H2LE_U32((dmask16[(font_data >> 4)] & xorcol) ^ bgcol); + v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = RT_H2LE_U32(v); + if (dup9) + ((uint8_t *)d)[8] = v >> (24 * (1 - BIG)); + else + ((uint8_t *)d)[8] = bgcol; + +#elif BPP == 2 + ((uint32_t *)d)[0] = RT_H2LE_U32((dmask4[(font_data >> 6)] & xorcol) ^ bgcol); + ((uint32_t *)d)[1] = RT_H2LE_U32((dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol); + ((uint32_t *)d)[2] = RT_H2LE_U32((dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol); + v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = RT_H2LE_U32(v); + if (dup9) + ((uint16_t *)d)[8] = v >> (16 * (1 - BIG)); + else + ((uint16_t *)d)[8] = bgcol; +#else + ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; + v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[7] = v; + if (dup9) + ((uint32_t *)d)[8] = v; + else + ((uint32_t *)d)[8] = bgcol; +#endif + font_ptr += 4; + d += linesize; + } while (--h); +} + +/* + * 4 color mode + */ +static void RT_CONCAT(vga_draw_line2_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, *palette, data, v, src_inc, dwb_mode; + int x; + RT_NOREF(pThisCC); + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[0x12] & 0xf]; + dwb_mode = (s1->cr[0x14] & 0x40) ? 2 : (s1->cr[0x17] & 0x40) ? 0 : 1; + src_inc = 4 << dwb_mode; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand2[GET_PLANE(data, 0)]; + v |= expand2[GET_PLANE(data, 2)] << 2; + ((PIXEL_TYPE *)d)[0] = palette[v >> 12]; + ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf]; + + v = expand2[GET_PLANE(data, 1)]; + v |= expand2[GET_PLANE(data, 3)] << 2; + ((PIXEL_TYPE *)d)[4] = palette[v >> 12]; + ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; + d += BPP * 8; + s += src_inc; + } +} + +#if BPP == 1 +#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v) +#elif BPP == 2 +#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v) +#else +#define PUT_PIXEL2(d, n, v) \ +((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) +#endif + +/* + * 4 color mode, dup2 horizontal + */ +static void RT_CONCAT(vga_draw_line2d2_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, *palette, data, v, src_inc, dwb_mode; + int x; + RT_NOREF(pThisCC); + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[0x12] & 0xf]; + dwb_mode = (s1->cr[0x14] & 0x40) ? 2 : (s1->cr[0x17] & 0x40) ? 0 : 1; + src_inc = 4 << dwb_mode; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand2[GET_PLANE(data, 0)]; + v |= expand2[GET_PLANE(data, 2)] << 2; + PUT_PIXEL2(d, 0, palette[v >> 12]); + PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); + + v = expand2[GET_PLANE(data, 1)]; + v |= expand2[GET_PLANE(data, 3)] << 2; + PUT_PIXEL2(d, 4, palette[v >> 12]); + PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); + d += BPP * 16; + s += src_inc; + } +} + +/* + * 16 color mode + */ +static void RT_CONCAT(vga_draw_line4_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, data, v, *palette, vram_ofs; + int x; + RT_NOREF(pThisCC); + + vram_ofs = s - pThisCC->pbVRam; + palette = s1->last_palette; + plane_mask = mask16[s1->ar[0x12] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + s = pThisCC->pbVRam + (vram_ofs & s1->vga_addr_mask); + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand4[GET_PLANE(data, 0)]; + v |= expand4[GET_PLANE(data, 1)] << 1; + v |= expand4[GET_PLANE(data, 2)] << 2; + v |= expand4[GET_PLANE(data, 3)] << 3; + ((PIXEL_TYPE *)d)[0] = palette[v >> 28]; + ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf]; + ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf]; + ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf]; + ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf]; + ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; + d += BPP * 8; + vram_ofs += 4; + } +} + +/* + * 16 color mode, dup2 horizontal + */ +static void RT_CONCAT(vga_draw_line4d2_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, data, v, *palette; + int x; + RT_NOREF(pThisCC); + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[0x12] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand4[GET_PLANE(data, 0)]; + v |= expand4[GET_PLANE(data, 1)] << 1; + v |= expand4[GET_PLANE(data, 2)] << 2; + v |= expand4[GET_PLANE(data, 3)] << 3; + PUT_PIXEL2(d, 0, palette[v >> 28]); + PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); + PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); + PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); + PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); + PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); + d += BPP * 16; + s += 4; + } +} + +/* + * 256 color mode, double pixels + * + * XXX: add plane_mask support (never used in standard VGA modes) + */ +static void RT_CONCAT(vga_draw_line8d2_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t *palette; + int x; + RT_NOREF(pThisCC); + + palette = s1->last_palette; + width >>= 3; + for(x = 0; x < width; x++) { + PUT_PIXEL2(d, 0, palette[s[0]]); + PUT_PIXEL2(d, 1, palette[s[1]]); + PUT_PIXEL2(d, 2, palette[s[2]]); + PUT_PIXEL2(d, 3, palette[s[3]]); + d += BPP * 8; + s += 4; + } +} + +/* + * standard 256 color mode + * + * XXX: add plane_mask support (never used in standard VGA modes) + */ +static void RT_CONCAT(vga_draw_line8_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t *palette; + int x; + RT_NOREF(pThisCC); + + palette = s1->last_palette; + width >>= 3; + for(x = 0; x < width; x++) { + ((PIXEL_TYPE *)d)[0] = palette[s[0]]; + ((PIXEL_TYPE *)d)[1] = palette[s[1]]; + ((PIXEL_TYPE *)d)[2] = palette[s[2]]; + ((PIXEL_TYPE *)d)[3] = palette[s[3]]; + ((PIXEL_TYPE *)d)[4] = palette[s[4]]; + ((PIXEL_TYPE *)d)[5] = palette[s[5]]; + ((PIXEL_TYPE *)d)[6] = palette[s[6]]; + ((PIXEL_TYPE *)d)[7] = palette[s[7]]; + d += BPP * 8; + s += 8; + } +} + +#endif /* DEPTH != 15 */ + + +/* XXX: optimize */ + +/* + * 15 bit color + */ +static void RT_CONCAT(vga_draw_line15_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + RT_NOREF(s1, pThisCC); +#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 2); +#else + int w; + uint32_t v, r, g, b; + + w = width; + do { + v = s[0] | (s[1] << 8); + r = (v >> 7) & 0xf8; + g = (v >> 2) & 0xf8; + b = (v << 3) & 0xf8; + ((PIXEL_TYPE *)d)[0] = RT_CONCAT(rgb_to_pixel, DEPTH)(r, g, b); + s += 2; + d += BPP; + } while (--w != 0); +#endif +} + +/* + * 16 bit color + */ +static void RT_CONCAT(vga_draw_line16_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + RT_NOREF(s1, pThisCC); +#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 2); +#else + int w; + uint32_t v, r, g, b; + + w = width; + do { + v = s[0] | (s[1] << 8); + r = (v >> 8) & 0xf8; + g = (v >> 3) & 0xfc; + b = (v << 3) & 0xf8; + ((PIXEL_TYPE *)d)[0] = RT_CONCAT(rgb_to_pixel, DEPTH)(r, g, b); + s += 2; + d += BPP; + } while (--w != 0); +#endif +} + +/* + * 24 bit color + */ +static void RT_CONCAT(vga_draw_line24_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + int w; + uint32_t r, g, b; + RT_NOREF(s1, pThisCC); + + w = width; + do { +#if defined(TARGET_WORDS_BIGENDIAN) + r = s[0]; + g = s[1]; + b = s[2]; +#else + b = s[0]; + g = s[1]; + r = s[2]; +#endif + ((PIXEL_TYPE *)d)[0] = RT_CONCAT(rgb_to_pixel, DEPTH)(r, g, b); + s += 3; + d += BPP; + } while (--w != 0); +} + +/* + * 32 bit color + */ +static void RT_CONCAT(vga_draw_line32_, DEPTH)(VGAState *s1, PVGASTATER3 pThisCC, uint8_t *d, + const uint8_t *s, int width) +{ + RT_NOREF(s1, pThisCC); +#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 4); +#else + int w; + uint32_t r, g, b; + + w = width; + do { +#if defined(TARGET_WORDS_BIGENDIAN) + r = s[1]; + g = s[2]; + b = s[3]; +#else + b = s[0]; + g = s[1]; + r = s[2]; +#endif + ((PIXEL_TYPE *)d)[0] = RT_CONCAT(rgb_to_pixel, DEPTH)(r, g, b); + s += 4; + d += BPP; + } while (--w != 0); +#endif +} + +#if DEPTH != 15 +#ifndef VBOX +#ifdef VBOX +static +#endif/* VBOX */ +void RT_CONCAT(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, + const uint8_t *src1, + int poffset, int w, + unsigned int color0, + unsigned int color1, + unsigned int color_xor) +{ + const uint8_t *plane0, *plane1; + int x, b0, b1; + uint8_t *d; + + d = d1; + plane0 = src1; + plane1 = src1 + poffset; + for(x = 0; x < w; x++) { + b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; + b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; +#if DEPTH == 8 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + d[0] ^= color_xor; + break; + case 2: + d[0] = color0; + break; + case 3: + d[0] = color1; + break; + } +#elif DEPTH == 16 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + ((uint16_t *)d)[0] ^= color_xor; + break; + case 2: + ((uint16_t *)d)[0] = color0; + break; + case 3: + ((uint16_t *)d)[0] = color1; + break; + } +#elif DEPTH == 32 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + ((uint32_t *)d)[0] ^= color_xor; + break; + case 2: + ((uint32_t *)d)[0] = color0; + break; + case 3: + ((uint32_t *)d)[0] = color1; + break; + } +#else +#error unsupported depth +#endif + d += BPP; + } +} +#endif /* !VBOX */ +#endif + +#undef PUT_PIXEL2 +#undef DEPTH +#undef BPP +#undef PIXEL_TYPE diff --git a/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp b/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp new file mode 100644 index 00000000..a38f7e7c --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp @@ -0,0 +1,2884 @@ +/* $Id: DevVGA_VBVA.cpp $ */ +/** @file + * VirtualBox Video Acceleration (VBVA). + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VGA +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef VBOX_WITH_VIDEOHWACCEL +#include +#endif + +#include "DevVGA.h" + +/* A very detailed logging. */ +#if 0 // def DEBUG_sunlover +#define LOGVBVABUFFER(a) LogFlow(a) +#else +#define LOGVBVABUFFER(a) do {} while (0) +#endif + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +typedef struct VBVAPARTIALRECORD +{ + uint8_t *pu8; + uint32_t cb; +} VBVAPARTIALRECORD; + +typedef struct VBVADATA +{ + struct + { + VBVABUFFER RT_UNTRUSTED_VOLATILE_GUEST *pVBVA; /**< Pointer to the guest memory with the VBVABUFFER. */ + uint8_t RT_UNTRUSTED_VOLATILE_GUEST *pu8Data; /**< For convenience, pointer to the guest ring buffer (VBVABUFFER::au8Data). */ + } guest; + uint32_t u32VBVAOffset; /**< VBVABUFFER offset in the guest VRAM. */ + VBVAPARTIALRECORD partialRecord; /**< Partial record temporary storage. */ + uint32_t off32Data; /**< The offset where the data starts in the VBVABUFFER. + * The host code uses it instead of VBVABUFFER::off32Data. */ + uint32_t indexRecordFirst; /**< Index of the first filled record in VBVABUFFER::aRecords. */ + uint32_t cbPartialWriteThreshold; /**< Copy of VBVABUFFER::cbPartialWriteThreshold used by host code. */ + uint32_t cbData; /**< Copy of VBVABUFFER::cbData used by host code. */ +} VBVADATA; + +typedef struct VBVAVIEW +{ + VBVAINFOVIEW view; + VBVAINFOSCREEN screen; + VBVADATA vbva; +} VBVAVIEW; + +typedef struct VBVAMOUSESHAPEINFO +{ + bool fSet; + bool fVisible; + bool fAlpha; + uint32_t u32HotX; + uint32_t u32HotY; + uint32_t u32Width; + uint32_t u32Height; + uint32_t cbShape; + uint32_t cbAllocated; + uint8_t *pu8Shape; +} VBVAMOUSESHAPEINFO; + +/** @todo saved state: save and restore VBVACONTEXT */ +typedef struct VBVACONTEXT +{ + uint32_t cViews; + VBVAVIEW aViews[VBOX_VIDEO_MAX_SCREENS]; + VBVAMOUSESHAPEINFO mouseShapeInfo; + bool fPaused; + VBVAMODEHINT aModeHints[VBOX_VIDEO_MAX_SCREENS]; +} VBVACONTEXT; + + +static void vbvaDataCleanup(VBVADATA *pVBVAData) +{ + if (pVBVAData->guest.pVBVA) + { + pVBVAData->guest.pVBVA->hostFlags.u32HostEvents = 0; + pVBVAData->guest.pVBVA->hostFlags.u32SupportedOrders = 0; + } + + RTMemFreeZ(pVBVAData->partialRecord.pu8, pVBVAData->partialRecord.cb); + + RT_ZERO(*pVBVAData); + pVBVAData->u32VBVAOffset = HGSMIOFFSET_VOID; +} + +/** Copies @a cb bytes from the VBVA ring buffer to the @a pbDst. + * Used for partial records or for records which cross the ring boundary. + */ +static bool vbvaFetchBytes(VBVADATA *pVBVAData, uint8_t *pbDst, uint32_t cb) +{ + if (cb >= pVBVAData->cbData) + { + AssertMsgFailed(("cb = 0x%08X, ring buffer size 0x%08X", cb, pVBVAData->cbData)); + return false; + } + + const uint8_t RT_UNTRUSTED_VOLATILE_GUEST *pbSrc = &pVBVAData->guest.pu8Data[pVBVAData->off32Data]; + const uint32_t u32BytesTillBoundary = pVBVAData->cbData - pVBVAData->off32Data; + const int32_t i32Diff = cb - u32BytesTillBoundary; + + if (i32Diff <= 0) + { + /* Chunk will not cross buffer boundary. */ + RT_BCOPY_VOLATILE(pbDst, pbSrc, cb); + } + else + { + /* Chunk crosses buffer boundary. */ + RT_BCOPY_VOLATILE(pbDst, pbSrc, u32BytesTillBoundary); + RT_BCOPY_VOLATILE(pbDst + u32BytesTillBoundary, &pVBVAData->guest.pu8Data[0], i32Diff); + } + + /* Advance data offset and sync with guest. */ + pVBVAData->off32Data = (pVBVAData->off32Data + cb) % pVBVAData->cbData; + pVBVAData->guest.pVBVA->off32Data = pVBVAData->off32Data; + return true; +} + + +static bool vbvaPartialRead(uint32_t cbRecord, VBVADATA *pVBVAData) +{ + VBVAPARTIALRECORD *pPartialRecord = &pVBVAData->partialRecord; + uint8_t *pu8New; + + LOGVBVABUFFER(("vbvaPartialRead: p = %p, cb = %d, cbRecord 0x%08X\n", + pPartialRecord->pu8, pPartialRecord->cb, cbRecord)); + + Assert(cbRecord > pPartialRecord->cb); /* Caller ensures this. */ + + const uint32_t cbChunk = cbRecord - pPartialRecord->cb; + if (cbChunk >= pVBVAData->cbData) + { + return false; + } + + if (pPartialRecord->pu8) + { + Assert(pPartialRecord->cb); + pu8New = (uint8_t *)RTMemRealloc(pPartialRecord->pu8, cbRecord); + } + else + { + Assert(!pPartialRecord->cb); + pu8New = (uint8_t *)RTMemAlloc(cbRecord); + } + + if (!pu8New) + { + /* Memory allocation failed, fail the function. */ + Log(("vbvaPartialRead: failed to (re)alocate memory for partial record!!! cbRecord 0x%08X\n", + cbRecord)); + + return false; + } + + /* Fetch data from the ring buffer. */ + if (!vbvaFetchBytes(pVBVAData, pu8New + pPartialRecord->cb, cbChunk)) + { + return false; + } + + pPartialRecord->pu8 = pu8New; + pPartialRecord->cb = cbRecord; + + return true; +} + +/** + * For contiguous chunks just return the address in the buffer. For crossing + * boundary - allocate a buffer from heap. + */ +static bool vbvaFetchCmd(VBVADATA *pVBVAData, VBVACMDHDR RT_UNTRUSTED_VOLATILE_GUEST **ppHdr, uint32_t *pcbCmd) +{ + VBVAPARTIALRECORD *pPartialRecord = &pVBVAData->partialRecord; + uint32_t indexRecordFirst = pVBVAData->indexRecordFirst; + const uint32_t indexRecordFree = ASMAtomicReadU32(&pVBVAData->guest.pVBVA->indexRecordFree); + + LOGVBVABUFFER(("first = %d, free = %d\n", + indexRecordFirst, indexRecordFree)); + + if (indexRecordFree >= RT_ELEMENTS(pVBVAData->guest.pVBVA->aRecords)) + { + return false; + } + + if (indexRecordFirst == indexRecordFree) + { + /* No records to process. Return without assigning output variables. */ + return true; + } + + uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVAData->guest.pVBVA->aRecords[indexRecordFirst].cbRecord); + + LOGVBVABUFFER(("cbRecord = 0x%08X, pPartialRecord->cb = 0x%08X\n", cbRecordCurrent, pPartialRecord->cb)); + + uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL; + + if (cbRecord > VBVA_MAX_RECORD_SIZE) + { + return false; + } + + if (pPartialRecord->cb) + { + /* There is a partial read in process. Continue with it. */ + Assert (pPartialRecord->pu8); + + LOGVBVABUFFER(("continue partial record cb = %d cbRecord 0x%08X, first = %d, free = %d\n", + pPartialRecord->cb, cbRecordCurrent, indexRecordFirst, indexRecordFree)); + + if (cbRecord > pPartialRecord->cb) + { + /* New data has been added to the record. */ + if (!vbvaPartialRead(cbRecord, pVBVAData)) + { + return false; + } + } + + if (!(cbRecordCurrent & VBVA_F_RECORD_PARTIAL)) + { + /* The record is completed by guest. Return it to the caller. */ + *ppHdr = (VBVACMDHDR *)pPartialRecord->pu8; + *pcbCmd = pPartialRecord->cb; + + pPartialRecord->pu8 = NULL; + pPartialRecord->cb = 0; + + /* Advance the record index and sync with guest. */ + pVBVAData->indexRecordFirst = (indexRecordFirst + 1) % RT_ELEMENTS(pVBVAData->guest.pVBVA->aRecords); + pVBVAData->guest.pVBVA->indexRecordFirst = pVBVAData->indexRecordFirst; + + LOGVBVABUFFER(("partial done ok, data = %d, free = %d\n", + pVBVAData->off32Data, pVBVAData->guest.pVBVA->off32Free)); + } + + return true; + } + + /* A new record need to be processed. */ + if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL) + { + /* Current record is being written by guest. '=' is important here, + * because the guest will do a FLUSH at this condition. + * This partial record is too large for the ring buffer and must + * be accumulated in an allocated buffer. + */ + if (cbRecord >= pVBVAData->cbData - pVBVAData->cbPartialWriteThreshold) + { + /* Partial read must be started. */ + if (!vbvaPartialRead(cbRecord, pVBVAData)) + { + return false; + } + + LOGVBVABUFFER(("started partial record cb = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n", + pPartialRecord->cb, cbRecordCurrent, indexRecordFirst, indexRecordFree)); + } + + return true; + } + + /* Current record is complete. If it is not empty, process it. */ + if (cbRecord >= pVBVAData->cbData) + { + return false; + } + + if (cbRecord) + { + /* The size of largest contiguous chunk in the ring buffer. */ + uint32_t u32BytesTillBoundary = pVBVAData->cbData - pVBVAData->off32Data; + + /* The pointer to data in the ring buffer. */ + uint8_t RT_UNTRUSTED_VOLATILE_GUEST *pbSrc = &pVBVAData->guest.pu8Data[pVBVAData->off32Data]; + + /* Fetch or point the data. */ + if (u32BytesTillBoundary >= cbRecord) + { + /* The command does not cross buffer boundary. Return address in the buffer. */ + *ppHdr = (VBVACMDHDR RT_UNTRUSTED_VOLATILE_GUEST *)pbSrc; + + /* The data offset will be updated in vbvaReleaseCmd. */ + } + else + { + /* The command crosses buffer boundary. Rare case, so not optimized. */ + uint8_t *pbDst = (uint8_t *)RTMemAlloc(cbRecord); + if (!pbDst) + { + LogFlowFunc (("could not allocate %d bytes from heap!!!\n", cbRecord)); + return false; + } + + vbvaFetchBytes(pVBVAData, pbDst, cbRecord); + + *ppHdr = (VBVACMDHDR *)pbDst; + + LOGVBVABUFFER(("Allocated from heap %p\n", pbDst)); + } + } + + *pcbCmd = cbRecord; + + /* Advance the record index and sync with guest. */ + pVBVAData->indexRecordFirst = (indexRecordFirst + 1) % RT_ELEMENTS(pVBVAData->guest.pVBVA->aRecords); + pVBVAData->guest.pVBVA->indexRecordFirst = pVBVAData->indexRecordFirst; + + LOGVBVABUFFER(("done ok, data = %d, free = %d\n", + pVBVAData->off32Data, pVBVAData->guest.pVBVA->off32Free)); + + return true; +} + +static void vbvaReleaseCmd(VBVADATA *pVBVAData, VBVACMDHDR RT_UNTRUSTED_VOLATILE_GUEST *pHdr, uint32_t cbCmd) +{ + VBVAPARTIALRECORD *pPartialRecord = &pVBVAData->partialRecord; + const uint8_t RT_UNTRUSTED_VOLATILE_GUEST *pbRingBuffer = pVBVAData->guest.pu8Data; + + if ( (uintptr_t)pHdr >= (uintptr_t)pbRingBuffer + && (uintptr_t)pHdr < (uintptr_t)&pbRingBuffer[pVBVAData->cbData]) + { + /* The pointer is inside ring buffer. Must be continuous chunk. */ + Assert(pVBVAData->cbData - (uint32_t)((uint8_t *)pHdr - pbRingBuffer) >= cbCmd); + + /* Advance data offset and sync with guest. */ + pVBVAData->off32Data = (pVBVAData->off32Data + cbCmd) % pVBVAData->cbData; + pVBVAData->guest.pVBVA->off32Data = pVBVAData->off32Data; + + Assert(!pPartialRecord->pu8 && pPartialRecord->cb == 0); + } + else + { + /* The pointer is outside. It is then an allocated copy. */ + LOGVBVABUFFER(("Free heap %p\n", pHdr)); + + if ((uint8_t *)pHdr == pPartialRecord->pu8) + { + pPartialRecord->pu8 = NULL; + pPartialRecord->cb = 0; + } + else + { + Assert(!pPartialRecord->pu8 && pPartialRecord->cb == 0); + } + + RTMemFree((void *)pHdr); + } +} + +static int vbvaFlushProcess(PVGASTATECC pThisCC, VBVADATA *pVBVAData, unsigned uScreenId) +{ + LOGVBVABUFFER(("uScreenId %d, indexRecordFirst = %d, indexRecordFree = %d, off32Data = %d, off32Free = %d\n", + uScreenId, pVBVAData->indexRecordFirst, pVBVAData->guest.pVBVA->indexRecordFree, + pVBVAData->off32Data, pVBVAData->guest.pVBVA->off32Free)); + struct + { + /* The rectangle that includes all dirty rectangles. */ + int32_t xLeft; + int32_t xRight; + int32_t yTop; + int32_t yBottom; + } dirtyRect; + RT_ZERO(dirtyRect); + + bool fUpdate = false; /* Whether there were any updates. */ + bool fDirtyEmpty = true; + + for (;;) + { + /* Fetch the command data. */ + VBVACMDHDR RT_UNTRUSTED_VOLATILE_GUEST *pHdr = NULL; + uint32_t cbCmd = UINT32_MAX; + if (!vbvaFetchCmd(pVBVAData, &pHdr, &cbCmd)) + { + LogFunc(("unable to fetch command. off32Data = %d, off32Free = %d!!!\n", + pVBVAData->off32Data, pVBVAData->guest.pVBVA->off32Free)); + return VERR_NOT_SUPPORTED; + } + + if (cbCmd == UINT32_MAX) + { + /* No more commands yet in the queue. */ + break; + } + + if (cbCmd < sizeof(VBVACMDHDR)) + { + LogFunc(("short command. off32Data = %d, off32Free = %d, cbCmd %d!!!\n", + pVBVAData->off32Data, pVBVAData->guest.pVBVA->off32Free, cbCmd)); + + return VERR_NOT_SUPPORTED; + } + + if (cbCmd != 0) + { + if (!fUpdate) + { + pThisCC->pDrv->pfnVBVAUpdateBegin(pThisCC->pDrv, uScreenId); + fUpdate = true; + } + + /* Updates the rectangle and sends the command to the VRDP server. */ + pThisCC->pDrv->pfnVBVAUpdateProcess(pThisCC->pDrv, uScreenId, pHdr, cbCmd); + + int32_t xRight = pHdr->x + pHdr->w; + int32_t yBottom = pHdr->y + pHdr->h; + + /* These are global coords, relative to the primary screen. */ + + LOGVBVABUFFER(("cbCmd = %d, x=%d, y=%d, w=%d, h=%d\n", cbCmd, pHdr->x, pHdr->y, pHdr->w, pHdr->h)); + LogRel3(("%s: update command cbCmd = %d, x=%d, y=%d, w=%d, h=%d\n", + __FUNCTION__, cbCmd, pHdr->x, pHdr->y, pHdr->w, pHdr->h)); + + /* Collect all rects into one. */ + if (fDirtyEmpty) + { + /* This is the first rectangle to be added. */ + dirtyRect.xLeft = pHdr->x; + dirtyRect.yTop = pHdr->y; + dirtyRect.xRight = xRight; + dirtyRect.yBottom = yBottom; + fDirtyEmpty = false; + } + else + { + /* Adjust region coordinates. */ + if (dirtyRect.xLeft > pHdr->x) + { + dirtyRect.xLeft = pHdr->x; + } + + if (dirtyRect.yTop > pHdr->y) + { + dirtyRect.yTop = pHdr->y; + } + + if (dirtyRect.xRight < xRight) + { + dirtyRect.xRight = xRight; + } + + if (dirtyRect.yBottom < yBottom) + { + dirtyRect.yBottom = yBottom; + } + } + } + + vbvaReleaseCmd(pVBVAData, pHdr, cbCmd); + } + + if (fUpdate) + { + if (dirtyRect.xRight - dirtyRect.xLeft) + { + LogRel3(("%s: sending update screen=%d, x=%d, y=%d, w=%d, h=%d\n", + __FUNCTION__, uScreenId, dirtyRect.xLeft, + dirtyRect.yTop, dirtyRect.xRight - dirtyRect.xLeft, + dirtyRect.yBottom - dirtyRect.yTop)); + pThisCC->pDrv->pfnVBVAUpdateEnd(pThisCC->pDrv, uScreenId, dirtyRect.xLeft, dirtyRect.yTop, + dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop); + } + else + { + pThisCC->pDrv->pfnVBVAUpdateEnd(pThisCC->pDrv, uScreenId, 0, 0, 0, 0); + } + } + + return VINF_SUCCESS; +} + +static int vbvaFlush(PVGASTATE pThis, PVGASTATECC pThisCC, VBVACONTEXT *pCtx) +{ + int rc = VINF_SUCCESS; + + unsigned uScreenId; + for (uScreenId = 0; uScreenId < pCtx->cViews; uScreenId++) + { + VBVADATA *pVBVAData = &pCtx->aViews[uScreenId].vbva; + if (pVBVAData->guest.pVBVA) + { + rc = vbvaFlushProcess(pThisCC, pVBVAData, uScreenId); + if (RT_FAILURE(rc)) + break; + } + } + + if (RT_FAILURE(rc)) + { + /* Turn off VBVA processing. */ + LogRel(("VBVA: Disabling (%Rrc)\n", rc)); + pThis->fGuestCaps = 0; + pThisCC->pDrv->pfnVBVAGuestCapabilityUpdate(pThisCC->pDrv, pThis->fGuestCaps); + for (uScreenId = 0; uScreenId < pCtx->cViews; uScreenId++) + { + VBVADATA *pVBVAData = &pCtx->aViews[uScreenId].vbva; + if (pVBVAData->guest.pVBVA) + { + vbvaDataCleanup(pVBVAData); + pThisCC->pDrv->pfnVBVADisable(pThisCC->pDrv, uScreenId); + } + } + } + + return rc; +} + +static int vbvaResize(PVGASTATECC pThisCC, VBVAVIEW *pView, const VBVAINFOSCREEN *pNewScreen, bool fResetInputMapping) +{ + /* Callers ensure that pNewScreen contains valid data. */ + + /* Apply these changes. */ + pView->screen = *pNewScreen; + + uint8_t *pbVRam = pThisCC->pbVRam + pView->view.u32ViewOffset; + return pThisCC->pDrv->pfnVBVAResize(pThisCC->pDrv, &pView->view, &pView->screen, pbVRam, fResetInputMapping); +} + +static int vbvaEnable(PVGASTATE pThis, PVGASTATECC pThisCC, VBVACONTEXT *pCtx, unsigned uScreenId, + VBVABUFFER RT_UNTRUSTED_VOLATILE_GUEST *pVBVA, uint32_t u32Offset, bool fRestored) +{ + /* + * Copy into non-volatile memory and validate its content. + */ + VBVABUFFER VbgaSafe; + RT_COPY_VOLATILE(VbgaSafe, *pVBVA); + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + uint32_t const cbVBVABuffer = RT_UOFFSETOF(VBVABUFFER, au8Data) + VbgaSafe.cbData; + ASSERT_GUEST_RETURN( VbgaSafe.cbData <= UINT32_MAX - RT_UOFFSETOF(VBVABUFFER, au8Data) + && cbVBVABuffer <= pThis->vram_size + && u32Offset <= pThis->vram_size - cbVBVABuffer, + VERR_INVALID_PARAMETER); + if (!fRestored) + { + ASSERT_GUEST_RETURN(VbgaSafe.off32Data == 0, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(VbgaSafe.off32Free == 0, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(VbgaSafe.indexRecordFirst == 0, VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(VbgaSafe.indexRecordFree == 0, VERR_INVALID_PARAMETER); + } + ASSERT_GUEST_RETURN( VbgaSafe.cbPartialWriteThreshold < VbgaSafe.cbData + && VbgaSafe.cbPartialWriteThreshold != 0, + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* + * Okay, try do the job. + */ + int rc; + if (pThisCC->pDrv->pfnVBVAEnable) + { + pVBVA->hostFlags.u32HostEvents = 0; + pVBVA->hostFlags.u32SupportedOrders = 0; + rc = pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, uScreenId, &pVBVA->hostFlags); + if (RT_SUCCESS(rc)) + { + /* pVBVA->hostFlags has been set up by pfnVBVAEnable. */ + LogFlowFunc(("u32HostEvents=0x%08x u32SupportedOrders=0x%08x\n", + pVBVA->hostFlags.u32HostEvents, pVBVA->hostFlags.u32SupportedOrders)); + + VBVADATA *pVBVAData = &pCtx->aViews[uScreenId].vbva; + pVBVAData->guest.pVBVA = pVBVA; + pVBVAData->guest.pu8Data = &pVBVA->au8Data[0]; + pVBVAData->u32VBVAOffset = u32Offset; + pVBVAData->off32Data = VbgaSafe.off32Data; + pVBVAData->indexRecordFirst = VbgaSafe.indexRecordFirst; + pVBVAData->cbPartialWriteThreshold = VbgaSafe.cbPartialWriteThreshold; + pVBVAData->cbData = VbgaSafe.cbData; + + if (!fRestored) + { + /** @todo Actually this function must not touch the partialRecord structure at all, + * because initially it is a zero and when VBVA is disabled this should be set to zero. + * But I'm not sure that no code depends on zeroing partialRecord here. + * So for now (a quick fix for 4.1) just do not do this if the VM was restored, + * when partialRecord might be loaded already from the saved state. + */ + pVBVAData->partialRecord.pu8 = NULL; + pVBVAData->partialRecord.cb = 0; + } + + /* VBVA is working so disable the pause. */ + pCtx->fPaused = false; + } + } + else + rc = VERR_NOT_SUPPORTED; + return rc; +} + +static int vbvaDisable(PVGASTATE pThis, PVGASTATECC pThisCC, VBVACONTEXT *pCtx, unsigned idScreen) +{ + /* Process any pending orders and empty the VBVA ring buffer. */ + vbvaFlush(pThis, pThisCC, pCtx); + + AssertReturn(idScreen < RT_ELEMENTS(pCtx->aViews), VERR_OUT_OF_RANGE); + VBVADATA *pVBVAData = &pCtx->aViews[idScreen].vbva; + vbvaDataCleanup(pVBVAData); + + if (idScreen == 0) + { + pThis->fGuestCaps = 0; + pThisCC->pDrv->pfnVBVAGuestCapabilityUpdate(pThisCC->pDrv, pThis->fGuestCaps); + } + pThisCC->pDrv->pfnVBVADisable(pThisCC->pDrv, idScreen); + return VINF_SUCCESS; +} + +#ifdef UNUSED_FUNCTION +bool VBVAIsEnabled(PVGASTATECC pThisCC) +{ + PHGSMIINSTANCE pHGSMI = pThisCC->pHGSMI; + if (pHGSMI) + { + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pHGSMI); + if (pCtx) + { + if (pCtx->cViews) + { + VBVAVIEW * pView = &pCtx->aViews[0]; + if (pView->vbva.guest.pVBVA) + return true; + } + } + } + return false; +} +#endif + +#ifdef DEBUG_sunlover +void dumpMouseShapeInfo(const VBVAMOUSESHAPEINFO *pMouseShapeInfo) +{ + LogFlow(("fSet = %d, fVisible %d, fAlpha %d, @%d,%d %dx%d (%p, %d/%d)\n", + pMouseShapeInfo->fSet, + pMouseShapeInfo->fVisible, + pMouseShapeInfo->fAlpha, + pMouseShapeInfo->u32HotX, + pMouseShapeInfo->u32HotY, + pMouseShapeInfo->u32Width, + pMouseShapeInfo->u32Height, + pMouseShapeInfo->pu8Shape, + pMouseShapeInfo->cbShape, + pMouseShapeInfo->cbAllocated + )); +} +#endif + +static int vbvaUpdateMousePointerShape(PVGASTATECC pThisCC, VBVAMOUSESHAPEINFO *pMouseShapeInfo, bool fShape) +{ + LogFlowFunc(("pThisCC %p, pMouseShapeInfo %p, fShape %d\n", pThisCC, pMouseShapeInfo, fShape)); +#ifdef DEBUG_sunlover + dumpMouseShapeInfo(pMouseShapeInfo); +#endif + + if (pThisCC->pDrv->pfnVBVAMousePointerShape == NULL) + return VERR_NOT_SUPPORTED; + + int rc; + if (fShape && pMouseShapeInfo->pu8Shape != NULL) + rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, + pMouseShapeInfo->fVisible, + pMouseShapeInfo->fAlpha, + pMouseShapeInfo->u32HotX, + pMouseShapeInfo->u32HotY, + pMouseShapeInfo->u32Width, + pMouseShapeInfo->u32Height, + pMouseShapeInfo->pu8Shape); + else + rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, + pMouseShapeInfo->fVisible, + false, + 0, 0, + 0, 0, + NULL); + return rc; +} + +static int vbvaMousePointerShape(PVGASTATECC pThisCC, VBVACONTEXT *pCtx, + const VBVAMOUSEPOINTERSHAPE RT_UNTRUSTED_VOLATILE_GUEST *pShape, HGSMISIZE cbShape) +{ + /* + * Make non-volatile copy of the shape header and validate it. + */ + VBVAMOUSEPOINTERSHAPE SafeShape; + RT_COPY_VOLATILE(SafeShape, *pShape); + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + LogFlowFunc(("VBVA_MOUSE_POINTER_SHAPE: i32Result 0x%x, fu32Flags 0x%x, hot spot %d,%d, size %dx%d\n", + SafeShape.i32Result, SafeShape.fu32Flags, SafeShape.u32HotX, SafeShape.u32HotY, SafeShape.u32Width, SafeShape.u32Height)); + + const bool fVisible = RT_BOOL(SafeShape.fu32Flags & VBOX_MOUSE_POINTER_VISIBLE); + const bool fAlpha = RT_BOOL(SafeShape.fu32Flags & VBOX_MOUSE_POINTER_ALPHA); + const bool fShape = RT_BOOL(SafeShape.fu32Flags & VBOX_MOUSE_POINTER_SHAPE); + + HGSMISIZE cbPointerData = 0; + if (fShape) + { + static const uint32_t s_cxMax = 2048; //used to be: 8192; + static const uint32_t s_cyMax = 2048; //used to be: 8192; + ASSERT_GUEST_MSG_RETURN( SafeShape.u32Width <= s_cxMax + || SafeShape.u32Height <= s_cyMax, + ("Too large: %ux%u, max %ux%x\n", SafeShape.u32Width, SafeShape.u32Height, s_cxMax, s_cyMax), + VERR_INVALID_PARAMETER); + + cbPointerData = ((((SafeShape.u32Width + 7) / 8) * SafeShape.u32Height + 3) & ~3) + + SafeShape.u32Width * 4 * SafeShape.u32Height; + + ASSERT_GUEST_MSG_RETURN(cbPointerData <= cbShape - RT_UOFFSETOF(VBVAMOUSEPOINTERSHAPE, au8Data), + ("Insufficent pointer data: Expected %#x, got %#x\n", + cbPointerData, cbShape - RT_UOFFSETOF(VBVAMOUSEPOINTERSHAPE, au8Data) ), + VERR_INVALID_PARAMETER); + } + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* + * Do the job. + */ + /* Save mouse info it will be used to restore mouse pointer after restoring saved state. */ + pCtx->mouseShapeInfo.fSet = true; + pCtx->mouseShapeInfo.fVisible = fVisible; + if (fShape) + { + /* Data related to shape. */ + pCtx->mouseShapeInfo.u32HotX = SafeShape.u32HotX; + pCtx->mouseShapeInfo.u32HotY = SafeShape.u32HotY; + pCtx->mouseShapeInfo.u32Width = SafeShape.u32Width; + pCtx->mouseShapeInfo.u32Height = SafeShape.u32Height; + pCtx->mouseShapeInfo.fAlpha = fAlpha; + + /* Reallocate memory buffer if necessary. */ + if (cbPointerData > pCtx->mouseShapeInfo.cbAllocated) + { + RTMemFreeZ(pCtx->mouseShapeInfo.pu8Shape, pCtx->mouseShapeInfo.cbAllocated); + pCtx->mouseShapeInfo.pu8Shape = NULL; + pCtx->mouseShapeInfo.cbShape = 0; + + uint8_t *pu8Shape = (uint8_t *)RTMemAlloc(cbPointerData); + if (pu8Shape) + { + pCtx->mouseShapeInfo.pu8Shape = pu8Shape; + pCtx->mouseShapeInfo.cbAllocated = cbPointerData; + } + } + + /* Copy shape bitmaps. */ + if (pCtx->mouseShapeInfo.pu8Shape) + { + RT_BCOPY_VOLATILE(pCtx->mouseShapeInfo.pu8Shape, &pShape->au8Data[0], cbPointerData); + pCtx->mouseShapeInfo.cbShape = cbPointerData; + } + } + + return vbvaUpdateMousePointerShape(pThisCC, &pCtx->mouseShapeInfo, fShape); +} + +static uint32_t vbvaViewFromBufferPtr(PHGSMIINSTANCE pIns, const VBVACONTEXT *pCtx, + const void RT_UNTRUSTED_VOLATILE_GUEST *pvBuffer) +{ + /* Check which view contains the buffer. */ + HGSMIOFFSET offBuffer = HGSMIPointerToOffsetHost(pIns, pvBuffer); + if (offBuffer != HGSMIOFFSET_VOID) + { + unsigned uScreenId; + for (uScreenId = 0; uScreenId < pCtx->cViews; uScreenId++) + { + const VBVAINFOVIEW *pView = &pCtx->aViews[uScreenId].view; + if ((uint32_t)(offBuffer - pView->u32ViewOffset) < pView->u32ViewSize) + return pView->u32ViewIndex; + } + } + return UINT32_MAX; +} + +#ifdef DEBUG_sunlover +static void dumpctx(const VBVACONTEXT *pCtx) +{ + Log(("VBVACONTEXT dump: cViews %d\n", pCtx->cViews)); + + uint32_t iView; + for (iView = 0; iView < pCtx->cViews; iView++) + { + const VBVAVIEW *pView = &pCtx->aViews[iView]; + + Log((" view %d o 0x%x s 0x%x m 0x%x\n", + pView->view.u32ViewIndex, + pView->view.u32ViewOffset, + pView->view.u32ViewSize, + pView->view.u32MaxScreenSize)); + + Log((" screen %d @%d,%d s 0x%x l 0x%x %dx%d bpp %d f 0x%x\n", + pView->screen.u32ViewIndex, + pView->screen.i32OriginX, + pView->screen.i32OriginY, + pView->screen.u32StartOffset, + pView->screen.u32LineSize, + pView->screen.u32Width, + pView->screen.u32Height, + pView->screen.u16BitsPerPixel, + pView->screen.u16Flags)); + + Log((" VBVA o 0x%x p %p\n", + pView->vbva.u32VBVAOffset, + pView->vbva.guest.pVBVA)); + + Log((" PR cb 0x%x p %p\n", + pView->vbva.partialRecord.cb, + pView->vbva.partialRecord.pu8)); + } + + dumpMouseShapeInfo(&pCtx->mouseShapeInfo); +} +#endif /* DEBUG_sunlover */ + +#define VBOXVBVASAVEDSTATE_VHWAAVAILABLE_MAGIC 0x12345678 +#define VBOXVBVASAVEDSTATE_VHWAUNAVAILABLE_MAGIC 0x9abcdef0 + +#ifdef VBOX_WITH_VIDEOHWACCEL + +static void vbvaVHWAHHCommandReinit(VBOXVHWACMD* pHdr, VBOXVHWACMD_TYPE enmCmd, int32_t iDisplay) +{ + memset(pHdr, 0, VBOXVHWACMD_HEADSIZE()); + pHdr->cRefs = 1; + pHdr->iDisplay = iDisplay; + pHdr->rc = VERR_NOT_IMPLEMENTED; + pHdr->enmCmd = enmCmd; + pHdr->Flags = VBOXVHWACMD_FLAG_HH_CMD; +} + +static VBOXVHWACMD *vbvaVHWAHHCommandCreate(VBOXVHWACMD_TYPE enmCmd, int32_t iDisplay, VBOXVHWACMD_LENGTH cbCmd) +{ + VBOXVHWACMD *pHdr = (VBOXVHWACMD *)RTMemAllocZ(cbCmd + VBOXVHWACMD_HEADSIZE()); + Assert(pHdr); + if (pHdr) + vbvaVHWAHHCommandReinit(pHdr, enmCmd, iDisplay); + + return pHdr; +} + +DECLINLINE(void) vbvaVHWAHHCommandRelease(VBOXVHWACMD *pCmd) +{ + uint32_t cRefs = ASMAtomicDecU32(&pCmd->cRefs); + if (!cRefs) + RTMemFree(pCmd); +} + +DECLINLINE(void) vbvaVHWAHHCommandRetain(VBOXVHWACMD *pCmd) +{ + ASMAtomicIncU32(&pCmd->cRefs); +} + +static void vbvaVHWACommandComplete(PVGASTATECC pThisCC, VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand, bool fAsyncCommand) +{ + if (fAsyncCommand) + { + Assert(pCommand->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH); + vbvaR3VHWACommandCompleteAsync(&pThisCC->IVBVACallbacks, pCommand); + } + else + { + Log(("VGA Command <<< Sync rc %d %#p, %d\n", pCommand->rc, pCommand, pCommand->enmCmd)); + pCommand->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH; + } + +} + +static void vbvaVHWACommandCompleteAllPending(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, int rc) +{ + if (!ASMAtomicUoReadU32(&pThis->pendingVhwaCommands.cPending)) + return; + + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + + VBOX_VHWA_PENDINGCMD *pIter, *pNext; + RTListForEachSafe(&pThis->pendingVhwaCommands.PendingList, pIter, pNext, VBOX_VHWA_PENDINGCMD, Node) + { + pIter->pCommand->rc = rc; + vbvaVHWACommandComplete(pThisCC, pIter->pCommand, true); + + /* the command is submitted/processed, remove from the pend list */ + RTListNodeRemove(&pIter->Node); + ASMAtomicDecU32(&pThis->pendingVhwaCommands.cPending); + RTMemFree(pIter); + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); +} + +static void vbvaVHWACommandClearAllPending(PPDMDEVINS pDevIns, PVGASTATE pThis) +{ + if (!ASMAtomicUoReadU32(&pThis->pendingVhwaCommands.cPending)) + return; + + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + + VBOX_VHWA_PENDINGCMD *pIter, *pNext; + RTListForEachSafe(&pThis->pendingVhwaCommands.PendingList, pIter, pNext, VBOX_VHWA_PENDINGCMD, Node) + { + RTListNodeRemove(&pIter->Node); + ASMAtomicDecU32(&pThis->pendingVhwaCommands.cPending); + RTMemFree(pIter); + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); +} + +static void vbvaVHWACommandPend(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand) +{ + int rc = VERR_BUFFER_OVERFLOW; + + if (ASMAtomicUoReadU32(&pThis->pendingVhwaCommands.cPending) < VBOX_VHWA_MAX_PENDING_COMMANDS) + { + VBOX_VHWA_PENDINGCMD *pPend = (VBOX_VHWA_PENDINGCMD *)RTMemAlloc(sizeof(*pPend)); + if (pPend) + { + pCommand->Flags |= VBOXVHWACMD_FLAG_HG_ASYNCH; + pPend->pCommand = pCommand; + + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + + if (ASMAtomicUoReadU32(&pThis->pendingVhwaCommands.cPending) < VBOX_VHWA_MAX_PENDING_COMMANDS) + { + RTListAppend(&pThis->pendingVhwaCommands.PendingList, &pPend->Node); + ASMAtomicIncU32(&pThis->pendingVhwaCommands.cPending); + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return; + } + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + LogRel(("VBVA: Pending command count has reached its threshold.. completing them all..")); + RTMemFree(pPend); + } + else + rc = VERR_NO_MEMORY; + } + else + LogRel(("VBVA: Pending command count has reached its threshold, completing them all..")); + + vbvaVHWACommandCompleteAllPending(pDevIns, pThis, pThisCC, rc); + + pCommand->rc = rc; + + vbvaVHWACommandComplete(pThisCC, pCommand, false); +} + +static bool vbvaVHWACommandCanPend(VBOXVHWACMD_TYPE enmCmd) +{ + switch (enmCmd) + { + case VBOXVHWACMD_TYPE_HH_CONSTRUCT: + case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEBEGIN: + case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEEND: + case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEPERFORM: + case VBOXVHWACMD_TYPE_HH_SAVESTATE_LOADPERFORM: + return false; + default: + return true; + } +} + +static int vbvaVHWACommandSavePending(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM) +{ + int rc = pHlp->pfnSSMPutU32(pSSM, pThis->pendingVhwaCommands.cPending); + AssertRCReturn(rc, rc); + + VBOX_VHWA_PENDINGCMD *pIter; + RTListForEach(&pThis->pendingVhwaCommands.PendingList, pIter, VBOX_VHWA_PENDINGCMD, Node) + { + AssertContinue((uintptr_t)pIter->pCommand - (uintptr_t)pThisCC->pbVRam < pThis->vram_size); + rc = pHlp->pfnSSMPutU32(pSSM, (uint32_t)(((uint8_t *)pIter->pCommand) - ((uint8_t *)pThisCC->pbVRam))); + AssertRCReturn(rc, rc); + } + return rc; +} + +static int vbvaVHWACommandLoadPending(PPDMDEVINS pDevIns, PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, + PSSMHANDLE pSSM, uint32_t u32Version) +{ + if (u32Version < VGA_SAVEDSTATE_VERSION_WITH_PENDVHWA) + return VINF_SUCCESS; + + uint32_t u32; + int rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertRCReturn(rc, rc); + for (uint32_t i = 0; i < u32; ++i) + { + uint32_t off32; + rc = pHlp->pfnSSMGetU32(pSSM, &off32); + AssertRCReturn(rc, rc); + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand + = (VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *)((uint8_t volatile *)pThisCC->pbVRam + off32); + vbvaVHWACommandPend(pDevIns, pThis, pThisCC, pCommand); + } + return rc; +} + + +/** Worker for vbvaVHWACommandSubmit. */ +static bool vbvaVHWACommandSubmitInner(PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand, bool *pfPending) +{ + *pfPending = false; + + /* + * Read the command type and validate it and our driver state. + */ + VBOXVHWACMD_TYPE enmCmd = pCommand->enmCmd; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + bool fGuestCmd = (uintptr_t)pCommand - (uintptr_t)pThisCC->pbVRam < pThis->vram_size; + ASSERT_GUEST_LOGREL_MSG_STMT_RETURN( !fGuestCmd + || ( enmCmd != VBOXVHWACMD_TYPE_HH_CONSTRUCT + && enmCmd != VBOXVHWACMD_TYPE_HH_RESET + && enmCmd != VBOXVHWACMD_TYPE_HH_DISABLE + && enmCmd != VBOXVHWACMD_TYPE_HH_ENABLE + && enmCmd != VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEBEGIN + && enmCmd != VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEEND + && enmCmd != VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEPERFORM + && enmCmd != VBOXVHWACMD_TYPE_HH_SAVESTATE_LOADPERFORM), + ("enmCmd=%d\n", enmCmd), + pCommand->rc = VERR_INVALID_PARAMETER, + true); + ASSERT_GUEST_STMT_RETURN(pThisCC->pDrv->pfnVHWACommandProcess, pCommand->rc = VERR_INVALID_STATE, true); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* + * Call the driver to process the command. + */ + Log(("VGA Command >>> %#p, %d\n", pCommand, enmCmd)); + int rc = pThisCC->pDrv->pfnVHWACommandProcess(pThisCC->pDrv, enmCmd, fGuestCmd, pCommand); + if (rc == VINF_CALLBACK_RETURN) + { + Log(("VGA Command --- Going Async %#p, %d\n", pCommand, enmCmd)); + *pfPending = true; + return true; /* Command will be completed asynchronously by the driver and need not be put in the pending list. */ + } + + if (rc == VERR_INVALID_STATE) + { + Log(("VGA Command --- Trying Pend %#p, %d\n", pCommand, enmCmd)); + if (vbvaVHWACommandCanPend(enmCmd)) + { + Log(("VGA Command --- Can Pend %#p, %d\n", pCommand, enmCmd)); + *pfPending = true; + return false; /* put on pending list so it can be retried?? */ + } + + Log(("VGA Command --- Can NOT Pend %#p, %d\n", pCommand, enmCmd)); + } + else + Log(("VGA Command --- Going Complete Sync rc %d %#p, %d\n", rc, pCommand, enmCmd)); + + /* the command was completed, take a special care about it (see caller) */ + pCommand->rc = rc; + return true; +} + + +static bool vbvaVHWACommandSubmit(PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand, bool fAsyncCommand) +{ + bool fPending = false; + bool fRet = vbvaVHWACommandSubmitInner(pThis, pThisCC, pCommand, &fPending); + if (!fPending) + vbvaVHWACommandComplete(pThisCC, pCommand, fAsyncCommand); + return fRet; +} + + +/** + * @returns false if commands are pending, otherwise true. + */ +static bool vbvaVHWACheckPendingCommands(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + if (!ASMAtomicUoReadU32(&pThis->pendingVhwaCommands.cPending)) + return true; + + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock); + + VBOX_VHWA_PENDINGCMD *pIter, *pNext; + RTListForEachSafe(&pThis->pendingVhwaCommands.PendingList, pIter, pNext, VBOX_VHWA_PENDINGCMD, Node) + { + if (!vbvaVHWACommandSubmit(pThis, pThisCC, pIter->pCommand, true)) + { + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return false; /* the command should be still pending */ + } + + /* the command is submitted/processed, remove from the pend list */ + RTListNodeRemove(&pIter->Node); + ASMAtomicDecU32(&pThis->pendingVhwaCommands.cPending); + RTMemFree(pIter); + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + + return true; +} + +void vbvaTimerCb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + vbvaVHWACheckPendingCommands(pDevIns, pThis, pThisCC); +} + +static void vbvaVHWAHandleCommand(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd) +{ + if (vbvaVHWACheckPendingCommands(pDevIns, pThis, pThisCC)) + { + if (vbvaVHWACommandSubmit(pThis, pThisCC, pCmd, false)) + return; + } + + vbvaVHWACommandPend(pDevIns, pThis, pThisCC, pCmd); +} + +static DECLCALLBACK(void) vbvaVHWAHHCommandSetEventCallback(void * pContext) +{ + RTSemEventSignal((RTSEMEVENT)pContext); +} + +static int vbvaVHWAHHCommandPost(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, VBOXVHWACMD *pCmd) +{ + RTSEMEVENT hComplEvent; + int rc = RTSemEventCreate(&hComplEvent); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + /* ensure the cmd is not deleted until we process it */ + vbvaVHWAHHCommandRetain(pCmd); + + VBOXVHWA_HH_CALLBACK_SET(pCmd, vbvaVHWAHHCommandSetEventCallback, (void *)hComplEvent); + vbvaVHWAHandleCommand(pDevIns, pThis, pThisCC, pCmd); + + if ((ASMAtomicReadU32((volatile uint32_t *)&pCmd->Flags) & VBOXVHWACMD_FLAG_HG_ASYNCH) != 0) + rc = RTSemEventWaitNoResume(hComplEvent, RT_INDEFINITE_WAIT); /** @todo Why the NoResume and event leaking here? */ + /* else: the command is completed */ + + AssertRC(rc); + if (RT_SUCCESS(rc)) + RTSemEventDestroy(hComplEvent); + + vbvaVHWAHHCommandRelease(pCmd); + } + return rc; +} + +int vbvaVHWAConstruct(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + pThis->pendingVhwaCommands.cPending = 0; + RTListInit(&pThis->pendingVhwaCommands.PendingList); + + VBOXVHWACMD *pCmd = vbvaVHWAHHCommandCreate(VBOXVHWACMD_TYPE_HH_CONSTRUCT, 0, sizeof(VBOXVHWACMD_HH_CONSTRUCT)); + Assert(pCmd); + if(pCmd) + { + uint32_t iDisplay = 0; + int rc = VINF_SUCCESS; + VBOXVHWACMD_HH_CONSTRUCT *pBody = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_CONSTRUCT); + + for (;;) + { + memset(pBody, 0, sizeof(VBOXVHWACMD_HH_CONSTRUCT)); + + PVM pVM = PDMDevHlpGetVM(pDevIns); + + pBody->pVM = pVM; + pBody->pvVRAM = pThisCC->pbVRam; + pBody->cbVRAM = pThis->vram_size; + + rc = vbvaVHWAHHCommandPost(pDevIns, pThis, pThisCC, pCmd); + ASMCompilerBarrier(); + + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + rc = pCmd->rc; + AssertMsg(RT_SUCCESS(rc) || rc == VERR_NOT_IMPLEMENTED, ("%Rrc\n", rc)); + if(rc == VERR_NOT_IMPLEMENTED) + { + /** @todo set some flag in pThis indicating VHWA is not supported */ + /* VERR_NOT_IMPLEMENTED is not a failure, we just do not support it */ + rc = VINF_SUCCESS; + } + + if (!RT_SUCCESS(rc)) + break; + } + else + break; + + ++iDisplay; + if (iDisplay >= pThis->cMonitors) + break; + vbvaVHWAHHCommandReinit(pCmd, VBOXVHWACMD_TYPE_HH_CONSTRUCT, (int32_t)iDisplay); + } + + vbvaVHWAHHCommandRelease(pCmd); + + return rc; + } + return VERR_OUT_OF_RESOURCES; +} + +static int vbvaVHWAReset(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + vbvaVHWACommandClearAllPending(pDevIns, pThis); + + /* ensure we have all pending cmds processed and h->g cmds disabled */ + VBOXVHWACMD *pCmd = vbvaVHWAHHCommandCreate(VBOXVHWACMD_TYPE_HH_RESET, 0, 0); + Assert(pCmd); + if (pCmd) + { + int rc = VINF_SUCCESS; + uint32_t iDisplay = 0; + + do + { + rc = vbvaVHWAHHCommandPost(pDevIns, pThis, pThisCC, pCmd); + AssertRC(rc); + if(RT_SUCCESS(rc)) + { + rc = pCmd->rc; + AssertMsg(RT_SUCCESS(rc) || rc == VERR_NOT_IMPLEMENTED, ("%Rrc\n", rc)); + if (rc == VERR_NOT_IMPLEMENTED) + rc = VINF_SUCCESS; + } + + if (!RT_SUCCESS(rc)) + break; + + ++iDisplay; + if (iDisplay >= pThis->cMonitors) + break; + vbvaVHWAHHCommandReinit(pCmd, VBOXVHWACMD_TYPE_HH_RESET, (int32_t)iDisplay); + + } while (true); + + vbvaVHWAHHCommandRelease(pCmd); + + return rc; + } + return VERR_OUT_OF_RESOURCES; +} + +typedef DECLCALLBACKTYPE(bool, FNVBOXVHWAHHCMDPRECB,(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, VBOXVHWACMD *pCmd, + uint32_t iDisplay, void *pvContext)); +typedef FNVBOXVHWAHHCMDPRECB *PFNVBOXVHWAHHCMDPRECB; + +typedef DECLCALLBACKTYPE(bool, FNVBOXVHWAHHCMDPOSTCB,(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, VBOXVHWACMD *pCmd, + uint32_t iDisplay, int rc, void *pvContext)); +typedef FNVBOXVHWAHHCMDPOSTCB *PFNVBOXVHWAHHCMDPOSTCB; + +static int vbvaVHWAHHPost(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, VBOXVHWACMD *pCmd, + PFNVBOXVHWAHHCMDPRECB pfnPre, PFNVBOXVHWAHHCMDPOSTCB pfnPost, void *pvContext) +{ + const VBOXVHWACMD_TYPE enmType = pCmd->enmCmd; + int rc = VINF_SUCCESS; + uint32_t iDisplay = 0; + + do + { + if (!pfnPre || pfnPre(pDevIns, pThis, pThisCC, pCmd, iDisplay, pvContext)) + { + rc = vbvaVHWAHHCommandPost(pDevIns, pThis, pThisCC, pCmd); + AssertRC(rc); + if (pfnPost) + { + if (!pfnPost(pDevIns, pThis, pThisCC, pCmd, iDisplay, rc, pvContext)) + { + rc = VINF_SUCCESS; + break; + } + rc = VINF_SUCCESS; + } + else if(RT_SUCCESS(rc)) + { + rc = pCmd->rc; + AssertMsg(RT_SUCCESS(rc) || rc == VERR_NOT_IMPLEMENTED, ("%Rrc\n", rc)); + if(rc == VERR_NOT_IMPLEMENTED) + { + rc = VINF_SUCCESS; + } + } + + if (!RT_SUCCESS(rc)) + break; + } + + ++iDisplay; + if (iDisplay >= pThis->cMonitors) + break; + vbvaVHWAHHCommandReinit(pCmd, enmType, (int32_t)iDisplay); + } while (true); + + return rc; +} + +/** @todo call this also on reset? */ +static int vbvaVHWAEnable(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, bool bEnable) +{ + const VBOXVHWACMD_TYPE enmType = bEnable ? VBOXVHWACMD_TYPE_HH_ENABLE : VBOXVHWACMD_TYPE_HH_DISABLE; + VBOXVHWACMD *pCmd = vbvaVHWAHHCommandCreate(enmType, 0, 0); + Assert(pCmd); + if(pCmd) + { + int rc = vbvaVHWAHHPost(pDevIns, pThis, pThisCC, pCmd, NULL, NULL, NULL); + vbvaVHWAHHCommandRelease(pCmd); + return rc; + } + return VERR_OUT_OF_RESOURCES; +} + +int vboxVBVASaveStatePrep(PPDMDEVINS pDevIns) +{ + /* ensure we have no pending commands */ + return vbvaVHWAEnable(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), false); +} + +int vboxVBVASaveStateDone(PPDMDEVINS pDevIns) +{ + /* ensure we have no pending commands */ + return vbvaVHWAEnable(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), true); +} + + +/** + * @interface_method_impl{PDMIDISPLAYVBVACALLBACKS,pfnVHWACommandCompleteAsync} + */ +DECLCALLBACK(int) vbvaR3VHWACommandCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IVBVACallbacks); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + int rc; + + Log(("VGA Command <<< Async rc %d %#p, %d\n", pCmd->rc, pCmd, pCmd->enmCmd)); + + if ((uintptr_t)pCmd - (uintptr_t)pThisCC->pbVRam < pThis->vram_size) + { + PHGSMIINSTANCE pIns = pThisCC->pHGSMI; + Assert(!(pCmd->Flags & VBOXVHWACMD_FLAG_HH_CMD)); + Assert(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH); +#ifdef VBOX_WITH_WDDM + if (pThis->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD) + { + rc = HGSMICompleteGuestCommand(pIns, pCmd, !!(pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ)); + AssertRC(rc); + } + else +#endif + { + VBVAHOSTCMD RT_UNTRUSTED_VOLATILE_GUEST *pHostCmd = NULL; /* Shut up MSC. */ + if (pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT) + { + rc = HGSMIHostCommandAlloc(pIns, + (void RT_UNTRUSTED_VOLATILE_GUEST **)&pHostCmd, + VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDEVENT)), + HGSMI_CH_VBVA, + VBVAHG_EVENT); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + memset((void *)pHostCmd, 0 , VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDEVENT))); + pHostCmd->iDstID = pCmd->iDisplay; + pHostCmd->customOpCode = 0; + VBVAHOSTCMDEVENT RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBVAHOSTCMD_BODY(pHostCmd, VBVAHOSTCMDEVENT); + pBody->pEvent = pCmd->GuestVBVAReserved1; + } + } + else + { + HGSMIOFFSET offCmd = HGSMIPointerToOffsetHost(pIns, pCmd); + Assert(offCmd != HGSMIOFFSET_VOID); + if (offCmd != HGSMIOFFSET_VOID) + { + rc = HGSMIHostCommandAlloc(pIns, + (void RT_UNTRUSTED_VOLATILE_GUEST **)&pHostCmd, + VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDVHWACMDCOMPLETE)), + HGSMI_CH_VBVA, + VBVAHG_DISPLAY_CUSTOM); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + memset((void *)pHostCmd, 0 , VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDVHWACMDCOMPLETE))); + pHostCmd->iDstID = pCmd->iDisplay; + pHostCmd->customOpCode = VBVAHG_DCUSTOM_VHWA_CMDCOMPLETE; + VBVAHOSTCMDVHWACMDCOMPLETE RT_UNTRUSTED_VOLATILE_GUEST *pBody + = VBVAHOSTCMD_BODY(pHostCmd, VBVAHOSTCMDVHWACMDCOMPLETE); + pBody->offCmd = offCmd; + } + } + else + rc = VERR_INVALID_PARAMETER; + } + + if (RT_SUCCESS(rc)) + { + rc = HGSMIHostCommandSubmitAndFreeAsynch(pIns, pHostCmd, RT_BOOL(pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ)); + AssertRC(rc); + if (RT_SUCCESS(rc)) + return rc; + + HGSMIHostCommandFree (pIns, pHostCmd); + } + } + } + else + { + Assert(pCmd->Flags & VBOXVHWACMD_FLAG_HH_CMD); + PFNVBOXVHWA_HH_CALLBACK pfn = VBOXVHWA_HH_CALLBACK_GET(pCmd); + if (pfn) + pfn(VBOXVHWA_HH_CALLBACK_GET_ARG(pCmd)); + rc = VINF_SUCCESS; + } + return rc; +} + +typedef struct VBOXVBVASAVEDSTATECBDATA +{ + PSSMHANDLE pSSM; + int rc; + bool ab2DOn[VBOX_VIDEO_MAX_SCREENS]; +} VBOXVBVASAVEDSTATECBDATA, *PVBOXVBVASAVEDSTATECBDATA; + +/** + * @callback_method_impl{FNVBOXVHWAHHCMDPOSTCB} + */ +static DECLCALLBACK(bool) vboxVBVASaveStateBeginPostCb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD *pCmd, uint32_t iDisplay, int rc, void *pvContext) +{ + RT_NOREF(pDevIns, pThis, pThisCC, pCmd); + PVBOXVBVASAVEDSTATECBDATA pData = (PVBOXVBVASAVEDSTATECBDATA)pvContext; + if (RT_FAILURE(pData->rc)) + return false; + if (RT_FAILURE(rc)) + { + pData->rc = rc; + return false; + } + + Assert(iDisplay < RT_ELEMENTS(pData->ab2DOn)); + if (iDisplay >= RT_ELEMENTS(pData->ab2DOn)) + { + pData->rc = VERR_INVALID_PARAMETER; + return false; + } + + Assert(RT_SUCCESS(pCmd->rc) || pCmd->rc == VERR_NOT_IMPLEMENTED); + if (RT_SUCCESS(pCmd->rc)) + { + pData->ab2DOn[iDisplay] = true; + } + else if (pCmd->rc != VERR_NOT_IMPLEMENTED) + { + pData->rc = pCmd->rc; + return false; + } + + return true; +} + +/** + * @callback_method_impl{FNVBOXVHWAHHCMDPRECB} + */ +static DECLCALLBACK(bool) vboxVBVASaveStatePerformPreCb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD *pCmd, uint32_t iDisplay, void *pvContext) +{ + RT_NOREF(pThis, pThisCC, pCmd); + PVBOXVBVASAVEDSTATECBDATA pData = (PVBOXVBVASAVEDSTATECBDATA)pvContext; + if (RT_FAILURE(pData->rc)) + return false; + + Assert(iDisplay < RT_ELEMENTS(pData->ab2DOn)); + if (iDisplay >= RT_ELEMENTS(pData->ab2DOn)) + { + pData->rc = VERR_INVALID_PARAMETER; + return false; + } + + int rc; + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + + if (pData->ab2DOn[iDisplay]) + { + rc = pHlp->pfnSSMPutU32(pData->pSSM, VBOXVBVASAVEDSTATE_VHWAAVAILABLE_MAGIC); AssertRC(rc); + if (RT_FAILURE(rc)) + { + pData->rc = rc; + return false; + } + return true; + } + + rc = pHlp->pfnSSMPutU32(pData->pSSM, VBOXVBVASAVEDSTATE_VHWAUNAVAILABLE_MAGIC); AssertRC(rc); + if (RT_FAILURE(rc)) + { + pData->rc = rc; + return false; + } + + return false; +} + +/** + * @callback_method_impl{FNVBOXVHWAHHCMDPOSTCB} + */ +static DECLCALLBACK(bool) vboxVBVASaveStateEndPreCb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD *pCmd, uint32_t iDisplay, void *pvContext) +{ + RT_NOREF(pDevIns, pThis, pThisCC, pCmd); + PVBOXVBVASAVEDSTATECBDATA pData = (PVBOXVBVASAVEDSTATECBDATA)pvContext; + Assert(iDisplay < RT_ELEMENTS(pData->ab2DOn)); + if (pData->ab2DOn[iDisplay]) + return true; + return false; +} + +/** + * @callback_method_impl{FNVBOXVHWAHHCMDPOSTCB} + */ +static DECLCALLBACK(bool) vboxVBVALoadStatePerformPostCb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD *pCmd, uint32_t iDisplay, int rc, void *pvContext) +{ + RT_NOREF(pThis, pThisCC, pCmd); + PVBOXVBVASAVEDSTATECBDATA pData = (PVBOXVBVASAVEDSTATECBDATA)pvContext; + if (RT_FAILURE(pData->rc)) + return false; + if (RT_FAILURE(rc)) + { + pData->rc = rc; + return false; + } + + Assert(iDisplay < RT_ELEMENTS(pData->ab2DOn)); + if (iDisplay >= RT_ELEMENTS(pData->ab2DOn)) + { + pData->rc = VERR_INVALID_PARAMETER; + return false; + } + + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + Assert(RT_SUCCESS(pCmd->rc) || pCmd->rc == VERR_NOT_IMPLEMENTED); + if (pCmd->rc == VERR_NOT_IMPLEMENTED) + { + pData->rc = pHlp->pfnSSMSkipToEndOfUnit(pData->pSSM); + AssertRC(pData->rc); + return false; + } + if (RT_FAILURE(pCmd->rc)) + { + pData->rc = pCmd->rc; + return false; + } + + return true; +} + +/** + * @callback_method_impl{FNVBOXVHWAHHCMDPOSTCB} + */ +static DECLCALLBACK(bool) vboxVBVALoadStatePerformPreCb(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + VBOXVHWACMD *pCmd, uint32_t iDisplay, void *pvContext) +{ + RT_NOREF(pThis, pThisCC, pCmd); + PVBOXVBVASAVEDSTATECBDATA pData = (PVBOXVBVASAVEDSTATECBDATA)pvContext; + if (RT_FAILURE(pData->rc)) + return false; + + Assert(iDisplay < RT_ELEMENTS(pData->ab2DOn)); + if (iDisplay >= RT_ELEMENTS(pData->ab2DOn)) + { + pData->rc = VERR_INVALID_PARAMETER; + return false; + } + + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc; + uint32_t u32; + rc = pHlp->pfnSSMGetU32(pData->pSSM, &u32); AssertRC(rc); + if (RT_FAILURE(rc)) + { + pData->rc = rc; + return false; + } + + switch (u32) + { + case VBOXVBVASAVEDSTATE_VHWAAVAILABLE_MAGIC: + pData->ab2DOn[iDisplay] = true; + return true; + case VBOXVBVASAVEDSTATE_VHWAUNAVAILABLE_MAGIC: + pData->ab2DOn[iDisplay] = false; + return false; + default: + pData->rc = VERR_INVALID_STATE; + return false; + } +} + +#endif /* VBOX_WITH_VIDEOHWACCEL */ + +static int vboxVBVASaveDevStateExec(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM) +{ + PHGSMIINSTANCE pIns = pThisCC->pHGSMI; + int rc = HGSMIHostSaveStateExec(pHlp, pIns, pSSM); + if (RT_SUCCESS(rc)) + { + VGA_SAVED_STATE_PUT_MARKER(pSSM, 2); + + /* Save VBVACONTEXT. */ + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext (pIns); + + if (!pCtx) + { + AssertFailed(); + + /* Still write a valid value to the SSM. */ + rc = pHlp->pfnSSMPutU32 (pSSM, 0); + AssertRCReturn(rc, rc); + } + else + { +#ifdef DEBUG_sunlover + dumpctx(pCtx); +#endif + + rc = pHlp->pfnSSMPutU32 (pSSM, pCtx->cViews); + AssertRCReturn(rc, rc); + + uint32_t iView; + for (iView = 0; iView < pCtx->cViews; iView++) + { + VBVAVIEW *pView = &pCtx->aViews[iView]; + + rc = pHlp->pfnSSMPutU32(pSSM, pView->view.u32ViewIndex); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pView->view.u32ViewOffset); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pView->view.u32ViewSize); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pView->view.u32MaxScreenSize); + AssertRCReturn(rc, rc); + + rc = pHlp->pfnSSMPutU32(pSSM, pView->screen.u32ViewIndex); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutS32(pSSM, pView->screen.i32OriginX); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutS32(pSSM, pView->screen.i32OriginY); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pView->screen.u32StartOffset); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pView->screen.u32LineSize); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pView->screen.u32Width); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pView->screen.u32Height); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU16(pSSM, pView->screen.u16BitsPerPixel); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU16(pSSM, pView->screen.u16Flags); + AssertRCReturn(rc, rc); + + rc = pHlp->pfnSSMPutU32(pSSM, pView->vbva.guest.pVBVA? pView->vbva.u32VBVAOffset: HGSMIOFFSET_VOID); + AssertRCReturn(rc, rc); + + rc = pHlp->pfnSSMPutU32(pSSM, pView->vbva.partialRecord.cb); + AssertRCReturn(rc, rc); + + if (pView->vbva.partialRecord.cb > 0) + { + rc = pHlp->pfnSSMPutMem(pSSM, pView->vbva.partialRecord.pu8, pView->vbva.partialRecord.cb); + AssertRCReturn(rc, rc); + } + } + + /* Save mouse pointer shape information. */ + rc = pHlp->pfnSSMPutBool(pSSM, pCtx->mouseShapeInfo.fSet); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutBool(pSSM, pCtx->mouseShapeInfo.fVisible); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutBool(pSSM, pCtx->mouseShapeInfo.fAlpha); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pCtx->mouseShapeInfo.u32HotX); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pCtx->mouseShapeInfo.u32HotY); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pCtx->mouseShapeInfo.u32Width); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pCtx->mouseShapeInfo.u32Height); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pCtx->mouseShapeInfo.cbShape); + AssertRCReturn(rc, rc); + if (pCtx->mouseShapeInfo.cbShape) + { + rc = pHlp->pfnSSMPutMem(pSSM, pCtx->mouseShapeInfo.pu8Shape, pCtx->mouseShapeInfo.cbShape); + AssertRCReturn(rc, rc); + } + +#ifdef VBOX_WITH_WDDM + /* Size of some additional data. For future extensions. */ + rc = pHlp->pfnSSMPutU32(pSSM, 4); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, pThis->fGuestCaps); + AssertRCReturn(rc, rc); +#else + /* Size of some additional data. For future extensions. */ + rc = pHlp->pfnSSMPutU32(pSSM, 0); + AssertRCReturn(rc, rc); +#endif + rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pCtx->aModeHints)); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMPutU32(pSSM, sizeof(VBVAMODEHINT)); + AssertRCReturn(rc, rc); + for (unsigned i = 0; i < RT_ELEMENTS(pCtx->aModeHints); ++i) + { + rc = pHlp->pfnSSMPutMem(pSSM, &pCtx->aModeHints[i], sizeof(VBVAMODEHINT)); + AssertRCReturn(rc, rc); + } + } + } + + return rc; +} + +int vboxVBVASaveStateExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc; +#ifdef VBOX_WITH_VIDEOHWACCEL + VBOXVBVASAVEDSTATECBDATA VhwaData = {0}; + VhwaData.pSSM = pSSM; + uint32_t cbCmd = sizeof (VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM); /* maximum cmd size */ + VBOXVHWACMD *pCmd = vbvaVHWAHHCommandCreate(VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEBEGIN, 0, cbCmd); + Assert(pCmd); + if (pCmd) + { + vbvaVHWAHHPost(pDevIns, pThis, pThisCC, pCmd, NULL, vboxVBVASaveStateBeginPostCb, &VhwaData); + rc = VhwaData.rc; + AssertRC(rc); + if (RT_SUCCESS(rc)) + { +#endif + rc = vboxVBVASaveDevStateExec(pHlp, pThis, pThisCC, pSSM); + AssertRC(rc); +#ifdef VBOX_WITH_VIDEOHWACCEL + if (RT_SUCCESS(rc)) + { + vbvaVHWAHHCommandReinit(pCmd, VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEPERFORM, 0); + VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM *pSave = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM); + pSave->pSSM = pSSM; + vbvaVHWAHHPost(pDevIns, pThis, pThisCC, pCmd, vboxVBVASaveStatePerformPreCb, NULL, &VhwaData); + rc = VhwaData.rc; + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + rc = vbvaVHWACommandSavePending(pHlp, pThis, pThisCC, pSSM); + AssertRCReturn(rc, rc); + + vbvaVHWAHHCommandReinit(pCmd, VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEEND, 0); + vbvaVHWAHHPost(pDevIns, pThis, pThisCC, pCmd, vboxVBVASaveStateEndPreCb, NULL, &VhwaData); + rc = VhwaData.rc; + AssertRC(rc); + } + } + } + + vbvaVHWAHHCommandRelease(pCmd); + } + else + rc = VERR_OUT_OF_RESOURCES; +#else + if (RT_SUCCESS(rc)) + { + for (uint32_t i = 0; i < pThis->cMonitors; ++i) + { + rc = pHlp->pfnSSMPutU32(pSSM, VBOXVBVASAVEDSTATE_VHWAUNAVAILABLE_MAGIC); + AssertRCReturn(rc, rc); + } + } + + /* no pending commands */ + pHlp->pfnSSMPutU32(pSSM, 0); +#endif + return rc; +} + +int vboxVBVALoadStateExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion) +{ + if (uVersion < VGA_SAVEDSTATE_VERSION_HGSMI) + { + /* Nothing was saved. */ + return VINF_SUCCESS; + } + + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PHGSMIINSTANCE pIns = pThisCC->pHGSMI; + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + int rc = HGSMIHostLoadStateExec(pHlp, pIns, pSSM, uVersion); + if (RT_SUCCESS(rc)) + { + VGA_SAVED_STATE_GET_MARKER_RETURN_ON_MISMATCH(pSSM, uVersion, 2); + + /* Load VBVACONTEXT. */ + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext (pIns); + + if (!pCtx) + { + /* This should not happen. */ + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + else + { + uint32_t cViews = 0; + rc = pHlp->pfnSSMGetU32 (pSSM, &cViews); + AssertRCReturn(rc, rc); + + uint32_t iView; + for (iView = 0; iView < cViews; iView++) + { + VBVAVIEW *pView = &pCtx->aViews[iView]; + + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->view.u32ViewIndex); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->view.u32ViewOffset); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->view.u32ViewSize); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->view.u32MaxScreenSize); + AssertRCReturn(rc, rc); + + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->screen.u32ViewIndex); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetS32 (pSSM, &pView->screen.i32OriginX); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetS32 (pSSM, &pView->screen.i32OriginY); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->screen.u32StartOffset); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->screen.u32LineSize); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->screen.u32Width); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->screen.u32Height); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU16 (pSSM, &pView->screen.u16BitsPerPixel); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU16 (pSSM, &pView->screen.u16Flags); + AssertRCReturn(rc, rc); + + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->vbva.u32VBVAOffset); + AssertRCReturn(rc, rc); + + rc = pHlp->pfnSSMGetU32 (pSSM, &pView->vbva.partialRecord.cb); + AssertRCReturn(rc, rc); + + if (pView->vbva.partialRecord.cb == 0) + { + pView->vbva.partialRecord.pu8 = NULL; + } + else + { + Assert(pView->vbva.partialRecord.pu8 == NULL); /* Should be it. */ + + uint8_t *pu8 = (uint8_t *)RTMemAlloc(pView->vbva.partialRecord.cb); + + if (!pu8) + { + return VERR_NO_MEMORY; + } + + pView->vbva.partialRecord.pu8 = pu8; + + rc = pHlp->pfnSSMGetMem (pSSM, pView->vbva.partialRecord.pu8, pView->vbva.partialRecord.cb); + AssertRCReturn(rc, rc); + } + + if (pView->vbva.u32VBVAOffset == HGSMIOFFSET_VOID) + { + pView->vbva.guest.pVBVA = NULL; + } + else + { + pView->vbva.guest.pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost(pIns, pView->vbva.u32VBVAOffset); + } + } + + if (uVersion > VGA_SAVEDSTATE_VERSION_WITH_CONFIG) + { + /* Read mouse pointer shape information. */ + rc = pHlp->pfnSSMGetBool (pSSM, &pCtx->mouseShapeInfo.fSet); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetBool (pSSM, &pCtx->mouseShapeInfo.fVisible); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetBool (pSSM, &pCtx->mouseShapeInfo.fAlpha); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pCtx->mouseShapeInfo.u32HotX); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pCtx->mouseShapeInfo.u32HotY); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pCtx->mouseShapeInfo.u32Width); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pCtx->mouseShapeInfo.u32Height); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &pCtx->mouseShapeInfo.cbShape); + AssertRCReturn(rc, rc); + if (pCtx->mouseShapeInfo.cbShape) + { + pCtx->mouseShapeInfo.pu8Shape = (uint8_t *)RTMemAlloc(pCtx->mouseShapeInfo.cbShape); + if (pCtx->mouseShapeInfo.pu8Shape == NULL) + { + return VERR_NO_MEMORY; + } + pCtx->mouseShapeInfo.cbAllocated = pCtx->mouseShapeInfo.cbShape; + rc = pHlp->pfnSSMGetMem (pSSM, pCtx->mouseShapeInfo.pu8Shape, pCtx->mouseShapeInfo.cbShape); + AssertRCReturn(rc, rc); + } + else + { + pCtx->mouseShapeInfo.pu8Shape = NULL; + } + + /* Size of some additional data. For future extensions. */ + uint32_t cbExtra = 0; + rc = pHlp->pfnSSMGetU32 (pSSM, &cbExtra); + AssertRCReturn(rc, rc); +#ifdef VBOX_WITH_WDDM + if (cbExtra >= 4) + { + rc = pHlp->pfnSSMGetU32 (pSSM, &pThis->fGuestCaps); + AssertRCReturn(rc, rc); + pThisCC->pDrv->pfnVBVAGuestCapabilityUpdate(pThisCC->pDrv, pThis->fGuestCaps); + cbExtra -= 4; + } +#endif + if (cbExtra > 0) + { + rc = pHlp->pfnSSMSkip(pSSM, cbExtra); + AssertRCReturn(rc, rc); + } + + if (uVersion >= VGA_SAVEDSTATE_VERSION_MODE_HINTS) + { + uint32_t cModeHints, cbModeHints; + rc = pHlp->pfnSSMGetU32 (pSSM, &cModeHints); + AssertRCReturn(rc, rc); + rc = pHlp->pfnSSMGetU32 (pSSM, &cbModeHints); + AssertRCReturn(rc, rc); + memset(&pCtx->aModeHints, ~0, sizeof(pCtx->aModeHints)); + unsigned iHint; + for (iHint = 0; iHint < cModeHints; ++iHint) + { + if ( cbModeHints <= sizeof(VBVAMODEHINT) + && iHint < RT_ELEMENTS(pCtx->aModeHints)) + rc = pHlp->pfnSSMGetMem(pSSM, &pCtx->aModeHints[iHint], + cbModeHints); + else + rc = pHlp->pfnSSMSkip(pSSM, cbModeHints); + AssertRCReturn(rc, rc); + } + } + } + + pCtx->cViews = iView; + LogFlowFunc(("%d views loaded\n", pCtx->cViews)); + + if (uVersion > VGA_SAVEDSTATE_VERSION_WDDM) + { + bool fLoadCommands; + + if (uVersion < VGA_SAVEDSTATE_VERSION_FIXED_PENDVHWA) + { + const char *pcszOsArch = pHlp->pfnSSMHandleHostOSAndArch(pSSM); + Assert(pcszOsArch); + fLoadCommands = !pcszOsArch || RTStrNCmp(pcszOsArch, RT_STR_TUPLE("solaris")); + } + else + fLoadCommands = true; + +#ifdef VBOX_WITH_VIDEOHWACCEL + uint32_t cbCmd = sizeof (VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM); /* maximum cmd size */ + VBOXVHWACMD *pCmd = vbvaVHWAHHCommandCreate(VBOXVHWACMD_TYPE_HH_SAVESTATE_LOADPERFORM, 0, cbCmd); + Assert(pCmd); + if(pCmd) + { + VBOXVBVASAVEDSTATECBDATA VhwaData = {0}; + VhwaData.pSSM = pSSM; + VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM *pLoad = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM); + pLoad->pSSM = pSSM; + vbvaVHWAHHPost(pDevIns, pThis, pThisCC, pCmd, vboxVBVALoadStatePerformPreCb, + vboxVBVALoadStatePerformPostCb, &VhwaData); + rc = VhwaData.rc; + vbvaVHWAHHCommandRelease(pCmd); + AssertRCReturn(rc, rc); + + if (fLoadCommands) + { + rc = vbvaVHWACommandLoadPending(pDevIns, pHlp, pThis, pThisCC, pSSM, uVersion); + AssertRCReturn(rc, rc); + } + } + else + { + rc = VERR_OUT_OF_RESOURCES; + } +#else + uint32_t u32; + + for (uint32_t i = 0; i < pThis->cMonitors; ++i) + { + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertRCReturn(rc, rc); + + if (u32 != VBOXVBVASAVEDSTATE_VHWAUNAVAILABLE_MAGIC) + { + LogRel(("VBVA: 2D data while 2D is not supported\n")); + return VERR_NOT_SUPPORTED; + } + } + + if (fLoadCommands) + { + rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertRCReturn(rc, rc); + + if (u32) + { + LogRel(("VBVA: 2D pending command while 2D is not supported\n")); + return VERR_NOT_SUPPORTED; + } + } +#endif + } + +#ifdef DEBUG_sunlover + dumpctx(pCtx); +#endif + } + } + + return rc; +} + +int vboxVBVALoadStateDone(PPDMDEVINS pDevIns) +{ + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + if (pCtx) + { + uint32_t iView; + for (iView = 0; iView < pCtx->cViews; iView++) + { + VBVAVIEW *pView = &pCtx->aViews[iView]; + if (pView->vbva.guest.pVBVA) + { + int rc = vbvaEnable(pThis, pThisCC, pCtx, iView, pView->vbva.guest.pVBVA, + pView->vbva.u32VBVAOffset, true /* fRestored */); + if (RT_SUCCESS(rc)) + vbvaResize(pThisCC, pView, &pView->screen, false); + else + LogRel(("VBVA: can not restore: %Rrc\n", rc)); + } + } + + if (pCtx->mouseShapeInfo.fSet) + vbvaUpdateMousePointerShape(pThisCC, &pCtx->mouseShapeInfo, true); + } + + return VINF_SUCCESS; +} + +void VBVARaiseIrq(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t fFlags) +{ + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSectIRQ, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSectIRQ, rcLock); + + const uint32_t fu32CurrentGuestFlags = HGSMIGetHostGuestFlags(pThisCC->pHGSMI); + if ((fu32CurrentGuestFlags & HGSMIHOSTFLAGS_IRQ) == 0) + { + /* No IRQ set yet. */ + Assert(pThis->fu32PendingGuestFlags == 0); + + HGSMISetHostGuestFlags(pThisCC->pHGSMI, HGSMIHOSTFLAGS_IRQ | fFlags); + + /* If VM is not running, the IRQ will be set in VBVAOnResume. */ + const VMSTATE enmVMState = PDMDevHlpVMState(pDevIns); + if ( enmVMState == VMSTATE_RUNNING + || enmVMState == VMSTATE_RUNNING_LS) + PDMDevHlpPCISetIrqNoWait(pDevIns, 0, PDM_IRQ_LEVEL_HIGH); + } + else + { + /* IRQ already set, remember the new flags. */ + pThis->fu32PendingGuestFlags |= HGSMIHOSTFLAGS_IRQ | fFlags; + } + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSectIRQ); +} + +void VBVAOnResume(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSectIRQ, VERR_SEM_BUSY); + PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSectIRQ, rcLock); + + if (HGSMIGetHostGuestFlags(pThisCC->pHGSMI) & HGSMIHOSTFLAGS_IRQ) + PDMDevHlpPCISetIrqNoWait(pDevIns, 0, PDM_IRQ_LEVEL_HIGH); + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSectIRQ); +} + +static int vbvaHandleQueryConf32(PVGASTATECC pThisCC, VBVACONF32 RT_UNTRUSTED_VOLATILE_GUEST *pConf32) +{ + uint32_t const idxQuery = pConf32->u32Index; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + LogFlowFunc(("VBVA_QUERY_CONF32: u32Index %d, u32Value 0x%x\n", idxQuery, pConf32->u32Value)); + + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + uint32_t uValue; + if (idxQuery == VBOX_VBVA_CONF32_MONITOR_COUNT) + uValue = pCtx->cViews; + else if (idxQuery == VBOX_VBVA_CONF32_HOST_HEAP_SIZE) + uValue = _64K; /** @todo a value calculated from the vram size */ + else if ( idxQuery == VBOX_VBVA_CONF32_MODE_HINT_REPORTING + || idxQuery == VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING) + uValue = VINF_SUCCESS; + else if (idxQuery == VBOX_VBVA_CONF32_CURSOR_CAPABILITIES) + uValue = VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE; + else if (idxQuery == VBOX_VBVA_CONF32_SCREEN_FLAGS) + uValue = VBVA_SCREEN_F_ACTIVE + | VBVA_SCREEN_F_DISABLED + | VBVA_SCREEN_F_BLANK + | VBVA_SCREEN_F_BLANK2; + else if (idxQuery == VBOX_VBVA_CONF32_MAX_RECORD_SIZE) + uValue = VBVA_MAX_RECORD_SIZE; + else if (idxQuery == UINT32_MAX) + uValue = UINT32_MAX; /* Older GA uses this for sanity checking. See testQueryConf in HGSMIBase.cpp on branches. */ + else + ASSERT_GUEST_MSG_FAILED_RETURN(("Invalid index %#x\n", idxQuery), VERR_INVALID_PARAMETER); + + pConf32->u32Value = uValue; + return VINF_SUCCESS; +} + +static int vbvaHandleSetConf32(VBVACONF32 RT_UNTRUSTED_VOLATILE_GUEST *pConf32) +{ + uint32_t const idxQuery = pConf32->u32Index; + uint32_t const uValue = pConf32->u32Value; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + LogFlowFunc(("VBVA_SET_CONF32: u32Index %d, u32Value 0x%x\n", idxQuery, uValue)); + + if (idxQuery == VBOX_VBVA_CONF32_MONITOR_COUNT) + { /* do nothing. this is a const. */ } + else if (idxQuery == VBOX_VBVA_CONF32_HOST_HEAP_SIZE) + { /* do nothing. this is a const. */ } + else + ASSERT_GUEST_MSG_FAILED_RETURN(("Invalid index %#x (value=%u)\n", idxQuery, uValue), VERR_INVALID_PARAMETER); + + RT_NOREF_PV(uValue); + return VINF_SUCCESS; +} + +static int vbvaHandleInfoHeap(PVGASTATECC pThisCC, const VBVAINFOHEAP RT_UNTRUSTED_VOLATILE_GUEST *pInfoHeap) +{ + uint32_t const offHeap = pInfoHeap->u32HeapOffset; + uint32_t const cbHeap = pInfoHeap->u32HeapSize; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + LogFlowFunc(("VBVA_INFO_HEAP: offset 0x%x, size 0x%x\n", offHeap, cbHeap)); + + return HGSMIHostHeapSetup(pThisCC->pHGSMI, offHeap, cbHeap); +} + +static int vbvaInfoView(PVGASTATE pThis, PVGASTATER3 pThisCC, const VBVAINFOVIEW RT_UNTRUSTED_VOLATILE_GUEST *pView) +{ + VBVAINFOVIEW view; + RT_COPY_VOLATILE(view, *pView); + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + LogFlowFunc(("VBVA_INFO_VIEW: u32ViewIndex %d, u32ViewOffset 0x%x, u32ViewSize 0x%x, u32MaxScreenSize 0x%x\n", + view.u32ViewIndex, view.u32ViewOffset, view.u32ViewSize, view.u32MaxScreenSize)); + + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + ASSERT_GUEST_LOGREL_MSG_RETURN( view.u32ViewIndex < pCtx->cViews + && view.u32ViewOffset <= pThis->vram_size + && view.u32ViewSize <= pThis->vram_size + && view.u32ViewOffset <= pThis->vram_size - view.u32ViewSize + && view.u32MaxScreenSize <= view.u32ViewSize, + ("index %d(%d), offset 0x%x, size 0x%x, max 0x%x, vram size 0x%x\n", + view.u32ViewIndex, pCtx->cViews, view.u32ViewOffset, view.u32ViewSize, + view.u32MaxScreenSize, pThis->vram_size), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pCtx->aViews[view.u32ViewIndex].view = view; + return VINF_SUCCESS; +} + +static int vbvaInfoScreen(PVGASTATECC pThisCC, const VBVAINFOSCREEN RT_UNTRUSTED_VOLATILE_GUEST *pScreen) +{ + /* + * Copy input into non-volatile buffer. + */ + VBVAINFOSCREEN screen; + RT_COPY_VOLATILE(screen, *pScreen); + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + LogRel2(("VBVA: InfoScreen: [%d] @%d,%d %dx%d, line 0x%x, BPP %d, flags 0x%x\n", + screen.u32ViewIndex, screen.i32OriginX, screen.i32OriginY, + screen.u32Width, screen.u32Height, + screen.u32LineSize, screen.u16BitsPerPixel, screen.u16Flags)); + + /* + * Validate input. + */ + /* Allow screen.u16BitsPerPixel == 0 because legacy guest code used it for screen blanking. */ + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + ASSERT_GUEST_LOGREL_MSG_RETURN(screen.u32ViewIndex < pCtx->cViews, + ("Screen index %#x is out of bound (cViews=%#x)\n", screen.u32ViewIndex, pCtx->cViews), + VERR_INVALID_PARAMETER); + ASSERT_GUEST_LOGREL_MSG_RETURN( screen.u16BitsPerPixel <= 32 + && screen.u32Width <= UINT16_MAX + && screen.u32Height <= UINT16_MAX + && screen.u32LineSize <= UINT16_MAX * UINT32_C(4), + ("One or more values out of range: u16BitsPerPixel=%#x u32Width=%#x u32Height=%#x u32LineSize=%#x\n", + screen.u16BitsPerPixel, screen.u32Width, screen.u32Height, screen.u32LineSize), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + const VBVAINFOVIEW *pView = &pCtx->aViews[screen.u32ViewIndex].view; + const uint32_t cbPerPixel = (screen.u16BitsPerPixel + 7) / 8; + ASSERT_GUEST_LOGREL_MSG_RETURN(screen.u32Width <= screen.u32LineSize / (cbPerPixel ? cbPerPixel : 1), + ("u32Width=%#x u32LineSize=%3x cbPerPixel=%#x\n", + screen.u32Width, screen.u32LineSize, cbPerPixel), + VERR_INVALID_PARAMETER); + + const uint64_t u64ScreenSize = (uint64_t)screen.u32LineSize * screen.u32Height; + + ASSERT_GUEST_LOGREL_MSG_RETURN( screen.u32StartOffset <= pView->u32ViewSize + && u64ScreenSize <= pView->u32MaxScreenSize + && screen.u32StartOffset <= pView->u32ViewSize - (uint32_t)u64ScreenSize, + ("u32StartOffset=%#x u32ViewSize=%#x u64ScreenSize=%#RX64 u32MaxScreenSize=%#x\n", + screen.u32StartOffset, pView->u32ViewSize, u64ScreenSize, pView->u32MaxScreenSize), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* + * Do the job. + */ + vbvaResize(pThisCC, &pCtx->aViews[screen.u32ViewIndex], &screen, true); + return VINF_SUCCESS; +} + +#ifdef UNUSED_FUNCTION +int VBVAGetInfoViewAndScreen(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32ViewIndex, VBVAINFOVIEW *pView, VBVAINFOSCREEN *pScreen) +{ + if (u32ViewIndex >= pThis->cMonitors) + return VERR_INVALID_PARAMETER; + + PHGSMIINSTANCE pIns = pThisCC->pHGSMI; + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext (pIns); + + if (pView) + *pView = pCtx->aViews[u32ViewIndex].view; + + if (pScreen) + *pScreen = pCtx->aViews[u32ViewIndex].screen; + + return VINF_SUCCESS; +} +#endif + +static int vbvaHandleEnable(PVGASTATE pThis, PVGASTATER3 pThisCC, uint32_t fEnableFlags, uint32_t offEnable, uint32_t idScreen) +{ + LogFlowFunc(("VBVA_ENABLE[%u]: fEnableFlags=0x%x offEnable=%#x\n", idScreen, fEnableFlags, offEnable)); + PHGSMIINSTANCE pIns = pThisCC->pHGSMI; + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pIns); + + /* + * Validate input. + */ + ASSERT_GUEST_LOGREL_MSG_RETURN(idScreen < pCtx->cViews, ("idScreen=%#x cViews=%#x\n", idScreen, pCtx->cViews), VERR_INVALID_PARAMETER); + ASSERT_GUEST_LOGREL_MSG_RETURN( (fEnableFlags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE + || (fEnableFlags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_DISABLE, + ("fEnableFlags=%#x\n", fEnableFlags), + VERR_INVALID_PARAMETER); + if (fEnableFlags & VBVA_F_ENABLE) + { + ASSERT_GUEST_LOGREL_MSG_RETURN(offEnable < pThis->vram_size, + ("offEnable=%#x vram_size=%#x\n", offEnable, pThis->vram_size), + VERR_INVALID_PARAMETER); + if (fEnableFlags & VBVA_F_ABSOFFSET) + /* Offset from VRAM start. */ + ASSERT_GUEST_LOGREL_MSG_RETURN( pThis->vram_size >= RT_UOFFSETOF(VBVABUFFER, au8Data) + && offEnable <= pThis->vram_size - RT_UOFFSETOF(VBVABUFFER, au8Data), + ("offEnable=%#x vram_size=%#x\n", offEnable, pThis->vram_size), + VERR_INVALID_PARAMETER); + else + { + /* Offset from the view start. We'd be using idScreen here to fence required. */ + RT_UNTRUSTED_VALIDATED_FENCE(); + const VBVAINFOVIEW *pView = &pCtx->aViews[idScreen].view; + ASSERT_GUEST_LOGREL_MSG_RETURN( pThis->vram_size - offEnable >= pView->u32ViewOffset + && pView->u32ViewSize >= RT_UOFFSETOF(VBVABUFFER, au8Data) + && offEnable <= pView->u32ViewSize - RT_UOFFSETOF(VBVABUFFER, au8Data), + ("offEnable=%#x vram_size=%#x view: %#x LB %#x\n", + offEnable, pThis->vram_size, pView->u32ViewOffset, pView->u32ViewSize), + VERR_INVALID_PARAMETER); + offEnable += pView->u32ViewOffset; + } + ASSERT_GUEST_LOGREL_MSG_RETURN(HGSMIIsOffsetValid(pIns, offEnable), + ("offEnable=%#x area %#x LB %#x\n", + offEnable, HGSMIGetAreaOffset(pIns), HGSMIGetAreaSize(pIns)), + VERR_INVALID_PARAMETER); + } + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* + * Execute. + */ + int rc = VINF_SUCCESS; + if (fEnableFlags & VBVA_F_ENABLE) + { + VBVABUFFER RT_UNTRUSTED_VOLATILE_GUEST *pVBVA + = (VBVABUFFER RT_UNTRUSTED_VOLATILE_GUEST *)HGSMIOffsetToPointerHost(pIns, offEnable); + ASSERT_GUEST_LOGREL_RETURN(pVBVA, VERR_INVALID_PARAMETER); /* already check above, but let's be careful. */ + + /* Process any pending orders and empty the VBVA ring buffer. */ + vbvaFlush(pThis, pThisCC, pCtx); + + rc = vbvaEnable(pThis, pThisCC, pCtx, idScreen, pVBVA, offEnable, false /* fRestored */); + if (RT_FAILURE(rc)) + LogRelMax(8, ("VBVA: can not enable: %Rrc\n", rc)); + } + else + rc = vbvaDisable(pThis, pThisCC, pCtx, idScreen); + return rc; +} + +static int vbvaHandleQueryModeHints(PVGASTATECC pThisCC, VBVAQUERYMODEHINTS volatile *pQueryModeHints, HGSMISIZE cbBuffer) +{ + PHGSMIINSTANCE pIns = pThisCC->pHGSMI; + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pIns); + + /* + * Copy and validate the request. + */ + uint16_t const cHintsQueried = pQueryModeHints->cHintsQueried; + uint16_t const cbHintStructureGuest = pQueryModeHints->cbHintStructureGuest; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + LogRelFlowFunc(("VBVA: HandleQueryModeHints: cHintsQueried=%RU16, cbHintStructureGuest=%RU16\n", + cHintsQueried, cbHintStructureGuest)); + ASSERT_GUEST_RETURN(cbBuffer >= sizeof(VBVAQUERYMODEHINTS) + (uint32_t)cHintsQueried * cbHintStructureGuest, + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* + * Produce the requested data. + */ + uint8_t *pbHint = (uint8_t *)(pQueryModeHints + 1); + memset(pbHint, ~0, cbBuffer - sizeof(VBVAQUERYMODEHINTS)); + + for (unsigned iHint = 0; iHint < cHintsQueried && iHint < VBOX_VIDEO_MAX_SCREENS; ++iHint) + { + memcpy(pbHint, &pCtx->aModeHints[iHint], RT_MIN(cbHintStructureGuest, sizeof(VBVAMODEHINT))); + pbHint += cbHintStructureGuest; + Assert((uintptr_t)(pbHint - (uint8_t *)pQueryModeHints) <= cbBuffer); + } + + return VINF_SUCCESS; +} + +/* + * + * New VBVA uses a new interface id: #define VBE_DISPI_ID_VBOX_VIDEO 0xBE01 + * + * VBVA uses two 32 bits IO ports to write VRAM offsets of shared memory blocks for commands. + * Read Write + * Host port 0x3b0 to process completed + * Guest port 0x3d0 control value? to process + * + */ + +static DECLCALLBACK(void) vbvaNotifyGuest(void *pvCallback) +{ +#if defined(VBOX_WITH_HGSMI) && (defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_VDMA) || defined(VBOX_WITH_WDDM)) + PPDMDEVINS pDevIns = (PPDMDEVINS)pvCallback; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + VBVARaiseIrq(pDevIns, pThis, pThisCC, 0); +#else + NOREF(pvCallback); + /* Do nothing. Later the VMMDev/VGA IRQ can be used for the notification. */ +#endif +} + +/** + * The guest submitted a command buffer (hit VGA_PORT_HGSMI_GUEST). + * + * Verify the buffer size and invoke corresponding handler. + * + * @return VBox status code. + * @param pvHandler The VBVA channel context. + * @param u16ChannelInfo Command code. + * @param pvBuffer HGSMI buffer with command data. Considered volatile! + * @param cbBuffer Size of command data. + * + * @thread EMT + */ +static DECLCALLBACK(int) vbvaChannelHandler(void *pvHandler, uint16_t u16ChannelInfo, + void RT_UNTRUSTED_VOLATILE_GUEST *pvBuffer, HGSMISIZE cbBuffer) +{ + int rc = VINF_SUCCESS; + + LogFlowFunc(("pvHandler %p, u16ChannelInfo %d, pvBuffer %p, cbBuffer %u\n", pvHandler, u16ChannelInfo, pvBuffer, cbBuffer)); + + PPDMDEVINS pDevIns = (PPDMDEVINS)pvHandler; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC); + PHGSMIINSTANCE pIns = pThisCC->pHGSMI; + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pIns); + + switch (u16ChannelInfo) + { +#ifdef VBOX_WITH_VDMA + case VBVA_VDMA_CMD: + if (cbBuffer >= VBoxSHGSMIBufferHeaderSize() + sizeof(VBOXVDMACBUF_DR)) + { + VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *pCmd + = (VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *)VBoxSHGSMIBufferData((VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer); + vboxVDMACommand(pThisCC->pVdma, pCmd, cbBuffer - VBoxSHGSMIBufferHeaderSize()); + rc = VINF_SUCCESS; + } + else + rc = VERR_INVALID_PARAMETER; + break; + + case VBVA_VDMA_CTL: + if (cbBuffer >= VBoxSHGSMIBufferHeaderSize() + sizeof(VBOXVDMA_CTL)) + { + VBOXVDMA_CTL RT_UNTRUSTED_VOLATILE_GUEST *pCmd + = (VBOXVDMA_CTL RT_UNTRUSTED_VOLATILE_GUEST *)VBoxSHGSMIBufferData((VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer); + vboxVDMAControl(pThisCC->pVdma, pCmd, cbBuffer - VBoxSHGSMIBufferHeaderSize()); + } + else + rc = VERR_INVALID_PARAMETER; + break; +#endif /* VBOX_WITH_VDMA */ + + case VBVA_QUERY_CONF32: + if (cbBuffer >= sizeof(VBVACONF32)) + rc = vbvaHandleQueryConf32(pThisCC, (VBVACONF32 RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer); + else + rc = VERR_INVALID_PARAMETER; + break; + + case VBVA_SET_CONF32: + if (cbBuffer >= sizeof(VBVACONF32)) + rc = vbvaHandleSetConf32((VBVACONF32 RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer); + else + rc = VERR_INVALID_PARAMETER; + break; + + case VBVA_INFO_VIEW: + /* Expect at least one VBVAINFOVIEW structure. */ + rc = VERR_INVALID_PARAMETER; + if (cbBuffer >= sizeof(VBVAINFOVIEW)) + { + /* Guest submits an array of VBVAINFOVIEW structures. */ + const VBVAINFOVIEW RT_UNTRUSTED_VOLATILE_GUEST *pView = (VBVAINFOVIEW RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + for (; + cbBuffer >= sizeof(VBVAINFOVIEW); + ++pView, cbBuffer -= sizeof(VBVAINFOVIEW)) + { + rc = vbvaInfoView(pThis, pThisCC, pView); + if (RT_FAILURE(rc)) + break; + } + } + break; + + case VBVA_INFO_HEAP: + if (cbBuffer >= sizeof(VBVAINFOHEAP)) + rc = vbvaHandleInfoHeap(pThisCC, (VBVAINFOHEAP RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer); + else + rc = VERR_INVALID_PARAMETER; + break; + + case VBVA_FLUSH: + if (cbBuffer >= sizeof(VBVAFLUSH)) + rc = vbvaFlush(pThis, pThisCC, pCtx); + else + rc = VERR_INVALID_PARAMETER; + break; + + case VBVA_INFO_SCREEN: + rc = VERR_INVALID_PARAMETER; + if (cbBuffer >= sizeof(VBVAINFOSCREEN)) + rc = vbvaInfoScreen(pThisCC, (VBVAINFOSCREEN RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer); + break; + + case VBVA_ENABLE: + rc = VERR_INVALID_PARAMETER; + if (cbBuffer >= sizeof(VBVAENABLE)) + { + VBVAENABLE RT_UNTRUSTED_VOLATILE_GUEST *pVbvaEnable = (VBVAENABLE RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + uint32_t const fEnableFlags = pVbvaEnable->u32Flags; + uint32_t const offEnable = pVbvaEnable->u32Offset; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + uint32_t idScreen; + if (fEnableFlags & VBVA_F_EXTENDED) + { + ASSERT_GUEST_STMT_BREAK(cbBuffer >= sizeof(VBVAENABLE_EX), rc = VERR_INVALID_PARAMETER); + idScreen = ((VBVAENABLE_EX RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer)->u32ScreenId; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + } + else + idScreen = vbvaViewFromBufferPtr(pIns, pCtx, pvBuffer); + + rc = vbvaHandleEnable(pThis, pThisCC, fEnableFlags, offEnable, idScreen); + pVbvaEnable->i32Result = rc; + } + break; + + case VBVA_MOUSE_POINTER_SHAPE: + if (cbBuffer >= sizeof(VBVAMOUSEPOINTERSHAPE)) + { + VBVAMOUSEPOINTERSHAPE RT_UNTRUSTED_VOLATILE_GUEST *pShape + = (VBVAMOUSEPOINTERSHAPE RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + rc = vbvaMousePointerShape(pThisCC, pCtx, pShape, cbBuffer); + pShape->i32Result = rc; + } + else + rc = VERR_INVALID_PARAMETER; + break; + + +#ifdef VBOX_WITH_VIDEOHWACCEL + case VBVA_VHWA_CMD: + if (cbBuffer >= VBOXVHWACMD_HEADSIZE()) + { + vbvaVHWAHandleCommand(pDevIns, pThis, pThisCC, (VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer); + rc = VINF_SUCCESS; + } + else + rc = VERR_INVALID_PARAMETER; + break; +#endif + +#ifdef VBOX_WITH_WDDM + case VBVA_INFO_CAPS: + if (cbBuffer >= sizeof(VBVACAPS)) + { + VBVACAPS RT_UNTRUSTED_VOLATILE_GUEST *pCaps = (VBVACAPS RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + pThis->fGuestCaps = pCaps->fCaps; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + pThisCC->pDrv->pfnVBVAGuestCapabilityUpdate(pThisCC->pDrv, pThis->fGuestCaps); + pCaps->rc = rc = VINF_SUCCESS; + } + else + rc = VERR_INVALID_PARAMETER; + break; +#endif + + case VBVA_SCANLINE_CFG: + if (cbBuffer >= sizeof(VBVASCANLINECFG)) + { + VBVASCANLINECFG RT_UNTRUSTED_VOLATILE_GUEST *pCfg = (VBVASCANLINECFG RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + pThis->fScanLineCfg = pCfg->fFlags; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + pCfg->rc = rc = VINF_SUCCESS; + } + else + rc = VERR_INVALID_PARAMETER; + break; + + case VBVA_QUERY_MODE_HINTS: + if (cbBuffer >= sizeof(VBVAQUERYMODEHINTS)) + { + VBVAQUERYMODEHINTS RT_UNTRUSTED_VOLATILE_GUEST *pQueryModeHints + = (VBVAQUERYMODEHINTS RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + rc = vbvaHandleQueryModeHints(pThisCC, pQueryModeHints, cbBuffer); + pQueryModeHints->rc = rc; + } + else + rc = VERR_INVALID_PARAMETER; + break; + + case VBVA_REPORT_INPUT_MAPPING: + if (cbBuffer >= sizeof(VBVAREPORTINPUTMAPPING)) + { + VBVAREPORTINPUTMAPPING inputMapping; + { + VBVAREPORTINPUTMAPPING RT_UNTRUSTED_VOLATILE_GUEST *pInputMapping + = (VBVAREPORTINPUTMAPPING RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + inputMapping.x = pInputMapping->x; + inputMapping.y = pInputMapping->y; + inputMapping.cx = pInputMapping->cx; + inputMapping.cy = pInputMapping->cy; + } + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + LogRelFlowFunc(("VBVA: ChannelHandler: VBVA_REPORT_INPUT_MAPPING: x=%RI32, y=%RI32, cx=%RU32, cy=%RU32\n", + inputMapping.x, inputMapping.y, inputMapping.cx, inputMapping.cy)); + pThisCC->pDrv->pfnVBVAInputMappingUpdate(pThisCC->pDrv, + inputMapping.x, inputMapping.y, + inputMapping.cx, inputMapping.cy); + rc = VINF_SUCCESS; + } + else + rc = VERR_INVALID_PARAMETER; + break; + + case VBVA_CURSOR_POSITION: + if (cbBuffer >= sizeof(VBVACURSORPOSITION)) + { + VBVACURSORPOSITION RT_UNTRUSTED_VOLATILE_GUEST *pReport = (VBVACURSORPOSITION RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + VBVACURSORPOSITION Report; + Report.fReportPosition = pReport->fReportPosition; + Report.x = pReport->x; + Report.y = pReport->y; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + LogRelFlowFunc(("VBVA: ChannelHandler: VBVA_CURSOR_POSITION: fReportPosition=%RTbool, Id=%RU32, x=%RU32, y=%RU32\n", + RT_BOOL(Report.fReportPosition), vbvaViewFromBufferPtr(pIns, pCtx, pvBuffer), Report.x, Report.y)); + + pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, RT_BOOL(Report.fReportPosition), vbvaViewFromBufferPtr(pIns, pCtx, pvBuffer), Report.x, Report.y); + /* This was only ever briefly used by the guest, and a value + * of zero in both was taken to mean "ignore". */ + pReport->x = 0; + pReport->y = 0; + rc = VINF_SUCCESS; + } + else + rc = VERR_INVALID_PARAMETER; + break; + + default: + Log(("Unsupported VBVA guest command %d (%#x)!!!\n", u16ChannelInfo, u16ChannelInfo)); + break; + } + + return rc; +} + +/** When VBVA is paused, the VGA device is allowed to work but + * no HGSMI etc state is changed. + */ +static void vbvaPause(PVGASTATECC pThisCC, bool fPause) +{ + if (!pThisCC || !pThisCC->pHGSMI) + return; + + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + if (pCtx) + pCtx->fPaused = fPause; +} + +bool VBVAIsPaused(PVGASTATECC pThisCC) +{ + if (pThisCC && pThisCC->pHGSMI) + { + const VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + if (pCtx && pCtx->cViews) + { + /* If VBVA is enabled at all. */ + const VBVAVIEW *pView = &pCtx->aViews[0]; + if (pView->vbva.guest.pVBVA) + return pCtx->fPaused; + } + } + /* VBVA is disabled. */ + return true; +} + +void VBVAOnVBEChanged(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + /* The guest does not depend on host handling the VBE registers. */ + if (pThis->fGuestCaps & VBVACAPS_USE_VBVA_ONLY) + return; + + vbvaPause(pThisCC, (pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) == 0); +} + +void VBVAReset(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + if (!pThis || !pThisCC->pHGSMI) + return; + + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + +#ifdef VBOX_WITH_VIDEOHWACCEL + vbvaVHWAReset(pDevIns, pThis, pThisCC); +#endif + + HGSMIReset(pThisCC->pHGSMI); + /* Make sure the IRQ is reset. */ + PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW); + pThis->fu32PendingGuestFlags = 0; + + if (pCtx) + { + vbvaFlush(pThis, pThisCC, pCtx); + + for (unsigned idScreen = 0; idScreen < pCtx->cViews; idScreen++) + vbvaDisable(pThis, pThisCC, pCtx, idScreen); + + pCtx->mouseShapeInfo.fSet = false; + RTMemFreeZ(pCtx->mouseShapeInfo.pu8Shape, pCtx->mouseShapeInfo.cbAllocated); + pCtx->mouseShapeInfo.pu8Shape = NULL; + pCtx->mouseShapeInfo.cbAllocated = 0; + pCtx->mouseShapeInfo.cbShape = 0; + } + +} + +int VBVAUpdateDisplay(PVGASTATE pThis, PVGASTATECC pThisCC) +{ + int rc = VERR_NOT_SUPPORTED; /* Assuming that the VGA device will have to do updates. */ + + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + if (pCtx) + { + if (!pCtx->fPaused) + { + rc = vbvaFlush(pThis, pThisCC, pCtx); + if (RT_SUCCESS(rc)) + { + if (!pCtx->aViews[0].vbva.guest.pVBVA) + { + /* VBVA is not enabled for the first view, so VGA device must do updates. */ + rc = VERR_NOT_SUPPORTED; + } + } + } + } + + return rc; +} + +static int vbvaSendModeHintWorker(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, + uint32_t cx, uint32_t cy, uint32_t cBPP, uint32_t iDisplay, uint32_t dx, + uint32_t dy, uint32_t fEnabled, + uint32_t fNotifyGuest) +{ + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + /** @note See Display::setVideoModeHint: "It is up to the guest to decide + * whether the hint is valid. Therefore don't do any VRAM sanity checks + * here! */ + if (iDisplay >= RT_MIN(pThis->cMonitors, RT_ELEMENTS(pCtx->aModeHints))) + return VERR_OUT_OF_RANGE; + pCtx->aModeHints[iDisplay].magic = VBVAMODEHINT_MAGIC; + pCtx->aModeHints[iDisplay].cx = cx; + pCtx->aModeHints[iDisplay].cy = cy; + pCtx->aModeHints[iDisplay].cBPP = cBPP; + pCtx->aModeHints[iDisplay].dx = dx; + pCtx->aModeHints[iDisplay].dy = dy; + pCtx->aModeHints[iDisplay].fEnabled = fEnabled; + if (fNotifyGuest && pThis->fGuestCaps & VBVACAPS_IRQ && pThis->fGuestCaps & VBVACAPS_VIDEO_MODE_HINTS) + VBVARaiseIrq(pDevIns, pThis, pThisCC, HGSMIHOSTFLAGS_HOTPLUG); + return VINF_SUCCESS; +} + + +/** + * @interface_method_impl{PDMIDISPLAYPORT,pfnSendModeHint} + */ +DECLCALLBACK(int) vbvaR3PortSendModeHint(PPDMIDISPLAYPORT pInterface, uint32_t cx, uint32_t cy, uint32_t cBPP, + uint32_t iDisplay, uint32_t dx, uint32_t dy, uint32_t fEnabled, uint32_t fNotifyGuest) +{ + PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort); + PPDMDEVINS pDevIns = pThisCC->pDevIns; + PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE); + int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_SEM_BUSY); + AssertRCReturn(rc, rc); + + rc = vbvaSendModeHintWorker(pDevIns, pThis, pThisCC, cx, cy, cBPP, iDisplay, dx, dy, fEnabled, fNotifyGuest); + + PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); + return rc; +} + +int VBVAInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) +{ + int rc = HGSMICreate(&pThisCC->pHGSMI, + pDevIns, + "VBVA", + 0, + pThisCC->pbVRam, + pThis->vram_size, + vbvaNotifyGuest, + pDevIns, + sizeof(VBVACONTEXT)); + if (RT_SUCCESS(rc)) + { + rc = HGSMIHostChannelRegister(pThisCC->pHGSMI, + HGSMI_CH_VBVA, + vbvaChannelHandler, + pDevIns); + if (RT_SUCCESS(rc)) + { + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pThisCC->pHGSMI); + pCtx->cViews = pThis->cMonitors; + pCtx->fPaused = true; + memset(pCtx->aModeHints, ~0, sizeof(pCtx->aModeHints)); + } + } + + return rc; + +} + +void VBVADestroy(PVGASTATECC pThisCC) +{ + PHGSMIINSTANCE pHgsmi = pThisCC->pHGSMI; + if (pHgsmi) + { + VBVACONTEXT *pCtx = (VBVACONTEXT *)HGSMIContext(pHgsmi); + pCtx->mouseShapeInfo.fSet = false; + RTMemFreeZ(pCtx->mouseShapeInfo.pu8Shape, pCtx->mouseShapeInfo.cbAllocated); + pCtx->mouseShapeInfo.pu8Shape = NULL; + pCtx->mouseShapeInfo.cbAllocated = 0; + pCtx->mouseShapeInfo.cbShape = 0; + + HGSMIDestroy(pHgsmi); + pThisCC->pHGSMI = NULL; + } +} + diff --git a/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp b/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp new file mode 100644 index 00000000..f1f3c6f7 --- /dev/null +++ b/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp @@ -0,0 +1,373 @@ +/* $Id: DevVGA_VDMA.cpp $ */ +/** @file + * Video DMA (VDMA) support. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_VGA +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DevVGA.h" +#include "HGSMI/SHGSMIHost.h" + +#ifdef DEBUG_misha +# define VBOXVDBG_MEMCACHE_DISABLE +#endif + +#ifndef VBOXVDBG_MEMCACHE_DISABLE +# include +#endif + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#ifdef DEBUG_misha +# define WARN_BP() do { AssertFailed(); } while (0) +#else +# define WARN_BP() do { } while (0) +#endif +#define WARN(_msg) do { \ + LogRel(_msg); \ + WARN_BP(); \ + } while (0) + +#define VBOXVDMATHREAD_STATE_TERMINATED 0 +#define VBOXVDMATHREAD_STATE_CREATING 1 +#define VBOXVDMATHREAD_STATE_CREATED 3 +#define VBOXVDMATHREAD_STATE_TERMINATING 4 + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +struct VBOXVDMATHREAD; + +typedef DECLCALLBACKPTR(void, PFNVBOXVDMATHREAD_CHANGED,(struct VBOXVDMATHREAD *pThread, int rc, + void *pvThreadContext, void *pvChangeContext)); + +typedef struct VBOXVDMATHREAD +{ + RTTHREAD hWorkerThread; + RTSEMEVENT hEvent; + volatile uint32_t u32State; + PFNVBOXVDMATHREAD_CHANGED pfnChanged; + void *pvChanged; +} VBOXVDMATHREAD, *PVBOXVDMATHREAD; + + +/* state transformations: + * + * submitter | processor + * + * LISTENING ---> PROCESSING + * + * */ +#define VBVAEXHOSTCONTEXT_STATE_LISTENING 0 +#define VBVAEXHOSTCONTEXT_STATE_PROCESSING 1 + +#define VBVAEXHOSTCONTEXT_ESTATE_DISABLED -1 +#define VBVAEXHOSTCONTEXT_ESTATE_PAUSED 0 +#define VBVAEXHOSTCONTEXT_ESTATE_ENABLED 1 + +typedef struct VBVAEXHOSTCONTEXT +{ + VBVABUFFER RT_UNTRUSTED_VOLATILE_GUEST *pVBVA; + /** Maximum number of data bytes addressible relative to pVBVA. */ + uint32_t cbMaxData; + volatile int32_t i32State; + volatile int32_t i32EnableState; + volatile uint32_t u32cCtls; + /* critical section for accessing ctl lists */ + RTCRITSECT CltCritSect; + RTLISTANCHOR GuestCtlList; + RTLISTANCHOR HostCtlList; +#ifndef VBOXVDBG_MEMCACHE_DISABLE + RTMEMCACHE CtlCache; +#endif +} VBVAEXHOSTCONTEXT; + +typedef enum +{ + VBVAEXHOSTCTL_TYPE_UNDEFINED = 0, + VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE, + VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME, + VBVAEXHOSTCTL_TYPE_HH_SAVESTATE, + VBVAEXHOSTCTL_TYPE_HH_LOADSTATE, + VBVAEXHOSTCTL_TYPE_HH_LOADSTATE_DONE, + VBVAEXHOSTCTL_TYPE_HH_BE_OPAQUE, + VBVAEXHOSTCTL_TYPE_HH_ON_HGCM_UNLOAD, + VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE, + VBVAEXHOSTCTL_TYPE_GHH_ENABLE, + VBVAEXHOSTCTL_TYPE_GHH_ENABLE_PAUSED, + VBVAEXHOSTCTL_TYPE_GHH_DISABLE, + VBVAEXHOSTCTL_TYPE_GHH_RESIZE +} VBVAEXHOSTCTL_TYPE; + +struct VBVAEXHOSTCTL; + +typedef DECLCALLBACKTYPE(void, FNVBVAEXHOSTCTL_COMPLETE,(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete)); +typedef FNVBVAEXHOSTCTL_COMPLETE *PFNVBVAEXHOSTCTL_COMPLETE; + +typedef struct VBVAEXHOSTCTL +{ + RTLISTNODE Node; + VBVAEXHOSTCTL_TYPE enmType; + union + { + struct + { + void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd; + uint32_t cbCmd; + } cmd; + + struct + { + PSSMHANDLE pSSM; + uint32_t u32Version; + } state; + } u; + PFNVBVAEXHOSTCTL_COMPLETE pfnComplete; + void *pvComplete; +} VBVAEXHOSTCTL; + +/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other, + * but can be called with other VBoxVBVAExS** (submitter) functions except Init/Start/Term aparently. + * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands + * see mor edetailed comments in headers for function definitions */ +typedef enum +{ + VBVAEXHOST_DATA_TYPE_NO_DATA = 0, + VBVAEXHOST_DATA_TYPE_CMD, + VBVAEXHOST_DATA_TYPE_HOSTCTL, + VBVAEXHOST_DATA_TYPE_GUESTCTL +} VBVAEXHOST_DATA_TYPE; + + +typedef struct VBOXVDMAHOST +{ + PHGSMIINSTANCE pHgsmi; /**< Same as VGASTATE::pHgsmi. */ + PVGASTATE pThis; +} VBOXVDMAHOST, *PVBOXVDMAHOST; + + +/** + * List selector for VBoxVBVAExHCtlSubmit(), vdmaVBVACtlSubmit(). + */ +typedef enum +{ + VBVAEXHOSTCTL_SOURCE_GUEST = 0, + VBVAEXHOSTCTL_SOURCE_HOST +} VBVAEXHOSTCTL_SOURCE; + + + + +/** + * Called by vgaR3Construct() to initialize the state. + * + * @returns VBox status code. + */ +int vboxVDMAConstruct(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t cPipeElements) +{ + RT_NOREF(cPipeElements); + PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)RTMemAllocZ(sizeof(*pVdma)); + Assert(pVdma); + if (pVdma) + { + pVdma->pHgsmi = pThisCC->pHGSMI; + pVdma->pThis = pThis; + + pThisCC->pVdma = pVdma; + return VINF_SUCCESS; + } + return VERR_NO_MEMORY; +} + +/** + * Called by vgaR3Reset() to do reset. + */ +void vboxVDMAReset(struct VBOXVDMAHOST *pVdma) +{ + RT_NOREF(pVdma); +} + +/** + * Called by vgaR3Destruct() to do cleanup. + */ +void vboxVDMADestruct(struct VBOXVDMAHOST *pVdma) +{ + if (!pVdma) + return; + RTMemFree(pVdma); +} + +/** + * Handle VBVA_VDMA_CTL, see vbvaChannelHandler + * + * @param pVdma The VDMA channel. + * @param pCmd The control command to handle. Considered volatile. + * @param cbCmd The size of the command. At least sizeof(VBOXVDMA_CTL). + */ +void vboxVDMAControl(struct VBOXVDMAHOST *pVdma, VBOXVDMA_CTL RT_UNTRUSTED_VOLATILE_GUEST *pCmd, uint32_t cbCmd) +{ + RT_NOREF(cbCmd); + PHGSMIINSTANCE pIns = pVdma->pHgsmi; + + VBOXVDMA_CTL_TYPE enmCtl = pCmd->enmCtl; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + int rc; + if (enmCtl < VBOXVDMA_CTL_TYPE_END) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + + switch (enmCtl) + { + case VBOXVDMA_CTL_TYPE_ENABLE: + rc = VINF_SUCCESS; + break; + case VBOXVDMA_CTL_TYPE_DISABLE: + rc = VINF_SUCCESS; + break; + case VBOXVDMA_CTL_TYPE_FLUSH: + rc = VINF_SUCCESS; + break; + case VBOXVDMA_CTL_TYPE_WATCHDOG: + rc = VERR_NOT_SUPPORTED; + break; + default: + AssertFailedBreakStmt(rc = VERR_IPE_NOT_REACHED_DEFAULT_CASE); + } + } + else + { + RT_UNTRUSTED_VALIDATED_FENCE(); + ASSERT_GUEST_FAILED(); + rc = VERR_NOT_SUPPORTED; + } + + pCmd->i32Result = rc; + rc = VBoxSHGSMICommandComplete(pIns, pCmd); + AssertRC(rc); +} + +/** + * Handle VBVA_VDMA_CMD, see vbvaChannelHandler(). + * + * @param pVdma The VDMA channel. + * @param pCmd The command to handle. Considered volatile. + * @param cbCmd The size of the command. At least sizeof(VBOXVDMACBUF_DR). + * @thread EMT + */ +void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_GUEST *pCmd, uint32_t cbCmd) +{ + /* + * Process the command. + */ + bool fAsyncCmd = false; + RT_NOREF(cbCmd); + int rc = VERR_NOT_IMPLEMENTED; + + /* + * Complete the command unless it's asynchronous (e.g. chromium). + */ + if (!fAsyncCmd) + { + pCmd->rc = rc; + int rc2 = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmd); + AssertRC(rc2); + } +} + + + +/* + * + * + * Saved state. + * Saved state. + * Saved state. + * + * + */ + +int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma) +{ + RT_NOREF(pVdma); + return VINF_SUCCESS; +} + +int vboxVDMASaveStateExecDone(struct VBOXVDMAHOST *pVdma) +{ + RT_NOREF(pVdma); + return VINF_SUCCESS; +} + +int vboxVDMASaveStateExecPerform(PCPDMDEVHLPR3 pHlp, struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM) +{ + int rc; + RT_NOREF(pVdma); + + rc = pHlp->pfnSSMPutU32(pSSM, UINT32_MAX); + AssertRCReturn(rc, rc); + return VINF_SUCCESS; +} + +int vboxVDMASaveLoadExecPerform(PCPDMDEVHLPR3 pHlp, struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM, uint32_t u32Version) +{ + uint32_t u32; + int rc = pHlp->pfnSSMGetU32(pSSM, &u32); + AssertLogRelRCReturn(rc, rc); + + if (u32 != UINT32_MAX) + { + RT_NOREF(pVdma, u32Version); + WARN(("Unsupported VBVACtl info!\n")); + return VERR_VERSION_MISMATCH; + } + + return VINF_SUCCESS; +} + +int vboxVDMASaveLoadDone(struct VBOXVDMAHOST *pVdma) +{ + RT_NOREF(pVdma); + return VINF_SUCCESS; +} + diff --git a/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp b/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp new file mode 100644 index 00000000..1571863e --- /dev/null +++ b/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.cpp @@ -0,0 +1,1702 @@ +/* $Id: HGSMIHost.cpp $ */ +/** @file + * VBox Host Guest Shared Memory Interface (HGSMI), host part. + * + * Host part: + * - virtual hardware IO handlers; + * - channel management; + * - low level interface for buffer transfer. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/* + * Async host->guest calls. Completion by an IO write from the guest or a timer timeout. + * + * Sync guest->host calls. Initiated by an IO write from the guest. + * + * Guest->Host + * ___________ + * + * Synchronous for the guest, an async result can be also reported later by a host->guest call: + * + * G: Alloc shared memory, fill the structure, issue an IO write (HGSMI_IO_GUEST) with the memory offset. + * H: Verify the shared memory and call the handler. + * G: Continue after the IO completion. + * + * + * Host->Guest + * __________ + * + * H: Alloc shared memory, fill in the info. + * Register in the FIFO with a callback, issue IRQ (on EMT). + * Wait on a sem with timeout if necessary. + * G: Read FIFO from HGSMI_IO_HOST_COMMAND. + * H(EMT): Get the shared memory offset from FIFO to return to the guest. + * G: Get offset, process command, issue IO write to HGSMI_IO_HOST_COMMAND. + * H(EMT): Find registered shared mem, run callback, which could post the sem. + * H: Get results and free shared mem (could be freed automatically on EMT too). + * + * + * Implementation notes: + * + * Host->Guest + * + * * Shared memory allocation using a critsect. + * * FIFO manipulation with a critsect. + * + */ + +#define LOG_GROUP LOG_GROUP_HGSMI +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "HGSMIHost.h" +#include + +#include "../DevVGASavedState.h" + +#ifdef DEBUG_sunlover +#define HGSMI_STRICT 1 +#endif /* !DEBUG_sunlover */ + +#ifdef DEBUG_misha +//# define VBOXHGSMI_STATE_DEBUG +#endif + +#ifdef VBOXHGSMI_STATE_DEBUG +# define VBOXHGSMI_STATE_START_MAGIC UINT32_C(0x12345678) +# define VBOXHGSMI_STATE_STOP_MAGIC UINT32_C(0x87654321) +# define VBOXHGSMI_STATE_FIFOSTART_MAGIC UINT32_C(0x9abcdef1) +# define VBOXHGSMI_STATE_FIFOSTOP_MAGIC UINT32_C(0x1fedcba9) + +# define VBOXHGSMI_SAVE_START(_pSSM) do{ int rc2 = pHlp->pfnSSMPutU32(_pSSM, VBOXHGSMI_STATE_START_MAGIC); AssertRC(rc2); }while(0) +# define VBOXHGSMI_SAVE_STOP(_pSSM) do{ int rc2 = pHlp->pfnSSMPutU32(_pSSM, VBOXHGSMI_STATE_STOP_MAGIC); AssertRC(rc2); }while(0) +# define VBOXHGSMI_SAVE_FIFOSTART(_pSSM) do{ int rc2 = pHlp->pfnSSMPutU32(_pSSM, VBOXHGSMI_STATE_FIFOSTART_MAGIC); AssertRC(rc2); }while(0) +# define VBOXHGSMI_SAVE_FIFOSTOP(_pSSM) do{ int rc2 = pHlp->pfnSSMPutU32(_pSSM, VBOXHGSMI_STATE_FIFOSTOP_MAGIC); AssertRC(rc2); }while(0) + +# define VBOXHGSMI_LOAD_CHECK(_pSSM, _v) \ + do { \ + uint32_t u32; \ + int rc2 = pHlp->pfnSSMGetU32(_pSSM, &u32); AssertRC(rc2); \ + Assert(u32 == (_v)); \ + } while(0) + +# define VBOXHGSMI_LOAD_START(_pSSM) VBOXHGSMI_LOAD_CHECK(_pSSM, VBOXHGSMI_STATE_START_MAGIC) +# define VBOXHGSMI_LOAD_FIFOSTART(_pSSM) VBOXHGSMI_LOAD_CHECK(_pSSM, VBOXHGSMI_STATE_FIFOSTART_MAGIC) +# define VBOXHGSMI_LOAD_FIFOSTOP(_pSSM) VBOXHGSMI_LOAD_CHECK(_pSSM, VBOXHGSMI_STATE_FIFOSTOP_MAGIC) +# define VBOXHGSMI_LOAD_STOP(_pSSM) VBOXHGSMI_LOAD_CHECK(_pSSM, VBOXHGSMI_STATE_STOP_MAGIC) +#else /* !VBOXHGSMI_STATE_DEBUG */ +# define VBOXHGSMI_SAVE_START(a_pSSM) do { } while(0) +# define VBOXHGSMI_SAVE_STOP(a_pSSM) do { } while(0) +# define VBOXHGSMI_SAVE_FIFOSTART(a_pSSM) do { } while(0) +# define VBOXHGSMI_SAVE_FIFOSTOP(a_pSSM) do { } while(0) + +# define VBOXHGSMI_LOAD_START(a_pSSM) do { } while(0) +# define VBOXHGSMI_LOAD_FIFOSTART(a_pSSM) do { } while(0) +# define VBOXHGSMI_LOAD_FIFOSTOP(a_pSSM) do { } while(0) +# define VBOXHGSMI_LOAD_STOP(a_pSSM) do { } while(0) +#endif + +/* Assertions for situations which could happen and normally must be processed properly + * but must be investigated during development: guest misbehaving, etc. + */ +#ifdef HGSMI_STRICT +# define HGSMI_STRICT_ASSERT_FAILED() AssertFailed() +# define HGSMI_STRICT_ASSERT(expr) Assert(expr) +#else +# define HGSMI_STRICT_ASSERT_FAILED() do {} while (0) +# define HGSMI_STRICT_ASSERT(expr) do {} while (0) +#endif + + +/** @name Host heap types. + * @{ */ +#define HGSMI_HEAP_TYPE_NULL 0 /**< Heap not initialized. */ +#define HGSMI_HEAP_TYPE_POINTER 1 /**< Deprecated, used only for old saved states. RTHEAPSIMPLE. */ +#define HGSMI_HEAP_TYPE_OFFSET 2 /**< Deprecated, used only for old saved states. RTHEAPOFFSET. */ +#define HGSMI_HEAP_TYPE_MA 3 /**< Memory allocator. */ +/** @} */ + +typedef struct HGSMIHOSTHEAP +{ + uint32_t u32HeapType; /**< HGSMI_HEAP_TYPE_* */ + int32_t volatile cRefs; /**< How many blocks allocated. */ + HGSMIAREA area; /**< Host heap location. */ + union + { + HGSMIMADATA ma; /**< Memory allocator for the default host heap implementation. */ + struct /**< Legacy heap implementations. For old saved states. */ + { + union + { + RTHEAPSIMPLE hPtr; /**< Pointer based heap. */ + RTHEAPOFFSET hOff; /**< Offset based heap. */ + } u; + } legacy; + } u; +} HGSMIHOSTHEAP; + +typedef struct HGSMIINSTANCE +{ + PPDMDEVINS pDevIns; /**< The device instance. */ + + const char *pszName; /**< A name for the instance. Mostyl used in the log. */ + + RTCRITSECT instanceCritSect; /**< For updating the instance data: FIFO's, channels. */ + + HGSMIAREA area; /**< The shared memory description. */ + HGSMIHOSTHEAP hostHeap; /**< Host heap instance. */ + RTCRITSECT hostHeapCritSect; /**< Heap serialization lock. */ + + RTLISTANCHOR hostFIFO; /**< Pending host buffers. */ + RTLISTANCHOR hostFIFORead; /**< Host buffers read by the guest. */ + RTLISTANCHOR hostFIFOProcessed; /**< Processed by the guest. */ + RTLISTANCHOR hostFIFOFree; /**< Buffers for reuse. */ +#ifdef VBOX_WITH_WDDM + RTLISTANCHOR guestCmdCompleted; /**< list of completed guest commands to be returned to the guest*/ +#endif + RTCRITSECT hostFIFOCritSect; /**< FIFO serialization lock. */ + + PFNHGSMINOTIFYGUEST pfnNotifyGuest; /**< Guest notification callback. */ + void *pvNotifyGuest; /**< Guest notification callback context. */ + + volatile HGSMIHOSTFLAGS *pHGFlags; + + HGSMICHANNELINFO channelInfo; /**< Channel handlers indexed by the channel id. + * The array is accessed under the instance lock. + */ +} HGSMIINSTANCE; + + +typedef DECLCALLBACKTYPE(void, FNHGSMIHOSTFIFOCALLBACK,(void *pvCallback)); +typedef FNHGSMIHOSTFIFOCALLBACK *PFNHGSMIHOSTFIFOCALLBACK; + +typedef struct HGSMIHOSTFIFOENTRY +{ + RTLISTNODE nodeEntry; + + HGSMIINSTANCE *pIns; /**< Backlink to the HGSMI instance. */ + + volatile uint32_t fl; /**< Status flags of the entry. */ + + HGSMIOFFSET offBuffer; /**< Offset of the HGSMI buffer header in the HGSMI host heap: + * [pIns->hostHeap.area.offBase .. offLast]. */ +} HGSMIHOSTFIFOENTRY; + + +#define HGSMI_F_HOST_FIFO_ALLOCATED 0x0001 +#define HGSMI_F_HOST_FIFO_QUEUED 0x0002 +#define HGSMI_F_HOST_FIFO_READ 0x0004 +#define HGSMI_F_HOST_FIFO_PROCESSED 0x0008 +#define HGSMI_F_HOST_FIFO_FREE 0x0010 +#define HGSMI_F_HOST_FIFO_CANCELED 0x0020 + +static DECLCALLBACK(void) hgsmiHostCommandFreeCallback(void *pvCallback); + +#ifdef VBOX_WITH_WDDM + +typedef struct HGSMIGUESTCOMPLENTRY +{ + RTLISTNODE nodeEntry; + HGSMIOFFSET offBuffer; /**< Offset of the guest command buffer. */ +} HGSMIGUESTCOMPLENTRY; + + +static void hgsmiGuestCompletionFIFOFree(HGSMIINSTANCE *pIns, HGSMIGUESTCOMPLENTRY *pEntry) +{ + NOREF (pIns); + RTMemFree (pEntry); +} + +static int hgsmiGuestCompletionFIFOAlloc(HGSMIINSTANCE *pIns, HGSMIGUESTCOMPLENTRY **ppEntry) +{ + HGSMIGUESTCOMPLENTRY *pEntry = (HGSMIGUESTCOMPLENTRY *)RTMemAllocZ(sizeof(HGSMIGUESTCOMPLENTRY)); + if (pEntry) + { + *ppEntry = pEntry; + return VINF_SUCCESS; + } + NOREF(pIns); + return VERR_NO_MEMORY; +} + +#endif /* VBOX_WITH_WDDM */ + +static int hgsmiLock(HGSMIINSTANCE *pIns) +{ + int rc = RTCritSectEnter(&pIns->instanceCritSect); + AssertRC(rc); + return rc; +} + +static void hgsmiUnlock(HGSMIINSTANCE *pIns) +{ + int rc = RTCritSectLeave(&pIns->instanceCritSect); + AssertRC(rc); +} + +static int hgsmiFIFOLock(HGSMIINSTANCE *pIns) +{ + int rc = RTCritSectEnter(&pIns->hostFIFOCritSect); + AssertRC(rc); + return rc; +} + +static void hgsmiFIFOUnlock(HGSMIINSTANCE *pIns) +{ + int rc = RTCritSectLeave(&pIns->hostFIFOCritSect); + AssertRC(rc); +} + +/* + * Virtual hardware IO handlers. + */ + +/* The guest submits a new buffer to the host. + * Called from the HGSMI_IO_GUEST write handler. + * @thread EMT + */ +void HGSMIGuestWrite(PHGSMIINSTANCE pIns, HGSMIOFFSET offBuffer) +{ + HGSMIBufferProcess(&pIns->area, &pIns->channelInfo, offBuffer); +} + +#ifdef VBOX_WITH_WDDM +static HGSMIOFFSET hgsmiProcessGuestCmdCompletion(HGSMIINSTANCE *pIns) +{ + HGSMIOFFSET offCmd = HGSMIOFFSET_VOID; + int rc = hgsmiFIFOLock(pIns); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + HGSMIGUESTCOMPLENTRY *pEntry = RTListGetFirst(&pIns->guestCmdCompleted, HGSMIGUESTCOMPLENTRY, nodeEntry); + if (pEntry) + { + RTListNodeRemove(&pEntry->nodeEntry); + } + + if (RTListIsEmpty(&pIns->guestCmdCompleted)) + { + if (pIns->pHGFlags) + ASMAtomicAndU32(&pIns->pHGFlags->u32HostFlags, ~HGSMIHOSTFLAGS_GCOMMAND_COMPLETED); + } + + hgsmiFIFOUnlock(pIns); + + if (pEntry) + { + offCmd = pEntry->offBuffer; + + LogFlowFunc(("host FIFO head %p.\n", pEntry)); + + hgsmiGuestCompletionFIFOFree(pIns, pEntry); + } + } + return offCmd; +} +#endif + + +/* Called from HGSMI_IO_GUEST read handler. */ +HGSMIOFFSET HGSMIGuestRead(PHGSMIINSTANCE pIns) +{ + LogFlowFunc(("pIns %p\n", pIns)); + + AssertPtr(pIns); + + Assert(PDMDevHlpGetVMCPU(pIns->pDevIns) != NULL); + +#ifndef VBOX_WITH_WDDM + /* Currently there is no functionality here. */ + NOREF(pIns); + + return HGSMIOFFSET_VOID; +#else + /* use this to speedup guest cmd completion + * this mechanism is alternative to submitting H->G command for notification */ + HGSMIOFFSET offCmd = hgsmiProcessGuestCmdCompletion(pIns); + return offCmd; +#endif +} + +static bool hgsmiProcessHostCmdCompletion(HGSMIINSTANCE *pIns, HGSMIOFFSET offBuffer, bool fCompleteFirst) +{ + Assert(PDMDevHlpGetVMCPU(pIns->pDevIns) != NULL); + + int rc = hgsmiFIFOLock(pIns); + if (RT_SUCCESS(rc)) + { + /* Search the Read list for the given buffer offset. */ + HGSMIHOSTFIFOENTRY *pEntry = NULL; + + HGSMIHOSTFIFOENTRY *pIter; + RTListForEach(&pIns->hostFIFORead, pIter, HGSMIHOSTFIFOENTRY, nodeEntry) + { + Assert(pIter->fl == (HGSMI_F_HOST_FIFO_ALLOCATED | HGSMI_F_HOST_FIFO_READ)); + if (fCompleteFirst || pIter->offBuffer == offBuffer) + { + pEntry = pIter; + break; + } + } + + LogFlowFunc(("read list entry: %p.\n", pEntry)); + + Assert(pEntry || fCompleteFirst); + + if (pEntry) + { + RTListNodeRemove(&pEntry->nodeEntry); + + pEntry->fl &= ~HGSMI_F_HOST_FIFO_READ; + pEntry->fl |= HGSMI_F_HOST_FIFO_PROCESSED; + + RTListAppend(&pIns->hostFIFOProcessed, &pEntry->nodeEntry); + + hgsmiFIFOUnlock(pIns); + + hgsmiHostCommandFreeCallback(pEntry); + return true; + } + + hgsmiFIFOUnlock(pIns); + if (!fCompleteFirst) + LogRel(("HGSMI[%s]: ignored invalid write to the host FIFO: 0x%08X!!!\n", pIns->pszName, offBuffer)); + } + return false; +} + +/** + * The guest has finished processing of a buffer previously submitted by the + * host. + * + * Called from HGSMI_IO_HOST write handler. + * @thread EMT + */ +void HGSMIHostWrite(HGSMIINSTANCE *pIns, HGSMIOFFSET offBuffer) +{ + LogFlowFunc(("pIns %p offBuffer 0x%x\n", pIns, offBuffer)); + + hgsmiProcessHostCmdCompletion(pIns, offBuffer, false); +} + +/** + * The guest reads a new host buffer to be processed. + * + * Called from the HGSMI_IO_HOST read handler. + * + * @thread EMT + */ +HGSMIOFFSET HGSMIHostRead(HGSMIINSTANCE *pIns) +{ + LogFlowFunc(("pIns %p\n", pIns)); + + Assert(PDMDevHlpGetVMCPU(pIns->pDevIns) != NULL); + + AssertPtrReturn(pIns->pHGFlags, HGSMIOFFSET_VOID); + int rc = hgsmiFIFOLock(pIns); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + /* Get the host FIFO head entry. */ + HGSMIHOSTFIFOENTRY *pEntry = RTListGetFirst(&pIns->hostFIFO, HGSMIHOSTFIFOENTRY, nodeEntry); + + LogFlowFunc(("host FIFO head %p.\n", pEntry)); + + if (pEntry != NULL) + { + Assert(pEntry->fl == (HGSMI_F_HOST_FIFO_ALLOCATED | HGSMI_F_HOST_FIFO_QUEUED)); + + /* + * Move the entry to the Read list. + */ + RTListNodeRemove(&pEntry->nodeEntry); + + if (RTListIsEmpty(&pIns->hostFIFO)) + { + ASMAtomicAndU32(&pIns->pHGFlags->u32HostFlags, (~HGSMIHOSTFLAGS_COMMANDS_PENDING)); + } + + pEntry->fl &= ~HGSMI_F_HOST_FIFO_QUEUED; + pEntry->fl |= HGSMI_F_HOST_FIFO_READ; + + RTListAppend(&pIns->hostFIFORead, &pEntry->nodeEntry); + + hgsmiFIFOUnlock(pIns); + + /* Return the buffer offset of the host FIFO head. */ + return pEntry->offBuffer; + } + + hgsmiFIFOUnlock(pIns); + } + /* Special value that means there is no host buffers to be processed. */ + return HGSMIOFFSET_VOID; +} + + +/** Tells the guest that a new buffer to be processed is available from the host. */ +static void hgsmiNotifyGuest(HGSMIINSTANCE *pIns) +{ + if (pIns->pfnNotifyGuest) + pIns->pfnNotifyGuest(pIns->pvNotifyGuest); +} + +void HGSMISetHostGuestFlags(HGSMIINSTANCE *pIns, uint32_t flags) +{ + AssertPtrReturnVoid(pIns->pHGFlags); + ASMAtomicOrU32(&pIns->pHGFlags->u32HostFlags, flags); +} + +uint32_t HGSMIGetHostGuestFlags(HGSMIINSTANCE *pIns) +{ + return pIns->pHGFlags ? ASMAtomicReadU32(&pIns->pHGFlags->u32HostFlags) : 0; +} + +void HGSMIClearHostGuestFlags(HGSMIINSTANCE *pIns, uint32_t flags) +{ + AssertPtrReturnVoid(pIns->pHGFlags); + ASMAtomicAndU32(&pIns->pHGFlags->u32HostFlags, ~flags); +} + + +/* + * The host heap. + * + * Uses the RTHeap implementation. + * + */ + +static int hgsmiHostHeapLock(HGSMIINSTANCE *pIns) +{ + int rc = RTCritSectEnter(&pIns->hostHeapCritSect); + AssertRC(rc); + return rc; +} + +static void hgsmiHostHeapUnlock(HGSMIINSTANCE *pIns) +{ + int rc = RTCritSectLeave(&pIns->hostHeapCritSect); + AssertRC(rc); +} + +static HGSMIOFFSET hgsmiHostHeapOffset(HGSMIHOSTHEAP *pHeap) +{ + return pHeap->area.offBase; +} + +static HGSMISIZE hgsmiHostHeapSize(HGSMIHOSTHEAP *pHeap) +{ + return pHeap->area.cbArea; +} + +static void RT_UNTRUSTED_VOLATILE_GUEST *hgsmiHostHeapBufferAlloc(HGSMIHOSTHEAP *pHeap, HGSMISIZE cbBuffer) +{ + void RT_UNTRUSTED_VOLATILE_GUEST *pvBuf = NULL; + + if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_MA) + pvBuf = HGSMIMAAlloc(&pHeap->u.ma, cbBuffer); + else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_POINTER) + pvBuf = RTHeapSimpleAlloc(pHeap->u.legacy.u.hPtr, cbBuffer, 0); + else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_OFFSET) + pvBuf = RTHeapOffsetAlloc(pHeap->u.legacy.u.hOff, cbBuffer, 0); + if (pvBuf) + ASMAtomicIncS32(&pHeap->cRefs); + + return pvBuf; +} + +static void hgsmiHostHeapBufferFree(HGSMIHOSTHEAP *pHeap, void RT_UNTRUSTED_VOLATILE_GUEST *pvBuf) +{ + if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_MA) + HGSMIMAFree(&pHeap->u.ma, pvBuf); + else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_POINTER) + RTHeapSimpleFree(pHeap->u.legacy.u.hPtr, (void *)pvBuf); + else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_OFFSET) + RTHeapOffsetFree(pHeap->u.legacy.u.hOff, (void *)pvBuf); + ASMAtomicDecS32(&pHeap->cRefs); +} + +static void RT_UNTRUSTED_VOLATILE_GUEST *hgsmiHostHeapDataAlloc(HGSMIHOSTHEAP *pHeap, HGSMISIZE cbData, + uint8_t u8Channel, uint16_t u16ChannelInfo) +{ + HGSMISIZE cbAlloc = HGSMIBufferRequiredSize(cbData); + HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)hgsmiHostHeapBufferAlloc(pHeap, cbAlloc); + if (!pHeader) + return NULL; + + HGSMIBufferInitializeSingle(&pHeap->area, pHeader, cbAlloc, u8Channel, u16ChannelInfo); + + return HGSMIBufferDataFromPtr(pHeader); +} + +static void hgsmiHostHeapDataFree(HGSMIHOSTHEAP *pHeap, void RT_UNTRUSTED_VOLATILE_GUEST *pvData) +{ + if ( pvData + && pHeap->u32HeapType != HGSMI_HEAP_TYPE_NULL) + { + HGSMIBUFFERHEADER RT_UNTRUSTED_VOLATILE_GUEST *pHeader = HGSMIBufferHeaderFromData(pvData); + hgsmiHostHeapBufferFree(pHeap, pHeader); + } +} + +/* Needed for heap relocation: offset of the heap handle relative to the start of heap area. */ +static HGSMIOFFSET hgsmiHostHeapHandleLocationOffset(HGSMIHOSTHEAP *pHeap) +{ + HGSMIOFFSET offHeapHandle; + if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_POINTER) + offHeapHandle = (HGSMIOFFSET)((uintptr_t)pHeap->u.legacy.u.hPtr - (uintptr_t)pHeap->area.pu8Base); + else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_OFFSET) + offHeapHandle = (HGSMIOFFSET)((uintptr_t)pHeap->u.legacy.u.hOff - (uintptr_t)pHeap->area.pu8Base); + else + offHeapHandle = HGSMIOFFSET_VOID; + return offHeapHandle; +} + +static int hgsmiHostHeapRelocate(HGSMIHOSTHEAP *pHeap, + uint32_t u32HeapType, + void *pvBase, + uint32_t offHeapHandle, + uintptr_t offDelta, + HGSMISIZE cbArea, + HGSMIOFFSET offBase) +{ + int rc = HGSMIAreaInitialize(&pHeap->area, pvBase, cbArea, offBase); + if (RT_SUCCESS(rc)) + { + if (u32HeapType == HGSMI_HEAP_TYPE_OFFSET) + pHeap->u.legacy.u.hOff = (RTHEAPOFFSET)((uint8_t *)pvBase + offHeapHandle); + else if (u32HeapType == HGSMI_HEAP_TYPE_POINTER) + { + pHeap->u.legacy.u.hPtr = (RTHEAPSIMPLE)((uint8_t *)pvBase + offHeapHandle); + rc = RTHeapSimpleRelocate(pHeap->u.legacy.u.hPtr, offDelta); AssertRC(rc); + } + else + { + /* HGSMI_HEAP_TYPE_MA does not need the relocation. */ + rc = VERR_NOT_SUPPORTED; + } + + if (RT_SUCCESS(rc)) + pHeap->u32HeapType = u32HeapType; + else + HGSMIAreaClear(&pHeap->area); + } + + return rc; +} + +static int hgsmiHostHeapRestoreMA(HGSMIHOSTHEAP *pHeap, + void *pvBase, + HGSMISIZE cbArea, + HGSMIOFFSET offBase, + uint32_t cBlocks, + HGSMIOFFSET *paDescriptors, + HGSMISIZE cbMaxBlock, + HGSMIENV *pEnv) +{ + int rc = HGSMIAreaInitialize(&pHeap->area, pvBase, cbArea, offBase); + if (RT_SUCCESS(rc)) + { + rc = HGSMIMAInit(&pHeap->u.ma, &pHeap->area, paDescriptors, cBlocks, cbMaxBlock, pEnv); + if (RT_SUCCESS(rc)) + pHeap->u32HeapType = HGSMI_HEAP_TYPE_MA; + else + HGSMIAreaClear(&pHeap->area); + } + + return rc; +} + +static void hgsmiHostHeapSetupUninitialized(HGSMIHOSTHEAP *pHeap) +{ + RT_ZERO(*pHeap); + pHeap->u32HeapType = HGSMI_HEAP_TYPE_NULL; +} + +static void hgsmiHostHeapDestroy(HGSMIHOSTHEAP *pHeap) +{ + if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_MA) + HGSMIMAUninit(&pHeap->u.ma); + hgsmiHostHeapSetupUninitialized(pHeap); +} + +static int hgsmiHostFIFOAlloc(HGSMIHOSTFIFOENTRY **ppEntry) +{ + HGSMIHOSTFIFOENTRY *pEntry = (HGSMIHOSTFIFOENTRY *)RTMemAllocZ(sizeof(HGSMIHOSTFIFOENTRY)); + if (pEntry) + { + pEntry->fl = HGSMI_F_HOST_FIFO_ALLOCATED; + *ppEntry = pEntry; + return VINF_SUCCESS; + } + return VERR_NO_MEMORY; +} + +static void hgsmiHostFIFOFree(HGSMIHOSTFIFOENTRY *pEntry) +{ + RTMemFree(pEntry); +} + +static int hgsmiHostCommandFreeByEntry (HGSMIHOSTFIFOENTRY *pEntry) +{ + LogFlowFunc(("offBuffer 0x%08X\n", pEntry->offBuffer)); + + HGSMIINSTANCE *pIns = pEntry->pIns; + int rc = hgsmiFIFOLock(pIns); + if (RT_SUCCESS(rc)) + { + RTListNodeRemove(&pEntry->nodeEntry); + hgsmiFIFOUnlock(pIns); + + void RT_UNTRUSTED_VOLATILE_GUEST *pvData = HGSMIBufferDataFromOffset(&pIns->hostHeap.area, pEntry->offBuffer); + + rc = hgsmiHostHeapLock(pIns); + if (RT_SUCCESS(rc)) + { + /* Deallocate the host heap memory. */ + hgsmiHostHeapDataFree(&pIns->hostHeap, pvData); + + hgsmiHostHeapUnlock(pIns); + } + + hgsmiHostFIFOFree(pEntry); + } + + LogFlowFunc(("%Rrc\n", rc)); + return rc; +} + +static int hgsmiHostCommandFree(HGSMIINSTANCE *pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvData) +{ + HGSMIOFFSET offBuffer = HGSMIBufferOffsetFromData(&pIns->hostHeap.area, pvData); + HGSMIHOSTFIFOENTRY *pEntry = NULL; + + int rc = hgsmiFIFOLock(pIns); + if (RT_SUCCESS(rc)) + { + /* Search the Processed list for the given offBuffer. */ + HGSMIHOSTFIFOENTRY *pIter; + RTListForEach(&pIns->hostFIFOProcessed, pIter, HGSMIHOSTFIFOENTRY, nodeEntry) + { + Assert(pIter->fl == (HGSMI_F_HOST_FIFO_ALLOCATED | HGSMI_F_HOST_FIFO_PROCESSED)); + + if (pIter->offBuffer == offBuffer) + { + pEntry = pIter; + break; + } + } + + if (pEntry) + RTListNodeRemove(&pEntry->nodeEntry); + else + AssertLogRelMsgFailed(("HGSMI[%s]: the host frees unprocessed FIFO entry: 0x%08X\n", + pIns->pszName, offBuffer)); + + hgsmiFIFOUnlock(pIns); + + rc = hgsmiHostHeapLock(pIns); + if (RT_SUCCESS(rc)) + { + /* Deallocate the host heap memory. */ + hgsmiHostHeapDataFree(&pIns->hostHeap, pvData); + + hgsmiHostHeapUnlock(pIns); + } + + if (pEntry) + { + /* Deallocate the entry. */ + hgsmiHostFIFOFree(pEntry); + } + } + + return rc; +} + +static DECLCALLBACK(void) hgsmiHostCommandFreeCallback(void *pvCallback) +{ + /* Guest has processed the command. */ + HGSMIHOSTFIFOENTRY *pEntry = (HGSMIHOSTFIFOENTRY *)pvCallback; + + Assert(pEntry->fl == (HGSMI_F_HOST_FIFO_ALLOCATED | HGSMI_F_HOST_FIFO_PROCESSED)); + + /* This is a simple callback, just signal the event. */ + hgsmiHostCommandFreeByEntry(pEntry); +} + +static int hgsmiHostCommandWrite(HGSMIINSTANCE *pIns, HGSMIOFFSET offBuffer) +{ + AssertPtrReturn(pIns->pHGFlags, VERR_WRONG_ORDER); + + HGSMIHOSTFIFOENTRY *pEntry; + int rc = hgsmiHostFIFOAlloc(&pEntry); + if (RT_SUCCESS(rc)) + { + /* Initialize the new entry and add it to the FIFO. */ + pEntry->fl |= HGSMI_F_HOST_FIFO_QUEUED; + + pEntry->pIns = pIns; + pEntry->offBuffer = offBuffer; + + rc = hgsmiFIFOLock(pIns); + if (RT_SUCCESS(rc)) + { + ASMAtomicOrU32(&pIns->pHGFlags->u32HostFlags, HGSMIHOSTFLAGS_COMMANDS_PENDING); + RTListAppend(&pIns->hostFIFO, &pEntry->nodeEntry); + + hgsmiFIFOUnlock(pIns); + } + else + hgsmiHostFIFOFree(pEntry); + } + + return rc; +} + + +/** + * Append the shared memory block to the FIFO, inform the guest. + * + * @param pIns Pointer to HGSMI instance. + * @param pvData The shared memory block data pointer. + * @param fDoIrq Whether the guest interrupt should be generated, i.e. if the command is not + * urgent (e.g. some guest command completion notification that does not require + * post-processing) the command could be submitted without raising an irq. + * @thread EMT + */ +static int hgsmiHostCommandSubmit(HGSMIINSTANCE *pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvData, bool fDoIrq) +{ + /* Append the command to FIFO. */ + HGSMIOFFSET offBuffer = HGSMIBufferOffsetFromData(&pIns->hostHeap.area, pvData); + int rc = hgsmiHostCommandWrite(pIns, offBuffer); + if (RT_SUCCESS(rc)) + { + if (fDoIrq) + { + /* Now guest can read the FIFO, the notification is informational. */ + hgsmiNotifyGuest(pIns); + } + } + + return rc; +} + +/** + * Allocate a shared memory buffer. The host can write command/data to the memory. + * The allocated buffer contains the 'header', 'data' and the 'tail', but *ppvData + * will point to the 'data'. + * + * @return VBox status code. Pointer to the payload data in *ppvData. + * @param pIns HGSMI instance, + * @param ppvData Where to store the allocated memory pointer to data. + * @param cbData How many bytes of data to allocate. + * @param u8Channel HGSMI channel. + * @param u16ChannelInfo Command parameter. + */ +int HGSMIHostCommandAlloc(HGSMIINSTANCE *pIns, void RT_UNTRUSTED_VOLATILE_GUEST **ppvData, HGSMISIZE cbData, + uint8_t u8Channel, uint16_t u16ChannelInfo) +{ + LogFlowFunc(("pIns = %p, cbData = %d, u8Channel %d, u16ChannelInfo 0x%04X\n", + pIns, cbData, u8Channel, u16ChannelInfo)); + + int rc = hgsmiHostHeapLock(pIns); + if (RT_SUCCESS(rc)) + { + void RT_UNTRUSTED_VOLATILE_GUEST *pvData = hgsmiHostHeapDataAlloc(&pIns->hostHeap, cbData, u8Channel, u16ChannelInfo); + hgsmiHostHeapUnlock(pIns); + + if (pvData) + *ppvData = pvData; + else + { + LogRel(("HGSMI[%s]: host heap allocation failed %d bytes\n", pIns->pszName, cbData)); + rc = VERR_NO_MEMORY; + } + } + + LogFlowFunc(("%Rrc, pvData = %p\n", rc, *ppvData)); + return rc; +} + +/** + * Convenience function that allows posting the host command asynchronously + * and make it freed on completion. + * The caller does not get notified in any way on command completion, + * on successful return the pvData buffer can not be used after being passed to this function. + * + * @param pIns HGSMI instance, + * @param pvData The pointer returned by 'HGSMIHostCommandAlloc'. + * @param fDoIrq Specifies whether the guest interrupt should be generated. + * In case the command is not urgent (e.g. some guest command + * completion notification that does not require post-processing) + * the command could be posted without raising an irq. + */ +int HGSMIHostCommandSubmitAndFreeAsynch(PHGSMIINSTANCE pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvData, bool fDoIrq) +{ + LogFlowFunc(("pIns = %p, pvData = %p, fDoIrq = %d\n", pIns, pvData, fDoIrq)); + + int rc; + if (HGSMIAreaContainsPointer(&pIns->hostHeap.area, pvData)) + rc = hgsmiHostCommandSubmit(pIns, pvData, fDoIrq); + else + { + AssertLogRelMsgFailed(("HGSMI[%s]: host submits invalid command %p/%p\n", + pIns->pszName, pvData, pIns->hostHeap.area.pu8Base)); + rc = VERR_INVALID_POINTER; + } + + LogFlowFunc(("rc = %Rrc\n", rc)); + return rc; +} + +/** + * Free the shared memory block. + * + * @param pIns Pointer to HGSMI instance, + * @param pvData The pointer returned by 'HGSMIHostCommandAlloc'. + */ +int HGSMIHostCommandFree(HGSMIINSTANCE *pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvData) +{ + LogFlowFunc(("pIns = %p, pvData = %p\n", pIns, pvData)); + + int rc; + if (HGSMIAreaContainsPointer(&pIns->hostHeap.area, pvData)) + rc = hgsmiHostCommandFree(pIns, pvData); + else + { + AssertLogRelMsgFailed(("HGSMI[%s]: the host frees invalid FIFO entry %p/%p\n", + pIns->pszName, pvData, pIns->hostHeap.area.pu8Base)); + rc = VERR_INVALID_POINTER; + } + + LogFlowFunc(("rc = %Rrc\n", rc)); + return rc; +} + +static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb) +{ + NOREF(pvEnv); + return RTMemAlloc(cb); +} + +static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv) +{ + NOREF(pvEnv); + RTMemFree(pv); +} + +static HGSMIENV g_hgsmiEnv = +{ + NULL, + hgsmiEnvAlloc, + hgsmiEnvFree +}; + +int HGSMIHostHeapSetup(PHGSMIINSTANCE pIns, HGSMIOFFSET RT_UNTRUSTED_GUEST offHeap, HGSMISIZE RT_UNTRUSTED_GUEST cbHeap) +{ + LogFlowFunc(("pIns %p, offHeap 0x%08X, cbHeap = 0x%08X\n", pIns, offHeap, cbHeap)); + + /* + * Validate input. + */ + AssertPtrReturn(pIns, VERR_INVALID_PARAMETER); + + ASSERT_GUEST_LOGREL_MSG_RETURN( offHeap < pIns->area.cbArea + && cbHeap <= pIns->area.cbArea + && offHeap <= pIns->area.cbArea - cbHeap, + ("Heap: %#x LB %#x; Area: %#x LB %#x\n", offHeap, cbHeap, pIns->area.offBase, pIns->area.cbArea), + VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* + * Lock the heap and do the job. + */ + int rc = hgsmiHostHeapLock(pIns); + AssertRCReturn(rc, rc); + + /* It is possible to change the heap only if there is no pending allocations. */ + ASSERT_GUEST_LOGREL_MSG_STMT_RETURN(pIns->hostHeap.cRefs == 0, + ("HGSMI[%s]: host heap setup ignored. %d allocated.\n", pIns->pszName, pIns->hostHeap.cRefs), + hgsmiHostHeapUnlock(pIns), + VERR_ACCESS_DENIED); + rc = HGSMIAreaInitialize(&pIns->hostHeap.area, pIns->area.pu8Base + offHeap, cbHeap, offHeap); + if (RT_SUCCESS(rc)) + { + rc = HGSMIMAInit(&pIns->hostHeap.u.ma, &pIns->hostHeap.area, NULL, 0, 0, &g_hgsmiEnv); + if (RT_SUCCESS(rc)) + pIns->hostHeap.u32HeapType = HGSMI_HEAP_TYPE_MA; + else + HGSMIAreaClear(&pIns->hostHeap.area); + } + + hgsmiHostHeapUnlock(pIns); + + LogFlowFunc(("rc = %Rrc\n", rc)); + return rc; +} + +static int hgsmiHostSaveFifoLocked(PCPDMDEVHLPR3 pHlp, RTLISTANCHOR *pList, PSSMHANDLE pSSM) +{ + VBOXHGSMI_SAVE_FIFOSTART(pSSM); + + HGSMIHOSTFIFOENTRY *pIter; + + uint32_t cEntries = 0; + RTListForEach(pList, pIter, HGSMIHOSTFIFOENTRY, nodeEntry) + { + ++cEntries; + } + + int rc = pHlp->pfnSSMPutU32(pSSM, cEntries); + if (RT_SUCCESS(rc)) + { + RTListForEach(pList, pIter, HGSMIHOSTFIFOENTRY, nodeEntry) + { + pHlp->pfnSSMPutU32(pSSM, pIter->fl); + rc = pHlp->pfnSSMPutU32(pSSM, pIter->offBuffer); + if (RT_FAILURE(rc)) + break; + } + } + + VBOXHGSMI_SAVE_FIFOSTOP(pSSM); + + return rc; +} + +static int hgsmiHostSaveGuestCmdCompletedFifoLocked(PCPDMDEVHLPR3 pHlp, RTLISTANCHOR *pList, PSSMHANDLE pSSM) +{ + VBOXHGSMI_SAVE_FIFOSTART(pSSM); + + HGSMIGUESTCOMPLENTRY *pIter; + + uint32_t cEntries = 0; + RTListForEach(pList, pIter, HGSMIGUESTCOMPLENTRY, nodeEntry) + { + ++cEntries; + } + int rc = pHlp->pfnSSMPutU32(pSSM, cEntries); + if (RT_SUCCESS(rc)) + { + RTListForEach(pList, pIter, HGSMIGUESTCOMPLENTRY, nodeEntry) + { + rc = pHlp->pfnSSMPutU32(pSSM, pIter->offBuffer); + if (RT_FAILURE(rc)) + break; + } + } + + VBOXHGSMI_SAVE_FIFOSTOP(pSSM); + + return rc; +} + +static int hgsmiHostLoadFifoEntryLocked(PCPDMDEVHLPR3 pHlp, PHGSMIINSTANCE pIns, HGSMIHOSTFIFOENTRY **ppEntry, PSSMHANDLE pSSM) +{ + HGSMIHOSTFIFOENTRY *pEntry; + int rc = hgsmiHostFIFOAlloc(&pEntry); AssertRC(rc); + if (RT_SUCCESS(rc)) + { + uint32_t u32; + pEntry->pIns = pIns; + rc = pHlp->pfnSSMGetU32(pSSM, &u32); AssertRC(rc); + pEntry->fl = u32; + rc = pHlp->pfnSSMGetU32(pSSM, &pEntry->offBuffer); AssertRC(rc); + if (RT_SUCCESS(rc)) + *ppEntry = pEntry; + else + hgsmiHostFIFOFree(pEntry); + } + + return rc; +} + +static int hgsmiHostLoadFifoLocked(PCPDMDEVHLPR3 pHlp, PHGSMIINSTANCE pIns, RTLISTANCHOR *pList, PSSMHANDLE pSSM) +{ + VBOXHGSMI_LOAD_FIFOSTART(pSSM); + + uint32_t cEntries = 0; + int rc = pHlp->pfnSSMGetU32(pSSM, &cEntries); + if (RT_SUCCESS(rc) && cEntries) + { + uint32_t i; + for (i = 0; i < cEntries; ++i) + { + HGSMIHOSTFIFOENTRY *pEntry = NULL; + rc = hgsmiHostLoadFifoEntryLocked(pHlp, pIns, &pEntry, pSSM); + AssertRCBreak(rc); + + RTListAppend(pList, &pEntry->nodeEntry); + } + } + + VBOXHGSMI_LOAD_FIFOSTOP(pSSM); + + return rc; +} + +static int hgsmiHostLoadGuestCmdCompletedFifoEntryLocked(PCPDMDEVHLPR3 pHlp, PHGSMIINSTANCE pIns, + HGSMIGUESTCOMPLENTRY **ppEntry, PSSMHANDLE pSSM) +{ + HGSMIGUESTCOMPLENTRY *pEntry; + int rc = hgsmiGuestCompletionFIFOAlloc(pIns, &pEntry); AssertRC(rc); + if (RT_SUCCESS (rc)) + { + rc = pHlp->pfnSSMGetU32(pSSM, &pEntry->offBuffer); AssertRC(rc); + if (RT_SUCCESS(rc)) + *ppEntry = pEntry; + else + hgsmiGuestCompletionFIFOFree(pIns, pEntry); + } + return rc; +} + +static int hgsmiHostLoadGuestCmdCompletedFifoLocked(PCPDMDEVHLPR3 pHlp, PHGSMIINSTANCE pIns, RTLISTANCHOR *pList, + PSSMHANDLE pSSM, uint32_t u32Version) +{ + VBOXHGSMI_LOAD_FIFOSTART(pSSM); + + uint32_t i; + + uint32_t cEntries = 0; + int rc = pHlp->pfnSSMGetU32(pSSM, &cEntries); + if (RT_SUCCESS(rc) && cEntries) + { + if (u32Version > VGA_SAVEDSTATE_VERSION_INV_GCMDFIFO) + { + for (i = 0; i < cEntries; ++i) + { + HGSMIGUESTCOMPLENTRY *pEntry = NULL; + rc = hgsmiHostLoadGuestCmdCompletedFifoEntryLocked(pHlp, pIns, &pEntry, pSSM); + AssertRCBreak(rc); + + RTListAppend(pList, &pEntry->nodeEntry); + } + } + else + { + LogRel(("WARNING: the current saved state version has some 3D support data missing, " + "which may lead to some guest applications function improperly")); + + /* Just read out all invalid data and discard it. */ + for (i = 0; i < cEntries; ++i) + { + HGSMIHOSTFIFOENTRY *pEntry = NULL; + rc = hgsmiHostLoadFifoEntryLocked(pHlp, pIns, &pEntry, pSSM); + AssertRCBreak(rc); + + hgsmiHostFIFOFree(pEntry); + } + } + } + + VBOXHGSMI_LOAD_FIFOSTOP(pSSM); + + return rc; +} + +static int hgsmiHostSaveMA(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, HGSMIMADATA *pMA) +{ + int rc = pHlp->pfnSSMPutU32(pSSM, pMA->cBlocks); + if (RT_SUCCESS(rc)) + { + HGSMIMABLOCK *pIter; + RTListForEach(&pMA->listBlocks, pIter, HGSMIMABLOCK, nodeBlock) + { + pHlp->pfnSSMPutU32(pSSM, pIter->descriptor); + } + + rc = pHlp->pfnSSMPutU32(pSSM, pMA->cbMaxBlock); + } + + return rc; +} + +static int hgsmiHostLoadMA(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, uint32_t *pcBlocks, + HGSMIOFFSET **ppaDescriptors, HGSMISIZE *pcbMaxBlock) +{ + int rc = pHlp->pfnSSMGetU32(pSSM, pcBlocks); + if (RT_SUCCESS(rc)) + { + HGSMIOFFSET *paDescriptors = NULL; + if (*pcBlocks > 0) + { + paDescriptors = (HGSMIOFFSET *)RTMemAlloc(*pcBlocks * sizeof(HGSMIOFFSET)); + if (paDescriptors) + { + uint32_t i; + for (i = 0; i < *pcBlocks; ++i) + pHlp->pfnSSMGetU32(pSSM, &paDescriptors[i]); + } + else + rc = VERR_NO_MEMORY; + } + + if (RT_SUCCESS(rc)) + rc = pHlp->pfnSSMGetU32(pSSM, pcbMaxBlock); + if (RT_SUCCESS(rc)) + *ppaDescriptors = paDescriptors; + else + RTMemFree(paDescriptors); + } + + return rc; +} + +int HGSMIHostSaveStateExec(PCPDMDEVHLPR3 pHlp, PHGSMIINSTANCE pIns, PSSMHANDLE pSSM) +{ + VBOXHGSMI_SAVE_START(pSSM); + + int rc; + + pHlp->pfnSSMPutU32(pSSM, pIns->hostHeap.u32HeapType); + + HGSMIOFFSET off = pIns->pHGFlags ? HGSMIPointerToOffset(&pIns->area, (const HGSMIBUFFERHEADER *)pIns->pHGFlags) + : HGSMIOFFSET_VOID; + pHlp->pfnSSMPutU32(pSSM, off); + + off = pIns->hostHeap.u32HeapType == HGSMI_HEAP_TYPE_MA ? 0 : hgsmiHostHeapHandleLocationOffset(&pIns->hostHeap); + rc = pHlp->pfnSSMPutU32 (pSSM, off); + if (off != HGSMIOFFSET_VOID) + { + pHlp->pfnSSMPutU32(pSSM, hgsmiHostHeapOffset(&pIns->hostHeap)); + pHlp->pfnSSMPutU32(pSSM, hgsmiHostHeapSize(&pIns->hostHeap)); + /* need save mem pointer to calculate offset on restore */ + pHlp->pfnSSMPutU64(pSSM, (uint64_t)(uintptr_t)pIns->area.pu8Base); + rc = hgsmiFIFOLock (pIns); + if (RT_SUCCESS(rc)) + { + rc = hgsmiHostSaveFifoLocked(pHlp, &pIns->hostFIFO, pSSM); AssertRC(rc); + rc = hgsmiHostSaveFifoLocked(pHlp, &pIns->hostFIFORead, pSSM); AssertRC(rc); + rc = hgsmiHostSaveFifoLocked(pHlp, &pIns->hostFIFOProcessed, pSSM); AssertRC(rc); +#ifdef VBOX_WITH_WDDM + rc = hgsmiHostSaveGuestCmdCompletedFifoLocked(pHlp, &pIns->guestCmdCompleted, pSSM); AssertRC(rc); +#endif + + hgsmiFIFOUnlock(pIns); + } + + if (RT_SUCCESS(rc)) + if (pIns->hostHeap.u32HeapType == HGSMI_HEAP_TYPE_MA) + rc = hgsmiHostSaveMA(pHlp, pSSM, &pIns->hostHeap.u.ma); + } + + VBOXHGSMI_SAVE_STOP(pSSM); + + return rc; +} + +int HGSMIHostLoadStateExec(PCPDMDEVHLPR3 pHlp, PHGSMIINSTANCE pIns, PSSMHANDLE pSSM, uint32_t u32Version) +{ + if (u32Version < VGA_SAVEDSTATE_VERSION_HGSMI) + return VINF_SUCCESS; + + VBOXHGSMI_LOAD_START(pSSM); + + int rc; + uint32_t u32HeapType = HGSMI_HEAP_TYPE_NULL; + if (u32Version >= VGA_SAVEDSTATE_VERSION_HGSMIMA) + { + rc = pHlp->pfnSSMGetU32(pSSM, &u32HeapType); + AssertRCReturn(rc, rc); + } + + HGSMIOFFSET off; + rc = pHlp->pfnSSMGetU32(pSSM, &off); + AssertLogRelRCReturn(rc, rc); + pIns->pHGFlags = off != HGSMIOFFSET_VOID ? (HGSMIHOSTFLAGS *)HGSMIOffsetToPointer(&pIns->area, off) : NULL; + + rc = pHlp->pfnSSMGetU32(pSSM, &off); + AssertLogRelRCReturn(rc, rc); + if (off != HGSMIOFFSET_VOID) + { + /* There is a saved heap. */ + if (u32HeapType == HGSMI_HEAP_TYPE_NULL) + u32HeapType = u32Version > VGA_SAVEDSTATE_VERSION_HOST_HEAP + ? HGSMI_HEAP_TYPE_OFFSET : HGSMI_HEAP_TYPE_POINTER; + + HGSMIOFFSET offHeap; + pHlp->pfnSSMGetU32(pSSM, &offHeap); + uint32_t cbHeap; + pHlp->pfnSSMGetU32(pSSM, &cbHeap); + uint64_t oldMem; + rc = pHlp->pfnSSMGetU64(pSSM, &oldMem); + AssertLogRelRCReturn(rc, rc); + + if (RT_SUCCESS(rc)) + { + rc = hgsmiFIFOLock(pIns); + if (RT_SUCCESS(rc)) + { + rc = hgsmiHostLoadFifoLocked(pHlp, pIns, &pIns->hostFIFO, pSSM); + if (RT_SUCCESS(rc)) + rc = hgsmiHostLoadFifoLocked(pHlp, pIns, &pIns->hostFIFORead, pSSM); + if (RT_SUCCESS(rc)) + rc = hgsmiHostLoadFifoLocked(pHlp, pIns, &pIns->hostFIFOProcessed, pSSM); +#ifdef VBOX_WITH_WDDM + if (RT_SUCCESS(rc) && u32Version > VGA_SAVEDSTATE_VERSION_PRE_WDDM) + rc = hgsmiHostLoadGuestCmdCompletedFifoLocked(pHlp, pIns, &pIns->guestCmdCompleted, pSSM, u32Version); +#endif + + hgsmiFIFOUnlock(pIns); + } + } + + if (RT_SUCCESS(rc)) + { + if (u32HeapType == HGSMI_HEAP_TYPE_MA) + { + uint32_t cBlocks = 0; + HGSMISIZE cbMaxBlock = 0; + HGSMIOFFSET *paDescriptors = NULL; + rc = hgsmiHostLoadMA(pHlp, pSSM, &cBlocks, &paDescriptors, &cbMaxBlock); + if (RT_SUCCESS(rc)) + { + rc = hgsmiHostHeapRestoreMA(&pIns->hostHeap, + pIns->area.pu8Base+offHeap, + cbHeap, + offHeap, + cBlocks, + paDescriptors, + cbMaxBlock, + &g_hgsmiEnv); + + RTMemFree(paDescriptors); + } + } + else if ( u32HeapType == HGSMI_HEAP_TYPE_OFFSET + || u32HeapType == HGSMI_HEAP_TYPE_POINTER) + { + rc = hgsmiHostHeapLock(pIns); + if (RT_SUCCESS(rc)) + { + Assert(!pIns->hostHeap.cRefs); + pIns->hostHeap.cRefs = 0; + + rc = hgsmiHostHeapRelocate(&pIns->hostHeap, + u32HeapType, + pIns->area.pu8Base+offHeap, + off, + uintptr_t(pIns->area.pu8Base) - uintptr_t(oldMem), + cbHeap, + offHeap); + + hgsmiHostHeapUnlock(pIns); + } + } + } + } + + VBOXHGSMI_LOAD_STOP(pSSM); + + return rc; +} + +/* + * Channels management. + */ + +/* Register a new HGSMI channel by a predefined index. + */ +int HGSMIHostChannelRegister(PHGSMIINSTANCE pIns, uint8_t u8Channel, + PFNHGSMICHANNELHANDLER pfnChannelHandler, void *pvChannelHandler) +{ + LogFlowFunc(("pIns %p, u8Channel %x, pfnChannelHandler %p, pvChannelHandler %p\n", + pIns, u8Channel, pfnChannelHandler, pvChannelHandler)); + + AssertReturn(!HGSMI_IS_DYNAMIC_CHANNEL(u8Channel), VERR_INVALID_PARAMETER); + AssertPtrReturn(pIns, VERR_INVALID_PARAMETER); + AssertPtrReturn(pfnChannelHandler, VERR_INVALID_PARAMETER); + + int rc = hgsmiLock(pIns); + + if (RT_SUCCESS(rc)) + { + rc = HGSMIChannelRegister(&pIns->channelInfo, u8Channel, NULL, pfnChannelHandler, pvChannelHandler); + + hgsmiUnlock(pIns); + } + + LogFlowFunc(("leave rc = %Rrc\n", rc)); + return rc; +} + +#if 0 /* unused */ + +static int hgsmiChannelMapCreate(PHGSMIINSTANCE pIns, const char *pszChannel, uint8_t *pu8Channel) +{ + RT_NOREF(pIns, pszChannel, pu8Channel); + /** @todo later */ + return VERR_NOT_SUPPORTED; +} + +/** + * Register a new HGSMI channel by name. + * + * @note currently unused. + */ +int HGSMIChannelRegisterName(PHGSMIINSTANCE pIns, + const char *pszChannel, + PFNHGSMICHANNELHANDLER pfnChannelHandler, + void *pvChannelHandler, + uint8_t *pu8Channel) +{ + LogFlowFunc(("pIns %p, pszChannel %s, pfnChannelHandler %p, pvChannelHandler %p, pu8Channel %p\n", + pIns, pszChannel, pfnChannelHandler, pvChannelHandler, pu8Channel)); + + AssertPtrReturn(pIns, VERR_INVALID_PARAMETER); + AssertPtrReturn(pszChannel, VERR_INVALID_PARAMETER); + AssertPtrReturn(pu8Channel, VERR_INVALID_PARAMETER); + AssertPtrReturn(pfnChannelHandler, VERR_INVALID_PARAMETER); + + int rc; + + /* The pointer to the copy will be saved in the channel description. */ + char *pszName = RTStrDup (pszChannel); + + if (pszName) + { + rc = hgsmiLock (pIns); + + if (RT_SUCCESS (rc)) + { + rc = hgsmiChannelMapCreate (pIns, pszName, pu8Channel); + + if (RT_SUCCESS (rc)) + { + rc = HGSMIChannelRegister (&pIns->channelInfo, *pu8Channel, pszName, pfnChannelHandler, pvChannelHandler); + } + + hgsmiUnlock (pIns); + } + + if (RT_FAILURE (rc)) + { + RTStrFree (pszName); + } + } + else + { + rc = VERR_NO_MEMORY; + } + + LogFlowFunc(("leave rc = %Rrc\n", rc)); + + return rc; +} +#endif + +void RT_UNTRUSTED_VOLATILE_GUEST *HGSMIOffsetToPointerHost(PHGSMIINSTANCE pIns, HGSMIOFFSET offBuffer) +{ + const HGSMIAREA *pArea = &pIns->area; + HGSMIOFFSET const offArea = offBuffer - pArea->offBase; + ASSERT_GUEST_MSG_RETURN(offArea < pArea->cbArea, + ("offBuffer=%#x; area %#x LB %#x\n", offBuffer, pArea->offBase, pArea->cbArea), + NULL); + return &pArea->pu8Base[offArea]; +} + + +HGSMIOFFSET HGSMIPointerToOffsetHost(PHGSMIINSTANCE pIns, const void RT_UNTRUSTED_VOLATILE_GUEST *pv) +{ + const HGSMIAREA *pArea = &pIns->area; + uintptr_t const offArea = (uintptr_t)pv - (uintptr_t)pArea->pu8Base; + ASSERT_GUEST_MSG_RETURN(offArea < pArea->cbArea, + ("pv=%p; area %#x LB %#x\n", pv, pArea->offBase, pArea->cbArea), + HGSMIOFFSET_VOID); + return pArea->offBase + (HGSMIOFFSET)offArea; +} + + +/** + * Checks if @a offBuffer is within the area of this instance. + * + * This is for use in input validations. + * + * @returns true / false. + * @param pIns The instance. + * @param offBuffer The buffer offset to check. + */ +bool HGSMIIsOffsetValid(PHGSMIINSTANCE pIns, HGSMIOFFSET offBuffer) +{ + return pIns + && offBuffer - pIns->area.offBase < pIns->area.cbArea; +} + + +/** + * Returns the area offset for use in logging and assertion messages. + */ +HGSMIOFFSET HGSMIGetAreaOffset(PHGSMIINSTANCE pIns) +{ + return pIns ? pIns->area.offBase : ~(HGSMIOFFSET)0; +} + + +/** + * Returns the area size for use in logging and assertion messages. + */ +HGSMIOFFSET HGSMIGetAreaSize(PHGSMIINSTANCE pIns) +{ + return pIns ? pIns->area.cbArea : 0; +} + + +void *HGSMIContext(PHGSMIINSTANCE pIns) +{ + uint8_t *p = (uint8_t *)pIns; + return p + sizeof(HGSMIINSTANCE); +} + +/* The guest submitted a buffer. */ +static DECLCALLBACK(int) hgsmiChannelHandler(void *pvHandler, uint16_t u16ChannelInfo, + RT_UNTRUSTED_VOLATILE_GUEST void *pvBuffer, HGSMISIZE cbBuffer) +{ + int rc = VINF_SUCCESS; + + LogFlowFunc(("pvHandler %p, u16ChannelInfo %d, pvBuffer %p, cbBuffer %u\n", + pvHandler, u16ChannelInfo, pvBuffer, cbBuffer)); + + PHGSMIINSTANCE pIns = (PHGSMIINSTANCE)pvHandler; + + switch (u16ChannelInfo) + { + case HGSMI_CC_HOST_FLAGS_LOCATION: + { + ASSERT_GUEST_RETURN(cbBuffer >= sizeof(HGSMIBUFFERLOCATION), VERR_INVALID_PARAMETER); + HGSMIBUFFERLOCATION RT_UNTRUSTED_VOLATILE_GUEST *pLoc = (HGSMIBUFFERLOCATION RT_UNTRUSTED_VOLATILE_GUEST *)pvBuffer; + HGSMIBUFFERLOCATION LocSafe; + LocSafe.cbLocation = pLoc->cbLocation; + LocSafe.offLocation = pLoc->offLocation; + RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); + + ASSERT_GUEST_RETURN(LocSafe.cbLocation == sizeof(HGSMIHOSTFLAGS), VERR_INVALID_PARAMETER); + ASSERT_GUEST_RETURN(LocSafe.offLocation + sizeof(HGSMIHOSTFLAGS) == pIns->area.cbArea, VERR_INVALID_PARAMETER); + RT_UNTRUSTED_VALIDATED_FENCE(); + + pIns->pHGFlags = (HGSMIHOSTFLAGS RT_UNTRUSTED_VOLATILE_GUEST *)HGSMIOffsetToPointer(&pIns->area, LocSafe.offLocation); + break; + } + + default: + Log(("Unsupported HGSMI guest command %d!!!\n", + u16ChannelInfo)); + break; + } + + return rc; +} + +int HGSMICreate(PHGSMIINSTANCE *ppIns, + PPDMDEVINS pDevIns, + const char *pszName, + HGSMIOFFSET offBase, + uint8_t *pu8MemBase, + HGSMISIZE cbMem, + PFNHGSMINOTIFYGUEST pfnNotifyGuest, + void *pvNotifyGuest, + size_t cbContext) +{ + LogFlowFunc(("ppIns = %p, pDevIns = %p, pszName = [%s], offBase = 0x%08X, pu8MemBase = %p, cbMem = 0x%08X, " + "pfnNotifyGuest = %p, pvNotifyGuest = %p, cbContext = %d\n", + ppIns, + pDevIns, + pszName, + offBase, + pu8MemBase, + cbMem, + pfnNotifyGuest, + pvNotifyGuest, + cbContext + )); + + AssertPtrReturn(ppIns, VERR_INVALID_PARAMETER); + AssertPtrReturn(pDevIns, VERR_INVALID_PARAMETER); + AssertPtrReturn(pu8MemBase, VERR_INVALID_PARAMETER); + + int rc; + PHGSMIINSTANCE pIns = (PHGSMIINSTANCE)RTMemAllocZ(sizeof(HGSMIINSTANCE) + cbContext); + if (pIns) + { + rc = HGSMIAreaInitialize(&pIns->area, pu8MemBase, cbMem, offBase); + if (RT_SUCCESS (rc)) + rc = RTCritSectInit(&pIns->instanceCritSect); + if (RT_SUCCESS (rc)) + rc = RTCritSectInit(&pIns->hostHeapCritSect); + if (RT_SUCCESS (rc)) + rc = RTCritSectInit(&pIns->hostFIFOCritSect); + if (RT_SUCCESS (rc)) + { + pIns->pDevIns = pDevIns; + pIns->pszName = RT_VALID_PTR(pszName) ? pszName : ""; + + hgsmiHostHeapSetupUninitialized(&pIns->hostHeap); + + pIns->pfnNotifyGuest = pfnNotifyGuest; + pIns->pvNotifyGuest = pvNotifyGuest; + + RTListInit(&pIns->hostFIFO); + RTListInit(&pIns->hostFIFORead); + RTListInit(&pIns->hostFIFOProcessed); + RTListInit(&pIns->hostFIFOFree); + RTListInit(&pIns->guestCmdCompleted); + + rc = HGSMIHostChannelRegister(pIns, HGSMI_CH_HGSMI, hgsmiChannelHandler, pIns); + } + if (RT_SUCCESS (rc)) + *ppIns = pIns; + else + HGSMIDestroy(pIns); + } + else + rc = VERR_NO_MEMORY; + + LogFlowFunc(("leave rc = %Rrc, pIns = %p\n", rc, pIns)); + return rc; +} + +uint32_t HGSMIReset(PHGSMIINSTANCE pIns) +{ + uint32_t flags = 0; + if (pIns->pHGFlags) + { + /* treat the abandoned commands as read.. */ + while (HGSMIHostRead(pIns) != HGSMIOFFSET_VOID) + {} + flags = pIns->pHGFlags->u32HostFlags; + pIns->pHGFlags->u32HostFlags = 0; + } + + /* .. and complete them */ + while (hgsmiProcessHostCmdCompletion(pIns, 0, true)) + {} + +#ifdef VBOX_WITH_WDDM + while (hgsmiProcessGuestCmdCompletion(pIns) != HGSMIOFFSET_VOID) + {} +#endif + + hgsmiHostHeapDestroy(&pIns->hostHeap); + + return flags; +} + +void HGSMIDestroy(PHGSMIINSTANCE pIns) +{ + LogFlowFunc(("pIns = %p\n", pIns)); + + if (pIns) + { + hgsmiHostHeapDestroy(&pIns->hostHeap); + if (RTCritSectIsInitialized(&pIns->hostHeapCritSect)) + RTCritSectDelete(&pIns->hostHeapCritSect); + if (RTCritSectIsInitialized(&pIns->instanceCritSect)) + RTCritSectDelete(&pIns->instanceCritSect); + if (RTCritSectIsInitialized(&pIns->hostFIFOCritSect)) + RTCritSectDelete(&pIns->hostFIFOCritSect); + + memset(pIns, 0, sizeof (HGSMIINSTANCE)); + RTMemFree(pIns); + } + + LogFlowFunc(("leave\n")); +} + +#ifdef VBOX_WITH_WDDM + +static int hgsmiGuestCommandComplete(HGSMIINSTANCE *pIns, HGSMIOFFSET offMem) +{ + HGSMIGUESTCOMPLENTRY *pEntry = NULL; + + AssertPtrReturn(pIns->pHGFlags, VERR_WRONG_ORDER); + int rc = hgsmiGuestCompletionFIFOAlloc(pIns, &pEntry); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + pEntry->offBuffer = offMem; + + rc = hgsmiFIFOLock(pIns); + AssertRC(rc); + if (RT_SUCCESS(rc)) + { + RTListAppend(&pIns->guestCmdCompleted, &pEntry->nodeEntry); + ASMAtomicOrU32(&pIns->pHGFlags->u32HostFlags, HGSMIHOSTFLAGS_GCOMMAND_COMPLETED); + + hgsmiFIFOUnlock(pIns); + } + else + hgsmiGuestCompletionFIFOFree(pIns, pEntry); + } + + return rc; +} + +int hgsmiCompleteGuestCommand(PHGSMIINSTANCE pIns, HGSMIOFFSET offBuffer, bool fDoIrq) +{ + int rc = hgsmiGuestCommandComplete(pIns, offBuffer); + if (RT_SUCCESS (rc)) + { +#ifdef DEBUG_misha + Assert(fDoIrq); +#endif + if (fDoIrq) + { + /* Now guest can read the FIFO, the notification is informational. */ + hgsmiNotifyGuest (pIns); + } + } + return rc; +} + +int HGSMICompleteGuestCommand(PHGSMIINSTANCE pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvMem, bool fDoIrq) +{ + LogFlowFunc(("pIns = %p, pvMem = %p\n", pIns, pvMem)); + + HGSMIBUFFERHEADER RT_UNTRUSTED_VOLATILE_GUEST *pHeader = HGSMIBufferHeaderFromData(pvMem); + HGSMIOFFSET offBuffer = HGSMIPointerToOffset(&pIns->area, pHeader); + ASSERT_GUEST_RETURN(offBuffer != HGSMIOFFSET_VOID, VERR_INVALID_PARAMETER); + + int rc = hgsmiCompleteGuestCommand(pIns, offBuffer, fDoIrq); + AssertRC(rc); + + LogFlowFunc(("rc = %Rrc\n", rc)); + return rc; +} + +#endif /* VBOX_WITH_WDDM */ + diff --git a/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.h b/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.h new file mode 100644 index 00000000..34028774 --- /dev/null +++ b/src/VBox/Devices/Graphics/HGSMI/HGSMIHost.h @@ -0,0 +1,122 @@ +/* $Id: HGSMIHost.h $ */ +/** @file + * VBox Host Guest Shared Memory Interface (HGSMI), host part. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_HGSMI_HGSMIHost_h +#define VBOX_INCLUDED_SRC_Graphics_HGSMI_HGSMIHost_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include +#include +#include + +struct HGSMIINSTANCE; +typedef struct HGSMIINSTANCE *PHGSMIINSTANCE; + +/** Callback for the guest notification about a new host buffer. */ +typedef DECLCALLBACKTYPE(void, FNHGSMINOTIFYGUEST,(void *pvCallback)); +typedef FNHGSMINOTIFYGUEST *PFNHGSMINOTIFYGUEST; + +/* + * Public Host API for virtual devices. + */ + +int HGSMICreate(PHGSMIINSTANCE *ppIns, + PPDMDEVINS pDevIns, + const char *pszName, + HGSMIOFFSET offBase, + uint8_t *pu8MemBase, + HGSMISIZE cbMem, + PFNHGSMINOTIFYGUEST pfnNotifyGuest, + void *pvNotifyGuest, + size_t cbContext); +void HGSMIDestroy(PHGSMIINSTANCE pIns); +void *HGSMIContext(PHGSMIINSTANCE pIns); + +void RT_UNTRUSTED_VOLATILE_GUEST *HGSMIOffsetToPointerHost(PHGSMIINSTANCE pIns, HGSMIOFFSET offBuffer); +HGSMIOFFSET HGSMIPointerToOffsetHost(PHGSMIINSTANCE pIns, const void RT_UNTRUSTED_VOLATILE_GUEST *pv); +bool HGSMIIsOffsetValid(PHGSMIINSTANCE pIns, HGSMIOFFSET offBuffer); +HGSMIOFFSET HGSMIGetAreaOffset(PHGSMIINSTANCE pIns); +HGSMIOFFSET HGSMIGetAreaSize(PHGSMIINSTANCE pIns); + + +int HGSMIHostChannelRegister(PHGSMIINSTANCE pIns, uint8_t u8Channel, + PFNHGSMICHANNELHANDLER pfnChannelHandler, void *pvChannelHandler); +#if 0 /* unused */ +int HGSMIChannelRegisterName (PHGSMIINSTANCE pIns, + const char *pszChannel, + PFNHGSMICHANNELHANDLER pfnChannelHandler, + void *pvChannelHandler, + uint8_t *pu8Channel); +#endif + +int HGSMIHostHeapSetup(PHGSMIINSTANCE pIns, HGSMIOFFSET RT_UNTRUSTED_GUEST offHeap, HGSMISIZE RT_UNTRUSTED_GUEST cbHeap); + +/* + * Virtual hardware IO handlers. + */ + +/* Guests passes a new command buffer to the host. */ +void HGSMIGuestWrite(PHGSMIINSTANCE pIns, HGSMIOFFSET offBuffer); + +/* Guest reads information about guest buffers. */ +HGSMIOFFSET HGSMIGuestRead(PHGSMIINSTANCE pIns); + +/* Guest reads the host FIFO to get a command. */ +HGSMIOFFSET HGSMIHostRead(PHGSMIINSTANCE pIns); + +/* Guest reports that the command at this offset has been processed. */ +void HGSMIHostWrite(PHGSMIINSTANCE pIns, HGSMIOFFSET offBuffer); + +void HGSMISetHostGuestFlags(PHGSMIINSTANCE pIns, uint32_t flags); +uint32_t HGSMIGetHostGuestFlags(HGSMIINSTANCE *pIns); + +void HGSMIClearHostGuestFlags(PHGSMIINSTANCE pIns, uint32_t flags); + +/* + * Low level interface for submitting buffers to the guest. + * + * These functions are not directly available for anyone but the + * virtual hardware device. + */ + +/* Allocate a buffer in the host heap. */ +int HGSMIHostCommandAlloc(PHGSMIINSTANCE pIns, void RT_UNTRUSTED_VOLATILE_GUEST **ppvData, HGSMISIZE cbData, + uint8_t u8Channel, uint16_t u16ChannelInfo); +int HGSMIHostCommandSubmitAndFreeAsynch(PHGSMIINSTANCE pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvData, bool fDoIrq); +int HGSMIHostCommandFree(PHGSMIINSTANCE pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvData); + +int HGSMIHostLoadStateExec(const struct PDMDEVHLPR3 *pHlp, PHGSMIINSTANCE pIns, PSSMHANDLE pSSM, uint32_t u32Version); +int HGSMIHostSaveStateExec(const struct PDMDEVHLPR3 *pHlp, PHGSMIINSTANCE pIns, PSSMHANDLE pSSM); + +#ifdef VBOX_WITH_WDDM +int HGSMICompleteGuestCommand(PHGSMIINSTANCE pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvMem, bool fDoIrq); +#endif + +#endif /* !VBOX_INCLUDED_SRC_Graphics_HGSMI_HGSMIHost_h */ + diff --git a/src/VBox/Devices/Graphics/HGSMI/Makefile.kup b/src/VBox/Devices/Graphics/HGSMI/Makefile.kup new file mode 100644 index 00000000..e69de29b diff --git a/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.cpp b/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.cpp new file mode 100644 index 00000000..f07382fa --- /dev/null +++ b/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.cpp @@ -0,0 +1,61 @@ +/* $Id: SHGSMIHost.cpp $ */ +/** @file + * Missing description. + */ + +/* + * Copyright (C) 2010-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "SHGSMIHost.h" +#include + +/* + * VBOXSHGSMI made on top HGSMI and allows receiving notifications + * about G->H command completion + */ + +static int vboxSHGSMICommandCompleteAsynch (PHGSMIINSTANCE pIns, VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_GUEST *pHdr) +{ + bool fDoIrq = !!(pHdr->fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ) + || !!(pHdr->fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ_FORCE); + return HGSMICompleteGuestCommand(pIns, pHdr, fDoIrq); +} + +void VBoxSHGSMICommandMarkAsynchCompletion(void RT_UNTRUSTED_VOLATILE_GUEST *pvData) +{ + VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_GUEST *pHdr = VBoxSHGSMIBufferHeader(pvData); + Assert(!(pHdr->fFlags & VBOXSHGSMI_FLAG_HG_ASYNCH)); + pHdr->fFlags |= VBOXSHGSMI_FLAG_HG_ASYNCH; +} + +int VBoxSHGSMICommandComplete(PHGSMIINSTANCE pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvData) +{ + VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_GUEST *pHdr = VBoxSHGSMIBufferHeader(pvData); + uint32_t fFlags = pHdr->fFlags; + ASMCompilerBarrier(); + if ( !(fFlags & VBOXSHGSMI_FLAG_HG_ASYNCH) /* <- check if synchronous completion */ + && !(fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE)) /* <- check if can complete synchronously */ + return VINF_SUCCESS; + + pHdr->fFlags = fFlags | VBOXSHGSMI_FLAG_HG_ASYNCH; + return vboxSHGSMICommandCompleteAsynch(pIns, pHdr); +} diff --git a/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.h b/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.h new file mode 100644 index 00000000..33835b17 --- /dev/null +++ b/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.h @@ -0,0 +1,40 @@ +/* $Id: SHGSMIHost.h $ */ +/** @file + * Missing description + */ + +/* + * Copyright (C) 2010-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_Graphics_HGSMI_SHGSMIHost_h +#define VBOX_INCLUDED_SRC_Graphics_HGSMI_SHGSMIHost_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HGSMIHost.h" + +int VBoxSHGSMICommandComplete(PHGSMIINSTANCE pIns, void RT_UNTRUSTED_VOLATILE_GUEST *pvData); +void VBoxSHGSMICommandMarkAsynchCompletion(void RT_UNTRUSTED_VOLATILE_GUEST *pvData); + +#endif /* !VBOX_INCLUDED_SRC_Graphics_HGSMI_SHGSMIHost_h */ + diff --git a/src/VBox/Devices/Graphics/Makefile.kup b/src/VBox/Devices/Graphics/Makefile.kup new file mode 100644 index 00000000..e69de29b diff --git a/src/VBox/Devices/Graphics/VBoxSVGA3D.def b/src/VBox/Devices/Graphics/VBoxSVGA3D.def new file mode 100644 index 00000000..04fc7297 --- /dev/null +++ b/src/VBox/Devices/Graphics/VBoxSVGA3D.def @@ -0,0 +1,49 @@ +; $Id: VBoxSVGA3D.def $ +;; @file +; VBoxSVGA3D - Definition file for lazy import generation. +; + +; +; Copyright (C) 2014-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see . +; +; SPDX-License-Identifier: GPL-3.0-only +; + +LIBRARY VBoxSVGA3D +EXPORTS + ShaderInitLib + ShaderDestroyLib + ShaderContextCreate + ShaderContextDestroy + ShaderCreateVertexShader + ShaderCreatePixelShader + ShaderDestroyVertexShader + ShaderDestroyPixelShader + ShaderSetVertexShader + ShaderSetPixelShader + ShaderSetVertexShaderConstantB + ShaderSetVertexShaderConstantI + ShaderSetVertexShaderConstantF + ShaderSetPixelShaderConstantB + ShaderSetPixelShaderConstantI + ShaderSetPixelShaderConstantF + ShaderUpdateState + ShaderTransformProjection + ShaderSetPositionTransformed + diff --git a/src/VBox/Devices/Graphics/VBoxSVGA3DObjC.def b/src/VBox/Devices/Graphics/VBoxSVGA3DObjC.def new file mode 100644 index 00000000..6b90b985 --- /dev/null +++ b/src/VBox/Devices/Graphics/VBoxSVGA3DObjC.def @@ -0,0 +1,39 @@ +; $Id: VBoxSVGA3DObjC.def $ +;; @file +; VBoxSVGA3DObjC - Definition file for lazy import generation (darwin specific). +; + +; +; Copyright (C) 2014-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see . +; +; SPDX-License-Identifier: GPL-3.0-only +; + +LIBRARY VBoxSVGA3DObjC +EXPORTS + vmsvga3dCocoaServiceRunLoop + vmsvga3dCocoaCreateViewAndContext + vmsvga3dCocoaDestroyViewAndContext + vmsvga3dCocoaViewInfo + vmsvga3dCocoaViewSetPosition + vmsvga3dCocoaViewSetSize + vmsvga3dCocoaViewUpdateViewport + vmsvga3dCocoaViewMakeCurrentContext + vmsvga3dCocoaSwapBuffers + diff --git a/src/VBox/Devices/Graphics/shaderlib/Makefile.kup b/src/VBox/Devices/Graphics/shaderlib/Makefile.kup new file mode 100644 index 00000000..e69de29b diff --git a/src/VBox/Devices/Graphics/shaderlib/directx.c b/src/VBox/Devices/Graphics/shaderlib/directx.c new file mode 100644 index 00000000..7cd1e59d --- /dev/null +++ b/src/VBox/Devices/Graphics/shaderlib/directx.c @@ -0,0 +1,2672 @@ +/* + * IWineD3D implementation + * + * Copyright 2002-2004 Jason Edmeades + * Copyright 2003-2004 Raphael Junqueira + * Copyright 2004 Christian Costa + * Copyright 2005 Oliver Stieber + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers + * Copyright 2009 Henri Verbeet for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include +#include "wined3d_private.h" + +#ifdef VBOX_WITH_WDDM +# include +#endif + +#ifdef VBOX_WITH_VMSVGA +# ifdef RT_OS_WINDOWS +DECLIMPORT(void) APIENTRY glFinish(void); +# else +void glFinish(void); +# endif +#endif + +WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); + +#define GLINFO_LOCATION (*gl_info) +#define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024) + +/* The d3d device ID */ +#if 0 /* VBox: unused */ +static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } }; +#endif + + +/* Extension detection */ +static const struct { + const char *extension_string; + GL_SupportedExt extension; + DWORD version; +} EXTENSION_MAP[] = { + /* APPLE */ + {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 }, + {"GL_APPLE_fence", APPLE_FENCE, 0 }, + {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 }, + {"GL_APPLE_flush_buffer_range", APPLE_FLUSH_BUFFER_RANGE, 0 }, + {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 }, + {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 }, + + /* ARB */ + {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 }, + {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 }, + {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP, 0 }, + {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 }, + {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 }, + {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 }, + {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 }, + {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT, 0 }, + {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 }, + {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 }, + {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 }, + {"GL_ARB_imaging", ARB_IMAGING, 0 }, + {"GL_ARB_map_buffer_range", ARB_MAP_BUFFER_RANGE, 0 }, + {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */ + {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 }, + {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 }, + {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 }, + {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 }, + {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 }, + {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX, 0 }, + {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 }, + {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 }, + {"GL_ARB_shading_language_100", ARB_SHADING_LANGUAGE_100, 0 }, + {"GL_ARB_sync", ARB_SYNC, 0 }, + {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 }, + {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 }, + {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 }, + {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 }, + {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 }, + {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 }, + {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 }, + {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 }, + {"GL_IBM_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 }, + {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) }, + {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 }, + {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 }, + {"GL_ARB_vertex_array_bgra", ARB_VERTEX_ARRAY_BGRA, 0 }, + {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 }, + {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 }, + {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 }, + {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 }, + + /* ATI */ + {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 }, + {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 }, + {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 }, + {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 }, + {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 }, + + /* EXT */ + {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 }, + {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 }, + {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 }, + {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 }, + {"GL_EXT_draw_buffers2", EXT_DRAW_BUFFERS2, 0 }, + {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 }, + {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 }, + {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 }, + {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 }, + {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 }, + {"GL_EXT_gpu_shader4", EXT_GPU_SHADER4, 0 }, + {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 }, + {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 }, + {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 }, + {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 }, + {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 }, + {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 }, + {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 }, + {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) }, + {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 }, + {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 }, + {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 }, + {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 }, + {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 }, + {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 }, + {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 }, + {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 }, + {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 }, + + /* NV */ + {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 }, + {"GL_NV_fence", NV_FENCE, 0 }, + {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 }, + {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 }, + {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 }, + {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 }, + {"GL_NV_half_float", NV_HALF_FLOAT, 0 }, + {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 }, + {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 }, + {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 }, + {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 }, + {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 }, + {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 }, + {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 }, + {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 }, + {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 }, + {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 }, + {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 }, + {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 }, + + /* SGI */ + {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 }, +}; + +/********************************************************** + * Utility functions follow + **********************************************************/ + +const struct min_lookup minMipLookup[] = +{ + /* NONE POINT LINEAR */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */ + {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/ + {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */ +}; + +const struct min_lookup minMipLookup_noFilter[] = +{ + /* NONE POINT LINEAR */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */ +}; + +const struct min_lookup minMipLookup_noMip[] = +{ + /* NONE POINT LINEAR */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */ + {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */ +}; + +const GLenum magLookup[] = +{ + /* NONE POINT LINEAR */ + GL_NEAREST, GL_NEAREST, GL_LINEAR, +}; + +const GLenum magLookup_noFilter[] = +{ + /* NONE POINT LINEAR */ + GL_NEAREST, GL_NEAREST, GL_NEAREST, +}; + +/* drawStridedSlow attributes */ +glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT]; +glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT]; +glAttribFunc specular_func_3ubv; +glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT]; +glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT]; +glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT]; + + +/********************************************************** + * IWineD3D parts follows + **********************************************************/ + +/* GL locking is done by the caller */ +static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info) +{ + GLuint prog; + BOOL ret = FALSE; + const char *testcode = + "!!ARBvp1.0\n" + "PARAM C[66] = { program.env[0..65] };\n" + "ADDRESS A0;" + "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n" + "ARL A0.x, zero.x;\n" + "MOV result.position, C[A0.x + 65];\n" + "END\n"; + + while(glGetError()); + GL_EXTCALL(glGenProgramsARB(1, &prog)); + if(!prog) { + ERR("Failed to create an ARB offset limit test program\n"); + } + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog)); + GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + (GLsizei)strlen(testcode), testcode)); + if(glGetError() != 0) { + TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n"); + TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + ret = TRUE; + } else TRACE("OpenGL implementation allows offsets > 63\n"); + + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0)); + GL_EXTCALL(glDeleteProgramsARB(1, &prog)); + checkGLcall("ARB vp offset limit test cleanup"); + + return ret; +} + +static DWORD ver_for_ext(GL_SupportedExt ext) +{ + unsigned int i; + for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) { + if(EXTENSION_MAP[i].extension == ext) { + return EXTENSION_MAP[i].version; + } + } + return 0; +} + +static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + if (card_vendor != HW_VENDOR_ATI) return FALSE; + if (device == CARD_ATI_RADEON_9500) return TRUE; + if (device == CARD_ATI_RADEON_X700) return TRUE; + if (device == CARD_ATI_RADEON_X1600) return TRUE; + return FALSE; +} + +static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + if (card_vendor == HW_VENDOR_NVIDIA) + { + if (device == CARD_NVIDIA_GEFORCEFX_5800 || device == CARD_NVIDIA_GEFORCEFX_5600) + { + return TRUE; + } + } + return FALSE; +} + +static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from + * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to + * detect the Apple OpenGL implementation to apply some extension fixups afterwards. + * + * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks + * aren't sufficient either because a Linux binary may display on a macos X server via remote X11. + * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions + * like client storage might be supported on other implementations too, but GL_APPLE_flush_render + * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So + * the chance that other implementations support them is rather small since Win32 QuickTime uses + * DirectDraw, not OpenGL. + * + * This test has been moved into wined3d_guess_gl_vendor() + */ + if (gl_vendor == GL_VENDOR_APPLE) + { + return TRUE; + } + return FALSE; +} + +/* Context activation is done by the caller. */ +static void test_pbo_functionality(struct wined3d_gl_info *gl_info) +{ + /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs, + * but glTexSubImage from a PBO fails miserably, with the first line repeated over + * all the texture. This function detects this bug by its symptom and disables PBOs + * if the test fails. + * + * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA, + * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use + * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data + * read back is compared to the original. If they are equal PBOs are assumed to work, + * otherwise the PBO extension is disabled. */ + GLuint texture, pbo; + static const unsigned int pattern[] = + { + 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000, + 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff, + 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff, + 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff + }; + unsigned int check[sizeof(pattern) / sizeof(pattern[0])]; + + /* No PBO -> No point in testing them. */ + if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return; + + ENTER_GL(); + + while (glGetError()); + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0); + checkGLcall("Specifying the PBO test texture"); + + GL_EXTCALL(glGenBuffersARB(1, &pbo)); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo)); + GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB)); + checkGLcall("Specifying the PBO test pbo"); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + checkGLcall("Loading the PBO test texture"); + + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +#ifdef VBOX_WITH_VMSVGA + glFinish(); +#else + wglFinish(); /* just to be sure */ +#endif + memset(check, 0, sizeof(check)); + glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check); + checkGLcall("Reading back the PBO test texture"); + + glDeleteTextures(1, &texture); + GL_EXTCALL(glDeleteBuffersARB(1, &pbo)); + checkGLcall("PBO test cleanup"); + + LEAVE_GL(); + + if (memcmp(check, pattern, sizeof(check))) + { + WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n"); + WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n"); + gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE; + } + else + { + TRACE_(d3d_caps)("PBO test successful.\n"); + } +} + +static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + return (card_vendor == HW_VENDOR_INTEL) && (gl_vendor == GL_VENDOR_APPLE); +} + +static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + if (gl_vendor != GL_VENDOR_APPLE) return FALSE; + if (card_vendor != HW_VENDOR_ATI) return FALSE; + if (device == CARD_ATI_RADEON_X1600) return FALSE; + return TRUE; +} + +static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + return gl_vendor == GL_VENDOR_FGLRX; + +} + +static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports + * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card. + * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44 + * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is + * hardcoded + * + * dx10 cards usually have 64 varyings */ + return gl_info->limits.glsl_varyings > 44; +} + +/* A GL context is provided by the caller */ +static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + GLenum error; + DWORD data[16]; + + if (!gl_info->supported[EXT_SECONDARY_COLOR]) return FALSE; + + ENTER_GL(); + while(glGetError()); + GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data); + error = glGetError(); + LEAVE_GL(); + + if(error == GL_NO_ERROR) + { + TRACE("GL Implementation accepts 4 component specular color pointers\n"); + return TRUE; + } + else + { + TRACE("GL implementation does not accept 4 component specular colors, error %s\n", + debug_glerror(error)); + return FALSE; + } +} + +static BOOL match_apple_nvts(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + if (!match_apple(gl_info, gl_renderer, gl_vendor, card_vendor, device)) return FALSE; + return gl_info->supported[NV_TEXTURE_SHADER]; +} + +/* A GL context is provided by the caller */ +static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + GLuint prog; + BOOL ret = FALSE; + GLint pos; + const char *testcode = + "!!ARBvp1.0\n" + "OPTION NV_vertex_program2;\n" + "MOV result.clip[0], 0.0;\n" + "MOV result.position, 0.0;\n" + "END\n"; + + if (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]) return FALSE; + + ENTER_GL(); + while(glGetError()); + + GL_EXTCALL(glGenProgramsARB(1, &prog)); + if(!prog) + { + ERR("Failed to create the NVvp clip test program\n"); + LEAVE_GL(); + return FALSE; + } + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog)); + GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + (GLsizei)strlen(testcode), testcode)); + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); + if(pos != -1) + { + WARN("GL_NV_vertex_program2_option result.clip[] test failed\n"); + TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + ret = TRUE; + while(glGetError()); + } + else TRACE("GL_NV_vertex_program2_option result.clip[] test passed\n"); + + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0)); + GL_EXTCALL(glDeleteProgramsARB(1, &prog)); + checkGLcall("GL_NV_vertex_program2_option result.clip[] test cleanup"); + + LEAVE_GL(); + return ret; +} + +/* Context activation is done by the caller. */ +static BOOL match_fbo_tex_update(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + char data[4 * 4 * 4]; + GLuint tex, fbo; + GLenum status; + +#ifndef VBOX_WITH_VMSVGA + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return FALSE; +#endif + memset(data, 0xcc, sizeof(data)); + + ENTER_GL(); + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + checkGLcall("glTexImage2D"); + + gl_info->fbo_ops.glGenFramebuffers(1, &fbo); + gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo); + gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + checkGLcall("glFramebufferTexture2D"); + + status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) ERR("FBO status %#x\n", status); + checkGLcall("glCheckFramebufferStatus"); + + memset(data, 0x11, sizeof(data)); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); + checkGLcall("glTexSubImage2D"); + + glClearColor(0.996, 0.729, 0.745, 0.792); + glClear(GL_COLOR_BUFFER_BIT); + checkGLcall("glClear"); + + glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); + checkGLcall("glGetTexImage"); + + gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + checkGLcall("glBindTexture"); + + gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo); + glDeleteTextures(1, &tex); + checkGLcall("glDeleteTextures"); + + LEAVE_GL(); + + return *(DWORD *)data == 0x11111111; +} + +static void quirk_arb_constants(struct wined3d_gl_info *gl_info) +{ + TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->limits.arb_vs_native_constants); + gl_info->limits.glsl_vs_float_constants = gl_info->limits.arb_vs_native_constants; + TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->limits.arb_ps_native_constants); + gl_info->limits.glsl_ps_float_constants = gl_info->limits.arb_ps_native_constants; +} + +static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info) +{ + quirk_arb_constants(gl_info); + /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms. + * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should + * allow 48 different offsets or other helper immediate values. */ + TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n"); + gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12); +} + +/* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB + * on more than one texture unit. This means that the d3d9 visual point size test will cause a + * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This + * quirk only enables point sprites on the first texture unit. This keeps point sprites working in + * most games, but avoids the crash + * + * A more sophisticated way would be to find all units that need texture coordinates and enable + * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow + * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though) + * + * Note that disabling the extension entirely does not gain predictability because there is no point + * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */ +static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info) +{ + if (gl_info->supported[ARB_POINT_SPRITE]) + { + TRACE("Limiting point sprites to one texture unit.\n"); + gl_info->limits.point_sprite_units = 1; + } +} + +static void quirk_ati_dx9(struct wined3d_gl_info *gl_info) +{ + quirk_arb_constants(gl_info); + + /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although + * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL). + * If real NP2 textures are used, the driver falls back to software. We could just remove the + * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient + * due to the non-normalized texture coordinates. Thus set an internal extension flag, + * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures + * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits. + * + * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which + * has this extension promoted to core. The extension loading code sets this extension supported + * due to that, so this code works on fglrx as well. */ + if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) + { + TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n"); + gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE; + gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE; + } + + /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although + * it is generally more efficient. Reserve just 8 constants. */ + TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n"); + gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8); +} + +static void quirk_no_np2(struct wined3d_gl_info *gl_info) +{ + /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but + * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string. + * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying + * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the + * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used. + * We therefore completely remove ARB_tex_npot from the list of supported extensions. + * + * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot, + * triggering the software fallback. There is not much we can do here apart from disabling the + * software-emulated extension and reenable ARB_tex_rect (which was previously disabled + * in IWineD3DImpl_FillGLCaps). + * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer + * post-processing effects in the game "Max Payne 2"). + * The behaviour can be verified through a simple test app attached in bugreport #14724. */ + TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n"); + gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE; + gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE; +} + +static void quirk_texcoord_w(struct wined3d_gl_info *gl_info) +{ + /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems + * with fixed function fragment processing. Ideally this flag should be detected with a test shader + * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones) + * do not like vertex shaders in feedback mode and return an error, even though it should be valid + * according to the spec. + * + * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This + * makes the shader slower and eats instruction slots which should be available to the d3d app. + * + * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist + * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If + * this workaround is activated on cards that do not need it, it won't break things, just affect + * performance negatively. */ + TRACE("Enabling vertex texture coord fixes in vertex shaders.\n"); + gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W; +} + +static void quirk_clip_varying(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING; +} + +static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA; +} + +static void quirk_apple_nvts(struct wined3d_gl_info *gl_info) +{ + gl_info->supported[NV_TEXTURE_SHADER] = FALSE; + gl_info->supported[NV_TEXTURE_SHADER2] = FALSE; +} + +static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN; +} + +static void quirk_fbo_tex_update(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_FBO_TEX_UPDATE; +} + +static BOOL match_ati_hd4800(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + if (card_vendor != HW_VENDOR_ATI) return FALSE; + if (device == CARD_ATI_RADEON_HD4800) return TRUE; + return FALSE; +} + +static void quirk_fullsize_blit(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_FULLSIZE_BLIT; +} + +#ifdef VBOX_WITH_WDDM +static BOOL match_mesa_nvidia(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + if (card_vendor != HW_VENDOR_NVIDIA) return FALSE; + if (gl_vendor != GL_VENDOR_MESA) return FALSE; + return TRUE; +} + +static void quirk_no_shader_3(struct wined3d_gl_info *gl_info) +{ + int vs_selected_mode, ps_selected_mode; + select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode); + if (vs_selected_mode != SHADER_GLSL && ps_selected_mode != SHADER_GLSL) + return; + + gl_info->limits.arb_ps_instructions = 512; +} +#endif + +static BOOL match_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + if (card_vendor == HW_VENDOR_INTEL) return TRUE; + if (gl_vendor == GL_VENDOR_INTEL) return TRUE; + return FALSE; +} + +static void quirk_force_blit(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_FORCE_BLIT; +} + +struct driver_quirk +{ + BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device); + void (*apply)(struct wined3d_gl_info *gl_info); + const char *description; +}; + +static const struct driver_quirk quirk_table[] = +{ + { + match_ati_r300_to_500, + quirk_ati_dx9, + "ATI GLSL constant and normalized texrect quirk" + }, + /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are + * used it falls back to software. While the compiler can detect if the shader uses all declared + * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader + * using relative addressing falls back to software. + * + * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */ + { + match_apple, + quirk_apple_glsl_constants, + "Apple GLSL uniform override" + }, + { + match_geforce5, + quirk_no_np2, + "Geforce 5 NP2 disable" + }, + { + match_apple_intel, + quirk_texcoord_w, + "Init texcoord .w for Apple Intel GPU driver" + }, + { + match_apple_nonr500ati, + quirk_texcoord_w, + "Init texcoord .w for Apple ATI >= r600 GPU driver" + }, + { + match_fglrx, + quirk_one_point_sprite, + "Fglrx point sprite crash workaround" + }, + { + match_dx10_capable, + quirk_clip_varying, + "Reserved varying for gl_ClipPos" + }, + { + /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most + * GL implementations accept it. The Mac GL is the only implementation known to + * reject it. + * + * If we can pass 4 component specular colors, do it, because (a) we don't have + * to screw around with the data, and (b) the D3D fixed function vertex pipeline + * passes specular alpha to the pixel shader if any is used. Otherwise the + * specular alpha is used to pass the fog coordinate, which we pass to opengl + * via GL_EXT_fog_coord. + */ + match_allows_spec_alpha, + quirk_allows_specular_alpha, + "Allow specular alpha quirk" + }, + { + /* The pixel formats provided by GL_NV_texture_shader are broken on OSX + * (rdar://5682521). + */ + match_apple_nvts, + quirk_apple_nvts, + "Apple NV_texture_shader disable" + }, +#ifndef VBOX_WITH_VMSVGA + { + match_broken_nv_clip, + quirk_disable_nvvp_clip, + "Apple NV_vertex_program clip bug quirk" + }, +#endif + { + match_fbo_tex_update, + quirk_fbo_tex_update, + "FBO rebind for attachment updates" + }, + { + match_ati_hd4800, + quirk_fullsize_blit, + "Fullsize blit" + }, +#ifdef VBOX_WITH_WDDM + { + match_mesa_nvidia, + quirk_no_shader_3, + "disable shader 3 support" + }, +#endif + { + match_intel, + quirk_force_blit, + "force framebuffer blit when possible" + } +}; + +/* Context activation is done by the caller. */ +static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + unsigned int i; + + for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i) + { + if (!quirk_table[i].match(gl_info, gl_renderer, gl_vendor, card_vendor, device)) continue; + TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description); + quirk_table[i].apply(gl_info); + } + + /* Find out if PBOs work as they are supposed to. */ + test_pbo_functionality(gl_info); +} + + +/* Certain applications (Steam) complain if we report an outdated driver version. In general, + * reporting a driver version is moot because we are not the Windows driver, and we have different + * bugs, features, etc. + * + * The driver version has the form "x.y.z.w". + * + * "x" is the Windows version the driver is meant for: + * 4 -> 95/98/NT4 + * 5 -> 2000 + * 6 -> 2000/XP + * 7 -> Vista + * 8 -> Win 7 + * + * "y" is the Direct3D level the driver supports: + * 11 -> d3d6 + * 12 -> d3d7 + * 13 -> d3d8 + * 14 -> d3d9 + * 15 -> d3d10 + * + * "z" is unknown, possibly vendor specific. + * + * "w" is the vendor specific driver version. + */ +struct driver_version_information +{ + WORD vendor; /* reported PCI card vendor ID */ + WORD card; /* reported PCI card device ID */ + const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */ + WORD d3d_level; /* driver hiword to report */ + WORD lopart_hi, lopart_lo; /* driver loword to report */ +}; + +#if 0 /* VBox: unused */ +static const struct driver_version_information driver_version_table[] = +{ + /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x) + * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown + * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89 + * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86 + * + * All version numbers used below are from the Linux nvidia drivers. */ + {HW_VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 1, 8, 6 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 1, 8, 6 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 1, 8, 6 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 6, 4, 3 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 1, 8, 6 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 6, 10, 9371 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 6, 10, 9371 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 6, 10, 9371 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 15, 11, 7516 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 15, 11, 7516 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 15, 11, 7516 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 15, 11, 8585 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 15, 11, 8585 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 15, 11, 8585 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 15, 11, 8618 }, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GT240, "NVIDIA GeForce GT 240", 15, 11, 8618 }, + + /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */ + {HW_VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2350, "ATI Mobility Radeon HD 2350", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD5700, "ATI Radeon HD 5700 Series", 14, 10, 8681 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD5800, "ATI Radeon HD 5800 Series", 14, 10, 8681 }, + + /* TODO: Add information about legacy ATI hardware, Intel and other cards. */ +}; +#endif /* VBox: unused */ + + +static DWORD wined3d_parse_gl_version(const char *gl_version) +{ + const char *ptr = gl_version; + int major, minor; + + major = atoi(ptr); + if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major); + + while (isdigit(*ptr)) ++ptr; + if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version)); + + minor = atoi(ptr); + + TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor); + + return MAKEDWORD_VERSION(major, minor); +} + +static enum wined3d_gl_vendor wined3d_guess_gl_vendor(struct wined3d_gl_info *gl_info, const char *gl_vendor_string, const char *gl_renderer) +{ + + /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from + * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to + * detect the Apple OpenGL implementation to apply some extension fixups afterwards. + * + * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks + * aren't sufficient either because a Linux binary may display on a macos X server via remote X11. + * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions + * like client storage might be supported on other implementations too, but GL_APPLE_flush_render + * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So + * the chance that other implementations support them is rather small since Win32 QuickTime uses + * DirectDraw, not OpenGL. */ + if (gl_info->supported[APPLE_FENCE] + && gl_info->supported[APPLE_CLIENT_STORAGE] + && gl_info->supported[APPLE_FLUSH_RENDER] + && gl_info->supported[APPLE_YCBCR_422]) + return GL_VENDOR_APPLE; + + if (strstr(gl_vendor_string, "NVIDIA")) + return GL_VENDOR_NVIDIA; + + if (strstr(gl_vendor_string, "ATI")) + return GL_VENDOR_FGLRX; + + if (strstr(gl_vendor_string, "Intel(R)") + || strstr(gl_renderer, "Intel(R)") + || strstr(gl_vendor_string, "Intel Inc.")) + { + if (strstr(gl_renderer, "Mesa")) + return GL_VENDOR_MESA; + return GL_VENDOR_INTEL; + } + + if (strstr(gl_vendor_string, "Mesa") + || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.") + || strstr(gl_vendor_string, "DRI R300 Project") + || strstr(gl_vendor_string, "X.Org R300 Project") + || strstr(gl_vendor_string, "Tungsten Graphics, Inc") + || strstr(gl_vendor_string, "VMware, Inc.") + || strstr(gl_renderer, "Mesa") + || strstr(gl_renderer, "Gallium")) + return GL_VENDOR_MESA; + + FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning GL_VENDOR_UNKNOWN.\n", + debugstr_a(gl_vendor_string)); + + return GL_VENDOR_UNKNOWN; +} + +static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_string, const char *gl_renderer) +{ + if (strstr(gl_vendor_string, "NVIDIA")) + return HW_VENDOR_NVIDIA; + + if (strstr(gl_vendor_string, "ATI") + || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.") + || strstr(gl_vendor_string, "X.Org R300 Project") + || strstr(gl_vendor_string, "DRI R300 Project")) + return HW_VENDOR_ATI; + + if (strstr(gl_vendor_string, "Intel(R)") + || strstr(gl_renderer, "Intel(R)") + || strstr(gl_vendor_string, "Intel Inc.")) + return HW_VENDOR_INTEL; + + if (strstr(gl_vendor_string, "Mesa") + || strstr(gl_vendor_string, "Tungsten Graphics, Inc") + || strstr(gl_vendor_string, "VMware, Inc.")) + return HW_VENDOR_SOFTWARE; + + FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning HW_VENDOR_NVIDIA.\n", debugstr_a(gl_vendor_string)); + + return HW_VENDOR_NVIDIA; +} + + + +static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) +{ +#ifndef VBOX_WITH_WDDM + if (WINE_D3D10_CAPABLE(gl_info)) +#endif + { + /* Geforce 200 - highend */ + if (strstr(gl_renderer, "GTX 280") + || strstr(gl_renderer, "GTX 285") + || strstr(gl_renderer, "GTX 295")) + { + *vidmem = 1024; + return CARD_NVIDIA_GEFORCE_GTX280; + } + + /* Geforce 200 - midend high */ + if (strstr(gl_renderer, "GTX 275")) + { + *vidmem = 896; + return CARD_NVIDIA_GEFORCE_GTX275; + } + + /* Geforce 200 - midend */ + if (strstr(gl_renderer, "GTX 260")) + { + *vidmem = 1024; + return CARD_NVIDIA_GEFORCE_GTX260; + } + /* Geforce 200 - midend */ + if (strstr(gl_renderer, "GT 240")) + { + *vidmem = 512; + return CARD_NVIDIA_GEFORCE_GT240; + } + + /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */ + if (strstr(gl_renderer, "9800") + || strstr(gl_renderer, "GTS 150") + || strstr(gl_renderer, "GTS 250")) + { + *vidmem = 512; + return CARD_NVIDIA_GEFORCE_9800GT; + } + + /* Geforce9 - midend */ + if (strstr(gl_renderer, "9600")) + { + *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */ + return CARD_NVIDIA_GEFORCE_9600GT; + } + + /* Geforce9 - midend low / Geforce 200 - low */ + if (strstr(gl_renderer, "9500") + || strstr(gl_renderer, "GT 120") + || strstr(gl_renderer, "GT 130")) + { + *vidmem = 256; /* The 9500GT has 256-1024MB */ + return CARD_NVIDIA_GEFORCE_9500GT; + } + + /* Geforce9 - lowend */ + if (strstr(gl_renderer, "9400")) + { + *vidmem = 256; /* The 9400GT has 256-1024MB */ + return CARD_NVIDIA_GEFORCE_9400GT; + } + + /* Geforce9 - lowend low */ + if (strstr(gl_renderer, "9100") + || strstr(gl_renderer, "9200") + || strstr(gl_renderer, "9300") + || strstr(gl_renderer, "G 100")) + { + *vidmem = 256; /* The 9100-9300 cards have 256MB */ + return CARD_NVIDIA_GEFORCE_9200; + } + + /* Geforce8 - highend */ + if (strstr(gl_renderer, "8800")) + { + *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */ + return CARD_NVIDIA_GEFORCE_8800GTS; + } + + /* Geforce8 - midend mobile */ + if (strstr(gl_renderer, "8600 M")) + { + *vidmem = 512; + return CARD_NVIDIA_GEFORCE_8600MGT; + } + + /* Geforce8 - midend */ + if (strstr(gl_renderer, "8600") + || strstr(gl_renderer, "8700")) + { + *vidmem = 256; + return CARD_NVIDIA_GEFORCE_8600GT; + } + + /* Geforce8 - lowend */ + if (strstr(gl_renderer, "8100") + || strstr(gl_renderer, "8200") + || strstr(gl_renderer, "8300") + || strstr(gl_renderer, "8400") + || strstr(gl_renderer, "8500")) + { + *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */ + return CARD_NVIDIA_GEFORCE_8300GS; + } + + /* Geforce8-compatible fall back if the GPU is not in the list yet */ + *vidmem = 128; + return CARD_NVIDIA_GEFORCE_8300GS; + } + + /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more + * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx. + */ + if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3]) + { + /* Geforce7 - highend */ + if (strstr(gl_renderer, "7800") + || strstr(gl_renderer, "7900") + || strstr(gl_renderer, "7950") + || strstr(gl_renderer, "Quadro FX 4") + || strstr(gl_renderer, "Quadro FX 5")) + { + *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */ + return CARD_NVIDIA_GEFORCE_7800GT; + } + + /* Geforce7 midend */ + if (strstr(gl_renderer, "7600") + || strstr(gl_renderer, "7700")) + { + *vidmem = 256; /* The 7600 uses 256-512MB */ + return CARD_NVIDIA_GEFORCE_7600; + } + + /* Geforce7 lower medium */ + if (strstr(gl_renderer, "7400")) + { + *vidmem = 256; /* The 7400 uses 256-512MB */ + return CARD_NVIDIA_GEFORCE_7400; + } + + /* Geforce7 lowend */ + if (strstr(gl_renderer, "7300")) + { + *vidmem = 256; /* Mac Pros with this card have 256 MB */ + return CARD_NVIDIA_GEFORCE_7300; + } + + /* Geforce6 highend */ + if (strstr(gl_renderer, "6800")) + { + *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */ + return CARD_NVIDIA_GEFORCE_6800; + } + + /* Geforce6 - midend */ + if (strstr(gl_renderer, "6600") + || strstr(gl_renderer, "6610") + || strstr(gl_renderer, "6700")) + { + *vidmem = 128; /* A 6600GT has 128-256MB */ + return CARD_NVIDIA_GEFORCE_6600GT; + } + + /* Geforce6/7 lowend */ + *vidmem = 64; /* */ + return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */ + } + + if (WINE_D3D9_CAPABLE(gl_info)) + { + /* GeforceFX - highend */ + if (strstr(gl_renderer, "5800") + || strstr(gl_renderer, "5900") + || strstr(gl_renderer, "5950") + || strstr(gl_renderer, "Quadro FX")) + { + *vidmem = 256; /* 5800-5900 cards use 256MB */ + return CARD_NVIDIA_GEFORCEFX_5800; + } + + /* GeforceFX - midend */ + if (strstr(gl_renderer, "5600") + || strstr(gl_renderer, "5650") + || strstr(gl_renderer, "5700") + || strstr(gl_renderer, "5750")) + { + *vidmem = 128; /* A 5600 uses 128-256MB */ + return CARD_NVIDIA_GEFORCEFX_5600; + } + + /* GeforceFX - lowend */ + *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */ + return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */ + } + + if (WINE_D3D8_CAPABLE(gl_info)) + { + if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4")) + { + *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */ + return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */ + } + + *vidmem = 64; /* Geforce3 cards have 64-128MB */ + return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */ + } + + if (WINE_D3D7_CAPABLE(gl_info)) + { + if (strstr(gl_renderer, "GeForce4 MX")) + { + /* Most Geforce4MX GPUs have at least 64MB of memory, some + * early models had 32MB but most have 64MB or even 128MB. */ + *vidmem = 64; + return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */ + } + + if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR")) + { + *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */ + return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */ + } + + if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2")) + { + *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */ + return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */ + } + + /* Most Geforce1 cards have 32MB, there are also some rare 16 + * and 64MB (Dell) models. */ + *vidmem = 32; + return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */ + } + + if (strstr(gl_renderer, "TNT2")) + { + *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */ + return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */ + } + + *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */ + return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */ + +} + +static enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) +{ + /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx + * + * Beware: renderer string do not match exact card model, + * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */ +#ifndef VBOX_WITH_WDDM + if (WINE_D3D10_CAPABLE(gl_info)) +#endif + { + /* Radeon EG CYPRESS XT / PRO HD5800 - highend */ + if (strstr(gl_renderer, "HD 5800") /* Radeon EG CYPRESS HD58xx generic renderer string */ + || strstr(gl_renderer, "HD 5850") /* Radeon EG CYPRESS XT */ + || strstr(gl_renderer, "HD 5870")) /* Radeon EG CYPRESS PRO */ + { + *vidmem = 1024; /* note: HD58xx cards use 1024MB */ + return CARD_ATI_RADEON_HD5800; + } + + /* Radeon EG JUNIPER XT / LE HD5700 - midend */ + if (strstr(gl_renderer, "HD 5700") /* Radeon EG JUNIPER HD57xx generic renderer string */ + || strstr(gl_renderer, "HD 5750") /* Radeon EG JUNIPER LE */ + || strstr(gl_renderer, "HD 5770")) /* Radeon EG JUNIPER XT */ + { + *vidmem = 512; /* note: HD5770 cards use 1024MB and HD5750 cards use 512MB or 1024MB */ + return CARD_ATI_RADEON_HD5700; + } + + /* Radeon R7xx HD4800 - highend */ + if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */ + || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */ + || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */ + || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */ + || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */ + { + *vidmem = 512; /* note: HD4890 cards use 1024MB */ + return CARD_ATI_RADEON_HD4800; + } + + /* Radeon R740 HD4700 - midend */ + if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */ + || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */ + { + *vidmem = 512; + return CARD_ATI_RADEON_HD4700; + } + + /* Radeon R730 HD4600 - midend */ + if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */ + || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */ + || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */ + { + *vidmem = 512; + return CARD_ATI_RADEON_HD4600; + } + + /* Radeon R710 HD4500/HD4350 - lowend */ + if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */ + || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */ + { + *vidmem = 256; + return CARD_ATI_RADEON_HD4350; + } + + /* Radeon R6xx HD2900/HD3800 - highend */ + if (strstr(gl_renderer, "HD 2900") + || strstr(gl_renderer, "HD 3870") + || strstr(gl_renderer, "HD 3850")) + { + *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */ + return CARD_ATI_RADEON_HD2900; + } + + /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */ + if (strstr(gl_renderer, "HD 2600") + || strstr(gl_renderer, "HD 3830") + || strstr(gl_renderer, "HD 3690") + || strstr(gl_renderer, "HD 3650")) + { + *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */ + return CARD_ATI_RADEON_HD2600; + } + + /* Radeon R6xx HD2350/HD2400/HD3400 - lowend + * Note HD2300=DX9, HD2350=DX10 */ + if (strstr(gl_renderer, "HD 2350") + || strstr(gl_renderer, "HD 2400") + || strstr(gl_renderer, "HD 3470") + || strstr(gl_renderer, "HD 3450") + || strstr(gl_renderer, "HD 3430") + || strstr(gl_renderer, "HD 3400")) + { + *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */ + return CARD_ATI_RADEON_HD2350; + } + + /* Radeon R6xx/R7xx integrated */ + if (strstr(gl_renderer, "HD 3100") + || strstr(gl_renderer, "HD 3200") + || strstr(gl_renderer, "HD 3300")) + { + *vidmem = 128; /* 128MB */ + return CARD_ATI_RADEON_HD3200; + } + + /* Default for when no GPU has been found */ + *vidmem = 128; /* 128MB */ + return CARD_ATI_RADEON_HD3200; + } + + if (WINE_D3D8_CAPABLE(gl_info)) + { + /* Radeon R5xx */ + if (strstr(gl_renderer, "X1600") + || strstr(gl_renderer, "X1650") + || strstr(gl_renderer, "X1800") + || strstr(gl_renderer, "X1900") + || strstr(gl_renderer, "X1950")) + { + *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */ + return CARD_ATI_RADEON_X1600; + } + + /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx) + * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */ + if (strstr(gl_renderer, "X700") + || strstr(gl_renderer, "X800") + || strstr(gl_renderer, "X850") + || strstr(gl_renderer, "X1300") + || strstr(gl_renderer, "X1400") + || strstr(gl_renderer, "X1450") + || strstr(gl_renderer, "X1550") + || strstr(gl_renderer, "X2300") + || strstr(gl_renderer, "X2500") + || strstr(gl_renderer, "HD 2300") + ) + { + *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */ + return CARD_ATI_RADEON_X700; + } + + /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */ + if (strstr(gl_renderer, "Radeon Xpress")) + { + *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */ + return CARD_ATI_RADEON_XPRESS_200M; + } + + /* Radeon R3xx */ + *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */ + return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */ + } + + if (WINE_D3D8_CAPABLE(gl_info)) + { + *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */ + return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */ + } + + if (WINE_D3D7_CAPABLE(gl_info)) + { + *vidmem = 32; /* There are models with up to 64MB */ + return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */ + } + + *vidmem = 16; /* There are 16-32MB models */ + return CARD_ATI_RAGE_128PRO; + +} + +static enum wined3d_pci_device select_card_intel_binary(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) +{ + if (strstr(gl_renderer, "X3100")) + { + /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */ + *vidmem = 128; + return CARD_INTEL_X3100; + } + + if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM")) + { + /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */ + *vidmem = 64; + return CARD_INTEL_I945GM; + } + + if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM; + if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G; + if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G; + if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G; + if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G; + return CARD_INTEL_I915G; + +} + +static enum wined3d_pci_device select_card_ati_mesa(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) +{ + /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx + * + * Beware: renderer string do not match exact card model, + * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */ + if (strstr(gl_renderer, "Gallium")) + { + /* Radeon R7xx HD4800 - highend */ + if (strstr(gl_renderer, "R700") /* Radeon R7xx HD48xx generic renderer string */ + || strstr(gl_renderer, "RV770") /* Radeon RV770 */ + || strstr(gl_renderer, "RV790")) /* Radeon RV790 */ + { + *vidmem = 512; /* note: HD4890 cards use 1024MB */ + return CARD_ATI_RADEON_HD4800; + } + + /* Radeon R740 HD4700 - midend */ + if (strstr(gl_renderer, "RV740")) /* Radeon RV740 */ + { + *vidmem = 512; + return CARD_ATI_RADEON_HD4700; + } + + /* Radeon R730 HD4600 - midend */ + if (strstr(gl_renderer, "RV730")) /* Radeon RV730 */ + { + *vidmem = 512; + return CARD_ATI_RADEON_HD4600; + } + + /* Radeon R710 HD4500/HD4350 - lowend */ + if (strstr(gl_renderer, "RV710")) /* Radeon RV710 */ + { + *vidmem = 256; + return CARD_ATI_RADEON_HD4350; + } + + /* Radeon R6xx HD2900/HD3800 - highend */ + if (strstr(gl_renderer, "R600") + || strstr(gl_renderer, "RV670") + || strstr(gl_renderer, "R680")) + { + *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */ + return CARD_ATI_RADEON_HD2900; + } + + /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */ + if (strstr(gl_renderer, "RV630") + || strstr(gl_renderer, "RV635")) + { + *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */ + return CARD_ATI_RADEON_HD2600; + } + + /* Radeon R6xx HD2350/HD2400/HD3400 - lowend */ + if (strstr(gl_renderer, "RV610") + || strstr(gl_renderer, "RV620")) + { + *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */ + return CARD_ATI_RADEON_HD2350; + } + + /* Radeon R6xx/R7xx integrated */ + if (strstr(gl_renderer, "RS780") + || strstr(gl_renderer, "RS880")) + { + *vidmem = 128; /* 128MB */ + return CARD_ATI_RADEON_HD3200; + } + + /* Radeon R5xx */ + if (strstr(gl_renderer, "RV530") + || strstr(gl_renderer, "RV535") + || strstr(gl_renderer, "RV560") + || strstr(gl_renderer, "R520") + || strstr(gl_renderer, "RV570") + || strstr(gl_renderer, "R580")) + { + *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */ + return CARD_ATI_RADEON_X1600; + } + + /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */ + if (strstr(gl_renderer, "R410") + || strstr(gl_renderer, "R420") + || strstr(gl_renderer, "R423") + || strstr(gl_renderer, "R430") + || strstr(gl_renderer, "R480") + || strstr(gl_renderer, "R481") + || strstr(gl_renderer, "RV410") + || strstr(gl_renderer, "RV515") + || strstr(gl_renderer, "RV516")) + { + *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */ + return CARD_ATI_RADEON_X700; + } + + /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */ + if (strstr(gl_renderer, "RS400") + || strstr(gl_renderer, "RS480") + || strstr(gl_renderer, "RS482") + || strstr(gl_renderer, "RS485") + || strstr(gl_renderer, "RS600") + || strstr(gl_renderer, "RS690") + || strstr(gl_renderer, "RS740")) + { + *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */ + return CARD_ATI_RADEON_XPRESS_200M; + } + + /* Radeon R3xx */ + if (strstr(gl_renderer, "R300") + || strstr(gl_renderer, "RV350") + || strstr(gl_renderer, "RV351") + || strstr(gl_renderer, "RV360") + || strstr(gl_renderer, "RV370") + || strstr(gl_renderer, "R350") + || strstr(gl_renderer, "R360")) + { + *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */ + return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */ + } + } + + if (WINE_D3D9_CAPABLE(gl_info)) + { + /* Radeon R7xx HD4800 - highend */ + if (strstr(gl_renderer, "(R700") /* Radeon R7xx HD48xx generic renderer string */ + || strstr(gl_renderer, "(RV770") /* Radeon RV770 */ + || strstr(gl_renderer, "(RV790")) /* Radeon RV790 */ + { + *vidmem = 512; /* note: HD4890 cards use 1024MB */ + return CARD_ATI_RADEON_HD4800; + } + + /* Radeon R740 HD4700 - midend */ + if (strstr(gl_renderer, "(RV740")) /* Radeon RV740 */ + { + *vidmem = 512; + return CARD_ATI_RADEON_HD4700; + } + + /* Radeon R730 HD4600 - midend */ + if (strstr(gl_renderer, "(RV730")) /* Radeon RV730 */ + { + *vidmem = 512; + return CARD_ATI_RADEON_HD4600; + } + + /* Radeon R710 HD4500/HD4350 - lowend */ + if (strstr(gl_renderer, "(RV710")) /* Radeon RV710 */ + { + *vidmem = 256; + return CARD_ATI_RADEON_HD4350; + } + + /* Radeon R6xx HD2900/HD3800 - highend */ + if (strstr(gl_renderer, "(R600") + || strstr(gl_renderer, "(RV670") + || strstr(gl_renderer, "(R680")) + { + *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */ + return CARD_ATI_RADEON_HD2900; + } + + /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */ + if (strstr(gl_renderer, "(RV630") + || strstr(gl_renderer, "(RV635")) + { + *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */ + return CARD_ATI_RADEON_HD2600; + } + + /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */ + if (strstr(gl_renderer, "(RV610") + || strstr(gl_renderer, "(RV620")) + { + *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */ + return CARD_ATI_RADEON_HD2350; + } + + /* Radeon R6xx/R7xx integrated */ + if (strstr(gl_renderer, "(RS780") + || strstr(gl_renderer, "(RS880")) + { + *vidmem = 128; /* 128MB */ + return CARD_ATI_RADEON_HD3200; + } + } + + if (WINE_D3D8_CAPABLE(gl_info)) + { + *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */ + return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */ + } + + if (WINE_D3D7_CAPABLE(gl_info)) + { + *vidmem = 32; /* There are models with up to 64MB */ + return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */ + } + + *vidmem = 16; /* There are 16-32MB models */ + return CARD_ATI_RAGE_128PRO; + +} + +static enum wined3d_pci_device select_card_nvidia_mesa(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) +{ + FIXME_(d3d_caps)("Card selection not handled for Mesa Nouveau driver\n"); +#ifndef VBOX_WITH_WDDM + if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600; +#else + /* tmp work around to disable quirk_no_np2 quirk for mesa drivers */ + if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE_6200; +#endif + if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3; + if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE; + if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT; + return CARD_NVIDIA_RIVA_128; +} + +static enum wined3d_pci_device select_card_intel_cmn(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) +{ + if (strstr(gl_renderer, "HD Graphics") + || strstr(gl_renderer, "Sandybridge")) + return CARD_INTEL_SBHD; + FIXME_(d3d_caps)("Card selection not handled for Windows Intel driver\n"); + return CARD_INTEL_I915G; +} + +static enum wined3d_pci_device select_card_intel_mesa(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) +{ + return select_card_intel_cmn(gl_info, gl_renderer, vidmem); +} + +struct vendor_card_selection +{ + enum wined3d_gl_vendor gl_vendor; + enum wined3d_pci_vendor card_vendor; + const char *description; /* Description of the card selector i.e. Apple OS/X Intel */ + enum wined3d_pci_device (*select_card)(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + unsigned int *vidmem ); +}; + +static const struct vendor_card_selection vendor_card_select_table[] = +{ + {GL_VENDOR_NVIDIA, HW_VENDOR_NVIDIA, "Nvidia binary driver", select_card_nvidia_binary}, + {GL_VENDOR_APPLE, HW_VENDOR_NVIDIA, "Apple OSX NVidia binary driver", select_card_nvidia_binary}, + {GL_VENDOR_APPLE, HW_VENDOR_ATI, "Apple OSX AMD/ATI binary driver", select_card_ati_binary}, + {GL_VENDOR_APPLE, HW_VENDOR_INTEL, "Apple OSX Intel binary driver", select_card_intel_binary}, + {GL_VENDOR_FGLRX, HW_VENDOR_ATI, "AMD/ATI binary driver", select_card_ati_binary}, + {GL_VENDOR_MESA, HW_VENDOR_ATI, "Mesa AMD/ATI driver", select_card_ati_mesa}, + {GL_VENDOR_MESA, HW_VENDOR_NVIDIA, "Mesa Nouveau driver", select_card_nvidia_mesa}, + {GL_VENDOR_MESA, HW_VENDOR_INTEL, "Mesa Intel driver", select_card_intel_mesa}, + {GL_VENDOR_INTEL, HW_VENDOR_INTEL, "Windows Intel binary driver", select_card_intel_cmn} +}; + + +static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor *gl_vendor, enum wined3d_pci_vendor *card_vendor, unsigned int *vidmem) +{ + /* Above is a list of Nvidia and ATI GPUs. Both vendors have dozens of + * different GPUs with roughly the same features. In most cases GPUs from a + * certain family differ in clockspeeds, the amount of video memory and the + * number of shader pipelines. + * + * A Direct3D device object contains the PCI id (vendor + device) of the + * videocard which is used for rendering. Various applications use this + * information to get a rough estimation of the features of the card and + * some might use it for enabling 3d effects only on certain types of + * videocards. In some cases games might even use it to work around bugs + * which happen on certain videocards/driver combinations. The problem is + * that OpenGL only exposes a rendering string containing the name of the + * videocard and not the PCI id. + * + * Various games depend on the PCI id, so somehow we need to provide one. + * A simple option is to parse the renderer string and translate this to + * the right PCI id. This is a lot of work because there are more than 200 + * GPUs just for Nvidia. Various cards share the same renderer string, so + * the amount of code might be 'small' but there are quite a number of + * exceptions which would make this a pain to maintain. Another way would + * be to query the PCI id from the operating system (assuming this is the + * videocard which is used for rendering which is not always the case). + * This would work but it is not very portable. Second it would not work + * well in, let's say, a remote X situation in which the amount of 3d + * features which can be used is limited. + * + * As said most games only use the PCI id to get an indication of the + * capabilities of the card. It doesn't really matter if the given id is + * the correct one if we return the id of a card with similar 3d features. + * + * The code below checks the OpenGL capabilities of a videocard and matches + * that to a certain level of Direct3D functionality. Once a card passes + * the Direct3D9 check, we know that the card (in case of Nvidia) is at + * least a GeforceFX. To give a better estimate we do a basic check on the + * renderer string but if that won't pass we return a default card. This + * way is better than maintaining a full card database as even without a + * full database we can return a card with similar features. Second the + * size of the database can be made quite small because when you know what + * type of 3d functionality a card has, you know to which GPU family the + * GPU must belong. Because of this you only have to check a small part of + * the renderer string to distinguishes between different models from that + * family. + * + * The code also selects a default amount of video memory which we will + * use for an estimation of the amount of free texture memory. In case of + * real D3D the amount of texture memory includes video memory and system + * memory (to be specific AGP memory or in case of PCIE TurboCache / + * HyperMemory). We don't know how much system memory can be addressed by + * the system but we can make a reasonable estimation about the amount of + * video memory. If the value is slightly wrong it doesn't matter as we + * didn't include AGP-like memory which makes the amount of addressable + * memory higher and second OpenGL isn't that critical it moves to system + * memory behind our backs if really needed. Note that the amount of video + * memory can be overruled using a registry setting. */ + +#ifndef VBOX + int i; +#else + size_t i; +#endif + + for (i = 0; i < (sizeof(vendor_card_select_table) / sizeof(*vendor_card_select_table)); ++i) + { + if ((vendor_card_select_table[i].gl_vendor != *gl_vendor) + || (vendor_card_select_table[i].card_vendor != *card_vendor)) + continue; + TRACE_(d3d_caps)("Applying card_selector \"%s\".\n", vendor_card_select_table[i].description); + return vendor_card_select_table[i].select_card(gl_info, gl_renderer, vidmem); + } + + FIXME_(d3d_caps)("No card selector available for GL vendor %d and card vendor %04x.\n", + *gl_vendor, *card_vendor); + + /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice + * for Nvidia was because the hardware and drivers they make are of good quality. This makes + * them a good generic choice. */ + *card_vendor = HW_VENDOR_NVIDIA; +#ifndef VBOX_WITH_WDDM + if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600; +#else + /* tmp work around to disable quirk_no_np2 quirk for not-recognized drivers */ + if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE_6200; +#endif + + if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3; + if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE; + if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT; + return CARD_NVIDIA_RIVA_128; +} + +#ifndef VBOX_WITH_VMSVGA +static const struct fragment_pipeline *select_fragment_implementation(struct wined3d_adapter *adapter) +{ + const struct wined3d_gl_info *gl_info = &adapter->gl_info; + int vs_selected_mode, ps_selected_mode; + + select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode); + if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) + && gl_info->supported[ARB_FRAGMENT_PROGRAM]) return &arbfp_fragment_pipeline; + else if (ps_selected_mode == SHADER_ATI) return &atifs_fragment_pipeline; + else if (gl_info->supported[NV_REGISTER_COMBINERS] + && gl_info->supported[NV_TEXTURE_SHADER2]) return &nvts_fragment_pipeline; + else if (gl_info->supported[NV_REGISTER_COMBINERS]) return &nvrc_fragment_pipeline; + else return &ffp_fragment_pipeline; +} +#endif + +static const shader_backend_t *select_shader_backend(struct wined3d_adapter *adapter) +{ + int vs_selected_mode, ps_selected_mode; + + select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode); + if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) return &glsl_shader_backend; +#ifndef VBOX_WITH_VMSVGA + if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) return &arb_program_shader_backend; +#endif + return &none_shader_backend; +} + +#ifndef VBOX_WITH_VMSVGA +static const struct blit_shader *select_blit_implementation(struct wined3d_adapter *adapter) +{ + const struct wined3d_gl_info *gl_info = &adapter->gl_info; + int vs_selected_mode, ps_selected_mode; + + select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode); + if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) + && gl_info->supported[ARB_FRAGMENT_PROGRAM]) return &arbfp_blit; + else return &ffp_blit; +} +#endif + +#ifdef VBOX_WITH_VMSVGA +/** Checks if @a pszExtension is one of the extensions we're looking for and + * updates @a pGlInfo->supported accordingly. */ +static void check_gl_extension(struct wined3d_gl_info *pGlInfo, const char *pszExtension) +{ + size_t i; + TRACE_(d3d_caps)("- %s\n", debugstr_a(pszExtension)); + for (i = 0; i < RT_ELEMENTS(EXTENSION_MAP); i++) + if (!strcmp(pszExtension, EXTENSION_MAP[i].extension_string)) + { + TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string); + pGlInfo->supported[EXTENSION_MAP[i].extension] = TRUE; + return; + } +} +#endif + +/* Context activation is done by the caller. */ +BOOL IWineD3DImpl_FillGLCaps(struct wined3d_adapter *adapter, struct VBOXVMSVGASHADERIF *pVBoxShaderIf) +{ +#ifndef VBOX_WITH_VMSVGA + struct wined3d_driver_info *driver_info = &adapter->driver_info; +#endif + struct wined3d_gl_info *gl_info = &adapter->gl_info; +#ifndef VBOX_WITH_VMSVGA + const char *GL_Extensions = NULL; + const char *WGL_Extensions = NULL; +#endif + const char *gl_vendor_str, *gl_renderer_str, *gl_version_str; +#ifndef VBOX_WITH_VMSVGA + struct fragment_caps fragment_caps; +#endif + enum wined3d_gl_vendor gl_vendor; + enum wined3d_pci_vendor card_vendor; + enum wined3d_pci_device device; + GLint gl_max; + GLfloat gl_floatv[2]; + unsigned i; +#ifndef VBOX_WITH_VMSVGA + HDC hdc; +#endif + unsigned int vidmem=0; + DWORD gl_version; +#ifndef VBOX_WITH_VMSVGA + size_t len; +#endif + + TRACE_(d3d_caps)("(%p)\n", gl_info); + + ENTER_GL(); + + VBOX_CHECK_GL_CALL(gl_renderer_str = (const char *)glGetString(GL_RENDERER)); + TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_renderer_str)); + if (!gl_renderer_str) + { + LEAVE_GL(); + ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n"); + return FALSE; + } + + VBOX_CHECK_GL_CALL(gl_vendor_str = (const char *)glGetString(GL_VENDOR)); + TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_vendor_str)); + if (!gl_vendor_str) + { + LEAVE_GL(); + ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n"); + return FALSE; + } + + /* Parse the GL_VERSION field into major and minor information */ + VBOX_CHECK_GL_CALL(gl_version_str = (const char *)glGetString(GL_VERSION)); + TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_version_str)); + if (!gl_version_str) + { + LEAVE_GL(); + ERR_(d3d_caps)("Received a NULL GL_VERSION.\n"); + return FALSE; + } + gl_version = wined3d_parse_gl_version(gl_version_str); + + /* + * Initialize openGL extension related variables + * with Default values + */ + memset(gl_info->supported, 0, sizeof(gl_info->supported)); + gl_info->limits.blends = 1; + gl_info->limits.buffers = 1; + gl_info->limits.textures = 1; + gl_info->limits.fragment_samplers = 1; + gl_info->limits.vertex_samplers = 0; + gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers; + gl_info->limits.sampler_stages = 1; + gl_info->limits.glsl_vs_float_constants = 0; + gl_info->limits.glsl_ps_float_constants = 0; + gl_info->limits.arb_vs_float_constants = 0; + gl_info->limits.arb_vs_native_constants = 0; + gl_info->limits.arb_vs_instructions = 0; + gl_info->limits.arb_vs_temps = 0; + gl_info->limits.arb_ps_float_constants = 0; + gl_info->limits.arb_ps_local_constants = 0; + gl_info->limits.arb_ps_instructions = 0; + gl_info->limits.arb_ps_temps = 0; + + /* Retrieve opengl defaults */ + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max)); + gl_info->limits.clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max); + TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max); + +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + glGetIntegerv(GL_MAX_LIGHTS, &gl_max); + if (glGetError() != GL_NO_ERROR) + { + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, true /*fOtherProfile*/); + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_LIGHTS, &gl_max)); + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, false /*fOtherProfile*/); + } +#else + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_LIGHTS, &gl_max)); +#endif + gl_info->limits.lights = gl_max; + TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max); + + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max)); + gl_info->limits.texture_size = gl_max; + TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max); + +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv); + if (glGetError() != GL_NO_ERROR) + { + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, true /*fOtherProfile*/); + VBOX_CHECK_GL_CALL(glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv)); + if (glGetError() != GL_NO_ERROR) + gl_floatv[0] = gl_floatv[1] = 1; + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, false /*fOtherProfile*/); + } +#else + VBOX_CHECK_GL_CALL(glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv)); +#endif + gl_info->limits.pointsize_min = gl_floatv[0]; + gl_info->limits.pointsize_max = gl_floatv[1]; + TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]); + + /* Parse the gl supported features, in theory enabling parts of our code appropriately. */ +#ifndef VBOX_WITH_VMSVGA + GL_Extensions = (const char *)glGetString(GL_EXTENSIONS); + if (!GL_Extensions) + { + LEAVE_GL(); + ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n"); + return FALSE; + } + + LEAVE_GL(); + + TRACE_(d3d_caps)("GL_Extensions reported:\n"); +#endif + + gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE; + + gl_info->supported[VBOX_SHARED_CONTEXTS] = TRUE; + +#ifdef VBOX_WITH_VMSVGA + { + void *pvEnumCtx = NULL; + char szCurExt[256]; + while (pVBoxShaderIf->pfnGetNextExtension(pVBoxShaderIf, &pvEnumCtx, szCurExt, sizeof(szCurExt), false /*fOtherProfile*/)) + check_gl_extension(gl_info, szCurExt); + + /* The cheap way out. */ + pvEnumCtx = NULL; + while (pVBoxShaderIf->pfnGetNextExtension(pVBoxShaderIf, &pvEnumCtx, szCurExt, sizeof(szCurExt), true /*fOtherProfile*/)) + check_gl_extension(gl_info, szCurExt); + } +#else /* !VBOX_WITH_VMSVGA */ + while (*GL_Extensions) + { + const char *start; + char current_ext[256]; + + while (isspace(*GL_Extensions)) ++GL_Extensions; + start = GL_Extensions; + while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions; + + len = GL_Extensions - start; + if (!len || len >= sizeof(current_ext)) continue; + + memcpy(current_ext, start, len); + current_ext[len] = '\0'; + TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext)); + + for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) + { + if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string)) + { + TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string); + gl_info->supported[EXTENSION_MAP[i].extension] = TRUE; + break; + } + } + } +#endif /* !VBOX_WITH_VMSVGA */ + +#ifdef VBOX_WITH_VMSVGA +# ifdef RT_OS_WINDOWS +# define OGLGETPROCADDRESS wglGetProcAddress +# elif RT_OS_DARWIN +# define OGLGETPROCADDRESS(x) MyNSGLGetProcAddress(x) +# else +extern void (*glXGetProcAddress(const GLubyte *procname))( void ); +# define OGLGETPROCADDRESS(x) glXGetProcAddress((const GLubyte *)x) +# endif +#endif + + /* Now work out what GL support this card really has */ +#define USE_GL_FUNC(type, pfn, ext, replace) \ +{ \ + DWORD ver = ver_for_ext(ext); \ + if (gl_info->supported[ext]) gl_info->pfn = (type)OGLGETPROCADDRESS(#pfn); \ + else if (ver && ver <= gl_version) gl_info->pfn = (type)OGLGETPROCADDRESS(#replace); \ + else gl_info->pfn = NULL; \ +} + GL_EXT_FUNCS_GEN; +#undef USE_GL_FUNC + +#ifndef VBOX_WITH_VMSVGA +#define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)OGLGETPROCADDRESS(#pfn); + WGL_EXT_FUNCS_GEN; +#undef USE_GL_FUNC +#endif + + ENTER_GL(); + + /* Now mark all the extensions supported which are included in the opengl core version. Do this *after* + * loading the functions, otherwise the code above will load the extension entry points instead of the + * core functions, which may not work. */ + for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) + { + if (!gl_info->supported[EXTENSION_MAP[i].extension] + && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version) + { + TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string); + gl_info->supported[EXTENSION_MAP[i].extension] = TRUE; + } + } + + if (gl_info->supported[APPLE_FENCE]) + { + /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically. + * The apple extension interacts with some other apple exts. Disable the NV + * extension if the apple one is support to prevent confusion in other parts + * of the code. */ + gl_info->supported[NV_FENCE] = FALSE; + } + if (gl_info->supported[APPLE_FLOAT_PIXELS]) + { + /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel + * + * The enums are the same: + * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A + * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B + * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814 + * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815 + * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B + */ + if (!gl_info->supported[ARB_TEXTURE_FLOAT]) + { + TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n"); + gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE; + } + if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) + { + TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n"); + gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE; + } + } + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + { + /* GL_ARB_map_buffer_range and GL_APPLE_flush_buffer_range provide the same + * functionality. Prefer the ARB extension */ + gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] = FALSE; + } + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) + { + TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n"); + gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE; + } + if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP]) + { + TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n"); + gl_info->supported[ARB_DEPTH_CLAMP] = TRUE; + } + if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && gl_info->supported[EXT_VERTEX_ARRAY_BGRA]) + { + TRACE_(d3d_caps)(" IMPLIED: ARB_vertex_array_bgra support (by EXT_vertex_array_bgra).\n"); + gl_info->supported[ARB_VERTEX_ARRAY_BGRA] = TRUE; + } + if (gl_info->supported[NV_TEXTURE_SHADER2]) + { + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2 + * are supported. The nv extensions provide the same functionality as the + * ATI one, and a bit more(signed pixelformats). */ + gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE; + } + } + + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max)); + gl_info->limits.general_combiners = gl_max; + TRACE_(d3d_caps)("Max general combiners: %d.\n", gl_max); + } + if (gl_info->supported[ARB_DRAW_BUFFERS]) + { + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max)); + gl_info->limits.buffers = gl_max; + TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max); + } + if (gl_info->supported[ARB_MULTITEXTURE]) + { +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max); + if (glGetError() != GL_NO_ERROR) + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &gl_max)); +#else + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max)); +#endif + gl_info->limits.textures = min(MAX_TEXTURES, gl_max); + TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->limits.textures); + + if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) + { + GLint tmp; + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp)); + gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp); + } + else + { + gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, (UINT)gl_max); + } + TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers); + + if (gl_info->supported[ARB_VERTEX_SHADER]) + { + GLint tmp; + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp)); + gl_info->limits.vertex_samplers = tmp; + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp)); + gl_info->limits.combined_samplers = tmp; + + /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup + * is known at shader link time. In a vertex shader + pixel shader combination this isn't + * an issue because then the sampler setup only depends on the two shaders. If a pixel + * shader is used with fixed function vertex processing we're fine too because fixed function + * vertex processing doesn't use any samplers. If fixed function fragment processing is + * used we have to make sure that all vertex sampler setups are valid together with all + * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES + * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards). + * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and + * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have + * a fixed function pipeline anymore. + * + * So this is just a check to check that our assumption holds true. If not, write a warning + * and reduce the number of vertex samplers or probably disable vertex texture fetch. */ + if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12 + && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers) + { + FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n", + gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers); + FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n"); + if (gl_info->limits.combined_samplers > MAX_TEXTURES) + gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES; + else + gl_info->limits.vertex_samplers = 0; + } + } + else + { + gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers; + } + TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers); + TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->limits.combined_samplers); + } + if (gl_info->supported[ARB_VERTEX_BLEND]) + { +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max); + if (glGetError() != GL_NO_ERROR) + { + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, true /*fOtherProfile*/); + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max)); + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, false /*fOtherProfile*/); + } +#else + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max)); +#endif + gl_info->limits.blends = gl_max; + TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->limits.blends); + } + if (gl_info->supported[EXT_TEXTURE3D]) + { + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max)); + gl_info->limits.texture3d_size = gl_max; + TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->limits.texture3d_size); + } + if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) + { + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max)); + gl_info->limits.anisotropy = gl_max; + TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->limits.anisotropy); + } + if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) + { +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max)); + if (glGetError() != GL_NO_ERROR) + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, true /*fOtherProfile*/); +#endif + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max))); + gl_info->limits.arb_ps_float_constants = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants); + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max))); + gl_info->limits.arb_ps_native_constants = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n", + gl_info->limits.arb_ps_native_constants); + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max))); + gl_info->limits.arb_ps_temps = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps); + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max))); + gl_info->limits.arb_ps_instructions = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions); + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max))); + gl_info->limits.arb_ps_local_constants = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions); +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, false /*fOtherProfile*/); +#endif + } + if (gl_info->supported[ARB_VERTEX_PROGRAM]) + { +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max)); + if (glGetError() != GL_NO_ERROR) + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, true /*fOtherProfile*/); +#endif + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max))); + gl_info->limits.arb_vs_float_constants = gl_max; + TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants); + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max))); + gl_info->limits.arb_vs_native_constants = gl_max; + TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native float constants: %d.\n", + gl_info->limits.arb_vs_native_constants); + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max))); + gl_info->limits.arb_vs_temps = gl_max; + TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps); + VBOX_CHECK_GL_CALL(GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max))); + gl_info->limits.arb_vs_instructions = gl_max; + TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions); +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, false /*fOtherProfile*/); +#endif +#ifndef VBOX_WITH_VMSVGA + if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT; +#endif + } + if (gl_info->supported[ARB_VERTEX_SHADER]) + { + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max)); + gl_info->limits.glsl_vs_float_constants = gl_max / 4; +#ifdef VBOX_WITH_WDDM + /* AFAICT the " / 4" here comes from that we're going to use the glsl_vs/ps_float_constants to create vec4 arrays, + * thus each array element has 4 components, so the actual number of vec4 arrays is GL_MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS_ARB / 4 + * win8 Aero won't properly work with this constant < 256 in any way, + * while Intel drivers I've encountered this problem with supports vec4 arrays of size > GL_MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS_ARB / 4 + * so use it here. + * @todo: add logging + * @todo: perhaps should be movet to quirks? + * */ + if (gl_info->limits.glsl_vs_float_constants < 256 && gl_max >= 256) + { + DWORD dwVersion = GetVersion(); + DWORD dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion))); + DWORD dwMinor = (DWORD)(HIBYTE(LOWORD(dwVersion))); + /* tmp workaround Win8 Aero requirement for 256 */ + if (dwMajor > 6 || dwMinor > 1) + { + gl_info->limits.glsl_vs_float_constants = 256; + } + } +#endif + TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants); + } + if (gl_info->supported[ARB_FRAGMENT_SHADER]) + { + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max)); + gl_info->limits.glsl_ps_float_constants = gl_max / 4; +#ifdef VBOX_WITH_WDDM + /* AFAICT the " / 4" here comes from that we're going to use the glsl_vs/ps_float_constants to create vec4 arrays, + * thus each array element has 4 components, so the actual number of vec4 arrays is GL_MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS_ARB / 4 + * win8 Aero won't properly work with this constant < 256 in any way, + * while Intel drivers I've encountered this problem with supports vec4 arrays of size > GL_MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS_ARB / 4 + * so use it here. + * @todo: add logging + * @todo: perhaps should be movet to quirks? + * */ + if (gl_info->limits.glsl_ps_float_constants < 256 && gl_max >= 256) + { + DWORD dwVersion = GetVersion(); + DWORD dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion))); + DWORD dwMinor = (DWORD)(HIBYTE(LOWORD(dwVersion))); + /* tmp workaround Win8 Aero requirement for 256 */ + if (dwMajor > 6 || dwMinor > 1) + { + gl_info->limits.glsl_ps_float_constants = 256; + } + } +#endif + TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants); +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max); + if (glGetError() != GL_NO_ERROR) + { + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, true /*fOtherProfile*/); + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max)); + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, false /*fOtherProfile*/); + } +#else + VBOX_CHECK_GL_CALL(glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max)); +#endif + gl_info->limits.glsl_varyings = gl_max; + TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4); + } + if (gl_info->supported[ARB_SHADING_LANGUAGE_100]) + { + const char *str = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB); + unsigned int major, minor; + + TRACE_(d3d_caps)("GLSL version string: %s.\n", debugstr_a(str)); + + /* The format of the GLSL version string is "major.minor[.release] [vendor info]". */ + sscanf(str, "%u.%u", &major, &minor); + gl_info->glsl_version = MAKEDWORD_VERSION(major, minor); + } + if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) + { +#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE + glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess); + if (glGetError() != GL_NO_ERROR) + { + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, true /*fOtherProfile*/); + VBOX_CHECK_GL_CALL(glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess)); + pVBoxShaderIf->pfnSwitchInitProfile(pVBoxShaderIf, false /*fOtherProfile*/); + } +#else + VBOX_CHECK_GL_CALL(glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess)); +#endif + } + else + { + gl_info->limits.shininess = 128.0f; + } + if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) + { + /* If we have full NP2 texture support, disable + * GL_ARB_texture_rectangle because we will never use it. + * This saves a few redundant glDisable calls. */ + gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE; + } + if (gl_info->supported[ATI_FRAGMENT_SHADER]) + { + /* Disable NV_register_combiners and fragment shader if this is supported. + * generally the NV extensions are preferred over the ATI ones, and this + * extension is disabled if register_combiners and texture_shader2 are both + * supported. So we reach this place only if we have incomplete NV dxlevel 8 + * fragment processing support. */ + gl_info->supported[NV_REGISTER_COMBINERS] = FALSE; + gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE; + gl_info->supported[NV_TEXTURE_SHADER] = FALSE; + gl_info->supported[NV_TEXTURE_SHADER2] = FALSE; + } + if (gl_info->supported[NV_HALF_FLOAT]) + { + /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */ + gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE; + } + if (gl_info->supported[ARB_POINT_SPRITE]) + { + gl_info->limits.point_sprite_units = gl_info->limits.textures; + } + else + { + gl_info->limits.point_sprite_units = 0; + } +#ifndef VBOX_WITH_VMSVGA + checkGLcall("extension detection"); +#endif + LEAVE_GL(); + +#ifndef VBOX_WITH_VMSVGA + adapter->fragment_pipe = select_fragment_implementation(adapter); +#endif + adapter->shader_backend = select_shader_backend(adapter); +#ifndef VBOX_WITH_VMSVGA + adapter->blitter = select_blit_implementation(adapter); + + adapter->fragment_pipe->get_caps(gl_info, &fragment_caps); + gl_info->limits.texture_stages = fragment_caps.MaxTextureBlendStages; + TRACE_(d3d_caps)("Max texture stages: %u.\n", gl_info->limits.texture_stages); + + /* In some cases the number of texture stages can be larger than the number + * of samplers. The GF4 for example can use only 2 samplers (no fragment + * shaders), but 8 texture stages (register combiners). */ + gl_info->limits.sampler_stages = max(gl_info->limits.fragment_samplers, gl_info->limits.texture_stages); +#endif + + if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]) + { + gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbuffer; + gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbuffer; + gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffers; + gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffers; + gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorage; + gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisample; + gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameteriv; + gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebuffer; + gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebuffer; + gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffers; + gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffers; + gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatus; + gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1D; + gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2D; + gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3D; + gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbuffer; + gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameteriv; + gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebuffer; + gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmap; + } + else + { + if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) + { + gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbufferEXT; + gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbufferEXT; + gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffersEXT; + gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffersEXT; + gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorageEXT; + gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameterivEXT; + gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebufferEXT; + gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebufferEXT; + gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffersEXT; + gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffersEXT; + gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatusEXT; + gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1DEXT; + gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2DEXT; + gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3DEXT; + gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbufferEXT; + gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameterivEXT; + gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmapEXT; + } +#ifndef VBOX_WITH_VMSVGA + else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + WARN_(d3d_caps)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n"); + wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER; + } +#endif + if (gl_info->supported[EXT_FRAMEBUFFER_BLIT]) + { + gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebufferEXT; + } + if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE]) + { + gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisampleEXT; + } + } + +#ifndef VBOX_WITH_VMSVGA + /* MRTs are currently only supported when FBOs are used. */ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) + { + gl_info->limits.buffers = 1; + } +#endif + gl_vendor = wined3d_guess_gl_vendor(gl_info, gl_vendor_str, gl_renderer_str); + card_vendor = wined3d_guess_card_vendor(gl_vendor_str, gl_renderer_str); + TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x/0x%04x)\n", debugstr_a(gl_vendor_str), gl_vendor, card_vendor); + + device = wined3d_guess_card(gl_info, gl_renderer_str, &gl_vendor, &card_vendor, &vidmem); + TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", card_vendor, device); + + /* If we have an estimate use it, else default to 64MB; */ + if(vidmem) + gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */ + else + gl_info->vidmem = WINE_DEFAULT_VIDMEM; + + gl_info->wrap_lookup[WINED3DTADDRESS_WRAP - WINED3DTADDRESS_WRAP] = GL_REPEAT; + gl_info->wrap_lookup[WINED3DTADDRESS_MIRROR - WINED3DTADDRESS_WRAP] = + gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT; + gl_info->wrap_lookup[WINED3DTADDRESS_CLAMP - WINED3DTADDRESS_WRAP] = GL_CLAMP_TO_EDGE; + gl_info->wrap_lookup[WINED3DTADDRESS_BORDER - WINED3DTADDRESS_WRAP] = + gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT; + gl_info->wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP] = + gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT; + +#ifndef VBOX_WITH_VMSVGA + /* Make sure there's an active HDC else the WGL extensions will fail */ + hdc = pwglGetCurrentDC(); + if (hdc) { + /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */ + if(GL_EXTCALL(wglGetExtensionsStringARB)) + WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc)); + + if (NULL == WGL_Extensions) { + ERR(" WGL_Extensions returns NULL\n"); + } else { + TRACE_(d3d_caps)("WGL_Extensions reported:\n"); + while (*WGL_Extensions != 0x00) { + const char *Start; + char ThisExtn[256]; + + while (isspace(*WGL_Extensions)) WGL_Extensions++; + Start = WGL_Extensions; + while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) { + WGL_Extensions++; + } + + len = WGL_Extensions - Start; + if (len == 0 || len >= sizeof(ThisExtn)) + continue; + + memcpy(ThisExtn, Start, len); + ThisExtn[len] = '\0'; + TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn)); + + if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) { + gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE; + TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n"); + } + if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) { + gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE; + TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n"); + } + } + } + } +#endif + + fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device); +#ifndef VBOX_WITH_VMSVGA + init_driver_info(driver_info, card_vendor, device); + add_gl_compat_wrappers(gl_info); +#endif + + return TRUE; +} + diff --git a/src/VBox/Devices/Graphics/shaderlib/glsl_shader.c b/src/VBox/Devices/Graphics/shaderlib/glsl_shader.c new file mode 100644 index 00000000..15b337b7 --- /dev/null +++ b/src/VBox/Devices/Graphics/shaderlib/glsl_shader.c @@ -0,0 +1,5608 @@ +/* + * GLSL pixel and vertex shader implementation + * + * Copyright 2006 Jason Green + * Copyright 2006-2007 Henri Verbeet + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers + * Copyright 2009 Henri Verbeet for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +/* + * D3D shader asm has swizzles on source parameters, and write masks for + * destination parameters. GLSL uses swizzles for both. The result of this is + * that for example "mov dst.xw, src.zyxw" becomes "dst.xw = src.zw" in GLSL. + * Ie, to generate a proper GLSL source swizzle, we need to take the D3D write + * mask for the destination parameter into account. + */ + +#include "config.h" +#include "wine/port.h" +#include +#include +#include "wined3d_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); +WINE_DECLARE_DEBUG_CHANNEL(d3d_constants); +WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); +WINE_DECLARE_DEBUG_CHANNEL(d3d); + +#ifdef VBOX_WITH_VMSVGA +#define LOG_GROUP LOG_GROUP_DEV_VMSVGA +#include +#undef WDLOG +#define WDLOG(_m) Log(_m) +#undef CONST +#define CONST const +#endif + +#define GLINFO_LOCATION (*gl_info) + +#define WINED3D_GLSL_SAMPLE_PROJECTED 0x1 +#define WINED3D_GLSL_SAMPLE_RECT 0x2 +#define WINED3D_GLSL_SAMPLE_LOD 0x4 +#define WINED3D_GLSL_SAMPLE_GRAD 0x8 + +typedef struct { + char reg_name[150]; + char mask_str[6]; +} glsl_dst_param_t; + +typedef struct { + char reg_name[150]; + char param_str[200]; +} glsl_src_param_t; + +typedef struct { + const char *name; + DWORD coord_mask; +} glsl_sample_function_t; + +enum heap_node_op +{ + HEAP_NODE_TRAVERSE_LEFT, + HEAP_NODE_TRAVERSE_RIGHT, + HEAP_NODE_POP, +}; + +struct constant_entry +{ + unsigned int idx; + unsigned int version; +}; + +struct constant_heap +{ + struct constant_entry *entries; + unsigned int *positions; + unsigned int size; +}; + +/* GLSL shader private data */ +struct shader_glsl_priv { + struct wined3d_shader_buffer shader_buffer; + struct wine_rb_tree program_lookup; + struct glsl_shader_prog_link *glsl_program; + struct constant_heap vconst_heap; + struct constant_heap pconst_heap; + unsigned char *stack; + GLhandleARB depth_blt_program[tex_type_count]; + UINT next_constant_version; +}; + +/* Struct to maintain data about a linked GLSL program */ +struct glsl_shader_prog_link { + struct wine_rb_entry program_lookup_entry; + struct list vshader_entry; + struct list pshader_entry; + GLhandleARB programId; + GLint *vuniformF_locations; + GLint *puniformF_locations; + GLint vuniformI_locations[MAX_CONST_I]; + GLint puniformI_locations[MAX_CONST_I]; + GLint posFixup_location; + GLint np2Fixup_location; + GLint bumpenvmat_location[MAX_TEXTURES]; + GLint luminancescale_location[MAX_TEXTURES]; + GLint luminanceoffset_location[MAX_TEXTURES]; + GLint ycorrection_location; + GLenum vertex_color_clamp; + IWineD3DVertexShader *vshader; + IWineD3DPixelShader *pshader; + struct vs_compile_args vs_args; + struct ps_compile_args ps_args; + UINT constant_version; + const struct wined3d_context *context; + UINT inp2Fixup_info; +}; + +#ifdef VBOX_WITH_VMSVGA +# define WINEFIXUPINFO_NOINDEX (~0U) +#else +#define WINEFIXUPINFO_NOINDEX (~0UL) +#endif +#define WINEFIXUPINFO_GET(_p) get_fixup_info((const IWineD3DPixelShaderImpl*)(_p)->pshader, (_p)->inp2Fixup_info) +#define WINEFIXUPINFO_ISVALID(_p) ((_p)->inp2Fixup_info != WINEFIXUPINFO_NOINDEX) +#ifdef VBOX_WITH_VMSVGA +# define WINEFIXUPINFO_INIT(_p) do { (_p)->inp2Fixup_info = WINEFIXUPINFO_NOINDEX; } while (0) +#else +#define WINEFIXUPINFO_INIT(_p) ((_p)->inp2Fixup_info == WINEFIXUPINFO_NOINDEX) +#endif + +typedef struct { + IWineD3DVertexShader *vshader; + IWineD3DPixelShader *pshader; + struct ps_compile_args ps_args; + struct vs_compile_args vs_args; + const struct wined3d_context *context; +} glsl_program_key_t; + +struct shader_glsl_ctx_priv { + const struct vs_compile_args *cur_vs_args; + const struct ps_compile_args *cur_ps_args; + struct ps_np2fixup_info *cur_np2fixup_info; +}; + +struct glsl_ps_compiled_shader +{ + struct ps_compile_args args; + struct ps_np2fixup_info np2fixup; + GLhandleARB prgId; + const struct wined3d_context *context; +}; + +struct glsl_pshader_private +{ + struct glsl_ps_compiled_shader *gl_shaders; + UINT num_gl_shaders, shader_array_size; +}; + +struct glsl_vs_compiled_shader +{ + struct vs_compile_args args; + GLhandleARB prgId; + const struct wined3d_context *context; +}; + +struct glsl_vshader_private +{ + struct glsl_vs_compiled_shader *gl_shaders; + UINT num_gl_shaders, shader_array_size; +}; + +static const char *debug_gl_shader_type(GLenum type) +{ + switch (type) + { +#define WINED3D_TO_STR(u) case u: return #u + WINED3D_TO_STR(GL_VERTEX_SHADER_ARB); + WINED3D_TO_STR(GL_GEOMETRY_SHADER_ARB); + WINED3D_TO_STR(GL_FRAGMENT_SHADER_ARB); +#undef WINED3D_TO_STR + default: + return wine_dbg_sprintf("UNKNOWN(%#x)", type); + } +} + +/* Extract a line from the info log. + * Note that this modifies the source string. */ +static char *get_info_log_line(char **ptr, int *pcbStr) +{ + char *p, *q; + const int cbStr = *pcbStr; + + if (!cbStr) + { + /* zero-length string */ + return NULL; + } + + if ((*ptr)[cbStr-1] != '\0') + { + ERR("string should be null-rerminated, forcing it!"); + (*ptr)[cbStr-1] = '\0'; + } + p = *ptr; + if (!*p) + { + *pcbStr = 0; + return NULL; + } + + if (!(q = strstr(p, "\n"))) + { + /* the string contains a single line! */ + *ptr += strlen(p); + *pcbStr = 0; + return p; + } + + *q = '\0'; + *pcbStr = cbStr - (((uintptr_t)q) - ((uintptr_t)p)) - 1; + Assert((*pcbStr) >= 0); + Assert((*pcbStr) < cbStr); + *ptr = q + 1; + + return p; +} + +/** Prints the GLSL info log which will contain error messages if they exist */ +/* GL locking is done by the caller */ +static void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLhandleARB obj) +{ + int infologLength = 0; + char *infoLog; + unsigned int i; + BOOL is_spam; + + static const char * const spam[] = + { + "Vertex shader was successfully compiled to run on hardware.\n", /* fglrx */ + "Fragment shader was successfully compiled to run on hardware.\n", /* fglrx, with \n */ + "Fragment shader was successfully compiled to run on hardware.", /* fglrx, no \n */ + "Fragment shader(s) linked, vertex shader(s) linked. \n ", /* fglrx, with \n */ + "Fragment shader(s) linked, vertex shader(s) linked.", /* fglrx, no \n */ + "Vertex shader(s) linked, no fragment shader(s) defined. \n ", /* fglrx, with \n */ + "Vertex shader(s) linked, no fragment shader(s) defined.", /* fglrx, no \n */ + "Fragment shader(s) linked, no vertex shader(s) defined. \n ", /* fglrx, with \n */ + "Fragment shader(s) linked, no vertex shader(s) defined.", /* fglrx, no \n */ + }; + +#ifndef VBOXWINEDBG_SHADERS + if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) return; +#endif + + GL_EXTCALL(glGetObjectParameterivARB(obj, + GL_OBJECT_INFO_LOG_LENGTH_ARB, + &infologLength)); + + /* A size of 1 is just a null-terminated string, so the log should be bigger than + * that if there are errors. */ + if (infologLength > 1) + { + char *ptr, *line; + int cbPtr; + + /* Fglrx doesn't terminate the string properly, but it tells us the proper length. + * So use HEAP_ZERO_MEMORY to avoid uninitialized bytes + */ + infoLog = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, infologLength); + GL_EXTCALL(glGetInfoLogARB(obj, infologLength, NULL, infoLog)); + is_spam = FALSE; + + for(i = 0; i < sizeof(spam) / sizeof(spam[0]); i++) { + if(strcmp(infoLog, spam[i]) == 0) { + is_spam = TRUE; + break; + } + } + + ptr = infoLog; + cbPtr = infologLength; + if (is_spam) + { + WDLOG(("Spam received from GLSL shader #%u:\n", obj)); + while ((line = get_info_log_line(&ptr, &cbPtr))) WDLOG((" %s\n", line)); + } + else + { + WDLOG(("Error received from GLSL shader #%u:\n", obj)); + while ((line = get_info_log_line(&ptr, &cbPtr))) WDLOG((" %s\n", line)); + } + HeapFree(GetProcessHeap(), 0, infoLog); + } +} + +static void shader_glsl_dump_shader_source(const struct wined3d_gl_info *gl_info, GLhandleARB shader) +{ + char *ptr; + GLint tmp, source_size; + char *source = NULL; + int cbPtr; + + GL_EXTCALL(glGetObjectParameterivARB(shader, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &tmp)); + + source = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, tmp); + if (!source) + { + ERR("Failed to allocate %d bytes for shader source.\n", tmp); + return; + } + + source_size = tmp; + + WDLOG(("Object %u:\n", shader)); + GL_EXTCALL(glGetObjectParameterivARB(shader, GL_OBJECT_SUBTYPE_ARB, &tmp)); + WDLOG((" GL_OBJECT_SUBTYPE_ARB: %s.\n", debug_gl_shader_type(tmp))); + GL_EXTCALL(glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &tmp)); + WDLOG((" GL_OBJECT_COMPILE_STATUS_ARB: %d.\n", tmp)); + WDLOG(("\n")); + + if (tmp == 0) + { + /* Compilation error, print the compiler's error messages. */ + print_glsl_info_log(gl_info, shader); + } + + ptr = source; + cbPtr = source_size; + GL_EXTCALL(glGetShaderSourceARB(shader, source_size, NULL, source)); +#if 0 + while ((line = get_info_log_line(&ptr, &cbPtr))) WDLOG((" %s\n", line)); +#else + WDLOG(("*****shader source***\n")); + WDLOG((" %s\n", source)); + WDLOG(("\n*****END shader source***\n\n")); +#endif + WDLOG(("\n")); +#ifdef VBOX + HeapFree(GetProcessHeap(), 0, source); +#endif +} + +/* GL locking is done by the caller. */ +static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_info, GLhandleARB program) +{ + GLint i, object_count; + GLhandleARB *objects; + char *source = NULL; + + WDLOG(("\n***************************dumping program %d******************************\n", program)); + + GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_ATTACHED_OBJECTS_ARB, &object_count)); + objects = HeapAlloc(GetProcessHeap(), 0, object_count * sizeof(*objects)); + if (!objects) + { + ERR("Failed to allocate object array memory.\n"); + return; + } + + GL_EXTCALL(glGetAttachedObjectsARB(program, object_count, NULL, objects)); + for (i = 0; i < object_count; ++i) + { + shader_glsl_dump_shader_source(gl_info, objects[i]); + } + + HeapFree(GetProcessHeap(), 0, source); + HeapFree(GetProcessHeap(), 0, objects); + + WDLOG(("\n***************************END dumping program %d******************************\n\n", program)); +} + +/* GL locking is done by the caller. */ +static void shader_glsl_validate_compile_link(const struct wined3d_gl_info *gl_info, GLhandleARB program, GLboolean fIsProgram) +{ + GLint tmp = -1; + +#ifndef VBOXWINEDBG_SHADERS + if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) return; +#endif + + GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_TYPE_ARB, &tmp)); + if (tmp == GL_PROGRAM_OBJECT_ARB) + { + if (!fIsProgram) + { + ERR("this is a program, but shader expected"); + } + GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &tmp)); + if (!tmp) + { + ERR("Program %p link status invalid.\n", (void *)(uintptr_t)program); +#ifndef VBOXWINEDBG_SHADERS + shader_glsl_dump_program_source(gl_info, program); +#endif + } +#if defined(VBOX_WITH_VMSVGA) && defined(DEBUG) + shader_glsl_dump_program_source(gl_info, program); +#endif + } + else if (tmp == GL_SHADER_OBJECT_ARB) + { + if (fIsProgram) + { + ERR("this is a shader, but program expected"); + } + + GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_COMPILE_STATUS_ARB, &tmp)); + if (!tmp) + { + ERR("Shader %p compile status invalid.\n", (void *)(uintptr_t)program); + shader_glsl_dump_shader_source(gl_info, program); + } + } + else + { + ERR("unexpected oject type(%d)!", tmp); + } + + print_glsl_info_log(gl_info, program); +} + +/** + * Loads (pixel shader) samplers + */ +/* GL locking is done by the caller */ +static void shader_glsl_load_psamplers(const struct wined3d_gl_info *gl_info, + DWORD *tex_unit_map, GLhandleARB programId) +{ + GLint name_loc; + int i; + char sampler_name[20]; + + for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { + snprintf(sampler_name, sizeof(sampler_name), "Psampler%d", i); + name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name)); + if (name_loc != -1) { + DWORD mapped_unit = tex_unit_map[i]; + if (mapped_unit != WINED3D_UNMAPPED_STAGE && mapped_unit < gl_info->limits.fragment_samplers) + { + TRACE("Loading %s for texture %d\n", sampler_name, mapped_unit); + GL_EXTCALL(glUniform1iARB(name_loc, mapped_unit)); + checkGLcall("glUniform1iARB"); + } else { + ERR("Trying to load sampler %s on unsupported unit %d\n", sampler_name, mapped_unit); + } + } + } +} + +/* GL locking is done by the caller */ +static void shader_glsl_load_vsamplers(const struct wined3d_gl_info *gl_info, + DWORD *tex_unit_map, GLhandleARB programId) +{ + GLint name_loc; + char sampler_name[20]; + int i; + + for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) { + snprintf(sampler_name, sizeof(sampler_name), "Vsampler%d", i); + name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name)); + if (name_loc != -1) { + DWORD mapped_unit = tex_unit_map[MAX_FRAGMENT_SAMPLERS + i]; + if (mapped_unit != WINED3D_UNMAPPED_STAGE && mapped_unit < gl_info->limits.combined_samplers) + { + TRACE("Loading %s for texture %d\n", sampler_name, mapped_unit); + GL_EXTCALL(glUniform1iARB(name_loc, mapped_unit)); + checkGLcall("glUniform1iARB"); + } else { + ERR("Trying to load sampler %s on unsupported unit %d\n", sampler_name, mapped_unit); + } + } + } +} + +/* GL locking is done by the caller */ +static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const float *constants, + const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) +{ + int stack_idx = 0; + unsigned int heap_idx = 1; + unsigned int idx; + + if (heap->entries[heap_idx].version <= version) return; + + idx = heap->entries[heap_idx].idx; + if (constant_locations[idx] != -1) GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4])); + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + + while (stack_idx >= 0) + { + /* Note that we fall through to the next case statement. */ + switch(stack[stack_idx]) + { + case HEAP_NODE_TRAVERSE_LEFT: + { + unsigned int left_idx = heap_idx << 1; + if (left_idx < heap->size && heap->entries[left_idx].version > version) + { + heap_idx = left_idx; + idx = heap->entries[heap_idx].idx; + if (constant_locations[idx] != -1) + GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4])); + + stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT; + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + break; + } + } RT_FALL_THRU(); + + case HEAP_NODE_TRAVERSE_RIGHT: + { + unsigned int right_idx = (heap_idx << 1) + 1; + if (right_idx < heap->size && heap->entries[right_idx].version > version) + { + heap_idx = right_idx; + idx = heap->entries[heap_idx].idx; + if (constant_locations[idx] != -1) + GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4])); + + stack[stack_idx++] = HEAP_NODE_POP; + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + break; + } + } RT_FALL_THRU(); + + case HEAP_NODE_POP: + { + heap_idx >>= 1; + --stack_idx; + break; + } + } + } + checkGLcall("walk_constant_heap()"); +} + +/* GL locking is done by the caller */ +static inline void apply_clamped_constant(const struct wined3d_gl_info *gl_info, GLint location, const GLfloat *data) +{ + GLfloat clamped_constant[4]; + + if (location == -1) return; + + clamped_constant[0] = data[0] < -1.0f ? -1.0f : data[0] > 1.0f ? 1.0f : data[0]; + clamped_constant[1] = data[1] < -1.0f ? -1.0f : data[1] > 1.0f ? 1.0f : data[1]; + clamped_constant[2] = data[2] < -1.0f ? -1.0f : data[2] > 1.0f ? 1.0f : data[2]; + clamped_constant[3] = data[3] < -1.0f ? -1.0f : data[3] > 1.0f ? 1.0f : data[3]; + + GL_EXTCALL(glUniform4fvARB(location, 1, clamped_constant)); +} + +/* GL locking is done by the caller */ +static inline void walk_constant_heap_clamped(const struct wined3d_gl_info *gl_info, const float *constants, + const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) +{ + int stack_idx = 0; + unsigned int heap_idx = 1; + unsigned int idx; + + if (heap->entries[heap_idx].version <= version) return; + + idx = heap->entries[heap_idx].idx; + apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]); + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + + while (stack_idx >= 0) + { + /* Note that we fall through to the next case statement. */ + switch(stack[stack_idx]) + { + case HEAP_NODE_TRAVERSE_LEFT: + { + unsigned int left_idx = heap_idx << 1; + if (left_idx < heap->size && heap->entries[left_idx].version > version) + { + heap_idx = left_idx; + idx = heap->entries[heap_idx].idx; + apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]); + + stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT; + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + break; + } + } RT_FALL_THRU(); + + case HEAP_NODE_TRAVERSE_RIGHT: + { + unsigned int right_idx = (heap_idx << 1) + 1; + if (right_idx < heap->size && heap->entries[right_idx].version > version) + { + heap_idx = right_idx; + idx = heap->entries[heap_idx].idx; + apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]); + + stack[stack_idx++] = HEAP_NODE_POP; + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + break; + } + } RT_FALL_THRU(); + + case HEAP_NODE_POP: + { + heap_idx >>= 1; + --stack_idx; + break; + } + } + } + checkGLcall("walk_constant_heap_clamped()"); +} + +/* Loads floating point constants (aka uniforms) into the currently set GLSL program. */ +/* GL locking is done by the caller */ +static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const struct wined3d_gl_info *gl_info, + const float *constants, const GLint *constant_locations, const struct constant_heap *heap, + unsigned char *stack, UINT version) +{ + const local_constant *lconst; + + /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */ + if (This->baseShader.reg_maps.shader_version.major == 1 + && shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type)) + walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version); + else + walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version); + + if (!This->baseShader.load_local_constsF) + { + TRACE("No need to load local float constants for this shader\n"); + return; + } + + /* Immediate constants are clamped to [-1;1] at shader creation time if needed */ + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) + { + GLint location = constant_locations[lconst->idx]; + /* We found this uniform name in the program - go ahead and send the data */ + if (location != -1) GL_EXTCALL(glUniform4fvARB(location, 1, (const GLfloat *)lconst->value)); + } + checkGLcall("glUniform4fvARB()"); +} + +/* Loads integer constants (aka uniforms) into the currently set GLSL program. */ +/* GL locking is done by the caller */ +static void shader_glsl_load_constantsI(IWineD3DBaseShaderImpl *This, const struct wined3d_gl_info *gl_info, + const GLint locations[MAX_CONST_I], const int *constants, WORD constants_set) +{ + unsigned int i; + struct list* ptr; + + for (i = 0; constants_set; constants_set >>= 1, ++i) + { + if (!(constants_set & 1)) continue; + + TRACE_(d3d_constants)("Loading constants %u: %i, %i, %i, %i\n", + i, constants[i*4], constants[i*4+1], constants[i*4+2], constants[i*4+3]); + + /* We found this uniform name in the program - go ahead and send the data */ + GL_EXTCALL(glUniform4ivARB(locations[i], 1, &constants[i*4])); + checkGLcall("glUniform4ivARB"); + } + + /* Load immediate constants */ + ptr = list_head(&This->baseShader.constantsI); + while (ptr) { + const struct local_constant *lconst = LIST_ENTRY(ptr, const struct local_constant, entry); + unsigned int idx = lconst->idx; + const GLint *values = (const GLint *)lconst->value; + + TRACE_(d3d_constants)("Loading local constants %i: %i, %i, %i, %i\n", idx, + values[0], values[1], values[2], values[3]); + + /* We found this uniform name in the program - go ahead and send the data */ + GL_EXTCALL(glUniform4ivARB(locations[idx], 1, values)); + checkGLcall("glUniform4ivARB"); + ptr = list_next(&This->baseShader.constantsI, ptr); + } +} + +/* Loads boolean constants (aka uniforms) into the currently set GLSL program. */ +/* GL locking is done by the caller */ +static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const struct wined3d_gl_info *gl_info, + GLhandleARB programId, const BOOL *constants, WORD constants_set) +{ + GLint tmp_loc; + unsigned int i; + char tmp_name[8]; + const char *prefix; + struct list* ptr; + + switch (This->baseShader.reg_maps.shader_version.type) + { + case WINED3D_SHADER_TYPE_VERTEX: + prefix = "VB"; + break; + + case WINED3D_SHADER_TYPE_GEOMETRY: + prefix = "GB"; + break; + + case WINED3D_SHADER_TYPE_PIXEL: + prefix = "PB"; + break; + + default: + FIXME("Unknown shader type %#x.\n", + This->baseShader.reg_maps.shader_version.type); + prefix = "UB"; + break; + } + + /* TODO: Benchmark and see if it would be beneficial to store the + * locations of the constants to avoid looking up each time */ + for (i = 0; constants_set; constants_set >>= 1, ++i) + { + if (!(constants_set & 1)) continue; + + TRACE_(d3d_constants)("Loading constants %i: %i;\n", i, constants[i]); + + /* TODO: Benchmark and see if it would be beneficial to store the + * locations of the constants to avoid looking up each time */ + snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i); + tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name)); + if (tmp_loc != -1) + { + /* We found this uniform name in the program - go ahead and send the data */ + GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, &constants[i])); + checkGLcall("glUniform1ivARB"); + } + } + + /* Load immediate constants */ + ptr = list_head(&This->baseShader.constantsB); + while (ptr) { + const struct local_constant *lconst = LIST_ENTRY(ptr, const struct local_constant, entry); + unsigned int idx = lconst->idx; + const GLint *values = (const GLint *)lconst->value; + + TRACE_(d3d_constants)("Loading local constants %i: %i\n", idx, values[0]); + + snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx); + tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name)); + if (tmp_loc != -1) { + /* We found this uniform name in the program - go ahead and send the data */ + GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, values)); + checkGLcall("glUniform1ivARB"); + } + ptr = list_next(&This->baseShader.constantsB, ptr); + } +} + +static void reset_program_constant_version(struct wine_rb_entry *entry, void *context) +{ + WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0; +} + +static const struct ps_np2fixup_info * get_fixup_info(const IWineD3DPixelShaderImpl *shader, UINT inp2fixup_info) +{ + struct glsl_pshader_private *shader_data = shader->baseShader.backend_data; + + if (inp2fixup_info == WINEFIXUPINFO_NOINDEX) + return NULL; + + if (!shader->baseShader.backend_data) + { + ERR("no backend data\n"); + return NULL; + } + shader_data = shader->baseShader.backend_data; + + if (inp2fixup_info >= shader_data->num_gl_shaders) + { + ERR("invalid index\n"); + return NULL; + } + + return &shader_data->gl_shaders[inp2fixup_info].np2fixup; +} + +/** + * Loads the texture dimensions for NP2 fixup into the currently set GLSL program. + */ +/* GL locking is done by the caller (state handler) */ +static void shader_glsl_load_np2fixup_constants( + IWineD3DDevice* device, + char usePixelShader, + char useVertexShader) { + + const IWineD3DDeviceImpl* deviceImpl = (const IWineD3DDeviceImpl*) device; + const struct glsl_shader_prog_link* prog = ((struct shader_glsl_priv *)(deviceImpl->shader_priv))->glsl_program; + + if (!prog) { + /* No GLSL program set - nothing to do. */ + return; + } + + if (!usePixelShader) { + /* NP2 texcoord fixup is (currently) only done for pixelshaders. */ + return; + } + + if (prog->ps_args.np2_fixup && -1 != prog->np2Fixup_location) { + const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info; + const IWineD3DStateBlockImpl* stateBlock = (const IWineD3DStateBlockImpl*) deviceImpl->stateBlock; + UINT i; + UINT fixup = prog->ps_args.np2_fixup; + GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS]; + + const struct ps_np2fixup_info *np2Fixup_info = WINEFIXUPINFO_GET(prog); + + for (i = 0; fixup; fixup >>= 1, ++i) { + const unsigned char idx = np2Fixup_info->idx[i]; + const IWineD3DBaseTextureImpl* const tex = (const IWineD3DBaseTextureImpl*) stateBlock->textures[i]; + GLfloat* tex_dim = &np2fixup_constants[(idx >> 1) * 4]; + + if (!tex) { + FIXME("Nonexistent texture is flagged for NP2 texcoord fixup\n"); + continue; + } + + if (idx % 2) { + tex_dim[2] = tex->baseTexture.pow2Matrix[0]; tex_dim[3] = tex->baseTexture.pow2Matrix[5]; + } else { + tex_dim[0] = tex->baseTexture.pow2Matrix[0]; tex_dim[1] = tex->baseTexture.pow2Matrix[5]; + } + } + + GL_EXTCALL(glUniform4fvARB(prog->np2Fixup_location, np2Fixup_info->num_consts, np2fixup_constants)); + } +} + +/** + * Loads the app-supplied constants into the currently set GLSL program. + */ +/* GL locking is done by the caller (state handler) */ +static void shader_glsl_load_constants(const struct wined3d_context *context, + char usePixelShader, char useVertexShader) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + IWineD3DDeviceImpl *device = context_get_device(context); + IWineD3DStateBlockImpl* stateBlock = device->stateBlock; + struct shader_glsl_priv *priv = device->shader_priv; + + GLhandleARB programId; + struct glsl_shader_prog_link *prog = priv->glsl_program; + UINT constant_version; + int i; + + if (!prog) { + /* No GLSL program set - nothing to do. */ + return; + } + programId = prog->programId; + constant_version = prog->constant_version; + + if (useVertexShader) { + IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader; + + /* Load DirectX 9 float constants/uniforms for vertex shader */ + shader_glsl_load_constantsF(vshader, gl_info, stateBlock->vertexShaderConstantF, + prog->vuniformF_locations, &priv->vconst_heap, priv->stack, constant_version); + + /* Load DirectX 9 integer constants/uniforms for vertex shader */ + shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations, stateBlock->vertexShaderConstantI, + stateBlock->changed.vertexShaderConstantsI & vshader->baseShader.reg_maps.integer_constants); + + /* Load DirectX 9 boolean constants/uniforms for vertex shader */ + shader_glsl_load_constantsB(vshader, gl_info, programId, stateBlock->vertexShaderConstantB, + stateBlock->changed.vertexShaderConstantsB & vshader->baseShader.reg_maps.boolean_constants); + + /* Upload the position fixup params */ + GL_EXTCALL(glUniform4fvARB(prog->posFixup_location, 1, &device->posFixup[0])); + checkGLcall("glUniform4fvARB"); + } + + if (usePixelShader) { + + IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader; + + /* Load DirectX 9 float constants/uniforms for pixel shader */ + shader_glsl_load_constantsF(pshader, gl_info, stateBlock->pixelShaderConstantF, + prog->puniformF_locations, &priv->pconst_heap, priv->stack, constant_version); + + /* Load DirectX 9 integer constants/uniforms for pixel shader */ + shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations, stateBlock->pixelShaderConstantI, + stateBlock->changed.pixelShaderConstantsI & pshader->baseShader.reg_maps.integer_constants); + + /* Load DirectX 9 boolean constants/uniforms for pixel shader */ + shader_glsl_load_constantsB(pshader, gl_info, programId, stateBlock->pixelShaderConstantB, + stateBlock->changed.pixelShaderConstantsB & pshader->baseShader.reg_maps.boolean_constants); + + /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from. + * It can't be 0 for a valid texbem instruction. + */ + for(i = 0; i < MAX_TEXTURES; i++) { + const float *data; + + if(prog->bumpenvmat_location[i] == -1) continue; + + data = (const float *)&stateBlock->textureState[i][WINED3DTSS_BUMPENVMAT00]; + GL_EXTCALL(glUniformMatrix2fvARB(prog->bumpenvmat_location[i], 1, 0, data)); + checkGLcall("glUniformMatrix2fvARB"); + + /* texbeml needs the luminance scale and offset too. If texbeml is used, needsbumpmat + * is set too, so we can check that in the needsbumpmat check + */ + if(prog->luminancescale_location[i] != -1) { + const GLfloat *scale = (const GLfloat *)&stateBlock->textureState[i][WINED3DTSS_BUMPENVLSCALE]; + const GLfloat *offset = (const GLfloat *)&stateBlock->textureState[i][WINED3DTSS_BUMPENVLOFFSET]; + + GL_EXTCALL(glUniform1fvARB(prog->luminancescale_location[i], 1, scale)); + checkGLcall("glUniform1fvARB"); + GL_EXTCALL(glUniform1fvARB(prog->luminanceoffset_location[i], 1, offset)); + checkGLcall("glUniform1fvARB"); + } + } + + if(((IWineD3DPixelShaderImpl *) pshader)->vpos_uniform) { + float correction_params[4]; + + if (context->render_offscreen) + { + correction_params[0] = 0.0f; + correction_params[1] = 1.0f; + } else { + /* position is window relative, not viewport relative */ +#ifdef VBOX_WITH_VMSVGA + correction_params[0] = device->rtHeight; +#else + correction_params[0] = ((IWineD3DSurfaceImpl *)context->current_rt)->currentDesc.Height; +#endif + correction_params[1] = -1.0f; + } + GL_EXTCALL(glUniform4fvARB(prog->ycorrection_location, 1, correction_params)); + } + } + + if (priv->next_constant_version == UINT_MAX) + { + TRACE("Max constant version reached, resetting to 0.\n"); + wine_rb_for_each_entry(&priv->program_lookup, reset_program_constant_version, NULL); + priv->next_constant_version = 1; + } + else + { + prog->constant_version = priv->next_constant_version++; + } +} + +static inline void update_heap_entry(struct constant_heap *heap, unsigned int idx, + unsigned int heap_idx, DWORD new_version) +{ + struct constant_entry *entries = heap->entries; + unsigned int *positions = heap->positions; + unsigned int parent_idx; + + while (heap_idx > 1) + { + parent_idx = heap_idx >> 1; + + if (new_version <= entries[parent_idx].version) break; + + entries[heap_idx] = entries[parent_idx]; + positions[entries[parent_idx].idx] = heap_idx; + heap_idx = parent_idx; + } + + entries[heap_idx].version = new_version; + entries[heap_idx].idx = idx; + positions[idx] = heap_idx; +} + +static void shader_glsl_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_glsl_priv *priv = This->shader_priv; + struct constant_heap *heap = &priv->vconst_heap; + UINT i; + + for (i = start; i < count + start; ++i) + { + if (!This->stateBlock->changed.vertexShaderConstantsF[i]) + update_heap_entry(heap, i, heap->size++, priv->next_constant_version); + else + update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version); + } +} + +static void shader_glsl_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_glsl_priv *priv = This->shader_priv; + struct constant_heap *heap = &priv->pconst_heap; + UINT i; + + for (i = start; i < count + start; ++i) + { + if (!This->stateBlock->changed.pixelShaderConstantsF[i]) + update_heap_entry(heap, i, heap->size++, priv->next_constant_version); + else + update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version); + } +} + +static unsigned int vec4_varyings(DWORD shader_major, const struct wined3d_gl_info *gl_info) +{ + unsigned int ret = gl_info->limits.glsl_varyings / 4; + /* 4.0 shaders do not write clip coords because d3d10 does not support user clipplanes */ + if(shader_major > 3) return ret; + + /* 3.0 shaders may need an extra varying for the clip coord on some cards(mostly dx10 ones) */ + if (gl_info->quirks & WINED3D_QUIRK_GLSL_CLIP_VARYING) ret -= 1; + return ret; +} + +/** Generate the variable & register declarations for the GLSL output target */ +static void shader_generate_glsl_declarations(const struct wined3d_context *context, + struct wined3d_shader_buffer *buffer, IWineD3DBaseShader *iface, + const shader_reg_maps *reg_maps, struct shader_glsl_ctx_priv *ctx_priv) +{ + IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; + const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int i, extra_constants_needed = 0; + const local_constant *lconst; + DWORD map; + + /* There are some minor differences between pixel and vertex shaders */ + char pshader = shader_is_pshader_version(reg_maps->shader_version.type); + char prefix = pshader ? 'P' : 'V'; + + /* Prototype the subroutines */ + for (i = 0, map = reg_maps->labels; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "void subroutine%u();\n", i); + } + +#ifdef VBOX_WITH_VMSVGA + /* Declare texture samplers before the constants in order to workaround a NVidia driver quirk. */ + for (i = 0; i < This->baseShader.limits.sampler; i++) { + if (reg_maps->sampler_type[i]) + { + switch (reg_maps->sampler_type[i]) + { + case WINED3DSTT_1D: + shader_addline(buffer, "uniform sampler1D %csampler%u;\n", prefix, i); + break; + case WINED3DSTT_2D: + if(device->stateBlock->textures[i] && + IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[i]) == GL_TEXTURE_RECTANGLE_ARB) { + shader_addline(buffer, "uniform sampler2DRect %csampler%u;\n", prefix, i); + } else { + shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i); + } + break; + case WINED3DSTT_CUBE: + shader_addline(buffer, "uniform samplerCube %csampler%u;\n", prefix, i); + break; + case WINED3DSTT_VOLUME: + shader_addline(buffer, "uniform sampler3D %csampler%u;\n", prefix, i); + break; + default: + shader_addline(buffer, "uniform unsupported_sampler %csampler%u;\n", prefix, i); + FIXME("Unrecognized sampler type: %#x\n", reg_maps->sampler_type[i]); + break; + } + } + } +#endif + + /* Declare the constants (aka uniforms) */ + if (This->baseShader.limits.constant_float > 0) { + unsigned max_constantsF; + /* Unless the shader uses indirect addressing, always declare the maximum array size and ignore that we need some + * uniforms privately. E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup and immediate values, still + * declare VC[256]. If the shader needs more uniforms than we have it won't work in any case. If it uses less, the + * compiler will figure out which uniforms are really used and strip them out. This allows a shader to use c255 on + * a dx9 card, as long as it doesn't also use all the other constants. + * + * If the shader uses indirect addressing the compiler must assume that all declared uniforms are used. In this case, + * declare only the amount that we're assured to have. + * + * Thus we run into problems in these two cases: + * 1) The shader really uses more uniforms than supported + * 2) The shader uses indirect addressing, less constants than supported, but uses a constant index > #supported consts + */ + if (pshader) + { + /* No indirect addressing here. */ + max_constantsF = gl_info->limits.glsl_ps_float_constants; + } + else + { +#ifndef VBOX_WITH_VMSVGA + if(This->baseShader.reg_maps.usesrelconstF) { +#else + /* If GL supports only 256 constants (seen on macOS drivers for compatibility profile, which we use), + * then ignore the need for potential uniforms and always declare VC[256]. + * This allows to compile Windows 10 shader which use hardcoded constants at 250+ index range. + * Fixes drawing problems on Windows 10 desktop. + * + * This hack is normally active only on macOS, because Windows and Linux OpenGL drivers + * have a more usable limit for GL compatibility context (1024+). + */ + if (This->baseShader.reg_maps.usesrelconstF && gl_info->limits.glsl_vs_float_constants > 256) { +#endif + /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix). + * Subtract another uniform for immediate values, which have to be loaded via uniform by the driver as well. + * The shader code only uses 0.5, 2.0, 1.0, 128 and -128 in vertex shader code, so one vec4 should be enough + * (Unfortunately the Nvidia driver doesn't store 128 and -128 in one float). + * + * Writing gl_ClipVertex requires one uniform for each clipplane as well. + */ +#ifdef VBOX_WITH_WDDM + if (gl_info->limits.glsl_vs_float_constants == 256) + { + DWORD dwVersion = GetVersion(); + DWORD dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion))); + DWORD dwMinor = (DWORD)(HIBYTE(LOWORD(dwVersion))); + /* tmp workaround Win8 Aero requirement for 256 */ + if (dwMajor > 6 || dwMinor > 1) + { + /* tmp work-around to make Internet Explorer in win8 work with GPU supporting only with 256 shader uniform vars + * @todo: make it more robust */ + max_constantsF = gl_info->limits.glsl_vs_float_constants - 1; + } + else + max_constantsF = gl_info->limits.glsl_vs_float_constants - 3; + } + else +#endif + { + max_constantsF = gl_info->limits.glsl_vs_float_constants - 3; + } + + if(ctx_priv->cur_vs_args->clip_enabled) + { + max_constantsF -= gl_info->limits.clipplanes; + } + max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants); + /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly, + * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but + * for now take this into account when calculating the number of available constants + */ + max_constantsF -= count_bits(This->baseShader.reg_maps.boolean_constants); + /* Set by driver quirks in directx.c */ + max_constantsF -= gl_info->reserved_glsl_constants; + } + else + { + max_constantsF = gl_info->limits.glsl_vs_float_constants; + } + } + max_constantsF = min(This->baseShader.limits.constant_float, max_constantsF); + shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, max_constantsF); + } + + /* Always declare the full set of constants, the compiler can remove the unused ones because d3d doesn't(yet) + * support indirect int and bool constant addressing. This avoids problems if the app uses e.g. i0 and i9. + */ + if (This->baseShader.limits.constant_int > 0 && This->baseShader.reg_maps.integer_constants) + shader_addline(buffer, "uniform ivec4 %cI[%u];\n", prefix, This->baseShader.limits.constant_int); + + if (This->baseShader.limits.constant_bool > 0 && This->baseShader.reg_maps.boolean_constants) + shader_addline(buffer, "uniform bool %cB[%u];\n", prefix, This->baseShader.limits.constant_bool); + + if(!pshader) { + shader_addline(buffer, "uniform vec4 posFixup;\n"); + /* Predeclaration; This function is added at link time based on the pixel shader. + * VS 3.0 shaders have an array OUT[] the shader writes to, earlier versions don't have + * that. We know the input to the reorder function at vertex shader compile time, so + * we can deal with that. The reorder function for a 1.x and 2.x vertex shader can just + * read gl_FrontColor. The output depends on the pixel shader. The reorder function for a + * 1.x and 2.x pshader or for fixed function will write gl_FrontColor, and for a 3.0 shader + * it will write to the varying array. Here we depend on the shader optimizer on sorting that + * out. The nvidia driver only does that if the parameter is inout instead of out, hence the + * inout. + */ + if (reg_maps->shader_version.major >= 3) + { + shader_addline(buffer, "void order_ps_input(in vec4[%u]);\n", MAX_REG_OUTPUT); + } else { + shader_addline(buffer, "void order_ps_input();\n"); + } + } else { + for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i) + { + if (!(map & 1)) continue; + + shader_addline(buffer, "uniform mat2 bumpenvmat%d;\n", i); + + if (reg_maps->luminanceparams & (1 << i)) + { + shader_addline(buffer, "uniform float luminancescale%d;\n", i); + shader_addline(buffer, "uniform float luminanceoffset%d;\n", i); + extra_constants_needed++; + } + + extra_constants_needed++; + } + + if (ps_args->srgb_correction) + { + shader_addline(buffer, "const vec4 srgb_const0 = vec4(%.8e, %.8e, %.8e, %.8e);\n", + srgb_pow, srgb_mul_high, srgb_sub_high, srgb_mul_low); + shader_addline(buffer, "const vec4 srgb_const1 = vec4(%.8e, 0.0, 0.0, 0.0);\n", + srgb_cmp); + } + if (reg_maps->vpos || reg_maps->usesdsy) + { + if (This->baseShader.limits.constant_float + extra_constants_needed + + 1 < gl_info->limits.glsl_ps_float_constants) + { + shader_addline(buffer, "uniform vec4 ycorrection;\n"); + ((IWineD3DPixelShaderImpl *) This)->vpos_uniform = 1; + extra_constants_needed++; + } else { + /* This happens because we do not have proper tracking of the constant registers that are + * actually used, only the max limit of the shader version + */ + FIXME("Cannot find a free uniform for vpos correction params\n"); + AssertFailed(); + shader_addline(buffer, "const vec4 ycorrection = vec4(%f, %f, 0.0, 0.0);\n", + context->render_offscreen ? 0.0f : ((IWineD3DSurfaceImpl *)device->render_targets[0])->currentDesc.Height, + context->render_offscreen ? 1.0f : -1.0f); + } + shader_addline(buffer, "vec4 vpos;\n"); + } + } + +#ifdef VBOX_WITH_VMSVGA + /* Declare texture samplers before the constants in order to workaround a NVidia driver quirk. */ +#else + /* Declare texture samplers */ + for (i = 0; i < This->baseShader.limits.sampler; i++) { + if (reg_maps->sampler_type[i]) + { + switch (reg_maps->sampler_type[i]) + { + case WINED3DSTT_1D: + shader_addline(buffer, "uniform sampler1D %csampler%u;\n", prefix, i); + break; + case WINED3DSTT_2D: + if(device->stateBlock->textures[i] && + IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[i]) == GL_TEXTURE_RECTANGLE_ARB) { + shader_addline(buffer, "uniform sampler2DRect %csampler%u;\n", prefix, i); + } else { + shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i); + } + break; + case WINED3DSTT_CUBE: + shader_addline(buffer, "uniform samplerCube %csampler%u;\n", prefix, i); + break; + case WINED3DSTT_VOLUME: + shader_addline(buffer, "uniform sampler3D %csampler%u;\n", prefix, i); + break; + default: + shader_addline(buffer, "uniform unsupported_sampler %csampler%u;\n", prefix, i); + FIXME("Unrecognized sampler type: %#x\n", reg_maps->sampler_type[i]); + break; + } + } + } +#endif + + /* Declare uniforms for NP2 texcoord fixup: + * This is NOT done inside the loop that declares the texture samplers since the NP2 fixup code + * is currently only used for the GeforceFX series and when forcing the ARB_npot extension off. + * Modern cards just skip the code anyway, so put it inside a separate loop. */ + if (pshader && ps_args->np2_fixup) { + + struct ps_np2fixup_info* const fixup = ctx_priv->cur_np2fixup_info; + UINT cur = 0; + + /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height] + * while D3D has them in the (normalized) [0,1]x[0,1] range. + * samplerNP2Fixup stores texture dimensions and is updated through + * shader_glsl_load_np2fixup_constants when the sampler changes. */ + + for (i = 0; i < This->baseShader.limits.sampler; ++i) { + if (reg_maps->sampler_type[i]) { + if (!(ps_args->np2_fixup & (1 << i))) continue; + + if (WINED3DSTT_2D != reg_maps->sampler_type[i]) { + FIXME("Non-2D texture is flagged for NP2 texcoord fixup.\n"); + continue; + } + + fixup->idx[i] = cur++; + } + } + + fixup->num_consts = (cur + 1) >> 1; + shader_addline(buffer, "uniform vec4 %csamplerNP2Fixup[%u];\n", prefix, fixup->num_consts); + } + + /* Declare address variables */ + for (i = 0, map = reg_maps->address; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i); + } + + /* Declare texture coordinate temporaries and initialize them */ + for (i = 0, map = reg_maps->texcoord; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "vec4 T%u = gl_TexCoord[%u];\n", i, i); + } + + /* Declare input register varyings. Only pixel shader, vertex shaders have that declared in the + * helper function shader that is linked in at link time + */ + if (pshader && reg_maps->shader_version.major >= 3) + { + if (use_vs(device->stateBlock)) + { + shader_addline(buffer, "varying vec4 IN[%u];\n", vec4_varyings(reg_maps->shader_version.major, gl_info)); + } else { + /* TODO: Write a replacement shader for the fixed function vertex pipeline, so this isn't needed. + * For fixed function vertex processing + 3.0 pixel shader we need a separate function in the + * pixel shader that reads the fixed function color into the packed input registers. + */ + shader_addline(buffer, "vec4 IN[%u];\n", vec4_varyings(reg_maps->shader_version.major, gl_info)); + } + } + + /* Declare output register temporaries */ + if(This->baseShader.limits.packed_output) { + shader_addline(buffer, "vec4 OUT[%u];\n", This->baseShader.limits.packed_output); + } + + /* Declare temporary variables */ + for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "vec4 R%u;\n", i); + } + + /* Declare attributes */ + if (reg_maps->shader_version.type == WINED3D_SHADER_TYPE_VERTEX) + { + for (i = 0, map = reg_maps->input_registers; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "attribute vec4 attrib%i;\n", i); + } + } + + /* Declare loop registers aLx */ + for (i = 0; i < reg_maps->loop_depth; i++) { + shader_addline(buffer, "int aL%u;\n", i); + shader_addline(buffer, "int tmpInt%u;\n", i); + } + + /* Temporary variables for matrix operations */ + shader_addline(buffer, "vec4 tmp0;\n"); + shader_addline(buffer, "vec4 tmp1;\n"); +#ifdef VBOX_WITH_VMSVGA + shader_addline(buffer, "bool p0[4];\n"); +#endif + + /* Local constants use a different name so they can be loaded once at shader link time + * They can't be hardcoded into the shader text via LC = {x, y, z, w}; because the + * float -> string conversion can cause precision loss. + */ + if(!This->baseShader.load_local_constsF) { + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + shader_addline(buffer, "uniform vec4 %cLC%u;\n", prefix, lconst->idx); + } + } + + shader_addline(buffer, "const float FLT_MAX = 1e38;\n"); + + /* Start the main program */ + shader_addline(buffer, "void main() {\n"); + if(pshader && reg_maps->vpos) { + /* DirectX apps expect integer values, while OpenGL drivers add approximately 0.5. This causes + * off-by-one problems as spotted by the vPos d3d9 visual test. Unfortunately the ATI cards do + * not add exactly 0.5, but rather something like 0.49999999 or 0.50000001, which still causes + * precision troubles when we just substract 0.5. + * + * To deal with that just floor() the position. This will eliminate the fraction on all cards. + * + * TODO: Test how that behaves with multisampling once we can enable multisampling in winex11. + * + * An advantage of floor is that it works even if the driver doesn't add 1/2. It is somewhat + * questionable if 1.5, 2.5, ... are the proper values to return in gl_FragCoord, even though + * coordinates specify the pixel centers instead of the pixel corners. This code will behave + * correctly on drivers that returns integer values. + */ + shader_addline(buffer, "vpos = floor(vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1));\n"); + } +} + +/***************************************************************************** + * Functions to generate GLSL strings from DirectX Shader bytecode begin here. + * + * For more information, see http://wiki.winehq.org/DirectX-Shaders + ****************************************************************************/ + +/* Prototypes */ +static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins, + const struct wined3d_shader_src_param *wined3d_src, DWORD mask, glsl_src_param_t *glsl_src); + +/** Used for opcode modifiers - They multiply the result by the specified amount */ +static const char * const shift_glsl_tab[] = { + "", /* 0 (none) */ + "2.0 * ", /* 1 (x2) */ + "4.0 * ", /* 2 (x4) */ + "8.0 * ", /* 3 (x8) */ + "16.0 * ", /* 4 (x16) */ + "32.0 * ", /* 5 (x32) */ + "", /* 6 (x64) */ + "", /* 7 (x128) */ + "", /* 8 (d256) */ + "", /* 9 (d128) */ + "", /* 10 (d64) */ + "", /* 11 (d32) */ + "0.0625 * ", /* 12 (d16) */ + "0.125 * ", /* 13 (d8) */ + "0.25 * ", /* 14 (d4) */ + "0.5 * " /* 15 (d2) */ +}; + +/* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */ +static void shader_glsl_gen_modifier(DWORD src_modifier, const char *in_reg, const char *in_regswizzle, char *out_str) +{ + out_str[0] = 0; + + switch (src_modifier) + { + case WINED3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */ + case WINED3DSPSM_DW: + case WINED3DSPSM_NONE: + sprintf(out_str, "%s%s", in_reg, in_regswizzle); + break; + case WINED3DSPSM_NEG: + sprintf(out_str, "-%s%s", in_reg, in_regswizzle); + break; + case WINED3DSPSM_NOT: + sprintf(out_str, "!%s%s", in_reg, in_regswizzle); + break; + case WINED3DSPSM_BIAS: + sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle); + break; + case WINED3DSPSM_BIASNEG: + sprintf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle); + break; + case WINED3DSPSM_SIGN: + sprintf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle); + break; + case WINED3DSPSM_SIGNNEG: + sprintf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle); + break; + case WINED3DSPSM_COMP: + sprintf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle); + break; + case WINED3DSPSM_X2: + sprintf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle); + break; + case WINED3DSPSM_X2NEG: + sprintf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle); + break; + case WINED3DSPSM_ABS: + sprintf(out_str, "abs(%s%s)", in_reg, in_regswizzle); + break; + case WINED3DSPSM_ABSNEG: + sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle); + break; + default: + FIXME("Unhandled modifier %u\n", src_modifier); + sprintf(out_str, "%s%s", in_reg, in_regswizzle); + } +} + +/** Writes the GLSL variable name that corresponds to the register that the + * DX opcode parameter is trying to access */ +static void shader_glsl_get_register_name(const struct wined3d_shader_register *reg, + char *register_name, BOOL *is_color, const struct wined3d_shader_instruction *ins) +{ + /* oPos, oFog and oPts in D3D */ + static const char * const hwrastout_reg_names[] = { "gl_Position", "gl_FogFragCoord", "gl_PointSize" }; + + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + char pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type); + + *is_color = FALSE; + + switch (reg->type) + { + case WINED3DSPR_TEMP: + sprintf(register_name, "R%u", reg->idx); + break; + + case WINED3DSPR_INPUT: + /* vertex shaders */ + if (!pshader) + { + struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; + if (priv->cur_vs_args->swizzle_map & (1 << reg->idx)) *is_color = TRUE; + sprintf(register_name, "attrib%u", reg->idx); + break; + } + + /* pixel shaders >= 3.0 */ + if (This->baseShader.reg_maps.shader_version.major >= 3) + { + DWORD idx = ((IWineD3DPixelShaderImpl *)This)->input_reg_map[reg->idx]; + unsigned int in_count = vec4_varyings(This->baseShader.reg_maps.shader_version.major, gl_info); + + if (reg->rel_addr) + { + glsl_src_param_t rel_param; + + shader_glsl_add_src_param(ins, reg->rel_addr, WINED3DSP_WRITEMASK_0, &rel_param); + + /* Removing a + 0 would be an obvious optimization, but macos doesn't see the NOP + * operation there */ + if (idx) + { + if (((IWineD3DPixelShaderImpl *)This)->declared_in_count > in_count) + { + sprintf(register_name, + "((%s + %u) > %d ? (%s + %u) > %d ? gl_SecondaryColor : gl_Color : IN[%s + %u])", + rel_param.param_str, idx, in_count - 1, rel_param.param_str, idx, in_count, + rel_param.param_str, idx); + } + else + { + sprintf(register_name, "IN[%s + %u]", rel_param.param_str, idx); + } + } + else + { + if (((IWineD3DPixelShaderImpl *)This)->declared_in_count > in_count) + { + sprintf(register_name, "((%s) > %d ? (%s) > %d ? gl_SecondaryColor : gl_Color : IN[%s])", + rel_param.param_str, in_count - 1, rel_param.param_str, in_count, + rel_param.param_str); + } + else + { + sprintf(register_name, "IN[%s]", rel_param.param_str); + } + } + } + else + { + if (idx == in_count) sprintf(register_name, "gl_Color"); + else if (idx == in_count + 1) sprintf(register_name, "gl_SecondaryColor"); + else sprintf(register_name, "IN[%u]", idx); + } + } + else + { + if (reg->idx == 0) strcpy(register_name, "gl_Color"); + else strcpy(register_name, "gl_SecondaryColor"); + break; + } + break; + + case WINED3DSPR_CONST: + { + const char prefix = pshader ? 'P' : 'V'; + + /* Relative addressing */ + if (reg->rel_addr) + { + glsl_src_param_t rel_param; + shader_glsl_add_src_param(ins, reg->rel_addr, WINED3DSP_WRITEMASK_0, &rel_param); + if (reg->idx) sprintf(register_name, "%cC[%s + %u]", prefix, rel_param.param_str, reg->idx); + else sprintf(register_name, "%cC[%s]", prefix, rel_param.param_str); + } + else + { + if (shader_constant_is_local(This, reg->idx)) + sprintf(register_name, "%cLC%u", prefix, reg->idx); + else + sprintf(register_name, "%cC[%u]", prefix, reg->idx); + } + } + break; + + case WINED3DSPR_CONSTINT: + if (pshader) sprintf(register_name, "PI[%u]", reg->idx); + else sprintf(register_name, "VI[%u]", reg->idx); + break; + + case WINED3DSPR_CONSTBOOL: + if (pshader) sprintf(register_name, "PB[%u]", reg->idx); + else sprintf(register_name, "VB[%u]", reg->idx); + break; + + case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */ + if (pshader) sprintf(register_name, "T%u", reg->idx); + else sprintf(register_name, "A%u", reg->idx); + break; + + case WINED3DSPR_LOOP: + sprintf(register_name, "aL%u", This->baseShader.cur_loop_regno - 1); + break; + + case WINED3DSPR_SAMPLER: + if (pshader) sprintf(register_name, "Psampler%u", reg->idx); + else sprintf(register_name, "Vsampler%u", reg->idx); + break; + + case WINED3DSPR_COLOROUT: + if (reg->idx >= gl_info->limits.buffers) + WARN("Write to render target %u, only %d supported.\n", reg->idx, gl_info->limits.buffers); + + sprintf(register_name, "gl_FragData[%u]", reg->idx); + break; + + case WINED3DSPR_RASTOUT: + if (reg->idx < RT_ELEMENTS(hwrastout_reg_names)) sprintf(register_name, "%s", hwrastout_reg_names[reg->idx]); + else sprintf(register_name, "%s", hwrastout_reg_names[0]); + break; + + case WINED3DSPR_DEPTHOUT: + sprintf(register_name, "gl_FragDepth"); + break; + + case WINED3DSPR_ATTROUT: + if (reg->idx == 0) sprintf(register_name, "gl_FrontColor"); + else sprintf(register_name, "gl_FrontSecondaryColor"); + break; + + case WINED3DSPR_TEXCRDOUT: + /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */ + if (This->baseShader.reg_maps.shader_version.major >= 3) sprintf(register_name, "OUT[%u]", reg->idx); + else sprintf(register_name, "gl_TexCoord[%u]", reg->idx); + break; + + case WINED3DSPR_MISCTYPE: + if (reg->idx == 0) + { + /* vPos */ + sprintf(register_name, "vpos"); + } + else if (reg->idx == 1) + { + /* Note that gl_FrontFacing is a bool, while vFace is + * a float for which the sign determines front/back */ + sprintf(register_name, "(gl_FrontFacing ? 1.0 : -1.0)"); + } + else + { + FIXME("Unhandled misctype register %d\n", reg->idx); + sprintf(register_name, "unrecognized_register"); + } + break; + + case WINED3DSPR_IMMCONST: + switch (reg->immconst_type) + { + case WINED3D_IMMCONST_FLOAT: + sprintf(register_name, "%.8e", *(const float *)reg->immconst_data); + break; + + case WINED3D_IMMCONST_FLOAT4: + sprintf(register_name, "vec4(%.8e, %.8e, %.8e, %.8e)", + *(const float *)®->immconst_data[0], *(const float *)®->immconst_data[1], + *(const float *)®->immconst_data[2], *(const float *)®->immconst_data[3]); + break; + + default: + FIXME("Unhandled immconst type %#x\n", reg->immconst_type); + sprintf(register_name, "", reg->immconst_type); + } + break; + +#ifdef VBOX_WITH_VMSVGA + case WINED3DSPR_PREDICATE: + sprintf(register_name, "p0"); + break; +#endif + + default: + FIXME("Unhandled register name Type(%d)\n", reg->type); + sprintf(register_name, "unrecognized_register"); + break; + } +} + +static void shader_glsl_write_mask_to_str(DWORD write_mask, char *str) +{ + *str++ = '.'; + if (write_mask & WINED3DSP_WRITEMASK_0) *str++ = 'x'; + if (write_mask & WINED3DSP_WRITEMASK_1) *str++ = 'y'; + if (write_mask & WINED3DSP_WRITEMASK_2) *str++ = 'z'; + if (write_mask & WINED3DSP_WRITEMASK_3) *str++ = 'w'; + *str = '\0'; +} + +/* Get the GLSL write mask for the destination register */ +static DWORD shader_glsl_get_write_mask(const struct wined3d_shader_dst_param *param, char *write_mask) +{ + DWORD mask = param->write_mask; + + if (shader_is_scalar(¶m->reg)) + { + mask = WINED3DSP_WRITEMASK_0; + *write_mask = '\0'; + } + else + { +#ifdef VBOX_WITH_VMSVGA + if (param->reg.type == WINED3DSPR_PREDICATE) + { + *write_mask++ = '['; + if (mask & WINED3DSP_WRITEMASK_0) *write_mask++ = '0'; + else + if (mask & WINED3DSP_WRITEMASK_1) *write_mask++ = '1'; + else + if (mask & WINED3DSP_WRITEMASK_2) *write_mask++ = '2'; + else + if (mask & WINED3DSP_WRITEMASK_3) *write_mask++ = '3'; + *write_mask++ = ']'; + *write_mask = '\0'; + } + else +#endif + shader_glsl_write_mask_to_str(mask, write_mask); + } + + return mask; +} + +static unsigned int shader_glsl_get_write_mask_size(DWORD write_mask) { + unsigned int size = 0; + + if (write_mask & WINED3DSP_WRITEMASK_0) ++size; + if (write_mask & WINED3DSP_WRITEMASK_1) ++size; + if (write_mask & WINED3DSP_WRITEMASK_2) ++size; + if (write_mask & WINED3DSP_WRITEMASK_3) ++size; + + return size; +} + +static void shader_glsl_swizzle_to_str(const DWORD swizzle, BOOL fixup, DWORD mask, char *str) +{ + /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra", + * but addressed as "rgba". To fix this we need to swap the register's x + * and z components. */ + const char *swizzle_chars = fixup ? "zyxw" : "xyzw"; + + *str++ = '.'; + /* swizzle bits fields: wwzzyyxx */ + if (mask & WINED3DSP_WRITEMASK_0) *str++ = swizzle_chars[swizzle & 0x03]; + if (mask & WINED3DSP_WRITEMASK_1) *str++ = swizzle_chars[(swizzle >> 2) & 0x03]; + if (mask & WINED3DSP_WRITEMASK_2) *str++ = swizzle_chars[(swizzle >> 4) & 0x03]; + if (mask & WINED3DSP_WRITEMASK_3) *str++ = swizzle_chars[(swizzle >> 6) & 0x03]; + *str = '\0'; +} + +static void shader_glsl_get_swizzle(const struct wined3d_shader_src_param *param, + BOOL fixup, DWORD mask, char *swizzle_str) +{ + if (shader_is_scalar(¶m->reg)) + *swizzle_str = '\0'; + else + shader_glsl_swizzle_to_str(param->swizzle, fixup, mask, swizzle_str); +} + +/* From a given parameter token, generate the corresponding GLSL string. + * Also, return the actual register name and swizzle in case the + * caller needs this information as well. */ +static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins, + const struct wined3d_shader_src_param *wined3d_src, DWORD mask, glsl_src_param_t *glsl_src) +{ + BOOL is_color = FALSE; + char swizzle_str[6]; + + glsl_src->reg_name[0] = '\0'; + glsl_src->param_str[0] = '\0'; + swizzle_str[0] = '\0'; + + shader_glsl_get_register_name(&wined3d_src->reg, glsl_src->reg_name, &is_color, ins); + shader_glsl_get_swizzle(wined3d_src, is_color, mask, swizzle_str); + shader_glsl_gen_modifier(wined3d_src->modifiers, glsl_src->reg_name, swizzle_str, glsl_src->param_str); +} + +/* From a given parameter token, generate the corresponding GLSL string. + * Also, return the actual register name and swizzle in case the + * caller needs this information as well. */ +static DWORD shader_glsl_add_dst_param(const struct wined3d_shader_instruction *ins, + const struct wined3d_shader_dst_param *wined3d_dst, glsl_dst_param_t *glsl_dst) +{ + BOOL is_color = FALSE; + + glsl_dst->mask_str[0] = '\0'; + glsl_dst->reg_name[0] = '\0'; + + shader_glsl_get_register_name(&wined3d_dst->reg, glsl_dst->reg_name, &is_color, ins); + return shader_glsl_get_write_mask(wined3d_dst, glsl_dst->mask_str); +} + +/* Append the destination part of the instruction to the buffer, return the effective write mask */ +static DWORD shader_glsl_append_dst_ext(struct wined3d_shader_buffer *buffer, + const struct wined3d_shader_instruction *ins, const struct wined3d_shader_dst_param *dst) +{ + glsl_dst_param_t glsl_dst; + DWORD mask; + + mask = shader_glsl_add_dst_param(ins, dst, &glsl_dst); + if (mask) shader_addline(buffer, "%s%s = %s(", glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); + + return mask; +} + +/* Append the destination part of the instruction to the buffer, return the effective write mask */ +static DWORD shader_glsl_append_dst(struct wined3d_shader_buffer *buffer, const struct wined3d_shader_instruction *ins) +{ + return shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0]); +} + +/** Process GLSL instruction modifiers */ +static void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) +{ + glsl_dst_param_t dst_param; + DWORD modifiers; + + if (!ins->dst_count) return; + + modifiers = ins->dst[0].modifiers; + if (!modifiers) return; + + shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); + + if (modifiers & WINED3DSPDM_SATURATE) + { + /* _SAT means to clamp the value of the register to between 0 and 1 */ + shader_addline(ins->ctx->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name, + dst_param.mask_str, dst_param.reg_name, dst_param.mask_str); + } + + if (modifiers & WINED3DSPDM_MSAMPCENTROID) + { + FIXME("_centroid modifier not handled\n"); + } + + if (modifiers & WINED3DSPDM_PARTIALPRECISION) + { + /* MSDN says this modifier can be safely ignored, so that's what we'll do. */ + } +} + +static inline const char *shader_get_comp_op(DWORD op) +{ + switch (op) { + case COMPARISON_GT: return ">"; + case COMPARISON_EQ: return "=="; + case COMPARISON_GE: return ">="; + case COMPARISON_LT: return "<"; + case COMPARISON_NE: return "!="; + case COMPARISON_LE: return "<="; + default: + FIXME("Unrecognized comparison value: %u\n", op); + return "(\?\?)"; + } +} + +static void shader_glsl_get_sample_function(const struct wined3d_gl_info *gl_info, + DWORD sampler_type, DWORD flags, glsl_sample_function_t *sample_function) +{ + BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED; + BOOL texrect = flags & WINED3D_GLSL_SAMPLE_RECT; + BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD; + BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD; + + /* Note that there's no such thing as a projected cube texture. */ + switch(sampler_type) { + case WINED3DSTT_1D: + if(lod) { + sample_function->name = projected ? "texture1DProjLod" : "texture1DLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "texture1DProjGrad" : "texture1DGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "texture1DProjGradARB" : "texture1DGradARB"; + else + { + FIXME("Unsupported 1D grad function.\n"); + sample_function->name = "unsupported1DGrad"; + } + } + else + { + sample_function->name = projected ? "texture1DProj" : "texture1D"; + } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0; + break; + case WINED3DSTT_2D: + if(texrect) { + if(lod) { + sample_function->name = projected ? "texture2DRectProjLod" : "texture2DRectLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "texture2DRectProjGrad" : "texture2DRectGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "texture2DRectProjGradARB" : "texture2DRectGradARB"; + else + { + FIXME("Unsupported RECT grad function.\n"); + sample_function->name = "unsupported2DRectGrad"; + } + } + else + { + sample_function->name = projected ? "texture2DRectProj" : "texture2DRect"; + } + } else { + if(lod) { + sample_function->name = projected ? "texture2DProjLod" : "texture2DLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "texture2DProjGrad" : "texture2DGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "texture2DProjGradARB" : "texture2DGradARB"; + else + { + FIXME("Unsupported 2D grad function.\n"); + sample_function->name = "unsupported2DGrad"; + } + } + else + { + sample_function->name = projected ? "texture2DProj" : "texture2D"; + } + } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1; + break; + case WINED3DSTT_CUBE: + if(lod) { + sample_function->name = "textureCubeLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = "textureCubeGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = "textureCubeGradARB"; + else + { + FIXME("Unsupported Cube grad function.\n"); + sample_function->name = "unsupportedCubeGrad"; + } + } + else + { + sample_function->name = "textureCube"; + } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + break; + case WINED3DSTT_VOLUME: + if(lod) { + sample_function->name = projected ? "texture3DProjLod" : "texture3DLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "texture3DProjGrad" : "texture3DGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "texture3DProjGradARB" : "texture3DGradARB"; + else + { + FIXME("Unsupported 3D grad function.\n"); + sample_function->name = "unsupported3DGrad"; + } + } + else + { + sample_function->name = projected ? "texture3DProj" : "texture3D"; + } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + break; + default: + sample_function->name = ""; + sample_function->coord_mask = 0; + FIXME("Unrecognized sampler type: %#x;\n", sampler_type); + break; + } +} + +static void shader_glsl_append_fixup_arg(char *arguments, const char *reg_name, + BOOL sign_fixup, enum fixup_channel_source channel_source) +{ + switch(channel_source) + { + case CHANNEL_SOURCE_ZERO: + strcat(arguments, "0.0"); + break; + + case CHANNEL_SOURCE_ONE: + strcat(arguments, "1.0"); + break; + + case CHANNEL_SOURCE_X: + strcat(arguments, reg_name); + strcat(arguments, ".x"); + break; + + case CHANNEL_SOURCE_Y: + strcat(arguments, reg_name); + strcat(arguments, ".y"); + break; + + case CHANNEL_SOURCE_Z: + strcat(arguments, reg_name); + strcat(arguments, ".z"); + break; + + case CHANNEL_SOURCE_W: + strcat(arguments, reg_name); + strcat(arguments, ".w"); + break; + + default: + FIXME("Unhandled channel source %#x\n", channel_source); + strcat(arguments, "undefined"); + break; + } + + if (sign_fixup) strcat(arguments, " * 2.0 - 1.0"); +} + +static void shader_glsl_color_correction(const struct wined3d_shader_instruction *ins, struct color_fixup_desc fixup) +{ + struct wined3d_shader_dst_param dst; + unsigned int mask_size, remaining; + glsl_dst_param_t dst_param; + char arguments[256]; + DWORD mask; + + mask = 0; + if (fixup.x_sign_fixup || fixup.x_source != CHANNEL_SOURCE_X) mask |= WINED3DSP_WRITEMASK_0; + if (fixup.y_sign_fixup || fixup.y_source != CHANNEL_SOURCE_Y) mask |= WINED3DSP_WRITEMASK_1; + if (fixup.z_sign_fixup || fixup.z_source != CHANNEL_SOURCE_Z) mask |= WINED3DSP_WRITEMASK_2; + if (fixup.w_sign_fixup || fixup.w_source != CHANNEL_SOURCE_W) mask |= WINED3DSP_WRITEMASK_3; + mask &= ins->dst[0].write_mask; + + if (!mask) return; /* Nothing to do */ + + if (is_complex_fixup(fixup)) + { + enum complex_fixup complex_fixup = get_complex_fixup(fixup); + FIXME("Complex fixup (%#x) not supported\n",complex_fixup); (void)complex_fixup; + return; + } + + mask_size = shader_glsl_get_write_mask_size(mask); + + dst = ins->dst[0]; + dst.write_mask = mask; + shader_glsl_add_dst_param(ins, &dst, &dst_param); + + arguments[0] = '\0'; + remaining = mask_size; + if (mask & WINED3DSP_WRITEMASK_0) + { + shader_glsl_append_fixup_arg(arguments, dst_param.reg_name, fixup.x_sign_fixup, fixup.x_source); + if (--remaining) strcat(arguments, ", "); + } + if (mask & WINED3DSP_WRITEMASK_1) + { + shader_glsl_append_fixup_arg(arguments, dst_param.reg_name, fixup.y_sign_fixup, fixup.y_source); + if (--remaining) strcat(arguments, ", "); + } + if (mask & WINED3DSP_WRITEMASK_2) + { + shader_glsl_append_fixup_arg(arguments, dst_param.reg_name, fixup.z_sign_fixup, fixup.z_source); + if (--remaining) strcat(arguments, ", "); + } + if (mask & WINED3DSP_WRITEMASK_3) + { + shader_glsl_append_fixup_arg(arguments, dst_param.reg_name, fixup.w_sign_fixup, fixup.w_source); + if (--remaining) strcat(arguments, ", "); + } + + if (mask_size > 1) + { + shader_addline(ins->ctx->buffer, "%s%s = vec%u(%s);\n", + dst_param.reg_name, dst_param.mask_str, mask_size, arguments); + } + else + { + shader_addline(ins->ctx->buffer, "%s%s = %s;\n", dst_param.reg_name, dst_param.mask_str, arguments); + } +} + +static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins, + DWORD sampler, const glsl_sample_function_t *sample_function, DWORD swizzle, + const char *dx, const char *dy, + const char *bias, const char *coord_reg_fmt, ...) +{ + const char *sampler_base; + char dst_swizzle[6]; + struct color_fixup_desc fixup; + BOOL np2_fixup = FALSE; + BOOL tmirror_tmp_reg = FALSE; + va_list args; + + shader_glsl_swizzle_to_str(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle); + + if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) + { + const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; + fixup = priv->cur_ps_args->color_fixup[sampler]; + sampler_base = "Psampler"; + + if (priv->cur_ps_args->np2_fixup & (1 << sampler)) { + if(bias) { + FIXME("Biased sampling from NP2 textures is unsupported\n"); + } else { + np2_fixup = TRUE; + } + } + + if (priv->cur_ps_args->t_mirror & (1 << sampler)) + { + if (ins->ctx->reg_maps->sampler_type[sampler]==WINED3DSTT_2D) + { + if (sample_function->coord_mask & WINED3DSP_WRITEMASK_1) + { + glsl_src_param_t coord_param; + shader_glsl_add_src_param(ins, &ins->src[0], sample_function->coord_mask, &coord_param); + + if (ins->src[0].reg.type != WINED3DSPR_INPUT) + { + shader_addline(ins->ctx->buffer, "%s.y=1.0-%s.y;\n", + coord_param.reg_name, coord_param.reg_name); + } + else + { + tmirror_tmp_reg = TRUE; + shader_addline(ins->ctx->buffer, "tmp0.xy=vec2(%s.x, 1.0-%s.y).xy;\n", + coord_param.reg_name, coord_param.reg_name); + } + } + else + { + DebugBreak(); + FIXME("Unexpected coord_mask with t_mirror\n"); + } + } + } + } else { + sampler_base = "Vsampler"; + fixup = COLOR_FIXUP_IDENTITY; /* FIXME: Vshader color fixup */ + } + + shader_glsl_append_dst(ins->ctx->buffer, ins); + + shader_addline(ins->ctx->buffer, "%s(%s%u, ", sample_function->name, sampler_base, sampler); + + if (tmirror_tmp_reg) + { + shader_addline(ins->ctx->buffer, "%s", "tmp0.xy"); + } + else + { + va_start(args, coord_reg_fmt); + shader_vaddline(ins->ctx->buffer, coord_reg_fmt, args); + va_end(args); + } + + if(bias) { + shader_addline(ins->ctx->buffer, ", %s)%s);\n", bias, dst_swizzle); + } else { + if (np2_fixup) { + const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; + const unsigned char idx = priv->cur_np2fixup_info->idx[sampler]; + + shader_addline(ins->ctx->buffer, " * PsamplerNP2Fixup[%u].%s)%s);\n", idx >> 1, + (idx % 2) ? "zw" : "xy", dst_swizzle); + } else if(dx && dy) { + shader_addline(ins->ctx->buffer, ", %s, %s)%s);\n", dx, dy, dst_swizzle); + } else { + shader_addline(ins->ctx->buffer, ")%s);\n", dst_swizzle); + } + } + + if(!is_identity_fixup(fixup)) { + shader_glsl_color_correction(ins, fixup); + } +} + +/***************************************************************************** + * Begin processing individual instruction opcodes + ****************************************************************************/ + +/* Generate GLSL arithmetic functions (dst = src1 + src2) */ +static void shader_glsl_arith(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + DWORD write_mask; + char op; + + /* Determine the GLSL operator to use based on the opcode */ + switch (ins->handler_idx) + { + case WINED3DSIH_MUL: op = '*'; break; + case WINED3DSIH_ADD: op = '+'; break; + case WINED3DSIH_SUB: op = '-'; break; + default: + op = ' '; + FIXME("Opcode %#x not yet handled in GLSL\n", ins->handler_idx); + break; + } + + write_mask = shader_glsl_append_dst(buffer, ins); + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); + shader_addline(buffer, "%s %c %s);\n", src0_param.param_str, op, src1_param.param_str); +} + +#ifdef VBOX_WITH_VMSVGA +static void shader_glsl_mov_impl(const struct wined3d_shader_instruction *ins, int p0_idx); + +/* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */ +static void shader_glsl_mov(const struct wined3d_shader_instruction *ins) +{ + if (ins->predicate) + { + int i; + DWORD dst_mask = ins->dst[0].write_mask; + struct wined3d_shader_dst_param *dst = (struct wined3d_shader_dst_param *)&ins->dst[0]; + + for (i = 0; i < 4; i++) + { + if (dst_mask & RT_BIT(i)) + { + dst->write_mask = RT_BIT(i); + + shader_glsl_mov_impl(ins, i); + } + } + dst->write_mask = dst_mask; + } + else + shader_glsl_mov_impl(ins, 0); +} + +/* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */ +static void shader_glsl_mov_impl(const struct wined3d_shader_instruction *ins, int p0_idx) + +#else +/* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */ +static void shader_glsl_mov(const struct wined3d_shader_instruction *ins) +#endif +{ + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src0_param; + DWORD write_mask; + +#ifdef VBOX_WITH_VMSVGA + if (ins->predicate) + { + shader_addline(buffer, "if (p0[%d]) {\n", p0_idx); + } +#endif + + write_mask = shader_glsl_append_dst(buffer, ins); + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); + + /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later + * shader versions WINED3DSIO_MOVA is used for this. */ + if (ins->ctx->reg_maps->shader_version.major == 1 + && !shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type) + && ins->dst[0].reg.type == WINED3DSPR_ADDR) + { + /* This is a simple floor() */ + unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); + if (mask_size > 1) { + shader_addline(buffer, "ivec%d(floor(%s)));\n", mask_size, src0_param.param_str); + } else { + shader_addline(buffer, "int(floor(%s)));\n", src0_param.param_str); + } + } + else if(ins->handler_idx == WINED3DSIH_MOVA) + { + /* We need to *round* to the nearest int here. */ + unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); + + if (gl_info->supported[EXT_GPU_SHADER4]) + { + if (mask_size > 1) + shader_addline(buffer, "ivec%d(round(%s)));\n", mask_size, src0_param.param_str); + else + shader_addline(buffer, "int(round(%s)));\n", src0_param.param_str); + } + else + { + if (mask_size > 1) + shader_addline(buffer, "ivec%d(floor(abs(%s) + vec%d(0.5)) * sign(%s)));\n", + mask_size, src0_param.param_str, mask_size, src0_param.param_str); + else + shader_addline(buffer, "int(floor(abs(%s) + 0.5) * sign(%s)));\n", + src0_param.param_str, src0_param.param_str); + } + } + else + { + shader_addline(buffer, "%s);\n", src0_param.param_str); + } +#ifdef VBOX_WITH_VMSVGA + if (ins->predicate) + { + shader_addline(buffer, "}\n"); + } +#endif +} + +/* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */ +static void shader_glsl_dot(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + DWORD dst_write_mask, src_write_mask; + unsigned int dst_size = 0; + + dst_write_mask = shader_glsl_append_dst(buffer, ins); + dst_size = shader_glsl_get_write_mask_size(dst_write_mask); + + /* dp3 works on vec3, dp4 on vec4 */ + if (ins->handler_idx == WINED3DSIH_DP4) + { + src_write_mask = WINED3DSP_WRITEMASK_ALL; + } else { + src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + } + + shader_glsl_add_src_param(ins, &ins->src[0], src_write_mask, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], src_write_mask, &src1_param); + + if (dst_size > 1) { + shader_addline(buffer, "vec%d(dot(%s, %s)));\n", dst_size, src0_param.param_str, src1_param.param_str); + } else { + shader_addline(buffer, "dot(%s, %s));\n", src0_param.param_str, src1_param.param_str); + } +} + +/* Note that this instruction has some restrictions. The destination write mask + * can't contain the w component, and the source swizzles have to be .xyzw */ +static void shader_glsl_cross(const struct wined3d_shader_instruction *ins) +{ + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + char dst_mask[6]; + + shader_glsl_get_write_mask(&ins->dst[0], dst_mask); + shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param); + shader_addline(ins->ctx->buffer, "cross(%s, %s)%s);\n", src0_param.param_str, src1_param.param_str, dst_mask); +} + +/* Process the WINED3DSIO_POW instruction in GLSL (dst = |src0|^src1) + * Src0 and src1 are scalars. Note that D3D uses the absolute of src0, while + * GLSL uses the value as-is. */ +static void shader_glsl_pow(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + DWORD dst_write_mask; + unsigned int dst_size; + + dst_write_mask = shader_glsl_append_dst(buffer, ins); + dst_size = shader_glsl_get_write_mask_size(dst_write_mask); + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); + + if (dst_size > 1) { + shader_addline(buffer, "vec%d(pow(abs(%s), %s)));\n", dst_size, src0_param.param_str, src1_param.param_str); + } else { + shader_addline(buffer, "pow(abs(%s), %s));\n", src0_param.param_str, src1_param.param_str); + } +} + +/* Process the WINED3DSIO_LOG instruction in GLSL (dst = log2(|src0|)) + * Src0 is a scalar. Note that D3D uses the absolute of src0, while + * GLSL uses the value as-is. */ +static void shader_glsl_log(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src0_param; + DWORD dst_write_mask; + unsigned int dst_size; + + dst_write_mask = shader_glsl_append_dst(buffer, ins); + dst_size = shader_glsl_get_write_mask_size(dst_write_mask); + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + + if (dst_size > 1) + { + shader_addline(buffer, "vec%d(%s == 0.0 ? -FLT_MAX : log2(abs(%s))));\n", + dst_size, src0_param.param_str, src0_param.param_str); + } + else + { + shader_addline(buffer, "%s == 0.0 ? -FLT_MAX : log2(abs(%s)));\n", + src0_param.param_str, src0_param.param_str); + } +} + +/* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */ +static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src_param; + const char *instruction; + DWORD write_mask; + unsigned i; + + /* Determine the GLSL function to use based on the opcode */ + /* TODO: Possibly make this a table for faster lookups */ + switch (ins->handler_idx) + { + case WINED3DSIH_MIN: instruction = "min"; break; + case WINED3DSIH_MAX: instruction = "max"; break; + case WINED3DSIH_ABS: instruction = "abs"; break; + case WINED3DSIH_FRC: instruction = "fract"; break; + case WINED3DSIH_EXP: instruction = "exp2"; break; + case WINED3DSIH_DSX: instruction = "dFdx"; break; + case WINED3DSIH_DSY: instruction = "ycorrection.y * dFdy"; break; + default: instruction = ""; + FIXME("Opcode %#x not yet handled in GLSL\n", ins->handler_idx); + break; + } + + write_mask = shader_glsl_append_dst(buffer, ins); + + shader_addline(buffer, "%s(", instruction); + + if (ins->src_count) + { + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); + shader_addline(buffer, "%s", src_param.param_str); + for (i = 1; i < ins->src_count; ++i) + { + shader_glsl_add_src_param(ins, &ins->src[i], write_mask, &src_param); + shader_addline(buffer, ", %s", src_param.param_str); + } + } + + shader_addline(buffer, "));\n"); +} + +static void shader_glsl_nrm(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src_param; + unsigned int mask_size; + DWORD write_mask; + char dst_mask[6]; + + write_mask = shader_glsl_get_write_mask(ins->dst, dst_mask); + mask_size = shader_glsl_get_write_mask_size(write_mask); + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); + + shader_addline(buffer, "tmp0.x = length(%s);\n", src_param.param_str); + shader_glsl_append_dst(buffer, ins); + if (mask_size > 1) + { + shader_addline(buffer, "tmp0.x == 0.0 ? vec%u(0.0) : (%s / tmp0.x));\n", + mask_size, src_param.param_str); + } + else + { + shader_addline(buffer, "tmp0.x == 0.0 ? 0.0 : (%s / tmp0.x));\n", + src_param.param_str); + } +} + +/** Process the WINED3DSIO_EXPP instruction in GLSL: + * For shader model 1.x, do the following (and honor the writemask, so use a temporary variable): + * dst.x = 2^(floor(src)) + * dst.y = src - floor(src) + * dst.z = 2^src (partial precision is allowed, but optional) + * dst.w = 1.0; + * For 2.0 shaders, just do this (honoring writemask and swizzle): + * dst = 2^src; (partial precision is allowed, but optional) + */ +static void shader_glsl_expp(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src_param; + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src_param); + + if (ins->ctx->reg_maps->shader_version.major < 2) + { + char dst_mask[6]; + + shader_addline(ins->ctx->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str); + shader_addline(ins->ctx->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str); + shader_addline(ins->ctx->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str); + shader_addline(ins->ctx->buffer, "tmp0.w = 1.0;\n"); + + shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_get_write_mask(&ins->dst[0], dst_mask); + shader_addline(ins->ctx->buffer, "tmp0%s);\n", dst_mask); + } else { + DWORD write_mask; + unsigned int mask_size; + + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + mask_size = shader_glsl_get_write_mask_size(write_mask); + + if (mask_size > 1) { + shader_addline(ins->ctx->buffer, "vec%d(exp2(%s)));\n", mask_size, src_param.param_str); + } else { + shader_addline(ins->ctx->buffer, "exp2(%s));\n", src_param.param_str); + } + } +} + +/** Process the RCP (reciprocal or inverse) opcode in GLSL (dst = 1 / src) */ +static void shader_glsl_rcp(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src_param; + DWORD write_mask; + unsigned int mask_size; + + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + mask_size = shader_glsl_get_write_mask_size(write_mask); + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param); + + if (mask_size > 1) + { + shader_addline(ins->ctx->buffer, "vec%d(%s == 0.0 ? FLT_MAX : 1.0 / %s));\n", + mask_size, src_param.param_str, src_param.param_str); + } + else + { + shader_addline(ins->ctx->buffer, "%s == 0.0 ? FLT_MAX : 1.0 / %s);\n", + src_param.param_str, src_param.param_str); + } +} + +static void shader_glsl_rsq(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src_param; + DWORD write_mask; + unsigned int mask_size; + + write_mask = shader_glsl_append_dst(buffer, ins); + mask_size = shader_glsl_get_write_mask_size(write_mask); + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param); + + if (mask_size > 1) + { + shader_addline(buffer, "vec%d(%s == 0.0 ? FLT_MAX : inversesqrt(abs(%s))));\n", + mask_size, src_param.param_str, src_param.param_str); + } + else + { + shader_addline(buffer, "%s == 0.0 ? FLT_MAX : inversesqrt(abs(%s)));\n", + src_param.param_str, src_param.param_str); + } +} + +#ifdef VBOX_WITH_VMSVGA +static void shader_glsl_setp(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src_param1, src_param2; + DWORD write_mask; + + int i; + DWORD dst_mask = ins->dst[0].write_mask; + struct wined3d_shader_dst_param dst = ins->dst[0]; + + /* Cycle through all source0 channels */ + for (i=0; i<4; i++) { + if (dst_mask & RT_BIT(i)) + { + write_mask = WINED3DSP_WRITEMASK_0 << i; + dst.write_mask = dst_mask & write_mask; + + write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst); + Assert(write_mask); + + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param1); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src_param2); + + shader_addline(buffer, "%s %s %s);\n", + src_param1.param_str, shader_get_comp_op(ins->flags), src_param2.param_str); + } + } +} +#endif + +/** Process signed comparison opcodes in GLSL. */ +static void shader_glsl_compare(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + DWORD write_mask; + unsigned int mask_size; + + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + mask_size = shader_glsl_get_write_mask_size(write_mask); + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); + + if (mask_size > 1) { + const char *compare; + + switch(ins->handler_idx) + { + case WINED3DSIH_SLT: compare = "lessThan"; break; + case WINED3DSIH_SGE: compare = "greaterThanEqual"; break; + default: compare = ""; + FIXME("Can't handle opcode %#x\n", ins->handler_idx); + } + + shader_addline(ins->ctx->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare, + src0_param.param_str, src1_param.param_str); + } else { + switch(ins->handler_idx) + { + case WINED3DSIH_SLT: + /* Step(src0, src1) is not suitable here because if src0 == src1 SLT is supposed, + * to return 0.0 but step returns 1.0 because step is not < x + * An alternative is a bvec compare padded with an unused second component. + * step(src1 * -1.0, src0 * -1.0) is not an option because it suffers from the same + * issue. Playing with not() is not possible either because not() does not accept + * a scalar. + */ + shader_addline(ins->ctx->buffer, "(%s < %s) ? 1.0 : 0.0);\n", + src0_param.param_str, src1_param.param_str); + break; + case WINED3DSIH_SGE: + /* Here we can use the step() function and safe a conditional */ + shader_addline(ins->ctx->buffer, "step(%s, %s));\n", src1_param.param_str, src0_param.param_str); + break; + default: + FIXME("Can't handle opcode %#x\n", ins->handler_idx); + } + + } +} + +/** Process CMP instruction in GLSL (dst = src0 >= 0.0 ? src1 : src2), per channel */ +static void shader_glsl_cmp(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + glsl_src_param_t src2_param; + DWORD write_mask, cmp_channel = 0; + unsigned int i, j; + char mask_char[6]; + BOOL temp_destination = FALSE; + + if (shader_is_scalar(&ins->src[0].reg)) + { + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); + shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); + + shader_addline(ins->ctx->buffer, "%s >= 0.0 ? %s : %s);\n", + src0_param.param_str, src1_param.param_str, src2_param.param_str); + } else { + DWORD dst_mask = ins->dst[0].write_mask; + struct wined3d_shader_dst_param dst = ins->dst[0]; + + /* Cycle through all source0 channels */ + for (i=0; i<4; i++) { + write_mask = 0; + /* Find the destination channels which use the current source0 channel */ + for (j=0; j<4; j++) { + if (((ins->src[0].swizzle >> (2 * j)) & 0x3) == i) + { + write_mask |= WINED3DSP_WRITEMASK_0 << j; + cmp_channel = WINED3DSP_WRITEMASK_0 << j; + } + } + dst.write_mask = dst_mask & write_mask; + + /* Splitting the cmp instruction up in multiple lines imposes a problem: + * The first lines may overwrite source parameters of the following lines. + * Deal with that by using a temporary destination register if needed + */ + if ((ins->src[0].reg.idx == ins->dst[0].reg.idx + && ins->src[0].reg.type == ins->dst[0].reg.type) + || (ins->src[1].reg.idx == ins->dst[0].reg.idx + && ins->src[1].reg.type == ins->dst[0].reg.type) + || (ins->src[2].reg.idx == ins->dst[0].reg.idx + && ins->src[2].reg.type == ins->dst[0].reg.type)) + { + write_mask = shader_glsl_get_write_mask(&dst, mask_char); + if (!write_mask) continue; + shader_addline(ins->ctx->buffer, "tmp0%s = (", mask_char); + temp_destination = TRUE; + } else { + write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst); + if (!write_mask) continue; + } + + shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); + shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); + + shader_addline(ins->ctx->buffer, "%s >= 0.0 ? %s : %s);\n", + src0_param.param_str, src1_param.param_str, src2_param.param_str); + } + + if(temp_destination) { + shader_glsl_get_write_mask(&ins->dst[0], mask_char); + shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_addline(ins->ctx->buffer, "tmp0%s);\n", mask_char); + } + } + +} + +/** Process the CND opcode in GLSL (dst = (src0 > 0.5) ? src1 : src2) */ +/* For ps 1.1-1.3, only a single component of src0 is used. For ps 1.4 + * the compare is done per component of src0. */ +static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_dst_param dst; + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + glsl_src_param_t src2_param; + DWORD write_mask, cmp_channel = 0; + unsigned int i, j; + DWORD dst_mask; + DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, + ins->ctx->reg_maps->shader_version.minor); + + if (shader_version < WINED3D_SHADER_VERSION(1, 4)) + { + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); + shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); + + /* Fun: The D3DSI_COISSUE flag changes the semantic of the cnd instruction for < 1.4 shaders */ + if (ins->coissue) + { + shader_addline(ins->ctx->buffer, "%s /* COISSUE! */);\n", src1_param.param_str); + } else { + shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n", + src0_param.param_str, src1_param.param_str, src2_param.param_str); + } + return; + } + /* Cycle through all source0 channels */ + dst_mask = ins->dst[0].write_mask; + dst = ins->dst[0]; + for (i=0; i<4; i++) { + write_mask = 0; + /* Find the destination channels which use the current source0 channel */ + for (j=0; j<4; j++) { + if (((ins->src[0].swizzle >> (2 * j)) & 0x3) == i) + { + write_mask |= WINED3DSP_WRITEMASK_0 << j; + cmp_channel = WINED3DSP_WRITEMASK_0 << j; + } + } + + dst.write_mask = dst_mask & write_mask; + write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst); + if (!write_mask) continue; + + shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); + shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); + + shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n", + src0_param.param_str, src1_param.param_str, src2_param.param_str); + } +} + +/** GLSL code generation for WINED3DSIO_MAD: Multiply the first 2 opcodes, then add the last */ +static void shader_glsl_mad(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + glsl_src_param_t src2_param; + DWORD write_mask; + + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); + shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); + shader_addline(ins->ctx->buffer, "(%s * %s) + %s);\n", + src0_param.param_str, src1_param.param_str, src2_param.param_str); +} + +/* Handles transforming all WINED3DSIO_M?x? opcodes for + Vertex shaders to GLSL codes */ +static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins) +{ + int i; + int nComponents = 0; + struct wined3d_shader_dst_param tmp_dst = {{0}}; + struct wined3d_shader_src_param tmp_src[2] = {{{0}}}; + struct wined3d_shader_instruction tmp_ins; + + memset(&tmp_ins, 0, sizeof(tmp_ins)); + + /* Set constants for the temporary argument */ + tmp_ins.ctx = ins->ctx; + tmp_ins.dst_count = 1; + tmp_ins.dst = &tmp_dst; + tmp_ins.src_count = 2; + tmp_ins.src = tmp_src; + + switch(ins->handler_idx) + { + case WINED3DSIH_M4x4: + nComponents = 4; + tmp_ins.handler_idx = WINED3DSIH_DP4; + break; + case WINED3DSIH_M4x3: + nComponents = 3; + tmp_ins.handler_idx = WINED3DSIH_DP4; + break; + case WINED3DSIH_M3x4: + nComponents = 4; + tmp_ins.handler_idx = WINED3DSIH_DP3; + break; + case WINED3DSIH_M3x3: + nComponents = 3; + tmp_ins.handler_idx = WINED3DSIH_DP3; + break; + case WINED3DSIH_M3x2: + nComponents = 2; + tmp_ins.handler_idx = WINED3DSIH_DP3; + break; + default: + break; + } + + tmp_dst = ins->dst[0]; + tmp_src[0] = ins->src[0]; + tmp_src[1] = ins->src[1]; + for (i = 0; i < nComponents; ++i) + { + tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i; + shader_glsl_dot(&tmp_ins); + ++tmp_src[1].reg.idx; + } +} + +/** + The LRP instruction performs a component-wise linear interpolation + between the second and third operands using the first operand as the + blend factor. Equation: (dst = src2 + src0 * (src1 - src2)) + This is equivalent to mix(src2, src1, src0); +*/ +static void shader_glsl_lrp(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + glsl_src_param_t src2_param; + DWORD write_mask; + + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); + shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); + + shader_addline(ins->ctx->buffer, "mix(%s, %s, %s));\n", + src2_param.param_str, src1_param.param_str, src0_param.param_str); +} + +/** Process the WINED3DSIO_LIT instruction in GLSL: + * dst.x = dst.w = 1.0 + * dst.y = (src0.x > 0) ? src0.x + * dst.z = (src0.x > 0) ? ((src0.y > 0) ? pow(src0.y, src.w) : 0) : 0 + * where src.w is clamped at +- 128 + */ +static void shader_glsl_lit(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + glsl_src_param_t src3_param; + char dst_mask[6]; + + shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_get_write_mask(&ins->dst[0], dst_mask); + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src1_param); + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src3_param); + + /* The sdk specifies the instruction like this + * dst.x = 1.0; + * if(src.x > 0.0) dst.y = src.x + * else dst.y = 0.0. + * if(src.x > 0.0 && src.y > 0.0) dst.z = pow(src.y, power); + * else dst.z = 0.0; + * dst.w = 1.0; + * + * Obviously that has quite a few conditionals in it which we don't like. So the first step is this: + * dst.x = 1.0 ... No further explanation needed + * dst.y = max(src.y, 0.0); ... If x < 0.0, use 0.0, otherwise x. Same as the conditional + * dst.z = x > 0.0 ? pow(max(y, 0.0), p) : 0; ... 0 ^ power is 0, and otherwise we use y anyway + * dst.w = 1.0. ... Nothing fancy. + * + * So we still have one conditional in there. So do this: + * dst.z = pow(max(0.0, src.y) * step(0.0, src.x), power); + * + * step(0.0, x) will return 1 if src.x > 0.0, and 0 otherwise. So if y is 0 we get pow(0.0 * 1.0, power), + * which sets dst.z to 0. If y > 0, but x = 0.0, we get pow(y * 0.0, power), which results in 0 too. + * if both x and y are > 0, we get pow(y * 1.0, power), as it is supposed to + */ + shader_addline(ins->ctx->buffer, + "vec4(1.0, max(%s, 0.0), pow(max(0.0, %s) * step(0.0, %s), clamp(%s, -128.0, 128.0)), 1.0)%s);\n", + src0_param.param_str, src1_param.param_str, src0_param.param_str, src3_param.param_str, dst_mask); +} + +/** Process the WINED3DSIO_DST instruction in GLSL: + * dst.x = 1.0 + * dst.y = src0.x * src0.y + * dst.z = src0.z + * dst.w = src1.w + */ +static void shader_glsl_dst(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0y_param; + glsl_src_param_t src0z_param; + glsl_src_param_t src1y_param; + glsl_src_param_t src1w_param; + char dst_mask[6]; + + shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_get_write_mask(&ins->dst[0], dst_mask); + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src0y_param); + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &src0z_param); + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_1, &src1y_param); + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_3, &src1w_param); + + shader_addline(ins->ctx->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n", + src0y_param.param_str, src1y_param.param_str, src0z_param.param_str, src1w_param.param_str, dst_mask); +} + +/** Process the WINED3DSIO_SINCOS instruction in GLSL: + * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware + * can handle it. But, these functions are built-in for GLSL, so we can just ignore the last 2 params. + * + * dst.x = cos(src0.?) + * dst.y = sin(src0.?) + * dst.z = dst.z + * dst.w = dst.w + */ +static void shader_glsl_sincos(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + DWORD write_mask; + + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + + switch (write_mask) { + case WINED3DSP_WRITEMASK_0: + shader_addline(ins->ctx->buffer, "cos(%s));\n", src0_param.param_str); + break; + + case WINED3DSP_WRITEMASK_1: + shader_addline(ins->ctx->buffer, "sin(%s));\n", src0_param.param_str); + break; + + case (WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1): + shader_addline(ins->ctx->buffer, "vec2(cos(%s), sin(%s)));\n", src0_param.param_str, src0_param.param_str); + break; + + default: + ERR("Write mask should be .x, .y or .xy\n"); + break; + } +} + +/* sgn in vs_2_0 has 2 extra parameters(registers for temporary storage) which we don't use + * here. But those extra parameters require a dedicated function for sgn, since map2gl would + * generate invalid code + */ +static void shader_glsl_sgn(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + DWORD write_mask; + + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); + + shader_addline(ins->ctx->buffer, "sign(%s));\n", src0_param.param_str); +} + +/** Process the WINED3DSIO_LOOP instruction in GLSL: + * Start a for() loop where src1.y is the initial value of aL, + * increment aL by src1.z for a total of src1.x iterations. + * Need to use a temporary variable for this operation. + */ +/* FIXME: I don't think nested loops will work correctly this way. */ +static void shader_glsl_loop(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src1_param; + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + const DWORD *control_values = NULL; + const local_constant *constant; + + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &src1_param); + + /* Try to hardcode the loop control parameters if possible. Direct3D 9 class hardware doesn't support real + * varying indexing, but Microsoft designed this feature for Shader model 2.x+. If the loop control is + * known at compile time, the GLSL compiler can unroll the loop, and replace indirect addressing with direct + * addressing. + */ + if (ins->src[1].reg.type == WINED3DSPR_CONSTINT) + { + LIST_FOR_EACH_ENTRY(constant, &shader->baseShader.constantsI, local_constant, entry) { + if (constant->idx == ins->src[1].reg.idx) + { + control_values = constant->value; + break; + } + } + } + + if (control_values) + { + struct wined3d_shader_loop_control loop_control; + loop_control.count = control_values[0]; + loop_control.start = control_values[1]; + loop_control.step = (int)control_values[2]; + + if (loop_control.step > 0) + { + shader_addline(ins->ctx->buffer, "for (aL%u = %u; aL%u < (%u * %d + %u); aL%u += %d) {\n", + shader->baseShader.cur_loop_depth, loop_control.start, + shader->baseShader.cur_loop_depth, loop_control.count, loop_control.step, loop_control.start, + shader->baseShader.cur_loop_depth, loop_control.step); + } + else if (loop_control.step < 0) + { + shader_addline(ins->ctx->buffer, "for (aL%u = %u; aL%u > (%u * %d + %u); aL%u += %d) {\n", + shader->baseShader.cur_loop_depth, loop_control.start, + shader->baseShader.cur_loop_depth, loop_control.count, loop_control.step, loop_control.start, + shader->baseShader.cur_loop_depth, loop_control.step); + } + else + { + shader_addline(ins->ctx->buffer, "for (aL%u = %u, tmpInt%u = 0; tmpInt%u < %u; tmpInt%u++) {\n", + shader->baseShader.cur_loop_depth, loop_control.start, shader->baseShader.cur_loop_depth, + shader->baseShader.cur_loop_depth, loop_control.count, + shader->baseShader.cur_loop_depth); + } + } else { + shader_addline(ins->ctx->buffer, + "for (tmpInt%u = 0, aL%u = %s.y; tmpInt%u < %s.x; tmpInt%u++, aL%u += %s.z) {\n", + shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_regno, + src1_param.reg_name, shader->baseShader.cur_loop_depth, src1_param.reg_name, + shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_regno, src1_param.reg_name); + } + + shader->baseShader.cur_loop_depth++; + shader->baseShader.cur_loop_regno++; +} + +static void shader_glsl_end(const struct wined3d_shader_instruction *ins) +{ + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + + shader_addline(ins->ctx->buffer, "}\n"); + + if (ins->handler_idx == WINED3DSIH_ENDLOOP) + { + shader->baseShader.cur_loop_depth--; + shader->baseShader.cur_loop_regno--; + } + + if (ins->handler_idx == WINED3DSIH_ENDREP) + { + shader->baseShader.cur_loop_depth--; + } +} + +static void shader_glsl_rep(const struct wined3d_shader_instruction *ins) +{ + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + glsl_src_param_t src0_param; + const DWORD *control_values = NULL; + const local_constant *constant; + + /* Try to hardcode local values to help the GLSL compiler to unroll and optimize the loop */ + if (ins->src[0].reg.type == WINED3DSPR_CONSTINT) + { + LIST_FOR_EACH_ENTRY(constant, &shader->baseShader.constantsI, local_constant, entry) + { + if (constant->idx == ins->src[0].reg.idx) + { + control_values = constant->value; + break; + } + } + } + + if(control_values) { + shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %d; tmpInt%d++) {\n", + shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_depth, + control_values[0], shader->baseShader.cur_loop_depth); + } else { + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %s; tmpInt%d++) {\n", + shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_depth, + src0_param.param_str, shader->baseShader.cur_loop_depth); + } + shader->baseShader.cur_loop_depth++; +} + +static void shader_glsl_if(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + shader_addline(ins->ctx->buffer, "if (%s) {\n", src0_param.param_str); +} + +static void shader_glsl_ifc(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); + + shader_addline(ins->ctx->buffer, "if (%s %s %s) {\n", + src0_param.param_str, shader_get_comp_op(ins->flags), src1_param.param_str); +} + +static void shader_glsl_else(const struct wined3d_shader_instruction *ins) +{ + shader_addline(ins->ctx->buffer, "} else {\n"); +} + +static void shader_glsl_break(const struct wined3d_shader_instruction *ins) +{ + shader_addline(ins->ctx->buffer, "break;\n"); +} + +/* FIXME: According to MSDN the compare is done per component. */ +static void shader_glsl_breakc(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); + + shader_addline(ins->ctx->buffer, "if (%s %s %s) break;\n", + src0_param.param_str, shader_get_comp_op(ins->flags), src1_param.param_str); +} + +static void shader_glsl_label(const struct wined3d_shader_instruction *ins) +{ + shader_addline(ins->ctx->buffer, "}\n"); + shader_addline(ins->ctx->buffer, "void subroutine%u () {\n", ins->src[0].reg.idx); +} + +static void shader_glsl_call(const struct wined3d_shader_instruction *ins) +{ + shader_addline(ins->ctx->buffer, "subroutine%u();\n", ins->src[0].reg.idx); +} + +static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src1_param; + + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); + shader_addline(ins->ctx->buffer, "if (%s) subroutine%u();\n", src1_param.param_str, ins->src[0].reg.idx); +} + +static void shader_glsl_ret(const struct wined3d_shader_instruction *ins) +{ + /* No-op. The closing } is written when a new function is started, and at the end of the shader. This + * function only suppresses the unhandled instruction warning + */ +} + +/********************************************* + * Pixel Shader Specific Code begins here + ********************************************/ +static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) +{ + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device; + DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, + ins->ctx->reg_maps->shader_version.minor); + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + glsl_sample_function_t sample_function; + DWORD sample_flags = 0; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type; + DWORD sampler_idx; + DWORD mask = 0, swizzle; + + /* 1.0-1.4: Use destination register as sampler source. + * 2.0+: Use provided sampler source. */ + if (shader_version < WINED3D_SHADER_VERSION(2,0)) sampler_idx = ins->dst[0].reg.idx; + else sampler_idx = ins->src[1].reg.idx; + + AssertReturnVoid(sampler_idx < RT_ELEMENTS(ins->ctx->reg_maps->sampler_type)); + sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; + + if (shader_version < WINED3D_SHADER_VERSION(1,4)) + { + const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; + DWORD flags = (priv->cur_ps_args->tex_transform >> (sampler_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT)) + & WINED3D_PSARGS_TEXTRANSFORM_MASK; + + /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */ + if (flags & WINED3D_PSARGS_PROJECTED && sampler_type != WINED3DSTT_CUBE) { + sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; + switch (flags & ~WINED3D_PSARGS_PROJECTED) { + case WINED3DTTFF_COUNT1: FIXME("WINED3DTTFF_PROJECTED with WINED3DTTFF_COUNT1?\n"); break; + case WINED3DTTFF_COUNT2: mask = WINED3DSP_WRITEMASK_1; break; + case WINED3DTTFF_COUNT3: mask = WINED3DSP_WRITEMASK_2; break; + case WINED3DTTFF_COUNT4: + case WINED3DTTFF_DISABLE: mask = WINED3DSP_WRITEMASK_3; break; + } + } + } + else if (shader_version < WINED3D_SHADER_VERSION(2,0)) + { + DWORD src_mod = ins->src[0].modifiers; + + if (src_mod == WINED3DSPSM_DZ) { + sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; + mask = WINED3DSP_WRITEMASK_2; + } else if (src_mod == WINED3DSPSM_DW) { + sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; + mask = WINED3DSP_WRITEMASK_3; + } + } else { + if (ins->flags & WINED3DSI_TEXLD_PROJECT) + { + /* ps 2.0 texldp instruction always divides by the fourth component. */ + sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; + mask = WINED3DSP_WRITEMASK_3; + } + } + + if(deviceImpl->stateBlock->textures[sampler_idx] && + IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) { + sample_flags |= WINED3D_GLSL_SAMPLE_RECT; + } + + shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function); + mask |= sample_function.coord_mask; + + if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE; + else swizzle = ins->src[1].swizzle; + + /* 1.0-1.3: Use destination register as coordinate source. + 1.4+: Use provided coordinate source register. */ + if (shader_version < WINED3D_SHADER_VERSION(1,4)) + { + char coord_mask[6]; + shader_glsl_write_mask_to_str(mask, coord_mask); + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, NULL, + "T%u%s", sampler_idx, coord_mask); + } else { + glsl_src_param_t coord_param; + shader_glsl_add_src_param(ins, &ins->src[0], mask, &coord_param); + if (ins->flags & WINED3DSI_TEXLD_BIAS) + { + glsl_src_param_t bias; + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &bias); + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, bias.param_str, + "%s", coord_param.param_str); + } else { + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, NULL, + "%s", coord_param.param_str); + } + } +} + +static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins) +{ + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + glsl_sample_function_t sample_function; + glsl_src_param_t coord_param, dx_param, dy_param; + DWORD sample_flags = WINED3D_GLSL_SAMPLE_GRAD; + DWORD sampler_type; + DWORD sampler_idx; + DWORD swizzle = ins->src[1].swizzle; + + if (!gl_info->supported[ARB_SHADER_TEXTURE_LOD] && !gl_info->supported[EXT_GPU_SHADER4]) + { + FIXME("texldd used, but not supported by hardware. Falling back to regular tex\n"); + shader_glsl_tex(ins); + return; + } + + sampler_idx = ins->src[1].reg.idx; + AssertReturnVoid(sampler_idx < RT_ELEMENTS(ins->ctx->reg_maps->sampler_type)); + + sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; + if(deviceImpl->stateBlock->textures[sampler_idx] && + IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) { + sample_flags |= WINED3D_GLSL_SAMPLE_RECT; + } + + shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function); + shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); + shader_glsl_add_src_param(ins, &ins->src[2], sample_function.coord_mask, &dx_param); + shader_glsl_add_src_param(ins, &ins->src[3], sample_function.coord_mask, &dy_param); + + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, dx_param.param_str, dy_param.param_str, NULL, + "%s", coord_param.param_str); +} + +static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins) +{ + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + glsl_sample_function_t sample_function; + glsl_src_param_t coord_param, lod_param; + DWORD sample_flags = WINED3D_GLSL_SAMPLE_LOD; + DWORD sampler_type; + DWORD sampler_idx; + DWORD swizzle = ins->src[1].swizzle; + + sampler_idx = ins->src[1].reg.idx; + AssertReturnVoid(sampler_idx < RT_ELEMENTS(ins->ctx->reg_maps->sampler_type)); + + sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; + if(deviceImpl->stateBlock->textures[sampler_idx] && + IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) { + sample_flags |= WINED3D_GLSL_SAMPLE_RECT; + } + shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function); + shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param); + + if (!gl_info->supported[ARB_SHADER_TEXTURE_LOD] && !gl_info->supported[EXT_GPU_SHADER4] + && shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) + { + /* The GLSL spec claims the Lod sampling functions are only supported in vertex shaders. + * However, they seem to work just fine in fragment shaders as well. */ + WARN("Using %s in fragment shader.\n", sample_function.name); + } + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, lod_param.param_str, + "%s", coord_param.param_str); +} + +static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins) +{ + /* FIXME: Make this work for more than just 2D textures */ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + DWORD write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + + if (!(ins->ctx->reg_maps->shader_version.major == 1 && ins->ctx->reg_maps->shader_version.minor == 4)) + { + char dst_mask[6]; + + shader_glsl_get_write_mask(&ins->dst[0], dst_mask); + shader_addline(buffer, "clamp(gl_TexCoord[%u], 0.0, 1.0)%s);\n", + ins->dst[0].reg.idx, dst_mask); + } else { + DWORD reg = ins->src[0].reg.idx; + DWORD src_mod = ins->src[0].modifiers; + char dst_swizzle[6]; + + shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle); + + if (src_mod == WINED3DSPSM_DZ) { + glsl_src_param_t div_param; + unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &div_param); + + if (mask_size > 1) { + shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str); + } else { + shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str); + } + } else if (src_mod == WINED3DSPSM_DW) { + glsl_src_param_t div_param; + unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &div_param); + + if (mask_size > 1) { + shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str); + } else { + shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str); + } + } else { + shader_addline(buffer, "gl_TexCoord[%u]%s);\n", reg, dst_swizzle); + } + } +} + +/** Process the WINED3DSIO_TEXDP3TEX instruction in GLSL: + * Take a 3-component dot product of the TexCoord[dstreg] and src, + * then perform a 1D texture lookup from stage dstregnum, place into dst. */ +static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins) +{ + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + glsl_src_param_t src0_param; + glsl_sample_function_t sample_function; + DWORD sampler_idx = ins->dst[0].reg.idx; + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; + UINT mask_size; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + + /* Do I have to take care about the projected bit? I don't think so, since the dp3 returns only one + * scalar, and projected sampling would require 4. + * + * It is a dependent read - not valid with conditional NP2 textures + */ + shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + mask_size = shader_glsl_get_write_mask_size(sample_function.coord_mask); + + switch(mask_size) + { + case 1: + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, + "dot(gl_TexCoord[%u].xyz, %s)", sampler_idx, src0_param.param_str); + break; + + case 2: + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, + "vec2(dot(gl_TexCoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str); + break; + + case 3: + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, + "vec3(dot(gl_TexCoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str); + break; + + default: + FIXME("Unexpected mask size %u\n", mask_size); + break; + } +} + +/** Process the WINED3DSIO_TEXDP3 instruction in GLSL: + * Take a 3-component dot product of the TexCoord[dstreg] and src. */ +static void shader_glsl_texdp3(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + DWORD dstreg = ins->dst[0].reg.idx; + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + DWORD dst_mask; + unsigned int mask_size; + + dst_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + mask_size = shader_glsl_get_write_mask_size(dst_mask); + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + + if (mask_size > 1) { + shader_addline(ins->ctx->buffer, "vec%d(dot(T%u.xyz, %s)));\n", mask_size, dstreg, src0_param.param_str); + } else { + shader_addline(ins->ctx->buffer, "dot(T%u.xyz, %s));\n", dstreg, src0_param.param_str); + } +} + +/** Process the WINED3DSIO_TEXDEPTH instruction in GLSL: + * Calculate the depth as dst.x / dst.y */ +static void shader_glsl_texdepth(const struct wined3d_shader_instruction *ins) +{ + glsl_dst_param_t dst_param; + + shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); + + /* Tests show that texdepth never returns anything below 0.0, and that r5.y is clamped to 1.0. + * Negative input is accepted, -0.25 / -0.5 returns 0.5. GL should clamp gl_FragDepth to [0;1], but + * this doesn't always work, so clamp the results manually. Whether or not the x value is clamped at 1 + * too is irrelevant, since if x = 0, any y value < 1.0 (and > 1.0 is not allowed) results in a result + * >= 1.0 or < 0.0 + */ + shader_addline(ins->ctx->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n", + dst_param.reg_name, dst_param.reg_name); +} + +/** Process the WINED3DSIO_TEXM3X2DEPTH instruction in GLSL: + * Last row of a 3x2 matrix multiply, use the result to calculate the depth: + * Calculate tmp0.y = TexCoord[dstreg] . src.xyz; (tmp0.x has already been calculated) + * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y + */ +static void shader_glsl_texm3x2depth(const struct wined3d_shader_instruction *ins) +{ + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + DWORD dstreg = ins->dst[0].reg.idx; + glsl_src_param_t src0_param; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + + shader_addline(ins->ctx->buffer, "tmp0.y = dot(T%u.xyz, %s);\n", dstreg, src0_param.param_str); + shader_addline(ins->ctx->buffer, "gl_FragDepth = (tmp0.y == 0.0) ? 1.0 : clamp(tmp0.x / tmp0.y, 0.0, 1.0);\n"); +} + +/** Process the WINED3DSIO_TEXM3X2PAD instruction in GLSL + * Calculate the 1st of a 2-row matrix multiplication. */ +static void shader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins) +{ + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + DWORD reg = ins->dst[0].reg.idx; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src0_param; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + shader_addline(buffer, "tmp0.x = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); +} + +/** Process the WINED3DSIO_TEXM3X3PAD instruction in GLSL + * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */ +static void shader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins) +{ + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + DWORD reg = ins->dst[0].reg.idx; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state; + glsl_src_param_t src0_param; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + shader_addline(buffer, "tmp0.%c = dot(T%u.xyz, %s);\n", 'x' + current_state->current_row, reg, src0_param.param_str); + current_state->texcoord_w[current_state->current_row++] = reg; +} + +static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins) +{ + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + DWORD reg = ins->dst[0].reg.idx; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + glsl_src_param_t src0_param; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg]; + glsl_sample_function_t sample_function; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); + + shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + + /* Sample the texture using the calculated coordinates */ + shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xy"); +} + +/** Process the WINED3DSIO_TEXM3X3TEX instruction in GLSL + * Perform the 3rd row of a 3x3 matrix multiply, then sample the texture using the calculated coordinates */ +static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins) +{ + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + SHADER_PARSE_STATE *current_state = &shader->baseShader.parse_state; + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + glsl_src_param_t src0_param; + DWORD reg = ins->dst[0].reg.idx; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg]; + glsl_sample_function_t sample_function; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + shader_addline(ins->ctx->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); + + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + + /* Sample the texture using the calculated coordinates */ + shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz"); + + current_state->current_row = 0; +} + +/** Process the WINED3DSIO_TEXM3X3 instruction in GLSL + * Perform the 3rd row of a 3x3 matrix multiply */ +static void shader_glsl_texm3x3(const struct wined3d_shader_instruction *ins) +{ + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + SHADER_PARSE_STATE *current_state = &shader->baseShader.parse_state; + glsl_src_param_t src0_param; + char dst_mask[6]; + DWORD reg = ins->dst[0].reg.idx; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + + shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_glsl_get_write_mask(&ins->dst[0], dst_mask); + shader_addline(ins->ctx->buffer, "vec4(tmp0.xy, dot(T%u.xyz, %s), 1.0)%s);\n", reg, src0_param.param_str, dst_mask); + + current_state->current_row = 0; +} + +/* Process the WINED3DSIO_TEXM3X3SPEC instruction in GLSL + * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */ +static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins) +{ + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + DWORD reg = ins->dst[0].reg.idx; + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state; + WINED3DSAMPLER_TEXTURE_TYPE stype = ins->ctx->reg_maps->sampler_type[reg]; + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + glsl_sample_function_t sample_function; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param); + + /* Perform the last matrix multiply operation */ + shader_addline(buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); + /* Reflection calculation */ + shader_addline(buffer, "tmp0.xyz = -reflect((%s), normalize(tmp0.xyz));\n", src1_param.param_str); + + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(gl_info, stype, 0, &sample_function); + + /* Sample the texture */ + shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz"); + + current_state->current_row = 0; +} + +/* Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL + * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */ +static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins) +{ + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + DWORD reg = ins->dst[0].reg.idx; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state; + glsl_src_param_t src0_param; + DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg]; + glsl_sample_function_t sample_function; + + shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); + + /* Perform the last matrix multiply operation */ + shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str); + + /* Construct the eye-ray vector from w coordinates */ + shader_addline(buffer, "tmp1.xyz = normalize(vec3(gl_TexCoord[%u].w, gl_TexCoord[%u].w, gl_TexCoord[%u].w));\n", + current_state->texcoord_w[0], current_state->texcoord_w[1], reg); + shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n"); + + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + + /* Sample the texture using the calculated coordinates */ + shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz"); + + current_state->current_row = 0; +} + +/** Process the WINED3DSIO_TEXBEM instruction in GLSL. + * Apply a fake bump map transform. + * texbem is pshader <= 1.3 only, this saves a few version checks + */ +static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins) +{ + /*IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device; - unused */ + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; + glsl_sample_function_t sample_function; + glsl_src_param_t coord_param; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type; + DWORD sampler_idx; + DWORD mask; + DWORD flags; + char coord_mask[6]; + + sampler_idx = ins->dst[0].reg.idx; + flags = (priv->cur_ps_args->tex_transform >> (sampler_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT)) + & WINED3D_PSARGS_TEXTRANSFORM_MASK; + + sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + mask = sample_function.coord_mask; + + shader_glsl_write_mask_to_str(mask, coord_mask); + + /* with projective textures, texbem only divides the static texture coord, not the displacement, + * so we can't let the GL handle this. + */ + if (flags & WINED3D_PSARGS_PROJECTED) { + DWORD div_mask=0; + char coord_div_mask[3]; + switch (flags & ~WINED3D_PSARGS_PROJECTED) { + case WINED3DTTFF_COUNT1: FIXME("WINED3DTTFF_PROJECTED with WINED3DTTFF_COUNT1?\n"); break; + case WINED3DTTFF_COUNT2: div_mask = WINED3DSP_WRITEMASK_1; break; + case WINED3DTTFF_COUNT3: div_mask = WINED3DSP_WRITEMASK_2; break; + case WINED3DTTFF_COUNT4: + case WINED3DTTFF_DISABLE: div_mask = WINED3DSP_WRITEMASK_3; break; + } + shader_glsl_write_mask_to_str(div_mask, coord_div_mask); + shader_addline(ins->ctx->buffer, "T%u%s /= T%u%s;\n", sampler_idx, coord_mask, sampler_idx, coord_div_mask); + } + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &coord_param); + + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, + "T%u%s + vec4(bumpenvmat%d * %s, 0.0, 0.0)%s", sampler_idx, coord_mask, sampler_idx, + coord_param.param_str, coord_mask); + + if (ins->handler_idx == WINED3DSIH_TEXBEML) + { + glsl_src_param_t luminance_param; + glsl_dst_param_t dst_param; + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &luminance_param); + shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); + + shader_addline(ins->ctx->buffer, "%s%s *= (%s * luminancescale%d + luminanceoffset%d);\n", + dst_param.reg_name, dst_param.mask_str, + luminance_param.param_str, sampler_idx, sampler_idx); + } +} + +static void shader_glsl_bem(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param, src1_param; + DWORD sampler_idx = ins->dst[0].reg.idx; + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param); + + shader_glsl_append_dst(ins->ctx->buffer, ins); + shader_addline(ins->ctx->buffer, "%s + bumpenvmat%d * %s);\n", + src0_param.param_str, sampler_idx, src1_param.param_str); +} + +/** Process the WINED3DSIO_TEXREG2AR instruction in GLSL + * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */ +static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins) +{ + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + glsl_src_param_t src0_param; + DWORD sampler_idx = ins->dst[0].reg.idx; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; + glsl_sample_function_t sample_function; + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); + + shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, + "%s.wx", src0_param.reg_name); +} + +/** Process the WINED3DSIO_TEXREG2GB instruction in GLSL + * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */ +static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins) +{ + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + glsl_src_param_t src0_param; + DWORD sampler_idx = ins->dst[0].reg.idx; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; + glsl_sample_function_t sample_function; + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); + + shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, + "%s.yz", src0_param.reg_name); +} + +/** Process the WINED3DSIO_TEXREG2RGB instruction in GLSL + * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */ +static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins) +{ + const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; + glsl_src_param_t src0_param; + DWORD sampler_idx = ins->dst[0].reg.idx; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; + glsl_sample_function_t sample_function; + + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &src0_param); + + shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, + "%s", src0_param.param_str); +} + +/** Process the WINED3DSIO_TEXKILL instruction in GLSL. + * If any of the first 3 components are < 0, discard this pixel */ +static void shader_glsl_texkill(const struct wined3d_shader_instruction *ins) +{ + glsl_dst_param_t dst_param; + + /* The argument is a destination parameter, and no writemasks are allowed */ + shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); + if (ins->ctx->reg_maps->shader_version.major >= 2) + { + /* 2.0 shaders compare all 4 components in texkill */ + shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyzw, vec4(0.0)))) discard;\n", dst_param.reg_name); + } else { + /* 1.X shaders only compare the first 3 components, probably due to the nature of the texkill + * instruction as a tex* instruction, and phase, which kills all a / w components. Even if all + * 4 components are defined, only the first 3 are used + */ + shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyz, vec3(0.0)))) discard;\n", dst_param.reg_name); + } +} + +/** Process the WINED3DSIO_DP2ADD instruction in GLSL. + * dst = dot2(src0, src1) + src2 */ +static void shader_glsl_dp2add(const struct wined3d_shader_instruction *ins) +{ + glsl_src_param_t src0_param; + glsl_src_param_t src1_param; + glsl_src_param_t src2_param; + DWORD write_mask; + unsigned int mask_size; + + write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); + mask_size = shader_glsl_get_write_mask_size(write_mask); + + shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param); + shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param); + shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &src2_param); + + if (mask_size > 1) { + shader_addline(ins->ctx->buffer, "vec%d(dot(%s, %s) + %s));\n", + mask_size, src0_param.param_str, src1_param.param_str, src2_param.param_str); + } else { + shader_addline(ins->ctx->buffer, "dot(%s, %s) + %s);\n", + src0_param.param_str, src1_param.param_str, src2_param.param_str); + } +} + +static void shader_glsl_input_pack(IWineD3DPixelShader *iface, struct wined3d_shader_buffer *buffer, + const struct wined3d_shader_signature_element *input_signature, const struct shader_reg_maps *reg_maps, + enum vertexprocessing_mode vertexprocessing) +{ + unsigned int i; + IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; + WORD map = reg_maps->input_registers; + + for (i = 0; map; map >>= 1, ++i) + { + const char *semantic_name; + UINT semantic_idx; + char reg_mask[6]; + + /* Unused */ + if (!(map & 1)) continue; + + semantic_name = input_signature[i].semantic_name; + semantic_idx = input_signature[i].semantic_idx; + shader_glsl_write_mask_to_str(input_signature[i].mask, reg_mask); + + if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + if (semantic_idx < 8 && vertexprocessing == pretransformed) + shader_addline(buffer, "IN[%u]%s = gl_TexCoord[%u]%s;\n", + This->input_reg_map[i], reg_mask, semantic_idx, reg_mask); + else + shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + if (semantic_idx == 0) + shader_addline(buffer, "IN[%u]%s = vec4(gl_Color)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); + else if (semantic_idx == 1) + shader_addline(buffer, "IN[%u]%s = vec4(gl_SecondaryColor)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); + else + shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); + } + else + { + shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); + } + } +} + +/********************************************* + * Vertex Shader Specific Code begins here + ********************************************/ + +static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_shader_prog_link *entry) { + glsl_program_key_t key; + + key.vshader = entry->vshader; + key.pshader = entry->pshader; + key.vs_args = entry->vs_args; + key.ps_args = entry->ps_args; + key.context = entry->context; + + if (wine_rb_put(&priv->program_lookup, &key, &entry->program_lookup_entry) == -1) + { + ERR("Failed to insert program entry.\n"); + } +} + +static struct glsl_shader_prog_link *get_glsl_program_entry(struct shader_glsl_priv *priv, + IWineD3DVertexShader *vshader, IWineD3DPixelShader *pshader, struct vs_compile_args *vs_args, + struct ps_compile_args *ps_args, const struct wined3d_context *context) { + struct wine_rb_entry *entry; + glsl_program_key_t key; + + key.vshader = vshader; + key.pshader = pshader; + key.vs_args = *vs_args; + key.ps_args = *ps_args; + key.context = context; + + entry = wine_rb_get(&priv->program_lookup, &key); + return entry ? WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry) : NULL; +} + +/* GL locking is done by the caller */ +static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struct wined3d_gl_info *gl_info, + struct glsl_shader_prog_link *entry) +{ + glsl_program_key_t key; + + key.vshader = entry->vshader; + key.pshader = entry->pshader; + key.vs_args = entry->vs_args; + key.ps_args = entry->ps_args; + key.context = entry->context; + wine_rb_remove(&priv->program_lookup, &key); + + if (context_get_current() == entry->context) + { + TRACE("deleting program %p\n", (void *)(uintptr_t)entry->programId); + GL_EXTCALL(glDeleteObjectARB(entry->programId)); + checkGLcall("glDeleteObjectARB"); + } + else + { + WARN("Attempting to delete program %p created in ctx %p from ctx %p\n", (void *)(uintptr_t)entry->programId, entry->context, context_get_current()); + } + + if (entry->vshader) list_remove(&entry->vshader_entry); + if (entry->pshader) list_remove(&entry->pshader_entry); + HeapFree(GetProcessHeap(), 0, entry->vuniformF_locations); + HeapFree(GetProcessHeap(), 0, entry->puniformF_locations); + HeapFree(GetProcessHeap(), 0, entry); +} + +static void handle_ps3_input(struct wined3d_shader_buffer *buffer, const struct wined3d_gl_info *gl_info, const DWORD *map, + const struct wined3d_shader_signature_element *input_signature, const struct shader_reg_maps *reg_maps_in, + const struct wined3d_shader_signature_element *output_signature, const struct shader_reg_maps *reg_maps_out) +{ + unsigned int i, j; + const char *semantic_name_in, *semantic_name_out; + UINT semantic_idx_in, semantic_idx_out; + DWORD *set; + DWORD in_idx; + unsigned int in_count = vec4_varyings(3, gl_info); + char reg_mask[6], reg_mask_out[6]; + char destination[50]; + WORD input_map, output_map; + + set = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*set) * (in_count + 2)); + + if (!output_signature) + { + /* Save gl_FrontColor & gl_FrontSecondaryColor before overwriting them. */ + shader_addline(buffer, "vec4 front_color = gl_FrontColor;\n"); + shader_addline(buffer, "vec4 front_secondary_color = gl_FrontSecondaryColor;\n"); + } + + input_map = reg_maps_in->input_registers; + for (i = 0; input_map; input_map >>= 1, ++i) + { + if (!(input_map & 1)) continue; + + in_idx = map[i]; + if (in_idx >= (in_count + 2)) { + FIXME("More input varyings declared than supported, expect issues\n"); + continue; + } + else if (map[i] == ~0U) + { + /* Declared, but not read register */ + continue; + } + + if (in_idx == in_count) { + sprintf(destination, "gl_FrontColor"); + } else if (in_idx == in_count + 1) { + sprintf(destination, "gl_FrontSecondaryColor"); + } else { + sprintf(destination, "IN[%u]", in_idx); + } + + semantic_name_in = input_signature[i].semantic_name; + semantic_idx_in = input_signature[i].semantic_idx; + set[map[i]] = input_signature[i].mask; + shader_glsl_write_mask_to_str(input_signature[i].mask, reg_mask); + + if (!output_signature) + { + if (shader_match_semantic(semantic_name_in, WINED3DDECLUSAGE_COLOR)) + { + if (semantic_idx_in == 0) + shader_addline(buffer, "%s%s = front_color%s;\n", + destination, reg_mask, reg_mask); + else if (semantic_idx_in == 1) + shader_addline(buffer, "%s%s = front_secondary_color%s;\n", + destination, reg_mask, reg_mask); + else + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); + } + else if (shader_match_semantic(semantic_name_in, WINED3DDECLUSAGE_TEXCOORD)) + { + if (semantic_idx_in < 8) + { + shader_addline(buffer, "%s%s = gl_TexCoord[%u]%s;\n", + destination, reg_mask, semantic_idx_in, reg_mask); + } + else + { + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); + } + } + else if (shader_match_semantic(semantic_name_in, WINED3DDECLUSAGE_FOG)) + { + shader_addline(buffer, "%s%s = vec4(gl_FogFragCoord, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); + } + else + { + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); + } + } else { + BOOL found = FALSE; + + output_map = reg_maps_out->output_registers; + for (j = 0; output_map; output_map >>= 1, ++j) + { + if (!(output_map & 1)) continue; + + semantic_name_out = output_signature[j].semantic_name; + semantic_idx_out = output_signature[j].semantic_idx; + shader_glsl_write_mask_to_str(output_signature[j].mask, reg_mask_out); + + if (semantic_idx_in == semantic_idx_out + && !strcmp(semantic_name_in, semantic_name_out)) + { + shader_addline(buffer, "%s%s = OUT[%u]%s;\n", + destination, reg_mask, j, reg_mask); + found = TRUE; + } + } + if(!found) { + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); + } + } + } + + /* This is solely to make the compiler / linker happy and avoid warning about undefined + * varyings. It shouldn't result in any real code executed on the GPU, since all read + * input varyings are assigned above, if the optimizer works properly. + */ + for(i = 0; i < in_count + 2; i++) { + if (set[i] && set[i] != WINED3DSP_WRITEMASK_ALL) + { + unsigned int size = 0; + memset(reg_mask, 0, sizeof(reg_mask)); + if(!(set[i] & WINED3DSP_WRITEMASK_0)) { + reg_mask[size] = 'x'; + size++; + } + if(!(set[i] & WINED3DSP_WRITEMASK_1)) { + reg_mask[size] = 'y'; + size++; + } + if(!(set[i] & WINED3DSP_WRITEMASK_2)) { + reg_mask[size] = 'z'; + size++; + } + if(!(set[i] & WINED3DSP_WRITEMASK_3)) { + reg_mask[size] = 'w'; + size++; + } + + if (i == in_count) { + sprintf(destination, "gl_FrontColor"); + } else if (i == in_count + 1) { + sprintf(destination, "gl_FrontSecondaryColor"); + } else { + sprintf(destination, "IN[%u]", i); + } + + if (size == 1) { + shader_addline(buffer, "%s.%s = 0.0;\n", destination, reg_mask); + } else { + shader_addline(buffer, "%s.%s = vec%u(0.0);\n", destination, reg_mask, size); + } + } + } + + HeapFree(GetProcessHeap(), 0, set); +} + +static void generate_texcoord_assignment(struct wined3d_shader_buffer *buffer, IWineD3DVertexShaderImpl *vs, IWineD3DPixelShaderImpl *ps) +{ + DWORD map; + unsigned int i; + char reg_mask[6]; + + if (!ps) + return; + + for (i = 0, map = ps->baseShader.reg_maps.texcoord; map && i < min(8, MAX_REG_TEXCRD); map >>= 1, ++i) + { + if (!(map & 1)) + continue; + + /* so far we assume that if texcoord_mask has any write flags, they are assigned appropriately with pixel shader */ + if ((vs->baseShader.reg_maps.texcoord_mask[i]) & WINED3DSP_WRITEMASK_ALL) + continue; + + shader_glsl_write_mask_to_str(WINED3DSP_WRITEMASK_ALL, reg_mask); + shader_addline(buffer, "gl_TexCoord[%u]%s = gl_MultiTexCoord%u%s;\n", i, reg_mask, i, reg_mask); + } +} + +/* GL locking is done by the caller */ +static GLhandleARB generate_param_reorder_function(struct wined3d_shader_buffer *buffer, + IWineD3DVertexShader *a_vertexshader, IWineD3DPixelShader *pixelshader, const struct wined3d_gl_info *gl_info) +{ + GLhandleARB ret = 0; + IWineD3DVertexShaderImpl *vs = (IWineD3DVertexShaderImpl *) a_vertexshader; + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) pixelshader; + IWineD3DDeviceImpl *device; + DWORD vs_major = vs->baseShader.reg_maps.shader_version.major; + DWORD ps_major = ps ? ps->baseShader.reg_maps.shader_version.major : 0; + unsigned int i; + const char *semantic_name; + UINT semantic_idx; + char reg_mask[6]; + const struct wined3d_shader_signature_element *output_signature; + + shader_buffer_clear(buffer); + + shader_addline(buffer, "#version 120\n"); + + if(vs_major < 3 && ps_major < 3) { + /* That one is easy: The vertex shader writes to the builtin varyings, the pixel shader reads from them. + * Take care about the texcoord .w fixup though if we're using the fixed function fragment pipeline + */ + device = (IWineD3DDeviceImpl *) vs->baseShader.device; + if ((gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W) + && ps_major == 0 && vs_major > 0 && !device->frag_pipe->ffp_proj_control) + { + shader_addline(buffer, "void order_ps_input() {\n"); + for(i = 0; i < min(8, MAX_REG_TEXCRD); i++) { + if(vs->baseShader.reg_maps.texcoord_mask[i] != 0 && + vs->baseShader.reg_maps.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL) { + shader_addline(buffer, "gl_TexCoord[%u].w = 1.0;\n", i); + } + } + shader_addline(buffer, "}\n"); + } else { + shader_addline(buffer, "void order_ps_input() {\n"); + generate_texcoord_assignment(buffer, vs, ps); + shader_addline(buffer, "}\n"); + } + } else if(ps_major < 3 && vs_major >= 3) { + WORD map = vs->baseShader.reg_maps.output_registers; + + /* The vertex shader writes to its own varyings, the pixel shader needs them in the builtin ones */ + output_signature = vs->baseShader.output_signature; + + shader_addline(buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT); + for (i = 0; map; map >>= 1, ++i) + { + DWORD write_mask; + + if (!(map & 1)) continue; + + semantic_name = output_signature[i].semantic_name; + semantic_idx = output_signature[i].semantic_idx; + write_mask = output_signature[i].mask; + shader_glsl_write_mask_to_str(write_mask, reg_mask); + + if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + if (semantic_idx == 0) + shader_addline(buffer, "gl_FrontColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); + else if (semantic_idx == 1) + shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION)) + { + shader_addline(buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + if (semantic_idx < 8) + { + if (!(gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W) || ps_major > 0) + write_mask |= WINED3DSP_WRITEMASK_3; + + shader_addline(buffer, "gl_TexCoord[%u]%s = OUT[%u]%s;\n", + semantic_idx, reg_mask, i, reg_mask); + if (!(write_mask & WINED3DSP_WRITEMASK_3)) + shader_addline(buffer, "gl_TexCoord[%u].w = 1.0;\n", semantic_idx); + } + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE)) + { + shader_addline(buffer, "gl_PointSize = OUT[%u].x;\n", i); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG)) + { + shader_addline(buffer, "gl_FogFragCoord = OUT[%u].%c;\n", i, reg_mask[1]); + } + } + shader_addline(buffer, "}\n"); + + } else if(ps_major >= 3 && vs_major >= 3) { + WORD map = vs->baseShader.reg_maps.output_registers; + + output_signature = vs->baseShader.output_signature; + + /* This one is tricky: a 3.0 pixel shader reads from a 3.0 vertex shader */ + shader_addline(buffer, "varying vec4 IN[%u];\n", vec4_varyings(3, gl_info)); + shader_addline(buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT); + + /* First, sort out position and point size. Those are not passed to the pixel shader */ + for (i = 0; map; map >>= 1, ++i) + { + if (!(map & 1)) continue; + + semantic_name = output_signature[i].semantic_name; + shader_glsl_write_mask_to_str(output_signature[i].mask, reg_mask); + + if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION)) + { + shader_addline(buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE)) + { + shader_addline(buffer, "gl_PointSize = OUT[%u].x;\n", i); + } + } + + /* Then, fix the pixel shader input */ + handle_ps3_input(buffer, gl_info, ps->input_reg_map, ps->baseShader.input_signature, + &ps->baseShader.reg_maps, output_signature, &vs->baseShader.reg_maps); + + shader_addline(buffer, "}\n"); + } else if(ps_major >= 3 && vs_major < 3) { + shader_addline(buffer, "varying vec4 IN[%u];\n", vec4_varyings(3, gl_info)); + shader_addline(buffer, "void order_ps_input() {\n"); + /* The vertex shader wrote to the builtin varyings. There is no need to figure out position and + * point size, but we depend on the optimizers kindness to find out that the pixel shader doesn't + * read gl_TexCoord and gl_ColorX, otherwise we'll run out of varyings + */ + handle_ps3_input(buffer, gl_info, ps->input_reg_map, ps->baseShader.input_signature, + &ps->baseShader.reg_maps, NULL, NULL); + shader_addline(buffer, "}\n"); + } else { + ERR("Unexpected vertex and pixel shader version condition: vs: %d, ps: %d\n", vs_major, ps_major); + } + + ret = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); + checkGLcall("glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)"); + GL_EXTCALL(glShaderSourceARB(ret, 1, (const char**)&buffer->buffer, NULL)); + checkGLcall("glShaderSourceARB(ret, 1, &buffer->buffer, NULL)"); + GL_EXTCALL(glCompileShaderARB(ret)); + checkGLcall("glCompileShaderARB(ret)"); + shader_glsl_validate_compile_link(gl_info, ret, FALSE); + return ret; +} + +#ifdef VBOX_WITH_VMSVGA +static GLhandleARB generate_passthrough_vshader(const struct wined3d_gl_info *gl_info) +{ + GLhandleARB ret = 0; + static const char *passthrough_vshader[] = + { + "#version 120\n" + "vec4 R0;\n" + "void main(void)\n" + "{\n" + " R0 = gl_Vertex;\n" + " R0.w = 1.0;\n" + " R0.z = 0.0;\n" + " gl_Position = gl_ModelViewProjectionMatrix * R0;\n" + "}\n" + }; + + ret = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); + checkGLcall("glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)"); + GL_EXTCALL(glShaderSourceARB(ret, 1, passthrough_vshader, NULL)); + checkGLcall("glShaderSourceARB(ret, 1, passthrough_vshader, NULL)"); + GL_EXTCALL(glCompileShaderARB(ret)); + checkGLcall("glCompileShaderARB(ret)"); + shader_glsl_validate_compile_link(gl_info, ret, FALSE); + + return ret; +} + +#endif + +/* GL locking is done by the caller */ +static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const struct wined3d_gl_info *gl_info, + GLhandleARB programId, char prefix) +{ + const local_constant *lconst; + GLint tmp_loc; + const float *value; + char glsl_name[8]; + + LIST_FOR_EACH_ENTRY(lconst, &shader->baseShader.constantsF, local_constant, entry) { + value = (const float *)lconst->value; + snprintf(glsl_name, sizeof(glsl_name), "%cLC%u", prefix, lconst->idx); + tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); + GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, value)); + } + checkGLcall("Hardcoding local constants"); +} + +/* GL locking is done by the caller */ +#ifdef VBOX_WITH_VMSVGA +static GLhandleARB shader_glsl_generate_pshader(const struct wined3d_context *context, +#else +static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context, +#endif + struct wined3d_shader_buffer *buffer, IWineD3DPixelShaderImpl *This, + const struct ps_compile_args *args, struct ps_np2fixup_info *np2fixup_info) +{ + const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; + const struct wined3d_gl_info *gl_info = context->gl_info; + CONST DWORD *function = This->baseShader.function; + struct shader_glsl_ctx_priv priv_ctx; + + /* Create the hw GLSL shader object and assign it as the shader->prgId */ + GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); + + memset(&priv_ctx, 0, sizeof(priv_ctx)); + priv_ctx.cur_ps_args = args; + priv_ctx.cur_np2fixup_info = np2fixup_info; + + shader_addline(buffer, "#version 120\n"); + + if (gl_info->supported[ARB_SHADER_TEXTURE_LOD] && reg_maps->usestexldd) + { + shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n"); + } + if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) + { + /* The spec says that it doesn't have to be explicitly enabled, but the nvidia + * drivers write a warning if we don't do so + */ + shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n"); + } + if (gl_info->supported[EXT_GPU_SHADER4]) + { + shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n"); + } + + /* Base Declarations */ + shader_generate_glsl_declarations(context, buffer, (IWineD3DBaseShader *)This, reg_maps, &priv_ctx); + + /* Pack 3.0 inputs */ + if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader) + { + shader_glsl_input_pack((IWineD3DPixelShader *) This, buffer, + This->baseShader.input_signature, reg_maps, args->vp_mode); + } + + /* Base Shader Body */ + shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx); + + /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */ + if (reg_maps->shader_version.major < 2) + { + /* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */ + shader_addline(buffer, "gl_FragData[0] = R0;\n"); + } + + if (args->srgb_correction) + { + shader_addline(buffer, "tmp0.xyz = pow(gl_FragData[0].xyz, vec3(srgb_const0.x));\n"); + shader_addline(buffer, "tmp0.xyz = tmp0.xyz * vec3(srgb_const0.y) - vec3(srgb_const0.z);\n"); + shader_addline(buffer, "tmp1.xyz = gl_FragData[0].xyz * vec3(srgb_const0.w);\n"); + shader_addline(buffer, "bvec3 srgb_compare = lessThan(gl_FragData[0].xyz, vec3(srgb_const1.x));\n"); + shader_addline(buffer, "gl_FragData[0].xyz = mix(tmp0.xyz, tmp1.xyz, vec3(srgb_compare));\n"); + shader_addline(buffer, "gl_FragData[0] = clamp(gl_FragData[0], 0.0, 1.0);\n"); + } + /* Pixel shader < 3.0 do not replace the fog stage. + * This implements linear fog computation and blending. + * TODO: non linear fog + * NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but + * -1/(e-s) and e/(e-s) respectively. + */ + if (reg_maps->shader_version.major < 3) + { + switch(args->fog) { + case FOG_OFF: break; + case FOG_LINEAR: + shader_addline(buffer, "float fogstart = -1.0 / (gl_Fog.end - gl_Fog.start);\n"); + shader_addline(buffer, "float fogend = gl_Fog.end * -fogstart;\n"); + shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * fogstart + fogend, 0.0, 1.0);\n"); + shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, Fog);\n"); + break; + case FOG_EXP: + /* Fog = e^(-gl_Fog.density * gl_FogFragCoord) */ + shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n"); + shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n"); + shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, Fog);\n"); + break; + case FOG_EXP2: + /* Fog = e^(-(gl_Fog.density * gl_FogFragCoord)^2) */ + shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n"); + shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n"); + shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, Fog);\n"); + break; + } + } + + shader_addline(buffer, "}\n"); + + TRACE("Compiling shader object %p\n", (void *)(uintptr_t)shader_obj); + GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL)); + GL_EXTCALL(glCompileShaderARB(shader_obj)); + shader_glsl_validate_compile_link(gl_info, shader_obj, FALSE); + + /* Store the shader object */ + return shader_obj; +} + +/* GL locking is done by the caller */ +#ifdef VBOX_WITH_VMSVGA +static GLhandleARB shader_glsl_generate_vshader(const struct wined3d_context *context, +#else +static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context, +#endif + struct wined3d_shader_buffer *buffer, IWineD3DVertexShaderImpl *This, + const struct vs_compile_args *args) +{ + const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; + const struct wined3d_gl_info *gl_info = context->gl_info; + CONST DWORD *function = This->baseShader.function; + struct shader_glsl_ctx_priv priv_ctx; + + /* Create the hw GLSL shader program and assign it as the shader->prgId */ + GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); + + shader_addline(buffer, "#version 120\n"); + + if (gl_info->supported[EXT_GPU_SHADER4]) + { + shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n"); + } + + memset(&priv_ctx, 0, sizeof(priv_ctx)); + priv_ctx.cur_vs_args = args; + + /* Base Declarations */ + shader_generate_glsl_declarations(context, buffer, (IWineD3DBaseShader *)This, reg_maps, &priv_ctx); + + /* Base Shader Body */ + shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function, &priv_ctx); + + /* Unpack 3.0 outputs */ + if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n"); + else shader_addline(buffer, "order_ps_input();\n"); + + /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used + * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), + * the fog frag coord is thrown away. If the fog frag coord is used, but not written by + * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0) + */ + if(args->fog_src == VS_FOG_Z) { + shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n"); + } else if (!reg_maps->fog) { + shader_addline(buffer, "gl_FogFragCoord = 0.0;\n"); + } + + /* Write the final position. + * + * OpenGL coordinates specify the center of the pixel while d3d coords specify + * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains + * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x + * contains 1.0 to allow a mad. + */ + shader_addline(buffer, "gl_Position.y = gl_Position.y * posFixup.y;\n"); + shader_addline(buffer, "gl_Position.xy += posFixup.zw * gl_Position.ww;\n"); + if(args->clip_enabled) { + shader_addline(buffer, "gl_ClipVertex = gl_Position;\n"); + } + + /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c + * + * Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, shaders are run + * before the homogeneous divide, so we have to take the w into account: z = ((z / w) * 2 - 1) * w, + * which is the same as z = z * 2 - w. + */ + shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"); + + shader_addline(buffer, "}\n"); + + TRACE("Compiling shader object %p\n", (void *)(uintptr_t)shader_obj); + GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL)); + GL_EXTCALL(glCompileShaderARB(shader_obj)); + shader_glsl_validate_compile_link(gl_info, shader_obj, FALSE); + + return shader_obj; +} + +static GLhandleARB find_glsl_pshader(const struct wined3d_context *context, + struct wined3d_shader_buffer *buffer, IWineD3DPixelShaderImpl *shader, + const struct ps_compile_args *args, + UINT *inp2fixup_info + ) +{ + UINT i; + DWORD new_size; + struct glsl_ps_compiled_shader *new_array; + struct glsl_pshader_private *shader_data; + struct ps_np2fixup_info *np2fixup = NULL; + GLhandleARB ret; + + if (!shader->baseShader.backend_data) + { + shader->baseShader.backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data)); + if (!shader->baseShader.backend_data) + { + ERR("Failed to allocate backend data.\n"); + return 0; + } + } + shader_data = shader->baseShader.backend_data; + + /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), + * so a linear search is more performant than a hashmap or a binary search + * (cache coherency etc) + */ + for(i = 0; i < shader_data->num_gl_shaders; i++) { + if(shader_data->gl_shaders[i].context==context + && memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)) == 0) { + if(args->np2_fixup) { + *inp2fixup_info = i; + } + return shader_data->gl_shaders[i].prgId; + } + } + + TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); + if(shader_data->shader_array_size == shader_data->num_gl_shaders) { + if (shader_data->num_gl_shaders) + { + new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); + new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders, + new_size * sizeof(*shader_data->gl_shaders)); + } else { + new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders)); + new_size = 1; + } + + if(!new_array) { + ERR("Out of memory\n"); + return 0; + } + shader_data->gl_shaders = new_array; + shader_data->shader_array_size = new_size; + } + + shader_data->gl_shaders[shader_data->num_gl_shaders].context = context; + shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args; + + memset(&shader_data->gl_shaders[shader_data->num_gl_shaders].np2fixup, 0, sizeof(struct ps_np2fixup_info)); + if (args->np2_fixup) np2fixup = &shader_data->gl_shaders[shader_data->num_gl_shaders].np2fixup; + + pixelshader_update_samplers(&shader->baseShader.reg_maps, + ((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures); + + shader_buffer_clear(buffer); + ret = shader_glsl_generate_pshader(context, buffer, shader, args, np2fixup); + *inp2fixup_info = shader_data->num_gl_shaders; + shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret; + + return ret; +} + +static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new, + const DWORD use_map) { + if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE; + if((stored->clip_enabled) != new->clip_enabled) return FALSE; + return stored->fog_src == new->fog_src; +} + +static GLhandleARB find_glsl_vshader(const struct wined3d_context *context, + struct wined3d_shader_buffer *buffer, IWineD3DVertexShaderImpl *shader, + const struct vs_compile_args *args) +{ + UINT i; + DWORD new_size; + struct glsl_vs_compiled_shader *new_array; + DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map; + struct glsl_vshader_private *shader_data; + GLhandleARB ret; + + if (!shader->baseShader.backend_data) + { + shader->baseShader.backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data)); + if (!shader->baseShader.backend_data) + { + ERR("Failed to allocate backend data.\n"); + return 0; + } + } + shader_data = shader->baseShader.backend_data; + + /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), + * so a linear search is more performant than a hashmap or a binary search + * (cache coherency etc) + */ + for(i = 0; i < shader_data->num_gl_shaders; i++) { + if(shader_data->gl_shaders[i].context==context + && vs_args_equal(&shader_data->gl_shaders[i].args, args, use_map)) { + return shader_data->gl_shaders[i].prgId; + } + } + + TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); + + if(shader_data->shader_array_size == shader_data->num_gl_shaders) { + if (shader_data->num_gl_shaders) + { + new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); + new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders, + new_size * sizeof(*shader_data->gl_shaders)); + } else { + new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders)); + new_size = 1; + } + + if(!new_array) { + ERR("Out of memory\n"); + return 0; + } + shader_data->gl_shaders = new_array; + shader_data->shader_array_size = new_size; + } + + shader_data->gl_shaders[shader_data->num_gl_shaders].context = context; + shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args; + + shader_buffer_clear(buffer); + ret = shader_glsl_generate_vshader(context, buffer, shader, args); + shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret; + + return ret; +} + +/** Sets the GLSL program ID for the given pixel and vertex shader combination. + * It sets the programId on the current StateBlock (because it should be called + * inside of the DrawPrimitive() part of the render loop). + * + * If a program for the given combination does not exist, create one, and store + * the program in the hash table. If it creates a program, it will link the + * given objects, too. + */ + +/* GL locking is done by the caller */ +static void set_glsl_shader_program(const struct wined3d_context *context, + IWineD3DDeviceImpl *device, BOOL a_use_ps, BOOL a_use_vs) +{ + IWineD3DVertexShader *vshader = a_use_vs ? device->stateBlock->vertexShader : NULL; + IWineD3DPixelShader *pshader = a_use_ps ? device->stateBlock->pixelShader : NULL; + const struct wined3d_gl_info *gl_info = context->gl_info; + struct shader_glsl_priv *priv = device->shader_priv; + struct glsl_shader_prog_link *entry = NULL; + GLhandleARB programId = 0; + GLhandleARB reorder_shader_id = 0; + unsigned int i; + char glsl_name[8]; + struct ps_compile_args ps_compile_args; + struct vs_compile_args vs_compile_args; + + if (vshader) find_vs_compile_args((IWineD3DVertexShaderImpl *)vshader, device->stateBlock, &vs_compile_args); + if (pshader) find_ps_compile_args((IWineD3DPixelShaderImpl *)pshader, device->stateBlock, &ps_compile_args); + + entry = get_glsl_program_entry(priv, vshader, pshader, &vs_compile_args, &ps_compile_args, context); + if (entry) { + priv->glsl_program = entry; + return; + } + + /* If we get to this point, then no matching program exists, so we create one */ + programId = GL_EXTCALL(glCreateProgramObjectARB()); + TRACE("Created new GLSL shader program %p\n", (void *)(uintptr_t)programId); + + /* Create the entry */ + entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct glsl_shader_prog_link)); + entry->context = context; + entry->programId = programId; + entry->vshader = vshader; + entry->pshader = pshader; + entry->vs_args = vs_compile_args; + entry->ps_args = ps_compile_args; + entry->constant_version = 0; + WINEFIXUPINFO_INIT(entry); + /* Add the hash table entry */ + add_glsl_program_entry(priv, entry); + + /* Set the current program */ + priv->glsl_program = entry; + + /* Attach GLSL vshader */ + if (vshader) + { + GLhandleARB vshader_id = find_glsl_vshader(context, &priv->shader_buffer, + (IWineD3DVertexShaderImpl *)vshader, &vs_compile_args); + WORD map = ((IWineD3DBaseShaderImpl *)vshader)->baseShader.reg_maps.input_registers; + char tmp_name[10]; + + reorder_shader_id = generate_param_reorder_function(&priv->shader_buffer, vshader, pshader, gl_info); + TRACE("Attaching GLSL shader object %p to program %p\n", (void *)(uintptr_t)reorder_shader_id, (void *)(uintptr_t)programId); + GL_EXTCALL(glAttachObjectARB(programId, reorder_shader_id)); + checkGLcall("glAttachObjectARB"); + /* Flag the reorder function for deletion, then it will be freed automatically when the program + * is destroyed + */ + GL_EXTCALL(glDeleteObjectARB(reorder_shader_id)); + + TRACE("Attaching GLSL shader object %p to program %p\n", (void *)(uintptr_t)vshader_id, (void *)(uintptr_t)programId); + GL_EXTCALL(glAttachObjectARB(programId, vshader_id)); + checkGLcall("glAttachObjectARB"); + + /* Bind vertex attributes to a corresponding index number to match + * the same index numbers as ARB_vertex_programs (makes loading + * vertex attributes simpler). With this method, we can use the + * exact same code to load the attributes later for both ARB and + * GLSL shaders. + * + * We have to do this here because we need to know the Program ID + * in order to make the bindings work, and it has to be done prior + * to linking the GLSL program. */ + for (i = 0; map; map >>= 1, ++i) + { + if (!(map & 1)) continue; + + snprintf(tmp_name, sizeof(tmp_name), "attrib%u", i); + GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name)); + } + checkGLcall("glBindAttribLocationARB"); + + list_add_head(&((IWineD3DBaseShaderImpl *)vshader)->baseShader.linked_programs, &entry->vshader_entry); + } +#ifdef VBOX_WITH_VMSVGA + else + if (device->strided_streams.position_transformed) + { + GLhandleARB passthrough_vshader_id; + + passthrough_vshader_id = generate_passthrough_vshader(gl_info); + TRACE("Attaching GLSL shader object %p to program %p\n", (void *)(uintptr_t)passthrough_vshader_id, (void *)(uintptr_t)programId); + GL_EXTCALL(glAttachObjectARB(programId, passthrough_vshader_id)); + checkGLcall("glAttachObjectARB"); + /* Flag the reorder function for deletion, then it will be freed automatically when the program + * is destroyed + */ + GL_EXTCALL(glDeleteObjectARB(passthrough_vshader_id)); + } +#endif + + + /* Attach GLSL pshader */ + if (pshader) + { + GLhandleARB pshader_id = find_glsl_pshader(context, &priv->shader_buffer, + (IWineD3DPixelShaderImpl *)pshader, &ps_compile_args, + &entry->inp2Fixup_info + ); + TRACE("Attaching GLSL shader object %p to program %p\n", (void *)(uintptr_t)pshader_id, (void *)(uintptr_t)programId); + GL_EXTCALL(glAttachObjectARB(programId, pshader_id)); + checkGLcall("glAttachObjectARB"); + + list_add_head(&((IWineD3DBaseShaderImpl *)pshader)->baseShader.linked_programs, &entry->pshader_entry); + } + + /* Link the program */ + TRACE("Linking GLSL shader program %p\n", (void *)(uintptr_t)programId); + GL_EXTCALL(glLinkProgramARB(programId)); + shader_glsl_validate_compile_link(gl_info, programId, TRUE); + + entry->vuniformF_locations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(GLhandleARB) * gl_info->limits.glsl_vs_float_constants); + for (i = 0; i < gl_info->limits.glsl_vs_float_constants; ++i) + { + snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i); + entry->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); + } + for (i = 0; i < MAX_CONST_I; ++i) + { + snprintf(glsl_name, sizeof(glsl_name), "VI[%i]", i); + entry->vuniformI_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); + } + entry->puniformF_locations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(GLhandleARB) * gl_info->limits.glsl_ps_float_constants); + for (i = 0; i < gl_info->limits.glsl_ps_float_constants; ++i) + { + snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i); + entry->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); + } + for (i = 0; i < MAX_CONST_I; ++i) + { + snprintf(glsl_name, sizeof(glsl_name), "PI[%i]", i); + entry->puniformI_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); + } + + if(pshader) { + char name[32]; + + for(i = 0; i < MAX_TEXTURES; i++) { + sprintf(name, "bumpenvmat%u", i); + entry->bumpenvmat_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); + sprintf(name, "luminancescale%u", i); + entry->luminancescale_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); + sprintf(name, "luminanceoffset%u", i); + entry->luminanceoffset_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); + } + + if (ps_compile_args.np2_fixup) { + if (WINEFIXUPINFO_ISVALID(entry)) { + entry->np2Fixup_location = GL_EXTCALL(glGetUniformLocationARB(programId, "PsamplerNP2Fixup")); + } else { + FIXME("NP2 texcoord fixup needed for this pixelshader, but no fixup uniform found.\n"); + } + } + } + + entry->posFixup_location = GL_EXTCALL(glGetUniformLocationARB(programId, "posFixup")); + entry->ycorrection_location = GL_EXTCALL(glGetUniformLocationARB(programId, "ycorrection")); + checkGLcall("Find glsl program uniform locations"); + + if (pshader + && ((IWineD3DPixelShaderImpl *)pshader)->baseShader.reg_maps.shader_version.major >= 3 + && ((IWineD3DPixelShaderImpl *)pshader)->declared_in_count > vec4_varyings(3, gl_info)) + { + TRACE("Shader %p needs vertex color clamping disabled\n", (void *)(uintptr_t)programId); + entry->vertex_color_clamp = GL_FALSE; + } else { + entry->vertex_color_clamp = GL_FIXED_ONLY_ARB; + } + + /* Set the shader to allow uniform loading on it */ + GL_EXTCALL(glUseProgramObjectARB(programId)); + checkGLcall("glUseProgramObjectARB(programId)"); + +#ifdef DEBUG_misha + { + GLint programIdTest = -1; + glGetIntegerv(GL_CURRENT_PROGRAM, &programIdTest); + Assert(programIdTest == programId); + } +#endif + + /* Load the vertex and pixel samplers now. The function that finds the mappings makes sure + * that it stays the same for each vertexshader-pixelshader pair(=linked glsl program). If + * a pshader with fixed function pipeline is used there are no vertex samplers, and if a + * vertex shader with fixed function pixel processing is used we make sure that the card + * supports enough samplers to allow the max number of vertex samplers with all possible + * fixed function fragment processing setups. So once the program is linked these samplers + * won't change. + */ + if (vshader) shader_glsl_load_vsamplers(gl_info, device->texUnitMap, programId); + if (pshader) shader_glsl_load_psamplers(gl_info, device->texUnitMap, programId); + + /* If the local constants do not have to be loaded with the environment constants, + * load them now to have them hardcoded in the GLSL program. This saves some CPU cycles + * later + */ + if (pshader && !((IWineD3DBaseShaderImpl *)pshader)->baseShader.load_local_constsF) + { + hardcode_local_constants((IWineD3DBaseShaderImpl *) pshader, gl_info, programId, 'P'); + } + if (vshader && !((IWineD3DBaseShaderImpl *)vshader)->baseShader.load_local_constsF) + { + hardcode_local_constants((IWineD3DBaseShaderImpl *) vshader, gl_info, programId, 'V'); + } +} + +/* GL locking is done by the caller */ +static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type) +{ + GLhandleARB program_id; + GLhandleARB vshader_id, pshader_id; + static const char *blt_vshader[] = + { + "#version 120\n" + "void main(void)\n" + "{\n" + " gl_Position = gl_Vertex;\n" + " gl_FrontColor = vec4(1.0);\n" + " gl_TexCoord[0] = gl_MultiTexCoord0;\n" + "}\n" + }; + + static const char *blt_pshaders[tex_type_count] = + { + /* tex_1d */ + NULL, + /* tex_2d */ + "#version 120\n" + "uniform sampler2D sampler;\n" + "void main(void)\n" + "{\n" + " gl_FragDepth = texture2D(sampler, gl_TexCoord[0].xy).x;\n" + "}\n", + /* tex_3d */ + NULL, + /* tex_cube */ + "#version 120\n" + "uniform samplerCube sampler;\n" + "void main(void)\n" + "{\n" + " gl_FragDepth = textureCube(sampler, gl_TexCoord[0].xyz).x;\n" + "}\n", + /* tex_rect */ + "#version 120\n" + "#extension GL_ARB_texture_rectangle : enable\n" + "uniform sampler2DRect sampler;\n" + "void main(void)\n" + "{\n" + " gl_FragDepth = texture2DRect(sampler, gl_TexCoord[0].xy).x;\n" + "}\n", + }; + + if (!blt_pshaders[tex_type]) + { + FIXME("tex_type %#x not supported\n", tex_type); + tex_type = tex_2d; + } + + vshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); + GL_EXTCALL(glShaderSourceARB(vshader_id, 1, blt_vshader, NULL)); + GL_EXTCALL(glCompileShaderARB(vshader_id)); + shader_glsl_validate_compile_link(gl_info, vshader_id, FALSE); + + pshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); + GL_EXTCALL(glShaderSourceARB(pshader_id, 1, &blt_pshaders[tex_type], NULL)); + GL_EXTCALL(glCompileShaderARB(pshader_id)); + + shader_glsl_validate_compile_link(gl_info, vshader_id, FALSE); + + program_id = GL_EXTCALL(glCreateProgramObjectARB()); + GL_EXTCALL(glAttachObjectARB(program_id, vshader_id)); + GL_EXTCALL(glAttachObjectARB(program_id, pshader_id)); + GL_EXTCALL(glLinkProgramARB(program_id)); + shader_glsl_validate_compile_link(gl_info, program_id, TRUE); + + /* Once linked we can mark the shaders for deletion. They will be deleted once the program + * is destroyed + */ + GL_EXTCALL(glDeleteObjectARB(vshader_id)); + GL_EXTCALL(glDeleteObjectARB(pshader_id)); + return program_id; +} + +/* GL locking is done by the caller */ +static void shader_glsl_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + IWineD3DDeviceImpl *device = context_get_device(context); + struct shader_glsl_priv *priv = device->shader_priv; + GLhandleARB program_id = 0; + GLenum old_vertex_color_clamp, current_vertex_color_clamp; + + old_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vertex_color_clamp : GL_FIXED_ONLY_ARB; + + if (useVS || usePS) set_glsl_shader_program(context, device, usePS, useVS); + else priv->glsl_program = NULL; + + current_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vertex_color_clamp : GL_FIXED_ONLY_ARB; + + if (old_vertex_color_clamp != current_vertex_color_clamp) + { + if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT]) + { + GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, current_vertex_color_clamp)); + checkGLcall("glClampColorARB"); + } + else + { + FIXME("vertex color clamp needs to be changed, but extension not supported.\n"); + } + } + + program_id = priv->glsl_program ? priv->glsl_program->programId : 0; + if (program_id) TRACE("Using GLSL program %p\n", (void *)(uintptr_t)program_id); + GL_EXTCALL(glUseProgramObjectARB(program_id)); + checkGLcall("glUseProgramObjectARB"); +#ifdef DEBUG_misha + { + GLint programIdTest = -1; + glGetIntegerv(GL_CURRENT_PROGRAM, &programIdTest); + Assert(programIdTest == program_id); + } +#endif + + /* In case that NP2 texcoord fixup data is found for the selected program, trigger a reload of the + * constants. This has to be done because it can't be guaranteed that sampler() (from state.c) is + * called between selecting the shader and using it, which results in wrong fixup for some frames. */ + if (priv->glsl_program && WINEFIXUPINFO_ISVALID(priv->glsl_program)) + { + shader_glsl_load_np2fixup_constants((IWineD3DDevice *)device, usePS, useVS); + } +} + +/* GL locking is done by the caller */ +static void shader_glsl_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + struct shader_glsl_priv *priv = This->shader_priv; + GLhandleARB *blt_program = &priv->depth_blt_program[tex_type]; + + if (!*blt_program) { + GLint loc; + *blt_program = create_glsl_blt_shader(gl_info, tex_type); + loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "sampler")); + GL_EXTCALL(glUseProgramObjectARB(*blt_program)); +#ifdef DEBUG_misha + { + GLint programIdTest = -1; + glGetIntegerv(GL_CURRENT_PROGRAM, &programIdTest); + Assert(programIdTest == *blt_program); + } +#endif + GL_EXTCALL(glUniform1iARB(loc, 0)); + } else { + GL_EXTCALL(glUseProgramObjectARB(*blt_program)); +#ifdef DEBUG_misha + { + GLint programIdTest = -1; + glGetIntegerv(GL_CURRENT_PROGRAM, &programIdTest); + Assert(programIdTest == *blt_program); + } +#endif + } +} + +/* GL locking is done by the caller */ +static void shader_glsl_deselect_depth_blt(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + struct shader_glsl_priv *priv = This->shader_priv; + GLhandleARB program_id; + + program_id = priv->glsl_program ? priv->glsl_program->programId : 0; + if (program_id) TRACE("Using GLSL program %p\n", (void *)(uintptr_t)program_id); + + GL_EXTCALL(glUseProgramObjectARB(program_id)); + checkGLcall("glUseProgramObjectARB"); +#ifdef DEBUG_misha + { + GLint programIdTest = -1; + glGetIntegerv(GL_CURRENT_PROGRAM, &programIdTest); + Assert(programIdTest == program_id); + } +#endif +} + +static void shader_glsl_destroy(IWineD3DBaseShader *iface) { + const struct list *linked_programs; + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) iface; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; + struct shader_glsl_priv *priv = device->shader_priv; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + + /* Note: Do not use QueryInterface here to find out which shader type this is because this code + * can be called from IWineD3DBaseShader::Release + */ + char pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type); + + if(pshader) { + struct glsl_pshader_private *shader_data; + shader_data = This->baseShader.backend_data; + if(!shader_data || shader_data->num_gl_shaders == 0) + { + HeapFree(GetProcessHeap(), 0, shader_data); + This->baseShader.backend_data = NULL; + return; + } + + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + gl_info = context->gl_info; + + if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->pshader == iface) + { + ENTER_GL(); + shader_glsl_select(context, FALSE, FALSE); + LEAVE_GL(); + } + } else { + struct glsl_vshader_private *shader_data; + shader_data = This->baseShader.backend_data; + if(!shader_data || shader_data->num_gl_shaders == 0) + { + HeapFree(GetProcessHeap(), 0, shader_data); + This->baseShader.backend_data = NULL; + return; + } + + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + gl_info = context->gl_info; + + if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->vshader == iface) + { + ENTER_GL(); + shader_glsl_select(context, FALSE, FALSE); + LEAVE_GL(); + } + } + + linked_programs = &This->baseShader.linked_programs; + + TRACE("Deleting linked programs\n"); + if (linked_programs->next) { + struct glsl_shader_prog_link *entry, *entry2; + + ENTER_GL(); + if(pshader) { + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) { + delete_glsl_program_entry(priv, gl_info, entry); + } + } else { + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, vshader_entry) { + delete_glsl_program_entry(priv, gl_info, entry); + } + } + LEAVE_GL(); + } + + if(pshader) { + UINT i; + struct glsl_pshader_private *shader_data = This->baseShader.backend_data; + + ENTER_GL(); + for(i = 0; i < shader_data->num_gl_shaders; i++) { + if (shader_data->gl_shaders[i].context==context_get_current()) + { + TRACE("deleting pshader %p\n", (void *)(uintptr_t)shader_data->gl_shaders[i].prgId); + GL_EXTCALL(glDeleteObjectARB(shader_data->gl_shaders[i].prgId)); + checkGLcall("glDeleteObjectARB"); + } + else + { + WARN("Attempting to delete pshader %p created in ctx %p from ctx %p\n", + (void *)(uintptr_t)shader_data->gl_shaders[i].prgId, shader_data->gl_shaders[i].context, context_get_current()); + } + } + LEAVE_GL(); + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders); + } + else + { + UINT i; + struct glsl_vshader_private *shader_data = This->baseShader.backend_data; + + ENTER_GL(); + for(i = 0; i < shader_data->num_gl_shaders; i++) { + if (shader_data->gl_shaders[i].context==context_get_current()) + { + TRACE("deleting vshader %p\n", (void *)(uintptr_t)shader_data->gl_shaders[i].prgId); + GL_EXTCALL(glDeleteObjectARB(shader_data->gl_shaders[i].prgId)); + checkGLcall("glDeleteObjectARB"); + } + else + { + WARN("Attempting to delete vshader %p created in ctx %p from ctx %p\n", + (void *)(uintptr_t)shader_data->gl_shaders[i].prgId, shader_data->gl_shaders[i].context, context_get_current()); + } + } + LEAVE_GL(); + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders); + } + + HeapFree(GetProcessHeap(), 0, This->baseShader.backend_data); + This->baseShader.backend_data = NULL; + + context_release(context); +} + +static int glsl_program_key_compare(const void *key, const struct wine_rb_entry *entry) +{ + const glsl_program_key_t *k = key; + const struct glsl_shader_prog_link *prog = WINE_RB_ENTRY_VALUE(entry, + const struct glsl_shader_prog_link, program_lookup_entry); + int cmp; + + if (k->context > prog->context) return 1; + else if (k->context < prog->context) return -1; + + if (k->vshader > prog->vshader) return 1; + else if (k->vshader < prog->vshader) return -1; + + if (k->pshader > prog->pshader) return 1; + else if (k->pshader < prog->pshader) return -1; + + if (k->vshader && (cmp = memcmp(&k->vs_args, &prog->vs_args, sizeof(prog->vs_args)))) return cmp; + if (k->pshader && (cmp = memcmp(&k->ps_args, &prog->ps_args, sizeof(prog->ps_args)))) return cmp; + + return 0; +} + +static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count) +{ +#ifndef VBOX + SIZE_T size = (constant_count + 1) * sizeof(*heap->entries) + constant_count * sizeof(*heap->positions); + void *mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); +#else + SIZE_T size; + void *mem; + + /* Don't trash the heap if the input is bogus. */ + if (constant_count == 0) + constant_count = 1; + + size = (constant_count + 1) * sizeof(*heap->entries) + constant_count * sizeof(*heap->positions); + mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); +#endif + + if (!mem) + { + ERR("Failed to allocate memory\n"); + return FALSE; + } + + heap->entries = mem; + heap->entries[1].version = 0; + heap->positions = (unsigned int *)(heap->entries + constant_count + 1); + heap->size = 1; + + return TRUE; +} + +static void constant_heap_free(struct constant_heap *heap) +{ + HeapFree(GetProcessHeap(), 0, heap->entries); +} + +static const struct wine_rb_functions wined3d_glsl_program_rb_functions = +{ + wined3d_rb_alloc, + wined3d_rb_realloc, + wined3d_rb_free, + glsl_program_key_compare, +}; + +static HRESULT shader_glsl_alloc(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv)); + SIZE_T stack_size = wined3d_log2i(max(gl_info->limits.glsl_vs_float_constants, + gl_info->limits.glsl_ps_float_constants)) + 1; + + if (!shader_buffer_init(&priv->shader_buffer)) + { + ERR("Failed to initialize shader buffer.\n"); + goto fail; + } + + priv->stack = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size * sizeof(*priv->stack)); + if (!priv->stack) + { + ERR("Failed to allocate memory.\n"); + goto fail; + } + if (!constant_heap_init(&priv->vconst_heap, gl_info->limits.glsl_vs_float_constants)) + { + ERR("Failed to initialize vertex shader constant heap\n"); + goto fail; + } + if (!constant_heap_init(&priv->pconst_heap, gl_info->limits.glsl_ps_float_constants)) + { + ERR("Failed to initialize pixel shader constant heap\n"); + goto fail; + } + + if (wine_rb_init(&priv->program_lookup, &wined3d_glsl_program_rb_functions) == -1) + { + ERR("Failed to initialize rbtree.\n"); + goto fail; + } + + priv->next_constant_version = 1; + + This->shader_priv = priv; + return WINED3D_OK; + +fail: + constant_heap_free(&priv->pconst_heap); + constant_heap_free(&priv->vconst_heap); + HeapFree(GetProcessHeap(), 0, priv->stack); + shader_buffer_free(&priv->shader_buffer); + HeapFree(GetProcessHeap(), 0, priv); + return E_OUTOFMEMORY; +} + +/* Context activation is done by the caller. */ +static void shader_glsl_free(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + struct shader_glsl_priv *priv = This->shader_priv; + int i; + + ENTER_GL(); + for (i = 0; i < tex_type_count; ++i) + { + if (priv->depth_blt_program[i]) + { + GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program[i])); + } + } + LEAVE_GL(); + + wine_rb_destroy(&priv->program_lookup, NULL, NULL); + constant_heap_free(&priv->pconst_heap); + constant_heap_free(&priv->vconst_heap); + HeapFree(GetProcessHeap(), 0, priv->stack); + shader_buffer_free(&priv->shader_buffer); + + HeapFree(GetProcessHeap(), 0, This->shader_priv); + This->shader_priv = NULL; +} + +static BOOL shader_glsl_dirty_const(IWineD3DDevice *iface) { + /* TODO: GL_EXT_bindable_uniform can be used to share constants across shaders */ + return FALSE; +} + +static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *pCaps) +{ + /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati + * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support based + * on the version of NV_vertex_program. + * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not + * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it + * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number + * of native instructions, so use that here. For more info see the pixel shader versioning code below. + */ + if ((gl_info->supported[NV_VERTEX_PROGRAM2] && !gl_info->supported[NV_VERTEX_PROGRAM3]) + || gl_info->limits.arb_ps_instructions <= 512 + || gl_info->limits.glsl_vs_float_constants < 256) + pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0); + else + pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0); + TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (pCaps->VertexShaderVersion >> 8) & 0xff, pCaps->VertexShaderVersion & 0xff); + pCaps->MaxVertexShaderConst = gl_info->limits.glsl_vs_float_constants; + + /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b. + * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed + * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment + * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info + * in max native instructions. Intel and others also offer the info in this extension but they + * don't support GLSL (at least on Windows). + * + * PS2.0 requires at least 96 instructions, 2.0a/2.0b go up to 512. Assume that if the number + * of instructions is 512 or less we have to do with ps2.0 hardware. + * NOTE: ps3.0 hardware requires 512 or more instructions but ati and nvidia offer 'enough' (1024 vs 4096) on their most basic ps3.0 hardware. + */ + if ((gl_info->supported[NV_FRAGMENT_PROGRAM] && !gl_info->supported[NV_FRAGMENT_PROGRAM2]) + || gl_info->limits.arb_ps_instructions <= 512 + || gl_info->limits.glsl_vs_float_constants < 256) + pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0); + else + pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0); + + pCaps->MaxPixelShaderConst = gl_info->limits.glsl_ps_float_constants; + + /* FIXME: The following line is card dependent. -8.0 to 8.0 is the + * Direct3D minimum requirement. + * + * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude" + * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here? + * + * The problem is that the refrast clamps temporary results in the shader to + * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here, + * then applications may miss the clamping behavior. On the other hand, if it is smaller, + * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't + * offer a way to query this. + */ + pCaps->PixelShader1xMaxValue = 8.0; + TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (pCaps->PixelShaderVersion >> 8) & 0xff, pCaps->PixelShaderVersion & 0xff); + + pCaps->VSClipping = TRUE; +} + +static BOOL shader_glsl_color_fixup_supported(struct color_fixup_desc fixup) +{ + if (TRACE_ON(d3d_shader) && TRACE_ON(d3d)) + { + TRACE("Checking support for fixup:\n"); + dump_color_fixup_desc(fixup); + } + + /* We support everything except YUV conversions. */ + if (!is_complex_fixup(fixup)) + { + TRACE("[OK]\n"); + return TRUE; + } + + TRACE("[FAILED]\n"); + return FALSE; +} + +static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TABLE_SIZE] = +{ + /* WINED3DSIH_ABS */ shader_glsl_map2gl, + /* WINED3DSIH_ADD */ shader_glsl_arith, + /* WINED3DSIH_BEM */ shader_glsl_bem, + /* WINED3DSIH_BREAK */ shader_glsl_break, + /* WINED3DSIH_BREAKC */ shader_glsl_breakc, + /* WINED3DSIH_BREAKP */ NULL, + /* WINED3DSIH_CALL */ shader_glsl_call, + /* WINED3DSIH_CALLNZ */ shader_glsl_callnz, + /* WINED3DSIH_CMP */ shader_glsl_cmp, + /* WINED3DSIH_CND */ shader_glsl_cnd, + /* WINED3DSIH_CRS */ shader_glsl_cross, + /* WINED3DSIH_CUT */ NULL, + /* WINED3DSIH_DCL */ NULL, + /* WINED3DSIH_DEF */ NULL, + /* WINED3DSIH_DEFB */ NULL, + /* WINED3DSIH_DEFI */ NULL, + /* WINED3DSIH_DP2ADD */ shader_glsl_dp2add, + /* WINED3DSIH_DP3 */ shader_glsl_dot, + /* WINED3DSIH_DP4 */ shader_glsl_dot, + /* WINED3DSIH_DST */ shader_glsl_dst, + /* WINED3DSIH_DSX */ shader_glsl_map2gl, + /* WINED3DSIH_DSY */ shader_glsl_map2gl, + /* WINED3DSIH_ELSE */ shader_glsl_else, + /* WINED3DSIH_EMIT */ NULL, + /* WINED3DSIH_ENDIF */ shader_glsl_end, + /* WINED3DSIH_ENDLOOP */ shader_glsl_end, + /* WINED3DSIH_ENDREP */ shader_glsl_end, + /* WINED3DSIH_EXP */ shader_glsl_map2gl, + /* WINED3DSIH_EXPP */ shader_glsl_expp, + /* WINED3DSIH_FRC */ shader_glsl_map2gl, + /* WINED3DSIH_IADD */ NULL, + /* WINED3DSIH_IF */ shader_glsl_if, + /* WINED3DSIH_IFC */ shader_glsl_ifc, + /* WINED3DSIH_IGE */ NULL, + /* WINED3DSIH_LABEL */ shader_glsl_label, + /* WINED3DSIH_LIT */ shader_glsl_lit, + /* WINED3DSIH_LOG */ shader_glsl_log, + /* WINED3DSIH_LOGP */ shader_glsl_log, + /* WINED3DSIH_LOOP */ shader_glsl_loop, + /* WINED3DSIH_LRP */ shader_glsl_lrp, + /* WINED3DSIH_LT */ NULL, + /* WINED3DSIH_M3x2 */ shader_glsl_mnxn, + /* WINED3DSIH_M3x3 */ shader_glsl_mnxn, + /* WINED3DSIH_M3x4 */ shader_glsl_mnxn, + /* WINED3DSIH_M4x3 */ shader_glsl_mnxn, + /* WINED3DSIH_M4x4 */ shader_glsl_mnxn, + /* WINED3DSIH_MAD */ shader_glsl_mad, + /* WINED3DSIH_MAX */ shader_glsl_map2gl, + /* WINED3DSIH_MIN */ shader_glsl_map2gl, + /* WINED3DSIH_MOV */ shader_glsl_mov, + /* WINED3DSIH_MOVA */ shader_glsl_mov, + /* WINED3DSIH_MUL */ shader_glsl_arith, + /* WINED3DSIH_NOP */ NULL, + /* WINED3DSIH_NRM */ shader_glsl_nrm, + /* WINED3DSIH_PHASE */ NULL, + /* WINED3DSIH_POW */ shader_glsl_pow, + /* WINED3DSIH_RCP */ shader_glsl_rcp, + /* WINED3DSIH_REP */ shader_glsl_rep, + /* WINED3DSIH_RET */ shader_glsl_ret, + /* WINED3DSIH_RSQ */ shader_glsl_rsq, +#ifdef VBOX_WITH_VMSVGA + /* WINED3DSIH_SETP */ shader_glsl_setp, +#else + /* WINED3DSIH_SETP */ NULL, +#endif + /* WINED3DSIH_SGE */ shader_glsl_compare, + /* WINED3DSIH_SGN */ shader_glsl_sgn, + /* WINED3DSIH_SINCOS */ shader_glsl_sincos, + /* WINED3DSIH_SLT */ shader_glsl_compare, + /* WINED3DSIH_SUB */ shader_glsl_arith, + /* WINED3DSIH_TEX */ shader_glsl_tex, + /* WINED3DSIH_TEXBEM */ shader_glsl_texbem, + /* WINED3DSIH_TEXBEML */ shader_glsl_texbem, + /* WINED3DSIH_TEXCOORD */ shader_glsl_texcoord, + /* WINED3DSIH_TEXDEPTH */ shader_glsl_texdepth, + /* WINED3DSIH_TEXDP3 */ shader_glsl_texdp3, + /* WINED3DSIH_TEXDP3TEX */ shader_glsl_texdp3tex, + /* WINED3DSIH_TEXKILL */ shader_glsl_texkill, + /* WINED3DSIH_TEXLDD */ shader_glsl_texldd, + /* WINED3DSIH_TEXLDL */ shader_glsl_texldl, + /* WINED3DSIH_TEXM3x2DEPTH */ shader_glsl_texm3x2depth, + /* WINED3DSIH_TEXM3x2PAD */ shader_glsl_texm3x2pad, + /* WINED3DSIH_TEXM3x2TEX */ shader_glsl_texm3x2tex, + /* WINED3DSIH_TEXM3x3 */ shader_glsl_texm3x3, + /* WINED3DSIH_TEXM3x3DIFF */ NULL, + /* WINED3DSIH_TEXM3x3PAD */ shader_glsl_texm3x3pad, + /* WINED3DSIH_TEXM3x3SPEC */ shader_glsl_texm3x3spec, + /* WINED3DSIH_TEXM3x3TEX */ shader_glsl_texm3x3tex, + /* WINED3DSIH_TEXM3x3VSPEC */ shader_glsl_texm3x3vspec, + /* WINED3DSIH_TEXREG2AR */ shader_glsl_texreg2ar, + /* WINED3DSIH_TEXREG2GB */ shader_glsl_texreg2gb, + /* WINED3DSIH_TEXREG2RGB */ shader_glsl_texreg2rgb, +}; + +static void shader_glsl_handle_instruction(const struct wined3d_shader_instruction *ins) { + SHADER_HANDLER hw_fct; + + /* Select handler */ + hw_fct = shader_glsl_instruction_handler_table[ins->handler_idx]; + + /* Unhandled opcode */ + if (!hw_fct) + { + FIXME("Backend can't handle opcode %#x\n", ins->handler_idx); + return; + } + hw_fct(ins); + + shader_glsl_add_instruction_modifiers(ins); +} + +const shader_backend_t glsl_shader_backend = { + shader_glsl_handle_instruction, + shader_glsl_select, + shader_glsl_select_depth_blt, + shader_glsl_deselect_depth_blt, + shader_glsl_update_float_vertex_constants, + shader_glsl_update_float_pixel_constants, + shader_glsl_load_constants, + shader_glsl_load_np2fixup_constants, + shader_glsl_destroy, + shader_glsl_alloc, + shader_glsl_free, + shader_glsl_dirty_const, + shader_glsl_get_caps, + shader_glsl_color_fixup_supported, +}; + +#if defined(VBOXWINEDBG_SHADERS) || defined(VBOX_WINE_WITH_PROFILE) +void vboxWDbgPrintF(char * szString, ...) +{ + char szBuffer[4096*2] = {0}; + va_list pArgList; + va_start(pArgList, szString); + _vsnprintf(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szString, pArgList); + va_end(pArgList); + + OutputDebugStringA(szBuffer); +} +#endif diff --git a/src/VBox/Devices/Graphics/shaderlib/libWineStub/Makefile.kup b/src/VBox/Devices/Graphics/shaderlib/libWineStub/Makefile.kup new file mode 100644 index 00000000..e69de29b diff --git a/src/VBox/Devices/Graphics/shaderlib/libWineStub/debug.c b/src/VBox/Devices/Graphics/shaderlib/libWineStub/debug.c new file mode 100644 index 00000000..9735cf26 --- /dev/null +++ b/src/VBox/Devices/Graphics/shaderlib/libWineStub/debug.c @@ -0,0 +1,534 @@ +/* + * Management of the debugging channels + * + * Copyright 2000 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include "wine/port.h" + +#include "initguid.h" +#ifdef VBOX +# ifdef _MSC_VER +# include +# else +# include +# endif +# include +# ifdef _MSC_VER +# include +# else +# include +# endif +#else +#include +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include "wine/debug.h" +//#include "wine/library.h" + +#ifdef VBOX_WITH_WDDM +# include +# include +#else +# include +#endif +#include + +#if VBOX_WITH_VMSVGA +/* WINE defines this as inline in its headers, directly accessing a memory location */ +#ifndef RT_OS_WINDOWS +#define GetCurrentThreadId() (1) +#define GetCurrentProcessId() (1) +#endif +#endif + +static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" }; + +#define MAX_DEBUG_OPTIONS 256 + +typedef DECLCALLBACKTYPE(void, FNVBOXWINELOGBACKDOOR,(char* pcszStr)); +typedef FNVBOXWINELOGBACKDOOR *PFNVBOXWINELOGBACKDOOR; +static PFNVBOXWINELOGBACKDOOR vbox_log_backdoor = NULL; +static unsigned char default_flags = (1 << __WINE_DBCL_ERR) | (1 << __WINE_DBCL_FIXME) | (1 << __WINE_DBCL_WARN); +static int nb_debug_options = -1; +static struct __wine_debug_channel debug_options[MAX_DEBUG_OPTIONS]; + +static struct __wine_debug_functions funcs; + +static void debug_init(void); + +static int cmp_name( const void *p1, const void *p2 ) +{ + const char *name = p1; + const struct __wine_debug_channel *chan = p2; + return strcmp( name, chan->name ); +} + +/* get the flags to use for a given channel, possibly setting them too in case of lazy init */ +unsigned char __wine_dbg_get_channel_flags( struct __wine_debug_channel *channel ) +{ + if (nb_debug_options == -1) debug_init(); + + if (nb_debug_options) + { + struct __wine_debug_channel *opt = bsearch( channel->name, debug_options, nb_debug_options, + sizeof(debug_options[0]), cmp_name ); + if (opt) return opt->flags; + } + /* no option for this channel */ + if (channel->flags & (1 << __WINE_DBCL_INIT)) channel->flags = default_flags; + return default_flags; +} + +/* set the flags to use for a given channel; return 0 if the channel is not available to set */ +int __wine_dbg_set_channel_flags( struct __wine_debug_channel *channel, + unsigned char set, unsigned char clear ) +{ + if (nb_debug_options == -1) debug_init(); + + if (nb_debug_options) + { + struct __wine_debug_channel *opt = bsearch( channel->name, debug_options, nb_debug_options, + sizeof(debug_options[0]), cmp_name ); + if (opt) + { + opt->flags = (opt->flags & ~clear) | set; + return 1; + } + } + return 0; +} + +/* add a new debug option at the end of the option list */ +static void add_option( const char *name, unsigned char set, unsigned char clear ) +{ + int min = 0, max = nb_debug_options - 1, pos, res; + + if (!name[0]) /* "all" option */ + { + default_flags = (default_flags & ~clear) | set; + return; + } + if (strlen(name) >= sizeof(debug_options[0].name)) return; + + while (min <= max) + { + pos = (min + max) / 2; + res = strcmp( name, debug_options[pos].name ); + if (!res) + { + debug_options[pos].flags = (debug_options[pos].flags & ~clear) | set; + return; + } + if (res < 0) max = pos - 1; + else min = pos + 1; + } + if (nb_debug_options >= MAX_DEBUG_OPTIONS) return; + + pos = min; + if (pos < nb_debug_options) memmove( &debug_options[pos + 1], &debug_options[pos], + (nb_debug_options - pos) * sizeof(debug_options[0]) ); + strcpy( debug_options[pos].name, name ); + debug_options[pos].flags = (default_flags & ~clear) | set; + nb_debug_options++; +} + +/* parse a set of debugging option specifications and add them to the option list */ +static void parse_options( const char *str ) +{ + char *opt, *next, *options; + unsigned int i; + + if (!(options = strdup(str))) return; + for (opt = options; opt; opt = next) + { + const char *p; + unsigned char set = 0, clear = 0; + + if ((next = strchr( opt, ',' ))) *next++ = 0; + + p = opt + strcspn( opt, "+-" ); + if (!p[0]) p = opt; /* assume it's a debug channel name */ + + if (p > opt) + { + for (i = 0; i < sizeof(debug_classes)/sizeof(debug_classes[0]); i++) + { + int len = (int)strlen(debug_classes[i]); + if (len != (p - opt)) continue; + if (!memcmp( opt, debug_classes[i], len )) /* found it */ + { + if (*p == '+') set |= 1 << i; + else clear |= 1 << i; + break; + } + } + if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */ + continue; + } + else + { + if (*p == '-') clear = ~0; + else set = ~0; + } + if (*p == '+' || *p == '-') p++; + if (!p[0]) continue; + + if (!strcmp( p, "all" )) + default_flags = (default_flags & ~clear) | set; + else + add_option( p, set, clear ); + } + free( options ); +} + + +/* print the usage message */ +static void debug_usage(void) +{ + static const char usage[] = + "Syntax of the WINEDEBUG variable:\n" + " WINEDEBUG=[class]+xxx,[class]-yyy,...\n\n" + "Example: WINEDEBUG=+all,warn-heap\n" + " turns on all messages except warning heap messages\n" + "Available message classes: err, warn, fixme, trace\n"; + int res = write( 2, usage, sizeof(usage) - 1 ); + NOREF(res); + exit(1); +} + +#ifndef VBOX_WITH_WDDM +static DECLCALLBACK(void) vbox_log_backdoor_rt(char* pcszStr) +{ + RTLogPrintf("%s", pcszStr); +} +#else +static DECLCALLBACK(void) vbox_log_backdoor_dispmp(char* pcszStr) +{ + VBoxDispMpLoggerLog(pcszStr); +} +#endif +static void vbox_log_v(const char *pszFormat, va_list args) +{ + if (vbox_log_backdoor) + { + static char buf[8092]; + int offset = sprintf(buf, "[0x%lx.0x%lx] Wine Debug: ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId()); + vsprintf(buf + offset, pszFormat, args); + vbox_log_backdoor(buf); + } +} + +/* initialize all options at startup */ +static void debug_init(void) +{ + char *wine_debug; + + if (nb_debug_options != -1) return; /* already initialized */ + nb_debug_options = 0; + if ((wine_debug = getenv("WINEDEBUG"))) + { +#ifndef VBOX_WITH_VMSVGA + Assert(0); +#endif + if (!strcmp( wine_debug, "help" )) + debug_usage(); + else if (getenv("WINEDEBUG_BACKDOOR")) + { +#ifdef VBOX_WITH_WDDM + int rc = VBoxDispMpLoggerInit(); + if (RT_SUCCESS(rc)) + vbox_log_backdoor = vbox_log_backdoor_dispmp; +// else +#else + vbox_log_backdoor = vbox_log_backdoor_rt; +#endif + } + parse_options( wine_debug ); + } +} + +/* varargs wrapper for funcs.dbg_vprintf */ +int wine_dbg_printf( const char *format, ... ) +{ + int ret; + va_list valist; + + va_start(valist, format); + ret = funcs.dbg_vprintf( format, valist ); + va_end(valist); + return ret; +} + +/* printf with temp buffer allocation */ +const char *wine_dbg_sprintf( const char *format, ... ) +{ + static const int max_size = 200; + char *ret; + int len; + va_list valist; + + va_start(valist, format); + ret = funcs.get_temp_buffer( max_size ); + len = vsnprintf( ret, max_size, format, valist ); + if (len == -1 || len >= max_size) ret[max_size-1] = 0; + else funcs.release_temp_buffer( ret, len + 1 ); + va_end(valist); + return ret; +} + + +/* varargs wrapper for funcs.dbg_vlog */ +int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *channel, + const char *func, const char *format, ... ) +{ + int ret; + va_list valist; + + if (!(__wine_dbg_get_channel_flags( channel ) & (1 << cls))) return -1; + + va_start(valist, format); + ret = funcs.dbg_vlog( cls, channel, func, format, valist ); + va_end(valist); + return ret; +} + +#ifndef VBOX //!defined(VBOX_WITH_VMSVGA) || defined(RT_OS_WINDOWS) +int interlocked_xchg_add( int *dest, int incr ) +{ + return InterlockedExchangeAdd((LONG *)dest, incr); +} +#endif + +/* allocate some tmp string space */ +/* FIXME: this is not 100% thread-safe */ +static char *get_temp_buffer( size_t size ) +{ + static char *list[32]; + static int pos; + char *ret; + int idx; + +#ifndef VBOX + idx = interlocked_xchg_add( &pos, 1 ) % (sizeof(list)/sizeof(list[0])); +#else + idx = ASMAtomicIncS32(&pos) - 1; + idx %= RT_ELEMENTS(list); +#endif + if ((ret = realloc( list[idx], size ))) list[idx] = ret; + return ret; +} + + +/* release unused part of the buffer */ +static void release_temp_buffer( char *buffer, size_t size ) +{ + /* don't bother doing anything */ +} + + +/* default implementation of wine_dbgstr_an */ +static const char *default_dbgstr_an( const char *str, int n ) +{ + static const char hex[16+1] = "0123456789abcdef"; + char *dst, *res; + size_t size; + + if (!((ULONG_PTR)str >> 16)) + { + if (!str) return "(null)"; + res = funcs.get_temp_buffer( 6 ); + sprintf( res, "#%04x", LOWORD(str) ); + return res; + } + if (n == -1) n = (int)strlen(str); + if (n < 0) n = 0; + size = 10 + min( 300, n * 4 ); + dst = res = funcs.get_temp_buffer( size ); + *dst++ = '"'; + while (n-- > 0 && dst <= res + size - 9) + { + unsigned char c = *str++; + switch (c) + { + case '\n': *dst++ = '\\'; *dst++ = 'n'; break; + case '\r': *dst++ = '\\'; *dst++ = 'r'; break; + case '\t': *dst++ = '\\'; *dst++ = 't'; break; + case '"': *dst++ = '\\'; *dst++ = '"'; break; + case '\\': *dst++ = '\\'; *dst++ = '\\'; break; + default: + if (c >= ' ' && c <= 126) + *dst++ = c; + else + { + *dst++ = '\\'; + *dst++ = 'x'; + *dst++ = hex[(c >> 4) & 0x0f]; + *dst++ = hex[c & 0x0f]; + } + } + } + *dst++ = '"'; + if (n > 0) + { + *dst++ = '.'; + *dst++ = '.'; + *dst++ = '.'; + } + *dst++ = 0; + funcs.release_temp_buffer( res, dst - res ); + return res; +} + + +/* default implementation of wine_dbgstr_wn */ +static const char *default_dbgstr_wn( const WCHAR *str, int n ) +{ + char *dst, *res; + size_t size; + + if (!((ULONG_PTR)str >> 16)) + { + if (!str) return "(null)"; + res = funcs.get_temp_buffer( 6 ); + sprintf( res, "#%04x", LOWORD(str) ); + return res; + } + if (n == -1) + { + const WCHAR *end = str; + while (*end) end++; + n = end - str; + } + if (n < 0) n = 0; + size = 12 + min( 300, n * 5 ); + dst = res = funcs.get_temp_buffer( size ); + *dst++ = 'L'; + *dst++ = '"'; + while (n-- > 0 && dst <= res + size - 10) + { + WCHAR c = *str++; + switch (c) + { + case '\n': *dst++ = '\\'; *dst++ = 'n'; break; + case '\r': *dst++ = '\\'; *dst++ = 'r'; break; + case '\t': *dst++ = '\\'; *dst++ = 't'; break; + case '"': *dst++ = '\\'; *dst++ = '"'; break; + case '\\': *dst++ = '\\'; *dst++ = '\\'; break; + default: + if (c >= ' ' && c <= 126) + *dst++ = c; + else + { + *dst++ = '\\'; + sprintf(dst,"%04x",c); + dst+=4; + } + } + } + *dst++ = '"'; + if (n > 0) + { + *dst++ = '.'; + *dst++ = '.'; + *dst++ = '.'; + } + *dst++ = 0; + funcs.release_temp_buffer( res, dst - res ); + return res; +} + + +/* default implementation of wine_dbg_vprintf */ +static int default_dbg_vprintf( const char *format, va_list args ) +{ + vbox_log_v(format, args); +#ifdef DEBUG_leo + static FILE *output=NULL; + static int first_time = 1; + + if (first_time) + { + first_time = 0; + output = fopen( "winelog.txt", "w" ); + } + + if (output) vfprintf( output, format, args ); +#endif + return vfprintf( stdout, format, args ); +} + + +/* default implementation of wine_dbg_vlog */ +static int default_dbg_vlog( enum __wine_debug_class cls, struct __wine_debug_channel *channel, + const char *func, const char *format, va_list args ) +{ + int ret = 0; + + if (cls < sizeof(debug_classes)/sizeof(debug_classes[0])) + ret += wine_dbg_printf( "%s:[%#x]:%s:%s ", debug_classes[cls], GetCurrentThreadId(), channel->name, func ); + if (format) + ret += funcs.dbg_vprintf( format, args ); + return ret; +} + +/* wrappers to use the function pointers */ + +const char *wine_dbgstr_an( const char * s, int n ) +{ + return funcs.dbgstr_an(s, n); +} + +const char *wine_dbgstr_wn( const WCHAR *s, int n ) +{ + return funcs.dbgstr_wn(s, n); +} + +void __wine_dbg_set_functions( const struct __wine_debug_functions *new_funcs, + struct __wine_debug_functions *old_funcs, size_t size ) +{ + if (old_funcs) memcpy( old_funcs, &funcs, min(sizeof(funcs),size) ); + if (new_funcs) memcpy( &funcs, new_funcs, min(sizeof(funcs),size) ); +} + +static struct __wine_debug_functions funcs = +{ + get_temp_buffer, + release_temp_buffer, + default_dbgstr_an, + default_dbgstr_wn, + default_dbg_vprintf, + default_dbg_vlog +}; diff --git a/src/VBox/Devices/Graphics/shaderlib/libWineStub/include/config.h b/src/VBox/Devices/Graphics/shaderlib/libWineStub/include/config.h new file mode 100644 index 00000000..998c28bd --- /dev/null +++ b/src/VBox/Devices/Graphics/shaderlib/libWineStub/include/config.h @@ -0,0 +1,1282 @@ +/* include/config.h. Generated from config.h.in by configure. */ +/* include/config.h.in. Generated from configure.ac by autoheader. */ + +#include + +#define __WINE_CONFIG_H + +/* Define to a function attribute for Microsoft hotpatch assembly prefix. */ +#define DECLSPEC_HOTPATCH /* */ + +/* Define to the file extension for executables. */ +#define EXEEXT ".exe" + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALIAS_H */ + +/* Define if you have ALSA 1.x including devel headers */ +/* #undef HAVE_ALSA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALSA_ASOUNDLIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AL_AL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_NAMESER_H */ + +/* Define to 1 if you have the `asctime_r' function. */ +#define HAVE_ASCTIME_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASM_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AUDIOUNIT_AUDIOUNIT_H */ + +/* Define to 1 if you have the