diff --git a/include/dos_inc.h b/include/dos_inc.h index 1919684a..a3729e26 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -110,19 +110,19 @@ 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 DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount); -bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type); -bool DOS_CloseFile(Bit16u handle); +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 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 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); @@ -501,6 +501,7 @@ public: 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); @@ -529,6 +530,8 @@ private: 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 */ diff --git a/src/dos/dos_classes.cpp b/src/dos/dos_classes.cpp index ac2d622d..5f59e839 100644 --- a/src/dos/dos_classes.cpp +++ b/src/dos/dos_classes.cpp @@ -435,6 +435,10 @@ void DOS_FCB::GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size) { _rec_size=(Bit16u)sGet(sFCB,rec_size); } +void DOS_FCB::SetSeqData(Bit8u _fhandle,Bit16u _rec_size) { + sSave(sFCB,file_handle,_fhandle); + sSave(sFCB,rec_size,_rec_size); +} void DOS_FCB::GetRandom(Bit32u & _random) { _random=sGet(sFCB,rndm); @@ -454,14 +458,13 @@ void DOS_FCB::FileOpen(Bit8u _fhandle) { sSave(sFCB,cur_block,0); sSave(sFCB,rec_size,128); // sSave(sFCB,rndm,0); // breaks Jewels of darkness. - Bit8u temp = RealHandle(_fhandle); Bit32u size = 0; - Files[temp]->Seek(&size,DOS_SEEK_END); + Files[_fhandle]->Seek(&size,DOS_SEEK_END); sSave(sFCB,filesize,size); size = 0; - Files[temp]->Seek(&size,DOS_SEEK_SET); - sSave(sFCB,time,Files[temp]->time); - sSave(sFCB,date,Files[temp]->date); + Files[_fhandle]->Seek(&size,DOS_SEEK_SET); + sSave(sFCB,time,Files[_fhandle]->time); + sSave(sFCB,date,Files[_fhandle]->date); } bool DOS_FCB::Valid() { diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index 614cdb90..38853bf0 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.cpp @@ -365,8 +365,8 @@ bool DOS_FindNext(void) { } -bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount) { - Bit32u handle=RealHandle(entry); +bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount,bool fcb) { + Bit32u handle = fcb?entry:RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; @@ -387,8 +387,8 @@ bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount) { return ret; } -bool DOS_WriteFile(Bit16u entry,Bit8u * data,Bit16u * amount) { - Bit32u handle=RealHandle(entry); +bool DOS_WriteFile(Bit16u entry,Bit8u * data,Bit16u * amount,bool fcb) { + Bit32u handle = fcb?entry:RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; @@ -409,8 +409,8 @@ bool DOS_WriteFile(Bit16u entry,Bit8u * data,Bit16u * amount) { return ret; } -bool DOS_SeekFile(Bit16u entry,Bit32u * pos,Bit32u type) { - Bit32u handle=RealHandle(entry); +bool DOS_SeekFile(Bit16u entry,Bit32u * pos,Bit32u type,bool fcb) { + Bit32u handle = fcb?entry:RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; @@ -422,8 +422,8 @@ bool DOS_SeekFile(Bit16u entry,Bit32u * pos,Bit32u type) { return Files[handle]->Seek(pos,type); } -bool DOS_CloseFile(Bit16u entry) { - Bit32u handle=RealHandle(entry); +bool DOS_CloseFile(Bit16u entry, bool fcb) { + Bit32u handle = fcb?entry:RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; @@ -435,8 +435,10 @@ bool DOS_CloseFile(Bit16u entry) { if (Files[handle]->IsOpen()) { Files[handle]->Close(); } + DOS_PSP psp(dos.psp()); - psp.SetFileHandle(entry,0xff); + if (!fcb) psp.SetFileHandle(entry,0xff); + if (Files[handle]->RemoveRef()<=0) { delete Files[handle]; Files[handle]=0; @@ -473,7 +475,7 @@ static bool PathExists(char const * const name) { } -bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry) { +bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry,bool fcb) { // Creation of a device is the same as opening it // Tc201 installer if (DOS_FindDevice(name) != DOS_DEVICES) @@ -496,7 +498,7 @@ bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry) { return false; } /* We have a position in the main table now find one in the psp table */ - *entry = psp.FindFreeFileEntry(); + *entry = fcb?handle:psp.FindFreeFileEntry(); if (*entry==0xff) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); return false; @@ -510,7 +512,7 @@ bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry) { if (foundit) { Files[handle]->SetDrive(drive); Files[handle]->AddRef(); - psp.SetFileHandle(*entry,handle); + if (!fcb) psp.SetFileHandle(*entry,handle); return true; } else { if(!PathExists(name)) DOS_SetError(DOSERR_PATH_NOT_FOUND); @@ -519,7 +521,7 @@ bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry) { } } -bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry) { +bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry,bool fcb) { /* First check for devices */ if (flags>2) LOG(LOG_FILES,LOG_ERROR)("Special file open command %X file %s",flags,name); else LOG(LOG_FILES,LOG_NORMAL)("file open command %X file %s",flags,name); @@ -552,7 +554,7 @@ bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry) { return false; } /* We have a position in the main table now find one in the psp table */ - *entry = psp.FindFreeFileEntry(); + *entry = fcb?handle:psp.FindFreeFileEntry(); if (*entry==0xff) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); @@ -567,7 +569,7 @@ bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry) { } if (exists || device ) { Files[handle]->AddRef(); - psp.SetFileHandle(*entry,handle); + if (!fcb) psp.SetFileHandle(*entry,handle); return true; } else { //Test if file exists, but opened in read-write mode (and writeprotected) @@ -959,7 +961,7 @@ bool DOS_FCBCreate(Bit16u seg,Bit16u offset) { Bit8u attr = DOS_ATTR_ARCHIVE; fcb.GetAttr(attr); if (!attr) attr = DOS_ATTR_ARCHIVE; //Better safe than sorry - if (!DOS_CreateFile(shortname,attr,&handle)) return false; + if (!DOS_CreateFile(shortname,attr,&handle,true)) return false; fcb.FileOpen((Bit8u)handle); return true; } @@ -975,21 +977,15 @@ bool DOS_FCBOpen(Bit16u seg,Bit16u offset) { if (!DOS_MakeName(shortname,fullname,&drive)) return false; /* Check, if file is already opened */ - for (Bit8u i=0;iIsOpen() && Files[i]->IsName(fullname)) { - handle = psp.FindEntryByHandle(i); - if (handle==0xFF) { - // This shouldnt happen - LOG(LOG_FILES,LOG_ERROR)("DOS: File %s is opened but has no psp entry.",shortname); - return false; - } - fcb.FileOpen((Bit8u)handle); + Files[i]->AddRef(); + fcb.FileOpen(i); return true; } } - if (!DOS_OpenFile(shortname,OPEN_READWRITE,&handle)) return false; + if (!DOS_OpenFile(shortname,OPEN_READWRITE,&handle,true)) return false; fcb.FileOpen((Bit8u)handle); return true; } @@ -999,7 +995,7 @@ bool DOS_FCBClose(Bit16u seg,Bit16u offset) { if(!fcb.Valid()) return false; Bit8u fhandle; fcb.FileClose(fhandle); - DOS_CloseFile(fhandle); + DOS_CloseFile(fhandle,true); return true; } @@ -1033,11 +1029,15 @@ Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset,Bit16u recno) { LOG(LOG_FCB,LOG_WARN)("Reopened closed FCB"); fcb.GetSeqData(fhandle,rec_size); } + if (rec_size == 0) { + rec_size = 128; + fcb.SetSeqData(fhandle,rec_size); + } fcb.GetRecord(cur_block,cur_rec); Bit32u pos=((cur_block*128)+cur_rec)*rec_size; - if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET)) return FCB_READ_NODATA; + if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET,true)) return FCB_READ_NODATA; Bit16u toread=rec_size; - if (!DOS_ReadFile(fhandle,dos_copybuf,&toread)) return FCB_READ_NODATA; + if (!DOS_ReadFile(fhandle,dos_copybuf,&toread,true)) return FCB_READ_NODATA; if (toread==0) return FCB_READ_NODATA; if (toread < rec_size) { //Zero pad copybuffer to rec_size Bitu i = toread; @@ -1060,12 +1060,16 @@ Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u recno) { LOG(LOG_FCB,LOG_WARN)("Reopened closed FCB"); fcb.GetSeqData(fhandle,rec_size); } + if (rec_size == 0) { + rec_size = 128; + fcb.SetSeqData(fhandle,rec_size); + } fcb.GetRecord(cur_block,cur_rec); Bit32u pos=((cur_block*128)+cur_rec)*rec_size; - if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET)) return FCB_ERR_WRITE; + if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET,true)) return FCB_ERR_WRITE; MEM_BlockRead(Real2Phys(dos.dta())+recno*rec_size,dos_copybuf,rec_size); Bit16u towrite=rec_size; - if (!DOS_WriteFile(fhandle,dos_copybuf,&towrite)) return FCB_ERR_WRITE; + if (!DOS_WriteFile(fhandle,dos_copybuf,&towrite,true)) return FCB_ERR_WRITE; Bit32u size;Bit16u date,time; fcb.GetSizeDateTime(size,date,time); if (pos+towrite>size) size=pos+towrite; @@ -1077,9 +1081,8 @@ Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u recno) { Bit16u min = (Bit16u)((seconds % 3600)/60); Bit16u sec = (Bit16u)(seconds % 60); time = DOS_PackTime(hour,min,sec); - Bit8u temp=RealHandle(fhandle); - Files[temp]->time=time; - Files[temp]->date=date; + Files[fhandle]->time = time; + Files[fhandle]->date = date; fcb.SetSizeDateTime(size,date,time); if (++cur_rec>127) { cur_block++;cur_rec=0; } fcb.SetRecord(cur_block,cur_rec); @@ -1092,9 +1095,9 @@ Bit8u DOS_FCBIncreaseSize(Bit16u seg,Bit16u offset) { fcb.GetSeqData(fhandle,rec_size); fcb.GetRecord(cur_block,cur_rec); Bit32u pos=((cur_block*128)+cur_rec)*rec_size; - if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET)) return FCB_ERR_WRITE; + if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET,true)) return FCB_ERR_WRITE; Bit16u towrite=0; - if (!DOS_WriteFile(fhandle,dos_copybuf,&towrite)) return FCB_ERR_WRITE; + if (!DOS_WriteFile(fhandle,dos_copybuf,&towrite,true)) return FCB_ERR_WRITE; Bit32u size;Bit16u date,time; fcb.GetSizeDateTime(size,date,time); if (pos+towrite>size) size=pos+towrite; @@ -1106,9 +1109,8 @@ Bit8u DOS_FCBIncreaseSize(Bit16u seg,Bit16u offset) { Bit16u min = (Bit16u)((seconds % 3600)/60); Bit16u sec = (Bit16u)(seconds % 60); time = DOS_PackTime(hour,min,sec); - Bit8u temp=RealHandle(fhandle); - Files[temp]->time=time; - Files[temp]->date=date; + Files[fhandle]->time = time; + Files[fhandle]->date = date; fcb.SetSizeDateTime(size,date,time); fcb.SetRecord(cur_block,cur_rec); return FCB_SUCCESS; @@ -1178,14 +1180,18 @@ Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u * numRec,bool restore) } bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset) { - char shortname[DOS_PATHLENGTH];Bit16u entry;Bit8u handle;Bit16u rec_size; + char shortname[DOS_PATHLENGTH];Bit16u entry; DOS_FCB fcb(seg,offset); fcb.GetName(shortname); - if (!DOS_OpenFile(shortname,OPEN_READ,&entry)) return false; - handle = RealHandle(entry); + if (!DOS_OpenFile(shortname,OPEN_READ,&entry,true)) return false; Bit32u size = 0; - Files[handle]->Seek(&size,DOS_SEEK_END); - DOS_CloseFile(entry);fcb.GetSeqData(handle,rec_size); + Files[entry]->Seek(&size,DOS_SEEK_END); + DOS_CloseFile(entry,true); + + Bit8u handle; Bit16u rec_size; + fcb.GetSeqData(handle,rec_size); + if (rec_size == 0) rec_size = 128; //Use default if missing. + Bit32u random=(size/rec_size); if (size % rec_size) random++; fcb.SetRandom(random); @@ -1212,7 +1218,7 @@ bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset){ nextfile = DOS_FCBFindNext(seg,offset); } dos.dta(old_dta); /*Restore dta */ - return return_value; + return return_value; } bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset){ @@ -1231,12 +1237,12 @@ bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset){ for (Bit8u i=0;iIsOpen() && Files[i]->IsName(fullname)) { Bit16u handle = psp.FindEntryByHandle(i); + //(more than once maybe) if (handle == 0xFF) { - // This shouldnt happen - LOG(LOG_FILES,LOG_ERROR)("DOS: File %s is opened but has no psp entry.",oldname); - return false; + DOS_CloseFile(i,true); + } else { + DOS_CloseFile(handle); } - DOS_CloseFile(handle); } }