bochs-emu / Bochs

Bochs - Cross Platform x86 Emulator Project
https://bochs.sourceforge.io/
GNU Lesser General Public License v2.1
913 stars 109 forks source link

No video playback in Diablo II with Voodoo 3 #349

Closed Vort closed 2 months ago

Vort commented 2 months ago

After Diablo II game is started in 3dfx Glide mode with Voodoo 3 card, black screen appears instead of video playback.

It happens because v->fbi.video_changed is never set to 1 during video playback. Game renders video data using LFB writes, which are processed by lfb_w function of voodoo_func.h. In this function, video_changed is modified only in front buffer case, which is never triggered because of VOODOO_BANSHEE check.

With the help of debugger, I noticed that during video playback, back and front buffer addresses are the same. So in fact, writes are happening to both buffers at the same time. I made such change to take this property into account:

diff --git a/bochs/iodev/display/voodoo_func.h b/bochs/iodev/display/voodoo_func.h
index 42050fb25..685cb2134 100644
--- a/bochs/iodev/display/voodoo_func.h
+++ b/bochs/iodev/display/voodoo_func.h
@@ -2471,7 +2471,6 @@ Bit32u lfb_w(Bit32u offset, Bit32u data, Bit32u mem_mask)
 {
   Bit16u *dest, *depth;
   Bit32u destmax, depthmax;
-  Bit32u forcefront=0;

   int sr[2], sg[2], sb[2], sa[2], sw[2];
   int x, y, scry, mask;
@@ -2679,7 +2678,7 @@ Bit32u lfb_w(Bit32u offset, Bit32u data, Bit32u mem_mask)
     mask &= ~(0xf0 + LFB_DEPTH_PRESENT_MSW);

   /* select the target buffer */
-  destbuf = (v->type >= VOODOO_BANSHEE) ? (!forcefront) : LFBMODE_WRITE_BUFFER_SELECT(v->reg[lfbMode].u);
+  destbuf = (v->type >= VOODOO_BANSHEE) ? 1 : LFBMODE_WRITE_BUFFER_SELECT(v->reg[lfbMode].u);
   switch (destbuf)
   {
     case 0:     /* front buffer */
@@ -2691,6 +2690,8 @@ Bit32u lfb_w(Bit32u offset, Bit32u data, Bit32u mem_mask)
     case 1:     /* back buffer */
       dest = (Bit16u *)(v->fbi.ram + v->fbi.rgboffs[v->fbi.backbuf]);
       destmax = (v->fbi.mask + 1 - v->fbi.rgboffs[v->fbi.backbuf]) / 2;
+      if (v->fbi.rgboffs[v->fbi.frontbuf] == v->fbi.rgboffs[v->fbi.backbuf])
+        v->fbi.video_changed = 1;
       break;

     default:    /* reserved */ 

And video started to appear: bochs_diablo2_video

I do not know how proper fix for this problem should look like however.


To reproduce this problem, Diablo II version 1.00 should be installed first.

Then Glide mode should be selected: image

Then either patch D2Patch_109d.exe and Loader.exe should be used in case of Windows 95. Or D2Patch_113d.exe without loader in case of Windows 98.

I found 3 ISO images needed for installation on BitTorrent tracker, so I can't give direct links to the files. But I can find these files somewhere else if needed.


Version: f5e3dd9

vruppert commented 2 months ago

Yesterday I have applied your suggested fix for this issue.

Vort commented 2 months ago

I worried that such change may hurt performance. However adding more code to handle this case (like caching equality of buffer addresses) may hurt readability. But maybe I'm overcomplicating things and this change is just fine. I'm closing this issue anyway. Performance improvements may have their own issue if needed.