Re: [hatari-users] Fforce() fails with GEMDOS drive emulation

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-users Archives ]


Hi,

On keskiviikko 13 maaliskuu 2013, Eero Tamminen wrote:
> Redirecting the handle is easy, but when Hatari should stop
> redirecting it?

> When program calls something else (what?)?

On Fclose() redirection should be removed.  This is easy.

Attached patch adds that and Fforce() emulation.  However...


> When the program exits (=must hook also Pterm())?

...this is much trickier.  I noticed that Hatari doesn't
close *any* file handles when program terminates.

I.e. if one runs in a row a large number of programs that open
many files, but which don't close them before exiting, Hatari
GEMDOS emulation will run out of internal file handles.

I could add a hook for Pterm(), Pterm0() and Ptermres()
that will close files and unalias them, but which of the open
emulated files should be closed/unaliased on program exit?

How Hatari could know that given file is for current program
and not for a program that started it?

And what should happen if program crashes instead of
terminating normally?


	- Eero
diff -r 30de442830c5 src/gemdos.c
--- a/src/gemdos.c	Wed Mar 13 23:06:53 2013 +0200
+++ b/src/gemdos.c	Wed Mar 13 23:10:04 2013 +0200
@@ -130,6 +130,9 @@
 static Uint16 nAttrSFirst;  /* File attribute for SFirst/Snext */
 
 
+#define UNFORCED_HANDLE -1
+static int ForcedHandles[5]; /* (standard) handles aliased to emulated handles */
+
 #if defined(WIN32) && !defined(mkdir)
 #define mkdir(name,mode) mkdir(name)
 #endif  /* WIN32 */
@@ -415,6 +418,7 @@
 
 	/* Clear handles structure */
 	memset(FileHandles, 0, sizeof(FileHandles));
+	memset(ForcedHandles, UNFORCED_HANDLE, sizeof(ForcedHandles));
 	/* Clear DTAs */
 	for(i = 0; i < MAX_DTAS_FILES; i++)
 	{
@@ -444,6 +448,7 @@
 		FileHandles[i].FileHandle = NULL;
 		FileHandles[i].bUsed = false;
 	}
+	memset(ForcedHandles, UNFORCED_HANDLE, sizeof(ForcedHandles));
 
 	for (DTAIndex = 0; DTAIndex < MAX_DTAS_FILES; DTAIndex++)
 	{
@@ -748,7 +753,8 @@
 	}
 	MemorySnapShot_Store(&CurrentDrive,sizeof(CurrentDrive));
 	/* Don't save file handles as files may have changed which makes
-	   it impossible to get a valid handle back */
+	 * it impossible to get a valid handle back
+	 */
 	if (!bSave)
 	{
 		/* Clear file handles  */
@@ -757,6 +763,7 @@
 			FileHandles[i].FileHandle = NULL;
 			FileHandles[i].bUsed = false;
 		}
+		memset(ForcedHandles, UNFORCED_HANDLE, sizeof(ForcedHandles));
 	}
 }
 
@@ -782,18 +789,29 @@
 
 /*-----------------------------------------------------------------------*/
 /**
- * Check ST handle is within our table range, return TRUE if not
+ * Check whether TOS handle is within our table range, or aliased,
+ * return (positive) internal Handle if yes, (negative) -1 for error.
  */
-static bool GemDOS_IsInvalidFileHandle(int Handle)
+static int GemDOS_GetValidFileHandle(int Handle)
 {
+	/* Has handle been aliased with Fforce()? */
+	if (Handle >= 0 && Handle < ARRAYSIZE(ForcedHandles)
+	    && ForcedHandles[Handle] != UNFORCED_HANDLE)
+	{
+		Handle = ForcedHandles[Handle];
+	}
+	else
+	{
+		Handle -= BASE_FILEHANDLE;
+	}
 	/* Check handle was valid with our handle table */
 	if (Handle >= 0 && Handle < MAX_FILE_HANDLES
 	    && FileHandles[Handle].bUsed)
 	{
-		return false;
+		return Handle;
 	}
 	/* invalid handle */
-	return true;
+	return -1;
 }
 
 /*-----------------------------------------------------------------------*/
@@ -1806,17 +1824,15 @@
  */
 static bool GemDOS_Close(Uint32 Params)
 {
-	int Handle;
+	int i, Handle;
 
 	/* Find our handle - may belong to TOS */
 	Handle = STMemory_ReadWord(Params);
 
 	LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS 0x3E Fclose(%i)\n", Handle);
 
-	Handle -= BASE_FILEHANDLE;
-
-	/* Check handle was valid */
-	if (GemDOS_IsInvalidFileHandle(Handle))
+	/* Get internal handle */
+	if ((Handle = GemDOS_GetValidFileHandle(Handle)) < 0)
 	{
 		/* no, assume it was TOS one -> redirect */
 		return false;
@@ -1829,6 +1845,12 @@
 	}
 	FileHandles[Handle].bUsed = false;
 
+	/* unalias handle */
+	for (i = 0; i < ARRAYSIZE(ForcedHandles); i++)
+	{
+		if (ForcedHandles[i] == Handle)
+			ForcedHandles[i] = UNFORCED_HANDLE;
+	}
 	/* Return no error */
 	Regs[REG_D0] = GEMDOS_EOK;
 	return true;
@@ -1856,10 +1878,8 @@
 	LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS 0x3F Fread(%i, %i, 0x%x)\n", 
 	          Handle, Size, Addr);
 
-	Handle -= BASE_FILEHANDLE;
-
-	/* Check handle was valid */
-	if (GemDOS_IsInvalidFileHandle(Handle))
+	/* Get internal handle */
+	if ((Handle = GemDOS_GetValidFileHandle(Handle)) < 0)
 	{
 		/* assume it was TOS one -> redirect */
 		return false;
@@ -1932,10 +1952,8 @@
 	LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS 0x40 Fwrite(%i, %i, 0x%x)\n", 
 	          Handle, Size, Addr);
 
-	Handle -= BASE_FILEHANDLE;
-
-	/* Check handle was valid */
-	if (GemDOS_IsInvalidFileHandle(Handle))
+	/* Get internal handle */
+	if ((Handle = GemDOS_GetValidFileHandle(Handle)) < 0)
 	{
 		/* assume it was TOS one -> redirect */
 		return false;
@@ -2047,10 +2065,8 @@
 
 	LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS 0x42 Fseek(%li, %i, %i)\n", Offset, Handle, Mode);
 
-	Handle -= BASE_FILEHANDLE;
-
-	/* Check handle was valid */
-	if (GemDOS_IsInvalidFileHandle(Handle))
+	/* get internal handle */
+	if ((Handle = GemDOS_GetValidFileHandle(Handle)) < 0)
 	{
 		/* assume it was TOS one -> redirect */
 		return false;
@@ -2203,6 +2219,45 @@
 
 /*-----------------------------------------------------------------------*/
 /**
+ * GEMDOS Force (file handle aliasing)
+ * Call 0x46
+ */
+static bool GemDOS_Force(Uint32 Params)
+{
+	int std, own;
+
+	/* Read details from stack */
+	std = STMemory_ReadWord(Params);
+        own = STMemory_ReadWord(Params+SIZE_WORD);
+
+	LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS 0x46 Fforce(%d, %d)\n", std, own);
+
+	/* Get internal handle */
+	if (std > own)
+	{
+		int tmp = std;
+		std = own;
+		own = tmp;
+	}
+	if ((own = GemDOS_GetValidFileHandle(own)) < 0)
+	{
+		/* assume it was TOS one -> let TOS handle it */
+		return false;
+	}
+	if (std < 0 || std >= ARRAYSIZE(ForcedHandles))
+	{
+		Log_Printf(LOG_WARN, "Forcing of non-standard %d (> %d) handle ignored\n", std, ARRAYSIZE(ForcedHandles));
+		return false;
+	}
+	ForcedHandles[std] = own;
+	
+	Regs[REG_D0] = GEMDOS_EOK;
+	return true;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/**
  * GEMDOS Get Directory
  * Call 0x47
  */
@@ -2583,10 +2638,8 @@
 	LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS 0x57 Fdatime(0x%x, %i, %i)\n", pBuffer,
 	          Handle, Flag);
 
-	Handle -= BASE_FILEHANDLE;
-
-	/* Check handle was valid */
-	if (GemDOS_IsInvalidFileHandle(Handle))
+	/* get internal handle */
+	if ((Handle = GemDOS_GetValidFileHandle(Handle)) < 0)
 	{
 		/* No, assume was TOS -> redirect */
 		return false;
@@ -2907,6 +2960,9 @@
 	 case 0x43:
 		Finished = GemDOS_Fattrib(Params);
 		break;
+	 case 0x46:
+		Finished = GemDOS_Force(Params);
+		break;
 	 case 0x47:
 		Finished = GemDOS_GetDir(Params);
 		break;
@@ -2974,6 +3030,7 @@
 			  STMemory_ReadLong(Params));
 		break;
 
+	case 0x31:	/* Ptermres */
 	default:
 		/* rest of commands */
 		LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS 0x%2hX (%s)\n",


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/