dmsc / emu2

Simple x86 and DOS emulator for the Linux terminal.
GNU General Public License v2.0
397 stars 30 forks source link

No consistent flushing strategy #59

Closed nero closed 10 months ago

nero commented 10 months ago

Hi dmsc,

today i worked on getting the original MS-DOS 3.2 from the Amstrad PC1512 to run on emu2. Or at least the COMMAND.COM and DEBUG.EXE. For both programs i had the following issue: When the program launches, no prompt is printed. I can type a command and press enter, and the first prompt appears after the input.

I correctly suspected the libc file descriptor buffering being responsible for the delayed output and also saw that your char_input() already accounts for that by calling fflush. But my COMMAND.COM uses int 21,AH=0A (buffered line input), which uses C's getc directly.

My DEBUG.EXE has the same bug using a different codepath: It calls int 10,AH=0F (get video state), causing its output to be handled by the video.c code. When it later also calls int 21,AH=0A (buffered line input), the buffer on the tty descriptor is not flushed, either.

Adding both flushes to int 21,AH=0A (buffered line input) fixes both issues:

diff --git a/src/dos.c b/src/dos.c
index 326cb2d..e7683e8 100644
--- a/src/dos.c
+++ b/src/dos.c
@@ -1082,6 +1082,9 @@ void int21()
         if(devinfo[0] == 0x80D3)
             suspend_keyboard();

+        fflush(handles[1] ? handles[1] : stdout);
+        check_screen();
+
         FILE *f = handles[0] ? handles[0] : stdin;
         int addr = cpuGetAddrDS(cpuGetDX());
         unsigned len = memory[addr], i = 2;

I would work out a more complete patch and submit it as PR, but i'm not sure how the end result should look like. Maybe rewrite int 21,AH=0A to use char_input and patch char_input to account for the tty descriptor buffer. Your thoughts?

dmsc commented 10 months ago

Hi!

Thanks for the investigation.

I see two different issues:

I fixed this differently: flushing stdout in "emulator_update" and calling emulator_update from buffered input.

Attached is the two binaries mentioned - patched so they work in any DOS version: DEBUG.EXE.FIX.gz COMMAND.COM.FIX.gz

dmsc commented 10 months ago

Hi!

Also, I just added a way to setup the reported DOS version with an environment variable - this makes easier to run any DOS utility of any version. In your example, just do EMU2_DOSVER=3.20 emu2 COMMAND.COM

Have Fun!

nero commented 10 months ago

Ah thanks for the quick response. I had the DOS version fixed up manually in my local checkout and was planning to add a DOSVER functionality like that. I really dislike modifying my old binaries.