AppleDouble support

This commit is contained in:
Wolfgang Thaller 2017-09-23 21:02:22 +02:00
parent 57906f91c1
commit 406471dd79
4 changed files with 86 additions and 19 deletions

View File

@ -109,6 +109,7 @@ Sample programs are built in several formats:
- Elsewhere: `ApplicationName.APPL`, `.rsrc/ApplicationName.APPL`, `.finf/ApplicationName.APPL` (BasiliskII/Sheepshaver compatible) - Elsewhere: `ApplicationName.APPL`, `.rsrc/ApplicationName.APPL`, `.finf/ApplicationName.APPL` (BasiliskII/Sheepshaver compatible)
- MacBinary files (`ApplicationName.bin`) - MacBinary files (`ApplicationName.bin`)
- Raw HFS disk image (`ApplicationName.dsk`, containing `ApplicationName`) - Raw HFS disk image (`ApplicationName.dsk`, containing `ApplicationName`)
- AppleDouble file pairs (`ApplicationName.ad`, `%ApplicationName.ad`, Executor compatible)
Look under `Retro68-build/build-target/` (68K), Look under `Retro68-build/build-target/` (68K),
`Retro68-build/build-target-ppc/` (PowerPC Classic) and `Retro68-build/build-target-ppc/` (PowerPC Classic) and

View File

@ -125,6 +125,24 @@ ResourceFile::~ResourceFile()
} }
static bool CheckAppleDouble(fs::path path, std::string prefix)
{
fs::path adPath = path.parent_path() / (prefix + path.filename().string());
fs::ifstream in(adPath);
if(in)
{
int magic1 = longword(in);
if(in && magic1 == 0x00051607)
{
int magic2 = longword(in);
if(in && magic2 == 0x00020000)
return true;
}
}
return false;
}
bool ResourceFile::assign(std::string pathstring, ResourceFile::Format f) bool ResourceFile::assign(std::string pathstring, ResourceFile::Format f)
{ {
this->pathstring = pathstring; this->pathstring = pathstring;
@ -140,24 +158,27 @@ bool ResourceFile::assign(std::string pathstring, ResourceFile::Format f)
format = Format::macbin; format = Format::macbin;
else if(path.extension() == ".dsk" || path.extension() == ".img") else if(path.extension() == ".dsk" || path.extension() == ".img")
format = Format::diskimage; format = Format::diskimage;
else if(path.filename().string().substr(0,2) == "._")
{
path = path.parent_path() / path.filename().string().substr(2);
format = Format::underscore_appledouble;
this->pathstring = path.string();
}
else if(path.filename().string()[0] == '%')
{
path = path.parent_path() / path.filename().string().substr(1);
format = Format::percent_appledouble;
this->pathstring = path.string();
}
//else if(fs::exists(rsrcPath)) //else if(fs::exists(rsrcPath))
// format = Format::basilisk; // format = Format::basilisk;
} }
if(format == Format::autodetect) if(format == Format::autodetect)
{ {
fs::path adPath = path.parent_path() / ("._" + path.filename().string()); if(CheckAppleDouble(path, "._"))
fs::ifstream in(adPath); format = Format::underscore_appledouble;
if(in) if(CheckAppleDouble(path, "%"))
{ format = Format::percent_appledouble;
int magic1 = longword(in);
if(in && magic1 == 0x00051607)
{
int magic2 = longword(in);
if(in && magic2 == 0x00020000)
format = Format::underscore_appledouble;
}
}
} }
if(format == Format::autodetect) if(format == Format::autodetect)
{ {
@ -264,12 +285,16 @@ bool ResourceFile::read()
} }
break; break;
case Format::underscore_appledouble: case Format::underscore_appledouble:
case Format::percent_appledouble:
{ {
fs::ifstream dataIn(path); fs::ifstream dataIn(path);
data = std::string(std::istreambuf_iterator<char>(dataIn), data = std::string(std::istreambuf_iterator<char>(dataIn),
std::istreambuf_iterator<char>()); std::istreambuf_iterator<char>());
fs::path adPath = path.parent_path() / ("._" + path.filename().string()); std::string prefix = format == Format::underscore_appledouble ?
"._" : "%";
fs::path adPath = path.parent_path() / (prefix + path.filename().string());
fs::ifstream in(adPath); fs::ifstream in(adPath);
if(longword(in) != 0x00051607) if(longword(in) != 0x00051607)
return false; return false;
@ -404,14 +429,53 @@ bool ResourceFile::write()
longword(out, 2); longword(out, 2);
longword(out, rsrcStart); longword(out, rsrcStart);
longword(out, finfStart - rsrcStart); longword(out, finfStart - rsrcStart);
longword(out, 3); longword(out, 9);
longword(out, finfStart); longword(out, finfStart);
longword(out, 32); longword(out, 32);
} }
break; break;
// TODO: case Format::underscore_appledouble // TODO: case Format::underscore_appledouble
case Format::underscore_appledouble:
case Format::percent_appledouble:
{
fs::ofstream dataOut(path);
dataOut << data;
std::string prefix = format == Format::underscore_appledouble ?
"._" : "%";
fs::path adPath = path.parent_path() / (prefix + path.filename().string());
fs::ofstream out(adPath);
longword(out, 0x00051607);
longword(out, 0x00020000);
for(int i = 0; i < 16; i++)
byte(out, 0);
word(out, 2);
std::streampos entries = out.tellp();
for(int i = 0; i < 2*3; i++)
longword(out, 0);
std::streampos rsrcStart = out.tellp();
resources.writeFork(out);
std::streampos finfStart = out.tellp();
ostype(out, type);
ostype(out, creator);
for(int i = 8; i < 32; i++)
byte(out, 0);
out.seekp(entries);
longword(out, 2);
longword(out, rsrcStart);
longword(out, finfStart - rsrcStart);
longword(out, 9);
longword(out, finfStart);
longword(out, 32);
}
break;
case Format::diskimage: case Format::diskimage:
{ {
std::ostringstream rsrcOut; std::ostringstream rsrcOut;

View File

@ -19,7 +19,7 @@ public:
basilisk, basilisk,
applesingle, applesingle,
underscore_appledouble, underscore_appledouble,
//appledouble percent_appledouble
}; };
ResourceFile(); ResourceFile();

View File

@ -73,12 +73,13 @@ function(add_application name)
set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}.flt) set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}.flt)
add_custom_command( add_custom_command(
OUTPUT ${name}.bin ${name}.APPL ${name}.dsk OUTPUT ${name}.bin ${name}.APPL ${name}.dsk ${name}.ad "%${name}.ad"
COMMAND ${REZ} ${REZ_FLAGS} COMMAND ${REZ} ${REZ_FLAGS}
${REZ_TEMPLATES_PATH}/Retro68APPL.r ${REZ_TEMPLATES_PATH}/Retro68APPL.r
-I${REZ_INCLUDE_PATH} -I${REZ_INCLUDE_PATH}
-DFLT_FILE_NAME="\\"${name}.flt\\"" -DFLT_FILE_NAME="\\"${name}.flt\\""
-o "${name}.bin" --cc "${name}.dsk" --cc "${name}.APPL" -o "${name}.bin" --cc "${name}.dsk" --cc "${name}.APPL"
--cc "%${name}.ad"
-t ${ARGS_TYPE} -c ${ARGS_CREATOR} -t ${ARGS_TYPE} -c ${ARGS_CREATOR}
${ARGS_MAKEAPPL_ARGS} ${ARGS_MAKEAPPL_ARGS}
DEPENDS ${name} ${rsrc_files}) DEPENDS ${name} ${rsrc_files})
@ -100,13 +101,14 @@ function(add_application name)
DEPENDS ${name}) DEPENDS ${name})
add_custom_command( add_custom_command(
OUTPUT ${name}.bin ${name}.APPL ${name}.dsk OUTPUT ${name}.bin ${name}.APPL ${name}.dsk ${name}.ad "%${name}.ad"
COMMAND ${REZ} COMMAND ${REZ}
${REZ_FLAGS} ${REZ_FLAGS}
${REZ_TEMPLATE} ${REZ_TEMPLATE}
-I${REZ_INCLUDE_PATH} -I${REZ_INCLUDE_PATH}
-DCFRAG_NAME="\\"${name}\\"" -DCFRAG_NAME="\\"${name}\\""
-o "${name}.bin" --cc "${name}.dsk" --cc "${name}.APPL" -o "${name}.bin" --cc "${name}.dsk" --cc "${name}.APPL"
--cc "%${name}.ad"
-t ${ARGS_TYPE} -c ${ARGS_CREATOR} -t ${ARGS_TYPE} -c ${ARGS_CREATOR}
--data ${name}.pef --data ${name}.pef
${ARGS_MAKEAPPL_ARGS} ${ARGS_MAKEAPPL_ARGS}