Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSR function of CMDFIFO is not implemented for Voodoo 3 #340

Closed
Vort opened this issue Aug 26, 2024 · 3 comments
Closed

JSR function of CMDFIFO is not implemented for Voodoo 3 #340

Vort opened this issue Aug 26, 2024 · 3 comments

Comments

@Vort
Copy link
Contributor

Vort commented Aug 26, 2024

When I launch Darwinia v1.0.0.1 game in Windows 98 SE with Voodoo 3 drivers v1.07.00-WHQL (4.12.01.0666) and DirectX 9.0c from 22 Jul 2004, black screen appears and logs starts to be flooded with CMDFIFO packet type 0: unsupported code 1 messages.
It happens because JSR and RET functions of CMDFIFO are not implemented.
Windows XP with bunch of hacks to overcome problems #178 and #196 allows this game to run without JSR function, but it would be nice to have proper Windows 98 support as well, however such fix is low priority.

To run this game (and reproduce problem), few changes needs to be made:

  1. Installer unpacks large .avi file to game directory. It is not needed and can be deleted;
  2. After first launch, game creates preferences.txt file, but default settings does not allow game to run;
    2.1. There is some problem with sound support (either in Bochs or in audio drivers), so SoundLibrary option should be set to null (note: works fine with Windows XP);
    2.2. Voodoo 3 can support only 16 bit color and Z buffer depths, these options should be tuned accordingly. Also there is no shaders support, so RenderPixelShader should be set to 0;
    2.3. Here are preferences which were working well for me: preferences.zip.
  3. Game files are packed by default. It makes game to load very slow. However, .dat files of the game are just RAR archives and can be unpacked into game directory. This significantly speeds up game loading.

One more note: even when problems are solved, game runs very slowly, so when black screen appears after first level is selected, waiting for several minutes may be required.

I have very little knowledge about Voodoo 3 internals, so I don't know how to implement JSR properly, however I was able to make game running with such changes:

diff --git a/bochs/iodev/display/voodoo_data.h b/bochs/iodev/display/voodoo_data.h
index 3bde87c41..5f5a29cb1 100644
--- a/bochs/iodev/display/voodoo_data.h
+++ b/bochs/iodev/display/voodoo_data.h
@@ -1509,7 +1509,9 @@ struct _cmdfifo_info
   Bit32u  depth;        /* current depth */
   Bit32u  depth_needed; /* depth needed for command */
   Bit32u  holes;        /* number of holes */
+  Bit32u  retAddr;
   bool    cmd_ready;
+  bool    jsr;
 };
 
 
diff --git a/bochs/iodev/display/voodoo_func.h b/bochs/iodev/display/voodoo_func.h
index c8ce83c5b..42050fb25 100644
--- a/bochs/iodev/display/voodoo_func.h
+++ b/bochs/iodev/display/voodoo_func.h
@@ -2936,11 +2936,13 @@ Bit32u cmdfifo_r(cmdfifo_info *f)
 
   data = *(Bit32u*)(&v->fbi.ram[f->rdptr & v->fbi.mask]);
   f->rdptr += 4;
-  if (f->rdptr >= f->end) {
-    BX_INFO(("CMDFIFO RdPtr rollover"));
-    f->rdptr = f->base;
+  if (!f->jsr) {
+    if (f->rdptr >= f->end) {
+      BX_INFO(("CMDFIFO RdPtr rollover"));
+      f->rdptr = f->base;
+    }
+    f->depth--;
   }
-  f->depth--;
   return data;
 }
 
@@ -2961,6 +2963,24 @@ void cmdfifo_process(cmdfifo_info *f)
       switch (code) {
         case 0: // NOP
           break;
+        case 1: // JSR
+          if (f->jsr) {
+            BX_ERROR(("cmdfifo_process(): JSR: already inside of subroutine"));
+          } else {
+            f->jsr = true;
+            f->retAddr = f->rdptr;
+            f->rdptr = (command >> 4) & 0xfffffc;
+          }
+          break;
+        case 2: // RET
+          if (!f->jsr) {
+            BX_ERROR(("cmdfifo_process(): RET: not inside of subroutine"));
+          } else {
+            f->rdptr = f->retAddr;
+            f->retAddr = 0;
+            f->jsr = false;
+          }
+          break;
         case 3: // JMP
           f->rdptr = (command >> 4) & 0xfffffc;
           if (f->count_holes) {
@@ -3209,7 +3229,7 @@ void cmdfifo_process(cmdfifo_info *f)
       BX_ERROR(("CMDFIFO: unsupported packet type %d", type));
   }
   f->depth_needed = cmdfifo_calc_depth_needed(f);
-  if (f->depth < f->depth_needed) {
+  if (!f->jsr && f->depth < f->depth_needed) {
     f->cmd_ready = 0;
   }
 } 

Here are game screenshots when it works. This is how "success" looks like:
Intro (one of):
image

Level selection screen:
image

First level loaded:
image

Version: 0138ad4

@Vort
Copy link
Contributor Author

Vort commented Sep 8, 2024

Another reproduction method for CMDFIFO packet type 0: unsupported code 1, with different game:

  1. Switch resolution to 1152x864x16;
  2. Unpack RagdollMasters_3_1.zip and launch Ragdoll Masters v3.1.exe.

This is how loading screen looks like when problem is solved:
image

Without JSR implemented, black window appears.

@vruppert
Copy link
Contributor

vruppert commented Sep 8, 2024

I have now applied your JSR / RET changes to the Bochs code. The code looks okay to me, so I think it's good for now.

@Vort
Copy link
Contributor Author

Vort commented Sep 8, 2024

Ok, thanks.
Even in case if it won't work perfectly, it will be better than black screen anyway.

@Vort Vort closed this as completed Sep 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@Vort @vruppert and others