Change tabs to spaces, use Linux EOL
No substantative changes (unless the tabs-to-spaces messed something up).
This commit is contained in:
parent
683eb05a82
commit
090797a76f
|
@ -1,491 +1,491 @@
|
||||||
/*
|
/*
|
||||||
* CiderPress
|
* CiderPress
|
||||||
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
||||||
* See the file LICENSE for distribution terms.
|
* See the file LICENSE for distribution terms.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Convert from one image format to another.
|
* Convert from one image format to another.
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "../diskimg/DiskImg.h"
|
#include "../diskimg/DiskImg.h"
|
||||||
#include "../nufxlib/NufxLib.h"
|
#include "../nufxlib/NufxLib.h"
|
||||||
|
|
||||||
using namespace DiskImgLib;
|
using namespace DiskImgLib;
|
||||||
|
|
||||||
#define nil NULL
|
#define nil NULL
|
||||||
#define ASSERT assert
|
#define ASSERT assert
|
||||||
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
FILE* gLog = nil;
|
FILE* gLog = nil;
|
||||||
pid_t gPid = getpid();
|
pid_t gPid = getpid();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle a debug message from the DiskImg library.
|
* Handle a debug message from the DiskImg library.
|
||||||
*/
|
*/
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
MsgHandler(const char* file, int line, const char* msg)
|
MsgHandler(const char* file, int line, const char* msg)
|
||||||
{
|
{
|
||||||
ASSERT(file != nil);
|
ASSERT(file != nil);
|
||||||
ASSERT(msg != nil);
|
ASSERT(msg != nil);
|
||||||
|
|
||||||
fprintf(gLog, "%05u %s", gPid, msg);
|
fprintf(gLog, "%05u %s", gPid, msg);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Handle a global error message from the NufxLib library by shoving it
|
* Handle a global error message from the NufxLib library by shoving it
|
||||||
* through the DiskImgLib message function.
|
* through the DiskImgLib message function.
|
||||||
*/
|
*/
|
||||||
NuResult
|
NuResult
|
||||||
NufxErrorMsgHandler(NuArchive* /*pArchive*/, void* vErrorMessage)
|
NufxErrorMsgHandler(NuArchive* /*pArchive*/, void* vErrorMessage)
|
||||||
{
|
{
|
||||||
const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage;
|
const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage;
|
||||||
|
|
||||||
if (pErrorMessage->isDebug) {
|
if (pErrorMessage->isDebug) {
|
||||||
Global::PrintDebugMsg(pErrorMessage->file, pErrorMessage->line,
|
Global::PrintDebugMsg(pErrorMessage->file, pErrorMessage->line,
|
||||||
"<nufxlib> [D] %s\n", pErrorMessage->message);
|
"<nufxlib> [D] %s\n", pErrorMessage->message);
|
||||||
} else {
|
} else {
|
||||||
Global::PrintDebugMsg(pErrorMessage->file, pErrorMessage->line,
|
Global::PrintDebugMsg(pErrorMessage->file, pErrorMessage->line,
|
||||||
"<nufxlib> %s\n", pErrorMessage->message);
|
"<nufxlib> %s\n", pErrorMessage->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return kNuOK;
|
return kNuOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert one disk image to another.
|
* Convert one disk image to another.
|
||||||
*/
|
*/
|
||||||
DIError
|
DIError
|
||||||
Convert(const char* infile, const char* outfile)
|
Convert(const char* infile, const char* outfile)
|
||||||
{
|
{
|
||||||
DIError dierr = kDIErrNone;
|
DIError dierr = kDIErrNone;
|
||||||
DiskImg srcImg, dstImg;
|
DiskImg srcImg, dstImg;
|
||||||
const char* storageName = nil;
|
const char* storageName = nil;
|
||||||
|
|
||||||
printf("Converting in='%s' out='%s'\n", infile, outfile);
|
printf("Converting in='%s' out='%s'\n", infile, outfile);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the source image.
|
* Prepare the source image.
|
||||||
*/
|
*/
|
||||||
dierr = srcImg.OpenImage(infile, '/', true);
|
dierr = srcImg.OpenImage(infile, '/', true);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Unable to open disk image: %s.\n",
|
fprintf(stderr, "Unable to open disk image: %s.\n",
|
||||||
DiskImgLib::DIStrError(dierr));
|
DiskImgLib::DIStrError(dierr));
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
dierr = srcImg.AnalyzeImage();
|
dierr = srcImg.AnalyzeImage();
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Unable to determine source image format.\n");
|
fprintf(stderr, "Unable to determine source image format.\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!srcImg.GetHasBlocks() && !srcImg.GetHasSectors()) {
|
if (!srcImg.GetHasBlocks() && !srcImg.GetHasSectors()) {
|
||||||
/* add nibble tracks someday */
|
/* add nibble tracks someday */
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Sorry, only block- or sector-addressable images allowed.\n");
|
"Sorry, only block- or sector-addressable images allowed.\n");
|
||||||
dierr = kDIErrUnsupportedPhysicalFmt;
|
dierr = kDIErrUnsupportedPhysicalFmt;
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if (srcImg.GetHasBlocks()) {
|
if (srcImg.GetHasBlocks()) {
|
||||||
assert(srcImg.GetNumBlocks() > 0);
|
assert(srcImg.GetNumBlocks() > 0);
|
||||||
} else {
|
} else {
|
||||||
assert(srcImg.GetNumTracks() > 0);
|
assert(srcImg.GetNumTracks() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) {
|
if (srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) {
|
||||||
fprintf(stderr, "(QUERY) don't know sector order\n");
|
fprintf(stderr, "(QUERY) don't know sector order\n");
|
||||||
dierr = kDIErrFilesystemNotFound;
|
dierr = kDIErrFilesystemNotFound;
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
storageName = "MyHappyDisk";
|
storageName = "MyHappyDisk";
|
||||||
|
|
||||||
/* force the access to be ProDOS-ordered */
|
/* force the access to be ProDOS-ordered */
|
||||||
dierr = srcImg.OverrideFormat(srcImg.GetPhysicalFormat(),
|
dierr = srcImg.OverrideFormat(srcImg.GetPhysicalFormat(),
|
||||||
DiskImg::kFormatGenericProDOSOrd, srcImg.GetSectorOrder());
|
DiskImg::kFormatGenericProDOSOrd, srcImg.GetSectorOrder());
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Couldn't switch to generic ProDOS: %s.\n",
|
fprintf(stderr, "Couldn't switch to generic ProDOS: %s.\n",
|
||||||
DiskImgLib::DIStrError(dierr));
|
DiskImgLib::DIStrError(dierr));
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* transfer the DOS volume num, if one was set */
|
/* transfer the DOS volume num, if one was set */
|
||||||
printf("DOS volume number set to %d\n", srcImg.GetDOSVolumeNum());
|
printf("DOS volume number set to %d\n", srcImg.GetDOSVolumeNum());
|
||||||
dstImg.SetDOSVolumeNum(srcImg.GetDOSVolumeNum());
|
dstImg.SetDOSVolumeNum(srcImg.GetDOSVolumeNum());
|
||||||
|
|
||||||
const DiskImg::NibbleDescr* pNibbleDescr;
|
const DiskImg::NibbleDescr* pNibbleDescr;
|
||||||
pNibbleDescr = nil;
|
pNibbleDescr = nil;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the destination image.
|
* Prepare the destination image.
|
||||||
*
|
*
|
||||||
* We *always* use DiskImg::kFormatGenericProDOSOrd here, because it
|
* We *always* use DiskImg::kFormatGenericProDOSOrd here, because it
|
||||||
* must match up with what we selected above.
|
* must match up with what we selected above.
|
||||||
*
|
*
|
||||||
* We could enable "skipFormat" on all of these but the nibble images,
|
* We could enable "skipFormat" on all of these but the nibble images,
|
||||||
* but we go ahead and set it to "false" on all of them just for fun.
|
* but we go ahead and set it to "false" on all of them just for fun.
|
||||||
*/
|
*/
|
||||||
switch (18) {
|
switch (18) {
|
||||||
case 0:
|
case 0:
|
||||||
/* 16-sector nibble image, by blocks */
|
/* 16-sector nibble image, by blocks */
|
||||||
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatNib525_6656,
|
DiskImg::kPhysicalFormatNib525_6656,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderPhysical,
|
DiskImg::kSectorOrderPhysical,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* 16-sector nibble image, by tracks/sectors */
|
/* 16-sector nibble image, by tracks/sectors */
|
||||||
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatNib525_6656,
|
DiskImg::kPhysicalFormatNib525_6656,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderPhysical,
|
DiskImg::kSectorOrderPhysical,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
35, 16,
|
35, 16,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
/* 16-sector NB2 nibble image, by tracks/sectors */
|
/* 16-sector NB2 nibble image, by tracks/sectors */
|
||||||
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatNib525_6384,
|
DiskImg::kPhysicalFormatNib525_6384,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderPhysical,
|
DiskImg::kSectorOrderPhysical,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
35, 16,
|
35, 16,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
/* 13-sector nibble image, by tracks/sectors */
|
/* 13-sector nibble image, by tracks/sectors */
|
||||||
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS32Std);
|
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS32Std);
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatNib525_6656,
|
DiskImg::kPhysicalFormatNib525_6656,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderPhysical,
|
DiskImg::kSectorOrderPhysical,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
35, 13,
|
35, 13,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
/* 16-sector nb2 image, by tracks/sectors */
|
/* 16-sector nb2 image, by tracks/sectors */
|
||||||
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatNib525_6384,
|
DiskImg::kPhysicalFormatNib525_6384,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderPhysical,
|
DiskImg::kSectorOrderPhysical,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
35, 16,
|
35, 16,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* sector image, by blocks, ProDOS order */
|
/* sector image, by blocks, ProDOS order */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
/* sector image, by blocks, DOS order */
|
/* sector image, by blocks, DOS order */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderDOS,
|
DiskImg::kSectorOrderDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
/* sector image, by blocks, ProDOS order, Sim2e */
|
/* sector image, by blocks, ProDOS order, Sim2e */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatSim2eHDV,
|
DiskImg::kFileFormatSim2eHDV,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
/* odd-length HUGE sector image, by blocks */
|
/* odd-length HUGE sector image, by blocks */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
65535,
|
65535,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
/* sector image, by blocks, physical order, with gzip */
|
/* sector image, by blocks, physical order, with gzip */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatGzip,
|
DiskImg::kOuterFormatGzip,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderPhysical,
|
DiskImg::kSectorOrderPhysical,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
/* sector image, by blocks, ProDOS order, with gzip */
|
/* sector image, by blocks, ProDOS order, with gzip */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatGzip,
|
DiskImg::kOuterFormatGzip,
|
||||||
DiskImg::kFileFormatSim2eHDV,
|
DiskImg::kFileFormatSim2eHDV,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
/* sector image, by blocks, ProDOS order, 2MG */
|
/* sector image, by blocks, ProDOS order, 2MG */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormat2MG,
|
DiskImg::kFileFormat2MG,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
/* 16-sector nibble image, by tracks/sectors, 2MG */
|
/* 16-sector nibble image, by tracks/sectors, 2MG */
|
||||||
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormat2MG,
|
DiskImg::kFileFormat2MG,
|
||||||
DiskImg::kPhysicalFormatNib525_6656,
|
DiskImg::kPhysicalFormatNib525_6656,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderPhysical,
|
DiskImg::kSectorOrderPhysical,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
35, 16,
|
35, 16,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
/* 16-sector nibble image, by tracks/sectors, 2MG, gzip */
|
/* 16-sector nibble image, by tracks/sectors, 2MG, gzip */
|
||||||
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatGzip,
|
DiskImg::kOuterFormatGzip,
|
||||||
DiskImg::kFileFormat2MG,
|
DiskImg::kFileFormat2MG,
|
||||||
DiskImg::kPhysicalFormatNib525_6656,
|
DiskImg::kPhysicalFormatNib525_6656,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderPhysical,
|
DiskImg::kSectorOrderPhysical,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
35, 16,
|
35, 16,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
/* sector image, by blocks, for DC42 (800K only) */
|
/* sector image, by blocks, for DC42 (800K only) */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatDiskCopy42,
|
DiskImg::kFileFormatDiskCopy42,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
/* sector image, by blocks, for NuFX */
|
/* sector image, by blocks, for NuFX */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatNuFX,
|
DiskImg::kFileFormatNuFX,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
/* sector image, by blocks, for DDD */
|
/* sector image, by blocks, for DDD */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatDDD,
|
DiskImg::kFileFormatDDD,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderDOS,
|
DiskImg::kSectorOrderDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 17:
|
case 17:
|
||||||
/* sector image, by blocks, ProDOS order, stored in ZIP (.po.zip) */
|
/* sector image, by blocks, ProDOS order, stored in ZIP (.po.zip) */
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatZip,
|
DiskImg::kOuterFormatZip,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
srcImg.GetNumBlocks(),
|
srcImg.GetNumBlocks(),
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 18:
|
||||||
/* 13-sector nibble image, by tracks/sectors */
|
/* 13-sector nibble image, by tracks/sectors */
|
||||||
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
pNibbleDescr= DiskImg::GetStdNibbleDescr(DiskImg::kNibbleDescrDOS33Std);
|
||||||
dierr = dstImg.CreateImage(outfile, storageName,
|
dierr = dstImg.CreateImage(outfile, storageName,
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
pNibbleDescr,
|
pNibbleDescr,
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
35, 13,
|
35, 13,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "UNEXPECTED NUMBER\n");
|
fprintf(stderr, "UNEXPECTED NUMBER\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Couldn't create new image file '%s': %s.\n",
|
fprintf(stderr, "Couldn't create new image file '%s': %s.\n",
|
||||||
outfile, DiskImgLib::DIStrError(dierr));
|
outfile, DiskImgLib::DIStrError(dierr));
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy blocks or sectors from source to destination.
|
* Copy blocks or sectors from source to destination.
|
||||||
*/
|
*/
|
||||||
if (srcImg.GetHasBlocks()) {
|
if (srcImg.GetHasBlocks()) {
|
||||||
int numBlocks;
|
int numBlocks;
|
||||||
numBlocks = srcImg.GetNumBlocks();
|
numBlocks = srcImg.GetNumBlocks();
|
||||||
if (dstImg.GetNumBlocks() < srcImg.GetNumBlocks())
|
if (dstImg.GetNumBlocks() < srcImg.GetNumBlocks())
|
||||||
numBlocks = dstImg.GetNumBlocks();
|
numBlocks = dstImg.GetNumBlocks();
|
||||||
printf("Copying %d blocks\n", numBlocks);
|
printf("Copying %d blocks\n", numBlocks);
|
||||||
|
|
||||||
unsigned char blkBuf[512];
|
unsigned char blkBuf[512];
|
||||||
for (int block = 0; block < numBlocks; block++) {
|
for (int block = 0; block < numBlocks; block++) {
|
||||||
dierr = srcImg.ReadBlock(block, blkBuf);
|
dierr = srcImg.ReadBlock(block, blkBuf);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: ReadBlock failed (err=%d)\n", dierr);
|
fprintf(stderr, "ERROR: ReadBlock failed (err=%d)\n", dierr);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
dierr = dstImg.WriteBlock(block, blkBuf);
|
dierr = dstImg.WriteBlock(block, blkBuf);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: WriteBlock failed (err=%d)\n", dierr);
|
fprintf(stderr, "ERROR: WriteBlock failed (err=%d)\n", dierr);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int numTracks, numSectPerTrack;
|
int numTracks, numSectPerTrack;
|
||||||
numTracks = srcImg.GetNumTracks();
|
numTracks = srcImg.GetNumTracks();
|
||||||
numSectPerTrack = srcImg.GetNumSectPerTrack();
|
numSectPerTrack = srcImg.GetNumSectPerTrack();
|
||||||
if (dstImg.GetNumTracks() < srcImg.GetNumTracks())
|
if (dstImg.GetNumTracks() < srcImg.GetNumTracks())
|
||||||
numTracks = dstImg.GetNumTracks();
|
numTracks = dstImg.GetNumTracks();
|
||||||
if (dstImg.GetNumSectPerTrack() < srcImg.GetNumSectPerTrack())
|
if (dstImg.GetNumSectPerTrack() < srcImg.GetNumSectPerTrack())
|
||||||
numSectPerTrack = dstImg.GetNumSectPerTrack();
|
numSectPerTrack = dstImg.GetNumSectPerTrack();
|
||||||
printf("Copying %d tracks of %d sectors\n", numTracks, numSectPerTrack);
|
printf("Copying %d tracks of %d sectors\n", numTracks, numSectPerTrack);
|
||||||
|
|
||||||
unsigned char sctBuf[256];
|
unsigned char sctBuf[256];
|
||||||
for (int track = 0; track < numTracks; track++) {
|
for (int track = 0; track < numTracks; track++) {
|
||||||
for (int sector = 0; sector < numSectPerTrack; sector++) {
|
for (int sector = 0; sector < numSectPerTrack; sector++) {
|
||||||
dierr = srcImg.ReadTrackSector(track, sector, sctBuf);
|
dierr = srcImg.ReadTrackSector(track, sector, sctBuf);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"WARNING: ReadTrackSector failed on T=%d S=%d (err=%d)\n",
|
"WARNING: ReadTrackSector failed on T=%d S=%d (err=%d)\n",
|
||||||
track, sector, dierr);
|
track, sector, dierr);
|
||||||
dierr = kDIErrNone; // allow bad blocks
|
dierr = kDIErrNone; // allow bad blocks
|
||||||
memset(sctBuf, 0, sizeof(sctBuf));
|
memset(sctBuf, 0, sizeof(sctBuf));
|
||||||
}
|
}
|
||||||
dierr = dstImg.WriteTrackSector(track, sector, sctBuf);
|
dierr = dstImg.WriteTrackSector(track, sector, sctBuf);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ERROR: WriteBlock failed on T=%d S=%d (err=%d)\n",
|
"ERROR: WriteBlock failed on T=%d S=%d (err=%d)\n",
|
||||||
track, sector, dierr);
|
track, sector, dierr);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dierr = srcImg.CloseImage();
|
dierr = srcImg.CloseImage();
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: srcImg close failed?!\n");
|
fprintf(stderr, "ERROR: srcImg close failed?!\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
dierr = dstImg.CloseImage();
|
dierr = dstImg.CloseImage();
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: dstImg close failed (err=%d)\n", dierr);
|
fprintf(stderr, "ERROR: dstImg close failed (err=%d)\n", dierr);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(dierr == kDIErrNone);
|
assert(dierr == kDIErrNone);
|
||||||
bail:
|
bail:
|
||||||
return dierr;
|
return dierr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process every argument.
|
* Process every argument.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
main(int argc, char** argv)
|
main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
const char* kLogFile = "iconv-log.txt";
|
const char* kLogFile = "iconv-log.txt";
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
fprintf(stderr, "%s: infile outfile\n", argv[0]);
|
fprintf(stderr, "%s: infile outfile\n", argv[0]);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
gLog = fopen(kLogFile, "w");
|
gLog = fopen(kLogFile, "w");
|
||||||
if (gLog == nil) {
|
if (gLog == nil) {
|
||||||
fprintf(stderr, "ERROR: unable to open log file\n");
|
fprintf(stderr, "ERROR: unable to open log file\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Image Converter for Linux v1.0\n");
|
printf("Image Converter for Linux v1.0\n");
|
||||||
printf("Copyright (C) 2014 by faddenSoft. All rights reserved.\n");
|
printf("Copyright (C) 2014 by faddenSoft. All rights reserved.\n");
|
||||||
int32_t major, minor, bug;
|
int32_t major, minor, bug;
|
||||||
Global::GetVersion(&major, &minor, &bug);
|
Global::GetVersion(&major, &minor, &bug);
|
||||||
printf("Linked against DiskImg library v%d.%d.%d\n",
|
printf("Linked against DiskImg library v%d.%d.%d\n",
|
||||||
major, minor, bug);
|
major, minor, bug);
|
||||||
printf("Log file is '%s'\n", kLogFile);
|
printf("Log file is '%s'\n", kLogFile);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
Global::SetDebugMsgHandler(MsgHandler);
|
Global::SetDebugMsgHandler(MsgHandler);
|
||||||
Global::AppInit();
|
Global::AppInit();
|
||||||
|
|
||||||
NuSetGlobalErrorMessageHandler(NufxErrorMsgHandler);
|
NuSetGlobalErrorMessageHandler(NufxErrorMsgHandler);
|
||||||
|
|
||||||
Convert(argv[1], argv[2]);
|
Convert(argv[1], argv[2]);
|
||||||
|
|
||||||
Global::AppCleanup();
|
Global::AppCleanup();
|
||||||
fclose(gLog);
|
fclose(gLog);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,220 +1,220 @@
|
||||||
/*
|
/*
|
||||||
* CiderPress
|
* CiderPress
|
||||||
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
||||||
* See the file LICENSE for distribution terms.
|
* See the file LICENSE for distribution terms.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Get a file from a disk image.
|
* Get a file from a disk image.
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "../diskimg/DiskImg.h"
|
#include "../diskimg/DiskImg.h"
|
||||||
|
|
||||||
using namespace DiskImgLib;
|
using namespace DiskImgLib;
|
||||||
|
|
||||||
#define nil NULL
|
#define nil NULL
|
||||||
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals.
|
* Globals.
|
||||||
*/
|
*/
|
||||||
FILE* gLog = nil;
|
FILE* gLog = nil;
|
||||||
pid_t gPid = getpid();
|
pid_t gPid = getpid();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Show usage info.
|
* Show usage info.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Usage(const char* argv0)
|
Usage(const char* argv0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s image-filename file\n", argv0);
|
fprintf(stderr, "Usage: %s image-filename file\n", argv0);
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "The file will be written to stdout.\n");
|
fprintf(stderr, "The file will be written to stdout.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy a file from "src" to "dst".
|
* Copy a file from "src" to "dst".
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
CopyFile(A2FileDescr* src, FILE* dst)
|
CopyFile(A2FileDescr* src, FILE* dst)
|
||||||
{
|
{
|
||||||
DIError dierr;
|
DIError dierr;
|
||||||
size_t actual;
|
size_t actual;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
dierr = src->Read(buf, sizeof(buf), &actual);
|
dierr = src->Read(buf, sizeof(buf), &actual);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Error: read failed: %s\n", DIStrError(dierr));
|
fprintf(stderr, "Error: read failed: %s\n", DIStrError(dierr));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actual == 0) // EOF hit
|
if (actual == 0) // EOF hit
|
||||||
break;
|
break;
|
||||||
|
|
||||||
fwrite(buf, 1, actual, dst);
|
fwrite(buf, 1, actual, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract the named file from the specified image.
|
* Extract the named file from the specified image.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
Process(const char* imageName, const char* wantedFileName)
|
Process(const char* imageName, const char* wantedFileName)
|
||||||
{
|
{
|
||||||
DIError dierr;
|
DIError dierr;
|
||||||
DiskImg diskImg;
|
DiskImg diskImg;
|
||||||
DiskFS* pDiskFS = nil;
|
DiskFS* pDiskFS = nil;
|
||||||
A2File* pFile = nil;
|
A2File* pFile = nil;
|
||||||
A2FileDescr* pDescr = nil;
|
A2FileDescr* pDescr = nil;
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
/* open read-only */
|
/* open read-only */
|
||||||
dierr = diskImg.OpenImage(imageName, '/', true);
|
dierr = diskImg.OpenImage(imageName, '/', true);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Unable to open '%s': %s\n", imageName,
|
fprintf(stderr, "Unable to open '%s': %s\n", imageName,
|
||||||
DIStrError(dierr));
|
DIStrError(dierr));
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* figure out the format */
|
/* figure out the format */
|
||||||
dierr = diskImg.AnalyzeImage();
|
dierr = diskImg.AnalyzeImage();
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Analysis of '%s' failed: %s\n", imageName,
|
fprintf(stderr, "Analysis of '%s' failed: %s\n", imageName,
|
||||||
DIStrError(dierr));
|
DIStrError(dierr));
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* recognized? */
|
/* recognized? */
|
||||||
if (diskImg.GetFSFormat() == DiskImg::kFormatUnknown ||
|
if (diskImg.GetFSFormat() == DiskImg::kFormatUnknown ||
|
||||||
diskImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown)
|
diskImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Unable to identify filesystem on '%s'\n", imageName);
|
fprintf(stderr, "Unable to identify filesystem on '%s'\n", imageName);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create an appropriate DiskFS object */
|
/* create an appropriate DiskFS object */
|
||||||
pDiskFS = diskImg.OpenAppropriateDiskFS();
|
pDiskFS = diskImg.OpenAppropriateDiskFS();
|
||||||
if (pDiskFS == nil) {
|
if (pDiskFS == nil) {
|
||||||
/* unknown FS should've been caught above! */
|
/* unknown FS should've been caught above! */
|
||||||
assert(false);
|
assert(false);
|
||||||
fprintf(stderr, "Format of '%s' not recognized.\n", imageName);
|
fprintf(stderr, "Format of '%s' not recognized.\n", imageName);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go ahead and load up volumes mounted inside volumes */
|
/* go ahead and load up volumes mounted inside volumes */
|
||||||
pDiskFS->SetScanForSubVolumes(DiskFS::kScanSubEnabled);
|
pDiskFS->SetScanForSubVolumes(DiskFS::kScanSubEnabled);
|
||||||
|
|
||||||
/* do a full scan */
|
/* do a full scan */
|
||||||
dierr = pDiskFS->Initialize(&diskImg, DiskFS::kInitFull);
|
dierr = pDiskFS->Initialize(&diskImg, DiskFS::kInitFull);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Error reading list of files from disk: %s\n",
|
fprintf(stderr, "Error reading list of files from disk: %s\n",
|
||||||
DIStrError(dierr));
|
DIStrError(dierr));
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the file. This comes out of a list of entries, so don't
|
* Find the file. This comes out of a list of entries, so don't
|
||||||
* delete "pFile" when we're done.
|
* delete "pFile" when we're done.
|
||||||
*/
|
*/
|
||||||
pFile = pDiskFS->GetFileByName(wantedFileName);
|
pFile = pDiskFS->GetFileByName(wantedFileName);
|
||||||
if (pFile == nil) {
|
if (pFile == nil) {
|
||||||
fprintf(stderr, "File '%s' not found in '%s'\n", wantedFileName,
|
fprintf(stderr, "File '%s' not found in '%s'\n", wantedFileName,
|
||||||
imageName);
|
imageName);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the file read-only.
|
* Open the file read-only.
|
||||||
*/
|
*/
|
||||||
dierr = pFile->Open(&pDescr, true);
|
dierr = pFile->Open(&pDescr, true);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "Error opening '%s': %s\n", wantedFileName,
|
fprintf(stderr, "Error opening '%s': %s\n", wantedFileName,
|
||||||
DIStrError(dierr));
|
DIStrError(dierr));
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the file to stdout.
|
* Copy the file to stdout.
|
||||||
*/
|
*/
|
||||||
result = CopyFile(pDescr, stdout);
|
result = CopyFile(pDescr, stdout);
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
if (pDescr != nil) {
|
if (pDescr != nil) {
|
||||||
pDescr->Close();
|
pDescr->Close();
|
||||||
//delete pDescr; -- don't do this (double free)
|
//delete pDescr; -- don't do this (double free)
|
||||||
}
|
}
|
||||||
delete pDiskFS;
|
delete pDiskFS;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle a debug message from the DiskImg library.
|
* Handle a debug message from the DiskImg library.
|
||||||
*/
|
*/
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
MsgHandler(const char* file, int line, const char* msg)
|
MsgHandler(const char* file, int line, const char* msg)
|
||||||
{
|
{
|
||||||
assert(file != nil);
|
assert(file != nil);
|
||||||
assert(msg != nil);
|
assert(msg != nil);
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
fprintf(gLog, "%05u %s", gPid, msg);
|
fprintf(gLog, "%05u %s", gPid, msg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process args.
|
* Process args.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
main(int argc, char** argv)
|
main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
const char* kLogFile = "makedisk-log.txt";
|
const char* kLogFile = "makedisk-log.txt";
|
||||||
gLog = fopen(kLogFile, "w");
|
gLog = fopen(kLogFile, "w");
|
||||||
if (gLog == nil) {
|
if (gLog == nil) {
|
||||||
fprintf(stderr, "ERROR: unable to open log file\n");
|
fprintf(stderr, "ERROR: unable to open log file\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
fprintf(stderr, "Log file is '%s'\n", kLogFile);
|
fprintf(stderr, "Log file is '%s'\n", kLogFile);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Global::SetDebugMsgHandler(MsgHandler);
|
Global::SetDebugMsgHandler(MsgHandler);
|
||||||
Global::AppInit();
|
Global::AppInit();
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
Usage(argv[0]);
|
Usage(argv[0]);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* imageName;
|
const char* imageName;
|
||||||
const char* getFileName;
|
const char* getFileName;
|
||||||
|
|
||||||
argv++;
|
argv++;
|
||||||
imageName = *argv++;
|
imageName = *argv++;
|
||||||
getFileName = *argv++;
|
getFileName = *argv++;
|
||||||
argc -= 2;
|
argc -= 2;
|
||||||
|
|
||||||
if (Process(imageName, getFileName) == 0)
|
if (Process(imageName, getFileName) == 0)
|
||||||
fprintf(stderr, "Success!\n");
|
fprintf(stderr, "Success!\n");
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Failed.\n");
|
fprintf(stderr, "Failed.\n");
|
||||||
|
|
||||||
Global::AppCleanup();
|
Global::AppCleanup();
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
fclose(gLog);
|
fclose(gLog);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1780
linux/MDC.cpp
1780
linux/MDC.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,388 +1,388 @@
|
||||||
/*
|
/*
|
||||||
* CiderPress
|
* CiderPress
|
||||||
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
||||||
* See the file LICENSE for distribution terms.
|
* See the file LICENSE for distribution terms.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Create a blank disk image, format it, and copy some files onto it.
|
* Create a blank disk image, format it, and copy some files onto it.
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "../diskimg/DiskImg.h"
|
#include "../diskimg/DiskImg.h"
|
||||||
|
|
||||||
using namespace DiskImgLib;
|
using namespace DiskImgLib;
|
||||||
|
|
||||||
#define nil NULL
|
#define nil NULL
|
||||||
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals.
|
* Globals.
|
||||||
*/
|
*/
|
||||||
FILE* gLog = nil;
|
FILE* gLog = nil;
|
||||||
pid_t gPid = getpid();
|
pid_t gPid = getpid();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Show usage info.
|
* Show usage info.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Usage(const char* argv0)
|
Usage(const char* argv0)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: %s {dos|prodos|pascal} size image-filename.po input-file1 ...\n",
|
"Usage: %s {dos|prodos|pascal} size image-filename.po input-file1 ...\n",
|
||||||
argv0);
|
argv0);
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Example: makedisk prodos 800k foo.po file1.txt file2.txt\n");
|
fprintf(stderr, "Example: makedisk prodos 800k foo.po file1.txt file2.txt\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a ProDOS-ordered disk image.
|
* Create a ProDOS-ordered disk image.
|
||||||
*
|
*
|
||||||
* Returns a DiskImg pointer on success, or nil on failure.
|
* Returns a DiskImg pointer on success, or nil on failure.
|
||||||
*/
|
*/
|
||||||
DiskImg*
|
DiskImg*
|
||||||
CreateDisk(const char* fileName, long blockCount)
|
CreateDisk(const char* fileName, long blockCount)
|
||||||
{
|
{
|
||||||
DIError dierr;
|
DIError dierr;
|
||||||
DiskImg* pDiskImg = nil;
|
DiskImg* pDiskImg = nil;
|
||||||
|
|
||||||
pDiskImg = new DiskImg;
|
pDiskImg = new DiskImg;
|
||||||
dierr = pDiskImg->CreateImage(
|
dierr = pDiskImg->CreateImage(
|
||||||
fileName,
|
fileName,
|
||||||
nil, // storageName
|
nil, // storageName
|
||||||
DiskImg::kOuterFormatNone,
|
DiskImg::kOuterFormatNone,
|
||||||
DiskImg::kFileFormatUnadorned,
|
DiskImg::kFileFormatUnadorned,
|
||||||
DiskImg::kPhysicalFormatSectors,
|
DiskImg::kPhysicalFormatSectors,
|
||||||
nil, // pNibbleDescr
|
nil, // pNibbleDescr
|
||||||
DiskImg::kSectorOrderProDOS,
|
DiskImg::kSectorOrderProDOS,
|
||||||
DiskImg::kFormatGenericProDOSOrd,
|
DiskImg::kFormatGenericProDOSOrd,
|
||||||
blockCount,
|
blockCount,
|
||||||
true); // no need to format the image
|
true); // no need to format the image
|
||||||
|
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: CreateImage failed: %s\n",
|
fprintf(stderr, "ERROR: CreateImage failed: %s\n",
|
||||||
DIStrError(dierr));
|
DIStrError(dierr));
|
||||||
delete pDiskImg;
|
delete pDiskImg;
|
||||||
pDiskImg = nil;
|
pDiskImg = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pDiskImg;
|
return pDiskImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy files to the disk.
|
* Copy files to the disk.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
CopyFiles(DiskFS* pDiskFS, int argc, char** argv)
|
CopyFiles(DiskFS* pDiskFS, int argc, char** argv)
|
||||||
{
|
{
|
||||||
DIError dierr;
|
DIError dierr;
|
||||||
DiskFS::CreateParms parms;
|
DiskFS::CreateParms parms;
|
||||||
A2File* pNewFile;
|
A2File* pNewFile;
|
||||||
|
|
||||||
struct CreateParms {
|
struct CreateParms {
|
||||||
const char* pathName; // full pathname
|
const char* pathName; // full pathname
|
||||||
char fssep;
|
char fssep;
|
||||||
int storageType; // determines normal, subdir, or forked
|
int storageType; // determines normal, subdir, or forked
|
||||||
long fileType;
|
long fileType;
|
||||||
long auxType;
|
long auxType;
|
||||||
int access;
|
int access;
|
||||||
time_t createWhen;
|
time_t createWhen;
|
||||||
time_t modWhen;
|
time_t modWhen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
while (argc--) {
|
while (argc--) {
|
||||||
printf("+++ Adding '%s'\n", *argv);
|
printf("+++ Adding '%s'\n", *argv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use external pathname as internal pathname. This isn't quite
|
* Use external pathname as internal pathname. This isn't quite
|
||||||
* right, since things like "../" will end up getting converted
|
* right, since things like "../" will end up getting converted
|
||||||
* to something we don't want, but it'll do for now.
|
* to something we don't want, but it'll do for now.
|
||||||
*/
|
*/
|
||||||
parms.pathName = *argv;
|
parms.pathName = *argv;
|
||||||
parms.fssep = '/'; // UNIX fssep
|
parms.fssep = '/'; // UNIX fssep
|
||||||
parms.storageType = DiskFS::kStorageSeedling; // not forked, not dir
|
parms.storageType = DiskFS::kStorageSeedling; // not forked, not dir
|
||||||
parms.fileType = 0; // NON
|
parms.fileType = 0; // NON
|
||||||
parms.auxType = 0; // $0000
|
parms.auxType = 0; // $0000
|
||||||
parms.access = DiskFS::kFileAccessUnlocked;
|
parms.access = DiskFS::kFileAccessUnlocked;
|
||||||
parms.createWhen = time(nil);
|
parms.createWhen = time(nil);
|
||||||
parms.modWhen = time(nil);
|
parms.modWhen = time(nil);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new, empty file. The "pNewFile" pointer does not belong
|
* Create a new, empty file. The "pNewFile" pointer does not belong
|
||||||
* to us, so we should not delete it later, or try to access it
|
* to us, so we should not delete it later, or try to access it
|
||||||
* after the underlying file is deleted.
|
* after the underlying file is deleted.
|
||||||
*/
|
*/
|
||||||
dierr = pDiskFS->CreateFile(&parms, &pNewFile);
|
dierr = pDiskFS->CreateFile(&parms, &pNewFile);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: unable to create '%s': %s\n",
|
fprintf(stderr, "ERROR: unable to create '%s': %s\n",
|
||||||
*argv, DIStrError(dierr));
|
*argv, DIStrError(dierr));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load the input file into memory.
|
* Load the input file into memory.
|
||||||
*/
|
*/
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
char* buf;
|
char* buf;
|
||||||
long len;
|
long len;
|
||||||
|
|
||||||
fp = fopen(*argv, "r");
|
fp = fopen(*argv, "r");
|
||||||
if (fp == nil) {
|
if (fp == nil) {
|
||||||
fprintf(stderr, "ERROR: unable to open input file '%s': %s\n",
|
fprintf(stderr, "ERROR: unable to open input file '%s': %s\n",
|
||||||
*argv, strerror(errno));
|
*argv, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fseek(fp, 0, SEEK_END) != 0) {
|
if (fseek(fp, 0, SEEK_END) != 0) {
|
||||||
fprintf(stderr, "ERROR: unable to seek input file '%s': %s\n",
|
fprintf(stderr, "ERROR: unable to seek input file '%s': %s\n",
|
||||||
*argv, strerror(errno));
|
*argv, strerror(errno));
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ftell(fp);
|
len = ftell(fp);
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
|
|
||||||
buf = new char[len];
|
buf = new char[len];
|
||||||
if (buf == nil) {
|
if (buf == nil) {
|
||||||
fprintf(stderr, "ERROR: unable to alloc %ld bytes\n", len);
|
fprintf(stderr, "ERROR: unable to alloc %ld bytes\n", len);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fread(buf, len, 1, fp) != 1) {
|
if (fread(buf, len, 1, fp) != 1) {
|
||||||
fprintf(stderr, "ERROR: fread of %ld bytes from '%s' failed: %s\n",
|
fprintf(stderr, "ERROR: fread of %ld bytes from '%s' failed: %s\n",
|
||||||
len, *argv, strerror(errno));
|
len, *argv, strerror(errno));
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write the buffer to the disk image.
|
* Write the buffer to the disk image.
|
||||||
*
|
*
|
||||||
* The A2FileDescr object is created by "Open" and deleted by
|
* The A2FileDescr object is created by "Open" and deleted by
|
||||||
* "Close".
|
* "Close".
|
||||||
*/
|
*/
|
||||||
A2FileDescr* pFD;
|
A2FileDescr* pFD;
|
||||||
|
|
||||||
dierr = pNewFile->Open(&pFD, true);
|
dierr = pNewFile->Open(&pFD, true);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: unable to open new file '%s': %s\n",
|
fprintf(stderr, "ERROR: unable to open new file '%s': %s\n",
|
||||||
pNewFile->GetPathName(), DIStrError(dierr));
|
pNewFile->GetPathName(), DIStrError(dierr));
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dierr = pFD->Write(buf, len);
|
dierr = pFD->Write(buf, len);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: failed writing to '%s': %s\n",
|
fprintf(stderr, "ERROR: failed writing to '%s': %s\n",
|
||||||
pNewFile->GetPathName(), DIStrError(dierr));
|
pNewFile->GetPathName(), DIStrError(dierr));
|
||||||
pFD->Close();
|
pFD->Close();
|
||||||
pDiskFS->DeleteFile(pNewFile);
|
pDiskFS->DeleteFile(pNewFile);
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
|
|
||||||
dierr = pFD->Close();
|
dierr = pFD->Close();
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: failed while closing '%s': %s\n",
|
fprintf(stderr, "ERROR: failed while closing '%s': %s\n",
|
||||||
pNewFile->GetPathName(), DIStrError(dierr));
|
pNewFile->GetPathName(), DIStrError(dierr));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On to the next file.
|
* On to the next file.
|
||||||
*/
|
*/
|
||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process the request.
|
* Process the request.
|
||||||
*
|
*
|
||||||
* Returns 0 on success, -1 on failure.
|
* Returns 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
Process(const char* formatName, const char* sizeStr,
|
Process(const char* formatName, const char* sizeStr,
|
||||||
const char* outputFileName, int argc, char** argv)
|
const char* outputFileName, int argc, char** argv)
|
||||||
{
|
{
|
||||||
DiskImg::FSFormat format;
|
DiskImg::FSFormat format;
|
||||||
long blockCount;
|
long blockCount;
|
||||||
|
|
||||||
if (strcasecmp(formatName, "dos") == 0)
|
if (strcasecmp(formatName, "dos") == 0)
|
||||||
format = DiskImg::kFormatDOS33;
|
format = DiskImg::kFormatDOS33;
|
||||||
else if (strcasecmp(formatName, "prodos") == 0)
|
else if (strcasecmp(formatName, "prodos") == 0)
|
||||||
format = DiskImg::kFormatProDOS;
|
format = DiskImg::kFormatProDOS;
|
||||||
else if (strcasecmp(formatName, "pascal") == 0)
|
else if (strcasecmp(formatName, "pascal") == 0)
|
||||||
format = DiskImg::kFormatPascal;
|
format = DiskImg::kFormatPascal;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "ERROR: invalid format '%s'\n", formatName);
|
fprintf(stderr, "ERROR: invalid format '%s'\n", formatName);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(sizeStr, "140k") == 0)
|
if (strcasecmp(sizeStr, "140k") == 0)
|
||||||
blockCount = 280;
|
blockCount = 280;
|
||||||
else if (strcasecmp(sizeStr, "800k") == 0)
|
else if (strcasecmp(sizeStr, "800k") == 0)
|
||||||
blockCount = 1600;
|
blockCount = 1600;
|
||||||
else {
|
else {
|
||||||
blockCount = atoi(sizeStr);
|
blockCount = atoi(sizeStr);
|
||||||
if (blockCount <= 0 || blockCount > 65536) {
|
if (blockCount <= 0 || blockCount > 65536) {
|
||||||
fprintf(stderr, "ERROR: invalid size '%s'\n", sizeStr);
|
fprintf(stderr, "ERROR: invalid size '%s'\n", sizeStr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (access(outputFileName, F_OK) == 0) {
|
if (access(outputFileName, F_OK) == 0) {
|
||||||
fprintf(stderr, "ERROR: output file '%s' already exists\n",
|
fprintf(stderr, "ERROR: output file '%s' already exists\n",
|
||||||
outputFileName);
|
outputFileName);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(argc >= 1);
|
assert(argc >= 1);
|
||||||
assert(*argv != nil);
|
assert(*argv != nil);
|
||||||
|
|
||||||
|
|
||||||
const char* volName;
|
const char* volName;
|
||||||
DiskImg* pDiskImg;
|
DiskImg* pDiskImg;
|
||||||
DiskFS* pDiskFS;
|
DiskFS* pDiskFS;
|
||||||
DIError dierr;
|
DIError dierr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the disk image file.
|
* Prepare the disk image file.
|
||||||
*/
|
*/
|
||||||
pDiskImg = CreateDisk(outputFileName, blockCount);
|
pDiskImg = CreateDisk(outputFileName, blockCount);
|
||||||
if (pDiskImg == nil)
|
if (pDiskImg == nil)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (format == DiskImg::kFormatDOS33)
|
if (format == DiskImg::kFormatDOS33)
|
||||||
volName = "DOS"; // put DOS 3.3 in tracks 0-2
|
volName = "DOS"; // put DOS 3.3 in tracks 0-2
|
||||||
else
|
else
|
||||||
volName = "TEST";
|
volName = "TEST";
|
||||||
dierr = pDiskImg->FormatImage(format, volName);
|
dierr = pDiskImg->FormatImage(format, volName);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: unable to format disk: %s\n",
|
fprintf(stderr, "ERROR: unable to format disk: %s\n",
|
||||||
DIStrError(dierr));
|
DIStrError(dierr));
|
||||||
delete pDiskImg;
|
delete pDiskImg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare to access the image as a filesystem.
|
* Prepare to access the image as a filesystem.
|
||||||
*/
|
*/
|
||||||
pDiskFS = pDiskImg->OpenAppropriateDiskFS(false);
|
pDiskFS = pDiskImg->OpenAppropriateDiskFS(false);
|
||||||
if (pDiskFS == nil) {
|
if (pDiskFS == nil) {
|
||||||
fprintf(stderr, "ERROR: unable to open appropriate DiskFS\n");
|
fprintf(stderr, "ERROR: unable to open appropriate DiskFS\n");
|
||||||
delete pDiskImg;
|
delete pDiskImg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dierr = pDiskFS->Initialize(pDiskImg, DiskFS::kInitFull);
|
dierr = pDiskFS->Initialize(pDiskImg, DiskFS::kInitFull);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: unable to initialize DiskFS: %s\n",
|
fprintf(stderr, "ERROR: unable to initialize DiskFS: %s\n",
|
||||||
DIStrError(dierr));
|
DIStrError(dierr));
|
||||||
delete pDiskFS;
|
delete pDiskFS;
|
||||||
delete pDiskImg;
|
delete pDiskImg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the files over.
|
* Copy the files over.
|
||||||
*/
|
*/
|
||||||
if (CopyFiles(pDiskFS, argc, argv) != 0) {
|
if (CopyFiles(pDiskFS, argc, argv) != 0) {
|
||||||
delete pDiskFS;
|
delete pDiskFS;
|
||||||
delete pDiskImg;
|
delete pDiskImg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up. Note "CloseImage" isn't strictly necessary, but it gives
|
* Clean up. Note "CloseImage" isn't strictly necessary, but it gives
|
||||||
* us an opportunity to detect failures.
|
* us an opportunity to detect failures.
|
||||||
*/
|
*/
|
||||||
delete pDiskFS;
|
delete pDiskFS;
|
||||||
|
|
||||||
if (pDiskImg->CloseImage() != 0) {
|
if (pDiskImg->CloseImage() != 0) {
|
||||||
fprintf(stderr, "WARNING: CloseImage failed: %s\n",
|
fprintf(stderr, "WARNING: CloseImage failed: %s\n",
|
||||||
DIStrError(dierr));
|
DIStrError(dierr));
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pDiskImg;
|
delete pDiskImg;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle a debug message from the DiskImg library.
|
* Handle a debug message from the DiskImg library.
|
||||||
*/
|
*/
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
MsgHandler(const char* file, int line, const char* msg)
|
MsgHandler(const char* file, int line, const char* msg)
|
||||||
{
|
{
|
||||||
assert(file != nil);
|
assert(file != nil);
|
||||||
assert(msg != nil);
|
assert(msg != nil);
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
fprintf(gLog, "%05u %s", gPid, msg);
|
fprintf(gLog, "%05u %s", gPid, msg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process args.
|
* Process args.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
main(int argc, char** argv)
|
main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
const char* kLogFile = "makedisk-log.txt";
|
const char* kLogFile = "makedisk-log.txt";
|
||||||
gLog = fopen(kLogFile, "w");
|
gLog = fopen(kLogFile, "w");
|
||||||
if (gLog == nil) {
|
if (gLog == nil) {
|
||||||
fprintf(stderr, "ERROR: unable to open log file\n");
|
fprintf(stderr, "ERROR: unable to open log file\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
printf("Log file is '%s'\n", kLogFile);
|
printf("Log file is '%s'\n", kLogFile);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Global::SetDebugMsgHandler(MsgHandler);
|
Global::SetDebugMsgHandler(MsgHandler);
|
||||||
Global::AppInit();
|
Global::AppInit();
|
||||||
|
|
||||||
if (argc < 5) {
|
if (argc < 5) {
|
||||||
Usage(argv[0]);
|
Usage(argv[0]);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* formatName;
|
const char* formatName;
|
||||||
const char* sizeStr;
|
const char* sizeStr;
|
||||||
const char* outputFileName;
|
const char* outputFileName;
|
||||||
|
|
||||||
argv++;
|
argv++;
|
||||||
formatName = *argv++;
|
formatName = *argv++;
|
||||||
sizeStr = *argv++;
|
sizeStr = *argv++;
|
||||||
outputFileName = *argv++;
|
outputFileName = *argv++;
|
||||||
argc -= 4;
|
argc -= 4;
|
||||||
|
|
||||||
if (Process(formatName, sizeStr, outputFileName, argc, argv) == 0)
|
if (Process(formatName, sizeStr, outputFileName, argc, argv) == 0)
|
||||||
fprintf(stderr, "Success!\n");
|
fprintf(stderr, "Success!\n");
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Failed.\n");
|
fprintf(stderr, "Failed.\n");
|
||||||
|
|
||||||
Global::AppCleanup();
|
Global::AppCleanup();
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
fclose(gLog);
|
fclose(gLog);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1532
linux/PackDDD.cpp
1532
linux/PackDDD.cpp
File diff suppressed because it is too large
Load Diff
650
linux/SSTAsm.cpp
650
linux/SSTAsm.cpp
|
@ -1,325 +1,325 @@
|
||||||
/*
|
/*
|
||||||
* CiderPress
|
* CiderPress
|
||||||
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
||||||
* See the file LICENSE for distribution terms.
|
* See the file LICENSE for distribution terms.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Reassemble SST disk images into a .NIB file.
|
* Reassemble SST disk images into a .NIB file.
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "../diskimg/DiskImg.h"
|
#include "../diskimg/DiskImg.h"
|
||||||
|
|
||||||
using namespace DiskImgLib;
|
using namespace DiskImgLib;
|
||||||
|
|
||||||
#define nil NULL
|
#define nil NULL
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
inline int
|
inline int
|
||||||
ConvOddEven(unsigned char val1, unsigned char val2)
|
ConvOddEven(unsigned char val1, unsigned char val2)
|
||||||
{
|
{
|
||||||
return ((val1 & 0x55) << 1) | (val2 & 0x55);
|
return ((val1 & 0x55) << 1) | (val2 & 0x55);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
const int kSSTNumTracks = 35;
|
const int kSSTNumTracks = 35;
|
||||||
const int kSSTTrackLen = 6656; // or 6384 for .NB2
|
const int kSSTTrackLen = 6656; // or 6384 for .NB2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the destination file offset for a particular source track. The
|
* Compute the destination file offset for a particular source track. The
|
||||||
* track number ranges from 0 to 69 inclusive. Sectors from two adjacent
|
* track number ranges from 0 to 69 inclusive. Sectors from two adjacent
|
||||||
* "cooked" tracks are combined into a single "raw nibbilized" track.
|
* "cooked" tracks are combined into a single "raw nibbilized" track.
|
||||||
*
|
*
|
||||||
* The data is ordered like this:
|
* The data is ordered like this:
|
||||||
* track 1 sector 15 --> track 1 sector 4 (12 sectors)
|
* track 1 sector 15 --> track 1 sector 4 (12 sectors)
|
||||||
* track 0 sector 13 --> track 0 sector 0 (14 sectors)
|
* track 0 sector 13 --> track 0 sector 0 (14 sectors)
|
||||||
*
|
*
|
||||||
* Total of 26 sectors, or $1a00 bytes.
|
* Total of 26 sectors, or $1a00 bytes.
|
||||||
*/
|
*/
|
||||||
long
|
long
|
||||||
GetBufOffset(int track)
|
GetBufOffset(int track)
|
||||||
{
|
{
|
||||||
assert(track >= 0 && track < kSSTNumTracks*2);
|
assert(track >= 0 && track < kSSTNumTracks*2);
|
||||||
|
|
||||||
long offset;
|
long offset;
|
||||||
|
|
||||||
if (track & 0x01) {
|
if (track & 0x01) {
|
||||||
/* odd, use start of data */
|
/* odd, use start of data */
|
||||||
offset = (track / 2) * kSSTTrackLen;
|
offset = (track / 2) * kSSTTrackLen;
|
||||||
} else {
|
} else {
|
||||||
/* even, start of data plus 12 sectors */
|
/* even, start of data plus 12 sectors */
|
||||||
offset = (track / 2) * kSSTTrackLen + 12 * 256;
|
offset = (track / 2) * kSSTTrackLen + 12 * 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(offset >= 0 && offset < kSSTTrackLen * kSSTNumTracks);
|
assert(offset >= 0 && offset < kSSTTrackLen * kSSTNumTracks);
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy 17.5 tracks of data from the SST image to a .NIB image.
|
* Copy 17.5 tracks of data from the SST image to a .NIB image.
|
||||||
*
|
*
|
||||||
* Data is stored in all 16 sectors of track 0, followed by the first
|
* Data is stored in all 16 sectors of track 0, followed by the first
|
||||||
* 12 sectors of track 1, then on to track 2. Total of $1a00 bytes.
|
* 12 sectors of track 1, then on to track 2. Total of $1a00 bytes.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
LoadSSTData(DiskImg* pDiskImg, int seqNum, unsigned char* trackBuf)
|
LoadSSTData(DiskImg* pDiskImg, int seqNum, unsigned char* trackBuf)
|
||||||
{
|
{
|
||||||
DIError dierr;
|
DIError dierr;
|
||||||
char sctBuf[256];
|
char sctBuf[256];
|
||||||
int track, sector;
|
int track, sector;
|
||||||
long bufOffset;
|
long bufOffset;
|
||||||
|
|
||||||
for (track = 0; track < kSSTNumTracks; track++) {
|
for (track = 0; track < kSSTNumTracks; track++) {
|
||||||
int virtualTrack = track + (seqNum * kSSTNumTracks);
|
int virtualTrack = track + (seqNum * kSSTNumTracks);
|
||||||
bufOffset = GetBufOffset(virtualTrack);
|
bufOffset = GetBufOffset(virtualTrack);
|
||||||
//fprintf(stderr, "USING offset=%ld (track=%d / %d)\n",
|
//fprintf(stderr, "USING offset=%ld (track=%d / %d)\n",
|
||||||
// bufOffset, track, virtualTrack);
|
// bufOffset, track, virtualTrack);
|
||||||
|
|
||||||
if (virtualTrack & 0x01) {
|
if (virtualTrack & 0x01) {
|
||||||
/* odd-numbered track, sectors 15-4 */
|
/* odd-numbered track, sectors 15-4 */
|
||||||
for (sector = 15; sector >= 4; sector--) {
|
for (sector = 15; sector >= 4; sector--) {
|
||||||
dierr = pDiskImg->ReadTrackSector(track, sector, sctBuf);
|
dierr = pDiskImg->ReadTrackSector(track, sector, sctBuf);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: on track=%d sector=%d\n",
|
fprintf(stderr, "ERROR: on track=%d sector=%d\n",
|
||||||
track, sector);
|
track, sector);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(trackBuf + bufOffset, sctBuf, 256);
|
memcpy(trackBuf + bufOffset, sctBuf, 256);
|
||||||
bufOffset += 256;
|
bufOffset += 256;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (sector = 13; sector >= 0; sector--) {
|
for (sector = 13; sector >= 0; sector--) {
|
||||||
dierr = pDiskImg->ReadTrackSector(track, sector, sctBuf);
|
dierr = pDiskImg->ReadTrackSector(track, sector, sctBuf);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: on track=%d sector=%d\n",
|
fprintf(stderr, "ERROR: on track=%d sector=%d\n",
|
||||||
track, sector);
|
track, sector);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(trackBuf + bufOffset, sctBuf, 256);
|
memcpy(trackBuf + bufOffset, sctBuf, 256);
|
||||||
bufOffset += 256;
|
bufOffset += 256;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; (size_t) i < sizeof(trackBuf)-10; i++) {
|
for (i = 0; (size_t) i < sizeof(trackBuf)-10; i++) {
|
||||||
if ((trackBuf[i] | 0x80) == 0xd5 &&
|
if ((trackBuf[i] | 0x80) == 0xd5 &&
|
||||||
(trackBuf[i+1] | 0x80) == 0xaa &&
|
(trackBuf[i+1] | 0x80) == 0xaa &&
|
||||||
(trackBuf[i+2] | 0x80) == 0x96)
|
(trackBuf[i+2] | 0x80) == 0x96)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "off=%5d vol=%d trk=%d sct=%d chk=%d\n", i,
|
fprintf(stderr, "off=%5d vol=%d trk=%d sct=%d chk=%d\n", i,
|
||||||
ConvOddEven(trackBuf[i+3], trackBuf[i+4]),
|
ConvOddEven(trackBuf[i+3], trackBuf[i+4]),
|
||||||
ConvOddEven(trackBuf[i+5], trackBuf[i+6]),
|
ConvOddEven(trackBuf[i+5], trackBuf[i+6]),
|
||||||
ConvOddEven(trackBuf[i+7], trackBuf[i+8]),
|
ConvOddEven(trackBuf[i+7], trackBuf[i+8]),
|
||||||
ConvOddEven(trackBuf[i+9], trackBuf[i+10]));
|
ConvOddEven(trackBuf[i+9], trackBuf[i+10]));
|
||||||
i += 10;
|
i += 10;
|
||||||
if ((size_t)i < sizeof(trackBuf)-3) {
|
if ((size_t)i < sizeof(trackBuf)-3) {
|
||||||
fprintf(stderr, " 0x%02x 0x%02x 0x%02x\n",
|
fprintf(stderr, " 0x%02x 0x%02x 0x%02x\n",
|
||||||
trackBuf[i+1], trackBuf[i+2], trackBuf[i+3]);
|
trackBuf[i+1], trackBuf[i+2], trackBuf[i+3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy sectors from a single image.
|
* Copy sectors from a single image.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
HandleSSTImage(const char* fileName, int seqNum, unsigned char* trackBuf)
|
HandleSSTImage(const char* fileName, int seqNum, unsigned char* trackBuf)
|
||||||
{
|
{
|
||||||
DIError dierr;
|
DIError dierr;
|
||||||
DiskImg diskImg;
|
DiskImg diskImg;
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
fprintf(stderr, "Handling '%s'\n", fileName);
|
fprintf(stderr, "Handling '%s'\n", fileName);
|
||||||
|
|
||||||
dierr = diskImg.OpenImage(fileName, '/', true);
|
dierr = diskImg.OpenImage(fileName, '/', true);
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: unable to open '%s'\n", fileName);
|
fprintf(stderr, "ERROR: unable to open '%s'\n", fileName);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
dierr = diskImg.AnalyzeImage();
|
dierr = diskImg.AnalyzeImage();
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: image analysis failed\n");
|
fprintf(stderr, "ERROR: image analysis failed\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diskImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) {
|
if (diskImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) {
|
||||||
fprintf(stderr, "ERROR: sector order not set\n");
|
fprintf(stderr, "ERROR: sector order not set\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if (diskImg.GetFSFormat() != DiskImg::kFormatUnknown) {
|
if (diskImg.GetFSFormat() != DiskImg::kFormatUnknown) {
|
||||||
fprintf(stderr, "WARNING: file format *was* recognized!\n");
|
fprintf(stderr, "WARNING: file format *was* recognized!\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if (diskImg.GetNumTracks() != kSSTNumTracks ||
|
if (diskImg.GetNumTracks() != kSSTNumTracks ||
|
||||||
diskImg.GetNumSectPerTrack() != 16)
|
diskImg.GetNumSectPerTrack() != 16)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ERROR: only 140K floppies can be SST inputs\n");
|
fprintf(stderr, "ERROR: only 140K floppies can be SST inputs\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
dierr = diskImg.OverrideFormat(diskImg.GetPhysicalFormat(),
|
dierr = diskImg.OverrideFormat(diskImg.GetPhysicalFormat(),
|
||||||
DiskImg::kFormatGenericDOSOrd, diskImg.GetSectorOrder());
|
DiskImg::kFormatGenericDOSOrd, diskImg.GetSectorOrder());
|
||||||
if (dierr != kDIErrNone) {
|
if (dierr != kDIErrNone) {
|
||||||
fprintf(stderr, "ERROR: format override failed\n");
|
fprintf(stderr, "ERROR: format override failed\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have the image open successfully, now do something with it.
|
* We have the image open successfully, now do something with it.
|
||||||
*/
|
*/
|
||||||
result = LoadSSTData(&diskImg, seqNum, trackBuf);
|
result = LoadSSTData(&diskImg, seqNum, trackBuf);
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run through the data, adding 0x80 everywhere and re-aligning the
|
* Run through the data, adding 0x80 everywhere and re-aligning the
|
||||||
* tracks so that the big clump of sync bytes is at the end.
|
* tracks so that the big clump of sync bytes is at the end.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ProcessTrackData(unsigned char* trackBuf)
|
ProcessTrackData(unsigned char* trackBuf)
|
||||||
{
|
{
|
||||||
unsigned char* trackPtr;
|
unsigned char* trackPtr;
|
||||||
int track;
|
int track;
|
||||||
|
|
||||||
for (track = 0, trackPtr = trackBuf; track < kSSTNumTracks;
|
for (track = 0, trackPtr = trackBuf; track < kSSTNumTracks;
|
||||||
track++, trackPtr += kSSTTrackLen)
|
track++, trackPtr += kSSTTrackLen)
|
||||||
{
|
{
|
||||||
bool inRun;
|
bool inRun;
|
||||||
int start = 0;
|
int start = 0;
|
||||||
int longestStart = -1;
|
int longestStart = -1;
|
||||||
int count7f = 0;
|
int count7f = 0;
|
||||||
int longest = -1;
|
int longest = -1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
inRun = false;
|
inRun = false;
|
||||||
for (i = 0; i < kSSTTrackLen; i++) {
|
for (i = 0; i < kSSTTrackLen; i++) {
|
||||||
if (trackPtr[i] == 0x7f) {
|
if (trackPtr[i] == 0x7f) {
|
||||||
if (inRun) {
|
if (inRun) {
|
||||||
count7f++;
|
count7f++;
|
||||||
} else {
|
} else {
|
||||||
count7f = 1;
|
count7f = 1;
|
||||||
start = i;
|
start = i;
|
||||||
inRun = true;
|
inRun = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (inRun) {
|
if (inRun) {
|
||||||
if (count7f > longest) {
|
if (count7f > longest) {
|
||||||
longest = count7f;
|
longest = count7f;
|
||||||
longestStart = start;
|
longestStart = start;
|
||||||
}
|
}
|
||||||
inRun = false;
|
inRun = false;
|
||||||
} else {
|
} else {
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trackPtr[i] |= 0x80;
|
trackPtr[i] |= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (longest == -1) {
|
if (longest == -1) {
|
||||||
fprintf(stderr, "HEY: couldn't find any 0x7f in track %d\n",
|
fprintf(stderr, "HEY: couldn't find any 0x7f in track %d\n",
|
||||||
track);
|
track);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Found run of %d at %d in track %d\n",
|
fprintf(stderr, "Found run of %d at %d in track %d\n",
|
||||||
longest, longestStart, track);
|
longest, longestStart, track);
|
||||||
|
|
||||||
int bkpt = longestStart + longest;
|
int bkpt = longestStart + longest;
|
||||||
assert(bkpt < kSSTTrackLen);
|
assert(bkpt < kSSTTrackLen);
|
||||||
|
|
||||||
char oneTrack[kSSTTrackLen];
|
char oneTrack[kSSTTrackLen];
|
||||||
memcpy(oneTrack, trackPtr, kSSTTrackLen);
|
memcpy(oneTrack, trackPtr, kSSTTrackLen);
|
||||||
|
|
||||||
/* copy it back so sync bytes are at end of track */
|
/* copy it back so sync bytes are at end of track */
|
||||||
memcpy(trackPtr, oneTrack + bkpt, kSSTTrackLen - bkpt);
|
memcpy(trackPtr, oneTrack + bkpt, kSSTTrackLen - bkpt);
|
||||||
memcpy(trackPtr + (kSSTTrackLen - bkpt), oneTrack, bkpt);
|
memcpy(trackPtr + (kSSTTrackLen - bkpt), oneTrack, bkpt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read sectors from file1 and file2, and write them in the correct
|
* Read sectors from file1 and file2, and write them in the correct
|
||||||
* sequence to outfp.
|
* sequence to outfp.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ReassembleSST(const char* file1, const char* file2, FILE* outfp)
|
ReassembleSST(const char* file1, const char* file2, FILE* outfp)
|
||||||
{
|
{
|
||||||
unsigned char* trackBuf = nil;
|
unsigned char* trackBuf = nil;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
trackBuf = new unsigned char[kSSTNumTracks * kSSTTrackLen];
|
trackBuf = new unsigned char[kSSTNumTracks * kSSTTrackLen];
|
||||||
if (trackBuf == nil) {
|
if (trackBuf == nil) {
|
||||||
fprintf(stderr, "ERROR: malloc failed\n");
|
fprintf(stderr, "ERROR: malloc failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = HandleSSTImage(file1, 0, trackBuf);
|
result = HandleSSTImage(file1, 0, trackBuf);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
result = HandleSSTImage(file2, 1, trackBuf);
|
result = HandleSSTImage(file2, 1, trackBuf);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
result = ProcessTrackData(trackBuf);
|
result = ProcessTrackData(trackBuf);
|
||||||
|
|
||||||
fprintf(stderr, "Writing %d bytes\n", kSSTNumTracks * kSSTTrackLen);
|
fprintf(stderr, "Writing %d bytes\n", kSSTNumTracks * kSSTTrackLen);
|
||||||
fwrite(trackBuf, 1, kSSTNumTracks * kSSTTrackLen, outfp);
|
fwrite(trackBuf, 1, kSSTNumTracks * kSSTTrackLen, outfp);
|
||||||
|
|
||||||
delete[] trackBuf;
|
delete[] trackBuf;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle a debug message from the DiskImg library.
|
* Handle a debug message from the DiskImg library.
|
||||||
*/
|
*/
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
MsgHandler(const char* file, int line, const char* msg)
|
MsgHandler(const char* file, int line, const char* msg)
|
||||||
{
|
{
|
||||||
assert(file != nil);
|
assert(file != nil);
|
||||||
assert(msg != nil);
|
assert(msg != nil);
|
||||||
|
|
||||||
fprintf(stderr, "%s", msg);
|
fprintf(stderr, "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse args, go.
|
* Parse args, go.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
main(int argc, char** argv)
|
main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
fprintf(stderr, "Usage: %s file1 file2 > outfile\n", argv[0]);
|
fprintf(stderr, "Usage: %s file1 file2 > outfile\n", argv[0]);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Global::SetDebugMsgHandler(MsgHandler);
|
Global::SetDebugMsgHandler(MsgHandler);
|
||||||
Global::AppInit();
|
Global::AppInit();
|
||||||
|
|
||||||
result = ReassembleSST(argv[1], argv[2], stdout);
|
result = ReassembleSST(argv[1], argv[2], stdout);
|
||||||
|
|
||||||
Global::AppCleanup();
|
Global::AppCleanup();
|
||||||
exit(result != 0);
|
exit(result != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,101 +1,101 @@
|
||||||
/*
|
/*
|
||||||
* CiderPress
|
* CiderPress
|
||||||
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
||||||
* See the file LICENSE for distribution terms.
|
* See the file LICENSE for distribution terms.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* An expandable array of strings.
|
* An expandable array of strings.
|
||||||
*/
|
*/
|
||||||
#ifndef __STRING_ARRAY__
|
#ifndef __STRING_ARRAY__
|
||||||
#define __STRING_ARRAY__
|
#define __STRING_ARRAY__
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is a simple container for an array of strings. You can add strings
|
// This is a simple container for an array of strings. You can add strings
|
||||||
// to the list and sort them.
|
// to the list and sort them.
|
||||||
//
|
//
|
||||||
class StringArray {
|
class StringArray {
|
||||||
public:
|
public:
|
||||||
StringArray()
|
StringArray()
|
||||||
: mMax(0), mCurrent(0), mArray(NULL)
|
: mMax(0), mCurrent(0), mArray(NULL)
|
||||||
{}
|
{}
|
||||||
virtual ~StringArray()
|
virtual ~StringArray()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < mCurrent; i++)
|
for (int i = 0; i < mCurrent; i++)
|
||||||
delete[] mArray[i];
|
delete[] mArray[i];
|
||||||
delete[] mArray;
|
delete[] mArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Add a string. A copy of the string is made.
|
// Add a string. A copy of the string is made.
|
||||||
//
|
//
|
||||||
bool Add(const char* str)
|
bool Add(const char* str)
|
||||||
{
|
{
|
||||||
if (mCurrent >= mMax) {
|
if (mCurrent >= mMax) {
|
||||||
char** tmp;
|
char** tmp;
|
||||||
|
|
||||||
if (mMax == 0)
|
if (mMax == 0)
|
||||||
mMax = 16;
|
mMax = 16;
|
||||||
else
|
else
|
||||||
mMax *= 2;
|
mMax *= 2;
|
||||||
|
|
||||||
tmp = new char*[mMax];
|
tmp = new char*[mMax];
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memcpy(tmp, mArray, mCurrent * sizeof(char*));
|
memcpy(tmp, mArray, mCurrent * sizeof(char*));
|
||||||
delete[] mArray;
|
delete[] mArray;
|
||||||
mArray = tmp;
|
mArray = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(str);
|
int len = strlen(str);
|
||||||
mArray[mCurrent] = new char[len+1];
|
mArray[mCurrent] = new char[len+1];
|
||||||
memcpy(mArray[mCurrent], str, len+1);
|
memcpy(mArray[mCurrent], str, len+1);
|
||||||
mCurrent++;
|
mCurrent++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sort the array. Supply a sort function that takes two strings
|
// Sort the array. Supply a sort function that takes two strings
|
||||||
// and returns <0, 0, or >0 if the first argument is less than,
|
// and returns <0, 0, or >0 if the first argument is less than,
|
||||||
// equal to, or greater than the second argument. (strcmp works.)
|
// equal to, or greater than the second argument. (strcmp works.)
|
||||||
//
|
//
|
||||||
void Sort(int (*compare)(const void*, const void*))
|
void Sort(int (*compare)(const void*, const void*))
|
||||||
{
|
{
|
||||||
qsort(mArray, mCurrent, sizeof(char*), compare);
|
qsort(mArray, mCurrent, sizeof(char*), compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Use this as an argument to the sort routine.
|
// Use this as an argument to the sort routine.
|
||||||
//
|
//
|
||||||
static int CmpAscendingAlpha(const void* pstr1, const void* pstr2)
|
static int CmpAscendingAlpha(const void* pstr1, const void* pstr2)
|
||||||
{
|
{
|
||||||
return strcmp(*(const char**)pstr1, *(const char**)pstr2);
|
return strcmp(*(const char**)pstr1, *(const char**)pstr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the #of items in the array.
|
// Get the #of items in the array.
|
||||||
//
|
//
|
||||||
inline int GetCount(void) const { return mCurrent; }
|
inline int GetCount(void) const { return mCurrent; }
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get entry N.
|
// Get entry N.
|
||||||
//
|
//
|
||||||
const char* GetEntry(int idx) const
|
const char* GetEntry(int idx) const
|
||||||
{
|
{
|
||||||
if (idx < 0 || idx >= mCurrent)
|
if (idx < 0 || idx >= mCurrent)
|
||||||
return NULL;
|
return NULL;
|
||||||
return mArray[idx];
|
return mArray[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mMax;
|
int mMax;
|
||||||
int mCurrent;
|
int mCurrent;
|
||||||
char** mArray;
|
char** mArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__STRING_ARRAY__*/
|
#endif /*__STRING_ARRAY__*/
|
||||||
|
|
Loading…
Reference in New Issue