Source: dosbox
Version: 0.74-4
Severity: wishlist
Tags: patch

Hi Maintainer

Since wine 1.3.12, wine will attempt to launch MS-DOS executables with
dosbox [1].
For this integration to work, dosbox needs to support the 'mount -z y'
command to move the Z: mount to Y:.

This feature was added upstream in r3736 [2].

I examined the svn log to find other patches relating to wine and
found one other; r3742 [3].

Please consider including the two attached patches to improve
interoperability with wine.

Regards
Graham


[1] https://www.winehq.org/announce/1.3.12
[2] http://sourceforge.net/p/dosbox/code-0/3736/
[3] http://sourceforge.net/p/dosbox/code-0/3743/
Description: Rewrite mount without arguments to display volume label as well.
 Some refactoring of the code.
 Add mount -z X, where X is the new virtual drive for the Wine Team.
Origin: upstream, http://sourceforge.net/p/dosbox/code-0/3736/
Author: Peter Veenstra <[email protected]>
Last-Update: 2011-07-23
--- a/src/dos/dos_programs.cpp
+++ b/src/dos/dos_programs.cpp
@@ -49,27 +49,55 @@
 #endif
 
 void MSCDEX_SetCDInterface(int intNr, int forceCD);
-
+static Bitu ZDRIVE_NUM = 25;
 
 class MOUNT : public Program {
 public:
-	void Run(void)
-	{
+	void ListMounts(void) {
+		char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
+		/* Command uses dta so set it to our internal dta */
+		RealPt save_dta = dos.dta();
+		dos.dta(dos.tables.tempdta);
+		DOS_DTA dta(dos.dta());
+
+		WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1"));
+		WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_FORMAT"),"Drive","Type","Label");
+		for(int p = 0;p < 8;p++) WriteOut("----------");
+
+		for (int d = 0;d < DOS_DRIVES;d++) {
+			if (!Drives[d]) continue;
+
+			char root[4] = {'A'+d,':','\\',0};
+			bool ret = DOS_FindFirst(root,DOS_ATTR_VOLUME);
+			if (ret) {
+				dta.GetResult(name,size,date,time,attr);
+				DOS_FindNext(); //Mark entry as invalid
+			} else name[0] = 0;
+
+			/* Change 8.3 to 11.0 */
+			char* dot = strchr(name,'.');
+			if(dot && (dot - name == 8) ) {
+				name[8] = name[9];name[9] = name[10];name[10] = name[11];name[11] = 0;
+			}
+
+			root[1] = 0; //This way, the format string can be reused.
+			WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_FORMAT"),root, Drives[d]->GetInfo(),name);
+		}
+		dos.dta(save_dta);
+	}
+
+	void Run(void) {
 		DOS_Drive * newdrive;char drive;
 		std::string label;
 		std::string umount;
+		std::string newz;
 
 		//Hack To allow long commandlines
 		ChangeToLongCmd();
 		/* Parse the command line */
 		/* if the command line is empty show current mounts */
 		if (!cmd->GetCount()) {
-			WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1"));
-			for (int d=0;d<DOS_DRIVES;d++) {
-				if (Drives[d]) {
-					WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),d+'A',Drives[d]->GetInfo());
-				}
-			}
+			ListMounts();
 			return;
 		}
 
@@ -84,12 +112,12 @@
 		if (cmd->FindString("-u",umount,false)) {
 			umount[0] = toupper(umount[0]);
 			int i_drive = umount[0]-'A';
-				if(i_drive < DOS_DRIVES && i_drive >= 0 && Drives[i_drive]) {
+				if (i_drive < DOS_DRIVES && i_drive >= 0 && Drives[i_drive]) {
 					switch (DriveManager::UnmountDrive(i_drive)) {
 					case 0:
 						Drives[i_drive] = 0;
 						if(i_drive == DOS_GetDefaultDrive()) 
-							DOS_SetDrive(toupper('Z') - 'A');
+							DOS_SetDrive(ZDRIVE_NUM);
 						WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_SUCCESS"),umount[0]);
 						break;
 					case 1:
@@ -104,8 +132,46 @@
 				}
 			return;
 		}
-	   
-		// Show list of cdroms
+
+		/* Check for moving Z: */
+		/* Only allowing moving it once. It is merely a convenience added for the wine team */
+		if (ZDRIVE_NUM == 25 && cmd->FindString("-z", newz,false)) {
+			newz[0] = toupper(newz[0]);
+			int i_newz = newz[0] - 'A';
+			if (i_newz >= 0 && i_newz < DOS_DRIVES-1 && !Drives[i_newz]) {
+				ZDRIVE_NUM = i_newz;
+				/* remap drives */
+				Drives[i_newz] = Drives[25];
+				Drives[25] = 0;
+				DOS_Shell *fs = static_cast<DOS_Shell *>(first_shell); //dynamic ?
+				/* Update environment */
+				std::string line = "";
+				char ppp[2] = {newz[0],0};
+				std::string tempenv = ppp; tempenv += ":\\";
+				if (fs->GetEnvStr("PATH",line)){
+					std::string::size_type idx = line.find('=');
+					std::string value = line.substr(idx +1 , std::string::npos);
+					while ( (idx = value.find("Z:\\")) != std::string::npos ||
+					        (idx = value.find("z:\\")) != std::string::npos  )
+						value.replace(idx,3,tempenv);
+					line = value;
+				}
+				if (!line.size()) line = tempenv;
+				fs->SetEnv("PATH",line.c_str());
+				tempenv += "COMMAND.COM";
+				fs->SetEnv("COMSPEC",tempenv.c_str());
+
+				/* Update batch file if running from Z: (very likely: autoexec) */
+				if(fs->bf) {
+					std::string &name = fs->bf->filename;
+					if(name.length() >2 &&  name[0] == 'Z' && name[1] == ':') name[0] = newz[0];
+				}
+				/* Change the active drive */
+				if (DOS_GetDefaultDrive() == 25) DOS_SetDrive(i_newz);
+			}
+			return;
+		}
+		/* Show list of cdroms */
 		if (cmd->FindExist("-cd",false)) {
 			int num = SDL_CDNumDrives();
    			WriteOut(MSG_Get("PROGRAM_MOUNT_CDROMS_FOUND"),num);
@@ -1347,8 +1413,9 @@
 	/*Add Messages */
 
 	MSG_Add("PROGRAM_MOUNT_CDROMS_FOUND","CDROMs found: %d\n");
+	MSG_Add("PROGRAM_MOUNT_STATUS_FORMAT","%-5s  %-58s %-12s\n");
 	MSG_Add("PROGRAM_MOUNT_STATUS_2","Drive %c is mounted as %s\n");
-	MSG_Add("PROGRAM_MOUNT_STATUS_1","Current mounted drives are:\n");
+	MSG_Add("PROGRAM_MOUNT_STATUS_1","The currently mounted drives are:\n");
 	MSG_Add("PROGRAM_MOUNT_ERROR_1","Directory %s doesn't exist.\n");
 	MSG_Add("PROGRAM_MOUNT_ERROR_2","%s isn't a directory\n");
 	MSG_Add("PROGRAM_MOUNT_ILL_TYPE","Illegal type %s\n");
Description: Be friendly for other open source projects: work with WINE style namemangling.
 Patch 3382938 from Andre_H (modified).
Origin: upstream, http://sourceforge.net/p/dosbox/code-0/3743/
Author: Peter Veenstra <[email protected]>
Last-Update: 2011-08-30
--- a/src/dos/drive_cache.cpp
+++ b/src/dos/drive_cache.cpp
@@ -370,6 +370,60 @@
 	return false;
 }
 
+#define WINE_DRIVE_SUPPORT 1
+#if WINE_DRIVE_SUPPORT
+//Changes to interact with WINE by supporting their namemangling.
+//The code is rather slow, because orglist is unordered, so it needs to be avoided if possible.
+//Hence the tests in GetLongFileName
+
+
+// From the Wine project
+static Bits wine_hash_short_file_name( char* name, char* buffer )
+{
+	static const char hash_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
+	static const char invalid_chars[] = { '*','?','<','>','|','"','+','=',',',';','[',']',' ','\345','~','.',0 };
+	char* p;
+	char* ext;
+	char* end = name + strlen(name);
+	char* dst;
+	unsigned short hash;
+	int i;
+
+	// Compute the hash code of the file name
+	for (p = name, hash = 0xbeef; p < end - 1; p++)
+		hash = (hash<<3) ^ (hash>>5) ^ tolower(*p) ^ (tolower(p[1]) << 8);
+	hash = (hash<<3) ^ (hash>>5) ^ tolower(*p); // Last character
+
+
+	// Find last dot for start of the extension
+	for (p = name + 1, ext = NULL; p < end - 1; p++) if (*p == '.') ext = p;
+
+	// Copy first 4 chars, replacing invalid chars with '_'
+	for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
+	{
+		if (p == end || p == ext) break;
+		*dst++ = (*p < 0 || strchr( invalid_chars, *p ) != NULL) ? '_' : toupper(*p);
+	}
+	// Pad to 5 chars with '~'
+	while (i-- >= 0) *dst++ = '~';
+
+	// Insert hash code converted to 3 ASCII chars
+	*dst++ = hash_chars[(hash >> 10) & 0x1f];
+	*dst++ = hash_chars[(hash >> 5) & 0x1f];
+	*dst++ = hash_chars[hash & 0x1f];
+
+	// Copy the first 3 chars of the extension (if any)
+	if (ext)
+	{
+		*dst++ = '.';
+		for (i = 3, ext++; (i > 0) && ext < end; i--, ext++)
+			*dst++ = (*ext < 0 || strchr( invalid_chars, *ext ) != NULL) ? '_' : toupper(*ext);
+	}
+
+	return dst - buffer;
+}
+#endif
+
 Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) {
 	std::vector<CFileInfo*>::size_type filelist_size = curDir->fileList.size();
 	if (GCC_UNLIKELY(filelist_size<=0)) return -1;
@@ -390,6 +444,20 @@
 			return mid;
 		};
 	}
+#ifdef WINE_DRIVE_SUPPORT
+	if (strlen(shortName) < 8 || shortName[4] != '~' || shortName[5] == '.' || shortName[6] == '.' || shortName[7] == '.') return -1; // not available
+	// else it's most likely a Wine style short name ABCD~###, # = not dot  (length at least 8)
+	// The above test is rather strict as the following loop can be really slow if filelist_size is large.
+	char buff[CROSS_LEN];
+	for (Bits i = 0; i < filelist_size; i++) {
+		res = wine_hash_short_file_name(curDir->fileList[i]->orgname,buff);
+		if (!strncmp(shortName,buff,res))
+		{	// Found
+			strcpy(shortName,curDir->fileList[i]->orgname);
+			return i;
+		};
+	}
+#endif
 	// not available
 	return -1;
 }

Reply via email to