From 33c702a8e4db0e240faa319f5ea69de1d5288129 Mon Sep 17 00:00:00 2001 From: Ulf Wohlers Date: Tue, 3 Sep 2002 12:07:58 +0000 Subject: [PATCH] Added missing FCB-functions Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@256 --- include/dos_inc.h | 12 +++ src/dos/dos.cpp | 55 +++++++++- src/dos/dos_classes.cpp | 12 +++ src/dos/dos_files.cpp | 218 ++++++++++++++++++++++++++++++++++++---- 4 files changed, 270 insertions(+), 27 deletions(-) diff --git a/include/dos_inc.h b/include/dos_inc.h index 5edb717f..8de46b2b 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -188,6 +188,14 @@ bool DOS_FCBOpen(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); +bool DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u numBlocks); +bool DOS_FCBCreate(Bit16u seg,Bit16u offset); +Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec); +bool DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec); +bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset,Bit16u numRec); +bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset); +bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset); Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change); /* Extra DOS Interrupts */ void DOS_SetupMisc(void); @@ -249,6 +257,8 @@ public: void Set_filesize(Bit32u a); void Set_date(Bit16u a); void Set_time(Bit16u a); + void Set_current_record(Bit8u a); + void Set_random_record(Bit32u a); // others nog yet handled Bit8u Get_drive(void); void Get_filename(char* a); @@ -258,6 +268,8 @@ public: Bit32u Get_filesize(void); Bit16u Get_date(void); Bit16u Get_time(void); + Bit8u Get_current_record(void); + Bit32u Get_random_record(void); private: PhysPt off; }; diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index c334de40..f847aced 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -202,19 +202,64 @@ static Bitu DOS_21Handler(void) { break; case 0x13: /* Delete File using FCB */ + if (DOS_FCBDeleteFile(SegValue(ds),reg_dx)) reg_al = 0x00; + else reg_al = 0xFF; + break; case 0x14: /* Sequential read from FCB */ + reg_al = DOS_FCBRead(SegValue(ds),reg_dx,0); + LOG_DEBUG("DOS:0x14 FCB-Read used, result:al=%d",reg_al); + break; case 0x15: /* Sequential write to FCB */ + if (DOS_FCBWrite(SegValue(ds),reg_dx,0)) reg_al = 0x00; + else reg_al = 0x01; + LOG_DEBUG("DOS:0x15 FCB-Write used, result:al=%d",reg_al); + break; case 0x16: /* Create or truncate file using FCB */ - case 0x17: /* Rename file using FCB */ + if (DOS_FCBCreate(SegValue(ds),reg_dx)) reg_al = 0x00; + else reg_al = 0x01; + LOG_DEBUG("DOS:0x16 FCB-Create used, result:al=%d",reg_al); + break; + case 0x17: /* Rename file using FCB */ + if (DOS_FCBRenameFile(SegValue(ds),reg_dx)) reg_al = 0x00; + else reg_al = 0xFF; + break; case 0x21: /* Read random record from FCB */ + { DOS_FCB fcb(SegValue(ds),reg_dx); + Bit8u curRec = fcb.Get_current_record(); + Bit16u curBlock = fcb.Get_current_block(); + reg_al = DOS_FCBRead(SegValue(ds),reg_dx,0); + fcb.Set_current_record(curRec); + fcb.Set_current_block(curBlock); + } + LOG_DEBUG("DOS:0x21 FCB-Random read used, result:al=%d",reg_al); + break; case 0x22: /* Write random record to FCB */ + { DOS_FCB fcb(SegValue(ds),reg_dx); + Bit8u curRec = fcb.Get_current_record(); + Bit16u curBlock = fcb.Get_current_block(); + if (DOS_FCBRandomWrite(SegValue(ds),reg_dx,reg_cx)) reg_al = 0x00; + else reg_al = 0x01; + fcb.Set_current_record(curRec); + fcb.Set_current_block(curBlock); + } + LOG_DEBUG("DOS:0x28 FCB-Random write used, result:al=%d",reg_al); + break; case 0x23: /* Get file size for FCB */ + if (DOS_FCBGetFileSize(SegValue(ds),reg_dx,reg_cx)) reg_al = 0x00; + else reg_al = 0xFF; + break; case 0x24: /* Set Random Record number for FCB */ + { DOS_FCB fcb(SegValue(ds),reg_dx); + fcb.Set_random_record(fcb.Get_current_block()*128+fcb.Get_current_record()); + } break; case 0x27: /* Random block read from FCB */ - case 0x28: /* Random Block read to FCB */ - LOG_ERROR("DOS:Unhandled call %02X, FCB Stuff",reg_ah); - reg_al=0xff; /* FCB Calls FAIL */ - //CALLBACK_SCF(true); not needed. + reg_al = DOS_FCBRandomRead(SegValue(ds),reg_dx,reg_cx); + LOG_DEBUG("DOS:0x27 FCB-Random read used, result:al=%d",reg_al); + break; + case 0x28: /* Random Block write to FCB */ + if (DOS_FCBRandomWrite(SegValue(ds),reg_dx,reg_cx)) reg_al = 0x00; + else reg_al = 0x01; + LOG_DEBUG("DOS:0x28 FCB-Random write used, result:al=%d",reg_al); break; case 0x29: /* Parse filename into FCB */ diff --git a/src/dos/dos_classes.cpp b/src/dos/dos_classes.cpp index 04cd8a33..f84995ed 100644 --- a/src/dos/dos_classes.cpp +++ b/src/dos/dos_classes.cpp @@ -208,6 +208,12 @@ void DOS_FCB::Set_date(Bit16u a){ void DOS_FCB::Set_time(Bit16u a){ mem_writew(off+offsetof(sFCB,time)+FCB_EXTENDED,a); } +void DOS_FCB::Set_current_record(Bit8u a){ + mem_writeb(off+offsetof(sFCB,current_relative_record_number)+FCB_EXTENDED,a); +} +void DOS_FCB::Set_random_record(Bit32u a){ + mem_writed(off+offsetof(sFCB,rel_record)+FCB_EXTENDED,a); +} Bit8u DOS_FCB::Get_drive(void){ return mem_readb(off+offsetof(sFCB,drive)+FCB_EXTENDED); } @@ -232,6 +238,12 @@ Bit16u DOS_FCB::Get_date(void){ Bit16u DOS_FCB::Get_time(void){ return mem_readw(off+offsetof(sFCB,time)+FCB_EXTENDED); } +Bit8u DOS_FCB::Get_current_record(void){ + return mem_readb(off+offsetof(sFCB,current_relative_record_number)+FCB_EXTENDED); +} +Bit32u DOS_FCB::Get_random_record(void){ + return mem_readd(off+offsetof(sFCB,rel_record)+FCB_EXTENDED); +} void DOS_ParamBlock::InitExec(RealPt cmdtail) { diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index 4ee82a0c..dab3a320 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.cpp @@ -583,27 +583,13 @@ Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u * fcb.Set_ext(ext); *change=string-backup; return retwaarde; - - - } -bool DOS_FCBOpen(Bit16u seg,Bit16u offset) { - DOS_FCB fcb(seg,offset); - Bit8u drive; - char fullname[DOS_PATHLENGTH]; - if(!FCB_MakeName (&fcb, fullname, &drive)) return false; - if(!Drives[drive]->FileExists(fullname)) return false; //not really needed as stat will error. - struct stat stat_block; - if(!Drives[drive]->FileStat(fullname, &stat_block)) return false; - fcb.Set_filesize((Bit32u)stat_block.st_size); - Bit16u constant = 0; - fcb.Set_current_block(constant); - constant=0x80; - fcb.Set_record_size(constant); - - struct tm *time; - if((time=localtime(&stat_block.st_mtime))!=0){ +void DOS_FCBSetDateTime(DOS_FCB& fcb,struct stat& stat_block) +{ + Bit16u constant; + struct tm *time; + if((time=localtime(&stat_block.st_mtime))!=0){ constant=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */ fcb.Set_time(constant); @@ -616,9 +602,28 @@ bool DOS_FCBOpen(Bit16u seg,Bit16u offset) { constant=4; fcb.Set_date(constant); } - fcb.Set_drive(drive +1); - return true; - } +}; + +bool DOS_FCBOpen(Bit16u seg,Bit16u offset) { + DOS_FCB fcb(seg,offset); + Bit8u drive; + char fullname[DOS_PATHLENGTH]; + if(!FCB_MakeName (&fcb, fullname, &drive)) return false; + if(!Drives[drive]->FileExists(fullname)) return false; //not really needed as stat will error. + + struct stat stat_block; + if(!Drives[drive]->FileStat(fullname, &stat_block)) return false; + fcb.Set_filesize((Bit32u)stat_block.st_size); + Bit16u constant = 0; + fcb.Set_current_block(constant); + constant=0x80; + fcb.Set_record_size(constant); + + DOS_FCBSetDateTime(fcb,stat_block); + + fcb.Set_drive(drive +1); + return true; +} bool DOS_FCBClose(Bit16u seg,Bit16u offset) { DOS_FCB fcb(seg,offset); @@ -707,6 +712,175 @@ bool DOS_FCBFindNext(Bit16u seg,Bit16u offset) return true; } +bool DOS_FCBCreate(Bit16u seg,Bit16u offset) +{ + DOS_FCB fcb(seg,offset); + Bit8u drive; + DOS_File* file; + char fullname[DOS_PATHLENGTH]; + + if (!FCB_MakeName (&fcb, fullname, &drive)) return false; + if (!Drives[drive]->FileCreate(&file,fullname,0)) return false; + // Set Date & time + struct stat stat_block; + Drives[drive]->FileStat(fullname, &stat_block); + DOS_FCBSetDateTime(fcb,stat_block); + file->Close(); + // Clear fcb + fcb.Set_record_size(128); // ? + fcb.Set_current_record(0); + fcb.Set_random_record(0); + fcb.Set_filesize(0); + return true; +}; + +Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset,Bit16u recno) +{ + DOS_FCB fcb(seg,offset); + Bit8u drive; + DOS_File* file; + char fullname[DOS_PATHLENGTH]; + // Open file + if (!FCB_MakeName (&fcb, fullname, &drive)) return 0x01; + if (!Drives[drive]->FileOpen(&file,fullname,OPEN_READ)) return 0x01; + // Position file + Bit32u filePos = (fcb.Get_current_block()*128+fcb.Get_current_record()) * fcb.Get_record_size(); + if (!file->Seek(&filePos,0x00)) { file->Close(); return 0x01; }; // end of file + // Calculate target + Bit8u* target = HostMake(RealSeg(dos.dta),RealOff(dos.dta)+recno*fcb.Get_record_size()); + // Read record + Bit16u toRead = fcb.Get_record_size(); + if (!file->Read(target,&toRead)) { file->Close(); return 0x01; }; + // fill with 0 + memset(target+toRead,0,fcb.Get_record_size()-toRead); + // Update record + Bit8u curRec = fcb.Get_current_record() + 1; + if (curRec>128) { + fcb.Set_current_record(0); + fcb.Set_current_block(fcb.Get_current_block()+1); + } else + fcb.Set_current_record(curRec); + + file->Close(); + // check for error + if (toReadFileOpen(&file,fullname,OPEN_WRITE)) return false; + // Position file + Bit32u filePos = (fcb.Get_current_block()*128+fcb.Get_current_record()) * fcb.Get_record_size(); + if (!file->Seek(&filePos,0x00)) { file->Close(); return false; }; // end of file + // Calculate source + Bit8u* source = HostMake(RealSeg(dos.dta),RealOff(dos.dta)+recno*fcb.Get_record_size()); + // Write record + Bit16u toWrite = fcb.Get_record_size(); + if (!file->Write(source,&toWrite)) { file->Close(); return false; }; + // Update size + Bit32u fsize = fcb.Get_filesize() + toWrite; + fcb.Set_filesize(fsize); + // Update Date & Time + struct stat stat_block; + Drives[drive]->FileStat(fullname, &stat_block); + DOS_FCBSetDateTime(fcb,stat_block); + // Update record + Bit8u curRec = fcb.Get_current_record() + 1; + if (curRec>128) { + fcb.Set_current_record(0); + fcb.Set_current_block(fcb.Get_current_block()+1); + } else + fcb.Set_current_record(curRec); + + file->Close(); + return (toWrite==fcb.Get_record_size()); +}; + +Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec) +{ + DOS_FCB fcb(seg,offset); + Bit16u recno = 0; + Bit8u error; + // Calculate block&rec + fcb.Set_current_block (Bit16u(fcb.Get_random_record() / 128)); + fcb.Set_current_record(Bit8u (fcb.Get_random_record() % 127)); + // Read records + for (int i=0; iFileOpen(&file,fullname,OPEN_WRITE)) return false; + struct stat stat_block; + if(!Drives[drive]->FileStat(fullname, &stat_block)) { file->Close(); return false; }; + Bit32u fsize = (Bit32u)stat_block.st_size; + //compute the size and update the fcb + fcb.Set_random_record(fsize / fcb.Get_record_size()); + if ((fsize % fcb.Get_record_size())!=0) fcb.Set_random_record(fcb.Get_random_record()+1); + fcb.Set_filesize(fsize); + return true; +}; + +bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset) +{ + DOS_FCB fcb(seg,offset); + Bit8u drive; + char fullname[DOS_PATHLENGTH]; + // Open file + if (!FCB_MakeName (&fcb, fullname, &drive)) return false; + return Drives[drive]->FileUnlink(fullname); +}; + +bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset) +{ + Bit8u olddrive,newdrive; + DOS_FCB fcbold(seg,offset); + DOS_FCB fcbnew(seg,offset+16); + char oldfullname[DOS_PATHLENGTH]; + char newfullname[DOS_PATHLENGTH]; + if (!FCB_MakeName (&fcbold, oldfullname, &olddrive)) return false; + if (!FCB_MakeName (&fcbnew, newfullname, &newdrive)) return false; + //TODO Test for different drives maybe + return (Drives[newdrive]->Rename(oldfullname,newfullname)); +}; + #endif bool DOS_FileExists(char * name) {