Dynamically allocate the second half of the SFT table, zero memory to avoid problems. Windows 3.1 is still pefectly happy with it

This commit is contained in:
Jonathan Campbell
2024-06-02 20:00:28 -07:00
parent 83d5a0a5ae
commit 544e9e4a27
2 changed files with 18 additions and 6 deletions

View File

@@ -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

View File

@@ -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
@@ -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");
@@ -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 */