DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/dos/dos_classes.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include <string.h>
00021 #include <stdlib.h>
00022 #include "dosbox.h"
00023 #include "mem.h"
00024 #include "dos_inc.h"
00025 #include "support.h"
00026 #include "drives.h"
00027 
00028 Bit8u sdriv[260], sattr[260], fattr;
00029 char sname[260][LFN_NAMELENGTH+1],storect[CTBUF];
00030 extern int lfn_filefind_handle;
00031 
00032 struct finddata {
00033        Bit8u attr;
00034        Bit8u fres1[19];
00035        Bit32u mtime;
00036        Bit32u mdate;
00037        Bit32u hsize;
00038        Bit32u size;
00039        Bit8u fres2[8];
00040        char lname[260];
00041        char sname[14];
00042 } fd;
00043 
00044 void DOS_ParamBlock::Clear(void) {
00045         memset(&exec,0,sizeof(exec));
00046         memset(&overlay,0,sizeof(overlay));
00047 }
00048 
00049 void DOS_ParamBlock::LoadData(void) {
00050         exec.envseg=(Bit16u)sGet(sExec,envseg);
00051         exec.cmdtail=sGet(sExec,cmdtail);
00052         exec.fcb1=sGet(sExec,fcb1);
00053         exec.fcb2=sGet(sExec,fcb2);
00054         exec.initsssp=sGet(sExec,initsssp);
00055         exec.initcsip=sGet(sExec,initcsip);
00056         overlay.loadseg=(Bit16u)sGet(sOverlay,loadseg);
00057         overlay.relocation=(Bit16u)sGet(sOverlay,relocation);
00058 }
00059 
00060 void DOS_ParamBlock::SaveData(void) {
00061         sSave(sExec,envseg,exec.envseg);
00062         sSave(sExec,cmdtail,exec.cmdtail);
00063         sSave(sExec,fcb1,exec.fcb1);
00064         sSave(sExec,fcb2,exec.fcb2);
00065         sSave(sExec,initsssp,exec.initsssp);
00066         sSave(sExec,initcsip,exec.initcsip);
00067 }
00068 
00069 extern int maxdrive;
00070 void DOS_InfoBlock::SetLocation(Bit16u segment) {
00071         seg = segment;
00072         pt=PhysMake(seg,0);
00073         /* Clear the initial Block */
00074         for(Bit8u i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff);
00075         for(Bit8u i=0;i<14;i++) mem_writeb(pt+i,0);
00076         
00077         sSave(sDIB,regCXfrom5e,(Bit16u)0);
00078         sSave(sDIB,countLRUcache,(Bit16u)0);
00079         sSave(sDIB,countLRUopens,(Bit16u)0);
00080 
00081         sSave(sDIB,protFCBs,(Bit16u)0);
00082         sSave(sDIB,specialCodeSeg,(Bit16u)0);
00083         sSave(sDIB,joindedDrives,(Bit8u)0);
00084         sSave(sDIB,lastdrive,(Bit8u)maxdrive);//increase this if you add drives to cds-chain
00085 
00086         sSave(sDIB,diskInfoBuffer,RealMake(segment,offsetof(sDIB,diskBufferHeadPt)));
00087         sSave(sDIB,setverPtr,(Bit32u)0);
00088 
00089         sSave(sDIB,a20FixOfs,(Bit16u)0);
00090         sSave(sDIB,pspLastIfHMA,(Bit16u)0);
00091         sSave(sDIB,blockDevices,(Bit8u)0);
00092         
00093         sSave(sDIB,bootDrive,(Bit8u)0);
00094         sSave(sDIB,useDwordMov,(Bit8u)1);
00095         sSave(sDIB,extendedSize,(Bit16u)(MEM_TotalPages()*4-1024));
00096         sSave(sDIB,magicWord,(Bit16u)0x0001);           // dos5+
00097 
00098         sSave(sDIB,sharingCount,(Bit16u)0);
00099         sSave(sDIB,sharingDelay,(Bit16u)0);
00100         sSave(sDIB,ptrCONinput,(Bit16u)0);                      // no unread input available
00101         sSave(sDIB,maxSectorLength,(Bit16u)0x200);
00102 
00103         sSave(sDIB,dirtyDiskBuffers,(Bit16u)0);
00104         sSave(sDIB,lookaheadBufPt,(Bit32u)0);
00105         sSave(sDIB,lookaheadBufNumber,(Bit16u)0);
00106         sSave(sDIB,bufferLocation,(Bit8u)0);            // buffer in base memory, no workspace
00107         sSave(sDIB,workspaceBuffer,(Bit32u)0);
00108 
00109         sSave(sDIB,minMemForExec,(Bit16u)0);
00110         sSave(sDIB,memAllocScanStart,(Bit16u)DOS_MEM_START);
00111         sSave(sDIB,startOfUMBChain,(Bit16u)0xffff);
00112         sSave(sDIB,chainingUMB,(Bit8u)0);
00113 
00114         sSave(sDIB,nulNextDriver,(Bit32u)0xffffffff);
00115         sSave(sDIB,nulAttributes,(Bit16u)0x8004);
00116         sSave(sDIB,nulStrategy,(Bit16u)0x0000);
00117         sSave(sDIB,nulInterrupt,(Bit16u)0x0000);
00118         sSave(sDIB,nulString[0],(Bit8u)0x4e);
00119         sSave(sDIB,nulString[1],(Bit8u)0x55);
00120         sSave(sDIB,nulString[2],(Bit8u)0x4c);
00121         sSave(sDIB,nulString[3],(Bit8u)0x20);
00122         sSave(sDIB,nulString[4],(Bit8u)0x20);
00123         sSave(sDIB,nulString[5],(Bit8u)0x20);
00124         sSave(sDIB,nulString[6],(Bit8u)0x20);
00125         sSave(sDIB,nulString[7],(Bit8u)0x20);
00126 
00127         /* Create a fake SFT, so programs think there are 100 file handles */
00128         Bit16u sftOffset=offsetof(sDIB,firstFileTable)+0xa2;
00129         sSave(sDIB,firstFileTable,RealMake(segment,sftOffset));
00130         real_writed(segment,sftOffset+0x00,RealMake(segment+0x26,0));   //Next File Table
00131         real_writew(segment,sftOffset+0x04,100);                //File Table supports 100 files
00132         real_writed(segment+0x26,0x00,0xffffffff);              //Last File Table
00133         real_writew(segment+0x26,0x04,100);                             //File Table supports 100 files
00134 }
00135 
00136 void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb) {
00137         sSave(sDIB,firstMCB,_firstmcb); //c2woody
00138 }
00139 
00140 void DOS_InfoBlock::SetBuffers(Bit16u x,Bit16u y) {
00141         sSave(sDIB,buffers_x,x);
00142         sSave(sDIB,buffers_y,y);
00143 }
00144 
00145 void DOS_InfoBlock::SetCurDirStruct(Bit32u _curdirstruct) {
00146         sSave(sDIB,curDirStructure,_curdirstruct);
00147 }
00148 
00149 void DOS_InfoBlock::SetFCBTable(Bit32u _fcbtable) {
00150         sSave(sDIB,fcbTable,_fcbtable);
00151 }
00152 
00153 void DOS_InfoBlock::SetDeviceChainStart(Bit32u _devchain) {
00154         sSave(sDIB,nulNextDriver,_devchain);
00155 }
00156 
00157 void DOS_InfoBlock::SetDiskBufferHeadPt(Bit32u _dbheadpt) {
00158         sSave(sDIB,diskBufferHeadPt,_dbheadpt);
00159 }
00160 
00161 Bit16u DOS_InfoBlock::GetStartOfUMBChain(void) {
00162         return (Bit16u)sGet(sDIB,startOfUMBChain);
00163 }
00164 
00165 void DOS_InfoBlock::SetStartOfUMBChain(Bit16u _umbstartseg) {
00166         sSave(sDIB,startOfUMBChain,_umbstartseg);
00167 }
00168 
00169 Bit8u DOS_InfoBlock::GetUMBChainState(void) {
00170         return (Bit8u)sGet(sDIB,chainingUMB);
00171 }
00172 
00173 void DOS_InfoBlock::SetUMBChainState(Bit8u _umbchaining) {
00174         sSave(sDIB,chainingUMB,_umbchaining);
00175 }
00176 
00177 void DOS_InfoBlock::SetBlockDevices(Bit8u _count) {
00178         sSave(sDIB,blockDevices,_count);
00179 }
00180 
00181 void DOS_InfoBlock::SetFirstDPB(Bit32u _first_dpb) {
00182     sSave(sDIB,firstDPB,_first_dpb);
00183 }
00184 
00185 RealPt DOS_InfoBlock::GetPointer(void) {
00186         return RealMake(seg,offsetof(sDIB,firstDPB));
00187 }
00188 
00189 Bit32u DOS_InfoBlock::GetDeviceChain(void) {
00190         return sGet(sDIB,nulNextDriver);
00191 }
00192 
00193 
00194 /* program Segment prefix */
00195 
00196 Bit16u DOS_PSP::rootpsp = 0;
00197 
00198 #define CPM_MAX_SEG_SIZE        0xfffu
00199 
00200 extern unsigned char cpm_compat_mode;
00201 
00202 void DOS_PSP::MakeNew(Bit16u mem_size) {
00203         /* get previous */
00204 //      DOS_PSP prevpsp(dos.psp());
00205         /* Clear it first */
00206         Bit16u i;
00207         for (i=0;i<sizeof(sPSP);i++) mem_writeb(pt+i,0);
00208         // Set size
00209         sSave(sPSP,next_seg,(unsigned int)seg+mem_size);
00210     /* cpm_entry is an alias for the int 30 vector (0:c0 = c:0); the offset is also the maximum program size */
00211     if (cpm_compat_mode == CPM_COMPAT_MSDOS2) { /* MS-DOS 2.x behavior, where offset is the memory size (for some reason) */
00212             /* far call opcode */
00213         sSave(sPSP,far_call,0x9a);
00214         /* and where to call to */
00215         if (mem_size>CPM_MAX_SEG_SIZE) mem_size=CPM_MAX_SEG_SIZE;
00216         mem_size-=0x10;
00217         sSave(sPSP,cpm_entry,RealMake(0xc-mem_size,mem_size<<4));
00218     }
00219     else if (cpm_compat_mode == CPM_COMPAT_MSDOS5) { /* MS-DOS 5.x behavior, for whatever reason */
00220             /* far call opcode */
00221         sSave(sPSP,far_call,0x9a);
00222         /* and where to call to.
00223          * if 64KB or more, call far to F01D:FEF0.
00224          * else, call far to 0000:00C0.
00225          * don't ask me why MS-DOS 5.0 does this, ask Microsoft. */
00226         if (mem_size >= CPM_MAX_SEG_SIZE)
00227             sSave(sPSP,cpm_entry,RealMake(0xF01D,0xFEF0));
00228         else
00229             sSave(sPSP,cpm_entry,RealMake(0x0000,0x00C0));
00230     }
00231     else if (cpm_compat_mode == CPM_COMPAT_DIRECT) {
00232         /* direct and to the point, though impossible to hook INT 21h without patching all PSP segments
00233          * which is probably why Microsoft never did this in the DOS kernel. Choosing this method
00234          * removes the need for the copy of INT 30h in the HMA area, and therefore opens up all 64KB of
00235          * HMA if you want. */
00236         Bit32u DOS_Get_CPM_entry_direct(void);
00237 
00238             /* far call opcode */
00239         sSave(sPSP,far_call,0x9a);
00240         /* and where to call to */
00241         sSave(sPSP,cpm_entry,DOS_Get_CPM_entry_direct());
00242     }
00243     else { /* off */
00244         /* stick an INT 20h in there to make calling the CP/M entry point an immediate exit */
00245         /* this is NOT default, but an option for users who are absolutely certain no CP/M code is going to run in their DOS box. */
00246         sSave(sPSP,far_call,0xCD);      // INT 20h + NOP NOP NOP
00247         sSave(sPSP,cpm_entry,0x90909020);
00248     }
00249         /* Standard blocks,int 20  and int21 retf */
00250         sSave(sPSP,exit[0],0xcd);
00251         sSave(sPSP,exit[1],0x20);
00252         sSave(sPSP,service[0],0xcd);
00253         sSave(sPSP,service[1],0x21);
00254         sSave(sPSP,service[2],0xcb);
00255         /* psp and psp-parent */
00256         sSave(sPSP,psp_parent,dos.psp());
00257         sSave(sPSP,prev_psp,0xffffffff);
00258         sSave(sPSP,dos_version,0x0005);
00259         /* terminate 22,break 23,crititcal error 24 address stored */
00260         SaveVectors();
00261 
00262         /* FCBs are filled with 0 */
00263         // ....
00264         /* Init file pointer and max_files */
00265         sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files)));
00266         sSave(sPSP,max_files,20);
00267         for (Bit16u ct=0;ct<20;ct++) SetFileHandle(ct,0xff);
00268 
00269         /* User Stack pointer */
00270 //      if (prevpsp.GetSegment()!=0) sSave(sPSP,stack,prevpsp.GetStack());
00271 
00272         if (rootpsp==0) rootpsp = seg;
00273 }
00274 
00275 Bit8u DOS_PSP::GetFileHandle(Bit16u index) {
00276         if (index>=sGet(sPSP,max_files)) return 0xff;
00277         PhysPt files=Real2Phys(sGet(sPSP,file_table));
00278         return mem_readb(files+index);
00279 }
00280 
00281 void DOS_PSP::SetFileHandle(Bit16u index, Bit8u handle) {
00282         if (index<sGet(sPSP,max_files)) {
00283                 PhysPt files=Real2Phys(sGet(sPSP,file_table));
00284                 mem_writeb(files+index,handle);
00285         }
00286 }
00287 
00288 Bit16u DOS_PSP::FindFreeFileEntry(void) {
00289         PhysPt files=Real2Phys(sGet(sPSP,file_table));
00290         for (Bit16u i=0;i<sGet(sPSP,max_files);i++) {
00291                 if (mem_readb(files+i)==0xff) return i;
00292         }       
00293         return 0xff;
00294 }
00295 
00296 Bit16u DOS_PSP::FindEntryByHandle(Bit8u handle) {
00297         PhysPt files=Real2Phys(sGet(sPSP,file_table));
00298         for (Bit16u i=0;i<sGet(sPSP,max_files);i++) {
00299                 if (mem_readb(files+i)==handle) return i;
00300         }       
00301         return 0xFF;
00302 }
00303 
00304 void DOS_PSP::CopyFileTable(DOS_PSP* srcpsp,bool createchildpsp) {
00305         /* Copy file table from calling process */
00306         for (Bit16u i=0;i<20;i++) {
00307                 Bit8u handle = srcpsp->GetFileHandle(i);
00308                 if(createchildpsp)
00309                 {       //copy obeying not inherit flag.(but dont duplicate them)
00310                         bool allowCopy = true;//(handle==0) || ((handle>0) && (FindEntryByHandle(handle)==0xff));
00311                         if((handle<DOS_FILES) && Files[handle] && !(Files[handle]->flags & DOS_NOT_INHERIT) && allowCopy)
00312                         {   
00313                                 Files[handle]->AddRef();
00314                                 SetFileHandle(i,handle);
00315                         }
00316                         else
00317                         {
00318                                 SetFileHandle(i,0xff);
00319                         }
00320                 }
00321                 else
00322                 {       //normal copy so don't mind the inheritance
00323                         SetFileHandle(i,handle);
00324                 }
00325         }
00326 }
00327 
00328 void DOS_PSP::CloseFiles(void) {
00329         for (Bit16u i=0;i<sGet(sPSP,max_files);i++) {
00330                 DOS_CloseFile(i);
00331         }
00332 }
00333 
00334 void DOS_PSP::SaveVectors(void) {
00335         /* Save interrupt 22,23,24 */
00336         sSave(sPSP,int_22,RealGetVec(0x22));
00337         sSave(sPSP,int_23,RealGetVec(0x23));
00338         sSave(sPSP,int_24,RealGetVec(0x24));
00339 }
00340 
00341 void DOS_PSP::RestoreVectors(void) {
00342         /* Restore interrupt 22,23,24 */
00343         RealSetVec(0x22,sGet(sPSP,int_22));
00344         RealSetVec(0x23,sGet(sPSP,int_23));
00345         RealSetVec(0x24,sGet(sPSP,int_24));
00346 }
00347 
00348 void DOS_PSP::SetCommandTail(RealPt src) {
00349         if (src) {      // valid source
00350         MEM_BlockCopy(pt+offsetof(sPSP,cmdtail),Real2Phys(src),CTBUF+1);
00351         } else {        // empty
00352                 sSave(sPSP,cmdtail.count,0x00);
00353                 mem_writeb(pt+offsetof(sPSP,cmdtail.buffer),0x0d);
00354         }
00355 }
00356 
00357 void DOS_PSP::StoreCommandTail() {
00358         int len=(int)mem_strlen(pt+offsetof(sPSP,cmdtail.buffer));
00359         MEM_StrCopy(pt+offsetof(sPSP,cmdtail.buffer),storect,len>CTBUF?CTBUF:len);
00360 }
00361 
00362 void DOS_PSP::RestoreCommandTail() {
00363         mem_writeb(pt+offsetof(sPSP,cmdtail.count),strlen(storect)>0?(Bit8u)(strlen(storect)-1):0);
00364         MEM_BlockWrite(pt+offsetof(sPSP,cmdtail.buffer),storect,strlen(storect));
00365 }
00366 
00367 void DOS_PSP::SetFCB1(RealPt src) {
00368         if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb1)),Real2Phys(src),16);
00369 }
00370 
00371 void DOS_PSP::SetFCB2(RealPt src) {
00372         if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb2)),Real2Phys(src),16);
00373 }
00374 
00375 bool DOS_PSP::SetNumFiles(Bit16u fileNum) {
00376         //20 minimum. clipper program.
00377         if (fileNum < 20) fileNum = 20;
00378          
00379         if (fileNum>20) {
00380                 // Allocate needed paragraphs
00381                 fileNum+=2;     // Add a few more files for safety
00382                 Bit16u para = (fileNum/16)+((fileNum%16)>0);
00383                 RealPt data     = RealMake(DOS_GetMemory(para,"SetNumFiles data"),0);
00384                 sSave(sPSP,file_table,data);
00385                 sSave(sPSP,max_files,fileNum);
00386                 Bit16u i;
00387                 for (i=0; i<20; i++)            SetFileHandle(i,(Bit8u)sGet(sPSP,files[i]));
00388                 for (i=20; i<fileNum; i++)      SetFileHandle(i,0xFF);
00389         } else {
00390                 sSave(sPSP,max_files,fileNum);
00391         }
00392         return true;
00393 }
00394 
00395 
00396 void DOS_DTA::SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * pattern) {
00397         unsigned int i;
00398 
00399         if (lfn_filefind_handle<LFN_FILEFIND_NONE) {
00400                 sdriv[lfn_filefind_handle]=_sdrive;
00401                 sattr[lfn_filefind_handle]=_sattr;
00402                 for (i=0;i<LFN_NAMELENGTH;i++) {
00403                         if (pattern[i]==0) break;
00404                                 sname[lfn_filefind_handle][i]=pattern[i];
00405                 }
00406                 while (i<=LFN_NAMELENGTH) sname[lfn_filefind_handle][i++]=0;
00407         }
00408     for (i=0;i<11;i++) mem_writeb(pt+offsetof(sDTA,spname)+i,0);
00409         
00410         sSave(sDTA,sdrive,_sdrive);
00411         sSave(sDTA,sattr,_sattr);
00412     const char* find_ext;
00413     find_ext=strchr(pattern,'.');
00414     if (find_ext) {
00415         Bitu size=(Bitu)(find_ext-pattern);
00416                 if (size>8) size=8;
00417                         MEM_BlockWrite(pt+offsetof(sDTA,spname),pattern,size);
00418                         find_ext++;
00419                         MEM_BlockWrite(pt+offsetof(sDTA,spext),find_ext,(strlen(find_ext)>3) ? 3 : (Bitu)strlen(find_ext));
00420         } else {
00421                 MEM_BlockWrite(pt+offsetof(sDTA,spname),pattern,(strlen(pattern) > 8) ? 8 : (Bitu)strlen(pattern));
00422         }
00423 }
00424 
00425 void DOS_DTA::SetResult(const char * _name, const char * _lname, Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr) {
00426         fd.hsize=0;
00427         fd.size=_size;
00428         fd.mdate=_date;
00429         fd.mtime=_time;
00430         fd.attr=_attr;
00431         strcpy(fd.lname,_lname);
00432         strcpy(fd.sname,_name);
00433         if (!strcmp(fd.lname,fd.sname)) fd.sname[0]=0;
00434         if (lfn_filefind_handle>=LFN_FILEFIND_MAX) {
00435                 MEM_BlockWrite(pt+offsetof(sDTA,name),(void *)_name,strlen(_name)+1);
00436                 sSave(sDTA,size,_size);
00437                 sSave(sDTA,date,_date);
00438                 sSave(sDTA,time,_time);
00439                 sSave(sDTA,attr,_attr);
00440         }
00441 }
00442 
00443 
00444 void DOS_DTA::GetResult(char * _name, char * _lname,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr) {
00445         strcpy(_lname,fd.lname);
00446         if (fd.sname[0]!=0) strcpy(_name,fd.sname);
00447         else if (strlen(fd.lname)<DOS_NAMELENGTH_ASCII) strcpy(_name,fd.lname);
00448         _size = fd.size;
00449         _date = fd.mdate;
00450         _time = fd.mtime;
00451         _attr = fd.attr;
00452         if (lfn_filefind_handle>=LFN_FILEFIND_MAX) {
00453                 MEM_BlockRead(pt+offsetof(sDTA,name),_name,DOS_NAMELENGTH_ASCII);
00454                 _size=sGet(sDTA,size);
00455                 _date=(Bit16u)sGet(sDTA,date);
00456                 _time=(Bit16u)sGet(sDTA,time);
00457                 _attr=(Bit8u)sGet(sDTA,attr);
00458         }
00459 }
00460 
00461 int DOS_DTA::GetFindData(int fmt, char * fdstr, int *c) {
00462         if (fmt==1)
00463                 sprintf(fdstr,"%-1s%-19s%-2s%-2s%-4s%-4s%-4s%-8s%-260s%-14s",(char*)&fd.attr,(char*)&fd.fres1,(char*)&fd.mtime,(char*)&fd.mdate,(char*)&fd.mtime,(char*)&fd.hsize,(char*)&fd.size,(char*)&fd.fres2,(char*)&fd.lname,(char*)&fd.sname);
00464         else
00465                 sprintf(fdstr,"%-1s%-19s%-4s%-4s%-4s%-4s%-8s%-260s%-14s",(char*)&fd.attr,(char*)&fd.fres1,(char*)&fd.mtime,(char*)&fd.mdate,(char*)&fd.hsize,(char*)&fd.size,(char*)&fd.fres2,(char*)&fd.lname,(char*)&fd.sname);
00466         for (int i=0;i<4;i++) fdstr[28+i]=0;
00467     fdstr[32]=(char)fd.size%256;
00468     fdstr[33]=(char)((fd.size%65536)/256);
00469     fdstr[34]=(char)((fd.size%16777216)/65536);
00470     fdstr[35]=(char)(fd.size/16777216);
00471     fdstr[44+strlen(fd.lname)]=0;
00472     fdstr[304+strlen(fd.sname)]=0;
00473         if (!strcmp(fd.sname,"?")&&strlen(fd.lname))
00474                 *c=2;
00475         else
00476                 *c=!strchr(fd.sname,'?')&&strchr(fd.lname,'?')?1:0;
00477     return (sizeof(fd));
00478 }
00479 
00480 Bit8u DOS_DTA::GetSearchDrive(void) {
00481         return lfn_filefind_handle>=LFN_FILEFIND_MAX?(Bit8u)sGet(sDTA,sdrive):sdriv[lfn_filefind_handle];
00482 }
00483 
00484 void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern, bool lfn) {
00485     if (lfn&&lfn_filefind_handle<LFN_FILEFIND_NONE) {
00486                 attr=sattr[lfn_filefind_handle];
00487         memcpy(pattern,sname[lfn_filefind_handle],LFN_NAMELENGTH);
00488         pattern[LFN_NAMELENGTH]=0;
00489     } else {
00490                 attr=(Bit8u)sGet(sDTA,sattr);
00491         char temp[11];
00492         MEM_BlockRead(pt+offsetof(sDTA,spname),temp,11);
00493         for (int i=0;i<13;i++) pattern[i]=0;
00494             memcpy(pattern,temp,8);
00495             pattern[strlen(pattern)]='.';
00496             memcpy(&pattern[strlen(pattern)],&temp[8],3);
00497     }
00498 }
00499 
00500 DOS_FCB::DOS_FCB(Bit16u seg,Bit16u off,bool allow_extended) { 
00501         SetPt(seg,off); 
00502         real_pt=pt;
00503         if (allow_extended) {
00504                 if (sGet(sFCB,drive)==0xff) {
00505                         pt+=7;
00506                         extended=true;
00507                 }
00508         }
00509 }
00510 
00511 bool DOS_FCB::Extended(void) {
00512         return extended;
00513 }
00514 
00515 void DOS_FCB::Create(bool _extended) {
00516         Bit8u fill;
00517         if (_extended) fill=33+7;
00518         else fill=33;
00519         Bit8u i;
00520         for (i=0;i<fill;i++) mem_writeb(real_pt+i,0);
00521         pt=real_pt;
00522         if (_extended) {
00523                 mem_writeb(real_pt,0xff);
00524                 pt+=7;
00525                 extended=true;
00526         } else extended=false;
00527 }
00528 
00529 void DOS_FCB::SetName(Bit8u _drive, const char* _fname, const char* _ext) {
00530         sSave(sFCB,drive,_drive);
00531         MEM_BlockWrite(pt+offsetof(sFCB,filename),_fname,8);
00532         MEM_BlockWrite(pt+offsetof(sFCB,ext),_ext,3);
00533 }
00534 
00535 void DOS_FCB::SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time) {
00536         sSave(sFCB,filesize,_size);
00537         sSave(sFCB,date,_date);
00538         sSave(sFCB,time,_time);
00539 }
00540 
00541 void DOS_FCB::GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time) {
00542         _size=sGet(sFCB,filesize);
00543         _date=(Bit16u)sGet(sFCB,date);
00544         _time=(Bit16u)sGet(sFCB,time);
00545 }
00546 
00547 void DOS_FCB::GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec) {
00548         _cur_block=(Bit16u)sGet(sFCB,cur_block);
00549         _cur_rec=(Bit8u)sGet(sFCB,cur_rec);
00550 
00551 }
00552 
00553 void DOS_FCB::SetRecord(Bit16u _cur_block,Bit8u _cur_rec) {
00554         sSave(sFCB,cur_block,_cur_block);
00555         sSave(sFCB,cur_rec,_cur_rec);
00556 }
00557 
00558 void DOS_FCB::GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size) {
00559         _fhandle=(Bit8u)sGet(sFCB,file_handle);
00560         _rec_size=(Bit16u)sGet(sFCB,rec_size);
00561 }
00562 
00563 void DOS_FCB::SetSeqData(Bit8u _fhandle,Bit16u _rec_size) {
00564         sSave(sFCB,file_handle,_fhandle);
00565         sSave(sFCB,rec_size,_rec_size);
00566 }
00567 
00568 void DOS_FCB::GetRandom(Bit32u & _random) {
00569         _random=sGet(sFCB,rndm);
00570 }
00571 
00572 void DOS_FCB::SetRandom(Bit32u _random) {
00573         sSave(sFCB,rndm,_random);
00574 }
00575 
00576 void DOS_FCB::ClearBlockRecsize(void) {
00577         sSave(sFCB,cur_block,0);
00578         sSave(sFCB,rec_size,0);
00579 }
00580 
00581 void DOS_FCB::FileOpen(Bit8u _fhandle) {
00582         sSave(sFCB,drive,GetDrive()+1u);
00583         sSave(sFCB,file_handle,_fhandle);
00584         sSave(sFCB,cur_block,0u);
00585         sSave(sFCB,rec_size,128u);
00586 //      sSave(sFCB,rndm,0); // breaks Jewels of darkness. 
00587         Bit32u size = 0;
00588         Files[_fhandle]->Seek(&size,DOS_SEEK_END);
00589         sSave(sFCB,filesize,size);
00590         size = 0;
00591         Files[_fhandle]->Seek(&size,DOS_SEEK_SET);
00592         sSave(sFCB,time,Files[_fhandle]->time);
00593         sSave(sFCB,date,Files[_fhandle]->date);
00594 }
00595 
00596 bool DOS_FCB::Valid() {
00597         //Very simple check for Oubliette
00598         if(sGet(sFCB,filename[0]) == 0 && sGet(sFCB,file_handle) == 0) return false;
00599         return true;
00600 }
00601 
00602 void DOS_FCB::FileClose(Bit8u & _fhandle) {
00603         _fhandle=(Bit8u)sGet(sFCB,file_handle);
00604         sSave(sFCB,file_handle,0xff);
00605 }
00606 
00607 Bit8u DOS_FCB::GetDrive(void) {
00608         Bit8u drive=(Bit8u)sGet(sFCB,drive);
00609         if (!drive) return  DOS_GetDefaultDrive();
00610         else return drive-1;
00611 }
00612 
00613 void DOS_FCB::GetVolumeName(char * fillname) {
00614         MEM_BlockRead(pt+offsetof(sFCB,filename),&fillname[0],8);
00615         MEM_BlockRead(pt+offsetof(sFCB,ext),&fillname[8],3);
00616     fillname[11]=0;
00617 }
00618 
00619 void DOS_FCB::GetName(char * fillname) {
00620         fillname[0]=GetDrive()+'A';
00621         fillname[1]=':';
00622         MEM_BlockRead(pt+offsetof(sFCB,filename),&fillname[2],8);
00623         fillname[10]='.';
00624         MEM_BlockRead(pt+offsetof(sFCB,ext),&fillname[11],3);
00625         fillname[14]=0;
00626 }
00627 
00628 void DOS_FCB::GetAttr(Bit8u& attr) {
00629         if(extended) attr=mem_readb(pt - 1);
00630 }
00631 
00632 void DOS_FCB::SetAttr(Bit8u attr) {
00633         if(extended) mem_writeb(pt - 1,attr);
00634 }
00635 
00636 void DOS_FCB::SetResult(Bit32u size,Bit16u date,Bit16u time,Bit8u attr) {
00637         mem_writed(pt + 0x1d,size);
00638         mem_writew(pt + 0x19,date);
00639         mem_writew(pt + 0x17,time);
00640         mem_writeb(pt + 0x0c,attr);
00641 }
00642 
00643 void DOS_SDA::Init() {
00644         /* Clear */
00645         for(Bit8u i=0;i<sizeof(sSDA);i++) mem_writeb(pt+i,0x00);
00646         sSave(sSDA,drive_crit_error,0xff);   
00647 }