diff --git a/CHANGELOG b/CHANGELOG index 9bed10550..1665b9ad2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,16 +6,21 @@ [dosbox] section) is added to toggle this setting, or you can toggle via BOOT command's -convertfat (or -convertfatro option for read-only access) and - -noconvertfat options. There is also a config - option "drive z convert fat" (in [dos] section) to - control whether to convert virtual drive Z:. Much - of the code is imported from DOSBox Pure. (Wengier) - - Added code pages 856 (Hebrew) and 859 (Latin 9) for - the guest-to-host code page conversions. (Wengier) + -noconvertfat options. There're also config options + "convert fat free space" (in [dosbox] section) and + "drive z convert fat" (in [dos] section) to control + free space (in MB; 0 means read-only) and whether + to also convert virtual drive Z:. Much of the code + is imported from DOSBox Pure. (Wengier) + - Added menu option "Save to disk image" (under drive + letter in "Drive" menu) to save a mounted non-FAT + drive to selected disk image. (Wengier) - Added the "Limit disk transfer speed" menu group (under "DOS") to toggle the hard & floppy disk data rate function. Also moved "Quick launch program..." menu from "DOS" menu to "Main" menu. (Wengier) + - Added code pages 856 (Hebrew) and 859 (Latin 9) for + the guest-to-host code page conversions. (Wengier) - Added config option to allow create of temporary devices for piping operations when a temporary DOS path is not available. (Wengier) @@ -25,14 +30,18 @@ ATAPI read errors. (schellingb) - You can use CONFIG -set langcp=... to change the current language along with the embedded code page, - or CHCP nnn:... to specify a language file as well. - Also improved -langcp option for SBCS code pages, - and the Windows installer will also set keyboard - layouts for the selected languages. (Wengier) + or CHCP nnn:... to specify a language file as well, + e.g. "CHCP 932:" or "CHCP 932:ja_JP" for Japanese + code page and language file. Also improved -langcp + option for SBCS code pages, and Windows installer + will additionally set keyboard layouts for the + selected languages. (Wengier) - Changed menu option "Restart DOSBox-X with language file..." to "Load language file..." for loading language files without rebooting DOSBox-X, unless a guest system is currently running. (Wengier) + - Imported the more recent MBR code from FreeDOS to + avoid the "boot menu" as in older code. (Wengier) - When changing TTF font, DOSBox-X will try to show the number of missing characters in the new TTF font (if any). (Wengier) diff --git a/contrib/linux/com.dosbox_x.DOSBox-X.metainfo.xml.in b/contrib/linux/com.dosbox_x.DOSBox-X.metainfo.xml.in index f19fc5a82..76bd47ddd 100644 --- a/contrib/linux/com.dosbox_x.DOSBox-X.metainfo.xml.in +++ b/contrib/linux/com.dosbox_x.DOSBox-X.metainfo.xml.in @@ -10,7 +10,7 @@ Emulation - + diff --git a/contrib/windows/installer/dosbox-x.reference.setup.conf b/contrib/windows/installer/dosbox-x.reference.setup.conf index f8b704d46..6b0e40d08 100644 --- a/contrib/windows/installer/dosbox-x.reference.setup.conf +++ b/contrib/windows/installer/dosbox-x.reference.setup.conf @@ -397,6 +397,8 @@ debuggerrun = debugger # 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:# convert fat free space: If set, automatically converted FAT images will have the specified free space (in MB) if less than the actual free space. +#DOSBOX-X-ADV:# If set to 0, the converted disk will be read-only; if set to -1, the actual free space will be used for the converted disk. #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. @@ -432,7 +434,7 @@ debuggerrun = debugger #DOSBOX-X-ADV:# enable pci bus: Enable PCI bus emulation #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:# -> 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 +#DOSBOX-X-ADV-SEE:# -> 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; convert fat free space; 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 #DOSBOX-X-ADV-SEE:# language = title = @@ -497,6 +499,7 @@ memsize = 16 nocachedir = false freesizecap = cap convertdrivefat = true +#DOSBOX-X-ADV:convert fat free space = 250 #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 diff --git a/dosbox-x.reference.conf b/dosbox-x.reference.conf index 250ec1114..15b9ebaaa 100644 --- a/dosbox-x.reference.conf +++ b/dosbox-x.reference.conf @@ -195,7 +195,7 @@ debuggerrun = debugger # 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 +# -> 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; convert fat free space; 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 # language = title = diff --git a/dosbox-x.reference.full.conf b/dosbox-x.reference.full.conf index 845f73f5d..1d9e7ec90 100644 --- a/dosbox-x.reference.full.conf +++ b/dosbox-x.reference.full.conf @@ -389,6 +389,8 @@ debuggerrun = debugger # 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. +# convert fat free space: If set, automatically converted FAT images will have the specified free space (in MB) if less than the actual free space. +# If set to 0, the converted disk will be read-only; if set to -1, the actual free space will be used for the converted disk. # 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. @@ -485,6 +487,7 @@ memalias = 0 nocachedir = false freesizecap = cap convertdrivefat = true +convert fat free space = 250 leading colon write protect image = true locking disk image mount = true unmask keyboard on int 16 read = true diff --git a/include/bios_disk.h b/include/bios_disk.h index 8250d589f..a208db5d5 100644 --- a/include/bios_disk.h +++ b/include/bios_disk.h @@ -65,12 +65,13 @@ 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, bool readonly); + imageDisk(class DOS_Drive *useDrive, unsigned int letter, int freeMB); 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(); void Set_GeometryForHardDisk(); struct fatFromDOSDrive* ffdd = NULL; + unsigned int drvnum = DOS_DRIVES; IMAGE_TYPE class_id = ID_BASE; std::string diskname; diff --git a/include/build_timestamp.h b/include/build_timestamp.h index 687800532..967ac556a 100644 --- a/include/build_timestamp.h +++ b/include/build_timestamp.h @@ -1,4 +1,4 @@ /*auto-generated*/ -#define UPDATED_STR "Jul 11, 2022 6:20:51pm" -#define GIT_COMMIT_HASH "a4bdbf8" +#define UPDATED_STR "Jul 16, 2022 3:40:09pm" +#define GIT_COMMIT_HASH "0098fc4" #define COPYRIGHT_END_YEAR "2022" diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index 767b757e0..d2547a18b 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -4621,6 +4621,8 @@ void DOS_EnableDriveMenu(char drv) { name = std::string("drive_") + drv + "_bootimg"; mainMenu.get_item(name).enable(!dos_kernel_disabled).refresh_item(mainMenu); } + name = std::string("drive_") + drv + "_saveimg"; + mainMenu.get_item(name).enable(Drives[drv-'A'] != NULL && !dynamic_cast(Drives[drv-'A'])).refresh_item(mainMenu); } } diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 0b8fc14a9..27059fc8a 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -201,7 +201,7 @@ void DetachFromBios(imageDisk* image) { void SwitchLanguage(int oldcp, int newcp, bool confirm) { auto iterold = langcp_map.find(oldcp), iternew = langcp_map.find(newcp); std::string langold = iterold != langcp_map.end() ? iterold->second : "", langnew = iternew != langcp_map.end() ? iternew->second : ""; - if (loadlang && (oldcp == lastmsgcp || (oldcp == 951 && lastmsgcp == 950)) && oldcp != newcp && newcp == dos.loaded_codepage && langnew.size() && !(langold.size() && langold == langnew)) { + if (loadlang && (oldcp == lastmsgcp || (oldcp == 951 && lastmsgcp == 950) || (oldcp == 950 && lastmsgcp == 951) || !confirm) && oldcp != newcp && newcp == dos.loaded_codepage && langnew.size() && !(langold.size() && langold == langnew)) { FILE *file = testLoadLangFile(langnew.c_str()); if (file) { fclose(file); @@ -2538,6 +2538,7 @@ public: const uint8_t page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); if (!dos_kernel_disabled && (convimg == 1 || (convertimg && convimg == -1 && !IS_PC98_ARCH))) { // PC-98 image not supported yet unsigned int drv = 2, nextdrv = 2; + int freeMB = static_cast(control->GetSection("dosbox"))->Get_int("convert fat free space"); for (unsigned int d=2;d(Drives[drv]); - imageDisk *imagedrv = new imageDisk(Drives[drv], convertro || Drives[drv]->readonly || (od && od->ovlreadonly)); + imageDisk *imagedrv = new imageDisk(Drives[drv], drv, (convertro || Drives[drv]->readonly || (od && od->ovlreadonly)) ? 0 : freeMB); if (imagedrv && imagedrv->ffdd) { imageDiskList[nextdrv] = imagedrv; bool ide_slave = false; @@ -2997,39 +2998,39 @@ unsigned char this_is_not_a_bootable_partition[512] = { }; const uint8_t freedos_mbr[] = { - 0x33,0xC0,0x8E,0xC0,0x8E,0xD8,0x8E,0xD0,0xBC,0x00,0x7C,0xFC,0x8B,0xF4,0xBF,0x00, - 0x06,0xB9,0x00,0x01,0xF2,0xA5,0xEA,0x67,0x06,0x00,0x00,0x8B,0xD5,0x58,0xA2,0x4F, // 10h - 0x07,0x3C,0x35,0x74,0x23,0xB4,0x10,0xF6,0xE4,0x05,0xAE,0x04,0x8B,0xF0,0x80,0x7C, // 20h - 0x04,0x00,0x74,0x44,0x80,0x7C,0x04,0x05,0x74,0x3E,0xC6,0x04,0x80,0xE8,0xDA,0x00, - 0x8A,0x74,0x01,0x8B,0x4C,0x02,0xEB,0x08,0xE8,0xCF,0x00,0xB9,0x01,0x00,0x32,0xD1, // 40h - 0xBB,0x00,0x7C,0xB8,0x01,0x02,0xCD,0x13,0x72,0x1E,0x81,0xBF,0xFE,0x01,0x55,0xAA, - 0x75,0x16,0xEA,0x00,0x7C,0x00,0x00,0x80,0xFA,0x81,0x74,0x02,0xB2,0x80,0x8B,0xEA, - 0x42,0x80,0xF2,0xB3,0x88,0x16,0x41,0x07,0xBF,0xBE,0x07,0xB9,0x04,0x00,0xC6,0x06, - 0x34,0x07,0x31,0x32,0xF6,0x88,0x2D,0x8A,0x45,0x04,0x3C,0x00,0x74,0x23,0x3C,0x05, // 80h - 0x74,0x1F,0xFE,0xC6,0xBE,0x31,0x07,0xE8,0x71,0x00,0xBE,0x4F,0x07,0x46,0x46,0x8B, - 0x1C,0x0A,0xFF,0x74,0x05,0x32,0x7D,0x04,0x75,0xF3,0x8D,0xB7,0x7B,0x07,0xE8,0x5A, - 0x00,0x83,0xC7,0x10,0xFE,0x06,0x34,0x07,0xE2,0xCB,0x80,0x3E,0x75,0x04,0x02,0x74, - 0x0B,0xBE,0x42,0x07,0x0A,0xF6,0x75,0x0A,0xCD,0x18,0xEB,0xAC,0xBE,0x31,0x07,0xE8, - 0x39,0x00,0xE8,0x36,0x00,0x32,0xE4,0xCD,0x1A,0x8B,0xDA,0x83,0xC3,0x60,0xB4,0x01, - 0xCD,0x16,0xB4,0x00,0x75,0x0B,0xCD,0x1A,0x3B,0xD3,0x72,0xF2,0xA0,0x4F,0x07,0xEB, - 0x0A,0xCD,0x16,0x8A,0xC4,0x3C,0x1C,0x74,0xF3,0x04,0xF6,0x3C,0x31,0x72,0xD6,0x3C, - 0x35,0x77,0xD2,0x50,0xBE,0x2F,0x07,0xBB,0x1B,0x06,0x53,0xFC,0xAC,0x50,0x24,0x7F, //100h - 0xB4,0x0E,0xCD,0x10,0x58,0xA8,0x80,0x74,0xF2,0xC3,0x56,0xB8,0x01,0x03,0xBB,0x00, //110h - 0x06,0xB9,0x01,0x00,0x32,0xF6,0xCD,0x13,0x5E,0xC6,0x06,0x4F,0x07,0x3F,0xC3,0x0D, //120h - 0x8A,0x0D,0x0A,0x46,0x35,0x20,0x2E,0x20,0x2E,0x20,0x2E,0xA0,0x64,0x69,0x73,0x6B, - 0x20,0x32,0x0D,0x0A,0x0A,0x44,0x65,0x66,0x61,0x75,0x6C,0x74,0x3A,0x20,0x46,0x31, //140h - 0xA0,0x00,0x01,0x00,0x04,0x00,0x06,0x03,0x07,0x07,0x0A,0x0A,0x63,0x0E,0x64,0x0E, - 0x65,0x14,0x80,0x19,0x81,0x19,0x82,0x19,0x83,0x1E,0x93,0x24,0xA5,0x2B,0x9F,0x2F, - 0x75,0x33,0x52,0x33,0xDB,0x36,0x40,0x3B,0xF2,0x41,0x00,0x44,0x6F,0xF3,0x48,0x70, - 0x66,0xF3,0x4F,0x73,0xB2,0x55,0x6E,0x69,0xF8,0x4E,0x6F,0x76,0x65,0x6C,0xEC,0x4D, //180h - 0x69,0x6E,0x69,0xF8,0x4C,0x69,0x6E,0x75,0xF8,0x41,0x6D,0x6F,0x65,0x62,0xE1,0x46, - 0x72,0x65,0x65,0x42,0x53,0xC4,0x42,0x53,0x44,0xE9,0x50,0x63,0x69,0xF8,0x43,0x70, - 0xED,0x56,0x65,0x6E,0x69,0xF8,0x44,0x6F,0x73,0x73,0x65,0xE3,0x3F,0xBF,0x00,0x00, //1B0h + 0xFA,0xFC,0x31,0xC0,0x8E,0xD0,0x8E,0xD8,0xBD,0x00,0x7C,0x8D,0x66,0xE0,0xFB,0xB8, + 0xE0,0x1F,0x8E,0xC0,0x89,0xEE,0x89,0xEF,0xB9,0x00,0x01,0xF3,0xA5,0xEA,0x22,0x7C, // 10h + 0xE0,0x1F,0x8E,0xD8,0x8E,0xD0,0x31,0xC0,0x8E,0xC0,0x8D,0xBE,0xBE,0x01,0xF6,0x05, // 20h + 0x80,0x75,0x6D,0x83,0xC7,0x10,0x81,0xFF,0xFE,0x7D,0x72,0xF2,0xE8,0xC4,0x00,0x6E, + 0x6F,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x20,0x70,0x61,0x72,0x74,0x69,0x74,0x69, // 40h + 0x6F,0x6E,0x20,0x66,0x6F,0x75,0x6E,0x64,0x00,0xEB,0xFE,0xE8,0xA5,0x00,0x72,0x65, + 0x61,0x64,0x20,0x65,0x72,0x72,0x6F,0x72,0x20,0x77,0x68,0x69,0x6C,0x65,0x20,0x72, + 0x65,0x61,0x64,0x69,0x6E,0x67,0x20,0x64,0x72,0x69,0x76,0x65,0x00,0xEB,0xDA,0xE8, + 0x81,0x00,0x70,0x61,0x72,0x74,0x69,0x74,0x69,0x6F,0x6E,0x20,0x73,0x69,0x67,0x6E, // 80h + 0x61,0x74,0x75,0x72,0x65,0x20,0x21,0x3D,0x20,0x35,0x35,0x41,0x41,0x00,0xEB,0xB9, + 0xE8,0x10,0x00,0x72,0xB6,0x26,0x81,0x3E,0xFE,0x7D,0x55,0xAA,0x75,0xD1,0xEA,0x00, + 0x7C,0x00,0x00,0xBB,0xAA,0x55,0xB4,0x41,0xCD,0x13,0x72,0x32,0x81,0xFB,0x55,0xAA, + 0x75,0x2C,0xF6,0xC1,0x01,0x74,0x27,0xEB,0x10,0x10,0x00,0x04,0x00,0x00,0x7C,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x45,0x08,0xA3,0xD1,0x7C,0x8B, + 0x45,0x0A,0xA3,0xD3,0x7C,0xB8,0x00,0x42,0xBE,0xC9,0x7C,0xCD,0x13,0xC3,0xB8,0x04, + 0x02,0xBB,0x00,0x7C,0x8B,0x4D,0x02,0x8A,0x75,0x01,0xCD,0x13,0xC3,0x31,0xDB,0xB4, + 0x0E,0xCD,0x10,0x5E,0xAC,0x56,0x3C,0x00,0x75,0xF3,0xC3,0x00,0x00,0x00,0x00,0x00, //100h + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //110h + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //120h + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //140h + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //180h + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x73,0x73,0x65,0xE3,0x3F,0xBF,0x00,0x00, //1B0h 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xAA - }; +}; #ifdef WIN32 #include #endif @@ -6120,7 +6121,6 @@ private: heads = buf[0x1c3] + 1u; sectors = buf[0x1c4] & 0x3fu; } - (void)ptype;//GCC: Set but not used. Assume it will be used someday --J.C. if (pe1_size != 0) { uint32_t part_start = startsect + sectors * starthead + startcyl * sectors * heads; diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 38f1ac47b..3fc59a281 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -1794,6 +1794,10 @@ void DOSBOX_SetupConfigSections(void) { 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); + Pint = secprop->Add_int("convert fat free space", Property::Changeable::WhenIdle,250); + Pint->Set_help("If set, automatically converted FAT images will have the specified free space (in MB) if less than the actual free space.\n" + "If set to 0, the converted disk will be read-only; if set to -1, the actual free space will be used for the converted disk."); + 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."); diff --git a/src/gui/menu_callback.cpp b/src/gui/menu_callback.cpp index 1e56edde2..ad66874ec 100644 --- a/src/gui/menu_callback.cpp +++ b/src/gui/menu_callback.cpp @@ -449,6 +449,56 @@ bool drive_bootimg_menu_callback(DOSBoxMenu * const menu,DOSBoxMenu::item * cons return true; } +bool saveDiskImage(imageDisk *image, const char *name); +bool drive_saveimg_menu_callback(DOSBoxMenu * const menu,DOSBoxMenu::item * const menuitem) { + (void)menu;//UNUSED + (void)menuitem;//UNUSED + + int drive; + const char *mname = menuitem->get_name().c_str(); + if (!strncmp(mname,"drive_",6)) + drive = mname[6] - 'A'; + else + return false; + if (drive < 0 || drive>=DOS_DRIVES) return false; + if (!Drives[drive] || dynamic_cast(Drives[drive])) { + systemmessagebox("Error", "Drive does not exist or is mounted from disk image.", "ok","error", 1); + return false; + } + +#if !defined(HX_DOS) + char CurrentDir[512]; + char * Temp_CurrentDir = CurrentDir; + if(getcwd(Temp_CurrentDir, 512) == NULL) { + LOG(LOG_GUI, LOG_ERROR)("drive_saveimg_menu_callback failed to get the current working directory."); + return false; + } + std::string cwd = std::string(Temp_CurrentDir)+CROSS_FILESPLIT; + const char *lFilterPatterns[] = {"*.img","*.IMG"}; + const char *lFilterDescription = "Disk image (*.img)"; + char const * lTheSaveFileName = tinyfd_saveFileDialog("Save image file...","",2,lFilterPatterns,lFilterDescription); + if (lTheSaveFileName==NULL) return false; + + for (int i=0; iffdd && imageDiskList[i]->drvnum == drive) { + if (!saveDiskImage(imageDiskList[i], lTheSaveFileName)) systemmessagebox("Error", "Failed to save disk image.", "ok","error", 1); + chdir(Temp_CurrentDir); + return true; + } + int freeMB = static_cast(control->GetSection("dosbox"))->Get_int("convert fat free space"); + imageDisk *imagedrv = new imageDisk(Drives[drive], drive, freeMB); + if (!saveDiskImage(imagedrv, lTheSaveFileName)) systemmessagebox("Error", "Failed to save disk image.", "ok","error", 1); + if (imagedrv) delete imagedrv; + + if(chdir(Temp_CurrentDir) == -1) { + LOG(LOG_GUI, LOG_ERROR)("drive_saveimg_menu_callback failed to change directories."); + return false; + } +#endif + + return true; +} + bool drive_unmount_menu_callback(DOSBoxMenu * const menu,DOSBoxMenu::item * const menuitem) { (void)menu;//UNUSED (void)menuitem;//UNUSED @@ -587,6 +637,7 @@ const DOSBoxMenu::callback_t drive_callbacks[] = { NULL, drive_boot_menu_callback, drive_bootimg_menu_callback, + drive_saveimg_menu_callback, NULL }; @@ -705,6 +756,7 @@ const char *drive_opts[][2] = { { "div3", "--" }, { "boot", "Boot from drive" }, { "bootimg", "Boot from disk image" }, + { "saveimg", "Save to disk image" }, { NULL, NULL } }; @@ -2272,7 +2324,7 @@ bool save_logas_menu_callback(DOSBoxMenu * const menu,DOSBoxMenu::item * const m char CurrentDir[512]; char * Temp_CurrentDir = CurrentDir; if(getcwd(Temp_CurrentDir, 512) == NULL) { - LOG(LOG_GUI, LOG_ERROR)("Restart_config_file failed to get the current working directory."); + LOG(LOG_GUI, LOG_ERROR)("save_logas_menu_callback failed to get the current working directory."); return false; } std::string cwd = std::string(Temp_CurrentDir)+CROSS_FILESPLIT; diff --git a/src/gui/sdl_gui.cpp b/src/gui/sdl_gui.cpp index 4d96dc46d..e794f0948 100644 --- a/src/gui/sdl_gui.cpp +++ b/src/gui/sdl_gui.cpp @@ -2860,7 +2860,7 @@ public: temp="-force -t "+temp+" \""+std::string(lTheSaveFileName)+"\""; void runImgmake(const char *str); runImgmake(temp.c_str()); - if (!dos_kernel_disabled) { + if (!dos_kernel_disabled && strcmp(RunningProgram, "LOADLIN")) { DOS_Shell shell; shell.ShowPrompt(); } diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index f9e4c61a8..c5d5d04c4 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.cpp @@ -36,6 +36,7 @@ extern int bootdrive; extern unsigned long freec; +extern const uint8_t freedos_mbr[]; extern bool int13_disk_change_detect_enable, skipintprog, rsize, tryconvertcp; extern bool int13_extensions_enable, bootguest, bootvm, use_quick_reboot; extern bool isDBCSCP(), isKanji1_gbk(uint8_t chr), shiftjis_lead_byte(int c); @@ -255,6 +256,7 @@ struct lfndirentry { #ifdef _MSC_VER #pragma pack () #endif + STATIC_ASSERT(sizeof(direntry) == sizeof(lfndirentry)); enum { @@ -270,7 +272,7 @@ struct fatFromDOSDrive enum ffddDefs : uint32_t { BYTESPERSECTOR = 512, - HEADCOUNT = 240, // needs to be >128 to fit 4GB into CHS + HEADCOUNT = 255, // needs to be >128 to fit 4GB into CHS SECTORSPERTRACK = 63, SECT_MBR = 0, SECT_BOOT = 32, @@ -315,7 +317,7 @@ struct fatFromDOSDrive if (df) { df->Close(); delete df; } } - fatFromDOSDrive(DOS_Drive* drv, bool ro) : drive(drv) + fatFromDOSDrive(DOS_Drive* drv, int freeMB) : drive(drv) { cacheSectorNumber[0] = 1; // must not state that sector 0 is already cached memset(&cacheSectorNumber[1], 0, sizeof(cacheSectorNumber) - sizeof(cacheSectorNumber[0])); @@ -566,9 +568,10 @@ struct fatFromDOSDrive free_clusters = freec?freec:drv_free_clusters; freeSpace = (uint64_t)drv_bytes_sector * drv_sectors_cluster * (freec?freec:free_clusters); freeSpaceMB = freeSpace / (1024*1024); + if (freeMB > -1 && freeMB < freeSpaceMB) freeSpaceMB = freeMB; rsize=false; tomany=false; - readOnly = ro || free_clusters == 0; + readOnly = free_clusters == 0 || freeSpaceMB == 0; if (!DriveFileIterator(drv, Iter::SumFileSize, (Bitu)&sum)) return; const uint32_t addFreeMB = (readOnly ? 0 : freeSpaceMB), totalMB = (uint32_t)(sum.used_bytes / (1024*1024)) + (addFreeMB ? (1 + addFreeMB) : 0); @@ -657,6 +660,7 @@ struct fatFromDOSDrive } memset(&mbr, 0, sizeof(mbr)); + //memcpy(&mbr,freedos_mbr,512); 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) @@ -722,6 +726,7 @@ struct fatFromDOSDrive var_write((uint32_t *const)&fsinfosec[492], (const uint32_t)(ver71 ? (sect_files_end / sectorsPerCluster): 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 } + codepage = dos.loaded_codepage; tryconvcp = tryconvertcp; success = true; @@ -913,8 +918,30 @@ struct fatFromDOSDrive if (src != cachedata) memcpy(cachedata, data, BYTESPERSECTOR); return 0; } + + bool SaveImage(const char *name) + { + FILE* f = fopen_wrap(name, "wb"); + if (f) { + uint8_t filebuf[BYTESPERSECTOR]; + for (int i = 0; i < sect_disk_end; i++) { + ReadSector(i, filebuf); + if (fwrite(filebuf, 1, BYTESPERSECTOR, f) != BYTESPERSECTOR) { + fclose(f); + return false; + } + } + fclose(f); + return true; + } else + return false; + } }; +bool saveDiskImage(imageDisk *image, const char *name) { + return image && image->ffdd && image->ffdd->SaveImage(name); +} + 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 @@ -1525,15 +1552,16 @@ imageDisk::imageDisk(FILE* imgFile, const char* imgName, uint32_t imgSizeK, bool } } -imageDisk::imageDisk(class DOS_Drive *useDrive, bool readonly) +imageDisk::imageDisk(class DOS_Drive *useDrive, unsigned int letter, int freeMB) { - ffdd = new fatFromDOSDrive(useDrive, readonly); + ffdd = new fatFromDOSDrive(useDrive, freeMB); if (!ffdd->success) { LOG_MSG("FAT conversion failed"); delete ffdd; ffdd = NULL; return; } + drvnum = letter; diskimg = NULL; diskname[0] = '\0'; hardDrive = true; diff --git a/src/misc/messages.cpp b/src/misc/messages.cpp index e099f62a7..1a878e519 100644 --- a/src/misc/messages.cpp +++ b/src/misc/messages.cpp @@ -38,15 +38,16 @@ #endif using namespace std; -Bitu DOS_LoadKeyboardLayout(const char * layoutname, int32_t codepage, const char * codepagefile); -int msgcodepage = 0, lastmsgcp = 0, FileDirExistUTF8(std::string &localname, const char *name), toSetCodePage(DOS_Shell *shell, int newCP, int opt); -bool morelen = false, inmsg = false, loadlang = false, uselangcp = false, systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton), OpenGL_using(void); -bool isSupportedCP(int newCP), CodePageHostToGuestUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/), CodePageGuestToHostUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/); -void InitFontHandle(void), ShutFontHandle(void), SetIME(void), menu_update_dynamic(void), menu_update_autocycle(void), update_bindbutton_text(void), set_eventbutton_text(const char *eventname, const char *buttonname), JFONT_Init(), DOSBox_SetSysMenu(), UpdateSDLDrawTexture(), makestdcp950table(), makeseacp951table(); +int msgcodepage = 0, lastmsgcp = 0; +bool morelen = false, inmsg = false, loadlang = false, uselangcp = false; +bool isSupportedCP(int newCP), CodePageHostToGuestUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/), CodePageGuestToHostUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/), systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton), OpenGL_using(void); +void InitFontHandle(void), ShutFontHandle(void), SetIME(void), runRescan(const char *str), menu_update_dynamic(void), menu_update_autocycle(void), update_bindbutton_text(void), set_eventbutton_text(const char *eventname, const char *buttonname), JFONT_Init(), DOSBox_SetSysMenu(), UpdateSDLDrawTexture(), makestdcp950table(), makeseacp951table(); std::string langname = "", langnote = "", GetDOSBoxXPath(bool withexe=false); -extern int lastcp; -extern const char * RunningProgram; +extern Bitu DOS_LoadKeyboardLayout(const char * layoutname, int32_t codepage, const char * codepagefile); +extern int lastcp, FileDirExistUTF8(std::string &localname, const char *name), toSetCodePage(DOS_Shell *shell, int newCP, int opt); extern bool dos_kernel_disabled, force_conversion, showdbcs, dbcs_sbcs, enableime, tonoime, chinasea; +extern uint16_t GetDefaultCP(); +extern const char * RunningProgram; #define LINE_IN_MAXLEN 2048 @@ -107,7 +108,7 @@ bool InitCodePage() { } } if (!dos.loaded_codepage) { - dos.loaded_codepage = IS_PC98_ARCH||IS_JEGA_ARCH||IS_JDOSV?932:(IS_PDOSV?936:(IS_KDOSV?949:(IS_TDOSV?950:437))); + dos.loaded_codepage = GetDefaultCP(); return false; } else return true; @@ -203,7 +204,7 @@ void AddMessages() { } void SetKEYBCP() { - if (IS_PC98_ARCH || dos_kernel_disabled || !strcmp(RunningProgram, "LOADLIN")) return; + if (IS_PC98_ARCH || IS_JEGA_ARCH || IS_DOSV || dos_kernel_disabled || !strcmp(RunningProgram, "LOADLIN")) return; if (msgcodepage == 437) {dos.loaded_codepage=0;DOS_LoadKeyboardLayout("us", 437, "auto");dos.loaded_codepage=437;} else if (msgcodepage == 857) {dos.loaded_codepage=437;DOS_LoadKeyboardLayout("tr", 857, "auto");dos.loaded_codepage=857;} else if (msgcodepage == 858) {dos.loaded_codepage=437;DOS_LoadKeyboardLayout("es", 858, "auto");dos.loaded_codepage=858;} @@ -214,6 +215,7 @@ void SetKEYBCP() { else if (msgcodepage == 949) {dos.loaded_codepage=0;DOS_LoadKeyboardLayout("us", 437, "auto");DOS_LoadKeyboardLayout("ko", 949, "auto");dos.loaded_codepage=949;} else if (msgcodepage == 950) {dos.loaded_codepage=0;DOS_LoadKeyboardLayout("us", 437, "auto");DOS_LoadKeyboardLayout("tw", 950, "auto");dos.loaded_codepage=950;} else if (msgcodepage == 951) {dos.loaded_codepage=0;DOS_LoadKeyboardLayout("us", 437, "auto");DOS_LoadKeyboardLayout("hk", 951, "auto");dos.loaded_codepage=951;} + runRescan("-A -Q"); } FILE *testLoadLangFile(const char *fname) { @@ -307,6 +309,8 @@ void LoadMessageFile(const char * fname) { dos.loaded_codepage = cp; return; } + std::string msg = "The specified language file uses code page " + std::to_string(c) + ". Do you want to change to this code page accordingly?"; + if (!control->opt_langcp && !uselangcp && c != 437 && GetDefaultCP() == 437 && systemmessagebox("DOSBox-X language file", msg.c_str(), "yesno", "question", 1)) control->opt_langcp = true; msgcodepage = c; dos.loaded_codepage = c; if (c == 950 && !chinasea) makestdcp950table(); @@ -374,9 +378,9 @@ void LoadMessageFile(const char * fname) { JFONT_Init(); dos.loaded_codepage = cp; } - if (uselangcp) { + if (uselangcp && !IS_DOSV && !IS_JEGA_ARCH) { #if defined(USE_TTF) - if (ttf.inUse) toSetCodePage(NULL, msgcodepage, -1); else + if (ttf.inUse) toSetCodePage(NULL, msgcodepage, -2); else #endif { dos.loaded_codepage = msgcodepage; @@ -386,7 +390,6 @@ void LoadMessageFile(const char * fname) { UpdateSDLDrawTexture(); #endif } - SetKEYBCP(); } } diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index c63de8503..281dd6eac 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -129,14 +129,12 @@ extern bool date_host_forced, usecon, outcon, rsize, autoboxdraw, dbcs_sbcs, syn extern unsigned long freec; extern uint8_t DOS_GetAnsiAttr(void); extern uint16_t countryNo, altcp_to_unicode[256]; -void GetExpandedPath(std::string &path); -bool Network_IsNetworkResource(const char * filename), DOS_SetAnsiAttr(uint8_t attr); -void DOS_SetCountry(uint16_t countryNo), DOSV_FillScreen(void); -extern bool isDBCSCP(), isKanji1(uint8_t chr), shiftjis_lead_byte(int c), TTF_using(void); -extern bool CheckBoxDrawing(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4), GFX_GetPreventFullscreen(void); +extern bool isDBCSCP(), isKanji1(uint8_t chr), shiftjis_lead_byte(int c), TTF_using(void), Network_IsNetworkResource(const char * filename); +extern bool CheckBoxDrawing(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4), GFX_GetPreventFullscreen(void), DOS_SetAnsiAttr(uint8_t attr); extern bool systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton); -extern void Load_Language(std::string name), SwitchLanguage(int oldcp, int newcp, bool confirm); +extern void Load_Language(std::string name), SwitchLanguage(int oldcp, int newcp, bool confirm), GetExpandedPath(std::string &path); extern void MAPPER_AutoType(std::vector &sequence, const uint32_t wait_ms, const uint32_t pace_ms, bool choice); +extern void DOS_SetCountry(uint16_t countryNo), DOSV_FillScreen(void); std::string GetDOSBoxXPath(bool withexe=false); FILE *testLoadLangFile(const char *fname); @@ -4436,7 +4434,7 @@ int toSetCodePage(DOS_Shell *shell, int newCP, int opt) { SetupDBCSTable(); runRescan("-A -Q"); #if defined(USE_TTF) - if (opt==-1&&TTF_using()&&(newCP==932||newCP==936||newCP==949||newCP==950||newCP==951)) { + if ((opt==-1||opt==-2)&&TTF_using()&&(newCP==932||newCP==936||newCP==949||newCP==950||newCP==951)) { Section_prop * ttf_section = static_cast(control->GetSection("ttf")); const char *font = ttf_section->Get_string("font"); if (!font || !*font) { @@ -4450,8 +4448,8 @@ int toSetCodePage(DOS_Shell *shell, int newCP, int opt) { return missing; } else if (opt<1 && shell) { shell->WriteOut(MSG_Get("SHELL_CMD_CHCP_INVALID"), std::to_string(newCP).c_str()); - return -1; } + return -1; } void DOS_Shell::CMD_CHCP(char * args) {