Skip to content

Commit

Permalink
Allocate enough memory to store the System File Table (SFT)
Browse files Browse the repository at this point in the history
  • Loading branch information
maron2000 committed May 28, 2024
1 parent 85eec1f commit 34a5c68
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 2 deletions.
49 changes: 48 additions & 1 deletion include/dos_inc.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,48 @@

#include <list>
#include <stddef.h> //for offsetof

/* Macros SSET_* and SGET_* are used to safely access fields in memory-mapped
* DOS structures represented via classes inheriting from MemStruct class.
*
* All of these macros depend on 'pt' base pointer from MemStruct base class;
* all DOS-specific fields are accessed by reading memory relative to that
* pointer.
*
* Example usage:
*
* SSET_WORD(dos-structure-name, field-name, value);
* uint16_t x = SGET_WORD(dos-structure-name, field-name);
*/
template <size_t N, typename S, typename T1, typename T2 = T1>
constexpr PhysPt assert_macro_args_ok()
{
static_assert(sizeof(T1) == N, "Requested struct field has unexpected size");
static_assert(sizeof(T2) == N, "Type used to save value has unexpected size");
static_assert(std::is_standard_layout<S>::value,
"Struct needs to have standard layout for offsetof calculation");
// returning 0, so compiler can optimize-out no-op "0 +" expression
return 0;
}

#define VERIFY_SSET_ARGS(n, s, f, v) \
assert_macro_args_ok<n, s, decltype(s::f), decltype(v)>()
#define VERIFY_SGET_ARGS(n, s, f) \
assert_macro_args_ok<n, s, decltype(s::f)>()

#define SSET_BYTE(s, f, v) \
mem_writeb(VERIFY_SSET_ARGS(1, s, f, v) + pt + offsetof(s, f), v)
#define SSET_WORD(s, f, v) \
mem_writew(VERIFY_SSET_ARGS(2, s, f, v) + pt + offsetof(s, f), v)
#define SSET_DWORD(s, f, v) \
mem_writed(VERIFY_SSET_ARGS(4, s, f, v) + pt + offsetof(s, f), v)

#define SGET_BYTE(s, f) \
mem_readb(VERIFY_SGET_ARGS(1, s, f) + pt + offsetof(s, f))
#define SGET_WORD(s, f) \
mem_readw(VERIFY_SGET_ARGS(2, s, f) + pt + offsetof(s, f))
#define SGET_DWORD(s, f) \
mem_readd(VERIFY_SGET_ARGS(4, s, f) + pt + offsetof(s, f))

#ifdef _MSC_VER
#pragma pack (1)
Expand Down Expand Up @@ -153,6 +195,10 @@ extern uint16_t DOS_MEM_START;// 0x158 // regression to r3437 fixes nascar 2 co

extern uint16_t DOS_PRIVATE_SEGMENT;// 0xc800
extern uint16_t DOS_PRIVATE_SEGMENT_END;// 0xd000

constexpr int SftHeaderSize = 6;
constexpr int SftEntrySize = 59;
constexpr int SftNumEntries = 16;

/* internal Dos Tables */

Expand Down Expand Up @@ -276,7 +322,8 @@ bool DOS_AllocateMemory(uint16_t * segment,uint16_t * blocks);
bool DOS_ResizeMemory(uint16_t segment,uint16_t * blocks);
bool DOS_FreeMemory(uint16_t segment);
void DOS_FreeProcessMemory(uint16_t pspseg);
uint16_t DOS_GetMemory(uint16_t pages,const char *who=NULL);
uint16_t DOS_GetMemory(uint16_t pages,const char *who=NULL);
void DOS_FreeTableMemory();
bool DOS_SetMemAllocStrategy(uint16_t strat);
uint16_t DOS_GetMemAllocStrategy(void);
void DOS_BuildUMBChain(bool umb_active,bool ems_active);
Expand Down
1 change: 1 addition & 0 deletions src/dos/dos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4715,6 +4715,7 @@ class DOS:public Module_base{
DOS_ShutdownFiles();
void DOS_ShutdownDevices(void);
DOS_ShutdownDevices();
DOS_FreeTableMemory();
RealSetVec(0x30,int30);
RealSetVec(0x31,int31);
}
Expand Down
31 changes: 30 additions & 1 deletion src/dos/dos_classes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,42 @@ void DOS_InfoBlock::SetLocation(uint16_t segment) {
sSave(sDIB,nulString[6],(uint8_t)0x20);
sSave(sDIB,nulString[7],(uint8_t)0x20);

/* Create a fake SFT, so programs think there are 100 file handles */
#if 0
/* Create a fake SFT, so programs think there are 100 file handles */
uint16_t sftOffset=offsetof(sDIB,firstFileTable)+0xa2;
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
#endif
/* Imported from dosbox-staging/dosbox-staging#3680 */
constexpr int FakeHandles = 100;

constexpr uint32_t EndPointer = 0xffffffff;
constexpr uint16_t NextTableOffset = 0x0;
constexpr uint16_t NumberOfFilesOffset = 0x04;

// We only need to actually allocate enough space for 16 handles
// This is the maximum that will get written to by DOS_MultiplexFunctions() in dos_misc.cpp
constexpr int BytesPerPage = 16;
constexpr int TotalBytes = SftHeaderSize + (SftEntrySize * SftNumEntries);
constexpr int NumPages = (TotalBytes / BytesPerPage) + (TotalBytes % BytesPerPage > 0 ? 1 : 0);

const uint16_t first_sft_segment = DOS_GetMemory(NumPages);
const RealPt first_sft_addr = RealMake(first_sft_segment, 0);
SSET_DWORD(sDIB, firstFileTable, first_sft_addr);

// Windows for Workgroups requires a 2nd linked SFT table
// This one only needs to allocate the header
const uint16_t second_sft_segment = DOS_GetMemory(1);
const RealPt second_sft_addr = RealMake(second_sft_segment, 0);

real_writed(first_sft_segment, NextTableOffset, second_sft_addr);
real_writew(first_sft_segment, NumberOfFilesOffset, FakeHandles);

real_writed(second_sft_segment, NextTableOffset, EndPointer);
real_writew(second_sft_segment, NumberOfFilesOffset, FakeHandles);
}

void DOS_InfoBlock::SetFirstMCB(uint16_t _firstmcb) {
Expand Down
5 changes: 5 additions & 0 deletions src/dos/dos_tables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ void DOS_GetMemory_reset() {
dos_memseg = 0;
}

void DOS_FreeTableMemory()
{
dos_memseg = DOS_PRIVATE_SEGMENT;
}

void DOS_GetMemory_reinit() {
DOS_GetMemory_unmapped = false;
DOS_GetMemory_reset();
Expand Down

0 comments on commit 34a5c68

Please sign in to comment.