DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/dos/dos_classes.cpp
00001 /*
00002  *  Copyright (C) 2002-2013  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
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 
00027 
00028 void DOS_ParamBlock::Clear(void) {
00029         memset(&exec,0,sizeof(exec));
00030         memset(&overlay,0,sizeof(overlay));
00031 }
00032 
00033 void DOS_ParamBlock::LoadData(void) {
00034         exec.envseg=(Bit16u)sGet(sExec,envseg);
00035         exec.cmdtail=sGet(sExec,cmdtail);
00036         exec.fcb1=sGet(sExec,fcb1);
00037         exec.fcb2=sGet(sExec,fcb2);
00038         exec.initsssp=sGet(sExec,initsssp);
00039         exec.initcsip=sGet(sExec,initcsip);
00040         overlay.loadseg=(Bit16u)sGet(sOverlay,loadseg);
00041         overlay.relocation=(Bit16u)sGet(sOverlay,relocation);
00042 }
00043 
00044 void DOS_ParamBlock::SaveData(void) {
00045         sSave(sExec,envseg,exec.envseg);
00046         sSave(sExec,cmdtail,exec.cmdtail);
00047         sSave(sExec,fcb1,exec.fcb1);
00048         sSave(sExec,fcb2,exec.fcb2);
00049         sSave(sExec,initsssp,exec.initsssp);
00050         sSave(sExec,initcsip,exec.initcsip);
00051 }
00052 
00053 
00054 void DOS_InfoBlock::SetLocation(Bit16u segment) {
00055         seg = segment;
00056         pt=PhysMake(seg,0);
00057         /* Clear the initial Block */
00058         for(Bitu i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff);
00059         for(Bitu i=0;i<14;i++) mem_writeb(pt+i,0);
00060 
00061         sSave(sDIB,regCXfrom5e,(Bit16u)0);
00062         sSave(sDIB,countLRUcache,(Bit16u)0);
00063         sSave(sDIB,countLRUopens,(Bit16u)0);
00064 
00065         sSave(sDIB,protFCBs,(Bit16u)0);
00066         sSave(sDIB,specialCodeSeg,(Bit16u)0);
00067         sSave(sDIB,joindedDrives,(Bit8u)0);
00068         sSave(sDIB,lastdrive,(Bit8u)0x01);//increase this if you add drives to cds-chain
00069 
00070         sSave(sDIB,diskInfoBuffer,RealMake(segment,offsetof(sDIB,diskBufferHeadPt)));
00071         sSave(sDIB,setverPtr,(Bit32u)0);
00072 
00073         sSave(sDIB,a20FixOfs,(Bit16u)0);
00074         sSave(sDIB,pspLastIfHMA,(Bit16u)0);
00075         sSave(sDIB,blockDevices,(Bit8u)0);
00076         
00077         sSave(sDIB,bootDrive,(Bit8u)0);
00078         sSave(sDIB,useDwordMov,(Bit8u)1);
00079         sSave(sDIB,extendedSize,(Bit16u)(MEM_TotalPages()*4-1024));
00080         sSave(sDIB,magicWord,(Bit16u)0x0001);           // dos5+
00081 
00082         sSave(sDIB,sharingCount,(Bit16u)0);
00083         sSave(sDIB,sharingDelay,(Bit16u)0);
00084         sSave(sDIB,ptrCONinput,(Bit16u)0);                      // no unread input available
00085         sSave(sDIB,maxSectorLength,(Bit16u)0x200);
00086 
00087         sSave(sDIB,dirtyDiskBuffers,(Bit16u)0);
00088         sSave(sDIB,lookaheadBufPt,(Bit32u)0);
00089         sSave(sDIB,lookaheadBufNumber,(Bit16u)0);
00090         sSave(sDIB,bufferLocation,(Bit8u)0);            // buffer in base memory, no workspace
00091         sSave(sDIB,workspaceBuffer,(Bit32u)0);
00092 
00093         sSave(sDIB,minMemForExec,(Bit16u)0);
00094         sSave(sDIB,memAllocScanStart,(Bit16u)DOS_MEM_START);
00095         sSave(sDIB,startOfUMBChain,(Bit16u)0xffff);
00096         sSave(sDIB,chainingUMB,(Bit8u)0);
00097 
00098         sSave(sDIB,nulNextDriver,(Bit32u)0xffffffff);
00099         sSave(sDIB,nulAttributes,(Bit16u)0x8004);
00100         sSave(sDIB,nulStrategy,(Bit16u)0x0000);
00101         sSave(sDIB,nulInterrupt,(Bit16u)0x0000);
00102         sSave(sDIB,nulString[0],(Bit8u)0x4e);
00103         sSave(sDIB,nulString[1],(Bit8u)0x55);
00104         sSave(sDIB,nulString[2],(Bit8u)0x4c);
00105         sSave(sDIB,nulString[3],(Bit8u)0x20);
00106         sSave(sDIB,nulString[4],(Bit8u)0x20);
00107         sSave(sDIB,nulString[5],(Bit8u)0x20);
00108         sSave(sDIB,nulString[6],(Bit8u)0x20);
00109         sSave(sDIB,nulString[7],(Bit8u)0x20);
00110 
00111         /* Create a fake SFT, so programs think there are 100 file handles */
00112         Bit16u sftOffset=offsetof(sDIB,firstFileTable)+0xa2;
00113         sSave(sDIB,firstFileTable,RealMake(segment,sftOffset));
00114         real_writed(segment,sftOffset+0x00,RealMake(segment+0x26,0));   //Next File Table
00115         real_writew(segment,sftOffset+0x04,100);                //File Table supports 100 files
00116         real_writed(segment+0x26,0x00,0xffffffff);              //Last File Table
00117         real_writew(segment+0x26,0x04,100);                             //File Table supports 100 files
00118 }
00119 
00120 void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb) {
00121         sSave(sDIB,firstMCB,_firstmcb); //c2woody
00122 }
00123 
00124 void DOS_InfoBlock::SetBuffers(Bit16u x,Bit16u y) {
00125         sSave(sDIB,buffers_x,x);
00126         sSave(sDIB,buffers_y,y);
00127 }
00128 
00129 void DOS_InfoBlock::SetCurDirStruct(Bit32u _curdirstruct) {
00130         sSave(sDIB,curDirStructure,_curdirstruct);
00131 }
00132 
00133 void DOS_InfoBlock::SetFCBTable(Bit32u _fcbtable) {
00134         sSave(sDIB,fcbTable,_fcbtable);
00135 }
00136 
00137 void DOS_InfoBlock::SetDeviceChainStart(Bit32u _devchain) {
00138         sSave(sDIB,nulNextDriver,_devchain);
00139 }
00140 
00141 void DOS_InfoBlock::SetDiskBufferHeadPt(Bit32u _dbheadpt) {
00142         sSave(sDIB,diskBufferHeadPt,_dbheadpt);
00143 }
00144 
00145 Bit16u DOS_InfoBlock::GetStartOfUMBChain(void) {
00146         return (Bit16u)sGet(sDIB,startOfUMBChain);
00147 }
00148 
00149 void DOS_InfoBlock::SetStartOfUMBChain(Bit16u _umbstartseg) {
00150         sSave(sDIB,startOfUMBChain,_umbstartseg);
00151 }
00152 
00153 Bit8u DOS_InfoBlock::GetUMBChainState(void) {
00154         return (Bit8u)sGet(sDIB,chainingUMB);
00155 }
00156 
00157 void DOS_InfoBlock::SetUMBChainState(Bit8u _umbchaining) {
00158         sSave(sDIB,chainingUMB,_umbchaining);
00159 }
00160 
00161 RealPt DOS_InfoBlock::GetPointer(void) {
00162         return RealMake(seg,offsetof(sDIB,firstDPB));
00163 }
00164 
00165 Bit32u DOS_InfoBlock::GetDeviceChain(void) {
00166         return sGet(sDIB,nulNextDriver);
00167 }
00168 
00169 
00170 /* program Segment prefix */
00171 
00172 Bit16u DOS_PSP::rootpsp = 0;
00173 
00174 #define CPM_MAX_SEG_SIZE        0xfffu
00175 
00176 extern unsigned char cpm_compat_mode;
00177 
00178 void DOS_PSP::MakeNew(Bit16u mem_size) {
00179         /* get previous */
00180 //      DOS_PSP prevpsp(dos.psp());
00181         /* Clear it first */
00182         Bitu i;
00183         for (i=0;i<sizeof(sPSP);i++) mem_writeb(pt+i,0);
00184         // Set size
00185         sSave(sPSP,next_seg,(unsigned int)seg+mem_size);
00186     /* cpm_entry is an alias for the int 30 vector (0:c0 = c:0); the offset is also the maximum program size */
00187     if (cpm_compat_mode == CPM_COMPAT_MSDOS2) { /* MS-DOS 2.x behavior, where offset is the memory size (for some reason) */
00188             /* far call opcode */
00189         sSave(sPSP,far_call,0x9a);
00190         /* and where to call to */
00191         if (mem_size>CPM_MAX_SEG_SIZE) mem_size=CPM_MAX_SEG_SIZE;
00192         mem_size-=0x10;
00193         sSave(sPSP,cpm_entry,RealMake(0xc-mem_size,mem_size<<4));
00194     }
00195     else if (cpm_compat_mode == CPM_COMPAT_MSDOS5) { /* MS-DOS 5.x behavior, for whatever reason */
00196             /* far call opcode */
00197         sSave(sPSP,far_call,0x9a);
00198         /* and where to call to.
00199          * if 64KB or more, call far to F01D:FEF0.
00200          * else, call far to 0000:00C0.
00201          * don't ask me why MS-DOS 5.0 does this, ask Microsoft. */
00202         if (mem_size >= CPM_MAX_SEG_SIZE)
00203             sSave(sPSP,cpm_entry,RealMake(0xF01D,0xFEF0));
00204         else
00205             sSave(sPSP,cpm_entry,RealMake(0x0000,0x00C0));
00206     }
00207     else if (cpm_compat_mode == CPM_COMPAT_DIRECT) {
00208         /* direct and to the point, though impossible to hook INT 21h without patching all PSP segments
00209          * which is probably why Microsoft never did this in the DOS kernel. Choosing this method
00210          * removes the need for the copy of INT 30h in the HMA area, and therefore opens up all 64KB of
00211          * HMA if you want. */
00212         Bitu DOS_Get_CPM_entry_direct(void);
00213 
00214             /* far call opcode */
00215         sSave(sPSP,far_call,0x9a);
00216         /* and where to call to */
00217         sSave(sPSP,cpm_entry,DOS_Get_CPM_entry_direct());
00218     }
00219     else { /* off */
00220         /* stick an INT 20h in there to make calling the CP/M entry point an immediate exit */
00221         /* 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. */
00222         sSave(sPSP,far_call,0xCD);      // INT 20h + NOP NOP NOP
00223         sSave(sPSP,cpm_entry,0x90909020);
00224     }
00225         /* Standard blocks,int 20  and int21 retf */
00226         sSave(sPSP,exit[0],0xcd);
00227         sSave(sPSP,exit[1],0x20);
00228         sSave(sPSP,service[0],0xcd);
00229         sSave(sPSP,service[1],0x21);
00230         sSave(sPSP,service[2],0xcb);
00231         /* psp and psp-parent */
00232         sSave(sPSP,psp_parent,dos.psp());
00233         sSave(sPSP,prev_psp,0xffffffff);
00234         sSave(sPSP,dos_version,0x0005);
00235         /* terminate 22,break 23,crititcal error 24 address stored */
00236         SaveVectors();
00237 
00238         /* FCBs are filled with 0 */
00239         // ....
00240         /* Init file pointer and max_files */
00241         sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files)));
00242         sSave(sPSP,max_files,20);
00243         for (Bit16u ct=0;ct<20;ct++) SetFileHandle(ct,0xff);
00244 
00245         /* User Stack pointer */
00246 //      if (prevpsp.GetSegment()!=0) sSave(sPSP,stack,prevpsp.GetStack());
00247 
00248         if (rootpsp==0) rootpsp = seg;
00249 }
00250 
00251 Bit8u DOS_PSP::GetFileHandle(Bit16u index) {
00252         if (index>=sGet(sPSP,max_files)) return 0xff;
00253         PhysPt files=Real2Phys(sGet(sPSP,file_table));
00254         return mem_readb(files+index);
00255 }
00256 
00257 void DOS_PSP::SetFileHandle(Bit16u index, Bit8u handle) {
00258         if (index<sGet(sPSP,max_files)) {
00259                 PhysPt files=Real2Phys(sGet(sPSP,file_table));
00260                 mem_writeb(files+index,handle);
00261         }
00262 }
00263 
00264 Bit16u DOS_PSP::FindFreeFileEntry(void) {
00265         PhysPt files=Real2Phys(sGet(sPSP,file_table));
00266         for (Bit16u i=0;i<sGet(sPSP,max_files);i++) {
00267                 if (mem_readb(files+i)==0xff) return i;
00268         }       
00269         return 0xff;
00270 }
00271 
00272 Bit16u DOS_PSP::FindEntryByHandle(Bit8u handle) {
00273         PhysPt files=Real2Phys(sGet(sPSP,file_table));
00274         for (Bit16u i=0;i<sGet(sPSP,max_files);i++) {
00275                 if (mem_readb(files+i)==handle) return i;
00276         }       
00277         return 0xFF;
00278 }
00279 
00280 void DOS_PSP::CopyFileTable(DOS_PSP* srcpsp,bool createchildpsp) {
00281         /* Copy file table from calling process */
00282         for (Bit16u i=0;i<20;i++) {
00283                 Bit8u handle = srcpsp->GetFileHandle(i);
00284                 if(createchildpsp)
00285                 {       //copy obeying not inherit flag.(but dont duplicate them)
00286                         bool allowCopy = true;//(handle==0) || ((handle>0) && (FindEntryByHandle(handle)==0xff));
00287                         if((handle<DOS_FILES) && Files[handle] && !(Files[handle]->flags & DOS_NOT_INHERIT) && allowCopy)
00288                         {   
00289                                 Files[handle]->AddRef();
00290                                 SetFileHandle(i,handle);
00291                         }
00292                         else
00293                         {
00294                                 SetFileHandle(i,0xff);
00295                         }
00296                 }
00297                 else
00298                 {       //normal copy so don't mind the inheritance
00299                         SetFileHandle(i,handle);
00300                 }
00301         }
00302 }
00303 
00304 void DOS_PSP::CloseFiles(void) {
00305         for (Bit16u i=0;i<sGet(sPSP,max_files);i++) {
00306                 DOS_CloseFile(i);
00307         }
00308 }
00309 
00310 void DOS_PSP::SaveVectors(void) {
00311         /* Save interrupt 22,23,24 */
00312         sSave(sPSP,int_22,RealGetVec(0x22));
00313         sSave(sPSP,int_23,RealGetVec(0x23));
00314         sSave(sPSP,int_24,RealGetVec(0x24));
00315 }
00316 
00317 void DOS_PSP::RestoreVectors(void) {
00318         /* Restore interrupt 22,23,24 */
00319         RealSetVec(0x22,sGet(sPSP,int_22));
00320         RealSetVec(0x23,sGet(sPSP,int_23));
00321         RealSetVec(0x24,sGet(sPSP,int_24));
00322 }
00323 
00324 void DOS_PSP::SetCommandTail(RealPt src) {
00325         if (src) {      // valid source
00326                 MEM_BlockCopy(pt+offsetof(sPSP,cmdtail),Real2Phys(src),128);
00327         } else {        // empty
00328                 sSave(sPSP,cmdtail.count,0x00);
00329                 mem_writeb(pt+offsetof(sPSP,cmdtail.buffer),0x0d);
00330         };
00331 }
00332 
00333 void DOS_PSP::SetFCB1(RealPt src) {
00334         if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb1)),Real2Phys(src),16);
00335 }
00336 
00337 void DOS_PSP::SetFCB2(RealPt src) {
00338         if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb2)),Real2Phys(src),16);
00339 }
00340 
00341 bool DOS_PSP::SetNumFiles(Bit16u fileNum) {
00342         //20 minimum. clipper program.
00343         if (fileNum < 20) fileNum = 20;
00344          
00345         if (fileNum>20) {
00346                 // Allocate needed paragraphs
00347                 fileNum+=2;     // Add a few more files for safety
00348                 Bit16u para = (fileNum/16)+((fileNum%16)>0);
00349                 RealPt data     = RealMake(DOS_GetMemory(para,"SetNumFiles data"),0);
00350                 sSave(sPSP,file_table,data);
00351                 sSave(sPSP,max_files,fileNum);
00352                 Bit16u i;
00353                 for (i=0; i<20; i++)            SetFileHandle(i,(Bit8u)sGet(sPSP,files[i]));
00354                 for (i=20; i<fileNum; i++)      SetFileHandle(i,0xFF);
00355         } else {
00356                 sSave(sPSP,max_files,fileNum);
00357         };
00358         return true;
00359 }
00360 
00361 
00362 void DOS_DTA::SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * pattern) {
00363         sSave(sDTA,sdrive,_sdrive);
00364         sSave(sDTA,sattr,_sattr);
00365         /* Fill with spaces */
00366         Bitu i;
00367         for (i=0;i<11;i++) mem_writeb(pt+offsetof(sDTA,sname)+i,' ');
00368         char * find_ext;
00369         find_ext=strchr(pattern,'.');
00370         if (find_ext) {
00371                 Bitu size=(Bitu)(find_ext-pattern);
00372                 if (size>8) size=8;
00373                 MEM_BlockWrite(pt+offsetof(sDTA,sname),pattern,size);
00374                 find_ext++;
00375                 MEM_BlockWrite(pt+offsetof(sDTA,sext),find_ext,(strlen(find_ext)>3) ? 3 : (Bitu)strlen(find_ext));
00376         } else {
00377                 MEM_BlockWrite(pt+offsetof(sDTA,sname),pattern,(strlen(pattern) > 8) ? 8 : (Bitu)strlen(pattern));
00378         }
00379 }
00380 
00381 void DOS_DTA::SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr) {
00382         MEM_BlockWrite(pt+offsetof(sDTA,name),(void *)_name,DOS_NAMELENGTH_ASCII);
00383         sSave(sDTA,size,_size);
00384         sSave(sDTA,date,_date);
00385         sSave(sDTA,time,_time);
00386         sSave(sDTA,attr,_attr);
00387 }
00388 
00389 
00390 void DOS_DTA::GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr) {
00391         MEM_BlockRead(pt+offsetof(sDTA,name),_name,DOS_NAMELENGTH_ASCII);
00392         _size=sGet(sDTA,size);
00393         _date=(Bit16u)sGet(sDTA,date);
00394         _time=(Bit16u)sGet(sDTA,time);
00395         _attr=(Bit8u)sGet(sDTA,attr);
00396 }
00397 
00398 Bit8u DOS_DTA::GetSearchDrive(void) {
00399         return (Bit8u)sGet(sDTA,sdrive);
00400 }
00401 
00402 void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern) {
00403         attr=(Bit8u)sGet(sDTA,sattr);
00404         char temp[11];
00405         MEM_BlockRead(pt+offsetof(sDTA,sname),temp,11);
00406         memcpy(pattern,temp,8);
00407         pattern[8]='.';
00408         memcpy(&pattern[9],&temp[8],3);
00409         pattern[12]=0;
00410 
00411 }
00412 
00413 DOS_FCB::DOS_FCB(Bit16u seg,Bit16u off,bool allow_extended) { 
00414         SetPt(seg,off); 
00415         real_pt=pt;
00416         extended=false;
00417         if (allow_extended) {
00418                 if (sGet(sFCB,drive)==0xff) {
00419                         pt+=7;
00420                         extended=true;
00421                 }
00422         }
00423 }
00424 
00425 bool DOS_FCB::Extended(void) {
00426         return extended;
00427 }
00428 
00429 void DOS_FCB::Create(bool _extended) {
00430         Bitu fill;
00431         if (_extended) fill=36+7;
00432         else fill=36;
00433         Bitu i;
00434         for (i=0;i<fill;i++) mem_writeb(real_pt+i,0);
00435         pt=real_pt;
00436         if (_extended) {
00437                 mem_writeb(real_pt,0xff);
00438                 pt+=7;
00439                 extended=true;
00440         } else extended=false;
00441 }
00442 
00443 void DOS_FCB::SetName(Bit8u _drive,char * _fname,char * _ext) {
00444         sSave(sFCB,drive,_drive);
00445         MEM_BlockWrite(pt+offsetof(sFCB,filename),_fname,8);
00446         MEM_BlockWrite(pt+offsetof(sFCB,ext),_ext,3);
00447 }
00448 
00449 void DOS_FCB::SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time) {
00450         sSave(sFCB,filesize,_size);
00451         sSave(sFCB,date,_date);
00452         sSave(sFCB,time,_time);
00453 }
00454 
00455 void DOS_FCB::GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time) {
00456         _size=sGet(sFCB,filesize);
00457         _date=(Bit16u)sGet(sFCB,date);
00458         _time=(Bit16u)sGet(sFCB,time);
00459 }
00460 
00461 void DOS_FCB::GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec) {
00462         _cur_block=(Bit16u)sGet(sFCB,cur_block);
00463         _cur_rec=(Bit8u)sGet(sFCB,cur_rec);
00464 
00465 }
00466 
00467 void DOS_FCB::SetRecord(Bit16u _cur_block,Bit8u _cur_rec) {
00468         sSave(sFCB,cur_block,_cur_block);
00469         sSave(sFCB,cur_rec,_cur_rec);
00470 }
00471 
00472 void DOS_FCB::GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size) {
00473         _fhandle=(Bit8u)sGet(sFCB,file_handle);
00474         _rec_size=(Bit16u)sGet(sFCB,rec_size);
00475 }
00476 
00477 
00478 void DOS_FCB::GetRandom(Bit32u & _random) {
00479         _random=sGet(sFCB,rndm);
00480 }
00481 
00482 void DOS_FCB::SetRandom(Bit32u _random) {
00483         sSave(sFCB,rndm,_random);
00484 }
00485 
00486 void DOS_FCB::FileOpen(Bit8u _fhandle) {
00487         sSave(sFCB,drive,GetDrive()+1u);
00488         sSave(sFCB,file_handle,_fhandle);
00489         sSave(sFCB,cur_block,0u);
00490         sSave(sFCB,rec_size,128u);
00491 //      sSave(sFCB,rndm,0); // breaks Jewels of darkness. 
00492         Bit8u temp = RealHandle(_fhandle);
00493         Bit32u size = 0;
00494         Files[temp]->Seek(&size,DOS_SEEK_END);
00495         sSave(sFCB,filesize,size);
00496         size = 0;
00497         Files[temp]->Seek(&size,DOS_SEEK_SET);
00498         sSave(sFCB,time,Files[temp]->time);
00499         sSave(sFCB,date,Files[temp]->date);
00500 }
00501 
00502 bool DOS_FCB::Valid() {
00503         //Very simple check for Oubliette
00504         if(sGet(sFCB,filename[0]) == 0 && sGet(sFCB,file_handle) == 0) return false;
00505         return true;
00506 }
00507 
00508 void DOS_FCB::FileClose(Bit8u & _fhandle) {
00509         _fhandle=(Bit8u)sGet(sFCB,file_handle);
00510         sSave(sFCB,file_handle,0xff);
00511 }
00512 
00513 Bit8u DOS_FCB::GetDrive(void) {
00514         Bit8u drive=(Bit8u)sGet(sFCB,drive);
00515         if (!drive) return  DOS_GetDefaultDrive();
00516         else return drive-1;
00517 }
00518 
00519 void DOS_FCB::GetName(char * fillname) {
00520         fillname[0]=GetDrive()+'A';
00521         fillname[1]=':';
00522         MEM_BlockRead(pt+offsetof(sFCB,filename),&fillname[2],8);
00523         fillname[10]='.';
00524         MEM_BlockRead(pt+offsetof(sFCB,ext),&fillname[11],3);
00525         fillname[14]=0;
00526 }
00527 
00528 void DOS_FCB::GetAttr(Bit8u& attr) {
00529         if(extended) attr=mem_readb(pt - 1);
00530 }
00531 
00532 void DOS_FCB::SetAttr(Bit8u attr) {
00533         if(extended) mem_writeb(pt - 1,attr);
00534 }
00535 
00536 void DOS_FCB::SetResultAttr(Bit8u attr) {
00537         mem_writeb(pt + 12,attr);
00538 }
00539 
00540 void DOS_SDA::Init() {
00541         /* Clear */
00542         for(Bitu i=0;i<sizeof(sSDA);i++) mem_writeb(pt+i,0x00);
00543         sSave(sSDA,drive_crit_error,0xff);   
00544 }