Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dosbox-staging/dosbox-staging.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorripsaw8080 <ripsaw8080@users.sourceforge.net>2022-05-29 03:39:15 +0300
committerkcgen <kcgen@users.noreply.github.com>2022-05-29 03:40:38 +0300
commitbf4a482ec600a74bf7823ec1789c964ab5d266c7 (patch)
tree174e4addf200d9b956c0ad0df19260654ed6a7d5
parent749183e6322137b33eee78333d68d7a611fbe4be (diff)
parentd40affc717e7430037a7a3fcb03f3f1daeaf2530 (diff)
Merge 'svn/trunk' r4475-r4477kc/merge-r4477
r4475: - Specified path can be invalid if filename is a device. Fixes installer for World Series of Poker. r4476: - Fix "Invalid Access Code" error when opening files. Preserve last error code when no error occurs. r4477: - Support BIOS access with multiple images. Fixes some mutli-floppy installers: Dark Seed, Master of Magic, et al. - Implement INT 25h and INT 26h. Fixes some installers: Dark Seed, Gods, et al. - Allow low-level hacks for local drive HDD when floppy image(s) mounted. Fixes installing Amberstar from floppy images. - Use real pointer when writing faked sector contents. - Prevent problematic condition: booting floppy image files when floppy image(s) mounted. - FAT drive improvements regarding zero-length truncation of files. - Update Drive Parameter Table only when necessary.
-rw-r--r--include/drives.h4
-rw-r--r--src/dos/dos.cpp49
-rw-r--r--src/dos/dos_devices.cpp10
-rw-r--r--src/dos/dos_files.cpp16
-rw-r--r--src/dos/drive_fat.cpp23
-rw-r--r--src/dos/drives.cpp17
-rw-r--r--src/dos/program_boot.cpp6
-rw-r--r--src/dos/program_imgmount.cpp16
-rw-r--r--src/ints/bios_disk.cpp13
9 files changed, 121 insertions, 33 deletions
diff --git a/include/drives.h b/include/drives.h
index aee341c47..51f5ff543 100644
--- a/include/drives.h
+++ b/include/drives.h
@@ -190,6 +190,7 @@ public:
uint8_t readSector(uint32_t sectnum, void * data);
uint8_t writeSector(uint32_t sectnum, void * data);
uint32_t getAbsoluteSectFromBytePos(uint32_t startClustNum, uint32_t bytePos);
+ uint32_t getSectorCount();
uint32_t getSectorSize(void);
uint32_t getClusterSize(void);
uint32_t getAbsoluteSectFromChain(uint32_t startClustNum, uint32_t logicalSector);
@@ -201,6 +202,8 @@ public:
bool directoryChange(uint32_t dirClustNumber, direntry *useEntry, int32_t entNum);
std::shared_ptr<imageDisk> loadedDisk;
bool created_successfully;
+ uint32_t partSectOff;
+
private:
uint32_t getClusterValue(uint32_t clustNum);
void setClusterValue(uint32_t clustNum, uint32_t clustValue);
@@ -217,7 +220,6 @@ private:
bool readonly;
uint8_t fattype;
uint32_t CountOfClusters;
- uint32_t partSectOff;
uint32_t firstDataSector;
uint32_t firstRootDirSect;
diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp
index 977b9e266..0f297d32c 100644
--- a/src/dos/dos.cpp
+++ b/src/dos/dos.cpp
@@ -26,6 +26,7 @@
#include "bios.h"
#include "callback.h"
+#include "drives.h"
#include "mem.h"
#include "regs.h"
#include "serialport.h"
@@ -1377,16 +1378,55 @@ static Bitu DOS_27Handler(void) {
return CBRET_NONE;
}
-static Bitu DOS_25Handler(void) {
+static uint16_t DOS_SectorAccess(const bool read)
+{
+ auto drive = static_cast<fatDrive *>(Drives[reg_al]);
+ auto bufferSeg = SegValue(ds);
+ auto bufferOff = reg_bx;
+ auto sectorCnt = reg_cx;
+ auto sectorNum = static_cast<uint32_t>(reg_dx) + drive->partSectOff;
+ auto sectorEnd = drive->getSectorCount() + drive->partSectOff;
+
+ if (sectorCnt == 0xffff) { // large partition form
+ bufferSeg = real_readw(SegValue(ds), reg_bx + 8);
+ bufferOff = real_readw(SegValue(ds), reg_bx + 6);
+ sectorCnt = real_readw(SegValue(ds), reg_bx + 4);
+ sectorNum = real_readd(SegValue(ds), reg_bx + 0) + drive->partSectOff;
+ } else if (sectorEnd > 0xffff)
+ return 0x0207; // must use large partition form
+
+ uint8_t sectorBuf[512];
+ while (sectorCnt--) {
+ if (sectorNum >= sectorEnd)
+ return 0x0408; // sector not found
+ if (read) {
+ if (drive->readSector(sectorNum++, &sectorBuf))
+ return 0x0408;
+ for (auto &sector_byte : sectorBuf)
+ real_writeb(bufferSeg, bufferOff++, sector_byte);
+ } else {
+ for (auto &sector_byte : sectorBuf)
+ sector_byte = real_readb(bufferSeg, bufferOff++);
+ if (drive->writeSector(sectorNum++, &sectorBuf))
+ return 0x0408;
+ }
+ }
+ return 0;
+}
+
+static Bitu DOS_25Handler(void)
+{
if (reg_al >= DOS_DRIVES || !Drives[reg_al] || Drives[reg_al]->isRemovable()) {
reg_ax = 0x8002;
SETFLAGBIT(CF,true);
+ } else if (strncmp(Drives[reg_al]->GetInfo(), "fatDrive", 8) == 0) {
+ reg_ax = DOS_SectorAccess(true);
+ SETFLAGBIT(CF, reg_ax != 0);
} else {
if (reg_cx == 1 && reg_dx == 0) {
if (reg_al >= 2) {
- PhysPt ptr = PhysMake(SegValue(ds),reg_bx);
// write some BPB data into buffer for MicroProse installers
- mem_writew(ptr+0x1c,0x3f); // hidden sectors
+ real_writew(SegValue(ds), reg_bx + 0x1c, 0x3f); // hidden sectors
}
} else {
LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as disk detection drive %u",reg_al);
@@ -1401,6 +1441,9 @@ static Bitu DOS_26Handler(void) {
if (reg_al >= DOS_DRIVES || !Drives[reg_al] || Drives[reg_al]->isRemovable()) {
reg_ax = 0x8002;
SETFLAGBIT(CF,true);
+ } else if (strncmp(Drives[reg_al]->GetInfo(), "fatDrive", 8) == 0) {
+ reg_ax = DOS_SectorAccess(false);
+ SETFLAGBIT(CF, reg_ax != 0);
} else {
SETFLAGBIT(CF,false);
reg_ax = 0;
diff --git a/src/dos/dos_devices.cpp b/src/dos/dos_devices.cpp
index 8c279d5fe..aae2a2b2b 100644
--- a/src/dos/dos_devices.cpp
+++ b/src/dos/dos_devices.cpp
@@ -346,10 +346,12 @@ uint8_t DOS_FindDevice(char const * name) {
char* name_part = strrchr(fullname,'\\');
if(name_part) {
*name_part++ = 0;
- //Check validity of leading directory.
- if(!Drives[drive]->TestDir(fullname)) return DOS_DEVICES;
- } else name_part = fullname;
-
+ // Check validity of leading directory.
+ // if(!Drives[drive]->TestDir(fullname)) return
+ // DOS_DEVICES; //can be invalid
+ } else
+ name_part = fullname;
+
char* dot = strrchr(name_part,'.');
if(dot) *dot = 0; //no ext checking
diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp
index 7356b42a4..656f0bf33 100644
--- a/src/dos/dos_files.cpp
+++ b/src/dos/dos_files.cpp
@@ -573,11 +573,14 @@ bool DOS_OpenFile(char const * name,uint8_t flags,uint16_t * entry,bool fcb) {
if (device) {
Files[handle]=new DOS_Device(*Devices[devnum]);
} else {
- exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags);
+ const auto old_errorcode = dos.errorcode;
+ dos.errorcode = 0;
+ exists = Drives[drive]->FileOpen(&Files[handle], fullname, flags);
if (exists)
Files[handle]->SetDrive(drive);
- else if (dos.errorcode == DOSERR_ACCESS_CODE_INVALID)
+ if (dos.errorcode)
return false;
+ dos.errorcode = old_errorcode;
}
if (exists || device ) {
Files[handle]->AddRef();
@@ -798,7 +801,8 @@ bool DOS_CreateTempFile(char * const name,uint16_t * entry) {
tempname++;
}
}
- dos.errorcode=0;
+ const auto old_errorcode = dos.errorcode;
+ dos.errorcode = 0;
static const auto randomize_letter = CreateRandomizer<char>('A', 'Z');
do {
@@ -808,8 +812,12 @@ bool DOS_CreateTempFile(char * const name,uint16_t * entry) {
}
tempname[8]=0;
} while (DOS_FileExists(name));
+
DOS_CreateFile(name,0,entry);
- if (dos.errorcode) return false;
+ if (dos.errorcode)
+ return false;
+
+ dos.errorcode = old_errorcode;
return true;
}
diff --git a/src/dos/drive_fat.cpp b/src/dos/drive_fat.cpp
index c69eb6de3..c306a0304 100644
--- a/src/dos/drive_fat.cpp
+++ b/src/dos/drive_fat.cpp
@@ -171,7 +171,10 @@ bool fatFile::Write(uint8_t * data, uint16_t *size) {
if(seekpos < filelength && *size == 0) {
/* Truncate file to current position */
- myDrive->deleteClustChain(firstCluster, seekpos);
+ if (firstCluster != 0)
+ myDrive->deleteClustChain(firstCluster, seekpos);
+ if (seekpos == 0)
+ firstCluster = 0;
filelength = seekpos;
goto finalizeWrite;
}
@@ -554,7 +557,16 @@ uint8_t fatDrive::writeSector(uint32_t sectnum, void * data) {
return loadedDisk->Write_Sector(head, cylinder, sector, data);
}
-uint32_t fatDrive::getSectorSize(void) {
+uint32_t fatDrive::getSectorCount()
+{
+ if (bootbuffer.totalsectorcount != 0)
+ return check_cast<uint32_t>(bootbuffer.totalsectorcount);
+ else
+ return bootbuffer.totalsecdword;
+}
+
+uint32_t fatDrive::getSectorSize(void)
+{
return bootbuffer.bytespersector;
}
@@ -989,9 +1001,12 @@ bool fatDrive::FileCreate(DOS_File **file, char *name, uint16_t attributes) {
/* Check if file already exists */
if(getFileDirEntry(name, &fileEntry, &dirClust, &subEntry)) {
/* Truncate file */
- fileEntry.entrysize=0;
+ if (fileEntry.loFirstClust != 0) {
+ deleteClustChain(fileEntry.loFirstClust, 0);
+ fileEntry.loFirstClust = 0;
+ }
+ fileEntry.entrysize = 0;
directoryChange(dirClust, &fileEntry, subEntry);
- if(fileEntry.loFirstClust != 0) deleteClustChain(fileEntry.loFirstClust, 0);
} else {
/* Can we even get the name of the file itself? */
if(!getEntryName(name, &dirName[0])) return false;
diff --git a/src/dos/drives.cpp b/src/dos/drives.cpp
index 5120471fa..a526b4b9b 100644
--- a/src/dos/drives.cpp
+++ b/src/dos/drives.cpp
@@ -15,12 +15,13 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-
#include "drives.h"
+#include <string_view>
+
+#include "bios_disk.h"
#include "ide.h"
#include "string_utils.h"
-#include <string_view>
extern char sfn[DOS_NAMELENGTH_ASCII];
@@ -264,7 +265,17 @@ void DriveManager::CycleDisks(int requested_drive, bool notify)
currentDisk = (currentDisk + 1) % numDisks;
DOS_Drive* newDisk = driveInfos[drive].disks[currentDisk];
driveInfos[drive].currentDisk = currentDisk;
-
+ if (drive < MAX_DISK_IMAGES && imageDiskList[drive] != nullptr) {
+ if (strncmp(newDisk->GetInfo(), "fatDrive", 8) == 0) {
+ imageDiskList[drive] = reinterpret_cast<fatDrive *>(newDisk)->loadedDisk;
+ } else {
+ imageDiskList[drive].reset(reinterpret_cast<imageDisk *>(newDisk));
+ }
+ if ((drive == 2 || drive == 3) && imageDiskList[drive]->hardDrive) {
+ updateDPT();
+ }
+ }
+
// copy working directory, acquire system resources and finally switch to next drive
strcpy(newDisk->curdir, oldDisk->curdir);
newDisk->Activate();
diff --git a/src/dos/program_boot.cpp b/src/dos/program_boot.cpp
index 4bd811c12..643359498 100644
--- a/src/dos/program_boot.cpp
+++ b/src/dos/program_boot.cpp
@@ -222,6 +222,11 @@ void BOOT::Run(void)
continue;
}
+ if (imageDiskList[0] != nullptr || imageDiskList[1] != NULL) {
+ WriteOut(MSG_Get("PROGRAM_BOOT_IMAGE_MOUNTED"));
+ return;
+ }
+
if (i >= MAX_SWAPPABLE_DISKS) {
return; // TODO give a warning.
}
@@ -520,6 +525,7 @@ void BOOT::AddMessages() {
"\033[34;1mIMGMOUNT\033[0m command.\n\n"
"Type \033[34;1mBOOT /?\033[0m for the syntax of this command.\033[0m\n");
MSG_Add("PROGRAM_BOOT_UNABLE","Unable to boot off of drive %c");
+ MSG_Add("PROGRAM_BOOT_IMAGE_MOUNTED", "Floppy image(s) already mounted.\n");
MSG_Add("PROGRAM_BOOT_IMAGE_OPEN","Opening image file: %s\n");
MSG_Add("PROGRAM_BOOT_IMAGE_NOT_OPEN","Cannot open %s");
MSG_Add("PROGRAM_BOOT_BOOT","Booting from drive %c...\n");
diff --git a/src/dos/program_imgmount.cpp b/src/dos/program_imgmount.cpp
index 20990c6b0..d449a8e72 100644
--- a/src/dos/program_imgmount.cpp
+++ b/src/dos/program_imgmount.cpp
@@ -383,14 +383,12 @@ void IMGMOUNT::Run(void) {
}
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"), drive, tmp.c_str());
- if (paths.size() == 1) {
- auto *newdrive = static_cast<fatDrive*>(imgDisks[0]);
- if (('A' <= drive && drive <= 'B' && !(newdrive->loadedDisk->hardDrive)) ||
- ('C' <= drive && drive <= 'D' && newdrive->loadedDisk->hardDrive)) {
- const size_t idx = drive_index(drive);
- imageDiskList[idx] = newdrive->loadedDisk;
- updateDPT();
- }
+ auto *newdrive = static_cast<fatDrive*>(imgDisks[0]);
+ if (('A' <= drive && drive <= 'B' && !(newdrive->loadedDisk->hardDrive)) ||
+ ('C' <= drive && drive <= 'D' && newdrive->loadedDisk->hardDrive)) {
+ const size_t idx = drive_index(drive);
+ imageDiskList[idx] = newdrive->loadedDisk;
+ updateDPT();
}
} else if (fstype=="iso") {
if (Drives[drive_index(drive)]) {
@@ -474,7 +472,7 @@ void IMGMOUNT::Run(void) {
if (hdd) newImage->Set_Geometry(sizes[2],sizes[3],sizes[1],sizes[0]);
imageDiskList[drive - '0'].reset(newImage);
- updateDPT();
+ if ((drive == '2' || drive == '3') && hdd) updateDPT();
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT_NUMBER"),drive - '0',temp_line.c_str());
}
diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp
index 0bc94d94e..538836b83 100644
--- a/src/ints/bios_disk.cpp
+++ b/src/ints/bios_disk.cpp
@@ -297,7 +297,7 @@ static uint8_t GetDosDriveNumber(uint8_t biosNum) {
}
static bool driveInactive(uint8_t driveNum) {
- if(driveNum>=(2 + MAX_HDD_IMAGES)) {
+ if (driveNum >= MAX_DISK_IMAGES) {
LOG(LOG_BIOS,LOG_ERROR)("Disk %d non-existent", driveNum);
last_status = 0x01;
CALLBACK_SCF(true);
@@ -380,7 +380,7 @@ static Bitu INT13_DiskHandler(void) {
CALLBACK_SCF(true);
return CBRET_NONE;
}
- if (!any_images) {
+ if (drivenum < MAX_DISK_IMAGES && imageDiskList[drivenum] == nullptr) {
if (drivenum >= DOS_DRIVES || !Drives[drivenum] || Drives[drivenum]->isRemovable()) {
reg_ah = 0x01;
CALLBACK_SCF(true);
@@ -389,10 +389,13 @@ static Bitu INT13_DiskHandler(void) {
// Inherit the Earth cdrom and Amberstar use it as a disk test
if (((reg_dl&0x80)==0x80) && (reg_dh==0) && ((reg_cl&0x3f)==1)) {
if (reg_ch==0) {
- PhysPt ptr = PhysMake(SegValue(es),reg_bx);
// write some MBR data into buffer for Amberstar installer
- mem_writeb(ptr+0x1be,0x80); // first partition is active
- mem_writeb(ptr+0x1c2,0x06); // first partition is FAT16B
+ real_writeb(SegValue(es),
+ reg_bx + 0x1be,
+ 0x80); // first partition is active
+ real_writeb(SegValue(es),
+ reg_bx + 0x1c2,
+ 0x06); // first partition is FAT16B
}
reg_ah = 0;
CALLBACK_SCF(false);