dosemu2 / dosemu2

Run DOS programs under linux:
http://dosemu2.github.io/dosemu2/
GNU General Public License v2.0
568 stars 59 forks source link

Scaling off by factor of two in text graphics of Paku Paku #1495

Closed mcericdos closed 3 years ago

mcericdos commented 3 years ago

The Pacman clone Paku Paku, in the ZIP on ibiblio mentioned on

http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/repositories/1.3/pkg-html/pakupaku.html

uses text graphics where each "character" poses as two pixels via foreground and background color, respectively, as far as I can tell. When playing the game, DOSEMU2 shows the game only in the upper half of the window, the bottom half of the window stays empty. Probably a bug in text mode font scaling for the unusually shallow font geometry used by the game?

stsp commented 3 years ago

Try $_force_vga_fonts = (on)

mcericdos commented 3 years ago

Thanks, but this does not solve the distortion, alas.

stsp commented 3 years ago

Yes, dosemu2 is smart enough to detect the custom font and switch out from ttf automatically.

From what I can see, the game sets the unusual text mode with 228 lines of text, but uses only half of them. I think it uses some vga parameter to scale the text image vertically, but not Scan Doubling, which seems still disabled.

stsp commented 3 years ago

Forcing the double scan like this:

--- a/src/base/dev/vga/vgaemu.c
+++ b/src/base/dev/vga/vgaemu.c
@@ -2929,6 +2929,7 @@ void vgaemu_adj_cfg(unsigned what, unsigned msg)
       vertical_blanking_end =
              vga.crtc.data[0x16] & 0x7F;
       char_height = (vga.crtc.data[0x9] & 0x1f) + 1;
+vga.crtc.data[0x9] |= 0x80;
       vertical_multiplier = char_height << ((vga.crtc.data[0x9] & 0x80) >> 7);
       /* see VGADOC: CGA is special for reg 9 */
       if(vga.mode_type == CGA) vertical_multiplier = char_height;

gives the desired effect.

stsp commented 3 years ago

So this game probably uses some other feature equivalent to double scan, but I am not aware about.

mcericdos commented 3 years ago

But if you would force it in vgaemu, you would distort other things, I assume?

Paku Paku is open source, so you can review all the evil things it does to the graphics card :-)

stsp commented 3 years ago

But if you would force it in vgaemu, you would distort other things, I assume?

I never said this patch should be applied. But it may be a hint.

stsp commented 3 years ago

Paku Paku is open source, so you can review all the evil things it does to the graphics card :-)

        EGA_CRTC:regData=(
                register:$3D4;
                data:
                        #$70+#$4F+#$5C+#$2F + #$5F+#$07+#$04+#$11 +
                        #$00+#$01+#$06+#$07 + #$00+#$00+#$00+#$00 +
                        #$E1+#$24+#$C7+#$28 + #$08+#$E0+#$F0+#$A3 +
                        #$FF+#$00
        );

Please review.

stsp commented 3 years ago

I suspect they just dumped the crtc valus obtained from dosbox. Does this even work on qemu?

mcericdos commented 3 years ago

Paul Dufresne has used Paku Paku on VirtualBox and QEMU and I have not seen him complain about the game filling only part of the screen, so I have done some more experiments. From my collection of retro graphics things, I found that:

My loader for DIGDUG does the following, so maybe this helps you to get DOSEMU2 further:

mov ax,5 int 0x10

out 0x3d4,0x11 x = in 0x3d5 and ~0x80

out 0x3d4,0x11 out 0x3d5,x

It also patches a routine (at 0x5cf in the unpatched game) which does: "ax=0x28 * (cl and 0xfe)", test cl,1, "if not zero add ax,0x2000", "di = (bx >> 2) + ax" into first doing "read byte port 0x80 in a 0xccc iteration loop", to make drawing of pixels slower and make the whole game acceptably slow ;-)

mcericdos commented 3 years ago

The docs of Paku Paku say that it has been written in 2011 for the "Retrochallenge 2011 Winter Warmup" and real CGA, but it has a /safe command line option of less compatible EGA/VGA cards which skips reprogramming the CRTC. With that option, the game uses 720x400 pixel mode and the bottom 25% of the screen stay blank in DOSEMU2. The docs claim that the bottom 15% would stay blank instead. Note that /safe mode uses the default 9 pixel VGA font width, which causes minimal horizontal jitter. Without the option, the DOSEMU2 window is 640x456 (?) pixels in size and only the top 200 pixels are used according to "kruler" in Linux. The docs claim that the non-safe mode is derived from 640x200 EGA mode instead of a default 350 pixel tall mode.

stsp commented 3 years ago

OK, the silliest bugs are the most difficult to spot. :)

mcericdos commented 3 years ago

So you found a solution? What was the trick?

stsp commented 3 years ago

The patch is referenced above.

mcericdos commented 3 years ago

Ah, read-only VGA CRTC in some context :-) Thanks for the patch!

stsp commented 3 years ago

So to answer my own question: they do not set double scan, but instead halve the Vertical Total register value. I believe crtc already has some kind of a scaler within to handle different resolutions on the same CRT, so the effect is similar to double scan.