/[pcsx2_0.9.7]/trunk/pcsx2/IopBios.cpp
ViewVC logotype

Diff of /trunk/pcsx2/IopBios.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

--- trunk/pcsx2/IopBios.cpp	2010/09/07 03:24:11	31
+++ trunk/pcsx2/IopBios.cpp	2010/09/07 11:08:22	62
@@ -25,6 +25,61 @@
 #define O_BINARY 0
 #endif
 
+// set this to 0 to disable rewriting 'host:' paths!
+#define USE_HOST_REWRITE 1
+
+#if USE_HOST_REWRITE
+#	ifdef WIN32
+		// disable this if you DON'T want "host:/usr/local/" paths
+		// to get rewritten into host:/
+#		define HOST_REWRITE_USR_LOCAL 1
+#	else
+		// unix/linux users might want to set it to 1
+		// if they DO want to keep demos from accessing their systems' /usr/local
+#		define HOST_REWRITE_USR_LOCAL 0
+#	endif
+
+static char HostRoot[1024];
+#endif
+
+void Hle_SetElfPath(const char* elfFileName)
+{
+#if USE_HOST_REWRITE
+	DevCon.WriteLn("HLE Host: Will load ELF: %s\n", elfFileName);
+
+	const char* pos1 = strrchr(elfFileName,'/');
+	const char* pos2 = strrchr(elfFileName,'\\');
+
+	if(pos2 > pos1) // we want the LAST path separator
+		pos1=pos2;
+
+	if(!pos1) // if pos1 is NULL, then pos2 was not > pos1, so it must also be NULL
+	{
+		Console.Warning("HLE Warning: ELF does not have a path!!\n");
+
+		// use %CD%/host/
+		getcwd(HostRoot,1000); // save the other 23 chars to append /host/ :P
+		HostRoot[1000]=0; // Be Safe.
+
+		char* last = HostRoot + strlen(HostRoot) - 1;
+		
+		if((*last!='/') && (*last!='\\')) // PathAppend()-ish
+			last++;
+
+		strcpy(last,"/host/");
+
+		return;
+	}
+
+	int len = pos1-elfFileName+1;
+	memcpy(HostRoot,elfFileName,len); // include the / (or \\)
+	HostRoot[len] = 0;
+
+	Console.WriteLn("HLE Host: Set 'host:' root path to: %s\n", HostRoot);
+
+#endif
+}
+
 namespace R3000A {
 
 #define v0 (psxRegs.GPR.n.v0)
@@ -52,7 +107,7 @@
 		fd = hostfd;
 	}
 
-	static __forceinline int translate_error(int err)
+	static __fi int translate_error(int err)
 	{
 		if (err >= 0)
 			return err;
@@ -75,10 +130,59 @@
 	{
 		const char *path = strchr(name, ':') + 1;
 
-		if (flags != IOP_O_RDONLY)
-			return -IOP_EROFS;
+		// host: actually DOES let you write!
+		//if (flags != IOP_O_RDONLY)
+		//	return -IOP_EROFS;
+
+		// WIP code. Works well on win32, not so sure on unixes
+		// TODO: get rid of dependency on CWD/PWD
+#if USE_HOST_REWRITE
+		// we want filenames to be relative to pcs2dir / host
+
+		static char pathMod[1024];
+
+		// partial "rooting",
+		// it will NOT avoid a path like "../../x" from escaping the pcsx2 folder!
+
+#if HOST_REWRITE_USR_LOCAL
+		const char *_local_root = "/usr/local/";
+		if(strncmp(path,_local_root,strlen(_local_root))==0)
+		{
+			strcpy(pathMod,HostRoot);
+			strcat(pathMod,path+strlen(_local_root));
+		}
+		else
+#endif
+		if((path[0] == '/') || (path[0] == '\\') || (isalpha(path[0]) && (path[1] == ':'))) // absolute NATIVE path (X:\blah)
+		{
+			// TODO: allow some way to use native paths in non-windows platforms
+			// maybe hack it so linux prefixes the path with "X:"? ;P
+			// or have all platforms use a common prefix for native paths
+			strcpy(pathMod,path);
+		}
+		else // relative paths
+		{
+			strcpy(pathMod,HostRoot);
+			strcat(pathMod,path);
+		}
+#else
+		const char* pathMod = path;
+#endif
+
+		int native_flags = O_BINARY; // necessary in Windows.
+
+		switch(flags&IOP_O_RDWR)
+		{
+		case IOP_O_RDONLY:	native_flags |= O_RDONLY;	break;
+		case IOP_O_WRONLY:	native_flags |= O_WRONLY; break;
+		case IOP_O_RDWR:	native_flags |= O_RDWR;	break;
+		}
+
+		if(flags&IOP_O_APPEND)	native_flags |= O_APPEND;
+		if(flags&IOP_O_CREAT)	native_flags |= O_CREAT;
+		if(flags&IOP_O_TRUNC)	native_flags |= O_TRUNC;
 
-		int hostfd = ::open(path, O_BINARY | O_RDONLY);
+		int hostfd = ::open(pathMod, native_flags);
 		if (hostfd < 0)
 			return translate_error(hostfd);
 
@@ -121,6 +225,11 @@
 	{
 		return translate_error(::read(fd, buf, count));
 	}
+
+	virtual int write(void *buf, u32 count)
+	{
+		return translate_error(::write(fd, buf, count));
+	}
 };
 
 namespace ioman {
@@ -248,7 +357,7 @@
 			else
 			{
 				v0 = allocfd(file);
-				if (v0 < 0)
+				if ((s32)v0 < 0)
 					file->close();
 			}
 
@@ -311,17 +420,26 @@
 
 	int write_HLE()
 	{
-		int fd = a0;
+		s32 fd = a0;
+		u32 buf = a1;
+		u32 count = a2;
 
-#ifdef PCSX2_DEVBUILD
 		if (fd == 1) // stdout
 		{
-			Console.Write(ConColor_IOP, L"%s", ShiftJIS_ConvertString(Ra1, a2).c_str());
+			iopConLog(ShiftJIS_ConvertString(Ra1, a2));
 			pc = ra;
 			v0 = a2;
 			return 1;
 		}
-#endif
+		else if (IOManFile *file = getfd<IOManFile>(fd))
+		{
+			if (!iopVirtMemR<void>(buf))
+				return 0;
+
+			v0 = file->write(iopVirtMemW<void>(buf), count);
+			pc = ra;
+			return 1;
+		}
 
 		return 0;
 	}
@@ -330,14 +448,23 @@
 namespace sysmem {
 	int Kprintf_HLE()
 	{
-		char tmp[1024], tmp2[1024];
-		char *ptmp = tmp;
-		int n=1, i=0, j = 0;
-
+		// Emulate the expected Kprintf functionality:
 		iopMemWrite32(sp, a0);
 		iopMemWrite32(sp + 4, a1);
 		iopMemWrite32(sp + 8, a2);
 		iopMemWrite32(sp + 12, a3);
+		pc = ra;
+
+
+		// From here we're intercepting the Kprintf and piping it to our console, complete with
+		// printf-style formatting processing.  This part can be skipped if the user has the
+		// console disabled.
+
+		if (!SysConsole.iopConsole.IsActive()) return 1;
+
+		char tmp[1024], tmp2[1024];
+		char *ptmp = tmp;
+		int n=1, i=0, j = 0;
 
 		while (Ra0[i])
 		{
@@ -414,12 +541,8 @@
 			}
 		}
 		*ptmp = 0;
+		iopConLog( ShiftJIS_ConvertString(tmp, 1023) );
 
-		// Use "%s" even though it seems indirect: this avoids chaos if/when the IOP decides
-		// to feed us strings that contain percentages or other printf formatting control chars.
-		Console.Write( ConColor_IOP, L"%s", ShiftJIS_ConvertString(tmp).c_str(), 1023 );
-		
-		pc = ra;
 		return 1;
 	}
 }
@@ -497,12 +620,11 @@
 
 irxHLE irxImportHLE(const char libname[8], u16 index)
 {
-#ifdef PCSX2_DEVBUILD
 	// debugging output
 	MODULE(sysmem)
 		EXPORT_H( 14, Kprintf)
 	END_MODULE
-#endif
+
 	MODULE(ioman)
 		EXPORT_H(  4, open)
 		EXPORT_H(  5, close)

 

  ViewVC Help
Powered by ViewVC 1.1.22