Skip to content

Commit

Permalink
Dynamically allocate the second half of the SFT table, zero memory to…
Browse files Browse the repository at this point in the history
… avoid problems. Windows 3.1 is still pefectly happy with it
  • Loading branch information
joncampbell123 committed Jun 3, 2024
1 parent 83d5a0a commit 544e9e4
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
Next:
- DOS kernel: Remove fixed hacks for SFT and dynamically allocate the
second SFT table for the last N - 5 file handles. Add code to zero
SFT table memory to ensure that random data doesn't cause issues.
Windows 3.1 is still perfectly fine with it, so the SFT table update
and cleanup is complete. (joncampbell123).
- DOS kernel: Move the magic "CON" strings into the first SFT and
mimic the 5 default open file handles that every DOS process starts
with: CON CON CON AUX PRN. Windows 3.1 is still happy with it, which
Expand Down
19 changes: 13 additions & 6 deletions src/dos/dos_classes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void DOS_InfoBlock::SetLocation(uint16_t segment) {
sSave(sDIB,nulString[6],(uint8_t)0x20);
sSave(sDIB,nulString[7],(uint8_t)0x20);

#if 1 // FIXME: The new code imported from DOSBox Staging is causing Windows 3.1 to crash on exit, so this old code remains active until that can be fixed
#if 1
/* Create a fake SFT, so programs think there are 100 file handles.
* NTS: The INFO block is only given 0x20 paragraphs (0x200 = 512 bytes) which is only enough for a 5-entry SFT table,
* however that's what MS-DOS does anyway. For any value of FILES you specify, the first SFT is 5 entries and the
Expand All @@ -136,9 +136,16 @@ void DOS_InfoBlock::SetLocation(uint16_t segment) {
* The table must be 5, or else it extends into other DOS kernel structures and memory corruption might happen. */
if (DOS_FILES < 6) E_Exit("[dos] files= setting is too small");

/* Secondary table */
unsigned int tbl2_seg = DOS_GetMemory((SftHeaderSize+(SftEntrySize*(DOS_FILES-5))+0xFu)/16u,"SFT secondary table");

uint16_t sftOffset=0xCC; /* this offset is fixed according to MS-DOS 5.0, MS-DOS 6.22, Windows 95, etc. */

/* zero out the table */
for (unsigned int i=sftOffset;i < 0x200;i++) real_writeb(segment,i,0);

sSave(sDIB,firstFileTable,RealMake(segment,sftOffset));
real_writed(segment,sftOffset+0x00,RealMake(segment+0x26,0)); //Next File Table
real_writed(segment,sftOffset+0x00,RealMake(tbl2_seg,0)); //Next File Table
real_writew(segment,sftOffset+0x04,5); //File Table supports 5 files

if ((sftOffset+SftHeaderSize+(5*SftEntrySize)) > 0x200) E_Exit("Primary SFT is too big");
Expand All @@ -156,10 +163,10 @@ void DOS_InfoBlock::SetLocation(uint16_t segment) {
real_writed(segment,sftOffset+SftHeaderSize+(SftEntrySize*3)+0x20,0x20585541); // AUX
real_writed(segment,sftOffset+SftHeaderSize+(SftEntrySize*4)+0x20,0x204e5250); // PRN

// FIXME: This must be segment+0x26 (DOS_CONSTRING_SEG-2) because some magic "CON" strings must be written there
// to make Windows 3.1 happy.
real_writed(segment+0x26,0x00,0xffffffff); //Last File Table
real_writew(segment+0x26,0x04,DOS_FILES-5); //File Table supports DOS_FILES-5 files
/* zero out the table */
for (unsigned int i=0;i < (SftHeaderSize+(SftEntrySize*(DOS_FILES-5)));i++) real_writeb(tbl2_seg,i,0);
real_writed(tbl2_seg,0x00,0xFFFFFFFFu);
real_writew(tbl2_seg,0x04,DOS_FILES-5);

#else
/* Imported from dosbox-staging/dosbox-staging#3680 */
Expand Down

0 comments on commit 544e9e4

Please sign in to comment.