VOGONS


INT21h and EOF

Topic actions

First post, by james.harper

User metadata
Rank Newbie
Rank
Newbie

I am trying to get an ancient DOS program working on newer hardware and under Windows XP. It's an upload/download app that talks to a cutting machine, sending and receiving program instructions which are just text files. I fixed one problem in DosBox where it called INT21h function 0x33/0x0b (don't know what that is but I just ignored it instead of crashing DosEmu), and have one final issue to resolve.

Everything works except for sending files. Basically the application doesn't ever see the end of file unless it has an actual EOF (^Z) character in it. It works fine on the original laptop running Win95 DOS with any file though.

I added some debug statements to INT21h 0x3F (read) and found for the working file (with the ^Z at the end) (each read is for one byte):

Read 1 byte
...
Read 1 byte (EOF char)
Read 0 bytes (eg no more data)
success!

and for the not working file (no ^Z)

Read 1 byte
...
Read 1 byte
Read 0 bytes
Read 0 bytes
...
Read 0 bytes forever

So i'm thinking that maybe DOS puts an EOF character in there automatically for the application or something when the file is a text file? I can't see anything to that effect in any of the various documentation for INT21h found via google though.

Can anyone make any suggestions? I'm running DOSBox under Windows, I can't easily bring a Linux machine on site to test if that makes any difference. DOSBox is 0.74 that I have compiled myself. I can't test the distributed binary of 0.74 as my application crashes out immediately when it tries to call INT21h 0x33/0x0b so I need to patch DOSBox to get my application to load at all.

Thanks!

James

Reply 1 of 18, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

When reading a file with INT 21h/AH=3Fh, MS-DOS does not "add" an EOF character at end of file, nor does it return an error when at end of file; it only returns 0 bytes read in AX, and it's up to a program to understand that AX=0 means end of file. There may be something else going on in the application in question, but I don't think it's because of function 3Fh, because DOSBox appears to be handling it exactly right compared to MS-DOS.

BTW, is the text file being opened directly with function 3Dh, or is the file being read through redirection of the STDIN/CON device?

Regarding function 33h, the RBIL does not document subfunction 0Bh, but it does say:

DR DOS 5.0 and 6.0 return CF set/AX=0001h for INT 21/AH=33h subfunctions other than 00h-02h and 05h, while MS-DOS returns AL=FFh for invalid subfunctions.

MS-DOS does indeed return AL=FFh for subfunction 0Bh. DOSBox exits to error for a number of unknown function calls rather than returning some kind of error like MS-DOS, and my understanding is that this is done intentionally to make it obvious that a program is doing something unusual and possibly unsupported. It's very easy to change the DOSBox source to return AL=FFh, which it seems you've already done.

Reply 2 of 18, by james.harper

User metadata
Rank Newbie
Rank
Newbie

When reading a file with INT 21h/AH=3Fh, MS-DOS does not "add" an EOF character at end of file, nor does it return an error when at end of file; it only returns 0 bytes read in AX, and it's up to a program to understand that AX=0 means end of file. There may be something else going on in the application in question, but I don't think it's because of function 3Fh, because DOSBox appears to be handling it exactly right compared to MS-DOS.

Yes, after pretty much exhaustively reading what google has to say about it i'm inclined to agree. I guess that leaves some other subtle difference between Win95 DOS and DosBox, which is going to be hard to debug (or at least much harder than a few printfs in INT 21h!)...

thanks for the reply!

James

Reply 3 of 18, by james.harper

User metadata
Rank Newbie
Rank
Newbie

BTW, is the text file being opened directly with function 3Dh, or is the file being read through redirection of the STDIN/CON device?

It turns out, after much digging, that the file is opened with 0f (DOS_FCBOpen), and read with 27 (DOS_FCBRandomRead). DOS_FCBRandomRead has a few comments with words like 'bug' and 'unsure', so I think i've finally tracked down where the problem lies! Should be easy enough to fix I hope. Do I just post the fix on here once i have something that works?

James

Reply 4 of 18, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

If the file is being opened and read with an FCB, I have to wonder how the "debug statements" you added to function 3Fh produced anything like what you reported in your initial posting...

Anyway, the "Not implemented yet" comment on the FCB random read function pretty much speaks for itself. It seems to me that reg_cx would be passed by reference from function 0x27 of the int21 handler, and numRec set to the number of records read in the function (numRec=(Bit16u)i;), the uncertainty is what the returned value should be when the last record read is a zero or partial read.

I'm sure the functionality would have been fully implemented by now if it was needed by a game.

Reply 5 of 18, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

if you find a bug in randomread, then just post a fix here and we will confirm the correctness of the fix.

Water flows down the stream
How to ask questions the smart way!

Reply 6 of 18, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

I think something that hasn't been implemented is not a bug per se, but this appears to cover the missing functionality. Checked that partial reads count in the number of records read but zero reads do not, and also checked that calling function 0x27 with CX=0 returns no error and CX=0.

Reply 7 of 18, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

if it fixes the problem the OP has, than I have no problems with the proposed modifications

Water flows down the stream
How to ask questions the smart way!

Reply 8 of 18, by james.harper

User metadata
Rank Newbie
Rank
Newbie

If the file is being opened and read with an FCB, I have to wonder how the "debug statements" you added to function 3Fh produced anything like what you reported in your initial posting...

Yes that's where I went wrong initially. I added my debug statements to DOS_ReadFile and (foolishly) assumed that it only got called from 3Fh. It turns out that it gets called from all sorts of places for all sorts of reasons.

Anyway, the "Not implemented yet" comment on the FCB random read function pretty much speaks for itself. It seems to me that reg_cx would be passed by reference from function 0x27 of the int21 handler, and numRec set to the number of records read in the function (numRec=(Bit16u)i;)

Yes i've done exactly that. No fix so far...

the uncertainty is what the returned value should be when the last record read is a zero or partial read.

Well the literature i've been reading says that a completely zero read should return NODATA, and a read of some records but less than the number requested should return PARTIAL. I've implemented that too but still haven't had any luck. I'm now hoping to find a problem with record counting or something...

Reply 10 of 18, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

erm, if the logging was on DOS_ReadFile(), then that doesn't suggest FCBs are involved...

Also, to restate my previous question, is the file being read through redirection of STDIN? There could be an issue with that.

Reply 11 of 18, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

fcb_read uses dos_readfile.
He probably had logging in dos_files.cpp instead of dos.cpp

Water flows down the stream
How to ask questions the smart way!

Reply 12 of 18, by james.harper

User metadata
Rank Newbie
Rank
Newbie

did you try ripsaw's patch ?

I didn't see it until you pointed it out. I'm not used to this forum and find the color scheme a bit difficult on the eyes (i guess there is a prefs system where I can change that?). Having looked at the patch, it's more or less identical to what i've done, and I think it might be working now. Thanks ripsaw!

The program in question talks via serial port to a cutting machine (used for tool sharpening). I've reverse engineered the serial protocol enough that I can fake the file transmission but having never seen the successful transmission work yet I can't fake the 'file received successfully' message. But having said that, it is behaving more like it's finished and just waiting for the cnc machine to sign off, rather than trying to keep transmitting the same final blocks over and over. I'll test tomorrow and confirm.

Thanks a lot for taking the time to look at this. I suspect that the fcb random write routine is similarly afflicted, but a 'short write' condition would be much rarer.

Is it too much to ask to log & continue when an unknown INT 21h subfunction 33h sub-sub function is called (instead of E_Exit("DOS:Illegal 0x33 Call %2X",reg_al);)? If that can be added I can work with the mainstream DOSBox instead of needing to patch and compile my own. I'm thinking along the lines of:

default:
LOG_MSG("INT 21h 0x33/0x%02x", reg_al);
reg_al = 0xff;
CALLBACK_SCF(true);
break;

Thanks again!

James

Reply 13 of 18, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

sure about the carry flag true ?

Water flows down the stream
How to ask questions the smart way!

Reply 14 of 18, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

heh, history repeats itself: Program makes an illegal call

And no, the carry flag is not set by MS-DOS for invalid subfunctions.

Reply 16 of 18, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

I don't see any uncertain rules about the record count returned for the random block write, and I implemented it as well. The code consistency is a good thing, even if there is no immediate need for the functionality (only an error would cause the returned count to differ from the requested number).

Reply 17 of 18, by james.harper

User metadata
Rank Newbie
Rank
Newbie
ripsaw8080 wrote:

I don't see any uncertain rules about the record count returned for the random block write, and I implemented it as well. The code consistency is a good thing, even if there is no immediate need for the functionality (only an error would cause the returned count to differ from the requested number).

I can confirm that my version of your first patch, which appears to be functionally identical to yours, works perfectly.

Once you have committed it, what's the easiest way to get to the tree with the patch in it for final testing?

Thanks

James

Reply 18 of 18, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

I already commited the stuff yesterday.
(both the fcb read/write and the int21 33 X calls)

Water flows down the stream
How to ask questions the smart way!