/* * Copyright (C) 2002-2019 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef DOSBOX_DOS_INC_H #define DOSBOX_DOS_INC_H #ifndef DOSBOX_DOS_SYSTEM_H #include "dos_system.h" #endif #ifndef DOSBOX_MEM_H #include "mem.h" #endif #include //for offsetof #ifdef _MSC_VER #pragma pack (1) #endif struct CommandTail{ Bit8u count; /* number of bytes returned */ char buffer[127]; /* the buffer itself */ } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack () #endif struct DOS_Date { Bit16u year; Bit8u month; Bit8u day; }; struct DOS_Version { Bit8u major,minor,revision; }; #ifdef _MSC_VER #pragma pack (1) #endif union bootSector { struct entries { Bit8u jump[3]; Bit8u oem_name[8]; Bit16u bytesect; Bit8u sectclust; Bit16u reserve_sect; Bit8u misc[496]; } bootdata; Bit8u rawdata[512]; } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack () #endif enum { MCB_FREE=0x0000,MCB_DOS=0x0008 }; enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3}; #define DOS_FILES 127 #define DOS_DRIVES 26 #define DOS_DEVICES 10 // dos swappable area is 0x320 bytes beyond the sysvars table // device driver chain is inside sysvars #define DOS_INFOBLOCK_SEG 0x80 // sysvars (list of lists) #define DOS_CONDRV_SEG 0xa0 #define DOS_CONSTRING_SEG 0xa8 #define DOS_SDA_SEG 0xb2 // dos swappable area #define DOS_SDA_OFS 0 #define DOS_CDS_SEG 0x108 #define DOS_FIRST_SHELL 0x118 #define DOS_MEM_START 0x16f //First Segment that DOS can use #define DOS_PRIVATE_SEGMENT 0xc800 #define DOS_PRIVATE_SEGMENT_END 0xd000 /* internal Dos Tables */ extern DOS_File * Files[DOS_FILES]; extern DOS_Drive * Drives[DOS_DRIVES]; extern DOS_Device * Devices[DOS_DEVICES]; extern Bit8u dos_copybuf[0x10000]; void DOS_SetError(Bit16u code); /* File Handling Routines */ enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDPRN=4}; enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE}; /* Routines for File Class */ void DOS_SetupFiles (void); bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount, bool fcb = false); bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount,bool fcb = false); bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type,bool fcb = false); bool DOS_CloseFile(Bit16u handle,bool fcb = false); bool DOS_FlushFile(Bit16u handle); bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry); bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry); bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate); /* Routines for Drive Class */ bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry,bool fcb = false); bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status); bool DOS_CreateFile(char const * name,Bit16u attribute,Bit16u * entry, bool fcb = false); bool DOS_UnlinkFile(char const * const name); bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false); bool DOS_FindNext(void); bool DOS_Canonicalize(char const * const name,char * const big); bool DOS_CreateTempFile(char * const name,Bit16u * entry); bool DOS_FileExists(char const * const name); /* Helper Functions */ bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive); /* Drive Handing Routines */ Bit8u DOS_GetDefaultDrive(void); void DOS_SetDefaultDrive(Bit8u drive); bool DOS_SetDrive(Bit8u drive); bool DOS_GetCurrentDir(Bit8u drive,char * const buffer); bool DOS_ChangeDir(char const * const dir); bool DOS_MakeDir(char const * const dir); bool DOS_RemoveDir(char const * const dir); bool DOS_Rename(char const * const oldname,char const * const newname); bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free); bool DOS_GetFileAttr(char const * const name,Bit16u * attr); bool DOS_SetFileAttr(char const * const name,Bit16u attr); /* IOCTL Stuff */ bool DOS_IOCTL(void); bool DOS_GetSTDINStatus(); Bit8u DOS_FindDevice(char const * name); void DOS_SetupDevices(void); /* Execute and new process creation */ bool DOS_NewPSP(Bit16u pspseg,Bit16u size); bool DOS_ChildPSP(Bit16u pspseg,Bit16u size); bool DOS_Execute(char * name,PhysPt block,Bit8u flags); void DOS_Terminate(Bit16u pspseg,bool tsr,Bit8u exitcode); /* Memory Handling Routines */ void DOS_SetupMemory(void); bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks); bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks); bool DOS_FreeMemory(Bit16u segment); void DOS_FreeProcessMemory(Bit16u pspseg); Bit16u DOS_GetMemory(Bit16u pages); bool DOS_SetMemAllocStrategy(Bit16u strat); Bit16u DOS_GetMemAllocStrategy(void); void DOS_BuildUMBChain(bool umb_active,bool ems_active); bool DOS_LinkUMBsToMemChain(Bit16u linkstate); /* FCB stuff */ bool DOS_FCBOpen(Bit16u seg,Bit16u offset); bool DOS_FCBCreate(Bit16u seg,Bit16u offset); bool DOS_FCBClose(Bit16u seg,Bit16u offset); bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset); bool DOS_FCBFindNext(Bit16u seg,Bit16u offset); Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset, Bit16u numBlocks); Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u numBlocks); Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u * numRec,bool restore); Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u * numRec,bool restore); bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset); bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset); bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset); void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset); Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change); bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters); /* Extra DOS Interrupts */ void DOS_SetupMisc(void); /* The DOS Tables */ void DOS_SetupTables(void); /* Internal DOS Setup Programs */ void DOS_SetupPrograms(void); /* Initialize Keyboard Layout */ void DOS_KeyboardLayout_Init(Section* sec); bool DOS_LayoutKey(Bitu key, Bit8u flags1, Bit8u flags2, Bit8u flags3); enum { KEYB_NOERROR=0, KEYB_FILENOTFOUND, KEYB_INVALIDFILE, KEYB_LAYOUTNOTFOUND, KEYB_INVALIDCPFILE }; static INLINE Bit16u long2para(Bit32u size) { if (size>0xFFFF0) return 0xffff; if (size&0xf) return (Bit16u)((size>>4)+1); else return (Bit16u)(size>>4); } static INLINE Bit16u DOS_PackTime(Bit16u hour,Bit16u min,Bit16u sec) { return (hour&0x1f)<<11 | (min&0x3f) << 5 | ((sec/2)&0x1f); } static INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) { return ((year-1980)&0x7f)<<9 | (mon&0x3f) << 5 | (day&0x1f); } /* Dos Error Codes */ #define DOSERR_NONE 0 #define DOSERR_FUNCTION_NUMBER_INVALID 1 #define DOSERR_FILE_NOT_FOUND 2 #define DOSERR_PATH_NOT_FOUND 3 #define DOSERR_TOO_MANY_OPEN_FILES 4 #define DOSERR_ACCESS_DENIED 5 #define DOSERR_INVALID_HANDLE 6 #define DOSERR_MCB_DESTROYED 7 #define DOSERR_INSUFFICIENT_MEMORY 8 #define DOSERR_MB_ADDRESS_INVALID 9 #define DOSERR_ENVIRONMENT_INVALID 10 #define DOSERR_FORMAT_INVALID 11 #define DOSERR_ACCESS_CODE_INVALID 12 #define DOSERR_DATA_INVALID 13 #define DOSERR_RESERVED 14 #define DOSERR_FIXUP_OVERFLOW 14 #define DOSERR_INVALID_DRIVE 15 #define DOSERR_REMOVE_CURRENT_DIRECTORY 16 #define DOSERR_NOT_SAME_DEVICE 17 #define DOSERR_NO_MORE_FILES 18 #define DOSERR_FILE_ALREADY_EXISTS 80 /* Remains some classes used to access certain things */ #define sOffset(s,m) ((char*)&(((s*)NULL)->m)-(char*)NULL) #define sGet(s,m) GetIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m)) #define sSave(s,m,val) SaveIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m),val) class MemStruct { public: Bitu GetIt(Bitu size,PhysPt addr) { switch (size) { case 1:return mem_readb(pt+addr); case 2:return mem_readw(pt+addr); case 4:return mem_readd(pt+addr); } return 0; } void SaveIt(Bitu size,PhysPt addr,Bitu val) { switch (size) { case 1:mem_writeb(pt+addr,(Bit8u)val);break; case 2:mem_writew(pt+addr,(Bit16u)val);break; case 4:mem_writed(pt+addr,(Bit32u)val);break; } } void SetPt(Bit16u seg) { pt=PhysMake(seg,0);} void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);} void SetPt(RealPt addr) { pt=Real2Phys(addr);} protected: PhysPt pt; }; class DOS_PSP :public MemStruct { public: DOS_PSP (Bit16u segment) { SetPt(segment);seg=segment;}; void MakeNew (Bit16u memSize); void CopyFileTable (DOS_PSP* srcpsp,bool createchildpsp); Bit16u FindFreeFileEntry (void); void CloseFiles (void); void SaveVectors (void); void RestoreVectors (void); void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); }; Bit16u GetSize (void) { return (Bit16u)sGet(sPSP,next_seg); }; void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); }; Bit16u GetEnvironment (void) { return (Bit16u)sGet(sPSP,environment); }; Bit16u GetSegment (void) { return seg; }; void SetFileHandle (Bit16u index, Bit8u handle); Bit8u GetFileHandle (Bit16u index); void SetParent (Bit16u parent) { sSave(sPSP,psp_parent,parent); }; Bit16u GetParent (void) { return (Bit16u)sGet(sPSP,psp_parent); }; void SetStack (RealPt stackpt) { sSave(sPSP,stack,stackpt); }; RealPt GetStack (void) { return sGet(sPSP,stack); }; void SetInt22 (RealPt int22pt) { sSave(sPSP,int_22,int22pt); }; RealPt GetInt22 (void) { return sGet(sPSP,int_22); }; void SetFCB1 (RealPt src); void SetFCB2 (RealPt src); void SetCommandTail (RealPt src); bool SetNumFiles (Bit16u fileNum); Bit16u FindEntryByHandle (Bit8u handle); private: #ifdef _MSC_VER #pragma pack(1) #endif struct sPSP { Bit8u exit[2]; /* CP/M-like exit poimt */ Bit16u next_seg; /* Segment of first byte beyond memory allocated or program */ Bit8u fill_1; /* single char fill */ Bit8u far_call; /* far call opcode */ RealPt cpm_entry; /* CPM Service Request address*/ RealPt int_22; /* Terminate Address */ RealPt int_23; /* Break Address */ RealPt int_24; /* Critical Error Address */ Bit16u psp_parent; /* Parent PSP Segment */ Bit8u files[20]; /* File Table - 0xff is unused */ Bit16u environment; /* Segment of evironment table */ RealPt stack; /* SS:SP Save point for int 0x21 calls */ Bit16u max_files; /* Maximum open files */ RealPt file_table; /* Pointer to File Table PSP:0x18 */ RealPt prev_psp; /* Pointer to previous PSP */ Bit8u interim_flag; Bit8u truename_flag; Bit16u nn_flags; Bit16u dos_version; Bit8u fill_2[14]; /* Lot's of unused stuff i can't care aboue */ Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */ Bit8u fill_3[9]; /* This has some blocks with FCB info */ Bit8u fcb1[16]; /* first FCB */ Bit8u fcb2[16]; /* second FCB */ Bit8u fill_4[4]; /* unused */ CommandTail cmdtail; } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack() #endif Bit16u seg; public: static Bit16u rootpsp; }; class DOS_ParamBlock:public MemStruct { public: DOS_ParamBlock(PhysPt addr) {pt=addr;} void Clear(void); void LoadData(void); void SaveData(void); /* Save it as an exec block */ #ifdef _MSC_VER #pragma pack (1) #endif struct sOverlay { Bit16u loadseg; Bit16u relocation; } GCC_ATTRIBUTE(packed); struct sExec { Bit16u envseg; RealPt cmdtail; RealPt fcb1; RealPt fcb2; RealPt initsssp; RealPt initcsip; }GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack() #endif sExec exec; sOverlay overlay; }; class DOS_InfoBlock:public MemStruct { public: DOS_InfoBlock () {}; void SetLocation(Bit16u seg); void SetFirstMCB(Bit16u _first_mcb); void SetBuffers(Bit16u x,Bit16u y); void SetCurDirStruct(Bit32u _curdirstruct); void SetFCBTable(Bit32u _fcbtable); void SetDeviceChainStart(Bit32u _devchain); void SetDiskBufferHeadPt(Bit32u _dbheadpt); void SetStartOfUMBChain(Bit16u _umbstartseg); void SetUMBChainState(Bit8u _umbchaining); void SetBlockDevices(Bit8u _count); Bit16u GetStartOfUMBChain(void); Bit8u GetUMBChainState(void); RealPt GetPointer(void); Bit32u GetDeviceChain(void); #ifdef _MSC_VER #pragma pack(1) #endif struct sDIB { Bit8u unknown1[4]; Bit16u magicWord; // -0x22 needs to be 1 Bit8u unknown2[8]; Bit16u regCXfrom5e; // -0x18 CX from last int21/ah=5e Bit16u countLRUcache; // -0x16 LRU counter for FCB caching Bit16u countLRUopens; // -0x14 LRU counter for FCB openings Bit8u stuff[6]; // -0x12 some stuff, hopefully never used.... Bit16u sharingCount; // -0x0c sharing retry count Bit16u sharingDelay; // -0x0a sharing retry delay RealPt diskBufPtr; // -0x08 pointer to disk buffer Bit16u ptrCONinput; // -0x04 pointer to con input Bit16u firstMCB; // -0x02 first memory control block RealPt firstDPB; // 0x00 first drive parameter block RealPt firstFileTable; // 0x04 first system file table RealPt activeClock; // 0x08 active clock device header RealPt activeCon; // 0x0c active console device header Bit16u maxSectorLength; // 0x10 maximum bytes per sector of any block device; RealPt diskInfoBuffer; // 0x12 pointer to disk info buffer RealPt curDirStructure; // 0x16 pointer to current array of directory structure RealPt fcbTable; // 0x1a pointer to system FCB table Bit16u protFCBs; // 0x1e protected fcbs Bit8u blockDevices; // 0x20 installed block devices Bit8u lastdrive; // 0x21 lastdrive Bit32u nulNextDriver; // 0x22 NUL driver next pointer Bit16u nulAttributes; // 0x26 NUL driver aattributes Bit32u nulStrategy; // 0x28 NUL driver strategy routine Bit8u nulString[8]; // 0x2c NUL driver name string Bit8u joindedDrives; // 0x34 joined drives Bit16u specialCodeSeg; // 0x35 special code segment RealPt setverPtr; // 0x37 pointer to setver Bit16u a20FixOfs; // 0x3b a20 fix routine offset Bit16u pspLastIfHMA; // 0x3d psp of last program (if dos in hma) Bit16u buffers_x; // 0x3f x in BUFFERS x,y Bit16u buffers_y; // 0x41 y in BUFFERS x,y Bit8u bootDrive; // 0x43 boot drive Bit8u useDwordMov; // 0x44 use dword moves Bit16u extendedSize; // 0x45 size of extended memory Bit32u diskBufferHeadPt; // 0x47 pointer to least-recently used buffer header Bit16u dirtyDiskBuffers; // 0x4b number of dirty disk buffers Bit32u lookaheadBufPt; // 0x4d pointer to lookahead buffer Bit16u lookaheadBufNumber; // 0x51 number of lookahead buffers Bit8u bufferLocation; // 0x53 workspace buffer location Bit32u workspaceBuffer; // 0x54 pointer to workspace buffer Bit8u unknown3[11]; // 0x58 Bit8u chainingUMB; // 0x63 bit0: UMB chain linked to MCB chain Bit16u minMemForExec; // 0x64 minimum paragraphs needed for current program Bit16u startOfUMBChain; // 0x66 segment of first UMB-MCB Bit16u memAllocScanStart; // 0x68 start paragraph for memory allocation } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack () #endif Bit16u seg; }; class DOS_DTA:public MemStruct{ public: DOS_DTA(RealPt addr) { SetPt(addr); } void SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * _pattern); void SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr); Bit8u GetSearchDrive(void); void GetSearchParams(Bit8u & _sattr,char * _spattern); void GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr); void SetDirID(Bit16u entry) { sSave(sDTA,dirID,entry); }; void SetDirIDCluster(Bit16u entry) { sSave(sDTA,dirCluster,entry); }; Bit16u GetDirID(void) { return (Bit16u)sGet(sDTA,dirID); }; Bit16u GetDirIDCluster(void) { return (Bit16u)sGet(sDTA,dirCluster); }; private: #ifdef _MSC_VER #pragma pack(1) #endif struct sDTA { Bit8u sdrive; /* The Drive the search is taking place */ Bit8u sname[8]; /* The Search pattern for the filename */ Bit8u sext[3]; /* The Search pattern for the extenstion */ Bit8u sattr; /* The Attributes that need to be found */ Bit16u dirID; /* custom: dir-search ID for multiple searches at the same time */ Bit16u dirCluster; /* custom (drive_fat only): cluster number for multiple searches at the same time */ Bit8u fill[4]; Bit8u attr; Bit16u time; Bit16u date; Bit32u size; char name[DOS_NAMELENGTH_ASCII]; } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack() #endif }; class DOS_FCB: public MemStruct { public: DOS_FCB(Bit16u seg,Bit16u off,bool allow_extended=true); void Create(bool _extended); void SetName(Bit8u _drive,char * _fname,char * _ext); void SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time); void GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time); void GetName(char * fillname); void FileOpen(Bit8u _fhandle); void FileClose(Bit8u & _fhandle); void GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec); void SetRecord(Bit16u _cur_block,Bit8u _cur_rec); void GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size); void SetSeqData(Bit8u _fhandle,Bit16u _rec_size); void GetRandom(Bit32u & _random); void SetRandom(Bit32u _random); Bit8u GetDrive(void); bool Extended(void); void GetAttr(Bit8u & attr); void SetAttr(Bit8u attr); void SetResult(Bit32u size,Bit16u date,Bit16u time,Bit8u attr); bool Valid(void); void ClearBlockRecsize(void); private: bool extended; PhysPt real_pt; #ifdef _MSC_VER #pragma pack (1) #endif struct sFCB { Bit8u drive; /* Drive number 0=default, 1=A, etc */ Bit8u filename[8]; /* Space padded name */ Bit8u ext[3]; /* Space padded extension */ Bit16u cur_block; /* Current Block */ Bit16u rec_size; /* Logical record size */ Bit32u filesize; /* File Size */ Bit16u date; Bit16u time; /* Reserved Block should be 8 bytes */ Bit8u sft_entries; Bit8u share_attributes; Bit8u extra_info; /* Maybe swap file_handle and sft_entries now that fcbs * aren't stored in the psp filetable anymore */ Bit8u file_handle; Bit8u reserved[4]; /* end */ Bit8u cur_rec; /* Current record in current block */ Bit32u rndm; /* Current relative record number */ } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack () #endif }; class DOS_MCB : public MemStruct{ public: DOS_MCB(Bit16u seg) { SetPt(seg); } void SetFileName(char const * const _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); } void GetFileName(char * const _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;} void SetType(Bit8u _type) { sSave(sMCB,type,_type);} void SetSize(Bit16u _size) { sSave(sMCB,size,_size);} void SetPSPSeg(Bit16u _pspseg) { sSave(sMCB,psp_segment,_pspseg);} Bit8u GetType(void) { return (Bit8u)sGet(sMCB,type);} Bit16u GetSize(void) { return (Bit16u)sGet(sMCB,size);} Bit16u GetPSPSeg(void) { return (Bit16u)sGet(sMCB,psp_segment);} private: #ifdef _MSC_VER #pragma pack (1) #endif struct sMCB { Bit8u type; Bit16u psp_segment; Bit16u size; Bit8u unused[3]; Bit8u filename[8]; } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack () #endif }; class DOS_SDA : public MemStruct { public: DOS_SDA(Bit16u _seg,Bit16u _offs) { SetPt(_seg,_offs); } void Init(); void SetDrive(Bit8u _drive) { sSave(sSDA,current_drive, _drive); } void SetDTA(Bit32u _dta) { sSave(sSDA,current_dta, _dta); } void SetPSP(Bit16u _psp) { sSave(sSDA,current_psp, _psp); } Bit8u GetDrive(void) { return (Bit8u)sGet(sSDA,current_drive); } Bit16u GetPSP(void) { return (Bit16u)sGet(sSDA,current_psp); } Bit32u GetDTA(void) { return (Bit32u)sGet(sSDA,current_dta); } private: #ifdef _MSC_VER #pragma pack (1) #endif struct sSDA { Bit8u crit_error_flag; /* 0x00 Critical Error Flag */ Bit8u inDOS_flag; /* 0x01 InDOS flag (count of active INT 21 calls) */ Bit8u drive_crit_error; /* 0x02 Drive on which current critical error occurred or FFh */ Bit8u locus_of_last_error; /* 0x03 locus of last error */ Bit16u extended_error_code; /* 0x04 extended error code of last error */ Bit8u suggested_action; /* 0x06 suggested action for last error */ Bit8u error_class; /* 0x07 class of last error*/ Bit32u last_error_pointer; /* 0x08 ES:DI pointer for last error */ Bit32u current_dta; /* 0x0C current DTA (Disk Transfer Address) */ Bit16u current_psp; /* 0x10 current PSP */ Bit16u sp_int_23; /* 0x12 stores SP across an INT 23 */ Bit16u return_code; /* 0x14 return code from last process termination (zerod after reading with AH=4Dh) */ Bit8u current_drive; /* 0x16 current drive */ Bit8u extended_break_flag; /* 0x17 extended break flag */ Bit8u fill[2]; /* 0x18 flag: code page switching || flag: copy of previous byte in case of INT 24 Abort*/ } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER #pragma pack() #endif }; extern DOS_InfoBlock dos_infoblock; struct DOS_Block { DOS_Date date; DOS_Version version; Bit16u firstMCB; Bit16u errorcode; Bit16u psp(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetPSP();}; void psp(Bit16u _seg){ DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetPSP(_seg);}; Bit16u env; RealPt cpmentry; RealPt dta(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDTA();}; void dta(RealPt _dta){DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDTA(_dta);}; Bit8u return_code,return_mode; Bit8u current_drive; bool verify; bool breakcheck; bool echo; // if set to true dev_con::read will echo input bool direct_output; bool internal_output; struct { RealPt mediaid; RealPt tempdta; RealPt tempdta_fcbdelete; RealPt dbcs; RealPt filenamechar; RealPt collatingseq; RealPt upcase; Bit8u* country;//Will be copied to dos memory. resides in real mem Bit16u dpb; //Fake Disk parameter system using only the first entry so the drive letter matches } tables; Bit16u loaded_codepage; }; extern DOS_Block dos; static INLINE Bit8u RealHandle(Bit16u handle) { DOS_PSP psp(dos.psp()); return psp.GetFileHandle(handle); } #endif