Skip to content

Commit

Permalink
Put the CON driver elsewhere, cleanup allocation a bit, arrange the S…
Browse files Browse the repository at this point in the history
…FT tables into a primary table of 5 and a secondary of N - 5 to match how MS-DOS arranges it
  • Loading branch information
joncampbell123 committed Jun 3, 2024
1 parent 1544a71 commit 13a81c4
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 16 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: Put the CON driver somewhere else because allowing it
to overlap the SFT is messy. Fix SFT generation to match the way that
MS-DOS 5.0 does it where the first table is always 5 entries and the
second table is always N - 5 entries. Cleanup the DOS memory allocation
a bit. So far, Windows 3.1 doesn't have a problem with it. (joncampbell123).
- DOS kernel: Interrupt handler IRET was accidentally placed within
the SFT table, move it up to resolve the conflict. (joncampbell123).
- Local DOS drive support: On Windows, if the guest is attempting to
Expand Down
26 changes: 15 additions & 11 deletions src/dos/dos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4310,9 +4310,9 @@ class DOS:public Module_base{
LOG(LOG_DOSMISC,LOG_DEBUG)("DOS kernel structures will be allocated from pool 0x%04x-0x%04x",
DOS_PRIVATE_SEGMENT,DOS_PRIVATE_SEGMENT_END-1);

DOS_IHSEG = DOS_GetMemory(1,"DOS_IHSEG");
DOS_IHSEG = DOS_GetMemory(1,"DOS_IHSEG");

/* DOS_INFOBLOCK_SEG contains the entire List of Lists, though the INT 21h call returns seg:offset with offset nonzero */
/* DOS_INFOBLOCK_SEG contains the entire List of Lists, though the INT 21h call returns seg:offset with offset nonzero */
/* NTS: DOS_GetMemory() allocation sizes are in PARAGRAPHS (16-byte units) not bytes */
/* NTS: DOS_INFOBLOCK_SEG must be 0x20 paragraphs, CONDRV_SEG 0x08 paragraphs, and CONSTRING_SEG 0x0A paragraphs.
* The total combined size of INFOBLOCK+CONDRV+CONSTRING must be 0x32 paragraphs.
Expand All @@ -4325,16 +4325,20 @@ class DOS:public Module_base{
* See also:
*
* [https://www.os2museum.com/wp/how-to-void-your-valuable-warranty/]
* [https://www.os2museum.com/files/drdos_detect.txt]
* [https://www.os2museum.com/wp/about-that-warranty/]
* [https://github.com/joncampbell123/dosbox-x/issues/3626]
* [https://www.os2museum.com/files/drdos_detect.txt]
* [https://www.os2museum.com/wp/about-that-warranty/]
* [https://github.com/joncampbell123/dosbox-x/issues/3626]
*/
DOS_INFOBLOCK_SEG = DOS_GetMemory(0x20,"DOS_INFOBLOCK_SEG"); // was 0x80
DOS_CONDRV_SEG = DOS_GetMemory(0x08,"DOS_CONDRV_SEG"); // was 0xA0
DOS_CONSTRING_SEG = DOS_GetMemory(0x0A,"DOS_CONSTRING_SEG"); // was 0xA8
DOS_SDA_SEG = DOS_GetMemory(DOS_SDA_SEG_SIZE>>4,"DOS_SDA_SEG"); // was 0xB2 (0xB2 + 0x56 = 0x108)
DOS_SDA_OFS = 0;
DOS_CDS_SEG = DOS_GetMemory(0x10,"DOS_CDA_SEG"); // was 0x108

// FIXME: 0x32 paragraphs (0x320 bytes) might not be enough for the second half of the SFT table placed at segment +0x26:0!
DOS_INFOBLOCK_SEG = DOS_GetMemory(0x32,"DOS_INFOBLOCK_SEG"); // was 0x80 0x32 = 0x20(INFOBLOCK) + 0x08(old CONDRV_SEG) + 0x0A(CONSTRING_SEG)
DOS_CONSTRING_SEG = DOS_INFOBLOCK_SEG + 0x28; // was 0xA8
DOS_SDA_SEG = DOS_GetMemory(DOS_SDA_SEG_SIZE>>4,"DOS_SDA_SEG"); // was 0xB2 (0xB2 + 0x56 = 0x108)
DOS_SDA_OFS = 0;

/* 2024/06/02: Keep the CON driver away from the clusterfuck of the INFOBLOCK and SFT mess */
DOS_CONDRV_SEG = DOS_GetMemory(0x04,"DOS_CONDRV_SEG"); // was 0xA0
DOS_CDS_SEG = DOS_GetMemory(0x10,"DOS_CDA_SEG"); // was 0x108

LOG(LOG_DOSMISC,LOG_DEBUG)("DOS kernel alloc:");
LOG(LOG_DOSMISC,LOG_DEBUG)(" IHSEG: seg 0x%04x",DOS_IHSEG);
Expand Down
23 changes: 18 additions & 5 deletions src/dos/dos_classes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,26 @@ void DOS_InfoBlock::SetLocation(uint16_t segment) {
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
/* Create a fake SFT, so programs think there are 100 file handles */
uint16_t sftOffset=offsetof(sDIB,firstFileTable)+0xa2;
/* 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
* second table is N - 5 entries. Maybe this is why MS-DOS doesn't let you specify a number below, I think, 6? in
* FILES= under CONFIG.SYS.
*
* 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");

uint16_t sftOffset=0xCC; /* this offset is fixed according to MS-DOS 5.0, MS-DOS 6.22, Windows 95, etc. */
sSave(sDIB,firstFileTable,RealMake(segment,sftOffset));
real_writed(segment,sftOffset+0x00,RealMake(segment+0x26,0)); //Next File Table
real_writew(segment,sftOffset+0x04,DOS_FILES/2); //File Table supports DOS_FILES/2 files
real_writed(segment+0x26,0x00,0xffffffff); //Last File Table
real_writew(segment+0x26,0x04,DOS_FILES-DOS_FILES/2); //File Table supports DOS_FILES/2 files
real_writew(segment,sftOffset+0x04,5); //File Table supports 5 files

if ((sftOffset+SftHeaderSize+(5*SftEntrySize)) > 0x200) E_Exit("Primary SFT is too big");

// 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
#else
/* Imported from dosbox-staging/dosbox-staging#3680 */
constexpr int FakeHandles = 100;
Expand Down

0 comments on commit 13a81c4

Please sign in to comment.