New Drive type: overlay.
When active, this drive redirects new and changed files to a different location. The files in the overlay and normal drive are merged on startup and kept up to date when the game changes something. Files in the overlay are priotizedi, if they exists, above the normal files. The drive will switch to an overlayed version of the file on the first write! (Not when opening the file in write-mode). The overlay is capable of creating missing directories. With the help of DBOVERLAY files, the drive keeps track of files that are present in the normal directory but deleted by the game. All changes are preserved between sessions. Current design principles/limitations/requirements: 1) All directories that can be used for saving, must exist already in the base before mounting. (they will be created by DOSBox if missing in the overlay) 2) All filenames inside the overlay directories are UPPERCASE and conform to the 8.3 standard except for the special DBOVERLAY files. 3) To keep point 1 valid at all times, support for creating/renaming/removing directories has been disabled. Thanks for the help GOG. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@4196
This commit is contained in:
parent
d137ec5c0d
commit
202bfa1155
6 changed files with 1134 additions and 9 deletions
|
@ -128,8 +128,8 @@ public:
|
|||
bool UpdateDateTimeFromHost(void);
|
||||
void FlagReadOnlyMedium(void);
|
||||
void Flush(void);
|
||||
FILE * fhandle; //todo handle this properly
|
||||
private:
|
||||
FILE * fhandle;
|
||||
bool read_only_medium;
|
||||
enum { NONE,READ,WRITE } last_action;
|
||||
};
|
||||
|
|
|
@ -7,4 +7,4 @@ libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioc
|
|||
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
|
||||
drive_iso.cpp dev_con.h dos_mscdex.cpp dos_keyboard_layout.cpp \
|
||||
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp \
|
||||
cdrom_ioctl_os2.cpp
|
||||
cdrom_ioctl_os2.cpp drive_overlay.cpp
|
||||
|
|
|
@ -195,14 +195,14 @@ public:
|
|||
std::string type="dir";
|
||||
cmd->FindString("-t",type,true);
|
||||
bool iscdrom = (type =="cdrom"); //Used for mscdex bug cdrom label name emulation
|
||||
if (type=="floppy" || type=="dir" || type=="cdrom") {
|
||||
if (type=="floppy" || type=="dir" || type=="cdrom" || type =="overlay") {
|
||||
Bit16u sizes[4];
|
||||
Bit8u mediaid;
|
||||
std::string str_size;
|
||||
if (type=="floppy") {
|
||||
str_size="512,1,2880,2880";/* All space free */
|
||||
mediaid=0xF0; /* Floppy 1.44 media */
|
||||
} else if (type=="dir") {
|
||||
} else if (type=="dir" || type == "overlay") {
|
||||
// 512*32*32765==~500MB total size
|
||||
// 512*32*16000==~250MB total free size
|
||||
str_size="512,32,32765,16000";
|
||||
|
@ -381,7 +381,39 @@ public:
|
|||
#else
|
||||
if(temp_line == "/") WriteOut(MSG_Get("PROGRAM_MOUNT_WARNING_OTHER"));
|
||||
#endif
|
||||
newdrive=new localDrive(temp_line.c_str(),sizes[0],bit8size,sizes[2],sizes[3],mediaid);
|
||||
if(type == "overlay") {
|
||||
//Ensure that the base drive exists:
|
||||
if (!Drives[drive-'A']) {
|
||||
WriteOut("No basedrive mounted yet!");
|
||||
return;
|
||||
}
|
||||
localDrive* ldp = dynamic_cast<localDrive*>(Drives[drive-'A']);
|
||||
cdromDrive* cdp = dynamic_cast<cdromDrive*>(Drives[drive-'A']);
|
||||
if (!ldp || cdp) {
|
||||
WriteOut("Basedrive not compatible");
|
||||
return;
|
||||
}
|
||||
std::string base = ldp->getBasedir();
|
||||
Bit8u o_error = 0;
|
||||
newdrive = new Overlay_Drive(base.c_str(),temp_line.c_str(),sizes[0],bit8size,sizes[2],sizes[3],mediaid,o_error);
|
||||
//Erase old drive on succes
|
||||
if (newdrive) {
|
||||
if (o_error) {
|
||||
if (o_error == 1) WriteOut("No mixing of relative and absolute paths. Overlay failed.");
|
||||
else if (o_error == 2) WriteOut("overlay directory can not be the same as underlying filesystem.");
|
||||
else WriteOut("Something went wrong");
|
||||
delete newdrive;
|
||||
return;
|
||||
}
|
||||
delete Drives[drive-'A'];
|
||||
Drives[drive-'A'] = 0;
|
||||
} else {
|
||||
WriteOut("overlaydrive construction failed.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
newdrive=new localDrive(temp_line.c_str(),sizes[0],bit8size,sizes[2],sizes[3],mediaid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
WriteOut(MSG_Get("PROGRAM_MOUNT_ILL_TYPE"),type.c_str());
|
||||
|
@ -396,13 +428,14 @@ public:
|
|||
Drives[drive-'A']=newdrive;
|
||||
/* Set the correct media byte in the table */
|
||||
mem_writeb(Real2Phys(dos.tables.mediaid)+(drive-'A')*9,newdrive->GetMediaByte());
|
||||
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),drive,newdrive->GetInfo());
|
||||
if (type != "overlay") WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),drive,newdrive->GetInfo());
|
||||
else WriteOut("Overlay %s on drive %c mounted.\n",temp_line.c_str(),drive);
|
||||
/* check if volume label is given and don't allow it to updated in the future */
|
||||
if (cmd->FindString("-label",label,true)) newdrive->dirCache.SetLabel(label.c_str(),iscdrom,false);
|
||||
/* For hard drives set the label to DRIVELETTER_Drive.
|
||||
* For floppy drives set the label to DRIVELETTER_Floppy.
|
||||
* This way every drive except cdroms should get a label.*/
|
||||
else if(type == "dir") {
|
||||
else if(type == "dir" || type == "overlay") {
|
||||
label = drive; label += "_DRIVE";
|
||||
newdrive->dirCache.SetLabel(label.c_str(),iscdrom,false);
|
||||
} else if(type == "floppy") {
|
||||
|
|
1039
src/dos/drive_overlay.cpp
Normal file
1039
src/dos/drive_overlay.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -21,6 +21,7 @@
|
|||
#define _DRIVES_H__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sys/types.h>
|
||||
#include "dos_system.h"
|
||||
#include "shell.h" /* for DOS_Shell */
|
||||
|
@ -70,13 +71,17 @@ public:
|
|||
virtual bool isRemote(void);
|
||||
virtual bool isRemovable(void);
|
||||
virtual Bits UnMount(void);
|
||||
private:
|
||||
const char* getBasedir() {return basedir;};
|
||||
protected:
|
||||
char basedir[CROSS_LEN];
|
||||
friend void DOS_Shell::CMD_SUBST(char* args);
|
||||
private:
|
||||
friend void DOS_Shell::CMD_SUBST(char* args);
|
||||
protected:
|
||||
struct {
|
||||
char srch_dir[CROSS_LEN];
|
||||
} srchInfo[MAX_OPENDIRS];
|
||||
|
||||
private:
|
||||
struct {
|
||||
Bit16u bytes_sector;
|
||||
Bit8u sectors_cluster;
|
||||
|
@ -406,6 +411,51 @@ private:
|
|||
VFILE_Block * search_file;
|
||||
};
|
||||
|
||||
class Overlay_Drive: public localDrive {
|
||||
public:
|
||||
Overlay_Drive(const char * startdir,const char* overlay, Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid,Bit8u &error);
|
||||
|
||||
virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags);
|
||||
virtual bool FileCreate(DOS_File * * file,char * name,Bit16u /*attributes*/);
|
||||
virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst);
|
||||
virtual bool FindNext(DOS_DTA & dta);
|
||||
virtual bool FileUnlink(char * name);
|
||||
virtual bool GetFileAttr(char * name,Bit16u * attr);
|
||||
virtual bool FileExists(const char* name);
|
||||
virtual bool Rename(char * oldname,char * newname);
|
||||
virtual bool FileStat(const char* name, FileStat_Block * const stat_block);
|
||||
virtual void EmptyCache(void);
|
||||
|
||||
bool Sync_leading_dirs(const char* dos_filename);
|
||||
FILE* create_file_in_overlay(char* dos_filename, char const* mode);
|
||||
virtual Bits UnMount(void);
|
||||
virtual bool TestDir(char * dir);
|
||||
virtual bool RemoveDir(char * dir);
|
||||
virtual bool MakeDir(char * dir);
|
||||
private:
|
||||
char overlaydir[CROSS_LEN];
|
||||
bool optimize_cache_v1;
|
||||
void add_DOSname_to_cache(const char* name);
|
||||
void remove_DOSname_from_cache(const char* name);
|
||||
void update_cache(bool read_directory_contents = false);
|
||||
|
||||
std::vector<std::string> deleted_files_in_base; //Set is probably better, or some other solution (involving the disk).
|
||||
std::vector<std::string> deleted_paths_in_base; //Currently used to hide the overlay folder.
|
||||
std::string overlap_folder;
|
||||
void add_deleted_file(const char* name, bool create_on_disk=true);
|
||||
void remove_deleted_file(const char* name, bool create_on_disk=true);
|
||||
bool is_deleted_file(const char* name);
|
||||
void add_deleted_path(const char* name);
|
||||
void remove_deleted_path(const char* name);
|
||||
bool is_deleted_path(const char* name);
|
||||
|
||||
void remove_deleted_file_from_disk(const char* dosname);
|
||||
void add_deleted_file_to_disk(const char* dosname);
|
||||
std::string create_filename_of_special_operation(const char* dosname, const char* operation);
|
||||
void convert_overlay_to_DOSname_in_base(char* dirname );
|
||||
//For caching the update_cache routine.
|
||||
std::vector<std::string> DOSnames_cache; //Also set is probably better.
|
||||
const std::string special_prefix;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -436,6 +436,9 @@
|
|||
<File
|
||||
RelativePath="..\src\dos\drive_local.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\dos\drive_overlay.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\dos\drive_virtual.cpp">
|
||||
</File>
|
||||
|
|
Loading…
Add table
Reference in a new issue