Re: [hatari-devel] Re: Feature request: allow to specify "-d" with autostart

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


Hi,

On 03/29/2017 01:44 AM, Miro Kropáček wrote:
thank you for taking time to look at this.

* "-d" option is already used for specifying GEMDOS HD directory
  (if you specify e.g. floppy image after that on command line,
   then A: is the boot drive, not GEMDOS HD C:)

Yes, this is what I have figured out in the meantime, this is good (if one
uses an ACSI boot drive).

* For autoexec to work, boot drive must be GEMDOS HD
  (because it works by hooking TOS *.INF file read, and
   TOS reads that only from boot drive)

This is the problem, yes. Isn't possible to make a simple hack where you
would listen to Fopen() / Fread() / Fclose() on *.INF and supply the
content regardless of the source? Something like a super lightweight GEMDOS
HD. ;-)

Attached patch handles also that case.

Thomas, Nicolas, any comments on the patch?


	- Eero

* Currently Hatari validates that autoexecuted program path and
  file are OK.  This cannot be done if the option doesn't know
  where it will be in the file system hierarchy, which would be
  the case with your proposal

I could live without this.

Instead, my proposal is an option for specifying the autostarted
program with full path:
  --auto <x>            Atari program autostarting with Atari path

Attached is a patch implementing that.  Only validation it does
is that the drive letter isn't obviously bogus.

I tried it and works OK. While it's definitely a step forward, it doesn't
solve my problem for 100% however. Right now I must have *one* specific
(GEMDOS HD) drive with AUTO, ACCs etc and copy my binaries there to make
the binaries autostarted after AUTO. So imagine I want to have a setup with
MagiC and setup with TOS. In my vision I'd just specific different ACSI/IDE
image with this setup and supply a path to my binaries, either as a folder
or directly as a file. Folder works, so this is solved, only the file
remains.

Opposite solution (having my files on an ACSI/IDE imagine and boot/parse
from a GEMDOS HD) isn't very helpful either as I'd need to create images
everytime I want to run my binaries. ;-)

diff -r d97b4d878ace src/cart.c
--- a/src/cart.c	Thu Mar 30 00:05:38 2017 +0300
+++ b/src/cart.c	Thu Mar 30 00:07:51 2017 +0300
@@ -116,11 +116,13 @@
 	}
 
 	/* Use internal cartridge trampoline code when user wants extended VDI
-	 * resolution, GEMDOS HD emulation or to trace GEMDOS, VDI or AES.
-	 * (OS_BASE does subset of GEMDOS tracing)
-	 * But don't use it on TOS 0.00, it does not work there. */
+	 * resolution, use GEMDOS HD emulation / Autostarting, or to trace GEMDOS,
+	 * VDI or AES (OS_BASE does subset of GEMDOS tracing).
+	 * But don't use it on TOS 0.00, it does not work there.
+	 */
 	PatchIllegal = false;				/* By default, don't patch opcodes */
-	if ((bUseVDIRes || ConfigureParams.HardDisk.bUseHardDiskDirectories ||
+	if ((bUseVDIRes || TOS_AutoStarting(AUTOSTART_INTERCEPT) ||
+	     ConfigureParams.HardDisk.bUseHardDiskDirectories ||
 	    LogTraceFlags & (TRACE_OS_GEMDOS | TRACE_OS_BASE | TRACE_OS_VDI | TRACE_OS_AES))
 	    && TosVersion >= 0x100)
 	{
diff -r d97b4d878ace src/gemdos.c
--- a/src/gemdos.c	Thu Mar 30 00:05:38 2017 +0300
+++ b/src/gemdos.c	Thu Mar 30 00:07:51 2017 +0300
@@ -1844,6 +1844,12 @@
 
 
 /*-----------------------------------------------------------------------*/
+static inline bool redirect_to_TOS(void)
+{
+	LOG_TRACE(TRACE_OS_GEMDOS|TRACE_OS_BASE, "-> to TOS\n");
+	return false;
+}
+
 /**
  * GEMDOS Open file
  * Call 0x3D
@@ -1859,6 +1865,7 @@
 	};
 	int Drive, Index, Mode;
 	FILE *AutostartHandle;
+	bool bToTos = false;
 
 	/* Find filename */
 	pszFileName = (char *)STMemory_STAddrToPointer(STMemory_ReadLong(Params));
@@ -1873,15 +1880,19 @@
 
 	if (!ISHARDDRIVE(Drive))
 	{
-		/* redirect to TOS */
-		LOG_TRACE(TRACE_OS_GEMDOS|TRACE_OS_BASE, "-> to TOS\n");
-		return false;
+		if (TOS_AutoStarting(AUTOSTART_FOPEN))
+			bToTos = true;
+		else
+			return redirect_to_TOS();
 	}
 
 	/* Find slot to store file handle, as need to return WORD handle for ST  */
 	Index = GemDOS_FindFreeFileHandle();
 	if (Index == -1)
 	{
+		if (bToTos)
+			return redirect_to_TOS();
+
 		/* No free handles, return error code */
 		Regs[REG_D0] = GEMDOS_ENHNDL;       /* No more handles */
 		return true;
@@ -1896,6 +1907,8 @@
 	else
 	{
 		struct stat FileStat;
+		if (bToTos)
+			return redirect_to_TOS();
 
 		/* Convert to hard drive filename */
 		GemDOS_CreateHardDriveFileName(Drive, pszFileName,
@@ -3466,10 +3479,12 @@
 
 	LOG_TRACE(TRACE_OS_GEMDOS, "Gemdos_Boot() at PC 0x%X\n", M68000_GetPC() );
 
-	/* install our gemdos handler, if -e or --harddrive option used,
-	 * or user wants to do GEMDOS tracing
+	/* install our gemdos handler, if user has enabled either
+	 * GEMDOS HD, autostarting or GEMDOS tracing
 	 */
-	if (!GEMDOS_EMU_ON && !(LogTraceFlags & (TRACE_OS_GEMDOS|TRACE_OS_BASE)))
+	if (!GEMDOS_EMU_ON &&
+	    !TOS_AutoStarting(AUTOSTART_INTERCEPT) &&
+	    !(LogTraceFlags & (TRACE_OS_GEMDOS|TRACE_OS_BASE)))
 		return;
 
 	/* Get the address of the p_run variable that points to the actual basepage */
diff -r d97b4d878ace src/includes/tos.h
--- a/src/includes/tos.h	Thu Mar 30 00:05:38 2017 +0300
+++ b/src/includes/tos.h	Thu Mar 30 00:07:51 2017 +0300
@@ -16,8 +16,15 @@
 extern unsigned int ConnectedDriveMask;
 extern int nNumDrives;
 
+typedef enum {
+	AUTOSTART_INTERCEPT,
+	AUTOSTART_FOPEN
+} autostart_t;
+
 extern void TOS_MemorySnapShot_Capture(bool bSave);
-extern void TOS_AutoStart(const char *prgname);
+extern bool TOS_AutoStartSet(const char *prgname);
+extern const char *TOS_AutoStartInvalidDrive(void);
+extern bool TOS_AutoStarting(autostart_t t);
 extern FILE *TOS_AutoStartOpen(const char *filename);
 extern bool TOS_AutoStartClose(FILE *fp);
 extern int TOS_LoadImage(void);
diff -r d97b4d878ace src/options.c
--- a/src/options.c	Thu Mar 30 00:05:38 2017 +0300
+++ b/src/options.c	Thu Mar 30 00:07:51 2017 +0300
@@ -64,6 +64,7 @@
 	OPT_CONFIGFILE,
 	OPT_KEYMAPFILE,
 	OPT_FASTFORWARD,
+	OPT_AUTOSTART,
 	OPT_MONO,		/* common display options */
 	OPT_MONITOR,
 	OPT_FULLSCREEN,
@@ -202,6 +203,8 @@
 	  "<file>", "Read (additional) keyboard mappings from <file>" },
 	{ OPT_FASTFORWARD, NULL, "--fast-forward",
 	  "<bool>", "Help skipping stuff on fast machine" },
+	{ OPT_AUTOSTART, NULL, "--auto",
+	  "<x>", "Atari program autostarting with Atari path" },
 
 	{ OPT_HEADER, NULL, NULL, NULL, "Common display" },
 	{ OPT_MONO,      "-m", "--mono",
@@ -867,6 +870,23 @@
 
 
 /**
+ * Do final validation for the earlier + parsed options
+ *
+ * Return false if they fail validation.
+ */
+static bool Opt_ValidateOptions(void)
+{
+	const char *err;
+
+	if ((err = TOS_AutoStartInvalidDrive()))
+	{
+		return Opt_ShowError(OPT_AUTOSTART, err, "Required autostart drive isn't enabled");
+	}
+	return true;
+}
+
+
+/**
  * Return true if given path points to an Atari program, false otherwise.
  */
 bool Opt_IsAtariProgram(const char *path)
@@ -912,7 +932,7 @@
 		 * then make sure that given program from that
 		 * dir will be started.
 		 */
-		TOS_AutoStart(prgname);
+		TOS_AutoStartSet(prgname);
 	}
 	if (dir) {
 		path = dir;
@@ -973,7 +993,7 @@
 	{
 		/* last argument can be a non-option */
 		if (argv[i][0] != '-' && i+1 == argc)
-			return Opt_HandleArgument(argv[i]);
+			return Opt_HandleArgument(argv[i]) && Opt_ValidateOptions();
 
 		/* WhichOption() checks also that there is an argument,
 		 * so we don't need to check that below
@@ -998,6 +1018,13 @@
 			ok = Opt_Bool(argv[++i], OPT_FASTFORWARD, &ConfigureParams.System.bFastForward);
 			break;
 
+		case OPT_AUTOSTART:
+			if (!(ok = TOS_AutoStartSet(argv[++i])))
+			{
+				return Opt_ShowError(OPT_AUTOSTART, argv[i], "Invalid drive specified for autostart path");
+			}
+			break;
+
 		case OPT_CONFIGFILE:
 			i += 1;
 			/* true -> file needs to exist */
@@ -2019,7 +2046,7 @@
 		}
 	}
 
-	return true;
+	return Opt_ValidateOptions();
 }
 
 /**
diff -r d97b4d878ace src/tos.c
--- a/src/tos.c	Thu Mar 30 00:05:38 2017 +0300
+++ b/src/tos.c	Thu Mar 30 00:07:51 2017 +0300
@@ -57,14 +57,14 @@
 
 static struct {
 	FILE *file;          /* file pointer to contents of INF file */
-	char prgname[16];    /* TOS name of the program to auto start */
+	char *prgname;       /* TOS name of the program to auto start */
 	const char *infname; /* name of the INF file TOS will try to match */
 } TosAutoStart;
 
-/* autostarted program name will be added after first '\' character */
+/* autostarted program name will be added befere first '@' character */
 static const char emudesk_inf[] =
 "#E 9A 07\r\n"
-"#Z 01 C:\\@\r\n"
+"#Z 01 @\r\n"
 "#W 00 00 02 06 26 0C 08 C:\\*.*@\r\n"
 "#W 00 00 02 08 26 0C 00 @\r\n"
 "#W 00 00 02 0A 26 0C 00 @\r\n"
@@ -85,7 +85,7 @@
 "#b001000\r\n"
 "#c7770007000600070055200505552220770557075055507703111302\r\n"
 "#d\r\n"
-"#Z 01 C:\\@\r\n"
+"#Z 01 @\r\n"
 "#E D8 11\r\n"
 "#W 00 00 10 01 17 17 13 C:\\*.*@\r\n"
 "#W 00 00 08 0B 1D 0D 00 @\r\n"
@@ -439,10 +439,117 @@
 /**
  * Set name of program that will be auto started after TOS boots.
  * Supported only from TOS 1.04 forward.
+ *
+ * If program lacks a path, "C:\" will be added.
+ *
+ * Returns true if OK, false for obviously invalid path specification.
  */
-void TOS_AutoStart(const char *prgname)
+bool TOS_AutoStartSet(const char *name)
 {
-	Str_Filename2TOSname(prgname, TosAutoStart.prgname);
+	char *prgname;
+	int len = strlen(name);
+	char drive = toupper(name[0]);
+
+	if (drive >= 'A' && drive <= 'Z' && name[1] == ':' && name[2] == '\\')
+	{
+		/* full path */
+		int offset;
+		prgname = malloc(len+1);
+		offset = strrchr(name, '\\') - name + 1;
+		/* copy/upcase path part */
+		memcpy(prgname, name, offset);
+		prgname[offset] = '\0';
+		Str_ToUpper(prgname);
+		/* copy/upcase file part */
+		Str_Filename2TOSname(name+offset, prgname+offset);
+	}
+	else if (strchr(name, '\\'))
+	{
+		/* partial path not accepted */
+		return false;
+	}
+	else
+	{
+		/* just program -> add path */
+		prgname = malloc(3 + len + 1);
+		strcpy(prgname, "C:\\");
+		Str_Filename2TOSname(name, prgname+3);
+	}
+	if (TosAutoStart.prgname)
+		free(TosAutoStart.prgname);
+	TosAutoStart.prgname = prgname;
+	return true;
+}
+
+/*-----------------------------------------------------------------------*/
+/**
+ * Trivial checks on whether autostart program drive may exist.
+ *
+ * Return NULL if it could, otherwise return the invalid autostart path.
+ */
+const char *TOS_AutoStartInvalidDrive(void)
+{
+	char drive;
+	const char *path = TosAutoStart.prgname;
+
+	if (!path)
+		return NULL;
+	drive = path[0];
+
+	if (drive == 'A')
+	{
+		if (ConfigureParams.DiskImage.EnableDriveA && ConfigureParams.DiskImage.szDiskFileName[0][0])
+			return NULL;
+	}
+	else if (drive == 'B')
+	{
+		if (ConfigureParams.DiskImage.EnableDriveB && ConfigureParams.DiskImage.szDiskFileName[1][0])
+			return NULL;
+	}
+	/* exact drive checking for hard drives would require:
+	 *
+	 * For images:
+	 * - finding out what partitions each of the IDE master &
+	 *   Slave, 8 ACSI, and 8 SCSI images do have, *and*
+	 * - finding out which of those partitions the native Atari
+	 *   harddisk driver happens to support...
+	 * -> not feasible
+	 *
+	 * For GEMDOS HD:
+	 * - If multiple partitions are specified, which ones
+	 * - If not, what is the single partition drive letter
+	 *
+	 * So, just check that some harddisk is enabled for C: ->
+	 */
+
+	/* GEMDOS HD */
+	else if (ConfigureParams.HardDisk.bUseHardDiskDirectories && ConfigureParams.HardDisk.szHardDiskDirectories[0])
+	{
+		return NULL;
+	}
+	/* IDE */
+	else if (ConfigureParams.HardDisk.bUseIdeMasterHardDiskImage && ConfigureParams.HardDisk.szIdeMasterHardDiskImage[0])
+	{
+		return NULL;
+	}
+	else if (ConfigureParams.HardDisk.bUseIdeMasterHardDiskImage && ConfigureParams.HardDisk.szIdeMasterHardDiskImage[0])
+	{
+		return NULL;
+	}
+	else
+	{
+		/* ACSI / SCSI */
+		int i;
+		for (i = 0; i < MAX_ACSI_DEVS; i++)
+		{
+			if (ConfigureParams.Acsi[i].bUseDevice && ConfigureParams.Acsi[i].sDeviceFile[0])
+				return NULL;
+			if (ConfigureParams.Scsi[i].bUseDevice && ConfigureParams.Scsi[i].sDeviceFile[0])
+				return NULL;
+		}
+	}
+	/* error */
+	return path;
 }
 
 /*-----------------------------------------------------------------------*/
@@ -464,7 +571,7 @@
 
 	prgname = TosAutoStart.prgname;
 	/* autostart not enabled? */
-	if (!*prgname)
+	if (!prgname)
 		return;
 
 	/* autostart not supported? */
@@ -476,7 +583,10 @@
 
 	if (bIsEmuTOS)
 	{
-		infname = "C:\\EMUDESK.INF";
+		if (ConfigureParams.HardDisk.bBootFromHardDisk)
+			infname = "C:\\EMUDESK.INF";
+		else
+			infname = "A:\\EMUDESK.INF";
 		size = sizeof(emudesk_inf);
 		contents = emudesk_inf;
 	} else {
@@ -494,9 +604,9 @@
 	TosAutoStart.infname = infname;
 
 	/* find where to insert the program name */
-	for (offset = 0; offset < size; )
+	for (offset = 0; offset < size; offset++)
 	{
-		if (contents[offset++] == '\\')
+		if (contents[offset] == '@')
 			break;
 	}
 	assert(offset < size);
@@ -527,6 +637,20 @@
 	Log_Printf(LOG_WARN, "Virtual autostart file '%s' created for '%s'.\n", infname, prgname);
 }
 
+
+/*-----------------------------------------------------------------------*/
+/**
+ * Whether autostarting needs GEMDOS
+ * interception or Fopen() check enabling
+ */
+bool TOS_AutoStarting(autostart_t t)
+{
+	if (t == AUTOSTART_FOPEN)
+		return (bool)TosAutoStart.file;
+	else
+		return (bool)TosAutoStart.prgname;
+}
+
 /*-----------------------------------------------------------------------*/
 /**
  * If given name matches autostart file, return its handle, NULL otherwise


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