Coder Social home page Coder Social logo

emu2's Introduction

EMU2: A simple text-mode x86 + DOS emulator

This is a simple DOS emulator for the Linux text console, supporting basic DOS system calls and console I/O.

Using the emulator

To run a DOS .exe or .com file, simply load it with

emu2 myprog.exe

The emulator accepts some options in the command line and more options as environment variables, this allows child process (programs run by your DOS program) to inherit the configuration.

The full usage is:

emu2 [options] <prog.exe> [args...] [-- environment vars]

Options (should be placed before the DOS program name):

  • -h Shows a brief help.

  • -b addr Load header-less binary at given address (to load ROMs or test data).

  • -r <seg>:<ip> Specify a run address to start execution (only for binary loaded data).

The available environment variables are:

  • EMU2_DEBUG_NAME Base name of a file to write the debug log, defaults to the exe name if not given.

  • EMU2_DEBUG List of debug options to activate, from the following: cpu, int, port, dos, video.

  • EMU2_PROGNAME DOS program name, if not given try to convert the unix name to an equivalent DOS path.

  • EMU2_DEFAULT_DRIVE DOS default (current) drive letter, if not given use C:

  • EMU2_CWD DOS current working directory, if not given tries to convert the current directory to the equivalent DOS path inside the DOS default drive, or C:\ if not possible.

  • EMU2_DRIVE_n Set unix path as root of drive n, by default all drives point to the unix working directory.

  • EMU2_APPEND Sets a list of paths to search for data files on open, emulating the DOS APPEND command. Only files with a relative path are included in the search, and the search is relative to the current working directory if no drive letter is specified in the append path. For example, if set to "TXT;C:\IN", when opening the file "CAT.TXT" the file is searched as "CAT.TXT", "TXT\CAT.TXT" and "C:\IN\CAT.TXT" in turn.

  • EMU2_CODEPAGE Set DOS code-page to the specified string. Set to '?' to show list of included code-pages, multiple aliases separated with commas. Set to a file name to read the mapping table from a file with the unicode value for each byte. You can download mapping tables from ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/ The code-page setting affects keyboard input and screen output, but does not change the DOS NLS information. The default code-page is CP437.

  • EMU2_LOWMEM Limits main memory to 512KB, this fixes some old DOS programs with a bug that checks available memory using "signed" comparison instructions (JLE instead of JBE). This is needed at least for MASM versions 1.0 and 1.10.

  • EMU2_DOSVER Changes the reported DOS version, allowing programs that checks this version to run. You can specify a major version or a major dot minor, for example "3.20", "2.11" or "5".

  • EMU2_ROWS Setups the VGA text mode to the given number of rows, from 12 to 50 at the program start. Some full-screen DOS programs will retrieve this info and adjust the screen properly, some other will ignore this and setup the text mode again.

Simple Example

For a simple example, we can run the Turbo Pascal 3, available from the antique software collection as a file tp302.zip.

First, make a new directory and unzip the file:

$ mkdir tp302
$ cd tp302
$ unzip ../tp302.zip
$ ls
$ ls
$ ls
ACCESS3.BOX   CALC.PAS      DEMO-BCD.PAS  GRAPH.P     SUBDIR.PAS    TURBO.COM
ART.PAS       CMDLINE.PAS   EXTERNAL.DOC  LISTER.PAS  TINST.COM     TURBO.MSG
CALCDEMO.MCS  COLOR.PAS     GETDATE.PAS   README      TINST.MSG     TURTLE.PAS
CALC.HLP      DEMO1-87.PAS  GETTIME.PAS   README.COM  TURBO-87.COM  WINDOW.PAS
CALC.INC      DEMO2-87.PAS  GRAPH.BIN     SOUND.PAS   TURBOBCD.COM
$ chmod +w *

The last is necessary as you will want to to modify the program files afterwards.

The main file is named "TURBO.COM", there is also a "README.COM" to read further info, try that:

$ emu2 README.COM

Image of README.COM

You can press exit to return to the command line. Now, you can configure the compiler, as the README said, just load TINST.COM, press "S" (screen type), "0" (default), "N" (screen does not blink) and "Q" to quit.

$ emu2 TINST.COM

                   TURBO Pascal installation menu.
             Choose installation item from the following:

[S]creen type |  [C]ommand installation  |  [M]sg file path  |  [Q]uit


                         Enter S, C, M or Q: 

Choose one of the following displays:

  0)  Default display mode
  1)  Monochrome display
  2)  Color display 80x25
  3)  Color display 40x25
  4)  b/w   display 80x25
  5)  b/w   display 40x25

Which display? (Enter no. or ^Q to exit):

Does your screen blink when the text scrolls? (Y/N):

Finally, we are ready to run the program:

$ emu2 TURBO.COM
----------------------------------------
TURBO Pascal system        Version 3.02A
                                  PC-DOS
                                        
Copyright (C) 1983,84,85,86 BORLAND Inc.
----------------------------------------
                                        
Default display mode                    
                                        
                                        
                                        
Include error messages (Y/N)?           

Logged drive: C                         
Active directory: \                     
                                        
Work file:                              
Main file:                              
                                        
Edit     Compile  Run   Save            
                                        
Dir      Quit  compiler Options         
                                        
Text:     0 bytes                       
Free: 62024 bytes                       
                                        
>                                       

Try loading a program, use "e" to edit, type "window.pas", and you are in the editor:

      Line 1    Col 1   Insert    Indent  C:WINDOW.PAS                          
program TestWindow;                                                             
{$C-}                                                                           
{                                                                               
              WINDOW DEMONSTRATION PROGRAM  Version 1.00A                       
                                                                                
       This program demonstrates the use of windows on the IBM PC               
       and true compatibles.                                                    
                                                                                
       PSEUDO CODE                                                              
       1.  MakeWindow        - draws window boxes on the screen                 
       2.  repeat                                                               
             UpdateWindow 1  - scrolls the window contents up or                
                               down for each window.                            
             UpdateWindow 2                                                     
             UpdateWindow 3                                                     
           until a key is pressed                                               
       3.  Reset to full screen window                                          
                                                                                
       INSTRUCTIONS                                                             
       1.  Compile this program using the TURBO.COM compiler.                   
       2.  Type any key to exit the program.                                    
}                                                                               

To exit the editor, type "CONTROL+K" and "D", in the prompt you can now type "R" to compile and run the program.

Image of WINDOW.PAS running

Advanced Example

For a more advanced example, we can install and run Turbo Pascal 5.5, available from the same antique software collection as a file tp55.zip.

First, make a new directory and unzip the file:

$ mkdir tp55
$ cd tp55
$ unzip ../tp55.zip
$ ls
Disk1 Disk2

As you see, the program was distributed in two disks, and must be installed before running.

To install, let's first copy all the contents to one directory:

$ mkdir all
$ cp -r Disk1/* Disk2/* all/

And now, run the emulator giving the correct paths to simulate a floppy drive:

$ EMU2_DEFAULT_DRIVE=A EMU2_DRIVE_A=all emu2 all/INSTALL.EXE

Image of TP55 INSTALL.EXE

Type enter, enter again to install from drive "A", again to install on a hard-drive, go down to "Start Installation" and enter again. The install program shows an error, this is because we copied all the content to one drive. Simply type "S" to skip all errors.

After the installation is finished, we must run the install again, to copy the missing files from before, with the same command line:

$ EMU2_DEFAULT_DRIVE=A EMU2_DRIVE_A=all emu2 all/INSTALL.EXE

Image of TP55 INSTALL.EXE at the end

Again, press enter to the questions and go to "Start Installation", this time will complete without errors.

You can now compile from the command line, as:

$ emu2 tp/tpc.exe -- 'PATH=C:\TP'
Turbo Pascal Version 5.5  Copyright (c) 1983,89 Borland International
Syntax: TPC [options] filename [options]
/B	Build all units		/$A-	No word alignment
/Dxxx	Define conditionals	/$B+	Complete boolean evaluation
/Exxx	EXE & TPU directory	/$D-	No debug information
/Fxxx	Find run-time error	/$E-	No 8087 emulation
/GS	Map file with segments	/$F+	Force FAR calls
/GP	Map file with publics	/$I-	No I/O checking
/GD	Detailed map file	/$L-	No local debug symbols
/Ixxx	Include directories	/$Mxxx	Memory allocation parameters
/L	Link buffer on disk	/$N+	8087 code generation
/M	Make modified units	/$O+	Overlays allowed
/Oxxx	Object directories	/$R+	Range checking
/Q	Quiet compile		/$S-	No stack checking
/Txxx	Turbo directories	/$V-	No var-string checking
/Uxxx	Unit directories
/V	EXE debug information

$ emu2 tp/tpc.exe tp\\qsort.pas -- 'PATH=C:\TP'
Turbo Pascal Version 5.5  Copyright (c) 1983,89 Borland International
TP\QSORT.PAS(66)
66 lines, 4384 bytes code, 2668 bytes data.

$ emu2 tp/qsort.exe
....

And for the IDE, you can use:

emu2 tp/turbo.exe  -- 'PATH=C:\TP'

Image of TP55 environment

emu2's People

Contributors

andrewshadura avatar bcoles avatar dmsc avatar jg1uaa avatar johnsonjh avatar satyrdiamond avatar tsupplis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

emu2's Issues

Functions 14h and 15h are overriding AH on return

I hope I am not a nuisance going through all the legacy functions ...
Using the same legacy program hex2bin and asm, I found they rely on the stability of ha coming out of int 21h functions 14h, and 15h. They are supposed to give their return in AL, not AX.
Here is the proposed fix:

   case 0x14: // SEQUENTIAL READ USING FCB
        dos_show_fcb();
        cpuSetAX(0x1400|dos_read_record_fcb(dosDTA, 1));
        break;
    case 0x15: // SEQUENTIAL WRITE USING FCB
        dos_show_fcb();
        cpuSetAX(0x1500|dos_write_record_fcb(dosDTA, 1));
        break;
....
    case 0x21: // RANDOM READ USING FCB
        dos_show_fcb();
        cpuSetAX(0x2100|dos_read_record_fcb(dosDTA, 0));
        break;
    case 0x22: // RANDOM WRITE USING FCB
        dos_show_fcb();
        cpuSetAX(0x2200|dos_write_record_fcb(dosDTA, 0));
        break;

[Not an issue] You saved my day.

Thanks for creating this wonderful tool! I was desperately searching for something I could use to easily emulate DOS programs for 8086 (similar to EMU8086, but libre), and this is just perfect. It implements basic interrupts for DOS API and runs executable files directly without having to run a whole IBM PC emulator or else.

I'm using JWASM to create DOS compatible executable files, and EMU2 to run them. The combination is simply perfect!

Windows [7] run without Cygwin?

This is exactly the program I've looking for (for years) as I have many DOS-era utilities that I need to run under Windows 7 console.

[I haven't been able to make DosBox[-x] work with text-only apps in a simple manner.]

I managed to get this emulator work straight out of the box by compiling under Gycwin, and running it there.
But, I want to be able to run it under Windows console directly. It fails. I suppose it needs to be compiled differently.

Any hints on that?

Int 21h function 26h/38 not implemented

I noticed that function 26h was currently not implemented.

Here is the snippet:

    case 0x26: // Create PSP (allocate segment (singleton), and copy PSP)
    {
        uint8_t *new_base = getptr(cpuGetAddress(cpuGetDX(),0), 0x100);
        uint8_t *orig = getptr(cpuGetAddress(get_current_PSP(),0), 0x100);
        // Copy PSP to the nex segment, 0x80 is what DOS does)
        memcpy(new_base,orig,0x80);
        debug(debug_dos, "\tnew psp segment %04x.\n", cpuGetDX());
        debug(debug_dos, "\tnew psp size %02x%02x.\n", new_base[7],new_base[6]);        
        debug(debug_dos, "\toriginal psp segment %04x.\n", get_current_PSP());
        debug(debug_dos, "\toriginal psp size %02x%02x.\n", orig[7],orig[6]);        
        break;
    }

As for the FCB problem, very happy to create a PR if you prefer.

Incorrect video display with Calvin v2.3

Calvin works with DOSEMU2 and DOSBox-X (including resizing under DOSEMU2), but the display is corrupted and it doesn't seem to respond to input.

Some warnings:

UNHANDLED INT 09, AX=273a
UNHANDLED INT 09, AX=1c0d
UNHANDLED INT 09, AX=1071

Strange bugs with DND 2.01

Noticed a few strange issues with DND 2.0.1 (1988), which was written in Turbo C.

Interestingly, these bugs don't affect the earlier DND 1.2.1 (1987), which was written in Microsoft Pascal.

You can get DND 2.0.1 here. Start with a clean players file by removing the PLAYERS.DND files.

To reproduce the issue:

  1. Start DND
  2. [C]reate a new character and enter the Dungeon.
  3. [K]ill yourself.
  4. [P]rint all characters

DOSEMU:

Screenshot from 2024-07-01 13-41-50

emu2:

Screenshot from 2024-07-01 13-42-18

As you can see, in DOSEMU with real DOS, the character is deleted.

In emu2, the character is not deleted, and in fact, the character never "dies" allowing you to cheat in the game, continuing along after death.

You can also now a new character, [Q]uit the dungeon:

DOSEMU:

Screenshot from 2024-07-01 13-45-23

emu2:

Screenshot from 2024-07-01 13-45-39

And now from the DND menu, [K]ill the new character, and [P]rint the characters.

In DOSEMU, now characters remain, which is correct, but in emu2, you now have two of the original characters, like this:

Screenshot from 2024-07-01 13-47-46

A quick examination of the players file shows the emu2 version is corrupted, having two copies of the character, which should be impossible:

$ strings ~/.dosemu/drive_c/dnd201/players.dnd 
$ strings ./players.dnd                         
Raven
raven
ANCALAGN.DGN
Raven
raven
ANCALAGN.DGN

There are a few minor cosmetic issue as well:

  • The screen is not correctly cleared after using the various menus and when entering the dungeon.
  • When entering invalid keys at the menus, a is displayed, like this, where real DOS displays nothing at all:

Screenshot from 2024-07-01 13-54-57

I've not had time to look at it myself, and while it might be a bug in the game, the game always malfunctions under emu2 this way, but never in real DOS (tested dosbox, dosemu, and DOS under KVM).

Handle relative overridden 32/16 call functions

Hi! I'm trying to use emu2 on an executable that includes a call instruction prefixed by 0x66. According to this Stack Overflow question this means that it's supposed to explicitly set the behavior. Dosbox provides this disassembly for the instruction:

01FE:0112 66E8C6000000 call 01DE ($+c6)

which emu2 provides this in the cpu log:

0087:0112 66 DB 66

and the error message:

./emu2: error, unimplemented opcode 66 at cs:ip = 0087:0112

What I'm wondering is if there's a semi-clean way of implementing this as an override, or what the appropriate change to do_instruction might be, to catch all the 0x66 prefixed instructions and have them zero out the upper bits of EIP. Is something like this out of scope for the project?

fseek state in FCB probably not initialized

Original problem:

Some files openend via the default FCB at 0x5C open successfully, but the first read with int 21h/ah=14h fails with al=01h (eof signal), despite the file having several records full of data.

I tracked this problem down to dos_read_record_fcb(int addr, int update), where unsigned pos = rsize * get32(0x21 + fcb); is reading seemingly garbage data, resulting in if(fseek(f, pos, SEEK_SET)) to set the read pointer behind the end of the file.

lseek(3, 0, SEEK_END)                   = 316
lseek(3, 0, SEEK_CUR)                   = 316
lseek(3, 0, SEEK_SET)                   = 0
lseek(3, 2147483648, SEEK_SET)          = 2147483648
readv(3, [{iov_base="", iov_len=127}, {iov_base="", iov_len=1024}], 2) = 0

I did only find two places where the 32-bit value at FCB+0x21 is written to, in the same function below and the equivalent in the dos_write_record_fcb, both are not reachable with the fseek failing beforehand.

Unaware of the right solution, i made the behavior disappear by initializing the value to zero during the int 21h/ah=0fh open call with the following patch:

diff --git a/src/dos.c b/src/dos.c
index 3d916e5..09fcc79 100644
--- a/src/dos.c
+++ b/src/dos.c
@@ -318,6 +318,7 @@ static void dos_open_file_fcb(int create)
     put16(fcb_addr + 0x16, 0);   // time of last write
     put16(fcb_addr + 0x18, h);   // reserved - store DOS handle!
     memory[fcb_addr + 0x20] = 0; // current record
+    put32(fcb_addr + 0x21, 0);   // fseek position
 
     debug(debug_dos, "OK.\n");
     cpuClrFlag(cpuFlag_CF);

Can you use this information to detect where this problem comes from?

I'm at loss why this only happens for a few files. I attached NASM code that fails to read this file. Exact commands that i used to reproduce: nasm -o test.com test.asm.txt and emu2 test.com a86.txt.

My system is alpine linux 3.15, running the musl-1.2.2 libc and manually compiled emu2 from gitrev c03b12c (current master).

Arithmetic Exception in get_actual_timer

in

static uint16_t get_actual_timer(struct i8253_timer *t)
{
    int64_t elapsed = get_timer_clock() - t->load_time;
    debug(debug_int, "timer elapsed: %lld\n", elapsed);
    switch(t->op_mode & 7)
    {
    case 2: // RATE GENERATOR
    case 3: // SQUARE WAVE GENERATOR
        return t->load_value - (elapsed % (t->load_value));
    default:
        return t->load_value - elapsed;
    }
}

we get an arithmetic expression when t->load_value is 0. This happens incidentally when executing qconfig.exe or checkit. Not too sure how to fix it there.

Advice required: CP/M-86 Emulator

Hi,

Now that your emulation is supporting most of the calls inherited from CP/M it is actually quite easy to create a CP/M-86 emulator by implementing

  • E0h instead of 21 and transposing register management
  • Adjust PSP and FCB
  • Load CMD formats

How would you approach that? I think it is too messy to overlap both, and a fork could do the job better, what do you think? Worse trying a single one? The appeal of it is far more limited than dos ...

Typo bug with FCB with file bigger that 65535 bytes: Memory Corruption and Hanging File Read

Hello,
I found a new bug with FCB based I/Os. using rasm86 on a file and the process hangs when the length of the file goes over .... 65536. The assembly works well on pc/ms-dos or dosbox....

emu2 rasm86.exe issue.a86

should hang, remove a character and it will work.

issue.zip

So something weird is happening here: the bc is going up to 0x200 and then goes back to the 0 and it is then running an infinite loop. so 0x200 * 128 = 65536 and a hence the reset? this does not seem quite right. The size of the file in blocks should be maxing out at ... 8MB with a record size of one 1 characters.

	FCB:[d=00:n=ISSUE   .A86:bn=01e8:rs=0001:fs=00010000:h=0005:rn=00:ra=0000f400]
D-211A83: set DTA         BX=31DE CX:321A DX:3205 DI=0100 DS:0736 ES:0736
D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=01e8:rs=0001:fs=00010000:h=0005:rn=00:ra=0000f400]
	FCB:[d=00:n=ISSUE   .A86:bn=01f0:rs=0001:fs=00010000:h=0005:rn=00:ra=0000f800]
D-211A83: set DTA         BX=31DE CX:321A DX:3205 DI=0100 DS:0736 ES:0736
D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=01f0:rs=0001:fs=00010000:h=0005:rn=00:ra=0000f800]
	FCB:[d=00:n=ISSUE   .A86:bn=01f8:rs=0001:fs=00010000:h=0005:rn=00:ra=0000fc00]
D-211A83: set DTA         BX=31DE CX:321A DX:3205 DI=0100 DS:0736 ES:0736
D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=01f8:rs=0001:fs=00010000:h=0005:rn=00:ra=0000fc00]
	FCB:[d=00:n=ISSUE   .A86:bn=0200:rs=0001:fs=00010000:h=0005:rn=00:ra=00000000]
D-211A83: set DTA         BX=31DE CX:321A DX:3205 DI=0100 DS:0736 ES:0736
D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=0200:rs=0001:fs=00010000:h=0005:rn=00:ra=00000000]
	FCB:[d=00:n=ISSUE   .A86:bn=0008:rs=0001:fs=00010000:h=0005:rn=00:ra=00000400]
D-211A83: set DTA         BX=31DE CX:321A DX:3205 DI=0100 DS:0736 ES:0736
D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=0008:rs=0001:fs=00010000:h=0005:rn=00:ra=00000400]
	FCB:[d=00:n=ISSUE   .A86:bn=0010:rs=0001:fs=00010000:h=0005:rn=00:ra=00000800]
D-211A83: set DTA         BX=31DE CX:321A DX:3205 DI=0100 DS:0736 ES:0736
D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=0010:rs=0001:fs=00010000:h=0005:rn=00:ra=00000800]
	FCB:[d=00:n=ISSUE   .A86:bn=0018:rs=0001:fs=00010000:h=0005:rn=00:ra=00000c00]
D-211A83: set DTA         BX=31DE CX:321A DX:3205 DI=0100 DS:0736 ES:0736
D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=0018:rs=0001:fs=00010000:h=0005:rn=00:ra=00000c00]

If the file is reduced by one, it seems ok.

D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=01f0:rs=0001:fs=0000ffff:h=0005:rn=00:ra=0000f800]
	FCB:[d=00:n=ISSUE   .A86:bn=01f8:rs=0001:fs=0000ffff:h=0005:rn=00:ra=0000fc00]
D-211A83: set DTA         BX=31DE CX:321A DX:3205 DI=0100 DS:0736 ES:0736
D-212787: read blk fcb    BX=31DA CX:0400 DX:31DE DI=0100 DS:0736 ES:0736
	FCB:[d=00:n=ISSUE   .A86:bn=01f8:rs=0001:fs=0000ffff:h=0005:rn=00:ra=0000fc00]
	FCB:[d=00:n=ISSUE   .A86:bn=01ff:rs=0001:fs=0000ffff:h=0005:rn=7f:ra=0000ffff]
D-21024F: putchar         BX=2F84 CX:2F02 DX:0045 DI=0100 DS:0736 ES:0736
D-21024F: putchar         BX=2F85 CX:0202 DX:006E DI=0100 DS:0736 ES:0736
D-21024F: putchar         BX=2F86 CX:0202 DX:0064 DI=0100 DS:0736 ES:0736
D-21024F: putchar         BX=2F87 CX:0202 DX:0020 DI=0100 DS:0736 ES:0736
D-21024F: putchar         BX=2F88 CX:0202 DX:006F DI=0100 DS:0736 ES:0736
D-21024F: putchar         BX=2F89 CX:0202 DX:0066 DI=0100 DS:0736 ES:0736
....

I will see what cycle I have in the next few days to help chasing the cause.

So just a first hint of digging, it took me a while to find the typo 😀. Could not see the glaring issue

dos.c line 370 and 372 -> + fcb missing of offsets 0x23 and 0x24 ... so then it works properly and removes a bad corruption of lower memory

            put16(0x21 + fcb, rnum & 0xFFFF);
            memory[0x23] = rnum >> 16;
            if(rsize < 64)
                memory[0x24] = rnum >> 24;

to

            put16(0x21 + fcb, rnum & 0xFFFF);
            memory[0x23 + fcb] = rnum >> 16;
            if(rsize < 64)
                memory[0x24 + fcb] = rnum >> 24;

Strange behavior with G ...

All of these issues might be my own fault, but, it does work correctly under real DOS (and DOSBox.)

Using the real-mode DOS 8086 version of G:

  • Initially no screen is displayed:

49A1070A-9961-41F9-8F5E-97F6F1EB4764

  • Upon a forced repaint (with !), quitting fails (via F7).

  • Pressing ^L to cause a dialog to appear causes that again when trying to exit via F7.

68AB7991-9A7A-41F9-97B4-8B4CDEC22748

  • Many other issues that make the editor unusable.

I'll try to look into it myself later tonight (it's a bit hard on a cell phone) but there are at least some unhandled interrupt warnings:

A004C634-E95D-4102-AA19-E5DBA6C5FEA7

It's being built using OpenWatcom - the other builds or a Linux build can be used for reference, but it very much looks like it's simply getting the wrong keyboard input.

FCB sequential read does not seem to advance read pointer when AL returns 3

Hello,

im running emu2 v2021.01-20-g40101bd (master branch at the moment of writing this).

I am opening and reading a file using the FCB syscalls 0fH and 014H. While iterating the file, the reads in the middle of the file return AL=0 as expected. Upon encountering the last record, which is a partial record (because the filesize on FAT can be a non-multiple of the record size), the DTA is filled with the data, correctly padded with zero, and AL=3 is returned.

Expected result: Upon the next read, EOF is signalled via AL=1

Real result: Upon the next read, the same partial record is written to the DTA again (overwriting, not just leaving untouched), and AL=3 is returned again.

This behavior seems to be in the realm of dos_rw_record_fcb. This function looks like it was written with the intent equal to my expectations, but i am not able to figure out why it behaves differently.

DEBUG=dos outputs:

D-211A20: set DTA         BX=031F CX:0000 DX:0080 DI=0327 DS:0087 ES:0087
D-210F20: open fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        convert dos fcb name C:'HELLO   LST'
        temp name '\HELLO.LST'
        open fcb './/hello.lst', 'r+b', 0005 OK.
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=00:ra=09000000]
D-211400: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=00:ra=09000000]
D-211468: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=01:ra=20000000]
D-211420: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=02:ra=69000000]
D-211430: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=03:ra=20000000]
D-211420: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=04:ra=30000000]
D-211430: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=05:ra=20000000]
D-211420: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=06:ra=30000000]
D-211400: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=06:ra=20000000]
D-211400: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=06:ra=20000000]
D-211400: read fcb        BX=031F CX:0000 DX:005C DI=0327 DS:0087 ES:0087
        FCB:[d=00:n=HELLO   .LST:bn=0000:rs=0080:fs=00000379:h=0005:rn=06:ra=20000000]

The last two lines repeat indefinitely.

I tested against dosbox, and i get the expected AL=0, AL=3, AL=1 sequence there.

VEDIT PLUS v4.12 (12/07/94) directory navigation issue

Directory navigation issues with VEDIT PLUS v4.12 (12/07/94)

  1. The first directory entry appears twice in listings,

    and...

  2. the '..' entry does not appear at all, making it impossible to navigate back to a starting/parent directory:
    Screenshot from 2022-04-05 15-24-38

Moved from #39

error, unimplemented opcode 66 at cs:ip = 0098:4FB3

We're looking for a lightweight alternative to dosemu2 for running some old dos-based compilers, however instantly hit a hurdle with emu2:

$ ./emu2 /tmp/CC1PSX.EXE
./emu2: error, unimplemented opcode 66 at cs:ip = 0097:4FB3

I can see from the code that this is explicit behaviour:

    else if(inum == 0x06)
    {
        uint16_t ip = cpuGetStack(0);
        uint16_t cs = cpuGetStack(2);
        print_error("error, unimplemented opcode %02X at cs:ip = %04X:%04X\n",
                    memory[cpuGetAddress(cs, ip)], cs, ip);
    }

.. is this because it's a significant amount of work to implement? where would one even start if I wanted to try? or should I throw in the towel now :)

PSP FCB1 and FCB2 not initialized in the loader

I am using emu2 very successfully with vintage old dos 1.X, some of which is still relying a lot on CP/M tricks. One of them is the feeding of the 2 first args of command line into the PSP (FCB1, FCB2). It is unfortunately a convoluted process with the algorithm used by dos with the special characters but I reached a fairly comfortable parity with real dos 1.x and modern dos. It is actually more accurate with the only other dos emulator I use: Dosbox.

Attached a proposed fix/implementation that works a treat for me. I am happy to propose a PR if you prefer. The fix is in my fork: https://github.com/tsupplis/emu2

It also fixes the default program size (psp[6,7])

Delete using FCB implementation

May I propose a beginning of an implementation (for discrete files only, no wild card)?

static void dos_delete_file_fcb()
{
    /* TODO: Limited support. No wild cards */
    int fcb_addr = get_fcb();
    char *fname = dos_unix_path_fcb(fcb_addr, 0);
    if(!fname)
    {
        debug(debug_dos, "\t(file not found)\n");
        dos_show_fcb();
        cpuSetAL(0xFF);
        return;
    }
    debug(debug_dos, "\tDelete fcb '%s'\n", fname);
    int e = unlink(fname);
    free(fname);
    if(e)
    {
        debug(debug_dos, "\tCould not delete file (%d).\n",errno);
        cpuSetAL(0xFF);
    } else {
        memory[fcb_addr+0x1]=0xE5; // Marker for file deleted
        debug(debug_dos, "\tOK.\n");
        cpuSetAL(0x00);
    }
    dos_show_fcb();
}

...

    case 0x13: // Delete FILE USING FCB
        dos_delete_file_fcb();
        break;

DOS string output does not expand tabs

The MS-DOS 3.2 DEBUG.EXE renders a circle ○ (character 9 of the current codepage) instead of whitespace in some places. During launch, it queries Int 10,AH=0Fh (get current video mode) and thus switches its output into video mode. For console writes, it uses Int 21,AH=40h (write to file or device). The code in dos.c for that syscall loops over the bytes and sends them to video_putch(). video_putch() does not expand tab characters.

Since im using a original PC1512 binary, i consulted the documentation of the original BIOS that the program was meant to run under. From http://www.seasip.info/AmstradXT/1512tech/section2.html#2.3.7.14:

The following display characters are executed rather than displayed symbolically:

BEL (07h)
Sounds a short (bleep) tone on the speaker.
BS (08h)
Decrements the cursor column one character position unless the column is already zero in which case it is ignored.
CR (0Dh)
Sets the cursor column address to zero.
LF (0Ah)
Increments the cursor row address by one and follows the scroll up procedure as detailed in the paragraph above.

All other control characters are displayed.

TAB (09h) is not mentioned, so i assume that video_putch() is right to not implement it.

In the RBIL on INT 21,AH=02h i found a hint about where tab is implemented. From http://www.ctyme.com/intr/rb-2554.htm:

The last character output will be the character in DL unless DL=09h on entry, in which case AL=20h as tabs are expanded to blanks.

So in the real DOS, its likely the CON device driver doing the expansion from tabs to spaces.

Program to reproduce:

; switch output into video mode by doing harmless use of int 10h
mov ah, f
int 10
; print a tab
mov ah, 2
mov dl, 9
int 21
; exit
int 20

On emu2, the above program prints a ○ instead of the expected whitespaces.

Small change for OSX (no /proc)

Here is a suggestion for macOS support

dos.c:796

#if defined(APPLE) && defined(MACH)
uint32_t length=4096;
int _NSGetExecutablePath(char * buf, uint32_t * length);
if(_NSGetExecutablePath(exe_path,&length))
print_error("can't get emulator path.\n");
#else
if(readlink("/proc/self/exe", exe_path, 4096) == -1)
print_error("can't get emulator path.\n");
#endif

signal.h to allow compilation on Mac

Here are outputs of compilation on macosx:

src/dis.c:850:1: warning: control may reach end of non-void function
[-Wreturn-type]
}
^
1 warning generated.
gcc -O3 -flto -Wall -g -Werror=implicit-function-declaration -Werror=int-conversion -c -o obj/dos.o src/dos.c
src/dos.c:811:13: error: implicit declaration of function 'raise' is invalid in
C99 [-Werror,-Wimplicit-function-declaration]
raise(SIGABRT);

simply adding signal.h to dos.c sorts out compatibility.

No consistent flushing strategy

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?

Time to create a release of this software ?

Judging based solely on the screenshots, is it time to create a release of this software ?

Having a release is helpful because there is then a release version number to refer to, which can be sorted to determine when newer versions are available for package maintainers.

Add basic Installing to README

As far as I can tell installing is done the standard way with make and sudo make install. Installing instructions in the README would be appreciated.

Infinite loop when doing DIV instruction

I'm not sure whether this is an issue with my code or an issue with emu2. Either way, I'll report it.

Incidencia

Here's the procedure where this gets triggered:

capturar_dec proc
   mov     dx, 0
   mov     cx, 10000
   
bucle:
   cmp     cx, 1
   je      terminar
   
;; Capturar caracter
   mov     ah, 01h
   int     21h

;; Validar caracter
   cmp     al, '0'
   jl      terminar_error
   cmp     al, '9'
   jg      terminar_error

;; Recalcular base en CX
   push    ax
   mov     ax, cx
   mov     bl, 10
   div     bl
   mov     ah, 0
   mov     cx, ax
   pop     ax

;; Convertir caracter
   mov     ah, 0
   and     al, 0fh              ; aplicar masking a AL para convertir a número

;; Multiplicar por base
   push    dx
   mov     bx, cx
   mul     bx                   ; multiplicar AX * CX, resultado en DX:AX
   pop     dx
   
   add     dx, ax               ; acumulamos parte baja (AX) en DX como resultado

   jmp     bucle

terminar:
   ret

terminar_error:
;; Imprimir mensaje de error
   mov     ah, 09h
   lea     dx, msgerr
   int     21h

;; Terminar con código de error
   mov     ah, 4ch
   mov     al, 1
   int     21h
capturar_dec endp

CON doesn't seem to be emulated properly

When I enter TYPE CON > TEST.TXT in 4DOS, the shell says that it can't find the file. The same thing when I make CON my input file in Professional Music Driver's MML compiler. This doesn't happen in DOSBox-X, which waits for my input.

[Feature request] Memory debug

Hello! I'm still using emu2 for school, and so far, I haven't had any kind of problem. But today I noticed emu2 doesn't have a debug option to log memory, which is lame. :( It would be very useful.

Selection of ansi codepage to use during emulation

Hi there,
I have just tried emulating with Emu2 and it works very nice, it is only Dos emulator accessible for screenreaders, that I know of, thanks to its textual output.
I have just encountered problems with text encoding, while playing a Slovak textual arcade game. The game as I guess uses codepage for central Europe, while Emu2 uses some other, perhaps western Europe?
Those are just guesses, but definite thing is, that I get messed special characters, for example σ instead of ň, τ instead of š, £ instead of ť etc.
Is there something I could do about this? Is Emu2 responsible for encoding translation, or does it send just playn bytes to the console, to be handled by system?

Thanks for any help, and for the amazing program!

Another little FCB issue. 'Option Characters'

'/ ' is a separator character for the FCB building on DOS > 2.X 🙁

A tested fix in (src/loader.c:21) is:

static int valid_fcb_sep(int i)
{
    return isspace(i) || i == ',' || i == '=' || i == ';' ||
        (i == '/' && FCB_PARSE_DOS > 2);
}

under dos >3:

pspdump /a/b
CD 20 FF 9F 00 9A F0 FE  1D F0 C8 5A 00 F0 28 01  |  . .........Z..(. 
2F CC 10 01 2F CC 2F CC  01 03 01 00 02 FF FF FF  |  /..././......... 
FF FF FF FF FF FF FF FF  FF FF FF FF 01 07 DC FF  |  ................ 
57 07 14 00 18 00 57 07  FF FF FF FF 00 00 00 00  |  W.....W......... 
05 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
CD 21 CB 00 00 00 00 00  00 00 00 00 00 41 20 20  |  .!...........A   
20 20 20 20 20 20 20 20  00 00 00 00 00 42 20 20  |          .....B   
20 20 20 20 20 20 20 20  00 00 00 00 00 00 00 00  |          ........ 
05 20 2F 61 2F 62 0D 00  00 00 00 00 00 00 00 00  |  . /a/b.......... 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 

under emu2:
pspdump /a/b

CD 20 00 A0 00 9A F0 FE  1D F0 22 00 00 00 23 00  |  . ........"...#. 
00 00 24 00 00 00 FE FF  00 00 00 00 00 00 00 00  |  ..$............. 
00 00 00 00 00 00 00 00  00 00 00 00 81 00 60 FE  |  ..............`. 
87 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
CD 21 CB 00 00 00 00 00  00 00 00 00 00 20 20 20  |  .!...........    
20 20 20 20 20 20 20 20  00 00 00 00 00 20 20 20  |          .....    
20 20 20 20 20 20 20 20  00 00 00 00 00 00 00 00  |          ........ 
04 2F 61 2F 62 0D 00 00  00 00 00 00 00 00 00 00  |  ./a/b........... 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ................ 

Append Capacity Request

Hello, for old dos 1.x software, there is a regular need to do without disks and paths. Append on dos is a saving grace. I am happy to give it a go and propose a pull request/or put in a fork for scrutiny if you are interested.

Something like:

EMU2_APPEND=[<dos-path>];[<dos-path>] emu2 ...

Any recommendation? I see you are very thorough in your coding style and efficiency. I would by happy to follow any rules.

The simplest naive way would be to treat the case at dos_open_file / dos_open_file_fcb or embed it with dos_unix_path / dos_unix_path_fcb adding an append dos api...

  1. create flag ignores append
  2. the path needs to be 'naked', i.e. no drive decoration/path
  3. a single path in EM2_APPEND would go a long way

What do you think?

Support for Rename with FCB (Int 21/AH=17h)

Hi, I would like to give a go at implementing

DOS 2+ - RENAME - RENAME FILE

AH = 56h
DS:DX -> ASCIZ filename of existing file (no wildcards, but see below)
ES:DI -> ASCIZ new filename (no wildcards)
CL = attribute mask (server call only, see below)

Return:
CF clear if successful
CF set on error
AX = error code (02h,03h,05h,11h)

If you are ok with that, I will push a candidate. I would ignore wildcarding as on the delete.

Adding Parent PSP to New PSP Creation

Hello,

Following up on your todo:

        debug(debug_dos, "\toriginal PSP segment %04x.\n", get_current_PSP());
        debug(debug_dos, "\toriginal PSP size %02x%02x.\n", orig[7], orig[6]);
        // TODO: Initialize PSP values: int 22h, 23h, 24h and parent PSP segment to 0
        break;
    }
  1. Aren't the int values already there because of the copy we do from the initial PSP
  2. Would setting the Parent PSP be
         new_base[16] = (get_current_PSP()&0xFF);
         new_base[17] = ((get_current_PSP()>>8)&0xFF);

profiling trick

I'm not sure where to include this in your package (maybe in the README?), but I've found this handy:

EMU2_DEBUG="cpu" emu2 whatever.exe
cut -b 129- whatever.exe-cpu.0.log | sort | uniq -c > whatever.exe.profile.0

This shows all of the instructions used in the given round of execution, as well as how many times each instruction was executed.

Regardless of what you decide, thank you for the awesome program.

Support for Truename (Int 21/AH=60h)

Would you be open to add this function? I am happy to provide trial implementation and tests

AH = 60h
DS:SI -> ASCIZ filename or path
ES:DI -> 128-byte buffer for canonicalized name

Return:
CF set on error
AX = error code
02h invalid component in directory path or drive letter only
03h malformed path or invalid drive letter
ES:DI buffer unchanged
CF clear if successful
AH = 00h or 3Ah (DOS 6.1/6.2 for character device)
AL = destroyed (00h or 2Fh or 5Ch or last character of current
directory on drive)

Various DOS Program Bugs under emu2

  • IBM PKZIP/PKUNZIP 2.06 works correctly, but without displaying any output. (Fixed)
  • IBM FileCommand II paints a blue screen and does not continue. (Moved)
  • IBM MYMENU (part of IBM Professional Editor II V1.35) does not start. (Fixed)
  • IBM Professional Editor II V1.35 (after un-EXEPACK'ing or LOADFIX) works fine for all editing functions, but locks up when attempting to display directory listings. (Update) (Moved)
  • Fifth Gen. Systems Direct Access 5.19 does not start once uncompressed or installed. (Moved)
    • When using the DA Decompression Utility (DA_DCMP.EXE, i.e. DA_DCMP.EXE LOGO_TXT.DA5), filenames that are less than eight characters are incorrectly padded with spaces, for example LOGO.TXT becomes LOGO.TXT . (Moved)
  • While of limited utility (as later MSC releases require a 386), Microsoft Programmer's Workbench IDE for DOS (PWB.EXE) displays a spurious error starting from the MSC7 BIN directory, (which doesn't happen under DOS): (Moved)

I haven't looked into causes myself, but perhaps I can this weekend.

I can also split these into separate issues, if you prefer. (Done)

Small typo

diff --git a/src/dbg.c b/src/dbg.c
index ddfee79..07ca718 100644
--- a/src/dbg.c
+++ b/src/dbg.c
@@ -23,21 +23,21 @@ void print_usage(void)
            "Environment variables:\n"
            "  %-18s  Base name of a file to write the debug log, defaults to\n"
            "\t\t      the exe name if not given.\n"
            "  %-18s  List of debug options to activate, from the following:\n"
            "\t\t      'cpu', 'int', 'port', 'dos', 'video'.\n"
            "  %-18s  DOS program name, if not given use the unix name.\n"
            "  %-18s  DOS default (current) drive letter, if not given use 'C:'\n"
            "  %-18s  DOS current working directory, use 'C:\\' if not given.\n"
            "  %-18s  Set unix path as root of drive 'n', by default all drives\n"
            "\t\t      point to the unix working directory.\n"
-           "  %-18s  Set DOS code-page. Set to '?' to show lost of code-pages.\n"
+           "  %-18s  Set DOS code-page. Set to '?' to show list of code-pages.\n"
            "  %-18s  Limit DOS memory to 512KB, fixes some old buggy programs.\n"
            "  %-18s  Specifies a DOS append paths, separated by ';'.\n",
            prog_name, ENV_DBG_NAME, ENV_DBG_OPT, ENV_PROGNAME, ENV_DEF_DRIVE, ENV_CWD,
            ENV_DRIVE "n", ENV_CODEPAGE, ENV_LOWMEM, ENV_APPEND);
     exit(EXIT_SUCCESS);
 }

 void print_usage_error(const char *format, ...)
 {
     va_list ap;

No stdout output running under node-pty

I'm attempting to use emu2 to run some old text mode DOS applications under https://github.com/microsoft/node-pty for the purpose of a BBS "door". Essentially I launch emu2 under node-pty's spawn() and capture stdout. Input from the user is sent to stdin.

Currently I'm trying this with Sleuth. When run from a standard Linux terminal, everything is fine. When run as described as above, I do not get any output.

I use the same technique for launching native OS binaries without issue.

Any ideas? I can provide any of the debug logs if they would be helpful.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.