diff --git a/CMakeLists.txt b/CMakeLists.txt
index b6deafc860..3a375c3a98 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,6 +22,7 @@ if(CMAKE_SYSTEM_NAME MATCHES Retro68)
add_subdirectory(libretro)
add_subdirectory(App2)
add_subdirectory(Raytracer)
+add_subdirectory(Launcher)
else()
add_subdirectory(MakeAPPL)
add_subdirectory(ASFilter)
diff --git a/Launcher/CMakeLists.txt b/Launcher/CMakeLists.txt
new file mode 100644
index 0000000000..ca72ea0710
--- /dev/null
+++ b/Launcher/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(CMAKE_C_FLAGS "-Wno-multichar")
+add_executable(Launcher
+ Launcher.c
+ )
+
+target_link_libraries(Launcher RetroConsole retrocrt)
+add_custom_command(
+ OUTPUT Launcher.bin
+ COMMAND ${MAKE_APPL} -c Launcher -o Launcher
+ DEPENDS Launcher)
+add_custom_target(LauncherAPPL ALL DEPENDS Launcher.bin)
diff --git a/Launcher/Launcher.c b/Launcher/Launcher.c
new file mode 100644
index 0000000000..e6a96191d1
--- /dev/null
+++ b/Launcher/Launcher.c
@@ -0,0 +1,151 @@
+/*
+ Copyright 2014 Wolfgang Thaller.
+
+ This file is part of Retro68.
+
+ Retro68 is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Retro68 is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Retro68. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+void Explain()
+{
+ printf("*********************************************************\n");
+ printf("This program is intended to make developing software\n");
+ printf("using Retro68K and Mini vMac a little more convenient.\n");
+ printf("\n");
+ printf("If you insert a disk that contains a single application\n");
+ printf("(= drag a disk image created by Retro68K to this window),\n");
+ printf("the application will be automatically launched and the\n");
+ printf("disk image unmounted again afterwards.\n");
+ printf("\n");
+ printf("It just saves a few repetitive clicks.\n");
+ printf("*********************************************************\n");
+}
+
+void EjectOldDisk()
+{
+ Handle h = GetResource('LNCH', 128);
+ if(h)
+ {
+ short refNum = **(short**)h;
+ printf("Ejecting disk (refNum = %d)\n", refNum);
+
+ Eject(NULL, refNum);
+ UnmountVol(NULL, refNum);
+ RemoveResource(h);
+ }
+}
+
+int main()
+{
+ Explain();
+ EjectOldDisk();
+ printf("Insert a disk or hit any key to abort.\n");
+
+ FlushEvents(everyEvent, 0);
+
+ for(;;)
+ {
+ EventRecord e;
+ GetNextEvent(everyEvent, &e);
+
+ switch(e.what)
+ {
+ case keyDown:
+ return 0;
+ break;
+
+ case diskEvt:
+ {
+ short refNum = LoWord(e.message);
+ short err = HiWord(e.message);
+ printf("Disk Inserted (refNum = %d, error = %d)\n", refNum, err);
+ if(err == 0)
+ {
+ {
+ Handle h = NewHandle(2);
+ **(short**)h = refNum;
+ AddResource(h, 'LNCH', 128, "");
+ }
+ SetVol(NULL, refNum);
+
+ CInfoPBRec cpb;
+ unsigned char name[257];
+ int i, nApps = 0;
+ unsigned char bestName[257];
+ for(i = 1;; i++)
+ {
+ memset(&cpb, 0, sizeof(cpb));
+ cpb.dirInfo.ioVRefNum = refNum;
+ cpb.dirInfo.ioFDirIndex = i;
+ cpb.dirInfo.ioNamePtr = name;
+ err = PBGetCatInfoSync(&cpb);
+
+ if(err != noErr)
+ break;
+
+ name[name[0]+1] = 0;
+ if(cpb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
+ {
+ printf("Application: %s\n", &name[1]);
+ memcpy(bestName, name, sizeof(bestName));
+ ++nApps;
+ }
+ }
+
+ if(nApps == 0)
+ {
+ printf("No applications found on disk.\n");
+ EjectOldDisk();
+ }
+ else if(nApps > 1)
+ {
+ printf("Multiple applications found on disk.\n");
+ EjectOldDisk();
+ }
+ else
+ {
+ LaunchParamBlockRec lpb;
+ memset(&lpb, 0, sizeof(lpb));
+
+ lpb.reserved1 = (unsigned long) bestName;
+ lpb.reserved2 = 0;
+ lpb.launchBlockID = extendedBlock;
+ lpb.launchEPBLength = 6;
+ lpb.launchFileFlags = 0;
+ lpb.launchControlFlags = 0xC000;
+
+ printf("Launching...\n");
+ err = LaunchApplication(&lpb);
+ printf("Still here after launch (err = %d). Press Enter to exit.\n");
+ getchar();
+ return 0;
+ }
+ }
+ else
+ Eject(NULL, refNum);
+ }
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/libretro/glue.c b/libretro/glue.c
index f6ebabae7c..bfe51d95bd 100644
--- a/libretro/glue.c
+++ b/libretro/glue.c
@@ -18,6 +18,8 @@
*/
#include
+#include
+#include
Size GetPtrSize(Ptr ptr)
{
@@ -32,3 +34,30 @@ Size GetPtrSize(Ptr ptr)
else
return 0;
}
+
+OSErr SetVol (ConstStr63Param volName, short vRefNum)
+{
+ ParamBlockRec pb;
+ memset(&pb, 0, sizeof(pb));
+ pb.volumeParam.ioNamePtr = (StringPtr)volName;
+ pb.volumeParam.ioVRefNum = vRefNum;
+ return PBSetVolSync(&pb);
+}
+
+OSErr UnmountVol (ConstStr63Param volName, short vRefNum)
+{
+ ParamBlockRec pb;
+ memset(&pb, 0, sizeof(pb));
+ pb.volumeParam.ioNamePtr = (StringPtr)volName;
+ pb.volumeParam.ioVRefNum = vRefNum;
+ return PBUnmountVolImmed(&pb);
+}
+
+OSErr Eject (ConstStr63Param volName, short vRefNum)
+{
+ ParamBlockRec pb;
+ memset(&pb, 0, sizeof(pb));
+ pb.volumeParam.ioNamePtr = (StringPtr)volName;
+ pb.volumeParam.ioVRefNum = vRefNum;
+ return PBEject(&pb);
+}
diff --git a/types.txt b/types.txt
index 7e74a06441..f2d20bdf03 100644
--- a/types.txt
+++ b/types.txt
@@ -1,6 +1,7 @@
L Size
B Boolean
P ConstStr255Param
+P ConstStr63Param
P Str255
W CharParameter
W OSErr