mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-09 03:41:10 +08:00
Merge branch 'joncampbell123:master' into master
This commit is contained in:
commit
846599c3b9
13
CHANGELOG
13
CHANGELOG
@ -1,5 +1,16 @@
|
||||
0.84.2
|
||||
-
|
||||
- Added support for auto-converting non-image drives
|
||||
(such as mounted local drives) to disk images, so
|
||||
that they will be visible when booting into guest
|
||||
systems. A config option "convertdrivefat" (in
|
||||
[dosbox] section) is added to toggle this setting,
|
||||
or you can toggle via BOOT command's -convertfat
|
||||
and -noconvertfat options. There is also a config
|
||||
option "drive z convert image" (in [dos] section)
|
||||
to control if to convert virtual drive Z:. Much of
|
||||
the code is imported from DOSBox Pure. (Wengier)
|
||||
- Fixed display of total file size in DIR command
|
||||
when the file sizes are very large. (Wengier)
|
||||
0.84.1
|
||||
- Added dosbox(-x).conf option to enable workaround
|
||||
for errant DOS programs that set the TF (trap flag)
|
||||
|
@ -10,7 +10,7 @@
|
||||
<category>Emulation</category>
|
||||
</categories>
|
||||
<releases>
|
||||
<release version="@PACKAGE_VERSION@" date="2022-7-1"/>
|
||||
<release version="@PACKAGE_VERSION@" date="2022-7-3"/>
|
||||
</releases>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
|
@ -396,6 +396,7 @@ debuggerrun = debugger
|
||||
# If set to "relative", the value of MOUNT -freesize will change relative to the specified value.
|
||||
# If set to "fixed" (="false"), the value of MOUNT -freesize will be a fixed one to be reported all the time.
|
||||
# Possible values: true, false, fixed, relative, cap, 2, 1, 0.
|
||||
# convertdrivefat: If set, DOSBox-X will auto-convert mounted non-FAT drives (such as local drives) to FAT format for use with guest systems.
|
||||
#DOSBOX-X-ADV:# leading colon write protect image: If set, BOOT and IMGMOUNT commands will put an image file name with a leading colon (:) in write-protect mode.
|
||||
#DOSBOX-X-ADV:# locking disk image mount: If set, BOOT and IMGMOUNT commands will try to lock the mounted disk image files. As a result, you cannot
|
||||
#DOSBOX-X-ADV:# mount the same disk image files in read/write mode at the same time as this can cause possible disk corruptions.
|
||||
@ -495,6 +496,7 @@ memsize = 16
|
||||
#DOSBOX-X-ADV:memalias = 0
|
||||
nocachedir = false
|
||||
freesizecap = cap
|
||||
convertdrivefat = true
|
||||
#DOSBOX-X-ADV:leading colon write protect image = true
|
||||
#DOSBOX-X-ADV:locking disk image mount = true
|
||||
#DOSBOX-X-ADV:unmask keyboard on int 16 read = true
|
||||
@ -2069,6 +2071,7 @@ timeout = 0
|
||||
#DOSBOX-X-ADV:# Set this option to true to prevent SCANDISK.EXE from attempting scan and repair drive Z:
|
||||
#DOSBOX-X-ADV:# which is impossible since Z: is a virtual drive not backed by a disk filesystem.
|
||||
#DOSBOX-X-ADV:# Possible values: true, false, 1, 0, auto.
|
||||
#DOSBOX-X-ADV:# drive z convert fat: If set, DOSBox-X will automatically convert the Z drive into disk image as well when "convertdrivefat" is set.
|
||||
#DOSBOX-X-ADV:# drive z expand path: If set, DOSBox-X will automatically expand the %PATH% environment variable to include the subdirectories on the Z drive.
|
||||
#DOSBOX-X-ADV:# drive z hide files: The files or directories listed here (separated by space) will be either hidden or removed from the Z drive.
|
||||
#DOSBOX-X-ADV:# Files with leading forward slashes (e.g. "/DEBUG\BIOSTEST.COM") will become hidden files (DIR /A will list them).
|
||||
@ -2251,7 +2254,7 @@ timeout = 0
|
||||
# dos clipboard api: If set, DOS APIs for communications with the Windows clipboard will be enabled for shared clipboard communications.
|
||||
#DOSBOX-X-ADV-SEE:#
|
||||
#DOSBOX-X-ADV-SEE:# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details):
|
||||
#DOSBOX-X-ADV-SEE:# -> badcommandhandler; hma allow reservation; special operation file prefix; drive z is remote; drive z expand path; drive z hide files; hidenonrepresentable; hma minimum allocation; dos sda size; hma free space; cpm compatibility mode; minimum dos initial private segment; minimum mcb segment; enable dummy device mcb; maximum environment block size on exec; additional environment block size on exec; enable a20 on windows init; zero memory on xms memory allocation; vcpi; unmask timer on disk io; zero int 67h if no ems; zero unused int 68h; emm386 startup active; zero memory on ems memory allocation; ems system handle memory size; ems system handle on even megabyte; umb start; umb end; kernel allocation in umb; keep umb on boot; keep private area on boot; private area in umb; autoa20fix; autoloadfix; startincon; int33 hide host cursor if interrupt subroutine; int33 hide host cursor when polling; int33 disable cell granularity; int 13 disk change detect; int 13 extensions; biosps2; int15 wait force unmask irq; int15 mouse callback does not preserve registers; filenamechar; collating and uppercase; con device use int 16h to detect keyboard input; zero memory on int 21h memory allocation
|
||||
#DOSBOX-X-ADV-SEE:# -> badcommandhandler; hma allow reservation; special operation file prefix; drive z is remote; drive z convert fat; drive z expand path; drive z hide files; hidenonrepresentable; hma minimum allocation; dos sda size; hma free space; cpm compatibility mode; minimum dos initial private segment; minimum mcb segment; enable dummy device mcb; maximum environment block size on exec; additional environment block size on exec; enable a20 on windows init; zero memory on xms memory allocation; vcpi; unmask timer on disk io; zero int 67h if no ems; zero unused int 68h; emm386 startup active; zero memory on ems memory allocation; ems system handle memory size; ems system handle on even megabyte; umb start; umb end; kernel allocation in umb; keep umb on boot; keep private area on boot; private area in umb; autoa20fix; autoloadfix; startincon; int33 hide host cursor if interrupt subroutine; int33 hide host cursor when polling; int33 disable cell granularity; int 13 disk change detect; int 13 extensions; biosps2; int15 wait force unmask irq; int15 mouse callback does not preserve registers; filenamechar; collating and uppercase; con device use int 16h to detect keyboard input; zero memory on int 21h memory allocation
|
||||
#DOSBOX-X-ADV-SEE:#
|
||||
xms = true
|
||||
xms handles = 0
|
||||
@ -2263,6 +2266,7 @@ hard drive data rate limit = -1
|
||||
floppy drive data rate limit = -1
|
||||
#DOSBOX-X-ADV:special operation file prefix = .DB
|
||||
#DOSBOX-X-ADV:drive z is remote = auto
|
||||
#DOSBOX-X-ADV:drive z convert fat = false
|
||||
#DOSBOX-X-ADV:drive z expand path = true
|
||||
#DOSBOX-X-ADV:drive z hide files = /TEXTUTIL\25.COM /TEXTUTIL\28.COM /TEXTUTIL\50.COM
|
||||
#DOSBOX-X-ADV:hidenonrepresentable = true
|
||||
|
@ -192,6 +192,7 @@ debuggerrun = debugger
|
||||
# If set to "relative", the value of MOUNT -freesize will change relative to the specified value.
|
||||
# If set to "fixed" (="false"), the value of MOUNT -freesize will be a fixed one to be reported all the time.
|
||||
# Possible values: true, false, fixed, relative, cap, 2, 1, 0.
|
||||
# convertdrivefat: If set, DOSBox-X will auto-convert mounted non-FAT drives (such as local drives) to FAT format for use with guest systems.
|
||||
#
|
||||
# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details):
|
||||
# -> disable graphical splash; allow quit after warning; keyboard hook; weitek; bochs debug port e9; compresssaveparts; show recorded filename; skip encoding unchanged frames; capture chroma format; capture format; shell environment size; private area size; turn off a20 gate on boot; cbus bus clock; isa bus clock; pci bus clock; call binary on reset; unhandled irq handler; call binary on boot; ibm rom basic; rom bios allocation max; rom bios minimum size; irq delay ns; iodelay; iodelay16; iodelay32; acpi; acpi rsd ptr location; acpi sci irq; acpi iobase; acpi reserved size; memsizekb; dos mem limit; isa memory hole at 512kb; reboot delay; memalias; leading colon write protect image; locking disk image mount; unmask keyboard on int 16 read; int16 keyboard polling undocumented cf behavior; allow port 92 reset; enable port 92; enable 1st dma controller; enable 2nd dma controller; allow dma address decrement; enable 128k capable 16-bit dma; enable dma extra page registers; dma page registers write-only; cascade interrupt never in service; cascade interrupt ignore in service; enable slave pic; enable pc nmi mask; allow more than 640kb base memory; enable pci bus
|
||||
@ -222,6 +223,7 @@ a20 = mask
|
||||
memsize = 16
|
||||
nocachedir = false
|
||||
freesizecap = cap
|
||||
convertdrivefat = true
|
||||
|
||||
[render]
|
||||
# frameskip: How many frames DOSBox-X skips before drawing one.
|
||||
@ -1086,7 +1088,7 @@ timeout = 0
|
||||
# dos clipboard api: If set, DOS APIs for communications with the Windows clipboard will be enabled for shared clipboard communications.
|
||||
#
|
||||
# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details):
|
||||
# -> badcommandhandler; hma allow reservation; special operation file prefix; drive z is remote; drive z expand path; drive z hide files; hidenonrepresentable; hma minimum allocation; dos sda size; hma free space; cpm compatibility mode; minimum dos initial private segment; minimum mcb segment; enable dummy device mcb; maximum environment block size on exec; additional environment block size on exec; enable a20 on windows init; zero memory on xms memory allocation; vcpi; unmask timer on disk io; zero int 67h if no ems; zero unused int 68h; emm386 startup active; zero memory on ems memory allocation; ems system handle memory size; ems system handle on even megabyte; umb start; umb end; kernel allocation in umb; keep umb on boot; keep private area on boot; private area in umb; autoa20fix; autoloadfix; startincon; int33 hide host cursor if interrupt subroutine; int33 hide host cursor when polling; int33 disable cell granularity; int 13 disk change detect; int 13 extensions; biosps2; int15 wait force unmask irq; int15 mouse callback does not preserve registers; filenamechar; collating and uppercase; con device use int 16h to detect keyboard input; zero memory on int 21h memory allocation
|
||||
# -> badcommandhandler; hma allow reservation; special operation file prefix; drive z is remote; drive z convert fat; drive z expand path; drive z hide files; hidenonrepresentable; hma minimum allocation; dos sda size; hma free space; cpm compatibility mode; minimum dos initial private segment; minimum mcb segment; enable dummy device mcb; maximum environment block size on exec; additional environment block size on exec; enable a20 on windows init; zero memory on xms memory allocation; vcpi; unmask timer on disk io; zero int 67h if no ems; zero unused int 68h; emm386 startup active; zero memory on ems memory allocation; ems system handle memory size; ems system handle on even megabyte; umb start; umb end; kernel allocation in umb; keep umb on boot; keep private area on boot; private area in umb; autoa20fix; autoloadfix; startincon; int33 hide host cursor if interrupt subroutine; int33 hide host cursor when polling; int33 disable cell granularity; int 13 disk change detect; int 13 extensions; biosps2; int15 wait force unmask irq; int15 mouse callback does not preserve registers; filenamechar; collating and uppercase; con device use int 16h to detect keyboard input; zero memory on int 21h memory allocation
|
||||
#
|
||||
xms = true
|
||||
xms handles = 0
|
||||
|
@ -388,6 +388,7 @@ debuggerrun = debugger
|
||||
# If set to "relative", the value of MOUNT -freesize will change relative to the specified value.
|
||||
# If set to "fixed" (="false"), the value of MOUNT -freesize will be a fixed one to be reported all the time.
|
||||
# Possible values: true, false, fixed, relative, cap, 2, 1, 0.
|
||||
# convertdrivefat: If set, DOSBox-X will auto-convert mounted non-FAT drives (such as local drives) to FAT format for use with guest systems.
|
||||
# leading colon write protect image: If set, BOOT and IMGMOUNT commands will put an image file name with a leading colon (:) in write-protect mode.
|
||||
# locking disk image mount: If set, BOOT and IMGMOUNT commands will try to lock the mounted disk image files. As a result, you cannot
|
||||
# mount the same disk image files in read/write mode at the same time as this can cause possible disk corruptions.
|
||||
@ -483,6 +484,7 @@ reboot delay = -1
|
||||
memalias = 0
|
||||
nocachedir = false
|
||||
freesizecap = cap
|
||||
convertdrivefat = true
|
||||
leading colon write protect image = true
|
||||
locking disk image mount = true
|
||||
unmask keyboard on int 16 read = true
|
||||
@ -2013,6 +2015,7 @@ timeout = 0
|
||||
# Set this option to true to prevent SCANDISK.EXE from attempting scan and repair drive Z:
|
||||
# which is impossible since Z: is a virtual drive not backed by a disk filesystem.
|
||||
# Possible values: true, false, 1, 0, auto.
|
||||
# drive z convert fat: If set, DOSBox-X will automatically convert the Z drive into disk image as well when "convertdrivefat" is set.
|
||||
# drive z expand path: If set, DOSBox-X will automatically expand the %PATH% environment variable to include the subdirectories on the Z drive.
|
||||
# drive z hide files: The files or directories listed here (separated by space) will be either hidden or removed from the Z drive.
|
||||
# Files with leading forward slashes (e.g. "/DEBUG\BIOSTEST.COM") will become hidden files (DIR /A will list them).
|
||||
@ -2203,6 +2206,7 @@ hard drive data rate limit = -1
|
||||
floppy drive data rate limit = -1
|
||||
special operation file prefix = .DB
|
||||
drive z is remote = auto
|
||||
drive z convert fat = false
|
||||
drive z expand path = true
|
||||
drive z hide files = /TEXTUTIL\25.COM /TEXTUTIL\28.COM /TEXTUTIL\50.COM
|
||||
hidenonrepresentable = true
|
||||
|
@ -65,9 +65,12 @@ class imageDisk {
|
||||
virtual void Get_Geometry(uint32_t * getHeads, uint32_t *getCyl, uint32_t *getSect, uint32_t *getSectSize);
|
||||
virtual uint8_t GetBiosType(void);
|
||||
virtual uint32_t getSectSize(void);
|
||||
imageDisk(class DOS_Drive *useDrive);
|
||||
imageDisk(FILE *imgFile, const char *imgName, uint32_t imgSizeK, bool isHardDisk);
|
||||
imageDisk(FILE* diskimg, const char* diskName, uint32_t cylinders, uint32_t heads, uint32_t sectors, uint32_t sector_size, bool hardDrive);
|
||||
virtual ~imageDisk() { if(diskimg != NULL) { fclose(diskimg); diskimg=NULL; } };
|
||||
virtual ~imageDisk();
|
||||
void Set_GeometryForHardDisk();
|
||||
struct fatFromDOSDrive* ffdd = NULL;
|
||||
|
||||
IMAGE_TYPE class_id = ID_BASE;
|
||||
std::string diskname;
|
||||
@ -91,6 +94,7 @@ class imageDisk {
|
||||
private:
|
||||
volatile int refcount = 0;
|
||||
std::vector<bool> partition_in_use; /* used by FAT driver to prevent mounting a partition twice */
|
||||
uint64_t current_fpos;
|
||||
|
||||
public:
|
||||
int Addref() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*auto-generated*/
|
||||
#define UPDATED_STR "Jul 1, 2022 2:43:23pm"
|
||||
#define GIT_COMMIT_HASH "644ab8a"
|
||||
#define UPDATED_STR "Jul 3, 2022 11:03:27pm"
|
||||
#define GIT_COMMIT_HASH "e73255c"
|
||||
#define COPYRIGHT_END_YEAR "2022"
|
||||
|
@ -332,7 +332,6 @@ public:
|
||||
virtual void closedir(void *handle) { (void)handle; };
|
||||
virtual bool read_directory_first(void *handle, char* entry_name, char* entry_sname, bool& is_directory) { (void)handle; (void)entry_name; (void)entry_sname; (void)is_directory; return false; };
|
||||
virtual bool read_directory_next(void *handle, char* entry_name, char* entry_sname, bool& is_directory) { (void)handle; (void)entry_name; (void)entry_sname; (void)is_directory; return false; };
|
||||
|
||||
virtual const char * GetInfo(void);
|
||||
char * GetBaseDir(void);
|
||||
|
||||
|
@ -99,6 +99,7 @@ bool Mouse_Vertical = false;
|
||||
bool force_nocachedir = false;
|
||||
bool lockmount = true;
|
||||
bool wpcolon = true;
|
||||
bool convertimg = true;
|
||||
bool startcmd = false;
|
||||
bool startwait = true;
|
||||
bool startquiet = false;
|
||||
@ -107,7 +108,7 @@ bool mountwarning = true;
|
||||
bool qmount = false;
|
||||
bool nowarn = false;
|
||||
bool CodePageHostToGuestUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/), CodePageHostToGuestUTF16(char *d/*CROSS_LEN*/,const uint16_t *s/*CROSS_LEN*/);
|
||||
extern bool addovl, addipx, addne2k, prepared, inshell, usecon, uao, morelen, mountfro[26], mountiro[26], resetcolor, staycolors;
|
||||
extern bool addovl, addipx, addne2k, prepared, inshell, usecon, uao, morelen, mountfro[26], mountiro[26], resetcolor, staycolors, internal_program;
|
||||
extern bool clear_screen(), OpenGL_using(void), DOS_SetAnsiAttr(uint8_t attr);
|
||||
extern int lastcp, FileDirExistCP(const char *name), FileDirExistUTF8(std::string &localname, const char *name);
|
||||
extern uint8_t DOS_GetAnsiAttr(void);
|
||||
@ -1846,6 +1847,7 @@ public:
|
||||
bool bios_boot = false;
|
||||
bool swaponedrive = false;
|
||||
bool force = false;
|
||||
int convimg = -1;
|
||||
int quiet = 0;
|
||||
|
||||
//Hack To allow long commandlines
|
||||
@ -1874,6 +1876,12 @@ public:
|
||||
if (cmd->FindExist("-force",true))
|
||||
force = true;
|
||||
|
||||
if (cmd->FindExist("-convertfat",true))
|
||||
convimg = 1;
|
||||
|
||||
if (cmd->FindExist("-noconvertfat",true))
|
||||
convimg = 0;
|
||||
|
||||
if (cmd->FindString("-bios",bios,true))
|
||||
bios_boot = true;
|
||||
|
||||
@ -2490,10 +2498,44 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
char msg[512] = {0};
|
||||
const uint8_t page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
||||
if ((convimg == 1 || (convertimg && convimg == -1 && !IS_PC98_ARCH))) { // PC-98 image not supported yet
|
||||
unsigned int drv = 2, nextdrv = 2;
|
||||
for (unsigned int d=2;d<DOS_DRIVES+2;d++) {
|
||||
if (d==DOS_DRIVES) drv=0;
|
||||
else if (d==DOS_DRIVES+1) drv=1;
|
||||
else drv=d;
|
||||
if (Drives[drv] && strncmp(Drives[drv]->GetInfo(), "fatDrive ", 9) && strncmp(Drives[drv]->GetInfo(), "isoDrive ", 9)) {
|
||||
if (drv==ZDRIVE_NUM && !static_cast<Section_prop *>(control->GetSection("dos"))->Get_bool("drive z convert fat")) continue;
|
||||
while (imageDiskList[nextdrv]) nextdrv++;
|
||||
if (nextdrv>=MAX_DISK_IMAGES) break;
|
||||
if (quiet<2) {
|
||||
size_t len = strlen(msg);
|
||||
if (!len) strcat(msg, CURSOR_POS_COL(page)>0?"\r\n":"");
|
||||
strcat(msg, "Converting drive ");
|
||||
strcat(msg, std::string(1, 'A'+drv).c_str());
|
||||
strcat(msg, ": to FAT...\r\n");
|
||||
LOG_MSG("%s", msg+len);
|
||||
if (!quiet) {
|
||||
uint16_t s = (uint16_t)strlen(msg);
|
||||
DOS_WriteFile(STDERR,(uint8_t*)msg,&s);
|
||||
*msg = 0;
|
||||
}
|
||||
}
|
||||
imageDiskList[nextdrv] = new imageDisk(Drives[drv]);
|
||||
if (imageDiskList[nextdrv]) {
|
||||
bool ide_slave = false;
|
||||
signed char ide_index = -1;
|
||||
IDE_Auto(ide_index,ide_slave);
|
||||
IDE_Hard_Disk_Attach((signed char)ide_index, ide_slave, nextdrv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (quiet<2) {
|
||||
char msg[30];
|
||||
const uint8_t page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
||||
strcpy(msg, CURSOR_POS_COL(page)>0?"\r\n":"");
|
||||
if (!strlen(msg)) strcat(msg, CURSOR_POS_COL(page)>0?"\r\n":"");
|
||||
strcat(msg, "Booting from drive ");
|
||||
strcat(msg, std::string(1, drive).c_str());
|
||||
strcat(msg, "...\r\n");
|
||||
@ -8283,8 +8325,10 @@ void Add_VFiles(bool usecp) {
|
||||
PROGRAMS_MakeFile("CONFIG.COM",CONFIG_ProgramStart,"/SYSTEM/");
|
||||
PROGRAMS_MakeFile("COUNTRY.COM",COUNTRY_ProgramStart,"/SYSTEM/");
|
||||
PROGRAMS_MakeFile("COMMAND.COM",SHELL_ProgramStart);
|
||||
internal_program = true;
|
||||
if (usecp) VFILE_Register("AUTOEXEC.BAT",(uint8_t *)autoexec_data,(uint32_t)strlen(autoexec_data));
|
||||
if (prepared) VFILE_Register("CONFIG.SYS",(uint8_t *)config_data,(uint32_t)strlen(config_data));
|
||||
internal_program = false;
|
||||
PROGRAMS_MakeFile("RE-DOS.COM",REDOS_ProgramStart,"/SYSTEM/");
|
||||
PROGRAMS_MakeFile("RESCAN.COM",RESCAN_ProgramStart,"/SYSTEM/");
|
||||
#if defined(WIN32) && !defined(HX_DOS) || defined(LINUX) || defined(MACOSX)
|
||||
|
@ -633,4 +633,3 @@ void isoDrive::GetLongName(const char* ident, char* lfindName) {
|
||||
strcpy(lfindName,ident);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1402,6 +1402,7 @@ bool localDrive::FileOpen(DOS_File * * file,const char * name,uint32_t flags) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dos_kernel_disabled)
|
||||
for (i=0;i<DOS_FILES;i++) {
|
||||
if (Files[i] && Files[i]->IsOpen() && Files[i]->GetDrive()==drive && Files[i]->IsName(name)) {
|
||||
lfp=dynamic_cast<localFile*>(Files[i]);
|
||||
@ -2283,7 +2284,6 @@ bool localDrive::FileStat(const char* name, FileStat_Block * const stat_block) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t localDrive::GetMediaByte(void) {
|
||||
return allocation.mediaid;
|
||||
}
|
||||
|
@ -593,6 +593,7 @@ bool Overlay_Drive::FileOpen(DOS_File * * file,const char * name,uint32_t flags)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dos_kernel_disabled)
|
||||
for (i=0;i<DOS_FILES;i++) {
|
||||
if (Files[i] && Files[i]->IsOpen() && Files[i]->GetDrive()==drive && Files[i]->IsName(name)) {
|
||||
lfp=dynamic_cast<localFile*>(Files[i]);
|
||||
|
@ -41,13 +41,14 @@ struct VFILE_Block {
|
||||
unsigned int onpos;
|
||||
bool isdir;
|
||||
bool hidden;
|
||||
bool intprog;
|
||||
VFILE_Block * next;
|
||||
};
|
||||
|
||||
#define MAX_VFILES 500
|
||||
unsigned int vfpos=1, lfn_id[256];
|
||||
char ondirs[MAX_VFILES][CROSS_LEN],sfn[DOS_NAMELENGTH_ASCII];
|
||||
char vfnames[MAX_VFILES][CROSS_LEN],vfsnames[MAX_VFILES][DOS_NAMELENGTH_ASCII];
|
||||
bool internal_program = false, skipintprog = false;
|
||||
char sfn[DOS_NAMELENGTH_ASCII],vfnames[MAX_VFILES][CROSS_LEN],vfsnames[MAX_VFILES][DOS_NAMELENGTH_ASCII];
|
||||
static VFILE_Block * first_file, * lfn_search[256], * parent_dir = NULL;
|
||||
|
||||
extern int lfn_filefind_handle;
|
||||
@ -249,7 +250,8 @@ void VFILE_Register(const char * name,uint8_t * data,uint32_t size,const char *d
|
||||
VFILE_Block * new_file=new VFILE_Block;
|
||||
new_file->name=vfsnames[vfpos];
|
||||
new_file->lname=vfnames[vfpos];
|
||||
vfpos++;
|
||||
vfpos++;
|
||||
new_file->intprog = internal_program;
|
||||
new_file->data=data;
|
||||
new_file->size=size;
|
||||
new_file->date=fztime||fzdate?fzdate:DOS_PackDate(2002,10,1);
|
||||
@ -550,7 +552,7 @@ bool Virtual_Drive::FindNext(DOS_DTA & dta) {
|
||||
|
||||
if (lfn_filefind_handle>=LFN_FILEFIND_MAX)
|
||||
while (search_file) {
|
||||
if (pos==search_file->onpos&&((attr & DOS_ATTR_DIRECTORY)||!search_file->isdir)&&(WildFileCmp(search_file->name,pattern)||LWildFileCmp(search_file->lname,pattern))) {
|
||||
if (!(skipintprog && search_file->intprog) && pos==search_file->onpos&&((attr & DOS_ATTR_DIRECTORY)||!search_file->isdir)&&(WildFileCmp(search_file->name,pattern)||LWildFileCmp(search_file->lname,pattern))) {
|
||||
dta.SetResult(search_file->name,search_file->lname,search_file->size,search_file->date,search_file->time,search_file->isdir?(search_file->hidden?DOS_ATTR_DIRECTORY|DOS_ATTR_HIDDEN:DOS_ATTR_DIRECTORY):(search_file->hidden?DOS_ATTR_ARCHIVE|DOS_ATTR_HIDDEN:DOS_ATTR_ARCHIVE));
|
||||
search_file=search_file->next;
|
||||
return true;
|
||||
@ -559,7 +561,7 @@ bool Virtual_Drive::FindNext(DOS_DTA & dta) {
|
||||
}
|
||||
else
|
||||
while (lfn_search[lfn_filefind_handle]) {
|
||||
if (pos==lfn_search[lfn_filefind_handle]->onpos&&((attr & DOS_ATTR_DIRECTORY)||!lfn_search[lfn_filefind_handle]->isdir)&&(WildFileCmp(lfn_search[lfn_filefind_handle]->name,pattern)||LWildFileCmp(lfn_search[lfn_filefind_handle]->lname,pattern))) {
|
||||
if (!(skipintprog && search_file->intprog) && pos==lfn_search[lfn_filefind_handle]->onpos&&((attr & DOS_ATTR_DIRECTORY)||!lfn_search[lfn_filefind_handle]->isdir)&&(WildFileCmp(lfn_search[lfn_filefind_handle]->name,pattern)||LWildFileCmp(lfn_search[lfn_filefind_handle]->lname,pattern))) {
|
||||
dta.SetResult(lfn_search[lfn_filefind_handle]->name,lfn_search[lfn_filefind_handle]->lname,lfn_search[lfn_filefind_handle]->size,lfn_search[lfn_filefind_handle]->date,lfn_search[lfn_filefind_handle]->time,lfn_search[lfn_filefind_handle]->isdir?(lfn_search[lfn_filefind_handle]->hidden?DOS_ATTR_DIRECTORY|DOS_ATTR_HIDDEN:DOS_ATTR_DIRECTORY):(lfn_search[lfn_filefind_handle]->hidden?DOS_ATTR_ARCHIVE|DOS_ATTR_HIDDEN:DOS_ATTR_ARCHIVE));
|
||||
lfn_search[lfn_filefind_handle]=lfn_search[lfn_filefind_handle]->next;
|
||||
return true;
|
||||
|
@ -99,7 +99,6 @@ public:
|
||||
virtual void remove_special_file_from_disk(const char* dosname, const char* operation);
|
||||
virtual std::string create_filename_of_special_operation(const char* dosname, const char* operation, bool expand);
|
||||
virtual bool add_special_file_to_disk(const char* dosname, const char* operation, uint16_t value, bool isdir);
|
||||
|
||||
virtual void EmptyCache(void) { dirCache.EmptyCache(); };
|
||||
virtual void MediaChange() {};
|
||||
const char* getBasedir() {return basedir;};
|
||||
@ -681,7 +680,7 @@ private:
|
||||
bool GetNextDirEntry(const int dirIteratorHandle, isoDirEntry* de);
|
||||
void FreeDirIterator(const int dirIterator);
|
||||
bool ReadCachedSector(uint8_t** buffer, const uint32_t sector);
|
||||
void GetLongName(const char* ident, char* lfindName);
|
||||
void GetLongName(const char* ident, char* lfindName);
|
||||
|
||||
struct DirIterator {
|
||||
bool valid;
|
||||
|
@ -124,6 +124,7 @@ static void CheckX86ExtensionsSupport()
|
||||
extern void GFX_SetTitle(int32_t cycles, int frameskip, Bits timing, bool paused);
|
||||
extern void AddSaveStateMapper(), AddMessages(), JFONT_Init(), J3_SetType(std::string type, std::string back, std::string text);
|
||||
extern bool force_nocachedir;
|
||||
extern bool convertimg;
|
||||
extern bool wpcolon;
|
||||
extern bool lockmount;
|
||||
extern bool clearline;
|
||||
@ -793,9 +794,8 @@ void DOSBOX_InitTickLoop() {
|
||||
void Init_VGABIOS() {
|
||||
long rom_sz = 0;
|
||||
FILE *rom_fp = NULL;
|
||||
Section_prop *section = static_cast<Section_prop *>(control->GetSection("dosbox"));
|
||||
Section_prop *video_section = static_cast<Section_prop *>(control->GetSection("video"));
|
||||
assert(section != NULL && video_section != NULL);
|
||||
assert(video_section != NULL);
|
||||
|
||||
if (IS_PC98_ARCH) {
|
||||
// There IS no VGA BIOS, this is PC-98 mode!
|
||||
@ -812,14 +812,6 @@ void Init_VGABIOS() {
|
||||
// We can remove this once the device callout system is in place.
|
||||
assert(MemBase != NULL);
|
||||
|
||||
force_nocachedir = section->Get_bool("nocachedir");
|
||||
std::string freesizestr = section->Get_string("freesizecap");
|
||||
if (freesizestr == "fixed" || freesizestr == "false" || freesizestr == "0") freesizecap = 0;
|
||||
else if (freesizestr == "relative" || freesizestr == "2") freesizecap = 2;
|
||||
else freesizecap = 1;
|
||||
wpcolon = section->Get_bool("leading colon write protect image");
|
||||
lockmount = section->Get_bool("locking disk image mount");
|
||||
|
||||
VGA_BIOS_use_rom = video_section->Get_bool("vga bios use rom image");
|
||||
VGA_BIOS_rom = video_section->Get_string("vga bios rom image");
|
||||
|
||||
@ -1036,6 +1028,15 @@ void DOSBOX_RealInit() {
|
||||
// TODO: should be parsed by motherboard emulation
|
||||
allow_port_92_reset = section->Get_bool("allow port 92 reset");
|
||||
|
||||
force_nocachedir = section->Get_bool("nocachedir");
|
||||
std::string freesizestr = section->Get_string("freesizecap");
|
||||
if (freesizestr == "fixed" || freesizestr == "false" || freesizestr == "0") freesizecap = 0;
|
||||
else if (freesizestr == "relative" || freesizestr == "2") freesizecap = 2;
|
||||
else freesizecap = 1;
|
||||
convertimg = section->Get_bool("convertdrivefat");
|
||||
wpcolon = section->Get_bool("leading colon write protect image");
|
||||
lockmount = section->Get_bool("locking disk image mount");
|
||||
|
||||
// CGA/EGA/VGA-specific
|
||||
extern unsigned char vga_p3da_undefined_bits;
|
||||
vga_p3da_undefined_bits = (unsigned char)static_cast<Section_prop *>(control->GetSection("video"))->Get_hex("vga 3da undefined bits");
|
||||
@ -1791,6 +1792,10 @@ void DOSBOX_SetupConfigSections(void) {
|
||||
"If set to \"fixed\" (=\"false\"), the value of MOUNT -freesize will be a fixed one to be reported all the time.");
|
||||
Pstring->SetBasic(true);
|
||||
|
||||
Pbool = secprop->Add_bool("convertdrivefat",Property::Changeable::WhenIdle,true);
|
||||
Pbool->Set_help("If set, DOSBox-X will auto-convert mounted non-FAT drives (such as local drives) to FAT format for use with guest systems.");
|
||||
Pbool->SetBasic(true);
|
||||
|
||||
Pbool = secprop->Add_bool("leading colon write protect image",Property::Changeable::WhenIdle,true);
|
||||
Pbool->Set_help("If set, BOOT and IMGMOUNT commands will put an image file name with a leading colon (:) in write-protect mode.");
|
||||
|
||||
@ -4100,6 +4105,9 @@ void DOSBOX_SetupConfigSections(void) {
|
||||
"Set this option to true to prevent SCANDISK.EXE from attempting scan and repair drive Z:\n"
|
||||
"which is impossible since Z: is a virtual drive not backed by a disk filesystem.");
|
||||
|
||||
Pbool = secprop->Add_bool("drive z convert fat",Property::Changeable::WhenIdle,false);
|
||||
Pbool->Set_help("If set, DOSBox-X will automatically convert the Z drive into disk image as well when \"convertdrivefat\" is set.");
|
||||
|
||||
Pbool = secprop->Add_bool("drive z expand path",Property::Changeable::WhenIdle,true);
|
||||
Pbool->Set_help("If set, DOSBox-X will automatically expand the %PATH% environment variable to include the subdirectories on the Z drive.");
|
||||
|
||||
|
@ -73,7 +73,7 @@ bool tonoime = false, enableime = false;
|
||||
bool usesystemcursor = false, rtl = false, selmark = false;
|
||||
bool mountfro[26], mountiro[26];
|
||||
bool OpenGL_using(void), Direct3D_using(void);
|
||||
void DOSBox_SetSysMenu(void), GFX_OpenGLRedrawScreen(void), InitFontHandle(void), DOSV_FillScreen(void), SetWindowTransparency(int trans);
|
||||
void DOSBox_SetSysMenu(void), GFX_OpenGLRedrawScreen(void), InitFontHandle(void), DOSV_FillScreen(void), Add_VFiles(bool usecp), SetWindowTransparency(int trans);
|
||||
void MenuBrowseProgramFile(void), OutputSettingMenuUpdate(void), aspect_ratio_menu(void), update_pc98_clock_pit_menu(void), AllocCallback1(void), AllocCallback2(void), ToggleMenu(bool pressed);
|
||||
int Reflect_Menu(void);
|
||||
|
||||
@ -9190,12 +9190,14 @@ fresh_boot:
|
||||
Voodoo_Output_Enable(false);
|
||||
|
||||
grGlideShutdown();
|
||||
|
||||
/* shutdown DOSBox-X's virtual drive Z */
|
||||
VFILE_Shutdown();
|
||||
|
||||
/* shutdown the programs */
|
||||
PROGRAMS_Shutdown(); /* FIXME: Is this safe? Or will this cause use-after-free bug? */
|
||||
|
||||
Add_VFiles(false);
|
||||
|
||||
/* remove environment variables for some components */
|
||||
DOS_UninstallMisc();
|
||||
SBLASTER_DOS_Shutdown();
|
||||
|
@ -34,9 +34,850 @@
|
||||
#endif
|
||||
|
||||
extern int bootdrive;
|
||||
extern bool int13_disk_change_detect_enable;
|
||||
extern unsigned long freec;
|
||||
extern bool int13_disk_change_detect_enable, skipintprog, rsize;
|
||||
extern bool int13_extensions_enable, bootguest, bootvm, use_quick_reboot;
|
||||
|
||||
#define STATIC_ASSERTM(A,B) static_assertion_##A##_##B
|
||||
#define STATIC_ASSERTN(A,B) STATIC_ASSERTM(A,B)
|
||||
#define STATIC_ASSERT(cond) typedef char STATIC_ASSERTN(__LINE__,__COUNTER__)[(cond)?1:-1]
|
||||
|
||||
uint32_t DriveCalculateCRC32(const uint8_t *ptr, size_t len, uint32_t crc)
|
||||
{
|
||||
// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/
|
||||
static const uint32_t s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
|
||||
uint32_t crcu32 = (uint32_t)~crc;
|
||||
while (len--) { uint8_t b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; }
|
||||
return ~crcu32;
|
||||
}
|
||||
|
||||
void DriveFileIterator(DOS_Drive* drv, void(*func)(const char* path, bool is_dir, uint32_t size, uint16_t date, uint16_t time, uint8_t attr, Bitu data), Bitu data)
|
||||
{
|
||||
if (!drv) return;
|
||||
struct Iter
|
||||
{
|
||||
static void ParseDir(DOS_Drive* drv, const std::string& dir, std::vector<std::string>& dirs, void(*func)(const char* path, bool is_dir, uint32_t size, uint16_t date, uint16_t time, uint8_t attr, Bitu data), Bitu data)
|
||||
{
|
||||
size_t dirlen = dir.length();
|
||||
if (dirlen + DOS_NAMELENGTH >= DOS_PATHLENGTH) return;
|
||||
char full_path[DOS_PATHLENGTH+4];
|
||||
if (dirlen)
|
||||
{
|
||||
memcpy(full_path, &dir[0], dirlen);
|
||||
full_path[dirlen++] = '\\';
|
||||
}
|
||||
full_path[dirlen] = '\0';
|
||||
|
||||
RealPt save_dta = dos.dta();
|
||||
dos.dta(dos.tables.tempdta);
|
||||
DOS_DTA dta(dos.dta());
|
||||
dta.SetupSearch(255, (uint8_t)(0xffff & ~DOS_ATTR_VOLUME), (char*)"*.*");
|
||||
for (bool more = drv->FindFirst((char*)dir.c_str(), dta); more; more = drv->FindNext(dta))
|
||||
{
|
||||
char dta_name[DOS_NAMELENGTH_ASCII], lname[LFN_NAMELENGTH+1]; uint32_t dta_size; uint16_t dta_date, dta_time; uint8_t dta_attr;
|
||||
dta.GetResult(dta_name, lname, dta_size, dta_date, dta_time, dta_attr);
|
||||
strcpy(full_path + dirlen, dta_name);
|
||||
bool is_dir = !!(dta_attr & DOS_ATTR_DIRECTORY);
|
||||
//if (is_dir) printf("[%s] [%s] %s (size: %u - date: %u - time: %u - attr: %u)\n", (const char*)data, (dta_attr == 8 ? "V" : (is_dir ? "D" : "F")), full_path, dta_size, dta_date, dta_time, dta_attr);
|
||||
if (dta_name[0] == '.' && dta_name[dta_name[1] == '.' ? 2 : 1] == '\0') continue;
|
||||
if (is_dir) dirs.emplace_back(full_path);
|
||||
func(full_path, is_dir, dta_size, dta_date, dta_time, dta_attr, data);
|
||||
}
|
||||
dos.dta(save_dta);
|
||||
}
|
||||
};
|
||||
std::vector<std::string> dirs;
|
||||
dirs.emplace_back("");
|
||||
std::string dir;
|
||||
while (dirs.size())
|
||||
{
|
||||
std::swap(dirs.back(), dir);
|
||||
dirs.pop_back();
|
||||
Iter::ParseDir(drv, dir.c_str(), dirs, func, data);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TVal> struct StringToPointerHashMap
|
||||
{
|
||||
StringToPointerHashMap() : len(0), maxlen(0), keys(NULL), vals(NULL) { }
|
||||
~StringToPointerHashMap() { free(keys); free(vals); }
|
||||
|
||||
static uint32_t Hash(const char* str, uint32_t str_limit = 0xFFFF, uint32_t hash_init = (uint32_t)0x811c9dc5)
|
||||
{
|
||||
for (const char* e = str + str_limit; *str && str != e;)
|
||||
hash_init = ((hash_init * (uint32_t)0x01000193) ^ (uint32_t)*(str++));
|
||||
return hash_init;
|
||||
}
|
||||
|
||||
TVal* Get(const char* str, uint32_t str_limit = 0xFFFF, uint32_t hash_init = (uint32_t)0x811c9dc5) const
|
||||
{
|
||||
if (len == 0) return NULL;
|
||||
for (uint32_t key0 = Hash(str, str_limit, hash_init), key = (key0 ? key0 : 1), i = key;; i++)
|
||||
{
|
||||
if (keys[i &= maxlen] == key) return vals[i];
|
||||
if (!keys[i]) return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Put(const char* str, TVal* val, uint32_t str_limit = 0xFFFF, uint32_t hash_init = (uint32_t)0x811c9dc5)
|
||||
{
|
||||
if (len * 2 >= maxlen) Grow();
|
||||
for (uint32_t key0 = Hash(str, str_limit, hash_init), key = (key0 ? key0 : 1), i = key;; i++)
|
||||
{
|
||||
if (!keys[i &= maxlen]) { len++; keys[i] = key; vals[i] = val; return; }
|
||||
if (keys[i] == key) { vals[i] = val; return; }
|
||||
}
|
||||
}
|
||||
|
||||
bool Remove(const char* str, uint32_t str_limit = 0xFFFF, uint32_t hash_init = (uint32_t)0x811c9dc5)
|
||||
{
|
||||
if (len == 0) return false;
|
||||
for (uint32_t key0 = Hash(str, str_limit, hash_init), key = (key0 ? key0 : 1), i = key;; i++)
|
||||
{
|
||||
if (keys[i &= maxlen] == key)
|
||||
{
|
||||
keys[i] = 0;
|
||||
len--;
|
||||
while ((key = keys[i = (i + 1) & maxlen]) != 0)
|
||||
{
|
||||
for (uint32_t j = key;; j++)
|
||||
{
|
||||
if (keys[j &= maxlen] == key) break;
|
||||
if (!keys[j]) { keys[i] = 0; keys[j] = key; vals[j] = vals[i]; break; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!keys[i]) return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Clear() { memset(keys, len = 0, (maxlen + 1) * sizeof(uint32_t)); }
|
||||
|
||||
uint32_t Len() const { return len; }
|
||||
uint32_t Capacity() const { return (maxlen ? maxlen + 1 : 0); }
|
||||
TVal* GetAtIndex(uint32_t idx) const { return (keys[idx] ? vals[idx] : NULL); }
|
||||
|
||||
struct Iterator
|
||||
{
|
||||
Iterator(StringToPointerHashMap<TVal>& _map, uint32_t _index) : map(_map), index(_index - 1) { this->operator++(); }
|
||||
StringToPointerHashMap<TVal>& map;
|
||||
uint32_t index;
|
||||
TVal* operator *() const { return map.vals[index]; }
|
||||
bool operator ==(const Iterator &other) const { return index == other.index; }
|
||||
bool operator !=(const Iterator &other) const { return index != other.index; }
|
||||
Iterator& operator ++()
|
||||
{
|
||||
if (!map.maxlen) { index = 0; return *this; }
|
||||
if (++index > map.maxlen) index = map.maxlen + 1;
|
||||
while (index <= map.maxlen && !map.keys[index]) index++;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
Iterator begin() { return Iterator(*this, 0); }
|
||||
Iterator end() { return Iterator(*this, (maxlen ? maxlen + 1 : 0)); }
|
||||
|
||||
private:
|
||||
uint32_t len, maxlen, *keys;
|
||||
TVal** vals;
|
||||
|
||||
void Grow()
|
||||
{
|
||||
uint32_t oldMax = maxlen, oldCap = (maxlen ? oldMax + 1 : 0), *oldKeys = keys;
|
||||
TVal **oldVals = vals;
|
||||
maxlen = (maxlen ? maxlen * 2 + 1 : 15);
|
||||
keys = (uint32_t*)calloc(maxlen + 1, sizeof(uint32_t));
|
||||
vals = (TVal**)malloc((maxlen + 1) * sizeof(TVal*));
|
||||
for (uint32_t i = 0; i != oldCap; i++)
|
||||
{
|
||||
if (!oldKeys[i]) continue;
|
||||
for (uint32_t key = oldKeys[i], j = key;; j++)
|
||||
{
|
||||
if (!keys[j &= maxlen]) { keys[j] = key; vals[j] = oldVals[i]; break; }
|
||||
}
|
||||
}
|
||||
free(oldKeys);
|
||||
free(oldVals);
|
||||
}
|
||||
|
||||
// not copyable
|
||||
StringToPointerHashMap(const StringToPointerHashMap&);
|
||||
StringToPointerHashMap& operator=(const StringToPointerHashMap&);
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack (1)
|
||||
#endif
|
||||
struct bootstrap {
|
||||
uint8_t nearjmp[3];
|
||||
uint8_t oemname[8];
|
||||
uint8_t bytespersector[2];
|
||||
uint8_t sectorspercluster;
|
||||
uint16_t reservedsectors;
|
||||
uint8_t fatcopies;
|
||||
uint16_t rootdirentries;
|
||||
uint16_t totalsectorcount;
|
||||
uint8_t mediadescriptor;
|
||||
uint16_t sectorsperfat;
|
||||
uint16_t sectorspertrack;
|
||||
uint16_t headcount;
|
||||
uint32_t hiddensectorcount;
|
||||
uint32_t totalsecdword;
|
||||
uint8_t bootcode[474];
|
||||
uint8_t magic1; /* 0x55 */
|
||||
uint8_t magic2; /* 0xaa */
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
|
||||
struct lfndirentry {
|
||||
uint8_t ord;
|
||||
uint8_t name1[10];
|
||||
uint8_t attrib;
|
||||
uint8_t type;
|
||||
uint8_t chksum;
|
||||
uint8_t name2[12];
|
||||
uint16_t loFirstClust;
|
||||
uint8_t name3[4];
|
||||
char* Name(int j) { return (char*)(j < 5 ? name1 + j*2 : j < 11 ? name2 + (j-5)*2 : name3 + (j-11)*2); }
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack ()
|
||||
#endif
|
||||
STATIC_ASSERT(sizeof(direntry) == sizeof(lfndirentry));
|
||||
enum
|
||||
{
|
||||
DOS_ATTR_LONG_NAME = (DOS_ATTR_READ_ONLY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM | DOS_ATTR_VOLUME),
|
||||
DOS_ATTR_LONG_NAME_MASK = (DOS_ATTR_READ_ONLY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM | DOS_ATTR_VOLUME | DOS_ATTR_DIRECTORY | DOS_ATTR_ARCHIVE),
|
||||
DOS_ATTR_PENDING_SHORT_NAME = 0x80,
|
||||
};
|
||||
|
||||
struct fatFromDOSDrive
|
||||
{
|
||||
DOS_Drive* drive;
|
||||
|
||||
enum ffddDefs : uint32_t
|
||||
{
|
||||
BYTESPERSECTOR = 512,
|
||||
HEADCOUNT = 240, // needs to be >128 to fit 4GB into CHS
|
||||
SECTORSPERTRACK = 63,
|
||||
SECT_MBR = 0,
|
||||
SECT_BOOT = 32,
|
||||
CACHECOUNT = 256,
|
||||
KEEPOPENCOUNT = 8,
|
||||
NULL_CURSOR = (uint32_t)-1,
|
||||
};
|
||||
|
||||
partTable mbr;
|
||||
bootstrap bootsec;
|
||||
uint8_t fsinfosec[BYTESPERSECTOR];
|
||||
uint32_t sectorsPerCluster;
|
||||
bool isFAT32, readOnly, tomany = false;
|
||||
|
||||
struct ffddFile { char path[DOS_PATHLENGTH+1]; uint32_t firstSect; };
|
||||
std::vector<direntry> root, dirs;
|
||||
std::vector<ffddFile> files;
|
||||
std::vector<uint32_t> fileAtSector;
|
||||
std::vector<uint8_t> fat;
|
||||
uint32_t sect_disk_end, sect_files_end, sect_files_start, sect_dirs_start, sect_root_start, sect_fat2_start, sect_fat1_start;
|
||||
|
||||
struct ffddBuf { uint8_t data[BYTESPERSECTOR]; };
|
||||
struct ffddSec { uint32_t cursor = NULL_CURSOR; };
|
||||
std::vector<ffddBuf> diffSectorBufs;
|
||||
std::vector<ffddSec> diffSectors;
|
||||
std::vector<uint32_t> diffFreeCursors;
|
||||
std::string savePath;
|
||||
FILE* saveFile = NULL;
|
||||
uint32_t saveEndCursor = 0;
|
||||
uint8_t cacheSectorData[CACHECOUNT][BYTESPERSECTOR];
|
||||
uint32_t cacheSectorNumber[CACHECOUNT];
|
||||
DOS_File* openFiles[KEEPOPENCOUNT];
|
||||
uint32_t openIndex[KEEPOPENCOUNT];
|
||||
uint32_t openCursor = 0;
|
||||
|
||||
~fatFromDOSDrive()
|
||||
{
|
||||
if (saveFile)
|
||||
fclose(saveFile);
|
||||
for (DOS_File* df : openFiles)
|
||||
if (df) { df->Close(); delete df; }
|
||||
}
|
||||
|
||||
fatFromDOSDrive(DOS_Drive* drv) : drive(drv)
|
||||
{
|
||||
cacheSectorNumber[0] = 1; // must not state that sector 0 is already cached
|
||||
memset(&cacheSectorNumber[1], 0, sizeof(cacheSectorNumber) - sizeof(cacheSectorNumber[0]));
|
||||
memset(openFiles, 0, sizeof(openFiles));
|
||||
|
||||
struct Iter
|
||||
{
|
||||
static void SetFAT(fatFromDOSDrive& ffdd, size_t idx, uint32_t val)
|
||||
{
|
||||
while (idx >= ffdd.fat.size() / (ffdd.isFAT32 ? 4 : 2))
|
||||
{
|
||||
ffdd.fat.resize(ffdd.fat.size() + BYTESPERSECTOR);
|
||||
memset(&ffdd.fat[ffdd.fat.size() - BYTESPERSECTOR], 0, BYTESPERSECTOR);
|
||||
}
|
||||
if (ffdd.isFAT32)
|
||||
var_write((uint32_t * const)&ffdd.fat[idx * 4], (const uint32_t)val);
|
||||
else
|
||||
var_write((uint16_t * const)&ffdd.fat[idx * 2], (const uint16_t)val);
|
||||
}
|
||||
|
||||
static direntry* AddDirEntry(fatFromDOSDrive& ffdd, bool useFAT16Root, size_t& diridx)
|
||||
{
|
||||
const uint32_t entriesPerCluster = ffdd.sectorsPerCluster * BYTESPERSECTOR / sizeof(direntry);
|
||||
if (!useFAT16Root && (diridx % entriesPerCluster) == 0)
|
||||
{
|
||||
// link fat (was set to 0xFFFF before but now we knew the chain continues)
|
||||
if (diridx) SetFAT(ffdd, 2 + (diridx - 1) / entriesPerCluster, (uint32_t)(2 + ffdd.dirs.size() / entriesPerCluster));
|
||||
diridx = ffdd.dirs.size();
|
||||
ffdd.dirs.resize(diridx + entriesPerCluster);
|
||||
memset(&ffdd.dirs[diridx], 0, sizeof(direntry) * entriesPerCluster);
|
||||
SetFAT(ffdd, 2 + diridx / entriesPerCluster, (uint32_t)0xFFFFFFFF); // set as last cluster in chain for now
|
||||
}
|
||||
else if (useFAT16Root && diridx && (diridx % 512) == 0)
|
||||
{
|
||||
// this actually should never be larger than 512 for some FAT16 drivers
|
||||
ffdd.root.resize(diridx + 512);
|
||||
memset(&ffdd.root[diridx], 0, sizeof(direntry) * 512);
|
||||
}
|
||||
return &(!useFAT16Root ? ffdd.dirs : ffdd.root)[diridx++];
|
||||
}
|
||||
|
||||
static void ParseDir(fatFromDOSDrive& ffdd, char* dir, const StringToPointerHashMap<void>* filter, int dirlen = 0, uint16_t parentFirstCluster = 0)
|
||||
{
|
||||
if (ffdd.tomany) return;
|
||||
const bool useFAT16Root = (!dirlen && !ffdd.isFAT32), readOnly = ffdd.readOnly;
|
||||
const size_t firstidx = (!useFAT16Root ? ffdd.dirs.size() : 0);
|
||||
const uint32_t sectorsPerCluster = ffdd.sectorsPerCluster, bytesPerCluster = sectorsPerCluster * BYTESPERSECTOR, entriesPerCluster = bytesPerCluster / sizeof(direntry);
|
||||
const uint16_t myFirstCluster = (dirlen ? (uint16_t)(2 + firstidx / entriesPerCluster) : (uint16_t)0) ;
|
||||
|
||||
char finddir[DOS_PATHLENGTH+4];
|
||||
memcpy(finddir, dir, dirlen); // because FindFirst can modify this...
|
||||
finddir[dirlen] = '\0';
|
||||
if (dirlen) dir[dirlen++] = '\\';
|
||||
|
||||
size_t diridx = 0;
|
||||
RealPt save_dta = dos.dta();
|
||||
dos.dta(dos.tables.tempdta);
|
||||
DOS_DTA dta(dos.dta());
|
||||
dta.SetupSearch(255, 0xFF, (char*)"*.*");
|
||||
skipintprog = true;
|
||||
for (bool more = ffdd.drive->FindFirst(finddir, dta); more; more = ffdd.drive->FindNext(dta))
|
||||
{
|
||||
char dta_name[DOS_NAMELENGTH_ASCII], lname[LFN_NAMELENGTH+1]; uint32_t dta_size; uint16_t dta_date, dta_time; uint8_t dta_attr;
|
||||
dta.GetResult(dta_name, lname, dta_size, dta_date, dta_time, dta_attr);
|
||||
//LOG_MSG("dta_name %s lname %s\n", dta_name, lname);
|
||||
const char *fend = dta_name + strlen(dta_name);
|
||||
const bool dot = (dta_name[0] == '.' && dta_name[1] == '\0'), dotdot = (dta_name[0] == '.' && dta_name[1] == '.' && dta_name[2] == '\0');
|
||||
if (!dirlen && (dot || dotdot)) continue; // root shouldn't have dot entries (yet localDrive does...)
|
||||
|
||||
ffddFile f;
|
||||
memcpy(f.path, dir, dirlen);
|
||||
memcpy(f.path + dirlen, dta_name, fend - dta_name + 1);
|
||||
if (filter && filter->Get(f.path)) continue;
|
||||
|
||||
const bool isLongFileName = (!dot && !dotdot && !(dta_attr & DOS_ATTR_VOLUME));
|
||||
if (isLongFileName)
|
||||
{
|
||||
size_t lfnlen = strlen(lname);
|
||||
const char *lfn_end = lname + lfnlen;
|
||||
for (size_t i = 0, lfnblocks = (lfnlen + 12) / 13; i != lfnblocks; i++)
|
||||
{
|
||||
lfndirentry* le = (lfndirentry*)AddDirEntry(ffdd, useFAT16Root, diridx);
|
||||
le->ord = (uint8_t)((lfnblocks - i)|(i == 0 ? 0x40 : 0x0));
|
||||
le->attrib = DOS_ATTR_LONG_NAME;
|
||||
le->type = 0;
|
||||
le->loFirstClust = 0;
|
||||
const char* plfn = lname + (lfnblocks - i - 1) * 13;
|
||||
for (int j = 0; j != 13; j++, plfn++)
|
||||
{
|
||||
char* p = le->Name(j);
|
||||
if (plfn > lfn_end) { p[0] = p[1] = (char)0xFF; }
|
||||
else if (plfn == lfn_end) { p[0] = p[1] = 0; }
|
||||
else { p[0] = *plfn; p[1] = 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *fext = (dot || dotdot ? NULL : strrchr(dta_name, '.'));
|
||||
direntry* e = AddDirEntry(ffdd, useFAT16Root, diridx);
|
||||
memset(e->entryname, ' ', sizeof(e->entryname));
|
||||
memcpy(e->entryname, dta_name, (fext ? fext : fend) - dta_name);
|
||||
if (fext++) memcpy(e->entryname + 8, fext, fend - fext);
|
||||
|
||||
e->attrib = dta_attr | (readOnly ? DOS_ATTR_READ_ONLY : 0) | (isLongFileName ? DOS_ATTR_PENDING_SHORT_NAME : 0);
|
||||
if (dos.version.major >= 7) {
|
||||
var_write(&e->crtTime, dta_time); // create date/time is DOS 7.0 and up only
|
||||
var_write(&e->crtDate, dta_date); // create date/time is DOS 7.0 and up only
|
||||
}
|
||||
var_write(&e->accessDate, dta_date);
|
||||
var_write(&e->modTime, dta_time);
|
||||
var_write(&e->modDate, dta_date);
|
||||
|
||||
if (dot)
|
||||
{
|
||||
e->attrib |= DOS_ATTR_DIRECTORY; // make sure
|
||||
var_write(&e->loFirstClust, myFirstCluster);
|
||||
}
|
||||
else if (dotdot)
|
||||
{
|
||||
e->attrib |= DOS_ATTR_DIRECTORY; // make sure
|
||||
var_write(&e->loFirstClust, parentFirstCluster);
|
||||
}
|
||||
else if (dta_attr & DOS_ATTR_VOLUME)
|
||||
{
|
||||
if ((dirlen || (e->attrib & DOS_ATTR_DIRECTORY) || dta_size)) {
|
||||
if (!strcmp(trim((char *)e->entryname), "DOSBOX-X")) continue;
|
||||
LOG_MSG("Invalid volume entry - %s\n", e->entryname);
|
||||
}
|
||||
}
|
||||
else if (!(dta_attr & DOS_ATTR_DIRECTORY))
|
||||
{
|
||||
var_write(&e->entrysize, dta_size);
|
||||
|
||||
uint32_t fileIdx = (uint32_t)ffdd.files.size();
|
||||
ffdd.files.push_back(f);
|
||||
|
||||
uint32_t numSects = (dta_size + bytesPerCluster - 1) / bytesPerCluster * sectorsPerCluster;
|
||||
try {
|
||||
ffdd.fileAtSector.resize(ffdd.fileAtSector.size() + numSects, fileIdx);
|
||||
} catch (...) {
|
||||
LOG_MSG("Too many sectors needed, will discard remaining files (from %s)", lname);
|
||||
ffdd.tomany = ffdd.readOnly = true;
|
||||
var_write((uint32_t *const)&ffdd.fsinfosec[488], (const uint32_t)0x0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
skipintprog = false;
|
||||
dos.dta(save_dta);
|
||||
if (dirlen && diridx < firstidx + 2) {
|
||||
LOG_MSG("Directory need at least . and .. entries - %s\n", finddir);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now fill out the subdirectories (can't be done above because only one dos.dta can run simultaneously
|
||||
std::vector<direntry>& entries = (!useFAT16Root ? ffdd.dirs : ffdd.root);
|
||||
for (size_t ei = firstidx; ei != diridx; ei++)
|
||||
{
|
||||
direntry& e = entries[ei];
|
||||
uint8_t* entryname = e.entryname;
|
||||
int totlen = dirlen;
|
||||
if (e.attrib & DOS_ATTR_DIRECTORY) // copy name before modifying SFN
|
||||
{
|
||||
if (entryname[0] == '.' && entryname[entryname[1] == '.' ? 2 : 1] == ' ') continue;
|
||||
for (int i = 0; i != 8 && entryname[i] != ' '; i++) dir[totlen++] = entryname[i];
|
||||
if (entryname[8] != ' ') dir[totlen++] = '.';
|
||||
for (int i = 8; i != 11 && entryname[i] != ' '; i++) dir[totlen++] = entryname[i];
|
||||
}
|
||||
if (e.attrib & DOS_ATTR_PENDING_SHORT_NAME) // convert LFN to SFN
|
||||
{
|
||||
memset(entryname, ' ', sizeof(e.entryname));
|
||||
int ni = 0, niext = 0, lossy = 0;
|
||||
for (lfndirentry* le = (lfndirentry*)&e; le-- == (lfndirentry*)&e || !(le[1].ord & 0x40);)
|
||||
{
|
||||
for (int j = 0; j != 13; j++)
|
||||
{
|
||||
char c = *le->Name(j);
|
||||
if (c == '\0') { lossy |= (niext && ni - niext > 3); break; }
|
||||
if (c == '.') { if (ni > 8) { memset(entryname+8, ' ', 3); ni = 8; } if (!ni || niext) { lossy = 1; } niext = ni; continue; }
|
||||
if (c == ' ' || ni == 11 || (ni == 8 && !niext)) { lossy = 1; continue; }
|
||||
if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) { }
|
||||
else if (c >= 'a' && c <= 'z') { c ^= 0x20; }
|
||||
else if (strchr("$%'-_@~`!(){}^#&", c)) { }
|
||||
else { lossy = 1; c = '_'; }
|
||||
entryname[ni++] = (uint8_t)c;
|
||||
}
|
||||
}
|
||||
|
||||
if (niext && niext != 8)
|
||||
for (int i = 2; i >= 0; i--)
|
||||
entryname[8+i] = entryname[niext+i], entryname[niext+i] = ' ';
|
||||
if (niext && niext <= 4 && ni - niext > 3)
|
||||
for (int i = niext + 3; i != 8; i++)
|
||||
entryname[i] = ' ';
|
||||
|
||||
if (lossy)
|
||||
{
|
||||
if (!niext) niext = ni;
|
||||
for (int i = 1; i <= 999999; i++)
|
||||
{
|
||||
int taillen = (i<=9?2:i<=99?3:i<=999?4:i<=9999?5:i<=99999?6:7);
|
||||
char* ptr = (char*)&entryname[niext + taillen > 8 ? 8 : niext + taillen];
|
||||
for (int j = i; j; j /= 10) *--ptr = '0'+(j%10);
|
||||
*--ptr = '~';
|
||||
|
||||
bool conflict = false;
|
||||
for (size_t e2 = firstidx; e2 != diridx; e2++)
|
||||
if (!(entries[e2].attrib & (DOS_ATTR_VOLUME|DOS_ATTR_PENDING_SHORT_NAME)) && !memcmp(entryname, entries[e2].entryname, sizeof(e.entryname)))
|
||||
{ conflict = true; break; }
|
||||
if (!conflict) break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t chksum = 0;
|
||||
for (int i = 0; i != 11;) chksum = (chksum >> 1) + (chksum << 7) + entryname[i++];
|
||||
for (lfndirentry* le = (lfndirentry*)&e; le-- == (lfndirentry*)&e || !(le[1].ord & 0x40);) le->chksum = chksum;
|
||||
e.attrib &= ~DOS_ATTR_PENDING_SHORT_NAME;
|
||||
}
|
||||
if (e.attrib & DOS_ATTR_DIRECTORY) // this reallocates ffdd.dirs so do this last
|
||||
{
|
||||
var_write(&e.loFirstClust, (const uint16_t)(2 + ffdd.dirs.size() / entriesPerCluster));
|
||||
ParseDir(ffdd, dir, filter, totlen, myFirstCluster);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SumInfo { uint64_t used_bytes; const StringToPointerHashMap<void>* filter; };
|
||||
static void SumFileSize(const char* path, bool is_dir, uint32_t size, uint16_t, uint16_t, uint8_t, Bitu data)
|
||||
{
|
||||
if (!((SumInfo*)data)->filter || !((SumInfo*)data)->filter->Get(path))
|
||||
((SumInfo*)data)->used_bytes += (size + (32*1024-1)) / (32*1024) * (32*1024); // count as 32 kb clusters
|
||||
}
|
||||
};
|
||||
|
||||
Iter::SumInfo sum = { 0, NULL };
|
||||
Bitu freeSpace = 0, freeSpaceMB = 0;
|
||||
uint32_t free_clusters = 0;
|
||||
uint16_t drv_bytes_sector; uint8_t drv_sectors_cluster; uint16_t drv_total_clusters, drv_free_clusters;
|
||||
rsize=true;
|
||||
freec=0;
|
||||
drv->AllocationInfo(&drv_bytes_sector, &drv_sectors_cluster, &drv_total_clusters, &drv_free_clusters);
|
||||
free_clusters = freec?freec:drv_free_clusters;
|
||||
freeSpace = (Bitu)drv_bytes_sector * (Bitu)drv_sectors_cluster * (Bitu)(freec?freec:free_clusters);
|
||||
freeSpaceMB = freeSpace / (1024*1024);
|
||||
rsize=false;
|
||||
DriveFileIterator(drv, Iter::SumFileSize, (Bitu)&sum);
|
||||
readOnly = (free_clusters == 0);
|
||||
tomany = false;
|
||||
|
||||
const uint32_t addFreeMB = (readOnly ? 0 : freeSpaceMB), totalMB = (uint32_t)(sum.used_bytes / (1024*1024)) + addFreeMB + 1;
|
||||
if (totalMB >= 3072) { isFAT32 = true; sectorsPerCluster = 64; } // 32 kb clusters ( 98304 ~ FAT entries)
|
||||
else if (totalMB >= 2048) { isFAT32 = true; sectorsPerCluster = 32; } // 16 kb clusters (131072 ~ 196608 FAT entries)
|
||||
else if (totalMB >= 384) { isFAT32 = false; sectorsPerCluster = 64; } // 32 kb clusters ( 12288 ~ 65504 FAT entries)
|
||||
else if (totalMB >= 192) { isFAT32 = false; sectorsPerCluster = 32; } // 16 kb clusters ( 12288 ~ 24576 FAT entries)
|
||||
else if (totalMB >= 96) { isFAT32 = false; sectorsPerCluster = 16; } // 8 kb clusters ( 12288 ~ 24576 FAT entries)
|
||||
else if (totalMB >= 48) { isFAT32 = false; sectorsPerCluster = 8; } // 4 kb clusters ( 12288 ~ 24576 FAT entries)
|
||||
else if (totalMB >= 8) { isFAT32 = false; sectorsPerCluster = 4; } // 4 kb clusters ( 4096 ~ 24576 FAT entries)
|
||||
else { isFAT32 = false; sectorsPerCluster = 1; } // 2 kb clusters ( ~ 16383 FAT entries)
|
||||
|
||||
// mediadescriptor in very first byte of FAT table
|
||||
Iter::SetFAT(*this, 0, (uint32_t)0xFFFFFF8);
|
||||
Iter::SetFAT(*this, 1, (uint32_t)0xFFFFFFF);
|
||||
|
||||
if (!isFAT32)
|
||||
{
|
||||
// this actually should never be anything but 512 for some FAT16 drivers
|
||||
root.resize(512);
|
||||
memset(&root[0], 0, sizeof(direntry) * 512);
|
||||
}
|
||||
|
||||
char dirbuf[DOS_PATHLENGTH+4];
|
||||
Iter::ParseDir(*this, dirbuf, NULL);
|
||||
|
||||
const uint32_t bytesPerCluster = sectorsPerCluster * BYTESPERSECTOR;
|
||||
const uint32_t entriesPerCluster = bytesPerCluster / sizeof(direntry);
|
||||
uint32_t fileCluster = (uint32_t)(2 + dirs.size() / entriesPerCluster);
|
||||
for (uint32_t fileSect = 0, rootOrDir = 0; rootOrDir != 2; rootOrDir++)
|
||||
{
|
||||
for (direntry& e : (rootOrDir ? dirs : root))
|
||||
{
|
||||
if (!e.entrysize || (e.attrib & DOS_ATTR_LONG_NAME_MASK) == DOS_ATTR_LONG_NAME) continue;
|
||||
var_write(&e.hiFirstClust, (const uint16_t)(fileCluster >> 16));
|
||||
var_write(&e.loFirstClust, (const uint16_t)(fileCluster));
|
||||
|
||||
// Write FAT link chain
|
||||
uint32_t numClusters = (var_read(&e.entrysize) + bytesPerCluster - 1) / bytesPerCluster;
|
||||
for (uint32_t i = fileCluster, iEnd = i + numClusters - 1; i != iEnd; i++) Iter::SetFAT(*this, i, i + 1);
|
||||
Iter::SetFAT(*this, fileCluster + numClusters - 1, (uint32_t)0xFFFFFFF);
|
||||
|
||||
files[fileAtSector[fileSect]].firstSect = fileSect;
|
||||
|
||||
fileCluster += numClusters;
|
||||
fileSect += numClusters * sectorsPerCluster;
|
||||
}
|
||||
}
|
||||
|
||||
// Add at least one page after the last file or FAT spec minimume to make ScanDisk happy (even on read-only disks)
|
||||
const uint32_t FATWidth = (isFAT32 ? 4 : 2), FATPageClusters = BYTESPERSECTOR / FATWidth, FATMinCluster = (isFAT32 ? 65525 : 4085) + FATPageClusters;
|
||||
const uint32_t addFreeClusters = ((addFreeMB * (1024*1024/BYTESPERSECTOR)) + sectorsPerCluster - 1) / sectorsPerCluster;
|
||||
const uint32_t targetClusters = fileCluster + (addFreeClusters < FATPageClusters ? FATPageClusters : addFreeClusters);
|
||||
Iter::SetFAT(*this, (targetClusters < FATMinCluster ? FATMinCluster : targetClusters) - 1, 0);
|
||||
const uint32_t totalClusters = (uint32_t)(fat.size() / FATWidth); // as set by Iter::SetFAT
|
||||
|
||||
// on read-only disks, fill up the end of the FAT table with "Bad sector in cluster or reserved cluster" markers
|
||||
if (readOnly)
|
||||
for (uint32_t cluster = fileCluster; cluster != totalClusters; cluster++)
|
||||
Iter::SetFAT(*this, cluster, 0xFFFFFF7);
|
||||
|
||||
const uint32_t sectorsPerFat = (uint32_t)(fat.size() / BYTESPERSECTOR);
|
||||
const uint16_t reservedSectors = (isFAT32 ? 32 : 1);
|
||||
const uint32_t partSize = totalClusters * sectorsPerCluster + reservedSectors;
|
||||
sect_fat1_start = SECT_BOOT + reservedSectors;
|
||||
sect_fat2_start = sect_fat1_start + sectorsPerFat;
|
||||
sect_root_start = sect_fat2_start + sectorsPerFat;
|
||||
sect_dirs_start = sect_root_start + ((root.size() * sizeof(direntry) + BYTESPERSECTOR - 1) / BYTESPERSECTOR);
|
||||
sect_files_start = sect_dirs_start + ((dirs.size() * sizeof(direntry) + BYTESPERSECTOR - 1) / BYTESPERSECTOR);
|
||||
sect_files_end = sect_files_start + fileAtSector.size();
|
||||
sect_disk_end = SECT_BOOT + partSize;
|
||||
assert(sect_disk_end >= sect_files_end);
|
||||
|
||||
for (ffddFile& f : files)
|
||||
f.firstSect += sect_files_start;
|
||||
|
||||
uint32_t serial = 0;
|
||||
if (!serial)
|
||||
{
|
||||
serial = DriveCalculateCRC32(&fat[0], fat.size(), 0);
|
||||
if (root.size()) serial = DriveCalculateCRC32((uint8_t*)&root[0], root.size() * sizeof(direntry), serial);
|
||||
if (dirs.size()) serial = DriveCalculateCRC32((uint8_t*)&dirs[0], dirs.size() * sizeof(direntry), serial);
|
||||
}
|
||||
|
||||
memset(&mbr, 0, sizeof(mbr));
|
||||
var_write((uint32_t *)&mbr.booter[440], serial); //4 byte disk serial number
|
||||
var_write(&mbr.pentry[0].bootflag, 0x80); //Active bootable
|
||||
if ((sect_disk_end - 1) / (HEADCOUNT * SECTORSPERTRACK) > 0x3FF)
|
||||
{
|
||||
mbr.pentry[0].beginchs[0] = mbr.pentry[0].beginchs[1] = mbr.pentry[0].beginchs[2] = 0;
|
||||
mbr.pentry[0].endchs[0] = mbr.pentry[0].endchs[1] = mbr.pentry[0].endchs[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
chs_write(mbr.pentry[0].beginchs, SECT_BOOT);
|
||||
chs_write(mbr.pentry[0].endchs, sect_disk_end - 1);
|
||||
}
|
||||
var_write(&mbr.pentry[0].absSectStart, SECT_BOOT);
|
||||
var_write(&mbr.pentry[0].partSize, partSize);
|
||||
mbr.magic1 = 0x55; mbr.magic2 = 0xaa;
|
||||
|
||||
memset(&bootsec, 0, sizeof(bootsec));
|
||||
memcpy(bootsec.nearjmp, "\xEB\x3C\x90", sizeof(bootsec.nearjmp));
|
||||
memcpy(bootsec.oemname, "MSWIN4.1", sizeof(bootsec.oemname));
|
||||
var_write((uint16_t *const)&bootsec.bytespersector, (const uint16_t)BYTESPERSECTOR);
|
||||
var_write(&bootsec.sectorspercluster, sectorsPerCluster);
|
||||
var_write(&bootsec.reservedsectors, reservedSectors);
|
||||
var_write(&bootsec.fatcopies, 2);
|
||||
var_write(&bootsec.totalsectorcount, 0); // 16 bit field is 0, actual value is in totalsecdword
|
||||
var_write(&bootsec.mediadescriptor, 0xF8); //also in FAT[0]
|
||||
var_write(&bootsec.sectorspertrack, SECTORSPERTRACK);
|
||||
var_write(&bootsec.headcount, HEADCOUNT);
|
||||
var_write(&bootsec.hiddensectorcount, SECT_BOOT);
|
||||
var_write(&bootsec.totalsecdword, partSize);
|
||||
bootsec.magic1 = 0x55; bootsec.magic2 = 0xaa;
|
||||
if (!isFAT32) // FAT16
|
||||
{
|
||||
var_write(&mbr.pentry[0].parttype, 0x04); //FAT16
|
||||
var_write((uint16_t *const)&bootsec.rootdirentries, (const uint16_t)root.size());
|
||||
var_write((uint16_t *const)&bootsec.sectorsperfat, (const uint16_t)sectorsPerFat);
|
||||
bootsec.bootcode[0] = 0x80; //Physical drive (harddisk) flag
|
||||
bootsec.bootcode[2] = 0x29; //Extended boot signature
|
||||
var_write((uint32_t *const)&bootsec.bootcode[3], (const uint32_t)(serial + 1)); //4 byte partition serial number
|
||||
memcpy(&bootsec.bootcode[7], "NO NAME ", 11); // volume label
|
||||
memcpy(&bootsec.bootcode[18], "FAT16 ", 8); // file system string name
|
||||
}
|
||||
else // FAT32
|
||||
{
|
||||
var_write(&mbr.pentry[0].parttype, 0x0C); //FAT32
|
||||
var_write((uint32_t *const)&bootsec.bootcode[0], sectorsPerFat);
|
||||
var_write((uint32_t *const)&bootsec.bootcode[8], (const uint32_t)2); // First cluster number of the root directory
|
||||
var_write((uint16_t *const)&bootsec.bootcode[12], (const uint16_t)1); // Sector of FSInfo structure in offset from top of the FAT32 volume
|
||||
var_write((uint16_t *const)&bootsec.bootcode[14], (const uint16_t)6); // Sector of backup boot sector in offset from top of the FAT32 volume
|
||||
bootsec.bootcode[28] = 0x80; //Physical drive (harddisk) flag
|
||||
bootsec.bootcode[30] = 0x29; //Extended boot signature
|
||||
var_write((uint32_t *const)&bootsec.bootcode[31], (const uint32_t)(serial + 1)); //4 byte partition serial number
|
||||
memcpy(&bootsec.bootcode[35], "NO NAME ", 11); // volume label
|
||||
memcpy(&bootsec.bootcode[46], "FAT32 ", 8); // file system string name
|
||||
|
||||
memset(fsinfosec, 0, sizeof(fsinfosec));
|
||||
var_write((uint32_t *const)&fsinfosec[0], (const uint32_t)0x41615252); //lead signature
|
||||
var_write((uint32_t *const)&fsinfosec[484], (const uint32_t)0x61417272); //Another signature
|
||||
Bitu freeclusters = (Bitu)freeSpace / (BYTESPERSECTOR * sectorsPerCluster);
|
||||
var_write((uint32_t *const)&fsinfosec[488], (const uint32_t)(readOnly ? 0x0 : (freeclusters < 0xFFFFFFFF ? freeclusters : 0xFFFFFFFF))); //last known free cluster count (all FF is unknown)
|
||||
var_write((uint32_t *const)&fsinfosec[492], (const uint32_t)0xFFFFFFFF); //the cluster number at which the driver should start looking for free clusters (all FF is unknown)
|
||||
var_write((uint32_t *const)&fsinfosec[508], (const uint32_t)0xAA550000); //ending signature
|
||||
}
|
||||
}
|
||||
|
||||
static void chs_write(uint8_t* chs, uint32_t lba)
|
||||
{
|
||||
uint32_t cylinder = lba / (HEADCOUNT * SECTORSPERTRACK);
|
||||
uint32_t head = (lba / SECTORSPERTRACK) % HEADCOUNT;
|
||||
uint32_t sector = (lba % SECTORSPERTRACK) + 1;
|
||||
if (head > 0xFF || sector > 0x3F || cylinder > 0x3FF)
|
||||
LOG_MSG("Warning: Invalid CHS data - %X, %X, %X\n", head, sector, cylinder);
|
||||
chs[0] = (uint8_t)(head & 0xFF);
|
||||
chs[1] = (uint8_t)((sector & 0x3F) | ((cylinder >> 8) & 0x3));
|
||||
chs[2] = (uint8_t)(cylinder & 0xFF);
|
||||
}
|
||||
|
||||
uint8_t WriteSector(uint32_t sectnum, const void* data)
|
||||
{
|
||||
if (sectnum >= sect_disk_end) return 1;
|
||||
if (sectnum == SECT_MBR)
|
||||
{
|
||||
// Windows 9x writes the disk timestamp into the booter area on startup.
|
||||
// Just copy that part over so it doesn't get treated as a difference that needs to be stored.
|
||||
memcpy(mbr.booter, data, sizeof(mbr.booter));
|
||||
}
|
||||
|
||||
if (readOnly) return 0; // just return without error to avoid bluescreens in Windows 9x
|
||||
|
||||
if (sectnum >= diffSectors.size()) diffSectors.resize(sectnum + 128);
|
||||
uint32_t *cursor_ptr = &diffSectors[sectnum].cursor, cursor_val = *cursor_ptr;
|
||||
|
||||
int is_different;
|
||||
uint8_t filebuf[BYTESPERSECTOR];
|
||||
void* unmodified = GetUnmodifiedSector(sectnum, filebuf);
|
||||
if (!unmodified)
|
||||
{
|
||||
is_different = false; // to be equal it must be filled with zeroes
|
||||
for (uint64_t* p = (uint64_t*)data, *pEnd = p + (BYTESPERSECTOR / sizeof(uint64_t)); p != pEnd; p++)
|
||||
if (*p) { is_different = true; break; }
|
||||
}
|
||||
else is_different = memcmp(unmodified, data, BYTESPERSECTOR);
|
||||
|
||||
if (is_different)
|
||||
{
|
||||
if (!saveFile && !savePath.empty())
|
||||
{
|
||||
saveFile = fopen(savePath.c_str(), "wb+");
|
||||
if (saveFile) { fwrite("FFDD\x1", 5, 1, saveFile); saveEndCursor = 5; };
|
||||
savePath.clear();
|
||||
}
|
||||
if (cursor_val == NULL_CURSOR && diffFreeCursors.size())
|
||||
{
|
||||
*cursor_ptr = cursor_val = diffFreeCursors.back();
|
||||
diffFreeCursors.pop_back();
|
||||
}
|
||||
if (saveFile)
|
||||
{
|
||||
if (cursor_val == NULL_CURSOR)
|
||||
{
|
||||
uint32_t sectnumval;
|
||||
var_write(§numval, sectnum);
|
||||
*cursor_ptr = cursor_val = saveEndCursor;
|
||||
saveEndCursor += sizeof(sectnumval) + BYTESPERSECTOR;
|
||||
fseeko64(saveFile, cursor_val, SEEK_SET);
|
||||
fwrite(§numval, sizeof(sectnumval), 1, saveFile);
|
||||
}
|
||||
else
|
||||
fseeko64(saveFile, cursor_val + sizeof(sectnum), SEEK_SET);
|
||||
fwrite(data, BYTESPERSECTOR, 1, saveFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cursor_val == NULL_CURSOR)
|
||||
{
|
||||
*cursor_ptr = cursor_val = (uint32_t)diffSectorBufs.size();
|
||||
diffSectorBufs.resize(cursor_val + 1);
|
||||
}
|
||||
memcpy(diffSectorBufs[cursor_val].data, data, BYTESPERSECTOR);
|
||||
}
|
||||
cacheSectorNumber[sectnum % CACHECOUNT] = (uint32_t)-1; // invalidate cache
|
||||
}
|
||||
else if (cursor_val != NULL_CURSOR)
|
||||
{
|
||||
if (saveFile)
|
||||
{
|
||||
// mark sector in diff file as free
|
||||
uint32_t sectnumval = 0xFFFFFFFF;
|
||||
fseeko64(saveFile, cursor_val, SEEK_SET);
|
||||
fwrite(§numval, sizeof(sectnumval), 1, saveFile);
|
||||
}
|
||||
diffFreeCursors.push_back(cursor_val);
|
||||
*cursor_ptr = NULL_CURSOR;
|
||||
cacheSectorNumber[sectnum % CACHECOUNT] = (uint32_t)-1; // invalidate cache
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* GetUnmodifiedSector(uint32_t sectnum, void* filebuf)
|
||||
{
|
||||
if (sectnum >= sect_files_end) {}
|
||||
else if (sectnum >= sect_files_start)
|
||||
{
|
||||
uint32_t idx = fileAtSector[sectnum - sect_files_start];
|
||||
ffddFile& f = files[idx];
|
||||
DOS_File* df = NULL;
|
||||
for (uint32_t i = 0; i != KEEPOPENCOUNT; i++)
|
||||
if (openIndex[i] == idx && openFiles[i])
|
||||
{ df = openFiles[i]; break; }
|
||||
if (!df)
|
||||
{
|
||||
openCursor = (openCursor + 1) % KEEPOPENCOUNT;
|
||||
DOS_File*& cachedf = openFiles[openCursor];
|
||||
if (cachedf)
|
||||
{
|
||||
cachedf->Close();
|
||||
delete cachedf;
|
||||
cachedf = NULL;
|
||||
}
|
||||
bool res = drive->FileOpen(&df, f.path, OPEN_READ) ;
|
||||
if (res)
|
||||
{
|
||||
df->AddRef();
|
||||
cachedf = df;
|
||||
openIndex[openCursor] = idx;
|
||||
}
|
||||
else return NULL;
|
||||
}
|
||||
if (df)
|
||||
{
|
||||
uint32_t pos = (sectnum - f.firstSect) * BYTESPERSECTOR;
|
||||
uint16_t read = (uint16_t)BYTESPERSECTOR;
|
||||
df->Seek(&pos, DOS_SEEK_SET);
|
||||
if (!df->Read((uint8_t*)filebuf, &read)) { read = 0; assert(0); }
|
||||
if (read != BYTESPERSECTOR)
|
||||
memset((uint8_t*)filebuf + read, 0, BYTESPERSECTOR - read);
|
||||
return filebuf;
|
||||
}
|
||||
}
|
||||
else if (sectnum >= sect_dirs_start) return &dirs[(sectnum - sect_dirs_start) * (BYTESPERSECTOR / sizeof(direntry))];
|
||||
else if (sectnum >= sect_root_start) return &root[(sectnum - sect_root_start) * (BYTESPERSECTOR / sizeof(direntry))];
|
||||
else if (sectnum >= sect_fat2_start) return &fat[(sectnum - sect_fat2_start) * BYTESPERSECTOR];
|
||||
else if (sectnum >= sect_fat1_start) return &fat[(sectnum - sect_fat1_start) * BYTESPERSECTOR];
|
||||
else if (sectnum == SECT_BOOT) return &bootsec;
|
||||
else if (sectnum == SECT_MBR) return &mbr;
|
||||
else if (sectnum == SECT_BOOT+1) return fsinfosec;
|
||||
else if (sectnum == SECT_BOOT+2) return fsinfosec; // additional boot loader code (anything is ok for us but needs 0x55AA footer signature)
|
||||
else if (sectnum == SECT_BOOT+6) return &bootsec; // boot sector copy
|
||||
else if (sectnum == SECT_BOOT+7) return fsinfosec; // boot sector copy
|
||||
else if (sectnum == SECT_BOOT+8) return fsinfosec; // boot sector copy
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t ReadSector(uint32_t sectnum, void* data)
|
||||
{
|
||||
uint32_t sectorHash = sectnum % CACHECOUNT;
|
||||
void *cachedata = cacheSectorData[sectorHash];
|
||||
if (cacheSectorNumber[sectorHash] == sectnum)
|
||||
{
|
||||
memcpy(data, cachedata, BYTESPERSECTOR);
|
||||
return 0;
|
||||
}
|
||||
cacheSectorNumber[sectorHash] = sectnum;
|
||||
|
||||
void *src;
|
||||
uint32_t cursor = (sectnum >= diffSectors.size() ? NULL_CURSOR : diffSectors[sectnum].cursor);
|
||||
if (cursor != NULL_CURSOR)
|
||||
{
|
||||
if (saveFile)
|
||||
{
|
||||
fseeko64(saveFile, cursor + sizeof(sectnum), SEEK_SET);
|
||||
src = (fread(cachedata, BYTESPERSECTOR, 1, saveFile) ? cachedata : NULL);
|
||||
}
|
||||
else src = diffSectorBufs[cursor].data;
|
||||
}
|
||||
else src = GetUnmodifiedSector(sectnum, cachedata);
|
||||
|
||||
if (src) memcpy(data, src, BYTESPERSECTOR);
|
||||
else memset(data, 0, BYTESPERSECTOR);
|
||||
if (src != cachedata) memcpy(cachedata, data, BYTESPERSECTOR);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
diskGeo DiskGeometryList[] = {
|
||||
{ 160, 8, 1, 40, 0, 512, 64, 1, 0xFE}, // IBM PC double density 5.25" single-sided 160KB
|
||||
{ 180, 9, 1, 40, 0, 512, 64, 2, 0xFC}, // IBM PC double density 5.25" single-sided 180KB
|
||||
@ -91,7 +932,7 @@ void FreeBIOSDiskList() {
|
||||
for (int i=0;i < MAX_DISK_IMAGES;i++) {
|
||||
if (imageDiskList[i] != NULL) {
|
||||
if (i >= 2) IDE_Hard_Disk_Detach(i);
|
||||
imageDiskList[i]->Release();
|
||||
if (!imageDiskList[i]->ffdd) imageDiskList[i]->Release();
|
||||
imageDiskList[i] = NULL;
|
||||
}
|
||||
}
|
||||
@ -269,6 +1110,8 @@ uint8_t imageDisk::Read_Sector(uint32_t head,uint32_t cylinder,uint32_t sector,v
|
||||
}
|
||||
|
||||
uint8_t imageDisk::Read_AbsoluteSector(uint32_t sectnum, void * data) {
|
||||
if (ffdd) return ffdd->ReadSector(sectnum, data);
|
||||
|
||||
uint64_t bytenum,res;
|
||||
int got;
|
||||
|
||||
@ -314,6 +1157,8 @@ uint8_t imageDisk::Write_Sector(uint32_t head,uint32_t cylinder,uint32_t sector,
|
||||
|
||||
|
||||
uint8_t imageDisk::Write_AbsoluteSector(uint32_t sectnum, const void *data) {
|
||||
if (ffdd) return ffdd->WriteSector(sectnum, data);
|
||||
|
||||
uint64_t bytenum;
|
||||
|
||||
bytenum = (uint64_t)sectnum * sector_size;
|
||||
@ -346,7 +1191,8 @@ uint32_t imageDisk::Get_Reserved_Cylinders() {
|
||||
imageDisk::imageDisk(IMAGE_TYPE class_id) : class_id(class_id) {
|
||||
}
|
||||
|
||||
imageDisk::imageDisk(FILE* diskimg, const char* diskName, uint32_t cylinders, uint32_t heads, uint32_t sectors, uint32_t sector_size, bool hardDrive) {
|
||||
imageDisk::imageDisk(FILE* diskimg, const char* diskName, uint32_t cylinders, uint32_t heads, uint32_t sectors, uint32_t sector_size, bool hardDrive) : ffdd(NULL)
|
||||
{
|
||||
if (diskName) this->diskname = diskName;
|
||||
this->cylinders = cylinders;
|
||||
this->heads = heads;
|
||||
@ -642,6 +1488,50 @@ imageDisk::imageDisk(FILE* imgFile, const char* imgName, uint32_t imgSizeK, bool
|
||||
}
|
||||
}
|
||||
|
||||
imageDisk::imageDisk(class DOS_Drive *useDrive)
|
||||
{
|
||||
ffdd = new fatFromDOSDrive(useDrive);
|
||||
diskimg = NULL;
|
||||
diskname[0] = '\0';
|
||||
hardDrive = true;
|
||||
Set_GeometryForHardDisk();
|
||||
}
|
||||
|
||||
imageDisk::~imageDisk()
|
||||
{
|
||||
if(diskimg != NULL) {
|
||||
fclose(diskimg);
|
||||
diskimg=NULL;
|
||||
}
|
||||
if (ffdd)
|
||||
delete ffdd;
|
||||
}
|
||||
|
||||
void imageDisk::Set_GeometryForHardDisk()
|
||||
{
|
||||
sector_size = 512;
|
||||
partTable mbrData;
|
||||
for (int m = (Read_AbsoluteSector(0, &mbrData) ? 0 : 4); m--;)
|
||||
{
|
||||
if(!mbrData.pentry[m].partSize) continue;
|
||||
bootstrap bootbuffer;
|
||||
if (Read_AbsoluteSector(mbrData.pentry[m].absSectStart, &bootbuffer)) continue;
|
||||
bootbuffer.sectorspertrack = var_read(&bootbuffer.sectorspertrack);
|
||||
bootbuffer.headcount = var_read(&bootbuffer.headcount);
|
||||
uint32_t setSect = bootbuffer.sectorspertrack;
|
||||
uint32_t setHeads = bootbuffer.headcount;
|
||||
uint32_t setCyl = (mbrData.pentry[m].absSectStart + mbrData.pentry[m].partSize) / (setSect * setHeads);
|
||||
Set_Geometry(setHeads, setCyl, setSect, 512);
|
||||
return;
|
||||
}
|
||||
if (!diskimg) return;
|
||||
uint32_t diskimgsize;
|
||||
fseek(diskimg,0,SEEK_END);
|
||||
diskimgsize = (uint32_t)ftell(diskimg);
|
||||
fseek(diskimg,current_fpos,SEEK_SET);
|
||||
Set_Geometry(16, (uint32_t)(diskimgsize / (512 * 63 * 16)), 63, 512);
|
||||
}
|
||||
|
||||
void imageDisk::Set_Geometry(uint32_t setHeads, uint32_t setCyl, uint32_t setSect, uint32_t setSectSize) {
|
||||
Bitu bigdisk_shift = 0;
|
||||
|
||||
|
@ -57,7 +57,7 @@ extern const char *modifier;
|
||||
extern unsigned int sendkeymap;
|
||||
extern std::string langname, configfile, dosbox_title;
|
||||
extern int autofixwarn, enablelfn, fat32setver, paste_speed, wheel_key, freesizecap, wpType, wpVersion, wpBG, wpFG, lastset, blinkCursor;
|
||||
extern bool dos_kernel_disabled, force_nocachedir, wpcolon, lockmount, enable_config_as_shell_commands, lesssize, load, winrun, winautorun, startcmd, startwait, startquiet, starttranspath, mountwarning, wheel_guest, clipboard_dosapi, noremark_save_state, force_load_state, sync_time, manualtime, ttfswitch, loadlang, showbold, showital, showline, showsout, char512, printfont, rtl, gbk, chinasea, uao, showdbcs, dbcs_sbcs, autoboxdraw, halfwidthkana, ticksLocked, outcon, enable_dbcs_tables, show_recorded_filename;
|
||||
extern bool dos_kernel_disabled, force_nocachedir, wpcolon, convertimg, lockmount, enable_config_as_shell_commands, lesssize, load, winrun, winautorun, startcmd, startwait, startquiet, starttranspath, mountwarning, wheel_guest, clipboard_dosapi, noremark_save_state, force_load_state, sync_time, manualtime, ttfswitch, loadlang, showbold, showital, showline, showsout, char512, printfont, rtl, gbk, chinasea, uao, showdbcs, dbcs_sbcs, autoboxdraw, halfwidthkana, ticksLocked, outcon, enable_dbcs_tables, show_recorded_filename, internal_program;
|
||||
|
||||
/* This registers a file on the virtual drive and creates the correct structure for it*/
|
||||
|
||||
@ -136,7 +136,9 @@ void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main,const char *
|
||||
ipe->comsize = size;
|
||||
ipe->comdata = comdata;
|
||||
internal_progs.push_back(ipe);
|
||||
internal_program = true;
|
||||
VFILE_Register(name,ipe->comdata,ipe->comsize,dir);
|
||||
internal_program = false;
|
||||
}
|
||||
|
||||
static Bitu PROGRAMS_Handler(void) {
|
||||
@ -641,6 +643,7 @@ void ApplySetting(std::string pvar, std::string inputline, bool quiet) {
|
||||
if (freesizestr == "fixed" || freesizestr == "false" || freesizestr == "0") freesizecap = 0;
|
||||
else if (freesizestr == "relative" || freesizestr == "2") freesizecap = 2;
|
||||
else freesizecap = 1;
|
||||
convertimg = section->Get_bool("convertdrivefat");
|
||||
wpcolon = section->Get_bool("leading colon write protect image");
|
||||
lockmount = section->Get_bool("locking disk image mount");
|
||||
if (!strcasecmp(inputline.substr(0, 9).c_str(), "saveslot=")) SetGameState_Run(section->Get_int("saveslot")-1);
|
||||
|
@ -50,9 +50,9 @@
|
||||
#endif
|
||||
#include "build_timestamp.h"
|
||||
|
||||
extern bool startcmd, startwait, startquiet, winautorun;
|
||||
extern bool dos_shell_running_program, mountwarning, winautorun;
|
||||
extern bool startcmd, startwait, startquiet, internal_program;
|
||||
extern bool halfwidthkana, force_conversion, showdbcs;
|
||||
extern bool dos_shell_running_program, mountwarning;
|
||||
extern bool addovl, addipx, addne2k, enableime, gbk;
|
||||
extern const char* RunningProgram;
|
||||
extern int enablelfn, msgcodepage;
|
||||
@ -212,7 +212,11 @@ void AutoexecObject::CreateAutoexec(void) {
|
||||
}
|
||||
sprintf((autoexec_data + auto_len),"%s\r\n",linecopy.c_str());
|
||||
}
|
||||
if (first_shell) VFILE_Register("AUTOEXEC.BAT",(uint8_t *)autoexec_data,(uint32_t)strlen(autoexec_data));
|
||||
if (first_shell) {
|
||||
internal_program = true;
|
||||
VFILE_Register("AUTOEXEC.BAT",(uint8_t *)autoexec_data,(uint32_t)strlen(autoexec_data));
|
||||
internal_program = false;
|
||||
}
|
||||
}
|
||||
|
||||
void AutoexecObject::Uninstall() {
|
||||
@ -854,7 +858,9 @@ void DOS_Shell::Prepare(void) {
|
||||
strcat(config_data, section->Get_string("rem"));
|
||||
strcat(config_data, "\r\n");
|
||||
}
|
||||
internal_program = true;
|
||||
VFILE_Register("CONFIG.SYS",(uint8_t *)config_data,(uint32_t)strlen(config_data));
|
||||
internal_program = false;
|
||||
#if defined(WIN32)
|
||||
if (!control->opt_securemode&&!control->SecureMode())
|
||||
{
|
||||
|
@ -1534,8 +1534,8 @@ char *FormatTime(Bitu hour, Bitu min, Bitu sec, Bitu msec) {
|
||||
return retBuf;
|
||||
}
|
||||
|
||||
|
||||
uint32_t byte_count,file_count,dir_count;
|
||||
uint64_t byte_count;
|
||||
uint32_t file_count,dir_count;
|
||||
Bitu p_count;
|
||||
std::vector<std::string> dirs, adirs;
|
||||
static bool dirPaused(DOS_Shell * shell, Bitu w_size, bool optP, bool optW, bool show=true) {
|
||||
@ -1581,7 +1581,8 @@ static bool doDir(DOS_Shell * shell, char * args, DOS_DTA dta, char * numformat,
|
||||
}
|
||||
if (*(sargs+strlen(sargs)-1) != '\\') strcat(sargs,"\\");
|
||||
|
||||
uint32_t cbyte_count=0,cfile_count=0,w_count=0;
|
||||
uint64_t cbyte_count=0;
|
||||
uint32_t cfile_count=0,w_count=0;
|
||||
int fbak=lfn_filefind_handle;
|
||||
lfn_filefind_handle=uselfn&&!optZ?LFN_FILEFIND_INTERNAL:LFN_FILEFIND_NONE;
|
||||
bool ret=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME), found=true, first=true;
|
||||
@ -2064,7 +2065,7 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
if ((dos.version.major > 7 || (dos.version.major == 7 && dos.version.minor >= 10)) &&
|
||||
Drives[drive]->AllocationInfo32(&bytes_sector32,§ors_cluster32,&total_clusters32,&free_clusters32)) { /* FAT32 aware extended API */
|
||||
freec=0;
|
||||
free_space=(Bitu)bytes_sector32 * (Bitu)sectors_cluster32 * (Bitu)(freec?freec:free_clusters32);
|
||||
free_space=(Bitu)bytes_sector32 * (Bitu)sectors_cluster32 * (Bitu)free_clusters32;
|
||||
} else {
|
||||
uint16_t bytes_sector;uint8_t sectors_cluster;uint16_t total_clusters;uint16_t free_clusters;
|
||||
rsize=true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user