Merge pull request #79 from szymonlopaciuk/support_autquit7

Add support for using AutQuit7
This commit is contained in:
Wolfgang Thaller 2019-02-11 21:07:41 +01:00 committed by GitHub
commit 5f60c59ea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2,6 +2,7 @@
#include "Launcher.h"
#include "Utilities.h"
#include "BinaryIO.h"
#include "ResourceFile.h"
extern "C" {
#include "hfs.h"
@ -24,6 +25,45 @@ using std::vector;
namespace po = boost::program_options;
namespace fs = boost::filesystem;
/* Adapted from http://sebastien.kirche.free.fr/python_stuff/MacOS-aliases.txt */
typedef struct
{
int16_t type; /* type of data */
int16_t size; /* length of variable length data */
char data[]; /* actual data */
} VarData;
typedef struct
{
/* Type Code: alis */
char userType[4] = {0, 0, 0, 0}; /* for application use, can be zeros */
uint16_t size; /* alias record size, including variable length data */
int16_t version = 2; /* alias version, current 2 */
int16_t type = 0; /* file = 0, directory = 1 */
char volumeNameSize;
char volumeName[27]; /* volume name */
uint32_t volumeCreationDate; /* volume creation date, seconds since 1904 */
uint16_t volumeSig = 0x4244; /*BD*/ /* volume signature MFS = RW, HFS = BD */
int16_t volumeType = 5; /* [HD] = 0, Foreign = 1, Floppy: 400K, 800K, 1400K = 2-4, OtherEjectable = 5 */
int32_t parentDirID; /* parent directory ID, 0 for relative searches */
char fileNameSize;
char fileName[63]; /* file or directory name */
int32_t fileNum; /* file number or directory ID */
uint32_t fileCreationDate; /* file or directory creation date, seconds since 1904 */
char typeCode[4]; /* file type */
char creatorCode[4]; /* file's creator */
int16_t nlvlFrom = 0; /* next level up from alias, used in relative searches */
int16_t nlvlTo = 0; /* next level down to target, ditto */
uint32_t volumeAttr = 0; /* various flags (locked, ejectable), see link above */
int16_t volumeFSID = 0; /* file system ID for the volume, 0 for MFS, HFS */
int16_t unused = 0;
uint32_t unused1 = 0;
uint32_t unused2 = 0;
VarData vdata[]; /* variable length data, see link above */
} AliasData;
class MiniVMacLauncher : public Launcher
{
fs::path imagePath;
@ -35,6 +75,8 @@ class MiniVMacLauncher : public Launcher
hfsvol *vol;
void CopySystemFile(const std::string& fn, bool required);
uint16_t GetSystemVersion(const std::string& systemFileName);
void MakeAlias(const std::string& dest, const std::string& src);
fs::path ConvertImage(const fs::path& path);
public:
MiniVMacLauncher(po::variables_map& options);
@ -127,10 +169,7 @@ MiniVMacLauncher::MiniVMacLauncher(po::variables_map &options)
vmacPath = fs::absolute( options["minivmac-path"].as<std::string>(), vmacDir );
systemImage = fs::absolute(options["system-image"].as<std::string>(), vmacDir);
fs::path autoquitImage = fs::absolute(options["autoquit-image"].as<std::string>(), vmacDir);
systemImage = ConvertImage(systemImage);
autoquitImage = ConvertImage(autoquitImage);
std::vector<unsigned char> bootblock1(1024);
fs::ifstream(systemImage).read((char*) bootblock1.data(), 1024);
@ -138,34 +177,38 @@ MiniVMacLauncher::MiniVMacLauncher(po::variables_map &options)
if(bootblock1[0] != 'L' || bootblock1[1] != 'K' || bootblock1[0xA] > 15)
throw std::runtime_error("Not a bootable Mac disk image: " + systemImage.string());
string systemFileName(bootblock1.begin() + 0xB, bootblock1.begin() + 0xB + bootblock1[0xA]);
int size = 5000*1024;
fs::ofstream(imagePath, std::ios::binary | std::ios::trunc).seekp(size-1).put(0);
hfs_format(imagePath.string().c_str(), 0, 0, "SysAndApp", 0, NULL);
{
bootblock1[0x1A] = 8;
memcpy(&bootblock1[0x1B],"AutoQuit", 8);
bootblock1[0x5A] = 3;
memcpy(&bootblock1[0x5B],"App", 3);
fs::fstream(imagePath, std::ios::in | std::ios::out | std::ios::binary)
.write((const char*) bootblock1.data(), 1024);
}
vol = hfs_mount(imagePath.string().c_str(), 0, HFS_MODE_RDWR);
assert(vol);
sysvol = hfs_mount(systemImage.string().c_str(),0, HFS_MODE_RDONLY);
assert(sysvol);
hfsvolent ent;
hfs_vstat(sysvol, &ent);
hfs_setcwd(sysvol, ent.blessed);
string systemFileName(bootblock1.begin() + 0xB, bootblock1.begin() + 0xB + bootblock1[0xA]);
uint16_t sysver = GetSystemVersion(systemFileName);
bool usesAutQuit7 = (sysver >= 0x700);
fs::path autoquitImage = fs::absolute(options[usesAutQuit7 ? "autquit7-image" : "autoquit-image"].as<std::string>(), vmacDir);
autoquitImage = ConvertImage(autoquitImage);
int size = 5000*1024;
fs::ofstream(imagePath, std::ios::binary | std::ios::trunc).seekp(size-1).put(0);
hfs_format(imagePath.string().c_str(), 0, 0, "SysAndApp", 0, NULL);
if(!usesAutQuit7)
{
std::string finderName = std::string(usesAutQuit7 ? "Finder" : "AutoQuit");
bootblock1[0x1A] = finderName.size();
memcpy(&bootblock1[0x1B], finderName.c_str(), finderName.size());
bootblock1[0x5A] = 3;
memcpy(&bootblock1[0x5B],"App", 3);
}
fs::fstream(imagePath, std::ios::in | std::ios::out | std::ios::binary)
.write((const char*) bootblock1.data(), 1024);
vol = hfs_mount(imagePath.string().c_str(), 0, HFS_MODE_RDWR);
assert(vol);
hfs_vstat(vol, &ent);
ent.blessed = hfs_getcwd(vol);
@ -176,6 +219,11 @@ MiniVMacLauncher::MiniVMacLauncher(po::variables_map &options)
CopySystemFile(systemFileName, true);
CopySystemFile("MacsBug", false);
if (usesAutQuit7)
{
CopySystemFile("Finder", true);
}
{
std::ostringstream rsrcOut;
app.resources.writeFork(rsrcOut);
@ -195,13 +243,22 @@ MiniVMacLauncher::MiniVMacLauncher(po::variables_map &options)
if(!sysvol)
throw std::runtime_error("Cannot open disk image: " + autoquitImage.string());
assert(sysvol);
CopySystemFile("AutoQuit", true);
if (usesAutQuit7)
{
CopySystemFile("AutQuit7", true);
MakeAlias("AutQuit7 alias", "AutQuit7");
hfs_mkdir(vol, "Startup Items");
hfs_rename(vol, "AutQuit7 alias", "Startup Items");
}
else
{
CopySystemFile("AutoQuit", true);
}
{
hfsfile *file = hfs_create(vol, "out", "TEXT", "MPS ");
hfs_close(file);
}
hfs_umount(sysvol); sysvol = NULL;
hfs_umount(vol); vol = NULL;
@ -326,6 +383,55 @@ void MiniVMacLauncher::CopySystemFile(const std::string &fn, bool required)
hfs_close(out);
}
void MiniVMacLauncher::MakeAlias(const std::string& dest, const std::string& src)
{
hfsdirent ent;
hfsvolent vent;
hfs_stat(vol, src.c_str(), &ent);
hfs_vstat(vol, &vent);
AliasData alias;
alias.size = sizeof(AliasData);
memcpy(&(alias.volumeName), vent.name, 27);
alias.volumeNameSize = strlen(vent.name);
alias.volumeCreationDate = vent.crdate;
alias.parentDirID = ent.parid;
memcpy(&(alias.fileName), ent.name, 63);
alias.fileNameSize = strlen(ent.name);
alias.fileNum = ent.cnid;
alias.fileCreationDate = ent.crdate;
memcpy(&(alias.typeCode), ent.u.file.type, 4);
memcpy(&(alias.creatorCode), ent.u.file.creator, 4);
std::ostringstream roalias;
Resources res;
res.addResource(Resource("alis", 0, std::string((char*)&alias, sizeof(AliasData))));
res.writeFork(roalias);
std::string ralias = roalias.str();
hfsfile *falias = hfs_create(vol, dest.c_str(), "adrp", ent.u.file.creator);
hfs_setfork(falias, 1);
hfs_write(falias, ralias.data(), ralias.size());
hfs_close(falias);
}
uint16_t MiniVMacLauncher::GetSystemVersion(const std::string& systemFileName)
{
hfsdirent fileent;
hfs_stat(sysvol, systemFileName.c_str(), &fileent);
hfsfile* system = hfs_open(sysvol, systemFileName.c_str());
std::vector<uint8_t> buffer(fileent.u.file.rsize);
hfs_setfork(system, 1);
hfs_read(system, buffer.data(), fileent.u.file.rsize);
hfs_close(system);
std::istringstream systemResStream(std::string((char*)buffer.data(), buffer.size()));
Resources systemRes(systemResStream);
Resource vers = systemRes.resources[ResRef('vers', 1)];
return (uint16_t)vers.getData()[0] << 8 | vers.getData()[1];
}
bool MiniVMacLauncher::Go(int timeout)
{
@ -361,6 +467,7 @@ void MiniVMac::GetOptions(options_description &desc)
("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")
("autoquit-image", po::value<std::string>(),"path to autoquit disk image, available from the minivmac web site")
("autquit7-image", po::value<std::string>(),"path to autquit7 disk image, available from the minivmac web site")
;
}
@ -370,7 +477,8 @@ bool MiniVMac::CheckOptions(variables_map &options)
&& options.count("minivmac-dir") != 0
&& options.count("minivmac-rom") != 0
&& options.count("system-image") != 0
&& options.count("autoquit-image") != 0;
&& options.count("autoquit-image") != 0
&& options.count("autquit7-image") != 0;
}
std::unique_ptr<Launcher> MiniVMac::MakeLauncher(variables_map &options)