initial import

This commit is contained in:
Andy McFadden 2007-03-27 17:47:10 +00:00
commit 0d7d1b67e0
337 changed files with 140029 additions and 0 deletions

107
CP.dsw Normal file
View File

@ -0,0 +1,107 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "app"=.\app\app.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name diskimg
End Project Dependency
Begin Project Dependency
Project_Dep_Name util
End Project Dependency
Begin Project Dependency
Project_Dep_Name reformat
End Project Dependency
}}}
###############################################################################
Project: "diskimg"=.\diskimg\diskimg.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name libhfs
End Project Dependency
}}}
###############################################################################
Project: "libhfs"=.\diskimg\libhfs\libhfs.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "mdc"=.\mdc\mdc.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name diskimg
End Project Dependency
Begin Project Dependency
Project_Dep_Name util
End Project Dependency
}}}
###############################################################################
Project: "reformat"=.\reformat\reformat.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "util"=.\util\util.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

67
CP.sln Normal file
View File

@ -0,0 +1,67 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "app", "app\app.vcproj", "{B023611B-7086-46E1-847B-3B21C4732384}"
ProjectSection(ProjectDependencies) = postProject
{04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5} = {04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5}
{18BCF397-397E-460C-A1DC-3E26798966E4} = {18BCF397-397E-460C-A1DC-3E26798966E4}
{0CFE6FAD-0126-4E99-8625-C807D1D2AAF4} = {0CFE6FAD-0126-4E99-8625-C807D1D2AAF4}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "diskimg", "diskimg\diskimg.vcproj", "{0CFE6FAD-0126-4E99-8625-C807D1D2AAF4}"
ProjectSection(ProjectDependencies) = postProject
{0FA742E9-8C07-43DD-AFF8-CE31FAF70821} = {0FA742E9-8C07-43DD-AFF8-CE31FAF70821}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdc", "mdc\mdc.vcproj", "{7DF41D71-C8DC-48AA-B372-4613210310A4}"
ProjectSection(ProjectDependencies) = postProject
{04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5} = {04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5}
{0CFE6FAD-0126-4E99-8625-C807D1D2AAF4} = {0CFE6FAD-0126-4E99-8625-C807D1D2AAF4}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "util", "util\util.vcproj", "{04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhfs", "diskimg\libhfs\libhfs.vcproj", "{0FA742E9-8C07-43DD-AFF8-CE31FAF70821}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reformat", "reformat\reformat.vcproj", "{18BCF397-397E-460C-A1DC-3E26798966E4}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{B023611B-7086-46E1-847B-3B21C4732384}.Debug.ActiveCfg = Debug|Win32
{B023611B-7086-46E1-847B-3B21C4732384}.Debug.Build.0 = Debug|Win32
{B023611B-7086-46E1-847B-3B21C4732384}.Release.ActiveCfg = Release|Win32
{B023611B-7086-46E1-847B-3B21C4732384}.Release.Build.0 = Release|Win32
{0CFE6FAD-0126-4E99-8625-C807D1D2AAF4}.Debug.ActiveCfg = Debug|Win32
{0CFE6FAD-0126-4E99-8625-C807D1D2AAF4}.Debug.Build.0 = Debug|Win32
{0CFE6FAD-0126-4E99-8625-C807D1D2AAF4}.Release.ActiveCfg = Release|Win32
{0CFE6FAD-0126-4E99-8625-C807D1D2AAF4}.Release.Build.0 = Release|Win32
{7DF41D71-C8DC-48AA-B372-4613210310A4}.Debug.ActiveCfg = Debug|Win32
{7DF41D71-C8DC-48AA-B372-4613210310A4}.Debug.Build.0 = Debug|Win32
{7DF41D71-C8DC-48AA-B372-4613210310A4}.Release.ActiveCfg = Release|Win32
{7DF41D71-C8DC-48AA-B372-4613210310A4}.Release.Build.0 = Release|Win32
{04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5}.Debug.ActiveCfg = Debug|Win32
{04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5}.Debug.Build.0 = Debug|Win32
{04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5}.Release.ActiveCfg = Release|Win32
{04BFAE2A-7AB3-4B63-B4AB-42FF1D6AD3C5}.Release.Build.0 = Release|Win32
{0FA742E9-8C07-43DD-AFF8-CE31FAF70821}.Debug.ActiveCfg = Debug|Win32
{0FA742E9-8C07-43DD-AFF8-CE31FAF70821}.Debug.Build.0 = Debug|Win32
{0FA742E9-8C07-43DD-AFF8-CE31FAF70821}.Release.ActiveCfg = Release|Win32
{0FA742E9-8C07-43DD-AFF8-CE31FAF70821}.Release.Build.0 = Release|Win32
{18BCF397-397E-460C-A1DC-3E26798966E4}.Debug.ActiveCfg = Debug|Win32
{18BCF397-397E-460C-A1DC-3E26798966E4}.Debug.Build.0 = Debug|Win32
{18BCF397-397E-460C-A1DC-3E26798966E4}.Release.ActiveCfg = Release|Win32
{18BCF397-397E-460C-A1DC-3E26798966E4}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

37
DIST/License.txt Normal file
View File

@ -0,0 +1,37 @@
End-User License Agreement for CiderPress
Copyright (C) 2007 FaddenSoft, LLC. All Rights Reserved.
AGREEMENT. After reading this agreement carefully, if you ("Customer") do
not agree to all of the terms of this agreement, you may not use
CiderPress ("Software"). Your use of this Software indicates your
acceptance of this license agreement and warranty. All updates to the
Software shall be considered part of the Software and subject to the terms
of this Agreement. Changes to this Agreement may accompany updates to the
Software, in which case by installing such update Customer accepts the
terms of the Agreement as changed. The Agreement is not otherwise subject
to addition, amendment, modification, or exception unless in writing
signed by an officer of both Customer and FaddenSoft, LLC ("FaddenSoft").
1. LICENSE. This is free software, distributed under the terms of the
BSD License. See "LICENSE.txt" for details.
2. LIMITED WARRANTY. THE SOFTWARE IS PROVIDED AS IS AND FADDENSOFT
DISCLAIMS ALL WARRANTIES RELATING TO THIS SOFTWARE, WHETHER EXPRESSED OR
IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
3. LIMITATION ON DAMAGES. NEITHER FADDENSOFT NOR ANYONE INVOLVED IN THE
CREATION, PRODUCTION, OR DELIVERY OF THIS SOFTWARE SHALL BE LIABLE FOR ANY
INDIRECT, CONSEQUENTIAL, OR INCIDENTAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE SUCH SOFTWARE EVEN IF FADDENSOFT HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES OR CLAIMS. IN NO EVENT SHALL FADDENSOFT'S
LIABILITY FOR ANY DAMAGES EXCEED THE PRICE PAID FOR THE LICENSE TO USE THE
SOFTWARE, REGARDLESS OF THE FORM OF CLAIM. THE PERSON USING THE SOFTWARE
BEARS ALL RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE.
4. GOVERNING LAW AND GENERAL PROVISIONS. This Agreement will be governed
by the laws of the State of California, U.S.A. If any part of this
Agreement is found void and unenforceable, it will not affect the validity
of the balance of the Agreement, which shall remain valid and enforceable
according to its terms. This Agreement shall automatically terminate upon
failure by Customer to comply with its terms.

2516
DIST/NList.Data.TXT Normal file

File diff suppressed because it is too large Load Diff

11
DIST/ReadMe.txt Normal file
View File

@ -0,0 +1,11 @@
faddenSoft CiderPress(tm)
CiderPress is a Windows utility for accessing Apple II archives and
disk images. A wide range of formats are supported, including
ShrinkIt (NuFX) archives and disk images with DOS, ProDOS, Pascal,
CP/M, and RDOS filesystems.
This program used to be shareware, but is now free.
If you have any questions, please visit the faddenSoft CiderPress
web site at http://www.faddensoft.com/ciderpress/.

271
DIST/with-mdc.deploy Normal file
View File

@ -0,0 +1,271 @@
DeployMaster Installation Script
9
faddenSoft
http://www.faddensoft.com/
CiderPress
http://www.faddensoft.com/ciderpress/
3.0.0
39166
C:\DATA\faddenSoft\fs.ico
Copyright © 2007 faddenSoft, LLC. All rights reserved.
C:\Src\CiderPress\DIST\ReadMe.txt
C:\Src\CiderPress\DIST\License.txt
%PROGRAMFILES%\faddenSoft\CiderPress
%COMMONFILES%\faddenSoft\
%PROGRAMSMENU%\CiderPress
TRUE
TRUE
1
-16777198
MS Sans Serif
8
FALSE
FALSE
FALSE
FALSE
FALSE
16711680
0
TRUE
faddenSoft CiderPress 0.1
1
16777215
Times New Roman
36
TRUE
FALSE
FALSE
FALSE
TRUE
0
Copyright © 2003 faddenSoft, LLC. All rights reserved.
1
16777215
Times New Roman
20
TRUE
FALSE
FALSE
FALSE
TRUE
0
English (Default)
FALSE
FALSE
FALSE
FALSE
TRUE
FALSE
FALSE
0
FALSE
0
+
CiderPress
0
TRUE
FALSE
Main CiderPress application
+
%APPFOLDER%
1
+
C:\Src\CiderPress\DIST\CiderPress.cnt
3
0
FALSE
FALSE
C:\Src\CiderPress\DIST\CiderPress.exe
3
0
FALSE
FALSE
C:\Src\CiderPress\DIST\CIDERPRESS.HLP
3
0
FALSE
FALSE
C:\Src\CiderPress\DIST\NList.Data.TXT
3
1
FALSE
FALSE
-
%APPCOMMONFOLDER%
1
%APPMENU%
1
+
C:\Src\CiderPress\DIST\CiderPress.exe
4
CiderPress
The ultimate Apple II archive utility
0
C:\Src\CiderPress\DIST\CIDERPRESS.HLP
4
CiderPress Help
Help file for CiderPress
0
-
%DESKTOP%
1
%SENDTO%
1
%STARTUP%
1
%WINDOWS%
1
%SYSTEM%
1
-
Common DLLs
0
FALSE
FALSE
NuFX, zlib, and disk image access libraries.
+
%APPFOLDER%
1
+
C:\Src\CiderPress\DIST\diskimg4.dll
3
0
FALSE
FALSE
C:\Src\CiderPress\DIST\nufxlib2.dll
3
0
FALSE
FALSE
C:\Src\CiderPress\DIST\zlib1.dll
3
0
FALSE
FALSE
-
%APPCOMMONFOLDER%
1
%APPMENU%
1
%DESKTOP%
1
%SENDTO%
1
%STARTUP%
1
%WINDOWS%
1
%SYSTEM%
1
-
MDC
0
TRUE
FALSE
Multi-Disk Catalog utility.
+
%APPFOLDER%
1
+
C:\Src\CiderPress\DIST\mdc.exe
3
0
FALSE
FALSE
-
%APPCOMMONFOLDER%
1
%APPMENU%
1
+
C:\Src\CiderPress\DIST\mdc.exe
4
MDC
Multi-Disk Catalog for Apple II disk images
0
-
%DESKTOP%
1
%SENDTO%
1
%STARTUP%
1
%WINDOWS%
1
%SYSTEM%
1
-
-
1
1
0
1
1
+
HKEY_CURRENT_USER
0
FALSE
+
Software
0
FALSE
+
faddenSoft
0
FALSE
+
CiderPress
0
TRUE
-
-
-
HKEY_LOCAL_MACHINE
0
FALSE
+
Software
0
FALSE
+
faddenSoft
0
FALSE
+
CiderPress
0
TRUE
-
-
-
-
0
TRUE
FALSE
TRUE
TRUE
C:\Src\CiderPress\DIST\CiderPress.exe
-install
C:\Src\CiderPress\DIST\CiderPress.exe
-uninstall
TRUE
TRUE
FALSE
36725
0
FALSE
36725
0
10
Setup300.exe
FALSE

25
LICENSE.txt Normal file
View File

@ -0,0 +1,25 @@
Copyright (c) 2007, FaddenSoft, LLC
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of FaddenSoft, LLC nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY FaddenSoft, LLC ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL FaddenSoft, LLC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

313
ReadMe.htm Normal file
View File

@ -0,0 +1,313 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>CiderPress Source README</title>
</head>
<body>
<h1>CiderPress Source README</h1>
Release notes for v3.0.0<br>
Last updated: 25-Mar-2007
<h2>Contents:</h2>
<ul>
<li><a href="#intro">What's Ciderpress?</a>
<li><a href="#build">Building the Sources</a>
<li><a href="#notes">Source Notes</a>
</ul>
<hr>
<h2><a name="intro">What's CiderPress?</a></h2>
<p>CiderPress is a Windows utility for manipulating Apple II disk images
and file archives. It supports all major disk and archive formats used
on the Apple II and by Apple II emulators.
<p>CiderPress was sold by faddenSoft, LLC as a shareware product for about four
years, starting in March 2003.
<h3>Why Bother?</h3>
<p>Back in 2002 I decided it was time to learn how to write an application for
Microsoft Windows. I had been a professional software engineer for many
years -- including 2.5 years at Microsoft! -- but had never written a
Windows program more complex than "Hello, world!".
<p>I decided to write a Windows version of GS/ShrinkIt. I had already written
NufxLib, which handled all of the ShrinkIt stuff, so I could focus
on writing the Windows user interface code.
<p>Somewhere in the early stages of the project, it occurred to me that a
disk image isn't substantially different from a file archive. They're
both just collections of files laid out in a well-defined manner. The
decision to handle disk images as well as ShrinkIt archives seemed like
a simple improvement at the time. The rest is history.
<p>CiderPress has allowed me to explore a variety of interesting technologies.
It has five different ways of reading a block from physical media, depending
on your operating system and what sort of device you're reading from. I
was able to take what I learned from a digital signal processing textbook
and apply it to a real-world problem (decoding Apple II cassette data). It
is also my first Shareware product, not to mention the initial product of
my first small business venture (faddenSoft, LLC).
<p>I could have written other things. No doubt they would have made more money.
CiderPress is something that I find very useful, however, in the pursuit of
my Apple II hobby.
<p>Above all, this has been a labor of love. I have tried to get the details
right, because in the end it's the little things that mean the difference
between "good" and merely "good enough".</p>
<h3>License</h3>
<p>The source code to CiderPress is being made available under the BSD license:</p>
<blockquote><code>
Copyright (c) 2007, FaddenSoft, LLC<br>
All rights reserved.
<p>Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
<ul>
<li> Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
<li> Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
<li> Neither the name of FaddenSoft, LLC nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
</ul>
<p>THIS SOFTWARE IS PROVIDED BY FaddenSoft, LLC ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL FaddenSoft, LLC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</code></blockquote>
CiderPress requires three other libraries, all of which are included as either
source or binaries:
<ul>
<li>NufxLib, also available under the BSD license.
<li>Zlib, available under the Zlib license.
<li>libhfs, available under the GPL license.
</ul>
<p>The license allows you to do a great many things. For example, you could
take the source code to CiderPress, compile it, and sell it. I'm not sure why
anyone would buy it, but you're legally allowed to do so, as long as you retain
the appropriate copyright notice.</p>
<p>If you retain libhfs, any changes you make to any part of CiderPress must
be made available, due to the "viral" nature of the GPL license. If this is
not acceptable, you can remove HFS disk image support from CiderPress (look for
&quot;EXCISE_GPL_CODE&quot; in DiskImg.h).</p>
<hr>
<h2><a name="build">Building the Sources</a></h2>
<p>How to build your own copy of CiderPress.
<h3>Windows</h3>
<p>The sources are distributed with the necessary project/solution files for
Microsoft Visual Studio 6.0 and Microsoft Visual Studio 2003.&nbsp; All you
really need is the C++ compiler.&nbsp; The free or student editions of the
compilers will probably work.
<p>I usually work on CiderPress in Visual C++ 6.0,
and use that when building for distribution.&nbsp; I chose to stick with 6.0 for
CiderPress because you need an additional MSVC DLL when you build with
2003.&nbsp; Also, the newer tools cause the newer file selection dialogs to be
used, and the custom dialog code gets all wonky.</p>
<p>In 6.0, you need to select &quot;app&quot; as the build target (Build-&gt;Set
active configuration), and hit F7.&nbsp; This will build everything except MDC,
which you can then build by selecting &quot;mdc&quot; and hitting F7.&nbsp; You
can also configure a batch build.&nbsp; In 2003 just select &quot;build
solution&quot;.&nbsp; The necessary prebuilt libraries should be there for both
&quot;debug&quot; and &quot;release&quot; builds.&nbsp; (You can tell how it has
been built by looking at the version string in the About box.)</p>
<p>When the build completes, the necessary DLLs are copied around so you can
execute the binary by launching it within Visual Studio (hit F5).&nbsp; You will
get a warning about not being able to find the NiftyList data file unless you
copy that from &quot;DIST&quot; into the app source directory.</p>
<p>The distribution comes with prebuilt versions of NufxLib2 and zlib in DLL
form.&nbsp; If you like, you can download and compile your own.</p>
<p>There are two things you can't create with the standard tools:</p>
<ul>
<li>The help text was created with HelpMatic Pro. The source file is in a
proprietary format. It should probably be converted to HTML Help.</li>
<li>The installation packages are created with DeployMaster. The
".deploy" file specifies how the package is built. </li>
</ul>
<p>Compiled help files are included, so you can still generate a new version of
CiderPress even if you can't update the help.&nbsp; You don't strictly need the installer either, though it is
quite handy, and the uninstaller will clean up the registry entries CiderPress
creates.</p>
<h3>Linux</h3>
<p>The &quot;linux&quot; directory has a few command-line utilities and a simple
makefile.&nbsp; It will build the diskimg and HFS libraries, then the sample utilities:</p>
<ul>
<li><code>getfile disk-image filename</code> -- extract a file from a disk
image.&nbsp; The file is written to stdout.</li>
<li><code>makedisk {dos|prodos|pascal} size image-filename.po file1 ...</code>
-- create a new disk image, with the specified size and format, and copy the
specified files onto it.</li>
<li><code>mdc file1 ...</code> -- this is equivalent to the MDC application
for Windows.&nbsp; It recursively scans all files and directories specified,
displaying the contents of any disk images it finds.</li>
</ul>
<p>This are mostly intended for testing and illustration of the interfaces, but
they can be useful as well.&nbsp; Some other code is also provided:</p>
<ul>
<li><code>iconv infile outfile</code> -- convert an image from one format to
another.&nbsp; This was used for testing.</li>
<li><code>packddd infile outfile</code> -- the DDD code was originally
developed under Linux.&nbsp; This code is here for historical reasons.</li>
<li><code>sstasm part1 part2</code> -- the SST re-assembly code was originally
developed under Linux.&nbsp; The code is here for historical reasons.</li>
</ul>
<p>The &quot;prebuilt&quot; directory has a pre-built copy of NufxLib, so you
don't have to build your own.</p>
<p>If you're planning to hack on this stuff, use &quot;make depend&quot; before
&quot;make&quot; to fill in the dependencies.</p>
<hr>
<h2><a name="notes">Source Notes</a></h2>
<p>Some notes on what you'll find in the various directories.
<h3>Main Application</h3>
<p>This is highly Windows-centric.&nbsp; My goal was to learn how to write a
Windows application, so I made no pretense at portability.&nbsp; For better or
worse, I avoided the Visual Studio &quot;wizards&quot; for the dialogs.
<p>Much of the user interface text is in the resource file.&nbsp; Much is not,
especially when it comes to error messages.&nbsp; This will need to be addressed
if internationalization is attempted.
<p>It may be possible to convert this for use
with wxWidgets, which uses an MFC-like structure, and runs on Mac and Linux as
well. The greatest barrier to
entry is probably the heavy reliance on the Rich Edit control. Despite
its bug-ridden history, the Rich Edit control allowed me to let Windows
deal with a lot of text formatting and image display stuff.
<h3>MDC Application</h3>
<p>MDC (Multi-Disk Catalog) was written as a simple demonstration of the value of having the DiskImg
code in a DLL instead of meshed with the main application.&nbsp; There's not
much to it, and it hasn't changed substantially since it was first written.
<h3>DiskImg Library</h3>
<p>This library provides access to disk images.&nbsp; It automatically handles a
wide variety of formats.
<p>This library can be built under Linux or Windows. One of my key motivations
for making it work under Linux was the availability of "valgrind". Similar
tools for Windows usually very expensive or inferior (or both).
<p>The basic classes, defined in DiskImg.h, are:
<ul>
<li>DiskImg.&nbsp; This represents a single disk image, which may have
sub-images.&nbsp; Operations on a DiskImg are roughly equivalent to a device
driver: you can read and write blocks, detect image formats, and create new
images.</li>
<li>DiskFS.&nbsp; Paired with a DiskImg, this is roughly equivalent to a GS/OS
FST (FileSystem Translator).&nbsp; You can perform file operations like
rename and delete, format disks, see how much space is available, and search
for sub-volumes.</li>
<li>A2File.&nbsp; Represents a file on a DiskFS.&nbsp; This holds the file's
name, attributes, track/sector or block lists, and provides a call to open a
file.</li>
<li>A2FileDescr.&nbsp; Represents an open file.&nbsp; You can read or write
data.</li>
</ul>
<p>Sub-classes are defined in DiskImgDetail.h.&nbsp; Most applications won't
need to access this header file.&nbsp; Each Apple II filesystem defines
sub-classes of DiskFS, A2File, and A2FileDescr.</p>
<p>In an ideal world, the code would mimic the GS/OS file operations.&nbsp; In
practice, CiderPress didn't need the full range of capabilities, so the
functions have some basic limitations:
<ul>
<li>On ProDOS and HFS, you can only open one fork at a time. This allowed me
to use simpler data structures.
<li>Files are expected to be written in one large chunk. This reduced the
complexity of the task enormously, because there's so much less that can
go wrong.
</ul>
<p>Some things that can be improved:
<ul>
<li>The overall structure of the filesystem handlers evolved over time. There
is some amount of redundancy that could be factored out.
<li>The API, especially in DiskImg, could probably be simplified.
</ul>
<p>The library depends on NufxLib and zlib for access to compressed images.</p>
<h3>Reformat Library</h3>
<p>This is probably the most "fun" component of CiderPress. It converts Apple II files
to more easily accessible Windows equivalents.
<p>Start in Reformat.h and ReformatBase.h. There are two basic kinds of
reformatter: text and graphics. Everything else is a sub-class of one of the
two basic types.
<p>The general idea is to allow the reformatter to decide whether or not it is
capable of reformatting a file. To this end, the file type information and
file contents are presented to the &quot;examine&quot; function of each reformatter in
turn. The level of confidence is specified in a range. If it's better than
"no", it is presented to the user as an option, ordered by the strength of its
convictions. If chosen, the &quot;process&quot; function is called to convert the data.
<p>Bear in mind that reformatters may be disabled from the preferences menu.&nbsp;
Also, when extracting files for easy access in Windows, the &quot;best&quot;
reformatter is employed by the extraction code.<p>Most of the code should be portable, though some of it uses the MFC CString class.&nbsp;
This could probably be altered to use STL strings or plain.
<h3>Util Library</h3>
<p>Miscellaneous utility functions.
<p>For a good time, look at SelectFilesDialog.cpp.
<p>To enable debug logging for one of the applications, define _DEBUG_LOG in
MyDebug.h in this library. You will see "_DEBUG_LOG" in the version string
in the About box when this is defined. The log is written to C:\cplog.txt.
An existing log file will be appended to if the previous log was written to
less than 8 hours ago.</p>
<hr>
<p>Enjoy!</p>
<address>Andy McFadden</address>
</body>
</html>

906
app/ACUArchive.cpp Normal file
View File

@ -0,0 +1,906 @@
/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
/*
* AppleLink Compression Utility file support.
*
* This was adapted from the Binary II support, which has a mixed history,
* so this is a little scrambled in spots.
*/
#include "stdafx.h"
#include "ACUArchive.h"
#include "NufxArchive.h" // uses NuError
#include "Preferences.h"
#include "Main.h"
#include "Squeeze.h"
#include <errno.h>
/*
+00 2b Number of items in archive
+02 2b 0100
+04 5b "fZink"
+09 11b 0136 0000 0000 0000 0000 dd
+14
+00 1b ?? 00
+01 1b Compression type, 00=none, 03=sq
+02 2b ?? 0000 0000 0000 0000
+04 2b ?? 0a74 961f 7d85 af2c 2775 <- 0000 for dir (checksum?)
+06 2b ?? 0000 0000 0000 0000
+08 2b ?? 0000 0000 0000 0000
+0a 2b Storage size (in 512-byte blocks)
+0c 6b ?? 000000 000000 000000 000000
+12 4b Length of file in this archive (compressed or uncompressed)
+16 2b ProDOS file permissions
+18 2b ProDOS file type
+1a 4b ProDOS aux type
+1e ?? 0000
+20 1b ProDOS storage type (usually 02, 0d for dirs)
+21 ?? 00
+22 ?? 0000 0000
+26 4b Uncompressed file len
+2a 2b ProDOS date (create?)
+2c 2b ProDOS time
+2e 2b ProDOS date (mod?)
+30 2b ProDOS time
+32 2b Filename len
+34 2b ?? ac4a 2d02 for dir <- header checksum?
+36 FL Filename
+xx data start (dir has no data)
*/
/*
* ===========================================================================
* AcuEntry
* ===========================================================================
*/
/*
* Extract data from an entry.
*
* If "*ppText" is non-nil, the data will be read into the pointed-to buffer
* so long as it's shorter than *pLength bytes. The value in "*pLength"
* will be set to the actual length used.
*
* If "*ppText" is nil, the uncompressed data will be placed into a buffer
* allocated with "new[]".
*
* Returns IDOK on success, IDCANCEL if the operation was cancelled by the
* user, and -1 value on failure. On failure, "*pErrMsg" holds an error
* message.
*
* "which" is an anonymous GenericArchive enum (e.g. "kDataThread").
*/
int
AcuEntry::ExtractThreadToBuffer(int which, char** ppText, long* pLength,
CString* pErrMsg) const
{
NuError nerr;
ExpandBuffer expBuf;
char* dataBuf = nil;
long len;
bool needAlloc = true;
int result = -1;
ASSERT(fpArchive != nil);
ASSERT(fpArchive->fFp != nil);
if (*ppText != nil)
needAlloc = false;
if (which != kDataThread) {
*pErrMsg = "No such fork";
goto bail;
}
len = (long) GetUncompressedLen();
if (len == 0) {
if (needAlloc) {
*ppText = new char[1];
**ppText = '\0';
}
*pLength = 0;
result = IDOK;
goto bail;
}
SET_PROGRESS_BEGIN();
errno = 0;
if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) {
pErrMsg->Format("Unable to seek to offset %ld: %s",
fOffset, strerror(errno));
goto bail;
}
if (GetSqueezed()) {
nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(),
&expBuf, false, 0);
if (nerr != kNuErrNone) {
pErrMsg->Format("File read failed: %s", NuStrError(nerr));
goto bail;
}
char* unsqBuf = nil;
long unsqLen = 0;
expBuf.SeizeBuffer(&unsqBuf, &unsqLen);
WMSG2("Unsqueezed %ld bytes to %d\n",
(unsigned long) GetCompressedLen(), unsqLen);
if (unsqLen == 0) {
// some bonehead squeezed a zero-length file
delete[] unsqBuf;
ASSERT(*ppText == nil);
WMSG0("Handling zero-length squeezed file!\n");
if (needAlloc) {
*ppText = new char[1];
**ppText = '\0';
}
*pLength = 0;
} else {
if (needAlloc) {
/* just use the seized buffer */
*ppText = unsqBuf;
*pLength = unsqLen;
} else {
if (*pLength < unsqLen) {
pErrMsg->Format("buf size %ld too short (%ld)",
*pLength, unsqLen);
delete[] unsqBuf;
goto bail;
}
memcpy(*ppText, unsqBuf, unsqLen);
delete[] unsqBuf;
*pLength = unsqLen;
}
}
} else {
if (needAlloc) {
dataBuf = new char[len];
if (dataBuf == nil) {
pErrMsg->Format("allocation of %ld bytes failed", len);
goto bail;
}
} else {
if (*pLength < (long) len) {
pErrMsg->Format("buf size %ld too short (%ld)",
*pLength, len);
goto bail;
}
dataBuf = *ppText;
}
if (fread(dataBuf, len, 1, fpArchive->fFp) != 1) {
pErrMsg->Format("File read failed: %s", strerror(errno));
goto bail;
}
if (needAlloc)
*ppText = dataBuf;
*pLength = len;
}
result = IDOK;
bail:
if (result == IDOK) {
SET_PROGRESS_END();
ASSERT(pErrMsg->IsEmpty());
} else {
ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty());
if (needAlloc) {
delete[] dataBuf;
ASSERT(*ppText == nil);
}
}
return result;
}
/*
* Extract data from a thread to a file. Since we're not copying to memory,
* we can't assume that we're able to hold the entire file all at once.
*
* Returns IDOK on success, IDCANCEL if the operation was cancelled by the
* user, and -1 value on failure. On failure, "*pMsg" holds an
* error message.
*/
int
AcuEntry::ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv,
ConvertHighASCII convHA, CString* pErrMsg) const
{
NuError nerr;
long len;
int result = -1;
ASSERT(IDOK != -1 && IDCANCEL != -1);
if (which != kDataThread) {
*pErrMsg = "No such fork";
goto bail;
}
len = (long) GetUncompressedLen();
if (len == 0) {
WMSG0("Empty fork\n");
result = IDOK;
goto bail;
}
errno = 0;
if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) {
pErrMsg->Format("Unable to seek to offset %ld: %s",
fOffset, strerror(errno));
goto bail;
}
SET_PROGRESS_BEGIN();
/*
* Generally speaking, anything in a BNY file is going to be small. The
* major exception is a BXY file, which could be huge. However, the
* SHK embedded in a BXY is never squeezed.
*
* To make life easy, we either unsqueeze the entire thing into a buffer
* and then write that, or we do a file-to-file copy of the specified
* number of bytes.
*/
if (GetSqueezed()) {
ExpandBuffer expBuf;
bool lastCR = false;
char* buf;
long uncLen;
nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(),
&expBuf, false, 0);
if (nerr != kNuErrNone) {
pErrMsg->Format("File read failed: %s", NuStrError(nerr));
goto bail;
}
expBuf.SeizeBuffer(&buf, &uncLen);
WMSG2("Unsqueezed %ld bytes to %d\n", len, uncLen);
// some bonehead squeezed a zero-length file
if (uncLen == 0) {
ASSERT(buf == nil);
WMSG0("Handling zero-length squeezed file!\n");
result = IDOK;
goto bail;
}
int err = GenericEntry::WriteConvert(outfp, buf, uncLen, &conv,
&convHA, &lastCR);
if (err != 0) {
pErrMsg->Format("File write failed: %s", strerror(err));
delete[] buf;
goto bail;
}
delete[] buf;
} else {
nerr = CopyData(outfp, conv, convHA, pErrMsg);
if (nerr != kNuErrNone) {
if (pErrMsg->IsEmpty()) {
pErrMsg->Format("Failed while copying data: %s\n",
NuStrError(nerr));
}
goto bail;
}
}
result = IDOK;
bail:
SET_PROGRESS_END();
return result;
}
/*
* Copy data from the seeked archive to outfp, possibly converting EOL along
* the way.
*/
NuError
AcuEntry::CopyData(FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA,
CString* pMsg) const
{
NuError nerr = kNuErrNone;
const int kChunkSize = 8192;
char buf[kChunkSize];
bool lastCR = false;
long srcLen, dataRem;
srcLen = (long) GetUncompressedLen();
ASSERT(srcLen > 0); // empty files should've been caught earlier
/*
* Loop until all data copied.
*/
dataRem = srcLen;
while (dataRem) {
int chunkLen;
if (dataRem > kChunkSize)
chunkLen = kChunkSize;
else
chunkLen = dataRem;
/* read a chunk from the source file */
nerr = fpArchive->AcuRead(buf, chunkLen);
if (nerr != kNuErrNone) {
pMsg->Format("File read failed: %s.", NuStrError(nerr));
goto bail;
}
/* write chunk to destination file */
int err = GenericEntry::WriteConvert(outfp, buf, chunkLen, &conv,
&convHA, &lastCR);
if (err != 0) {
pMsg->Format("File write failed: %s.", strerror(err));
nerr = kNuErrGeneric;
goto bail;
}
dataRem -= chunkLen;
SET_PROGRESS_UPDATE(ComputePercent(srcLen - dataRem, srcLen));
}
bail:
return nerr;
}
/*
* Test this entry by extracting it.
*
* If the file isn't compressed, just make sure the file is big enough. If
* it's squeezed, invoke the un-squeeze function with a "nil" buffer pointer.
*/
NuError
AcuEntry::TestEntry(CWnd* pMsgWnd)
{
NuError nerr = kNuErrNone;
CString errMsg;
long len;
int result = -1;
len = (long) GetUncompressedLen();
if (len == 0)
goto bail;
errno = 0;
if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) {
nerr = kNuErrGeneric;
errMsg.Format("Unable to seek to offset %ld: %s\n",
fOffset, strerror(errno));
ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED);
goto bail;
}
if (GetSqueezed()) {
nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(),
nil, false, 0);
if (nerr != kNuErrNone) {
errMsg.Format("Unsqueeze failed: %s.", NuStrError(nerr));
ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED);
goto bail;
}
} else {
errno = 0;
if (fseek(fpArchive->fFp, fOffset + len, SEEK_SET) < 0) {
nerr = kNuErrGeneric;
errMsg.Format("Unable to seek to offset %ld (file truncated?): %s\n",
fOffset, strerror(errno));
ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED);
goto bail;
}
}
if (SET_PROGRESS_UPDATE(100) == IDCANCEL)
nerr = kNuErrAborted;
bail:
return nerr;
}
/*
* ===========================================================================
* AcuArchive
* ===========================================================================
*/
/*
* Perform one-time initialization. There really isn't any for us.
*
* Returns 0 on success, nonzero on error.
*/
/*static*/ CString
AcuArchive::AppInit(void)
{
return "";
}
/*
* Open an ACU archive.
*
* Returns an error string on failure, or "" on success.
*/
GenericArchive::OpenResult
AcuArchive::Open(const char* filename, bool readOnly, CString* pErrMsg)
{
CString errMsg;
fIsReadOnly = true; // ignore "readOnly"
errno = 0;
fFp = fopen(filename, "rb");
if (fFp == nil) {
errMsg.Format("Unable to open %s: %s.", filename, strerror(errno));
goto bail;
}
{
CWaitCursor waitc;
int result;
result = LoadContents();
if (result < 0) {
errMsg.Format("The file is not an ACU archive.");
goto bail;
} else if (result > 0) {
errMsg.Format("Failed while reading data from ACU archive.");
goto bail;
}
}
SetPathName(filename);
bail:
*pErrMsg = errMsg;
if (!errMsg.IsEmpty())
return kResultFailure;
else
return kResultSuccess;
}
/*
* Finish instantiating an AcuArchive object by creating a new archive.
*
* Returns an error string on failure, or "" on success.
*/
CString
AcuArchive::New(const char* /*filename*/, const void* /*options*/)
{
CString retmsg("Sorry, AppleLink Compression Utility files can't be created.");
return retmsg;
}
/*
* Our capabilities.
*/
long
AcuArchive::GetCapability(Capability cap)
{
switch (cap) {
case kCapCanTest:
return true;
break;
case kCapCanRenameFullPath:
return true;
break;
case kCapCanRecompress:
return true;
break;
case kCapCanEditComment:
return false;
break;
case kCapCanAddDisk:
return false;
break;
case kCapCanConvEOLOnAdd:
return false;
break;
case kCapCanCreateSubdir:
return false;
break;
case kCapCanRenameVolume:
return false;
break;
default:
ASSERT(false);
return -1;
break;
}
}
/*
* Load the contents of the archive.
*
* Returns 0 on success, < 0 if this is not an ACU archive > 0 if this appears
* to be an ACU archive but it's damaged.
*/
int
AcuArchive::LoadContents(void)
{
NuError nerr;
int numEntries;
ASSERT(fFp != nil);
rewind(fFp);
/*
* Read the master header. In an ACU file this holds the number of
* files and a bunch of stuff that doesn't seem to change.
*/
if (ReadMasterHeader(&numEntries) != 0)
return -1;
while (numEntries) {
AcuFileEntry fileEntry;
nerr = ReadFileHeader(&fileEntry);
if (nerr != kNuErrNone)
return 1;
if (CreateEntry(&fileEntry) != 0)
return 1;
/* if file isn't empty, seek past it */
if (fileEntry.dataStorageLen) {
nerr = AcuSeek(fileEntry.dataStorageLen);
if (nerr != kNuErrNone)
return 1;
}
numEntries--;
}
return 0;
}
/*
* Reload the contents of the archive.
*/
CString
AcuArchive::Reload(void)
{
fReloadFlag = true; // tell everybody that cached data is invalid
DeleteEntries();
if (LoadContents() != 0) {
return "Reload failed.";
}
return "";
}
/*
* Read the archive header. The archive file is left seeked to the point
* at the end of the header.
*
* Returns 0 on success, -1 on failure. Sets *pNumEntries to the number of
* entries in the archive.
*/
int
AcuArchive::ReadMasterHeader(int* pNumEntries)
{
AcuMasterHeader header;
unsigned char buf[kAcuMasterHeaderLen];
NuError nerr;
nerr = AcuRead(buf, kAcuMasterHeaderLen);
if (nerr != kNuErrNone)
return -1;
header.fileCount = buf[0x00] | buf[0x01] << 8;
header.unknown1 = buf[0x02] | buf[0x03] << 8;
memcpy(header.fZink, &buf[0x04], 5);
header.fZink[5] = '\0';
memcpy(header.unknown2, &buf[0x09], 11);
if (header.fileCount == 0 ||
header.unknown1 != 1 ||
strcmp((char*) header.fZink, "fZink") != 0)
{
WMSG0("Not an ACU archive\n");
return -1;
}
WMSG1("Looks like an ACU archive with %d entries\n", header.fileCount);
*pNumEntries = header.fileCount;
return 0;
}
/*
* Read and decode an AppleLink Compression Utility file entry header.
* This leaves the file seeked to the point immediately past the filename.
*/
NuError
AcuArchive::ReadFileHeader(AcuFileEntry* pEntry)
{
NuError err = kNuErrNone;
unsigned char buf[kAcuEntryHeaderLen];
ASSERT(pEntry != nil);
err = AcuRead(buf, kAcuEntryHeaderLen);
if (err != kNuErrNone)
goto bail;
// unknown at 00
pEntry->compressionType = buf[0x01];
// unknown at 02-03
pEntry->dataChecksum = buf[0x04] | buf[0x05] << 8; // not sure
// unknown at 06-09
pEntry->blockCount = buf[0x0a] | buf[0x0b] << 8;
// unknown at 0c-11
pEntry->dataStorageLen = buf[0x12] | buf [0x13] << 8 | buf[0x14] << 16 |
buf[0x15] << 24;
pEntry->access = buf[0x16] | buf[0x17] << 8;
pEntry->fileType = buf[0x18] | buf[0x19] << 8;
pEntry->auxType = buf[0x1a] | buf[0x1b] << 8;
// unknown at 1e-1f
pEntry->storageType = buf[0x20];
// unknown at 21-25
pEntry->dataEof = buf[0x26] | buf[0x27] << 8 | buf[0x28] << 16 |
buf[0x29] << 24;
pEntry->prodosModDate = buf[0x2a] | buf[0x2b] << 8;
pEntry->prodosModTime = buf[0x2c] | buf[0x2d] << 8;
AcuConvertDateTime(pEntry->prodosModDate, pEntry->prodosModTime,
&pEntry->modWhen);
pEntry->prodosCreateDate = buf[0x2e] | buf[0x2f] << 8;
pEntry->prodosCreateTime = buf[0x30] | buf[0x31] << 8;
AcuConvertDateTime(pEntry->prodosCreateDate, pEntry->prodosCreateTime,
&pEntry->createWhen);
pEntry->fileNameLen = buf[0x32] | buf[0x33] << 8;
pEntry->headerChecksum = buf[0x34] | buf[0x35] << 8; // not sure
/* read the filename */
if (pEntry->fileNameLen > kAcuMaxFileName) {
WMSG1("GLITCH: filename is too long (%d bytes)\n",
pEntry->fileNameLen);
err = kNuErrGeneric;
goto bail;
}
if (!pEntry->fileNameLen) {
WMSG0("GLITCH: filename missing\n");
err = kNuErrGeneric;
goto bail;
}
/* don't know if this is possible or not */
if (pEntry->storageType == 5) {
WMSG0("HEY: EXTENDED FILE\n");
}
err = AcuRead(pEntry->fileName, pEntry->fileNameLen);
if (err != kNuErrNone)
goto bail;
pEntry->fileName[pEntry->fileNameLen] = '\0';
//DumpFileHeader(pEntry);
bail:
return err;
}
/*
* Dump the contents of an AcuFileEntry struct.
*/
void
AcuArchive::DumpFileHeader(const AcuFileEntry* pEntry)
{
time_t createWhen, modWhen;
CString createStr, modStr;
createWhen = NufxArchive::DateTimeToSeconds(&pEntry->createWhen);
modWhen = NufxArchive::DateTimeToSeconds(&pEntry->modWhen);
FormatDate(createWhen, &createStr);
FormatDate(modWhen, &modStr);
WMSG1(" Header for file '%s':\n", pEntry->fileName);
WMSG4(" dataStorageLen=%d eof=%d blockCount=%d checksum=0x%04x\n",
pEntry->dataStorageLen, pEntry->dataEof, pEntry->blockCount,
pEntry->dataChecksum);
WMSG4(" fileType=0x%02x auxType=0x%04x storageType=0x%02x access=0x%04x\n",
pEntry->fileType, pEntry->auxType, pEntry->storageType, pEntry->access);
WMSG2(" created %s, modified %s\n", (const char*) createStr,
(const char*) modStr);
WMSG2(" fileNameLen=%d headerChecksum=0x%04x\n",
pEntry->fileNameLen, pEntry->headerChecksum);
}
/*
* Given an AcuFileEntry structure, add an appropriate entry to the list.
*/
int
AcuArchive::CreateEntry(const AcuFileEntry* pEntry)
{
const int kAcuFssep = '/';
NuError err = kNuErrNone;
AcuEntry* pNewEntry;
/*
* Create the new entry.
*/
pNewEntry = new AcuEntry(this);
pNewEntry->SetPathName(pEntry->fileName);
pNewEntry->SetFssep(kAcuFssep);
pNewEntry->SetFileType(pEntry->fileType);
pNewEntry->SetAuxType(pEntry->auxType);
pNewEntry->SetAccess(pEntry->access);
pNewEntry->SetCreateWhen(NufxArchive::DateTimeToSeconds(&pEntry->createWhen));
pNewEntry->SetModWhen(NufxArchive::DateTimeToSeconds(&pEntry->modWhen));
/* always ProDOS? */
pNewEntry->SetSourceFS(DiskImg::kFormatProDOS);
pNewEntry->SetHasDataFork(true);
pNewEntry->SetHasRsrcFork(false); // ?
if (IsDir(pEntry)) {
pNewEntry->SetRecordKind(GenericEntry::kRecordKindDirectory);
} else {
pNewEntry->SetRecordKind(GenericEntry::kRecordKindFile);
}
pNewEntry->SetCompressedLen(pEntry->dataStorageLen);
pNewEntry->SetDataForkLen(pEntry->dataEof);