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",