DOSBox-X
|
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 }