mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-30 01:57:08 +00:00
LaunchAPPL: make minivmac backend work with the mac version
This commit is contained in:
parent
5808ab19f6
commit
39112683a3
@ -6,7 +6,7 @@
|
|||||||
# ########### Classic Environment
|
# ########### Classic Environment
|
||||||
|
|
||||||
# If you are on a PowerPC Mac running Tiger (10.4),
|
# If you are on a PowerPC Mac running Tiger (10.4),
|
||||||
# uncomment the following to use the Classic Environment:
|
# uncomment the following to use the Classic Environment:
|
||||||
|
|
||||||
# emulator = classic
|
# emulator = classic
|
||||||
|
|
||||||
@ -14,7 +14,7 @@
|
|||||||
# ########### Carbon on Mac OS X (native PowerPC or Rosetta)
|
# ########### Carbon on Mac OS X (native PowerPC or Rosetta)
|
||||||
|
|
||||||
# If you are on any Mac running Snow Leopard (10.6) or earlier
|
# If you are on any Mac running Snow Leopard (10.6) or earlier
|
||||||
# and you are developing Carbon applications, use the following:
|
# and you are developing Carbon applications, use the following:
|
||||||
|
|
||||||
# emulator = carbon
|
# emulator = carbon
|
||||||
|
|
||||||
@ -22,21 +22,25 @@
|
|||||||
# ########### Mini vMac (old 68K Macs)
|
# ########### Mini vMac (old 68K Macs)
|
||||||
|
|
||||||
# To use Mini vMac with LaunchAPPL, you need to supply the ROM file,
|
# To use Mini vMac with LaunchAPPL, you need to supply the ROM file,
|
||||||
# a system disk image, and a download of autoquit from the minivmac web
|
# a system disk image, and a download of autoquit from the minivmac web
|
||||||
# site, currently at
|
# site, currently at
|
||||||
# http://www.gryphel.com/c/minivmac/extras/autoquit/index.html
|
# http://www.gryphel.com/c/minivmac/extras/autoquit/index.html
|
||||||
# LaunchAPPL does not currently support MultiFinder or System 7.
|
# LaunchAPPL does not currently support MultiFinder or System 7.
|
||||||
|
|
||||||
# Fill in the information below and uncomment the lines:
|
# Fill in the information below and uncomment the lines:
|
||||||
|
|
||||||
# emulator = minivmac
|
# emulator = minivmac
|
||||||
|
|
||||||
# The directory containing vMac.ROM
|
# All minivmac related paths are specified relative to minivmac-dir:
|
||||||
# All other paths relevant to Mini vMac are relative to this directory.
|
|
||||||
# minivmac-dir = /path/to/directory/with/vMac.ROM/
|
# minivmac-dir = /path/to/directory/with/vMac.ROM/
|
||||||
|
|
||||||
# First, we need Mini vMac itself:
|
# First, we need Mini vMac itself:
|
||||||
# minivmac-path = ./Mini vMac
|
# minivmac-path = ./Mini vMac
|
||||||
|
# On Macs, specify the path of the application bundle, not the executable inside it:
|
||||||
|
# minivmac-path = ./Mini vMac.app
|
||||||
|
|
||||||
|
# A ROM file:
|
||||||
|
# minivmac-rom = ./vMac.ROM
|
||||||
|
|
||||||
# Next, a system disk image (System 6 or earlier)
|
# Next, a system disk image (System 6 or earlier)
|
||||||
# system-image = ./System.dsk
|
# system-image = ./System.dsk
|
||||||
@ -51,7 +55,7 @@
|
|||||||
# emulator = executor
|
# emulator = executor
|
||||||
|
|
||||||
# If Executor is in your PATH and the SystemFolder environment variable
|
# If Executor is in your PATH and the SystemFolder environment variable
|
||||||
# is already set up, nothing else is required.
|
# is already set up, nothing else is required.
|
||||||
|
|
||||||
# in case it's somewhere else:
|
# in case it's somewhere else:
|
||||||
# executor-path = /usr/local/bin/executor
|
# executor-path = /usr/local/bin/executor
|
||||||
@ -60,8 +64,8 @@
|
|||||||
# executor-system-folder = /path/to/ExecutorVolume/System Folder
|
# executor-system-folder = /path/to/ExecutorVolume/System Folder
|
||||||
|
|
||||||
# Pass more options to Executor.
|
# Pass more options to Executor.
|
||||||
# Note that each "word" needs to be specified separately:
|
# Note that each "word" needs to be specified separately:
|
||||||
# executor-option = -size # emulated screen size
|
# executor-option = -size # emulated screen size
|
||||||
# executor-option = 1600x1200
|
# executor-option = 1600x1200
|
||||||
|
|
||||||
# executor-option = -appearance # uncommenting these two lines
|
# executor-option = -appearance # uncommenting these two lines
|
||||||
|
@ -73,6 +73,10 @@ int Launcher::ChildProcess(string program, vector<string> args, int timeout)
|
|||||||
{
|
{
|
||||||
execvp(argv[0], const_cast<char* const *> (argv.data()));
|
execvp(argv[0], const_cast<char* const *> (argv.data()));
|
||||||
perror("exec failed");
|
perror("exec failed");
|
||||||
|
std::cerr << "Tried to execute: " << program;
|
||||||
|
for(auto a : args)
|
||||||
|
std::cerr << " " << a;
|
||||||
|
std::cerr << std::endl;
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,12 @@ extern "C" {
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define ResType MacResType
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
@ -36,11 +42,37 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recursive directory copy from https://stackoverflow.com/a/39146566
|
||||||
|
*/
|
||||||
|
static void copyDirectoryRecursively(const fs::path& sourceDir, const fs::path& destinationDir)
|
||||||
|
{
|
||||||
|
if (!fs::exists(sourceDir) || !fs::is_directory(sourceDir))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Source directory " + sourceDir.string() + " does not exist or is not a directory");
|
||||||
|
}
|
||||||
|
if (fs::exists(destinationDir))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Destination directory " + destinationDir.string() + " already exists");
|
||||||
|
}
|
||||||
|
if (!fs::create_directory(destinationDir))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot create destination directory " + destinationDir.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& dirEnt : fs::recursive_directory_iterator{sourceDir})
|
||||||
|
{
|
||||||
|
const auto& path = dirEnt.path();
|
||||||
|
auto relativePathStr = path.lexically_relative(sourceDir);
|
||||||
|
fs::copy(path, destinationDir / relativePathStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MiniVMacLauncher::MiniVMacLauncher(po::variables_map &options)
|
MiniVMacLauncher::MiniVMacLauncher(po::variables_map &options)
|
||||||
: Launcher(options),
|
: Launcher(options),
|
||||||
sysvol(NULL), vol(NULL)
|
sysvol(NULL), vol(NULL)
|
||||||
{
|
{
|
||||||
imagePath = tempDir / "image.dsk";
|
imagePath = tempDir / "disk1.dsk";
|
||||||
vmacDir = fs::absolute( options["minivmac-dir"].as<std::string>() );
|
vmacDir = fs::absolute( options["minivmac-dir"].as<std::string>() );
|
||||||
vmacPath = fs::absolute( options["minivmac-path"].as<std::string>(), vmacDir );
|
vmacPath = fs::absolute( options["minivmac-path"].as<std::string>(), vmacDir );
|
||||||
|
|
||||||
@ -119,6 +151,86 @@ MiniVMacLauncher::MiniVMacLauncher(po::variables_map &options)
|
|||||||
|
|
||||||
hfs_umount(sysvol); sysvol = NULL;
|
hfs_umount(sysvol); sysvol = NULL;
|
||||||
hfs_umount(vol); vol = NULL;
|
hfs_umount(vol); vol = NULL;
|
||||||
|
|
||||||
|
fs::path romFile = fs::absolute( options["minivmac-rom"].as<std::string>(), vmacDir );
|
||||||
|
|
||||||
|
fs::create_symlink(
|
||||||
|
romFile,
|
||||||
|
tempDir / romFile.filename() );
|
||||||
|
|
||||||
|
if(romFile.filename() != "vMac.ROM")
|
||||||
|
{
|
||||||
|
// If the ROM file is not named vMac.ROM, this might be for two different
|
||||||
|
// reasons.
|
||||||
|
// 1. The user didn't bother to rename it to the correct "vMac.ROM"
|
||||||
|
// 2. The user is using a MacII version of Mini vMac and has named the
|
||||||
|
// ROM file MacII.ROM on purpose.
|
||||||
|
|
||||||
|
// To be on the safe side, provide both the user-specified name and
|
||||||
|
// the standard vMac.ROM.
|
||||||
|
|
||||||
|
fs::create_symlink(
|
||||||
|
romFile,
|
||||||
|
tempDir / romFile.filename() );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
/*
|
||||||
|
A special case for the Mac.
|
||||||
|
|
||||||
|
The Mac build of Mini vMac does not look for files (vMac.ROM, disk1.dsk)
|
||||||
|
in the current directory, but rather in the parent directory
|
||||||
|
of the .app bundle.
|
||||||
|
|
||||||
|
Also, it ignores command line arguments.
|
||||||
|
|
||||||
|
So we just copy the entire application bundle over to our temporary
|
||||||
|
directory. It is five times smaller than System 6, so this really does not
|
||||||
|
matter.
|
||||||
|
*/
|
||||||
|
if(vmacPath.extension().string() == ".app")
|
||||||
|
{
|
||||||
|
fs::path appPath = tempDir / "minivmac.app";
|
||||||
|
|
||||||
|
copyDirectoryRecursively( vmacPath, appPath );
|
||||||
|
|
||||||
|
// The following 30 lines of code should rather be written as:
|
||||||
|
// vmacPath = appPath / "Contents" / "MacOS" / Bundle(appPath).getExecutablePath();
|
||||||
|
// But this is CoreFoundation, so it's a tiny little bit more verbose:
|
||||||
|
|
||||||
|
CFStringRef appPathCF
|
||||||
|
= CFStringCreateWithCString(
|
||||||
|
kCFAllocatorDefault, appPath.string().c_str(), kCFStringEncodingUTF8);
|
||||||
|
CFURLRef bundleURL = CFURLCreateWithFileSystemPath(
|
||||||
|
kCFAllocatorDefault, appPathCF, kCFURLPOSIXPathStyle, true);
|
||||||
|
|
||||||
|
CFBundleRef bundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
|
||||||
|
|
||||||
|
CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
|
||||||
|
|
||||||
|
CFStringRef executablePath = CFURLCopyFileSystemPath(executableURL, kCFURLPOSIXPathStyle);
|
||||||
|
|
||||||
|
if(const char *ptr = CFStringGetCStringPtr(executablePath, kCFURLPOSIXPathStyle))
|
||||||
|
{
|
||||||
|
vmacPath = string(ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector<char> buffer(
|
||||||
|
CFStringGetMaximumSizeForEncoding(
|
||||||
|
CFStringGetLength(executablePath), kCFStringEncodingUTF8) + 1);
|
||||||
|
CFStringGetCString(executablePath, buffer.data(), buffer.size(), kCFStringEncodingUTF8);
|
||||||
|
vmacPath = string(buffer.data());
|
||||||
|
}
|
||||||
|
vmacPath = appPath / "Contents" / "MacOS" / vmacPath;
|
||||||
|
|
||||||
|
CFRelease(appPathCF);
|
||||||
|
CFRelease(bundleURL);
|
||||||
|
CFRelease(bundle);
|
||||||
|
CFRelease(executableURL);
|
||||||
|
CFRelease(executablePath);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MiniVMacLauncher::~MiniVMacLauncher()
|
MiniVMacLauncher::~MiniVMacLauncher()
|
||||||
@ -159,17 +271,12 @@ void MiniVMacLauncher::CopySystemFile(const std::string &fn, bool required)
|
|||||||
|
|
||||||
bool MiniVMacLauncher::Go(int timeout)
|
bool MiniVMacLauncher::Go(int timeout)
|
||||||
{
|
{
|
||||||
fs::path minivmacdir = fs::absolute( options["minivmac-dir"].as<std::string>() );
|
fs::current_path(tempDir);
|
||||||
std::string minivmacpath = options["minivmac-path"].as<std::string>();
|
return ChildProcess(vmacPath.string(), {}, timeout) == 0;
|
||||||
|
|
||||||
fs::current_path(minivmacdir);
|
|
||||||
|
|
||||||
return ChildProcess(minivmacpath, { imagePath.string() }, timeout) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiniVMacLauncher::DumpOutput()
|
void MiniVMacLauncher::DumpOutput()
|
||||||
{
|
{
|
||||||
sleep(1);
|
|
||||||
vol = hfs_mount(imagePath.string().c_str(), 0, HFS_MODE_RDONLY);
|
vol = hfs_mount(imagePath.string().c_str(), 0, HFS_MODE_RDONLY);
|
||||||
hfsdirent fileent;
|
hfsdirent fileent;
|
||||||
int statres = hfs_stat(vol, "out", &fileent);
|
int statres = hfs_stat(vol, "out", &fileent);
|
||||||
@ -191,6 +298,7 @@ void MiniVMac::GetOptions(options_description &desc)
|
|||||||
desc.add_options()
|
desc.add_options()
|
||||||
("minivmac-dir", po::value<std::string>(),"directory containing vMac.ROM")
|
("minivmac-dir", po::value<std::string>(),"directory containing vMac.ROM")
|
||||||
("minivmac-path", po::value<std::string>()->default_value("./minivmac"),"relative path to minivmac")
|
("minivmac-path", po::value<std::string>()->default_value("./minivmac"),"relative path to minivmac")
|
||||||
|
("minivmac-rom", po::value<std::string>()->default_value("./vMac.ROM"),"minivmac ROM file")
|
||||||
("system-image", po::value<std::string>(),"path to disk image with system")
|
("system-image", po::value<std::string>(),"path to disk image with system")
|
||||||
("autoquit-image", po::value<std::string>(),"path to autoquit disk image, available from the minivmac web site")
|
("autoquit-image", po::value<std::string>(),"path to autoquit disk image, available from the minivmac web site")
|
||||||
;
|
;
|
||||||
@ -200,6 +308,7 @@ bool MiniVMac::CheckOptions(variables_map &options)
|
|||||||
{
|
{
|
||||||
return options.count("minivmac-path") != 0
|
return options.count("minivmac-path") != 0
|
||||||
&& options.count("minivmac-dir") != 0
|
&& options.count("minivmac-dir") != 0
|
||||||
|
&& options.count("minivmac-rom") != 0
|
||||||
&& options.count("system-image") != 0
|
&& options.count("system-image") != 0
|
||||||
&& options.count("autoquit-image") != 0;
|
&& options.count("autoquit-image") != 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user