Compare commits

...

63 Commits

Author SHA1 Message Date
Andy McFadden
fc2fc1429d
Add link to CiderPress II 2023-12-28 10:37:40 -08:00
Andy McFadden
53c4050b09 Version 4.1.1 2023-05-12 16:12:15 -07:00
Andy McFadden
e4cf9d8ba5 Fix DOS T/S end-of-list test
Only affects a small percentage of very large or sparse files.

(issue #59)
2023-03-10 17:25:13 -08:00
Andy McFadden
118b306e11 Recompile help blob
The hardest part is finding the HTML Help Workshop installer.

http://web.archive.org/web/20160201063255/http://download.microsoft.com/download/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe
http://web.archive.org/web/20160314043751/http://download.microsoft.com/download/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/helpdocs.zip
2023-01-14 21:19:33 -08:00
Andy McFadden
1d53e4bcae
Merge pull request #57 from polluks2/master
Fixed some typos
2023-01-14 15:16:34 -08:00
polluks
508475a094 Fixed some typos 2023-01-14 23:42:17 +01:00
Andy McFadden
a1218a8dcb Update URLs 2022-10-08 09:20:32 -07:00
Andy McFadden
0790c97ee2 Fix comment 2022-08-07 12:53:29 -07:00
Andy McFadden
5f5c089506 Update to Visual Studio 2022 2022-06-15 08:17:39 -07:00
Andy McFadden
f63738444c Version 4.1.1-d1 2022-01-07 11:35:36 -08:00
Andy McFadden
2cb5bf0dcc Fix file viewer layout
If scaling > 100% is enabled on the primary display, the controls in
the dialog window get bigger.  The file viewer uses hard-coded values
for the initial and minimum window size, which causes the expanded
controls to draw on top of each other.  (Issue #53.)

We now query the system for the scale factor, and adjust the window
size accordingly.
2022-01-07 11:34:46 -08:00
Andy McFadden
b42cc8efe9 Fix Linux build
gcc is justifiably annoyed by variable initialization crossed by
a goto.

(issue #51)
2021-09-07 13:36:28 -07:00
Andy McFadden
5950cb7c74 Version 4.1.0 2021-08-16 15:20:10 -07:00
Andy McFadden
b87037b75e Version 4.1.0-d3 2021-07-23 19:24:15 -07:00
Andy McFadden
d39c61255c Work around ProDOS sparse block issue
It appears that some programs, notably Copy ][+ and the GS/OS FST,
expect that the first block of a sparse file will always be
allocated, even if it's just 512 zeroes.  I've only seen this fail
in cases where the first entry in the master index block of a "tree"
file is zero, because the first 128KB are sparse, but rumor has it
that the issue can affect "sapling" files as well.

This changes CiderPress to work the way ProDOS does: always allocate
a block to hold the first 512 bytes of the file.  The only exception
to this is a file that is nothing but zeroes (perhaps populated by
creating a file and setting its EOF to something large), which can
be stored as a seedling.

(for issues #15 and #49)
2021-07-23 18:52:23 -07:00
Andy McFadden
e098069b10 Version 4.1.0-d2 2021-05-10 17:42:39 -07:00
Andy McFadden
6de7cfefc0 Properly restore negative window positions
It's okay to have the window off the top/left edge of the primary
display, but CiderPress was rejecting the values and reverting to
default placement.

(for issue #41)
2021-05-10 16:01:45 -07:00
Andy McFadden
e782a9df6e Update README to note loss of WinXP support 2021-05-10 14:51:37 -07:00
Andy McFadden
4235b47748 Save and restore main window placement
Windows' default behavior is apparently to fill the display with the
app window, capped at 1920x1200.  This is annoyingly large for most
situations.

We now save the main window rect (LTRB) and maximization status in
the configuration area of the registry.  The window placement calls
are supposed to do something reasonable when the window would be
completely off-screen (e.g. because a secondary monitor was disabled).
2021-05-10 14:15:49 -07:00
Andy McFadden
eff69cce86 Fix a few compiler warnings
Mostly uninitialized class members.  Should not cause a change in
behavior.
2021-05-09 18:43:59 -07:00
Andy McFadden
adaeb2c6eb Fix warnings
Added explicit casts and class initializers.  The problems were
identified by the VS2019 compiler.
2021-04-24 13:43:04 -07:00
Andy McFadden
8a6a4ada5c Update to latest build tools (breaks WinXP)
This updates the project to use the VS2019 toolchain (v142).  Note
this breaks WinXP compatibility.

The MFC and VC runtime DLLs have been updated from v120 to v140.

The program version has been updated to v4.1.0-d1.
2021-04-24 11:38:41 -07:00
Andy McFadden
295d9c269c Version 4.0.5 2021-04-24 10:05:44 -07:00
Andy McFadden
9698f46eae Revert "Workaround for egregious window placement behavior"
This reverts commit 0a317cb0e7.
2021-04-24 09:59:35 -07:00
Andy McFadden
17689a7b23 Merge branch 'master' of https://github.com/fadden/ciderpress 2021-04-18 17:16:58 -07:00
Andy McFadden
1f17f9747d Version 4.0.5-d2 2021-04-18 17:16:29 -07:00
Andy McFadden
0a317cb0e7 Workaround for egregious window placement behavior
Windows is currently creating the main window at near-maximal size.
It used to remember the size and placement, but no longer does.

As a workaround, the initial size is set to 1150x800, which is large
enough to show all columns without scrolling even with very wide
pathnames.  With some effort this could be modified to respect the
maximum size of the monitor on which it will be displayed, so that
anyone still running at 1024x768 won't be in a bad place.

Ideally it would remember the previous size and position.  See
issue #41 for discussion.
2021-04-18 17:06:01 -07:00
Andy McFadden
27cefa61d3
Merge pull request #47 from markdavidlong/dosnames
Raw Filename Accessor in A2File, et al.
2021-03-01 16:16:11 -08:00
mlong
8813a5efd9 Fixed typo. 2021-02-28 12:28:27 -06:00
mlong
dcefd2d2b6 Fixed a couple of stupid copy/paste errors 2021-02-27 18:24:28 -06:00
mlong
db3ca0a8ca Added file length size option to getRawFileName 2021-02-27 16:51:40 -06:00
mlong
fd4ac77bcf Added raw filename to A2File and children. Handled in RDOS and DOS types, especially. 2021-02-26 18:36:20 -06:00
mlong
95c0ec7348 Updating .gitignore 2021-02-26 18:12:29 -06:00
Andy McFadden
7c637c4e6d Fix MakeDisk utility
This addresses two issues: (1) failing to check for regular files;
(2) failing to test for files larger than 2GB.

(issue #44)
2020-11-07 09:17:14 -08:00
Andy McFadden
9de0b42147 Update dist config 2020-08-03 13:59:43 -07:00
Andy McFadden
008d13a4b1 Version 4.0.5-d1 2020-08-03 13:52:38 -07:00
Andy McFadden
5e9d8f0102 Fix crash in IsSCAssem
The test for "is this an S-C Assembler source file" tried to
dereference a null pointer when asked to examine a file with a
zero-length data fork.  The test only fires for files with type=INT
and auxType=0, so this is pretty hard to hit.  The specific failing
case had a damaged file with the appropriate file type.

Issue #42
2020-08-03 13:47:42 -07:00
Andy McFadden
a85ceca75f Version 4.0.4 2020-07-23 14:53:58 -07:00
Andy McFadden
fb25998be5 Fix handling of ProDOS disks with short volume directories
The ProDOS code was assuming that the volume directory was 4 blocks
long.  Some disks, such as the ProDOS 2.4.2 distribution disk, only
use the first two blocks.  CiderPress now scans the volume directory
to determine the actual length.

Fixes issue #32.
2020-07-23 14:12:16 -07:00
Andy McFadden
21151cd76a Version 4.0.4-d2 2020-07-12 11:10:44 -07:00
Andy McFadden
e5ac0ac631 Fix OMF version confusion
VERSION=0/1/2 corresponds, simply, to v0/v1/v2, where v0 was only
used for some older 8-bit Orca/M stuff.  v2.1 can be detected by
looking for the optional "tempOrg" field.

Also, allow the disk version number to be set to zero in 2IMG images.
2020-06-25 14:12:29 -07:00
Andy McFadden
e625ab5f3a Version 4.0.4-d1
The latest DeployMaster got fussy about registry keys and whether
it's installing for the computer or a single user.  Seemed to work
okay on my system.
2020-03-26 11:09:20 -07:00
Andy McFadden
8d5e07e683 Allow files larger than 16MB to be added to HFS volumes
Ideally this would add a "what's your limit" call to the disk image
library, but this will do for now.
2020-03-26 11:08:24 -07:00
Andy McFadden
8ecb8e35eb Fix INSTR( token in Apple /// Business BASIC
Should be "INSTR(" rather than "INSTR$(".  Fixes issue #38.
2019-10-27 08:05:12 -07:00
Andy McFadden
31197837fe Update version to 4.0.3 2017-12-12 10:54:20 -08:00
Andy McFadden
da182e1c61 Change file extraction extension handling
When extracting files, you can ask CiderPress to add a file extension
by checking the "add file extension" box.  Whether or not this box
is checked, files that undergo a format conversion (e.g. AWP to RTF,
or SHR to BMP) have a file extension added to identify the file's
new format.

This turned out to be confusing and inconvenient at times, notably
when working with Merlin source files.  See issues #10 and #26 on
github for details.

CiderPress no longer adds file extensions to format-converted files
unless the "add file extension" box is checked.  (The "Configure for
easy access in Windows" button checks this box for you, so the
default behavior is still "safe".)

Also, fix a minor visual glitch in the extract dialog.

Also, update to version 4.0.3-a3.
2017-12-01 13:48:50 -08:00
Andy McFadden
1c2b187a32 Release v4.0.3-a2 2017-11-13 14:33:08 -08:00
Andy McFadden
2adbe9591f Add optional MouseText-to-ASCII conversion
The AWP5 MouseText output is okay for some things but not others.
This adds an ASCII conversion, enabled through a preference.
2017-11-13 14:24:58 -08:00
Andy McFadden
3d88397024 Adjust width of extract dialog
The last letter of "Auto-detect & convert files with text" was being
cut off.
2017-11-13 12:59:34 -08:00
Andy McFadden
35a897b248 Add support for AW5 inverse and MouseText
AppleWorks 5 added inverse text and MouseText.  We can handle inverse
text with RTF features, and convert MouseText to something vaguely
similar in the Unicode symbol set.
2017-11-11 14:53:28 -08:00
Andy McFadden
640959dad5 Fix 64-bit math error
32-bit * 32-bit = 32-bit, so disk images with partitions whose size
exceeded the capacity of a 32-bit int were coming out wrong.

Updated version to 4.0.3-a1.
2017-10-30 10:17:54 -07:00
Andy McFadden
c2e3fb8353 Update version for v4.0.2 release 2017-09-22 17:40:23 -07:00
Andy McFadden
d35a9670b5 Rework Super Hi-Res handling, particularly APF
We weren't handling oddly sized images well.  This was mostly a
problem for Apple Preferred Format, PNT/$0002.
2017-09-22 16:23:33 -07:00
Andy McFadden
549342b3d9 Fix file viewer glitch with empty output
The file viewer was seeing zero-length formatted output and assuming
that it was the result of zero-length input.  This is a problem
because the code disables the format options when there's nothing to
format.  This resulted in the strange behavior noted in issue #14.

Now the "is source empty" value is passed explicitly, and we display
a different message when the formatter fails.
2017-09-22 11:25:08 -07:00
Andy McFadden
9f0640142d Update deploy file for v4.0.2-a3 2017-09-21 15:06:38 -07:00
Andy McFadden
1797536793 Update version to 4.0.2-a3 2017-09-21 13:59:33 -07:00
Andy McFadden
8e326f2f62 Fix for issue #20
Reject NuDateTime structs with invalid fields.  Passing bogus values
to the ATL CTime constructor does bad things.
2017-09-21 12:20:16 -07:00
Andy McFadden
a8c2e4cfd6 Bump copyright date 2016-01-11 13:52:30 -08:00
Andy McFadden
c1694deb7e Added notes about VS2015CE and WinXP 2016-01-11 13:41:54 -08:00
Andy McFadden
98f098d421 Half-step toward VS2015 CE
When initially opened in Visual Studio 2015 Community Edition, the
project was updated to use the v140_xp toolset.  When the program
was run under WinXP it complained about a missing runtime DLL.  When
the DLL was provided, it complained about another one (with a
slightly strange name).  So I reverted the tools to v120_xp, i.e.
Visual Studio 2013.  (I don't know if this works because the tools
are included with VS2015, or because I have VS2013 installed and it
managed to find them.)

Whatever the case, it now builds for me with either IDE, and seems
to work fine on Windows XP, but I'd like to figure out why the XP
build isn't working with the v140_xp tools.
2016-01-11 11:33:41 -08:00
Andy McFadden
9e2fded3b9 Bump version to v4.0.2-a2 2016-01-11 11:16:01 -08:00
Andy McFadden
c7869c38a5 Initialize fUseRTF to "true"
The field wasn't being initialized, so if you did things in a
certain way (open a .SDK as a ShrinkIt archive, double-click on
the disk image, then view an AppleWorks AWP document), the flag
might be initialized to "false" and you'd lose the formatting.
2016-01-11 10:53:32 -08:00
Andy McFadden
6153b0f9a1 Pull in recent nufxlib changes
Update to v3.1.0-a2.
2016-01-11 10:30:08 -08:00
89 changed files with 1823 additions and 536 deletions

415
.gitignore vendored
View File

@ -1,27 +1,402 @@
# build product output directories (top-level and component)
Debug
Release
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# precompiled headers
ipch
# CiderPress-specific
DIST/Setup*.exe
DIST/CiderPress*.zip
# binaries generated by Visual Studio
CP.sdf
CP.opensdf
CP.v12.suo
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# installer binary
DIST/Setup*.exe
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# linux binaries
*.o
diskimg/libdiskimg.a
diskimg/libhfs/libhfs.a
# Paket dependency manager
.paket/paket.exe
paket-files/
# ctags
tags
# FAKE - F# Make
.fake/
# VIM
*~
*.swp
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

View File

@ -1,5 +1,5 @@
End-User License Agreement for CiderPress
Copyright (c) 2014, CiderPress project authors
Copyright (C) 2017, CiderPress project authors
All rights reserved.
AGREEMENT. After reading this agreement carefully, if you ("Customer") do

Binary file not shown.

BIN
DIST/mfc140u.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
DIST/vcruntime140.dll Normal file

Binary file not shown.

View File

@ -1,17 +1,26 @@
DeployMaster Installation Script
16
720
faddenSoft
http://www.faddensoft.com/
CiderPress
http://a2ciderpress.com/
4.0.2-a1
42364
4.1.1
TRUE
45058
C:\DATA\faddenSoft\fs.ico
Copyright © 2015 CiderPress project authors. All rights reserved.
Copyright © 2023 CiderPress project authors. All rights reserved.
C:\Src\CiderPress\DIST\ReadMe.txt
C:\Src\CiderPress\DIST\License.txt
FALSE
FALSE
%PROGRAMFILES%\faddenSoft\CiderPress
%COMMONFILES%\faddenSoft\
%PROGRAMSMENU%\CiderPress
TRUE
TRUE
%PROGRAMFILES%\faddenSoft\CiderPress
%COMMONFILES%\faddenSoft\
%PROGRAMSMENU%\CiderPress
@ -24,14 +33,28 @@ FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
TRUE
TRUE
TRUE
TRUE
1507
9999
TRUE
21H2
9999
TRUE
1
You are attempting to run the installer for %APP% %VERSION%. This installer supports the following versions of Windows: %INSTALLER%. You are running %USER%. Please check the developer's website to see whether there is a separate installer for %APP% that you can use on %USER%.
FALSE
FALSE
FALSE
FALSE
3
The installer for %APP% %VERSION% needs to be able to write to folders that look like they are being protected by Controlled Folder Access in Windows Defender.
You will need to add %FILE% to the list of apps allowed through Controlled Folder Access in Windows Defender. Do this before you click Yes to continue with the installation. Otherwise the installer will not be able to properly install %APP% %VERSION%.
TRUE
TRUE
1
@ -165,16 +188,16 @@ FALSE
1
FALSE
+
C:\Src\ciderpress\DIST\mfc120u.dll
C:\Src\ciderpress\DIST\mfc140u.dll
3
0
1
TRUE
TRUE
FALSE
FALSE
C:\Src\ciderpress\DIST\msvcr120.dll
C:\Src\ciderpress\DIST\vcruntime140.dll
3
0
1
TRUE
TRUE
FALSE
@ -281,6 +304,14 @@ FALSE
TRUE
CiderPress
+
HKEY_AUTO
0
FALSE
+
Software
0
FALSE
-
HKEY_CLASSES_ROOT
0
FALSE
@ -320,6 +351,14 @@ TRUE
-
-
-
HKEY_USERS
0
FALSE
+
Software
0
FALSE
-
-
0
FALSE
@ -351,13 +390,21 @@ FALSE
0
FALSE
36725
FALSE
43446
FALSE
365
0
0
4095
Setup402a1.exe
Setup411.exe
FALSE
TRUE
FALSE
FALSE

View File

@ -2,7 +2,10 @@ CiderPress
==========
A Windows utility for managing Apple II file archives and disk images.
Visit the web site at http://a2ciderpress.com/.
Visit the web site at https://a2ciderpress.com/
(or https://fadden.github.io/ciderpress).
**NEW!** CiderPress II is now available from [github](https://github.com/fadden/CiderPress2).
CiderPress was initially sold by faddenSoft, LLC as a shareware product,
starting in March 2003. In March 2007, the program was released as
@ -71,13 +74,9 @@ is not acceptable, you can remove HFS disk image support from CiderPress
Building the Sources
--------------------
The current version of CiderPress is targeted for Visual Studio 2013,
using the WinXP compatibility Platform Toolset to allow installation on
Windows XP systems. You should be able to select Debug or Release and
just build the entire thing.
If you want to use the static analyzer, you will need to change the
Platform Toolset to straight Visual Studio 2013.
The current version of CiderPress is targeted for Visual Studio 2019
Community Edition (i.e. the free version). You should be able to select
Debug or Release and just build the entire thing.
A pre-compiled .CHM file, with the help text and pop-up messages,
is provided. The source files are all included, but generation of the
@ -85,7 +84,7 @@ is provided. The source files are all included, but generation of the
you will need to download the HTML Help Workshop from Microsoft, and use
that to compile the help project in the app/Help directory.
The installer binary is created with [DeployMaster](http://deploymaster.com/).
The installer binary is created with [DeployMaster](https://deploymaster.com/).
Building for Linux
@ -167,8 +166,8 @@ Miscellaneous utility functions.
#### NufxLib and zlib ####
These are source snapshots from [NufxLib](http://github.com/fadden/nulib2)
and [zlib](http://www.zlib.org).
These are source snapshots from [NufxLib](https://github.com/fadden/nulib2)
and [zlib](https://zlib.net).
#### DIST ####
@ -176,7 +175,7 @@ Files used when making a distribution, notably:
- the DeployMaster configuration file
- the license and README files that are included in the installer
- redistributable Windows runtime libraries (only needed on WinXP?)
- redistributable Windows runtime libraries
- NiftyList data file
@ -218,18 +217,16 @@ are expected to build on Linux, so converting them is a bit of a pain. At
some point it may be necessary to support Unicode fully. v4.0 did a lot of
code reorganization to make this easier, as did NufxLib v3.0.
4. Windows XP support. The default Visual Studio 2013 configuration creates
executables that do not work in Windows XP. CiderPress uses a compatibility
toolset and packs about 5MB of additional DLLs (mfc120u.dll, msvcr120.dll) in
the install package to keep things working. At some point it may not be
possible to support WinXP, or building for WinXP will prevent something from
working. The good news is that, for the current round of tools, it's
possible to build a single binary that works fully on WinXP and later systems.
5. Installer magic. Security improvements and changes like the Win8 "Metro"
4. Installer magic. Security improvements and changes like the Win8 "Metro"
launcher affect the way apps are installed and launched. So far the only
impact on CiderPress was to the file association handling (the stuff that
allows you to double-click a file and have CiderPress open it), but it's
likely that future OS changes will require matching app changes. The use
of DeployMaster is helpful here, as it has been kept up-to-date with changes
in Windows.
[ENDED] Windows XP support. Starting with the Visual Studio 2013 tools,
building an app that would work under WinXP required jumping through some
hoops. Microsoft's support for WinXP officially ended in April 2014.
CiderPress continued to support WinXP for several years, but support has been
dropped due to the added testing and maintenance burdens.

View File

@ -28,14 +28,8 @@ public:
kActionConvFile,
} Action;
ActionProgressDialog(void) {
fAction = kActionUnknown;
//fpSelSet = NULL;
//fpOptionsDlg = NULL;
fCancel = false;
//fResult = 0;
}
virtual ~ActionProgressDialog(void) {}
ActionProgressDialog(void) : fAction(kActionUnknown), fCancel(false) { }
virtual ~ActionProgressDialog(void) { }
BOOL Create(Action action, CWnd* pParentWnd = NULL) {
fAction = action;

View File

@ -912,6 +912,16 @@ bool MainWindow::ExtractEntry(GenericEntry* pEntry, int thread,
break;
}
/*
* Issue #26: if "add type extension" is not checked, don't add
* the format converter extension. This is useful for Merlin
* source files where you want to do the text conversion but still
* want the file to end with ".S".
*/
if (!pExtOpts->fAddExtension) {
noChangePath = true;
}
if (goodReformat) {
if (!noChangePath)
outputPath = tmpPath;

View File

@ -58,11 +58,16 @@ END
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME ICON "Graphics\\CiderPress.ico"
IDI_FILE_BINARY2 ICON "Graphics\\binary2.ico"
IDI_FILE_NUFX ICON "Graphics\\nufx.ico"
IDI_FILE_DISKIMAGE ICON "Graphics\\diskimage.ico"
IDI_FILE_VIEWER ICON "Graphics\\FileViewer.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
@ -222,11 +227,11 @@ BEGIN
PUSHBUTTON "Enter registration code",IDC_ABOUT_ENTER_REG,157,132,86,14
CONTROL IDB_FSLOGO,IDC_STATIC,"Static",SS_BITMAP,7,6,64,59
LTEXT "CiderPress v%d.%d.%d%ls%ls",IDC_CIDERPRESS_VERS_TEXT,77,7,167,9
LTEXT "Copyright © 2015 by CiderPress project authors\rAll Rights Reserved.",IDC_STATIC,77,20,167,19
ICON IDR_MAINFRAME,IDC_STATIC,77,45,21,20
ICON IDI_FILE_NUFX,IDC_STATIC,106,45,21,20
ICON IDI_FILE_BINARY2,IDC_STATIC,136,45,21,20
ICON IDI_FILE_DISKIMAGE,IDC_STATIC,166,45,21,20
LTEXT "Copyright © 2021 by CiderPress project authors.\rAll Rights Reserved.",IDC_STATIC,77,20,167,19
ICON IDR_MAINFRAME,IDC_STATIC,77,45,20,20
ICON IDI_FILE_NUFX,IDC_STATIC,106,45,20,20
ICON IDI_FILE_BINARY2,IDC_STATIC,136,45,20,20
ICON IDI_FILE_DISKIMAGE,IDC_STATIC,166,45,20,20
GROUPBOX "Libraries",IDC_STATIC,7,71,237,56
LTEXT "Using NufxLib DLL v%d.%d.%d",IDC_NUFXLIB_VERS_TEXT,16,82,170,10
LTEXT "Using DiskImg DLL v%d.%d.%d",IDC_DISKIMG_VERS_TEXT,16,92,172,8
@ -315,12 +320,12 @@ BEGIN
PUSHBUTTON "Help",IDHELP,376,242,50,14
END
IDD_PREF_FVIEW DIALOGEX 0, 0, 216, 263
IDD_PREF_FVIEW DIALOGEX 0, 0, 217, 274
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTEXTHELP | WS_CHILD | WS_CAPTION
CAPTION "File Viewer"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
GROUPBOX "Converters",IDC_STATIC,4,7,208,139
GROUPBOX "Converters",IDC_STATIC,4,7,209,139
CONTROL "High-ASCII &text",IDC_PVIEW_HITEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,19,88,10
CONTROL "&CP/M text",IDC_PVIEW_CPMTEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,30,92,10
CONTROL "&Pascal text",IDC_PVIEW_PASCALTEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,41,87,10
@ -343,7 +348,7 @@ BEGIN
CONTROL "MacPaint images",IDC_PVIEW_MACPAINT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,118,93,10
CONTROL "&Relax type-checking on graphics",IDC_PVIEW_RELAX_GFX,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,50,131,116,10
GROUPBOX "Conversion options",IDC_STATIC,4,150,208,90
GROUPBOX "Conversion options",IDC_STATIC,4,150,209,101
CONTROL "&Scroll horizontally instead of wrapping words",IDC_PVIEW_NOWRAP_TEXT,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,162,192,10
CONTROL "Highlight &hex dump columns (small files)",IDC_PVIEW_BOLD_HEXDUMP,
@ -354,12 +359,14 @@ BEGIN
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,195,189,10
CONTROL "Prefer &B&&W for hi-res images",IDC_PVIEW_HIRES_BW,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,206,148,10
LTEXT "Preferred DHR mode:",IDC_STATIC,12,223,69,8
COMBOBOX IDC_PVIEW_DHR_CONV_COMBO,84,220,118,48,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "Viewer file size &limit:",IDC_STATIC,4,247,62,8
EDITTEXT IDC_PVIEW_SIZE_EDIT,69,245,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "Spin2",IDC_PVIEW_SIZE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,112,247,11,14
LTEXT "KBytes",IDC_STATIC,110,247,36,8
CONTROL "Convert MouseText to ASCII",IDC_PVIEW_MOUSETEXT_TO_ASCII,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,217,194,10
LTEXT "Preferred DHR mode:",IDC_STATIC,12,234,69,8
COMBOBOX IDC_PVIEW_DHR_CONV_COMBO,84,231,118,48,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "Viewer file size &limit:",IDC_STATIC,4,258,62,8
EDITTEXT IDC_PVIEW_SIZE_EDIT,69,256,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "Spin2",IDC_PVIEW_SIZE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,112,258,11,14
LTEXT "KBytes",IDC_STATIC,110,258,36,8
END
IDD_DISKEDIT DIALOGEX 0, 0, 458, 197
@ -465,47 +472,47 @@ BEGIN
EDITTEXT IDC_PREF_EXTVIEWER_EXTS,7,68,197,14,ES_AUTOHSCROLL
END
IDD_EXTRACT_FILES DIALOGEX 0, 0, 299, 242
IDD_EXTRACT_FILES DIALOGEX 0, 0, 319, 242
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CONTEXTHELP | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Extract Files"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
DEFPUSHBUTTON "Extract",IDOK,68,220,50,14
PUSHBUTTON "Cancel",IDCANCEL,124,220,50,14
PUSHBUTTON "Help",IDHELP,180,220,50,14
DEFPUSHBUTTON "Extract",IDOK,78,220,50,14
PUSHBUTTON "Cancel",IDCANCEL,134,220,50,14
PUSHBUTTON "Help",IDHELP,190,220,50,14
LTEXT "Folder where files will be extracted:",IDC_STATIC,8,8,143,8
EDITTEXT IDC_EXT_PATH,8,18,263,14,ES_AUTOHSCROLL | WS_GROUP
PUSHBUTTON "",IDC_EXT_CHOOSE_FOLDER,276,18,16,14,BS_BITMAP | BS_CENTER | BS_VCENTER | WS_GROUP
GROUPBOX "Files to extract",IDC_STATIC,8,40,140,35
CONTROL ">Extract 65536 selected files<",IDC_EXT_SELECTED,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,16,50,124,10
PUSHBUTTON "",IDC_EXT_CHOOSE_FOLDER,296,18,16,14,BS_BITMAP | BS_CENTER | BS_VCENTER | WS_GROUP
GROUPBOX "Files to extract",IDC_STATIC,8,40,150,35
CONTROL ">Extract 65536 selected files<",IDC_EXT_SELECTED,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,16,50,135,10
CONTROL "Extract &all files",IDC_EXT_ALL,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,16,61,124,10
GROUPBOX "Parts to extract",IDC_STATIC,152,40,140,47,WS_GROUP
CONTROL "&Data forks",IDC_EXT_DATAFORK,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,160,50,128,10
CONTROL "&Resource forks",IDC_EXT_RSRCFORK,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,160,61,128,10
CONTROL "Disk &images",IDC_EXT_DISKIMAGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,72,128,10
GROUPBOX "Format conversion",IDC_STATIC,8,77,140,37
GROUPBOX "Parts to extract",IDC_STATIC,162,40,150,47,WS_GROUP
CONTROL "&Data forks",IDC_EXT_DATAFORK,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,170,50,128,10
CONTROL "&Resource forks",IDC_EXT_RSRCFORK,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,170,61,128,10
CONTROL "Disk &images",IDC_EXT_DISKIMAGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,72,128,10
GROUPBOX "Format conversion",IDC_STATIC,8,77,150,37
CONTROL "&Convert to non-Apple II formats",IDC_EXT_REFORMAT,
"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,16,88,124,10
CONTROL "Extract disks as .&2MG",IDC_EXT_DISK_2MG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,99,124,10
GROUPBOX "Filenames",IDC_STATIC,152,98,140,40
GROUPBOX "Filenames",IDC_STATIC,162,98,150,40
CONTROL "Add file attribute &preservation",IDC_EXT_ADD_PRESERVE,
"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,160,110,128,10
CONTROL "Add type &extension",IDC_EXT_ADD_EXTEN,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,160,122,128,10
GROUPBOX "Text conversion",IDC_STATIC,8,117,140,70,WS_GROUP
"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,170,110,128,10
CONTROL "Add type &extension",IDC_EXT_ADD_EXTEN,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,170,122,128,10
GROUPBOX "Text conversion",IDC_STATIC,8,117,150,70,WS_GROUP
CONTROL "&Don't convert text files",IDC_EXT_CONVEOLNONE,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,16,127,124,10
CONTROL "Convert text files by file type",IDC_EXT_CONVEOLTYPE,
"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,16,138,126,10
CONTROL "Auto-detect && &convert files with text",IDC_EXT_CONVEOLTEXT,
"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,16,149,126,10
"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,16,149,135,10
CONTROL "Convert &ALL files",IDC_EXT_CONVEOLALL,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,16,160,124,10
CONTROL "Strip ""&high ASCII"" files",IDC_EXT_CONVHIGHASCII,
"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,16,171,124,10
GROUPBOX "Miscellaneous",IDC_STATIC,152,151,140,36,WS_GROUP
CONTROL "&Strip folder names",IDC_EXT_STRIP_FOLDER,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,160,161,128,10
GROUPBOX "Miscellaneous",IDC_STATIC,162,151,150,36,WS_GROUP
CONTROL "&Strip folder names",IDC_EXT_STRIP_FOLDER,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,170,161,128,10
CONTROL "&Overwrite existing files",IDC_EXT_OVERWRITE_EXIST,
"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,160,172,128,10
PUSHBUTTON "Configure to preserve Apple II formats",IDC_EXT_CONFIG_PRESERVE,8,196,140,16
PUSHBUTTON "Configure for easy access in Windows",IDC_EXT_CONFIG_CONVERT,152,196,140,16
"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,170,172,128,10
PUSHBUTTON "Configure to preserve Apple II formats",IDC_EXT_CONFIG_PRESERVE,8,196,150,16
PUSHBUTTON "Configure for easy access in Windows",IDC_EXT_CONFIG_CONVERT,162,196,150,16
END
IDD_ACTION_PROGRESS DIALOGEX 0, 0, 276, 111
@ -1216,14 +1223,22 @@ END
//
IDB_FSLOGO BITMAP "Graphics\\fslogo.bmp"
IDR_TOOLBAR1 BITMAP "Graphics\\toolbar1.bmp"
IDB_LIST_PICS BITMAP "Graphics\\list-pics.bmp"
IDB_HDRBAR BITMAP "Graphics\\hdrbar.bmp"
IDB_NEW_FOLDER BITMAP "graphics\\NewFolder.bmp"
IDB_CHOOSE_FOLDER BITMAP "Graphics\\ChooseFolder.bmp"
IDB_VOL_PICS BITMAP "graphics\\vol_pics.bmp"
IDB_TREE_PICS BITMAP "graphics\\tree_pics.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Toolbar
@ -1349,12 +1364,12 @@ BEGIN
IDD_PREF_FVIEW, DIALOG
BEGIN
LEFTMARGIN, 4
RIGHTMARGIN, 212
RIGHTMARGIN, 213
VERTGUIDE, 12
VERTGUIDE, 50
VERTGUIDE, 112
TOPMARGIN, 7
BOTTOMMARGIN, 261
BOTTOMMARGIN, 272
END
IDD_DISKEDIT, DIALOG
@ -1403,8 +1418,10 @@ BEGIN
IDD_EXTRACT_FILES, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 292
RIGHTMARGIN, 312
VERTGUIDE, 16
VERTGUIDE, 158
VERTGUIDE, 170
TOPMARGIN, 7
BOTTOMMARGIN, 235
END
@ -1833,6 +1850,27 @@ BEGIN
END
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_ABOUTDLG AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_EXTRACT_FILES AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_PREF_FVIEW AFX_DIALOG_LAYOUT
BEGIN
0
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table

View File

@ -459,7 +459,7 @@ CString MainWindow::CopyToCollection(GenericEntry* pEntry, void** pBuf,
memset(&collEnt, 0x99, sizeof(collEnt));
collEnt.signature = kEntrySignature;
collEnt.dataOffset = sizeof(collEnt);
collEnt.fileNameLen = (wcslen(pEntry->GetPathNameUNI()) +1) * sizeof(WCHAR);
collEnt.fileNameLen = (uint16_t)((wcslen(pEntry->GetPathNameUNI()) +1) * sizeof(WCHAR));
if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) {
collEnt.dataLen = collEnt.rsrcLen = collEnt.cmmtLen = 0;
} else {

View File

@ -1581,14 +1581,15 @@ CString DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL)
else
convHA = GenericEntry::kConvertHAOff;
errMsg = LoadFile(pDataDetails->GetLocalPathName(), &dataBuf, &dataLen,
convEOL, convHA);
errMsg = LoadFile(pDataDetails->GetLocalPathName(), pDiskFS,
&dataBuf, &dataLen, convEOL, convHA);
if (!errMsg.IsEmpty())
goto bail;
}
if (pRsrcDetails != NULL) {
/* no text conversion on resource forks */
errMsg = LoadFile(pRsrcDetails->GetLocalPathName(), &rsrcBuf, &rsrcLen,
errMsg = LoadFile(pRsrcDetails->GetLocalPathName(), pDiskFS,
&rsrcBuf, &rsrcLen,
GenericEntry::kConvertEOLOff, GenericEntry::kConvertHAOff);
if (!errMsg.IsEmpty())
goto bail;
@ -1624,8 +1625,11 @@ bail:
// TODO: really ought to update the progress counter, especially when reading
// really large files.
CString DiskArchive::LoadFile(const WCHAR* pathName, uint8_t** pBuf, long* pLen,
GenericEntry::ConvertEOL conv, GenericEntry::ConvertHighASCII convHA) const
// TODO: shouldn't be loading really large files into memory. ProDOS is fine
// (16MB limit), HFS could be problematic in a 32-bit app.
CString DiskArchive::LoadFile(const WCHAR* pathName, DiskFS* pDiskFS,
uint8_t** pBuf, long* pLen,
GenericEntry::ConvertEOL conv, GenericEntry::ConvertHighASCII convHA) const
{
const char kCharLF = '\n';
const char kCharCR = '\r';
@ -1666,8 +1670,15 @@ CString DiskArchive::LoadFile(const WCHAR* pathName, uint8_t** pBuf, long* pLen,
*pBuf = NULL;
*pLen = 0;
goto bail;
} else if (fileLen > 0x00ffffff) {
errMsg = L"Cannot add files larger than 16MB to a disk image.";
}
// TODO: we want to limit the file length based on the filesystem type,
// so we don't initiate an operation that can't possibly succeed. We
// should be able to query the DiskImg for its max file size, but that
// API doesn't currently exist. For now, limit anything other than HFS
// to 16MB.
if (pDiskFS->GetDiskImg()->GetFSFormat() != DiskImg::kFormatMacHFS &&
fileLen > 0x00ffffff) {
errMsg = L"Cannot add files larger than 16MB to a non-HFS disk image.";
goto bail;
}
@ -1787,8 +1798,8 @@ bail:
DIError DiskArchive::AddForksToDisk(DiskFS* pDiskFS,
const DiskFS::CreateParms* pParms,
const unsigned char* dataBuf, long dataLen,
const unsigned char* rsrcBuf, long rsrcLen) const
const uint8_t* dataBuf, long dataLen,
const uint8_t* rsrcBuf, long rsrcLen) const
{
DIError dierr = kDIErrNone;
const int kFileTypeBIN = 0x06;

View File

@ -64,8 +64,14 @@ private:
*/
class DiskArchive : public GenericArchive {
public:
DiskArchive(void) : fpPrimaryDiskFS(NULL), fIsReadOnly(false),
fpAddDataHead(NULL), fpAddDataTail(NULL)
DiskArchive(void) :
fpPrimaryDiskFS(NULL),
fIsReadOnly(false),
fpAddDataHead(NULL),
fpAddDataTail(NULL),
fOverwriteExisting(false),
fOverwriteNoAsk(false),
fpXferTargetFS(NULL)
{}
virtual ~DiskArchive(void) { (void) Close(); }
@ -358,7 +364,7 @@ private:
*
* Returns an empty string on success, or an error message on failure.
*/
CString LoadFile(const WCHAR* pathName, uint8_t** pBuf, long* pLen,
CString LoadFile(const WCHAR* pathName, DiskFS* pDiskFS, uint8_t** pBuf, long* pLen,
GenericEntry::ConvertEOL conv, GenericEntry::ConvertHighASCII convHA) const;
/*

View File

@ -186,11 +186,11 @@ private:
class SectorEditDialog : public DiskEditDialog {
public:
SectorEditDialog(CWnd* pParentWnd = NULL) :
DiskEditDialog(IDD_DISKEDIT, pParentWnd)
{
fTrack = 0;
fSector = 0;
}
DiskEditDialog(IDD_DISKEDIT, pParentWnd),
fTrack(0),
fSector(0),
fSectorData()
{ }
virtual ~SectorEditDialog() {}
virtual int LoadData(void) override; // load the current track/sector
@ -234,11 +234,15 @@ protected:
class SectorFileEditDialog : public SectorEditDialog {
public:
SectorFileEditDialog(SectorEditDialog* pSectEdit, CWnd* pParentWnd = NULL):
SectorEditDialog(pParentWnd)
SectorEditDialog(pParentWnd),
fOpenRsrcFork(false),
fpFile(NULL),
fpOpenFile(NULL),
fSectorIdx(0),
fLength(0)
{
DiskEditDialog::Setup(pSectEdit->GetDiskFS(),
pSectEdit->GetFileName());
fSectorIdx = 0;
}
virtual ~SectorFileEditDialog() {}
@ -326,7 +330,12 @@ protected:
class BlockFileEditDialog : public BlockEditDialog {
public:
BlockFileEditDialog(BlockEditDialog* pBlockEdit, CWnd* pParentWnd = NULL) :
BlockEditDialog(pParentWnd)
BlockEditDialog(pParentWnd),
fOpenRsrcFork(false),
fpFile(NULL),
fpOpenFile(NULL),
fBlockIdx(0),
fLength(0)
{
DiskEditDialog::Setup(pBlockEdit->GetDiskFS(),
pBlockEdit->GetFileName());
@ -379,10 +388,11 @@ private:
class NibbleEditDialog : public DiskEditDialog {
public:
NibbleEditDialog(CWnd* pParentWnd = NULL) :
DiskEditDialog(IDD_DISKEDIT, pParentWnd)
{
fTrack = 0;
}
DiskEditDialog(IDD_DISKEDIT, pParentWnd),
fTrack(0),
fNibbleData(),
fNibbleDataLen(0)
{ }
virtual ~NibbleEditDialog() {}
virtual int LoadData(void) override; // load the current track/sector

View File

@ -17,7 +17,12 @@
class EOLScanDialog : public CDialog {
public:
EOLScanDialog(CWnd* pParentWnd = NULL) :
CDialog(IDD_EOLSCAN, pParentWnd)
CDialog(IDD_EOLSCAN, pParentWnd),
fCountChars(0),
fCountCR(0),
fCountLF(0),
fCountCRLF(0),
fCountHighASCII(0)
{}
virtual ~EOLScanDialog(void) {}

Binary file not shown.

View File

@ -82,6 +82,9 @@ If enabled, hi-res graphics are converted to black & white images by default.
.topic IDH_PVIEW_DHR_CONV_COMBO
Selects the preferred conversion algorithm for double-hi-res graphics.
.topic IDH_PVIEW_MOUSETEXT_TO_ASCII
Converts MouseText to ASCII instead of Unicode symbols.
.topic IDH_PVIEW_HITEXT
Enables the text converter, which strips "high ASCII" text and converts end-of-line characters.
@ -505,7 +508,7 @@ The file type, displayed as its hexadecimal code and the common three-letter mne
Tip: clicking in the file type box and then typing a letter takes you to the next entry whose mnemonic begins with that letter. This can make it easier to find an entry by "name".
.topic IDH_PROPS_AUXTYPE
The file's auxilliary type. Sometimes used to indicate information about the file (such as a 'BIN' load address), sometimes used to distinguish between files with the same file type (such as the various application-specific 'CFG' config file formats).
The file's auxiliary type. Sometimes used to indicate information about the file (such as a 'BIN' load address), sometimes used to distinguish between files with the same file type (such as the various application-specific 'CFG' config file formats).
Enter a four-digit hexadecimal number.

View File

@ -28,6 +28,7 @@
#define IDH_PVIEW_DISASM_ONEBYTEBRKCOP 1028
#define IDH_PVIEW_HIRES_BW 1029
#define IDH_PVIEW_DHR_CONV_COMBO 1030
#define IDH_PVIEW_MOUSETEXT_TO_ASCII 1031
#define IDH_PVIEW_HITEXT 1036
#define IDH_PVIEW_PASCALTEXT 1037
#define IDH_PVIEW_APPLESOFT 1038

View File

@ -11,3 +11,5 @@ This should update the CiderPress.chm in the app/Help directory. You can
copy it into the CiderPress directory, or just rebuild CiderPress to have
it copied automatically.
NOTE: pop-up text must be added to PopUp.txt, PopUpIds.h, and the
PopUpHelpIds table in MyApp.cpp.

View File

@ -91,7 +91,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="Courier New" SIZE="2">&nbsp;&nbsp; GetPort():@Port</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="Courier New" SIZE="2">&nbsp;&nbsp; FreeMem():FreeBytes/4</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="Courier New" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="Courier New" SIZE="2">A "/" and a digit after a parmeter means it takes the specified number</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="Courier New" SIZE="2">A "/" and a digit after a parameter means it takes the specified number</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="Courier New" SIZE="2">of bytes.&nbsp; (When making a tool call, you must push space on the stack</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="Courier New" SIZE="2">for any result values *before* pushing the input values.)</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="Courier New" SIZE="2">&nbsp;</FONT></P>

View File

@ -73,7 +73,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">When CiderPress encounters data that it can't interpret, it stops trying to read from that section of the WAV file.&nbsp; For this reason, damaged entries will usually be shorter than undamaged ones.&nbsp; If a file appears to have the correct length but the checksum still doesn't match, it means the signal was sufficiently distorted to make a '0' bit look like a '1' bit, which is actually pretty hard to do.&nbsp; In most cases the decoder will either make an accurate determination or will conclude that the signal is too distorted to process.&nbsp; So far only one case has been found where the checksum was deliberately altered, as part of a copy protection scheme (Sargon II).</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">If the tape has more than one program on it, you can usually tell if it's multiple copies of the same thing by comparing lengths and checksums.&nbsp; If the checkums say "good" but have different values, you probably have two different programs, or two slightly different versions of the same program.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">If the tape has more than one program on it, you can usually tell if it's multiple copies of the same thing by comparing lengths and checksums.&nbsp; If the checksums say "good" but have different values, you probably have two different programs, or two slightly different versions of the same program.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="3">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="3"><B>Saving the Data</B></FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>

View File

@ -17,7 +17,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">The pathname and modification date will be displayed but may not be changed.&nbsp; (To change the pathname, use the <A HREF="t42.htm">rename</A> feature.)&nbsp; The file type will be shown in the drop-down box, and may be changed by selecting a new entry.&nbsp; Tip: if you click in the drop box and type a letter, you will move to the next entry that begins with that letter.&nbsp; This can make it easier to find a file type by its three-letter abbreviation.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">The auxilliary type (usually called "aux type") is shown as a 4-digit hexadecimal number, and may be edited freely.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">The auxiliary type (usually called "aux type") is shown as a 4-digit hexadecimal number, and may be edited freely.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">The type description is based on both the file type and the aux type.&nbsp; For example, type "LBR $E0" with aux type "8002" is listed as a "ShrinkIt (NuFX) document" in the Apple File Type Notes.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>

View File

@ -83,7 +83,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">There are actually three formats here.&nbsp; All of them convert common symbols and accented characters from the IIgs fonts to Windows fonts.&nbsp; Not all of the symbols have equivalents, but many of them do.&nbsp; Text written in languages other than English should convert correctly.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">The supported formats are:</FONT></P>
<UL STYLE="margin-top:0;margin-bottom:0;margin-left:10pt;"><LI><FONT FACE="MS Sans Serif" SIZE="2">Teach document (GWP $5445).&nbsp; The "Teach" application on the Apple IIgs created these, which have text in the data fork and formatting information in the resource fork.&nbsp; Font size and style changes are supported, accented characters are converted, and an attempt is made to convert the typeface to something similar to the original.&nbsp; The results are ususally pretty good.</FONT>
<UL STYLE="margin-top:0;margin-bottom:0;margin-left:10pt;"><LI><FONT FACE="MS Sans Serif" SIZE="2">Teach document (GWP $5445).&nbsp; The "Teach" application on the Apple IIgs created these, which have text in the data fork and formatting information in the resource fork.&nbsp; Font size and style changes are supported, accented characters are converted, and an attempt is made to convert the typeface to something similar to the original.&nbsp; The results are usually pretty good.</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">AppleWorks GS Word Processor (GWP $8010).&nbsp; Same basic features as "Teach", plus some basic formatting features like centered and justified paragraphs.&nbsp; The "header" and "footer" sections are displayed at the top of the converted document.</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">Generic (GWP, any aux type except the two above).&nbsp; Does a IIgs text conversion without any other reformatting.&nbsp; If you have a text file that uses symbols or accented characters from the IIgs font values, you can change its file type to GWP to enable this converter.</FONT></UL>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
@ -118,7 +118,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="3">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="3"><B>Super Hi-Res Graphics (PIC/PNT or 32K BIN, 320/640x200)</B></FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">First introduced on the Apple IIgs, Super-Res was the first mode largely devoid of video idiosyncracies.&nbsp; When you set pixels to certain colors, the output on an RGB monitor was exactly what you expected.&nbsp; The resolution, which could be changed on every line, was 200 lines of either 320 pixels across with 4 bits of color per pixel, or 640 pixels across with 2 bits of color per pixel.&nbsp; The way colors in the file were translated to colors on screen involves some minor color palette gymnastics.&nbsp; The output of the converter is a 256-color 640x400 BMP.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">First introduced on the Apple IIgs, Super-Res was the first mode largely devoid of video idiosyncrasies.&nbsp; When you set pixels to certain colors, the output on an RGB monitor was exactly what you expected.&nbsp; The resolution, which could be changed on every line, was 200 lines of either 320 pixels across with 4 bits of color per pixel, or 640 pixels across with 2 bits of color per pixel.&nbsp; The way colors in the file were translated to colors on screen involves some minor color palette gymnastics.&nbsp; The output of the converter is a 256-color 640x400 BMP.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Super-Res images were also the first to be regularly compressed, which isn't surprising since they're 4x as large as standard hi-res.&nbsp; CiderPress can convert images in the following formats:</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>

View File

@ -42,7 +42,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">One caution: if you format a disk for ProDOS, and then format it with your camera, you may find that it still appears to have some ProDOS files on it.&nbsp; (CiderPress should identify it as an MS-DOS "FAT" filesystem, but if the camera uses a non-standard boot block it may not be detected correctly.)&nbsp; Some files may appear to be damaged.&nbsp; This is because the camera's format routine didn't zero out all of the blocks, so some of the ProDOS directory structure is still present.&nbsp; Attempting to read or write files to the volume as if it were a ProDOS disk is not recommended.&nbsp; The safe way to switch between Apple II and Windows formatting is to use the image-copy tool to overwrite the entire CF card.&nbsp; Be aware that formatting with a camera can reduce the number of blocks available on the drive, which will make copying images onto it impossible: the image copier only works if the destination volume is at least as large as the source volume.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">The speed at which CF cards are read or written depends primarly on your card reader.&nbsp; USB2.0 readers will be faster than USB1.x, and Firewire, PCMCIA, or IDE interfaces will usually be faster than USB2.0.&nbsp; Also, some cards have a higher speed rating than others.&nbsp; Speeds of 200-400KB/sec are typical when copying from a USB1.x device, while writing to it may reach 700KB/sec.&nbsp; Writing tends to be faster than reading because of block caching.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">The speed at which CF cards are read or written depends primarily on your card reader.&nbsp; USB2.0 readers will be faster than USB1.x, and Firewire, PCMCIA, or IDE interfaces will usually be faster than USB2.0.&nbsp; Also, some cards have a higher speed rating than others.&nbsp; Speeds of 200-400KB/sec are typical when copying from a USB1.x device, while writing to it may reach 700KB/sec.&nbsp; Writing tends to be faster than reading because of block caching.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">CiderPress assumes that the first partition on a CFFA card will be ProDOS or HFS.&nbsp; If it's not, the image will not be detected as CFFA.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="3">&nbsp;</FONT></P>
@ -56,7 +56,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="3">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="3"><B>Hard Drives</B></FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Apple II or Macintosh hard drives can be connected, assuming you have the necessary hardware (e.g. SCSI interface).&nbsp; Non-SCSI drives, such as the Applied Ingenuity InnerDrive or Vulcan drives, may not be formatted with the Macintosh partioning scheme and hence may be inaccessible.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Apple II or Macintosh hard drives can be connected, assuming you have the necessary hardware (e.g. SCSI interface).&nbsp; Non-SCSI drives, such as the Applied Ingenuity InnerDrive or Vulcan drives, may not be formatted with the Macintosh partitioning scheme and hence may be inaccessible.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Figuring out the size of a hard drive is a bit tricky under Windows, which uses different interfaces in different versions of the OS.&nbsp; Some interfaces return different answers depending on what version you're running.&nbsp; CiderPress currently scans the drive to determine its size.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;">

View File

@ -34,7 +34,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">The sizes used are for the entire partition.&nbsp; If you formatted a 32MB ProDOS volume in a 1GB partition on a CFFA card, CiderPress will treat it as a 1GB volume, even though ProDOS is only on the first part of it.&nbsp; Extracting that ProDOS volume may be awkward.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Hard drives with Macintosh-style partioning have explicit filesystem identification for each partition.&nbsp; That is, each partition will be labeled as ProDOS, HFS, a device driver, or whatever is appropriate.&nbsp; CiderPress does not currently have the ability to change these labels.&nbsp; Copying the wrong thing onto a partition, such as putting a ProDOS volume into a partition meant for HFS, could have unexpected results.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Hard drives with Macintosh-style partitioning have explicit filesystem identification for each partition.&nbsp; That is, each partition will be labeled as ProDOS, HFS, a device driver, or whatever is appropriate.&nbsp; CiderPress does not currently have the ability to change these labels.&nbsp; Copying the wrong thing onto a partition, such as putting a ProDOS volume into a partition meant for HFS, could have unexpected results.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Bear in mind that old hard drives are pretty slow by today's standards.&nbsp; A 2GB drive purchased in the mid-1990s will deliver 4-5MB/sec on bulk reads, which means it'll take about 8 minutes to back up the entire drive.&nbsp; These drives tended to have small caches and slow seeks though, so it can take 30 seconds to a minute for the contents of the disk to be loaded, because scanning the list of files requires lots of single-block reads.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>

View File

@ -35,7 +35,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">You can also copy documents to other programs.&nbsp; To select the entire document, click on the document to set the input focus, then hit Ctrl-A to select all and Ctrl-C to copy it to the clipboard.&nbsp; Switch to another application (Windows WordPad and Microsoft Word are the most appropriate) and hit Ctrl-V to paste.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Bear in mind that not all applications support all formats.&nbsp; Pasting text into Windows notepad, which doesn't support Rich Text Format, will cause highlighed BASIC listings and formatted AppleWorks documents to be converted to plain text.&nbsp; Pasting graphics into Notepad doesn't work at all.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Bear in mind that not all applications support all formats.&nbsp; Pasting text into Windows notepad, which doesn't support Rich Text Format, will cause highlighted BASIC listings and formatted AppleWorks documents to be converted to plain text.&nbsp; Pasting graphics into Notepad doesn't work at all.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Click "Done" to close the window.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>

View File

@ -39,7 +39,7 @@
<P STYLE="margin-top:0;margin-bottom:0;text-indent:-17pt;margin-left:17pt;"><SPAN STYLE="margin-left:-17pt;text-indent:0pt;width: 17pt"><FONT FACE="Symbol" SIZE="2"><B> </FONT></span><FONT FACE="MS Sans Serif" SIZE="2">Free Space:</B> how much free space is on the disk.&nbsp; For formats like CFFA, which just hold other disk images, this is meaningless.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;text-indent:-17pt;margin-left:17pt;"><SPAN STYLE="margin-left:-17pt;text-indent:0pt;width: 17pt"><FONT FACE="Symbol" SIZE="2"><B> </FONT></span><FONT FACE="MS Sans Serif" SIZE="2">Writable Format:</B> says whether or not CiderPress is capable of adding and deleting files on disks with this format.&nbsp; Currently this is "yes" for DOS 3.3, ProDOS, and UCSD Pascal.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;text-indent:-17pt;margin-left:17pt;"><SPAN STYLE="margin-left:-17pt;text-indent:0pt;width: 17pt"><FONT FACE="Symbol" SIZE="2"><B> </FONT></span><FONT FACE="MS Sans Serif" SIZE="2">Damaged: </B>this indicates whether or not CiderPress believes the disk is damaged.&nbsp; If it does, the disk will be marked read-only, and attempts to add or delete files will be blocked.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;text-indent:-17pt;margin-left:17pt;"><SPAN STYLE="margin-left:-17pt;text-indent:0pt;width: 17pt"><FONT FACE="Symbol" SIZE="2"><B> </FONT></span><FONT FACE="MS Sans Serif" SIZE="2">Notes:</B> if CiderPress detects damage or other anomalies when scanning the disk, they wll be noted here.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;text-indent:-17pt;margin-left:17pt;"><SPAN STYLE="margin-left:-17pt;text-indent:0pt;width: 17pt"><FONT FACE="Symbol" SIZE="2"><B> </FONT></span><FONT FACE="MS Sans Serif" SIZE="2">Notes:</B> if CiderPress detects damage or other anomalies when scanning the disk, they will be noted here.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">More information about the different disk formats can be found <A HREF="t18.htm">here</A>.</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="3">&nbsp;</FONT></P>

View File

@ -29,7 +29,7 @@
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">Windows XP:</FONT></P>
<UL STYLE="margin-top:0;margin-bottom:0;margin-left:17pt;"><LI><FONT FACE="MS Sans Serif" SIZE="2">From the "Start" menu, select "Control Panel".</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">Click on "User Accounts".&nbsp; If you only see the current account, and it says "limited user", you're not an administator and cannot proceed further.</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">Click on "User Accounts".&nbsp; If you only see the current account, and it says "limited user", you're not an administrator and cannot proceed further.</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">Click on the account you want to change.</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">Click on "Change my account type".</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">Click the "Computer Administrator" radio button.&nbsp; Click "change account type".</FONT>

View File

@ -88,7 +88,7 @@
<LI><FONT FACE="MS Sans Serif" SIZE="2">UNIDOS / AmDOS / OzDOS (two DOS volumes on an 800k disk)</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">ProSel Uni-DOS / DOS Master (DOS volumes embedded in an 800K ProDOS disk)</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">CFFA fixed-size partitions (4-part and 8-part formats)</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">Macintosh-style partitoning (for CD-ROMs and SCSI hard drives)</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">Macintosh-style partitioning (for CD-ROMs and SCSI hard drives)</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">///SHH Systeme MicroDrive partitioning</FONT>
<LI><FONT FACE="MS Sans Serif" SIZE="2">FocusDrive partitioning</FONT></UL>
<P STYLE="margin-top:0;margin-bottom:0;"><FONT FACE="MS Sans Serif" SIZE="2">&nbsp;</FONT></P>

View File

@ -133,6 +133,7 @@ static const UINT gFindReplaceID = RegisterWindowMessage(FINDMSGSTRING);
BEGIN_MESSAGE_MAP(MainWindow, CFrameWnd)
ON_WM_CREATE()
ON_WM_CLOSE()
ON_MESSAGE(WMU_LATE_INIT, OnLateInit)
//ON_MESSAGE(WMU_CLOSE_MAIN_DIALOG, OnCloseMainDialog)
ON_WM_SIZE()
@ -306,6 +307,12 @@ MainWindow::~MainWindow()
LOGI("MainWindow destructor complete");
}
void MainWindow::OnClose()
{
SaveWinPlacement();
CFrameWnd::OnClose();
}
BOOL MainWindow::PreCreateWindow(CREATESTRUCT& cs)
{
BOOL res = CFrameWnd::PreCreateWindow(cs);
@ -563,6 +570,8 @@ int MainWindow::OnCreate(LPCREATESTRUCT lpcs)
fStatusBar.SetPaneText(kProgressPane, L"");
RestoreWinPlacement();
return 0;
}
@ -827,6 +836,7 @@ void MainWindow::OnEditPreferences(void)
ps.fFviewPage.fHighlightHexDump = fPreferences.GetPrefBool(kPrHighlightHexDump);
ps.fFviewPage.fHighlightBASIC = fPreferences.GetPrefBool(kPrHighlightBASIC);
ps.fFviewPage.fConvDisasmOneByteBrkCop = fPreferences.GetPrefBool(kPrDisasmOneByteBrkCop);
ps.fFviewPage.fConvMouseTextToASCII = fPreferences.GetPrefBool(kPrConvMouseTextToASCII);
ps.fFviewPage.fConvHiResBlackWhite = fPreferences.GetPrefBool(kPrConvHiResBlackWhite);
ps.fFviewPage.fConvDHRAlgorithm = fPreferences.GetPrefLong(kPrConvDHRAlgorithm);
ps.fFviewPage.fRelaxGfxTypeCheck = fPreferences.GetPrefBool(kPrRelaxGfxTypeCheck);
@ -955,6 +965,7 @@ void MainWindow::ApplyNow(PrefsSheet* pPS)
fPreferences.SetPrefBool(kPrHighlightHexDump, pPS->fFviewPage.fHighlightHexDump != 0);
fPreferences.SetPrefBool(kPrHighlightBASIC, pPS->fFviewPage.fHighlightBASIC != 0);
fPreferences.SetPrefBool(kPrDisasmOneByteBrkCop, pPS->fFviewPage.fConvDisasmOneByteBrkCop != 0);
fPreferences.SetPrefBool(kPrConvMouseTextToASCII, pPS->fFviewPage.fConvMouseTextToASCII != 0);
fPreferences.SetPrefBool(kPrConvHiResBlackWhite, pPS->fFviewPage.fConvHiResBlackWhite != 0);
fPreferences.SetPrefLong(kPrConvDHRAlgorithm, pPS->fFviewPage.fConvDHRAlgorithm);
fPreferences.SetPrefBool(kPrRelaxGfxTypeCheck, pPS->fFviewPage.fRelaxGfxTypeCheck != 0);
@ -1887,6 +1898,84 @@ void MainWindow::EventPause(int duration)
* ===================================
*/
static const WCHAR kMainWinSection[] = L"mainwin";
static const WCHAR kMainWin_Left[] = L"left";
static const WCHAR kMainWin_Top[] = L"top";
static const WCHAR kMainWin_Right[] = L"right";
static const WCHAR kMainWin_Bottom[] = L"bottom";
static const WCHAR kMainWin_Cmd[] = L"cmd";
void MainWindow::SaveWinPlacement()
{
// Capture the current window position. At the point where the destructor
// fires, too much has been shut down, so we need to do it here.
WINDOWPLACEMENT wndpl;
wndpl.length = sizeof(wndpl);
if (!GetWindowPlacement(&wndpl)) {
LOGW("Unable to get window placement");
return;
}
LOGD("Window is at ltrb=%ld,%ld %ldx%ld showCmd=%d",
wndpl.rcNormalPosition.left,
wndpl.rcNormalPosition.top,
wndpl.rcNormalPosition.right - wndpl.rcNormalPosition.left,
wndpl.rcNormalPosition.bottom - wndpl.rcNormalPosition.top,
wndpl.showCmd);
gMyApp.WriteProfileInt(kMainWinSection,
kMainWin_Left, wndpl.rcNormalPosition.left);
gMyApp.WriteProfileInt(kMainWinSection,
kMainWin_Top, wndpl.rcNormalPosition.top);
gMyApp.WriteProfileInt(kMainWinSection,
kMainWin_Right, wndpl.rcNormalPosition.right);
gMyApp.WriteProfileInt(kMainWinSection,
kMainWin_Bottom, wndpl.rcNormalPosition.bottom);
gMyApp.WriteProfileInt(kMainWinSection,
kMainWin_Cmd, wndpl.showCmd);
}
void MainWindow::RestoreWinPlacement()
{
const int kNoVal = -32000;
RECT normPos;
normPos.left = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Left, kNoVal);
normPos.top = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Top, kNoVal);
normPos.right = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Right, kNoVal);
normPos.bottom = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Bottom, kNoVal);
int cmd = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Cmd, kNoVal);
if (normPos.left == kNoVal || normPos.top == kNoVal ||
normPos.right == kNoVal || normPos.bottom == kNoVal || cmd == kNoVal) {
LOGI("Previous window placement not found.");
return;
}
POINT nopt;
nopt.x = nopt.y = -1;
// We need to set the placement for "normal", and then deal with
// maximized windows by having the MyApp ShowWindow() call pass the
// appropriate command. If we pass the correct normal rect here with
// the "maximized" command, we end up with a non-maximized window of
// maximum size. (If done correctly, you can maximize, quit, restart,
// and un-maximize back to the original size.)
WINDOWPLACEMENT wndpl;
wndpl.length = sizeof(wndpl);
wndpl.flags = 0;
wndpl.showCmd = SW_SHOWNORMAL;
wndpl.ptMinPosition = nopt;
wndpl.ptMaxPosition = nopt;
wndpl.rcNormalPosition = normPos;
LOGD("Restoring previous placement, cmd=%d", wndpl.showCmd);
SetWindowPlacement(&wndpl);
// Stomp on MyApp's show command. We don't want to start minimized,
// so switch to "normal" if that's set.
gMyApp.m_nCmdShow = (cmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : cmd);
}
void MainWindow::DrawEmptyClientArea(CDC* pDC, const CRect& clientRect)
{
CBrush brush;
@ -2465,6 +2554,8 @@ CString MainWindow::RemoveFile(const WCHAR* fileName)
pPreferences->GetPrefBool(kPrRelaxGfxTypeCheck));
pReformat->SetOption(ReformatHolder::kOptOneByteBrkCop,
pPreferences->GetPrefBool(kPrDisasmOneByteBrkCop));
pReformat->SetOption(ReformatHolder::kOptMouseTextToASCII,
pPreferences->GetPrefBool(kPrConvMouseTextToASCII));
}
/*static*/ ReformatHolder::SourceFormat MainWindow::ReformatterSourceFormat(

View File

@ -54,7 +54,7 @@ public:
/*
* Override the pre-create function to tweak the window style.
*/
BOOL PreCreateWindow(CREATESTRUCT& cs) override;
virtual BOOL PreCreateWindow(CREATESTRUCT& cs) override;
/*
* Override GetClientRect so we can factor in the status and tool bars.
@ -71,8 +71,8 @@ public:
void ApplyNow(PrefsSheet*);
// get the text of the next file in the selection list
int GetPrevFileText(ReformatHolder* pHolder, CString* pTitle);
int GetNextFileText(ReformatHolder* pHolder, CString* pTitle);
//int GetPrevFileText(ReformatHolder* pHolder, CString* pTitle);
//int GetNextFileText(ReformatHolder* pHolder, CString* pTitle);
// update the progress meter
void SetProgressBegin(void);
@ -268,6 +268,7 @@ private:
// Command handlers
afx_msg int OnCreate(LPCREATESTRUCT lpcs);
afx_msg void OnClose();
afx_msg LONG OnLateInit(UINT, LONG);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnGetMinMaxInfo(MINMAXINFO* pMMI);
@ -489,6 +490,14 @@ private:
*/
void DrawEmptyClientArea(CDC* pDC, const CRect& clientRect);
/*
* Save/restore main window placement. The restore function will move
* the window if the previous placement is no longer visible (e.g. a
* secondary monitor was removed).
*/
void SaveWinPlacement();
void RestoreWinPlacement();
/*
* Extract a record to the temp folder and open it with a new instance of
* CiderPress. We might want to extract disk images as 2MG files to take
@ -607,7 +616,7 @@ private:
*/
void HandleView(void);
void DeleteFileOnExit(const WCHAR* name);
//void DeleteFileOnExit(const WCHAR* name);
/*
* Close and re-open the current archive.

View File

@ -64,6 +64,16 @@ MyApp::~MyApp(void)
BOOL MyApp::InitInstance(void)
{
// This causes functions like SetProfileInt to use the registry rather
// than a .INI file. The registry key is "usually the name of a company".
// (Must do this before creating main window so we can restore the
// previous window position.)
#ifdef CAN_UPDATE_FILE_ASSOC
SetRegistryKey(fRegistry.GetAppRegistryKey());
#else
SetRegistryKey(L"faddenSoft");
#endif
// Create the main window.
m_pMainWnd = new MainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
@ -92,14 +102,6 @@ BOOL MyApp::InitInstance(void)
LogModuleLocation(L"riched32.dll");
LogModuleLocation(L"msftedit.dll");
// This causes functions like SetProfileInt to use the registry rather
// than a .INI file. The registry key is "usually the name of a company".
#ifdef CAN_UPDATE_FILE_ASSOC
SetRegistryKey(fRegistry.GetAppRegistryKey());
#else
SetRegistryKey(L"faddenSoft");
#endif
//LOGI("Registry key is '%ls'", m_pszRegistryKey);
//LOGI("Profile name is '%ls'", m_pszProfileName);
LOGI("Short command line is '%ls'", m_lpCmdLine);
@ -201,6 +203,7 @@ BOOL MyApp::OnIdle(LONG lCount)
IDC_PVIEW_DISASM_ONEBYTEBRKCOP, IDH_PVIEW_DISASM_ONEBYTEBRKCOP,
IDC_PVIEW_HIRES_BW, IDH_PVIEW_HIRES_BW,
IDC_PVIEW_DHR_CONV_COMBO, IDH_PVIEW_DHR_CONV_COMBO,
IDC_PVIEW_MOUSETEXT_TO_ASCII, IDH_PVIEW_MOUSETEXT_TO_ASCII,
IDC_PVIEW_HITEXT, IDH_PVIEW_HITEXT,
IDC_PVIEW_PASCALTEXT, IDH_PVIEW_PASCALTEXT,
IDC_PVIEW_APPLESOFT, IDH_PVIEW_APPLESOFT,

View File

@ -13,9 +13,9 @@
/* CiderPress version numbers */
#define kAppMajorVersion 4
#define kAppMinorVersion 0
#define kAppBugVersion 2
#define kAppDevString L"a1"
#define kAppMinorVersion 1
#define kAppBugVersion 1
#define kAppDevString L""
/*
* Windows application object.

View File

@ -835,6 +835,7 @@ NuResult NufxArchive::ContentFunc(NuArchive* pArchive, void* vpRecord)
pDateTime->extra == 0 &&
pDateTime->weekDay == 0)
{
// not invalid; just no date set
return kDateNone;
}
@ -858,8 +859,17 @@ NuResult NufxArchive::ContentFunc(NuArchive* pArchive, void* vpRecord)
//LOGI(" Ignoring funky year %ld", year);
return kDateInvalid;
}
if (pDateTime->month > 11)
// Must range-check values before passing them to CTime constructor, which
// now throws a remarkably fatal exception.
if (pDateTime->month > 11 || // [0,11]
pDateTime->day > 30 || // [0,30]
pDateTime->hour > 59 || // [0,59]
pDateTime->minute > 59 || // [0,59]
pDateTime->second > 59) { // [0,59]
return kDateInvalid;
}
CTime modTime(year,
pDateTime->month+1,
@ -867,7 +877,8 @@ NuResult NufxArchive::ContentFunc(NuArchive* pArchive, void* vpRecord)
pDateTime->hour,
pDateTime->minute,
pDateTime->second);
return (time_t) modTime.GetTime();
time_t result = (time_t)modTime.GetTime();
return result;
}
/*static*/ NuResult NufxArchive::ArrayDeleteHandler(NuArchive* pArchive, void* ptr)

View File

@ -108,6 +108,7 @@ const Preferences::PrefMap Preferences::fPrefMaps[kPrefNumLastEntry] = {
{ kPrConvDHRAlgorithm, kLong, kPrefsSect, L"dhr-algorithm" },
{ kPrRelaxGfxTypeCheck, kBool, kPrefsSect, L"relax-gfx-type-check" },
{ kPrDisasmOneByteBrkCop, kBool, kPrefsSect, L"disasm-onebytebrkcop" },
{ kPrConvMouseTextToASCII, kBool, kPrefsSect, L"conv-mouse-text-to-ascii" },
//{ kPrEOLConvRaw, kBool, kPrefsSect, L"eol-conv-raw" },
{ kPrConvTextEOL_HA, kBool, kPrefsSect, L"conv-eol-ha" },
{ kPrConvPascalText, kBool, kPrefsSect, L"conv-pascal-text" },
@ -214,6 +215,7 @@ Preferences::Preferences(void)
SetPrefLong(kPrConvDHRAlgorithm, 1); // latched
SetPrefBool(kPrRelaxGfxTypeCheck, true);
SetPrefBool(kPrDisasmOneByteBrkCop, false);
SetPrefBool(kPrConvMouseTextToASCII, false);
//SetPrefBool(kPrEOLConvRaw, true);
SetPrefBool(kPrConvTextEOL_HA, true);
SetPrefBool(kPrConvPascalText, true);
@ -245,16 +247,20 @@ Preferences::Preferences(void)
SetPrefString(kPrViewTextTypeFace, L"Courier New");
SetPrefLong(kPrViewTextPointSize, 10);
long width = 680 + /* exact width for 80-column text */
::GetSystemMetrics(SM_CXVSCROLL);
long height = 516; /* exact height for file viewer to show IIgs graphic */
float scaleFactor = GetDesktopScaleFactor();
/* exact width for 80-column text; note text is scaled up */
long width = (int)(680 * scaleFactor) + ::GetSystemMetrics(SM_CXVSCROLL);
/* exact height for file viewer to show IIgs graphic at 1.0x */
long height = (int)(516 * scaleFactor);
if (GetSystemMetrics(SM_CXSCREEN) < width)
width = GetSystemMetrics(SM_CXSCREEN);
if (GetSystemMetrics(SM_CYSCREEN) < height)
height = GetSystemMetrics(SM_CYSCREEN); // may overlap system bar
//width = 640; height = 480;
SetPrefLong(kPrFileViewerWidth, width);
SetPrefLong(kPrFileViewerHeight, height);
SetPrefLong(kPrDiskImageCreateFormat, -1);
}

View File

@ -12,6 +12,13 @@
* section to the registry if appropriate.
* - Add a default value to Preferences::Preferences. If not specified,
* strings will be NULL and numeric values will be zero.
*
* For user-settable preferencers, you must also:
* - Add a UI element to the appropriate preference page.
* - Add the appropriate code for that item. Note in particular the data
* exchange and ON_CONTROL_RANGE values.
* - In Main.cpp, update OnEditPreferences() to init the page.
* - Add a tooltip to the help file.
*/
#ifndef APP_PREFERENCES_H
#define APP_PREFERENCES_H
@ -168,6 +175,7 @@ typedef enum {
kPrConvDHRAlgorithm, // long
kPrRelaxGfxTypeCheck, // bool
kPrDisasmOneByteBrkCop, // bool
kPrConvMouseTextToASCII, // bool
//kPrEOLConvRaw, // bool
kPrConvTextEOL_HA, // bool
kPrConvPascalText, // bool

View File

@ -316,6 +316,7 @@ void PrefsFviewPage::DoDataExchange(CDataExchange* pDX)
DDX_Check(pDX, IDC_PVIEW_BOLD_HEXDUMP, fHighlightHexDump);
DDX_Check(pDX, IDC_PVIEW_BOLD_BASIC, fHighlightBASIC);
DDX_Check(pDX, IDC_PVIEW_DISASM_ONEBYTEBRKCOP, fConvDisasmOneByteBrkCop);
DDX_Check(pDX, IDC_PVIEW_MOUSETEXT_TO_ASCII, fConvMouseTextToASCII);
DDX_Check(pDX, IDC_PVIEW_HIRES_BW, fConvHiResBlackWhite);
DDX_CBIndex(pDX, IDC_PVIEW_DHR_CONV_COMBO, fConvDHRAlgorithm);

View File

@ -23,11 +23,14 @@ public:
PrefsGeneralPage(void) :
CPropertyPage(IDD_PREF_GENERAL),
fReady(false),
fColumn(),
fMimicShrinkIt(FALSE),
fBadMacSHK(FALSE),
fReduceSHKErrorChecks(FALSE),
fCoerceDOSFilenames(FALSE),
fSpacesToUnder(FALSE),
fPasteJunkPaths(FALSE),
fBeepOnSuccess(FALSE),
fDefaultsPushed(FALSE),
fOurAssociations(NULL)
{}
@ -82,6 +85,7 @@ public:
fReady(false),
fQueryImageFormat(FALSE),
fOpenVolumeRO(FALSE),
fOpenVolumePhys0(FALSE),
fProDOSAllowLower(FALSE),
fProDOSUseSparse(FALSE)
{}
@ -119,7 +123,9 @@ class PrefsCompressionPage : public CPropertyPage
{
public:
PrefsCompressionPage(void) :
CPropertyPage(IDD_PREF_COMPRESSION), fReady(false)
CPropertyPage(IDD_PREF_COMPRESSION),
fReady(false),
fCompressType(-1)
{}
bool fReady;
@ -159,7 +165,39 @@ class PrefsFviewPage : public CPropertyPage
{
public:
PrefsFviewPage(void) :
CPropertyPage(IDD_PREF_FVIEW), fReady(false)
CPropertyPage(IDD_PREF_FVIEW),
fReady(false),
fEOLConvRaw(FALSE),
fNoWrapText(FALSE),
fHighlightHexDump(FALSE),
fHighlightBASIC(FALSE),
fConvDisasmOneByteBrkCop(FALSE),
fConvMouseTextToASCII(FALSE),
fConvHiResBlackWhite(FALSE),
fConvDHRAlgorithm(-1),
fConvTextEOL_HA(FALSE),
fConvCPMText(FALSE),
fConvPascalText(FALSE),
fConvPascalCode(FALSE),
fConvApplesoft(FALSE),
fConvInteger(FALSE),
fConvBusiness(FALSE),
fConvGWP(FALSE),
fConvText8(FALSE),
fConvAWP(FALSE),
fConvADB(FALSE),
fConvASP(FALSE),
fConvSCAssem(FALSE),
fConvDisasm(FALSE),
fConvHiRes(FALSE),
fConvDHR(FALSE),
fConvSHR(FALSE),
fConvPrintShop(FALSE),
fConvMacPaint(FALSE),
fConvProDOSFolder(FALSE),
fConvResources(FALSE),
fRelaxGfxTypeCheck(FALSE),
fMaxViewFileSizeKB(0)
{}
bool fReady;
@ -168,6 +206,7 @@ public:
BOOL fHighlightHexDump;
BOOL fHighlightBASIC;
BOOL fConvDisasmOneByteBrkCop;
BOOL fConvMouseTextToASCII;
BOOL fConvHiResBlackWhite;
int fConvDHRAlgorithm; // drop list

View File

@ -1787,7 +1787,7 @@ long MainWindow::SSTGetBufOffset(int track)
return offset;
}
long MainWindow::SSTCountBadBytes(const unsigned char* sctBuf, int count)
long MainWindow::SSTCountBadBytes(const uint8_t* sctBuf, int count)
{
long badCount = 0;
unsigned char uch;
@ -1802,7 +1802,7 @@ long MainWindow::SSTCountBadBytes(const unsigned char* sctBuf, int count)
return badCount;
}
void MainWindow::SSTProcessTrackData(unsigned char* trackBuf)
void MainWindow::SSTProcessTrackData(uint8_t* trackBuf)
{
unsigned char* trackPtr;
int track;
@ -1812,7 +1812,7 @@ void MainWindow::SSTProcessTrackData(unsigned char* trackBuf)
{
bool inRun;
int start, longestStart;
int count7f, longest = -1;
int count7f = 0, longest = -1;
int i;
inRun = false;

View File

@ -99,7 +99,7 @@ void TwoImgPropsDialog::DoDataExchange(CDataExchange* pDX)
fpHeader->fFlags |= (dosVolNum & TwoImgHeader::kDOSVolumeMask);
CString appStr, errMsg;
if (dosVolNum < 1 || dosVolNum > 254) {
if (dosVolNum < 0 || dosVolNum > 254) {
CheckedLoadString(&appStr, IDS_MB_APP_NAME);
CheckedLoadString(&errMsg, IDS_VALID_VOLNAME_DOS);
MessageBox(errMsg, appStr, MB_OK);

View File

@ -17,7 +17,13 @@
class UseSelectionDialog : public CDialog {
public:
UseSelectionDialog(int selCount, CWnd* pParentWnd = NULL, int rsrcID = IDD_USE_SELECTION) :
CDialog(rsrcID, pParentWnd), fSelectedCount(selCount)
CDialog(rsrcID, pParentWnd),
fSelectedCount(selCount),
fTitleID(-1),
fOkLabelID(-1),
fSelCountID(-1),
fSelCountsID(-1),
fAllID(-1)
{
// init values; these should be overridden before DoModal
fFilesToAction = 0;

View File

@ -154,8 +154,12 @@ void ViewFilesDialog::OnCancel(void)
void ViewFilesDialog::OnGetMinMaxInfo(MINMAXINFO* pMMI)
{
pMMI->ptMinTrackSize.x = 664;
pMMI->ptMinTrackSize.y = 200;
float scaleFactor = GetDesktopScaleFactor();
// 664x200 was determined empirically to fit all controls. The initial
// window size is set over in the Preferences constructor.
pMMI->ptMinTrackSize.x = (int)(664 * scaleFactor);
pMMI->ptMinTrackSize.y = (int)(200 * scaleFactor);
}
void ViewFilesDialog::OnSize(UINT nType, int cx, int cy)
@ -266,7 +270,22 @@ static void DumpBitmapInfo(HBITMAP hBitmap)
LOGD(" bmPits = 0x%p", info.bmBits);
}
void ViewFilesDialog::DisplayText(const WCHAR* fileName)
bool ViewFilesDialog::IsSourceEmpty(const GenericEntry* pEntry,
ReformatHolder::ReformatPart part)
{
switch (part) {
case ReformatHolder::ReformatPart::kPartData:
return pEntry->GetDataForkLen() == 0;
case ReformatHolder::ReformatPart::kPartRsrc:
return pEntry->GetRsrcForkLen() == 0;
case ReformatHolder::ReformatPart::kPartCmmt:
return !pEntry->GetHasNonEmptyComment();
default:
return false;
}
}
void ViewFilesDialog::DisplayText(const WCHAR* fileName, bool zeroSourceLen)
{
CWaitCursor wait; // streaming of big files can take a little while
bool errFlg;
@ -404,10 +423,14 @@ void ViewFilesDialog::DisplayText(const WCHAR* fileName)
if (fpOutput->GetOutputKind() == ReformatOutput::kOutputRTF)
streamFormat = SF_RTF;
if (fpOutput->GetTextLen() == 0) {
textBuf = "(file is empty)";
if (zeroSourceLen) {
textBuf = "(file is empty)";
EnableFormatSelection(FALSE);
} else {
textBuf = "(converted output is empty)";
}
textLen = strlen(textBuf);
emptyFlg = true;
EnableFormatSelection(FALSE);
}
if (fpOutput->GetOutputKind() == ReformatOutput::kOutputErrorMsg)
EnableFormatSelection(FALSE);
@ -638,7 +661,8 @@ void ViewFilesDialog::OnFviewNext(void)
id = ConfigureFormatSel(part);
Reformat(pSelEntry->GetEntry(), part, id);
DisplayText(pSelEntry->GetEntry()->GetDisplayName());
DisplayText(pSelEntry->GetEntry()->GetDisplayName(),
IsSourceEmpty(pSelEntry->GetEntry(), part));
}
void ViewFilesDialog::OnFviewPrev(void)
@ -681,7 +705,7 @@ void ViewFilesDialog::OnFviewPrev(void)
id = ConfigureFormatSel(part);
Reformat(pEntry, part, id);
DisplayText(pEntry->GetDisplayName());
DisplayText(pEntry->GetDisplayName(), IsSourceEmpty(pEntry, part));
}
void ViewFilesDialog::ConfigurePartButtons(const GenericEntry* pEntry)
@ -936,7 +960,7 @@ void ViewFilesDialog::OnFormatSelChange(void)
id = (ReformatHolder::ReformatID) pCombo->GetItemData(pCombo->GetCurSel());
Reformat(pEntry, part, id);
DisplayText(pEntry->GetDisplayName());
DisplayText(pEntry->GetDisplayName(), IsSourceEmpty(pEntry, part));
}
void ViewFilesDialog::OnFviewData(void)
@ -969,7 +993,7 @@ void ViewFilesDialog::ForkSelectCommon(ReformatHolder::ReformatPart part)
id = ConfigureFormatSel(part);
Reformat(pEntry, part, id);
DisplayText(pEntry->GetDisplayName());
DisplayText(pEntry->GetDisplayName(), IsSourceEmpty(pEntry, part));
}
void ViewFilesDialog::OnFviewFmtBest(void)

View File

@ -120,15 +120,23 @@ private:
//void StretchControl(int id, int deltaX, int deltaY);
void NewFontSelected(bool resetBold);
/*
* Determines whether the specified part is an empty fork/comment.
*/
bool IsSourceEmpty(const GenericEntry* pEntry,
ReformatHolder::ReformatPart part);
/*
* Display a buffer of text in the RichEdit control.
*
* The RichEdit dialog will hold its own copy of the data, so "pHolder" can
* be safely destroyed after this returns.
*
* "fileName" is for display only.
* "fileName" is for display only. "zeroSourceLen" allows the function to
* tell the difference between an empty file and a non-empty file that
* generated empty output.
*/
void DisplayText(const WCHAR* fileName);
void DisplayText(const WCHAR* fileName, bool zeroSourceLen);
/*
* Set up the fpHolder. Does not reformat the data, just loads the source

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -19,13 +19,13 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@ -93,6 +93,7 @@
#define IDC_PVIEW_DISASM_ONEBYTEBRKCOP 1028
#define IDC_PVIEW_HIRES_BW 1029
#define IDC_PVIEW_DHR_CONV_COMBO 1030
#define IDC_PVIEW_MOUSETEXT_TO_ASCII 1031
#define IDC_PVIEW_HITEXT 1036
#define IDC_PVIEW_PASCALTEXT 1037
#define IDC_PVIEW_APPLESOFT 1038
@ -559,9 +560,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 193
#define _APS_NEXT_RESOURCE_VALUE 196
#define _APS_NEXT_COMMAND_VALUE 40102
#define _APS_NEXT_CONTROL_VALUE 1454
#define _APS_NEXT_CONTROL_VALUE 1455
#define _APS_NEXT_SYMED_VALUE 102
#endif
#endif

View File

@ -835,6 +835,9 @@ DIError DiskFSDOS33::ProcessCatalogSector(int catTrack, int catSect,
break;
}
memcpy(pFile->fRawFileName, &pEntry[0x03], A2FileDOS::kMaxFileName);
pFile->fRawFileName[A2FileDOS::kMaxFileName] = '\0';
memcpy(pFile->fFileName, &pEntry[0x03], A2FileDOS::kMaxFileName);
pFile->fFileName[A2FileDOS::kMaxFileName] = '\0';
pFile->FixFilename();
@ -860,7 +863,6 @@ DIError DiskFSDOS33::ProcessCatalogSector(int catTrack, int catSect,
return kDIErrNone;
}
/*
* Perform consistency checks on the filesystem.
*
@ -2768,7 +2770,7 @@ DIError A2FileDOS::LoadTSList(TrackSector** pTSList, int* pTSCount,
if (dierr != kDIErrNone)
goto bail;
if (track != 0 && sector != 0) {
if (track != 0) {
/* more T/S lists to come, so we keep all entries */
tsCount += kMaxTSPairs;
} else {
@ -2869,6 +2871,19 @@ bail:
return dierr;
}
/*
* Returns the raw filename.
*
* If a pointer to a size_t is passed in, it will be filled with the
* raw filename length.
*/
const char* A2FileDOS::GetRawFileName(size_t* size) const {
if (size) {
*size = strlen(fRawFileName);
}
return fRawFileName;
}
/*
* ===========================================================================

View File

@ -211,6 +211,10 @@ DiskImg::DiskImg(void)
fNumBlocks = -1;
fpScanProgressCallback = NULL;
fScanProgressCookie = NULL;
fScanCount = 0;
fScanMsg[0] = '\0';
fScanLastMsgWhen = 0;
/*
* Create a working copy of the nibble descr table. We want to leave
@ -292,6 +296,12 @@ void DiskImg::SetCustomNibbleDescr(const NibbleDescr* pDescr)
}
}
const char* A2File::GetRawFileName(size_t* size) const { // get unmodified file name
if (size) {
*size = strlen(GetFileName());
}
return GetFileName();
}
/*
* Open a volume or a file on disk.
@ -472,7 +482,7 @@ DIError DiskImg::OpenImage(DiskImg* pParent, long firstBlock, long numBlocks)
* already have an open file with specific characteristics.
*/
//fOffset = pParent->fOffset + kBlockSize * firstBlock;
fLength = numBlocks * kBlockSize;
fLength = (di_off_t)numBlocks * kBlockSize;
fOuterLength = fWrappedLength = fLength;
fFileFormat = kFileFormatUnadorned;
fPhysical = pParent->fPhysical;

View File

@ -25,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <assert.h>
//#define EXCISE_GPL_CODE
@ -45,7 +46,7 @@ namespace DiskImgLib {
/* compiled-against versions; call DiskImg::GetVersion for linked-against */
#define kDiskImgVersionMajor 5
#define kDiskImgVersionMinor 0
#define kDiskImgVersionBug 0
#define kDiskImgVersionBug 1
/*
@ -1471,9 +1472,12 @@ public:
* The filename returned is defined to be null-terminated Mac OS Roman.
* For most filesystems this is automatic, as filenames are restricted
* to ASCII, but for DOS 3.3 it requires stripping high bits. It also
* means that embedded nulls in HFS filenames (which are discouraged but
* allowed) will be lost.
* means that embedded nulls will be lost.
*
* The original unmodified filename is available through GetRawFileName,
* which can be optionally passed a size_t pointer to get the size
* of the raw file name, in case it has embedded nulls.
*
* We do guarantee that the contents of subdirectories are grouped
* together. This makes it much easier to construct a hierarchy out of
* the linear list. This becomes important when dynamically adding
@ -1481,6 +1485,7 @@ public:
*/
virtual const char* GetFileName(void) const = 0; // name of this file
virtual const char* GetPathName(void) const = 0; // full path
virtual const char* GetRawFileName(size_t* size = NULL) const; // get unmodified file name
virtual char GetFssep(void) const = 0; // '\0' if none
virtual uint32_t GetFileType(void) const = 0;
virtual uint32_t GetAuxType(void) const = 0;
@ -1576,7 +1581,12 @@ private:
*/
class DISKIMG_API A2FileDescr {
public:
A2FileDescr(A2File* pFile) : fpFile(pFile), fProgressUpdateFunc(NULL) {}
A2FileDescr(A2File* pFile) :
fpFile(pFile),
fProgressUpdateFunc(NULL),
fProgressUpdateMax(0),
fProgressUpdateState(NULL)
{}
virtual ~A2FileDescr(void) { fpFile = NULL; /*paranoia*/ }
virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL) = 0;

View File

@ -630,7 +630,7 @@ private:
class WrapperFDI : public ImageWrapper {
public:
WrapperFDI(void) {}
WrapperFDI(void) : fHeaderBuf(), fImageTracks(0), fStorageName(NULL) {}
virtual ~WrapperFDI(void) {}
static DIError Test(GenericFD* pGFD, di_off_t wrappedLength);
@ -1213,10 +1213,21 @@ class A2FileDOS;
*/
class DISKIMG_API DiskFSDOS33 : public DiskFS {
public:
DiskFSDOS33(void) : DiskFS() {
fVTOCLoaded = false;
fDiskIsGood = false;
}
DiskFSDOS33(void) :
DiskFS(),
fFirstCatTrack(0),
fFirstCatSector(0),
fVTOCVolumeNumber(0),
fVTOCNumTracks(0),
fVTOCNumSectors(0),
fDiskVolumeNum(0),
fDiskVolumeName(),
fDiskVolumeID(),
fVTOC(),
fVTOCLoaded(false),
fCatalogSectors(),
fDiskIsGood(false)
{}
virtual ~DiskFSDOS33(void) {}
static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder,
@ -1259,7 +1270,7 @@ public:
// utility function
static void LowerASCII(uint8_t* buf, long len);
static void ReplaceFssep(char* str, char replacement);
//static void ReplaceFssep(char* str, char replacement);
enum {
kMinTracks = 17, // need to put the catalog track here
@ -1360,12 +1371,17 @@ private:
*/
class DISKIMG_API A2FDDOS : public A2FileDescr {
public:
A2FDDOS(A2File* pFile) : A2FileDescr(pFile) {
fTSList = NULL;
fIndexList = NULL;
fOffset = 0;
fModified = false;
}
A2FDDOS(A2File* pFile) :
A2FileDescr(pFile),
fTSList(NULL),
fTSCount(0),
fIndexList(NULL),
fIndexCount(0),
fOffset(0),
fOpenEOF(0),
fOpenSectorsUsed(0),
fModified(false)
{}
virtual ~A2FDDOS(void) {
delete[] fTSList;
delete[] fIndexList;
@ -1444,6 +1460,7 @@ public:
*/
virtual const char* GetFileName(void) const override { return fFileName; }
virtual const char* GetPathName(void) const override { return fFileName; }
virtual const char* GetRawFileName(size_t* size = NULL) const override;
virtual char GetFssep(void) const override { return '\0'; }
virtual uint32_t GetFileType(void) const override;
virtual uint32_t GetAuxType(void) const override { return fAuxType; }
@ -1482,6 +1499,7 @@ private:
short fTSListSector;
uint16_t fLengthInSectors;
bool fLocked;
char fRawFileName[kMaxFileName + 1]; // "raw" version
char fFileName[kMaxFileName+1]; // "fixed" version
FileType fFileType;
@ -1536,8 +1554,19 @@ class A2FileProDOS;
*/
class DISKIMG_API DiskFSProDOS : public DiskFS {
public:
DiskFSProDOS(void) : fBitMapPointer(0), fTotalBlocks(0), fBlockUseMap(NULL)
{}
DiskFSProDOS(void) :
fVolumeName(),
fVolumeID(),
fAccess(0),
fCreateWhen(0),
fModWhen(0),
fBitMapPointer(0),
fTotalBlocks(0),
fVolDirFileCount(0),
fBlockUseMap(NULL),
fDiskIsGood(false),
fEarlyDamage(false)
{}
virtual ~DiskFSProDOS(void) {
if (fBlockUseMap != NULL) {
assert(false); // unexpected
@ -1596,6 +1625,7 @@ private:
DIError Initialize(InitMode initMode);
DIError LoadVolHeader(void);
DIError DetermineVolDirLen(uint16_t nextBlock, uint16_t* pBlocksUsed);
void SetVolumeID(void);
void DumpVolHeader(void);
DIError ScanVolBitmap(void);
@ -1697,8 +1727,16 @@ private:
*/
class DISKIMG_API A2FDProDOS : public A2FileDescr {
public:
A2FDProDOS(A2File* pFile) : A2FileDescr(pFile), fModified(false),
fBlockList(NULL), fOffset(0)
A2FDProDOS(A2File* pFile) :
A2FileDescr(pFile),
fModified(false),
fBlockCount(0),
fBlockList(NULL),
fOpenEOF(0),
fOpenBlocksUsed(0),
fOpenStorageType(0),
fOpenRsrcFork(false),
fOffset(0)
{}
virtual ~A2FDProDOS(void) {
delete[] fBlockList;
@ -1742,14 +1780,16 @@ private:
*/
class DISKIMG_API A2FileProDOS : public A2File {
public:
A2FileProDOS(DiskFS* pDiskFS) : A2File(pDiskFS) {
fPathName = NULL;
fSparseDataEof = fSparseRsrcEof = -1;
fpOpenFile = NULL;
fParentDirBlock = 0;
fParentDirIdx = -1;
fpParent = NULL;
}
A2FileProDOS(DiskFS* pDiskFS) :
A2File(pDiskFS),
fParentDirBlock(0),
fParentDirIdx(0),
fSparseDataEof(0),
fSparseRsrcEof(0),
fPathName(NULL),
fpOpenFile(NULL),
fpParent(NULL)
{}
virtual ~A2FileProDOS(void) {
delete fpOpenFile;
delete[] fPathName;
@ -1949,7 +1989,21 @@ class A2FilePascal;
class DISKIMG_API DiskFSPascal : public DiskFS {
public:
DiskFSPascal(void) : fDirectory(NULL) {}
DiskFSPascal(void) :
fStartBlock(0),
fNextBlock(0),
fVolumeName(),
fVolumeID(),
fTotalBlocks(0),
fNumFiles(0),
fAccessWhen(0),
fDateSetWhen(0),
fStuff1(0),
fStuff2(0),
fDiskIsGood(false),
fEarlyDamage(false),
fDirectory(NULL)
{}
virtual ~DiskFSPascal(void) {
if (fDirectory != NULL) {
assert(false); // unexpected
@ -2051,9 +2105,13 @@ private:
*/
class DISKIMG_API A2FDPascal : public A2FileDescr {
public:
A2FDPascal(A2File* pFile) : A2FileDescr(pFile) {
fOffset = 0;
}
A2FDPascal(A2File* pFile) :
A2FileDescr(pFile),
fOffset(0),
fOpenEOF(0),
fOpenBlocksUsed(0),
fModified(0)
{}
virtual ~A2FDPascal(void) {
/* nothing to clean up */
}
@ -2085,9 +2143,17 @@ private:
*/
class DISKIMG_API A2FilePascal : public A2File {
public:
A2FilePascal(DiskFS* pDiskFS) : A2File(pDiskFS) {
fpOpenFile = NULL;
}
A2FilePascal(DiskFS* pDiskFS) :
A2File(pDiskFS),
fStartBlock(0),
fNextBlock(0),
fFileType(A2FilePascal::FileType::kTypeUntyped),
fFileName(),
fBytesRemaining(0),
fModWhen(0),
fLength(0),
fpOpenFile(NULL)
{}
virtual ~A2FilePascal(void) {
/* this comes back and calls CloseDescr */
if (fpOpenFile != NULL)
@ -2185,7 +2251,7 @@ private:
class A2FileCPM;
class DISKIMG_API DiskFSCPM : public DiskFS {
public:
DiskFSCPM(void) : fDiskIsGood(false) {}
DiskFSCPM(void) : fDirEntry(), fDiskIsGood(false) {}
virtual ~DiskFSCPM(void) {}
static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder,
@ -2269,10 +2335,12 @@ private:
*/
class DISKIMG_API A2FDCPM : public A2FileDescr {
public:
A2FDCPM(A2File* pFile) : A2FileDescr(pFile) {
//fOpen = false;
fBlockList = NULL;
}
A2FDCPM(A2File* pFile) :
A2FileDescr(pFile),
fOffset(0),
fBlockCount(0),
fBlockList(NULL)
{}
virtual ~A2FDCPM(void) {
delete fBlockList;
fBlockList = NULL;
@ -2308,7 +2376,13 @@ public:
typedef DiskFSCPM::DirEntry DirEntry;
A2FileCPM(DiskFS* pDiskFS, DirEntry* pDirEntry) :
A2File(pDiskFS), fpDirEntry(pDirEntry)
A2File(pDiskFS),
fFileName(),
fReadOnly(false),
fLength(0),
fDirIdx(0),
fpDirEntry(pDirEntry),
fpOpenFile(NULL)
{
fDirIdx = -1;
fpOpenFile = NULL;
@ -2389,7 +2463,7 @@ private:
class A2FileRDOS;
class DISKIMG_API DiskFSRDOS : public DiskFS {
public:
DiskFSRDOS(void) {}
DiskFSRDOS(void) : fVolumeName(), fOurSectPerTrack(0) {}
virtual ~DiskFSRDOS(void) {}
static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder,
@ -2468,10 +2542,17 @@ private:
*/
class DISKIMG_API A2FileRDOS : public A2File {
public:
A2FileRDOS(DiskFS* pDiskFS) : A2File(pDiskFS) {
//fOpen = false;
fpOpenFile = NULL;
}
A2FileRDOS(DiskFS* pDiskFS) :
A2File(pDiskFS),
fFileName(),
fRawFileName(),
fFileType(A2FileRDOS::FileType::kTypeUnknown),
fNumSectors(0),
fLoadAddr(0),
fLength(0),
fStartSector(0),
fpOpenFile(NULL)
{}
virtual ~A2FileRDOS(void) {
delete fpOpenFile;
}
@ -2492,6 +2573,7 @@ public:
*/
virtual const char* GetFileName(void) const override { return fFileName; }
virtual const char* GetPathName(void) const override { return fFileName; }
virtual const char* GetRawFileName(size_t* size = NULL) const override;
virtual char GetFssep(void) const override { return '\0'; }
virtual uint32_t GetFileType(void) const override;
virtual uint32_t GetAuxType(void) const override { return fLoadAddr; }
@ -2517,6 +2599,7 @@ public:
/* fields pulled out of directory block */
char fFileName[kMaxFileName+1];
char fRawFileName[kMaxFileName + 1];
FileType fFileType;
uint16_t fNumSectors;
uint16_t fLoadAddr;
@ -2542,9 +2625,19 @@ private:
class A2FileHFS;
class DISKIMG_API DiskFSHFS : public DiskFS {
public:
DiskFSHFS(void) {
fLocalTimeOffset = -1;
fDiskIsGood = true;
DiskFSHFS(void) :
fVolumeName(),
fVolumeID(),
fTotalBlocks(0),
fAllocationBlockSize(0),
fNumAllocationBlocks(0),
fCreatedDateTime(0),
fModifiedDateTime(0),
fNumFiles(0),
fNumDirectories(0),
fLocalTimeOffset(-1),
fDiskIsGood(true)
{
#ifndef EXCISE_GPL_CODE
fHfsVol = NULL;
#endif
@ -2717,12 +2810,25 @@ private:
*/
class DISKIMG_API A2FileHFS : public A2File {
public:
A2FileHFS(DiskFS* pDiskFS) : A2File(pDiskFS) {
fPathName = NULL;
fpOpenFile = NULL;
A2FileHFS(DiskFS* pDiskFS) :
A2File(pDiskFS),
fIsDir(false),
fIsVolumeDir(false),
fType(0),
fCreator(0),
fFileName(),
fPathName(NULL),
fDataLength(0),
fRsrcLength(0),
fCreateWhen(0),
fModWhen(0),
fAccess(0),
fpOpenFile(NULL)
{
#ifdef EXCISE_GPL_CODE
fFakeFileBuf = NULL;
#else
fpParent = NULL;
//fOrigPathName = NULL;
#endif
}
@ -2828,10 +2934,19 @@ class A2FileGutenberg;
*/
class DISKIMG_API DiskFSGutenberg : public DiskFS {
public:
DiskFSGutenberg(void) : DiskFS() {
fVTOCLoaded = false;
fDiskIsGood = false;
}
DiskFSGutenberg(void) : DiskFS(),
fFirstCatTrack(0),
fFirstCatSector(0),
fVTOCVolumeNumber(0),
fVTOCNumTracks(0),
fVTOCNumSectors(0),
fDiskVolumeName(),
fDiskVolumeID(),
fVTOC(),
fVTOCLoaded(false),
fCatalogSectors(),
fDiskIsGood(false)
{}
virtual ~DiskFSGutenberg(void) {}
static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder,
@ -2852,12 +2967,12 @@ public:
virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits,
int* pUnitSize) const override;
static bool IsValidFileName(const char* name);
static bool IsValidVolumeName(const char* name);
//static bool IsValidFileName(const char* name);
//static bool IsValidVolumeName(const char* name);
// utility function
static void LowerASCII(uint8_t* buf, long len);
static void ReplaceFssep(char* str, char replacement);
//static void ReplaceFssep(char* str, char replacement);
enum {
kMinTracks = 17, // need to put the catalog track here
@ -2875,43 +2990,13 @@ public:
private:
DIError Initialize(InitMode initMode);
DIError ReadVTOC(void);
void UpdateVolumeNum(void);
void DumpVTOC(void);
void SetSectorUsage(long track, long sector,
VolumeUsage::ChunkPurpose purpose);
void FixVolumeUsageMap(void);
DIError ReadCatalog(void);
DIError ProcessCatalogSector(int catTrack, int catSect,
const uint8_t* sctBuf);
DIError GetFileLengths(void);
DIError ComputeLength(A2FileGutenberg* pFile, const TrackSector* tsList,
int tsCount);
DIError TrimLastSectorUp(A2FileGutenberg* pFile, TrackSector lastTS);
void MarkFileUsage(A2FileGutenberg* pFile, TrackSector* tsList, int tsCount,
TrackSector* indexList, int indexCount);
DIError MakeFileNameUnique(char* fileName);
DIError GetFreeCatalogEntry(TrackSector* pCatSect, int* pCatEntry,
uint8_t* sctBuf, A2FileGutenberg** ppPrevEntry);
void CreateDirEntry(uint8_t* sctBuf, int catEntry,
const char* fileName, TrackSector* pTSSect, uint8_t fileType,
int access);
void FreeTrackSectors(TrackSector* pList, int count);
bool CheckDiskIsGood(void);
DIError WriteDOSTracks(int sectPerTrack);
DIError ScanVolBitmap(void);
DIError LoadVolBitmap(void);
DIError SaveVolBitmap(void);
void FreeVolBitmap(void);
DIError AllocSector(TrackSector* pTS);
DIError CreateEmptyBlockMap(bool withDOS);
bool GetSectorUseEntry(long track, int sector) const;
void SetSectorUseEntry(long track, int sector, bool inUse);
inline uint32_t GetVTOCEntry(const uint8_t* pVTOC, long track) const;
// Largest interesting volume is 400K (50 tracks, 32 sectors), but
// we may be looking at it in 16-sector mode, so max tracks is 100.
enum {
@ -2931,7 +3016,7 @@ private:
/* private data */
char fDiskVolumeName[10]; //
char fDiskVolumeID[11+12+1]; // sizeof "Gutenberg: " + 12 + null
uint8_t fVTOC[kSectorSize];
uint8_t fVTOC[kSectorSize];
bool fVTOCLoaded;
/*
@ -2950,12 +3035,15 @@ private:
*/
class DISKIMG_API A2FDGutenberg : public A2FileDescr {
public:
A2FDGutenberg(A2File* pFile) : A2FileDescr(pFile) {
fOffset = 0;
fModified = false;
}
virtual ~A2FDGutenberg(void) {
}
A2FDGutenberg(A2File* pFile) :
A2FileDescr(pFile),
fTSCount(0),
fOffset(0),
fOpenEOF(0),
fOpenSectorsUsed(0),
fModified(false)
{}
virtual ~A2FDGutenberg(void) {}
friend class A2FileGutenberg;
@ -3055,16 +3143,11 @@ public:
void FixFilename(void);
static FileType ConvertFileType(long prodosType, di_off_t fileLen);
static bool IsValidType(long prodosType);
static void MakeDOSName(char* buf, const char* name);
static void TrimTrailingSpaces(char* filename);
private:
DIError ExtractTSPairs(const uint8_t* sctBuf, TrackSector* tsList,
int* pLastNonZero);
A2FDGutenberg* fpOpenFile;
A2FDGutenberg* fpOpenFile;
};
@ -3083,7 +3166,11 @@ private:
class A2FileFAT;
class DISKIMG_API DiskFSFAT : public DiskFS {
public:
DiskFSFAT(void) {}
DiskFSFAT(void) :
fVolumeName(),
fVolumeID(),
fTotalBlocks(0)
{}
virtual ~DiskFSFAT(void) {}
static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder,
@ -3168,11 +3255,13 @@ private:
*/
class DISKIMG_API A2FileFAT : public A2File {
public:
A2FileFAT(DiskFS* pDiskFS) : A2File(pDiskFS) {
fFakeFileBuf = NULL;
//fFakeFileLen = -1;
fpOpenFile = NULL;
}
A2FileFAT(DiskFS* pDiskFS) :
A2File(pDiskFS),
fFileName(),
fLength(0),
fFakeFileBuf(NULL),
fpOpenFile(NULL)
{}
virtual ~A2FileFAT(void) {
delete fpOpenFile;
delete[] fFakeFileBuf;

View File

@ -337,6 +337,7 @@ void DiskFSFAT::CreateFakeFile(void)
fVolumeName,
capacity,
(double) capacity / 2048.0);
buf[sizeof(buf) - 1] = '\0';
pFile = new A2FileFAT(this);
pFile->SetFakeFile(buf, strlen(buf));

View File

@ -175,8 +175,12 @@ private:
#ifdef _WIN32
class GFDWinVolume : public GenericFD {
public:
GFDWinVolume(void) : fPathName(NULL), fCurrentOffset(0), fVolumeEOF(-1)
{}
GFDWinVolume(void) :
fPathName(NULL),
fCurrentOffset(0),
fVolumeEOF(-1),
fBlockSize(0)
{}
virtual ~GFDWinVolume(void) { delete[] fPathName; }
virtual DIError Open(const char* deviceName, bool readOnly);
@ -203,7 +207,14 @@ private:
class GFDBuffer : public GenericFD {
public:
GFDBuffer(void) : fBuffer(NULL) {}
GFDBuffer(void) :
fBuffer(NULL),
fLength(0),
fAllocLength(0),
fDoDelete(false),
fDoExpand(false),
fCurrentOffset(0)
{}
virtual ~GFDBuffer(void) { Close(); }
// If "doDelete" is set, the buffer will be freed with delete[] when

View File

@ -1145,7 +1145,7 @@ DIError WrapperDiskCopy42::WriteHeader(GenericFD* pGFD, const DC42Header* pHeade
* magic string. To be safe, we only increment it if it starts with '-'.
* (Need access to a Macintosh to test this.)
*/
hdrBuf[0] = strlen(pHeader->diskName);
hdrBuf[0] = (uint8_t) (strlen(pHeader->diskName) & 0xff);
if (pHeader->diskName[0] == '-' && hdrBuf[0] < (kDC42NameLen-1))
hdrBuf[0]++;
memcpy(&hdrBuf[1], pHeader->diskName, hdrBuf[0]);

View File

@ -1220,7 +1220,7 @@ void OuterZip::LocalFileHeader::SetFileName(const char* name)
fFileNameLength = 0;
if (name != NULL) {
fFileNameLength = strlen(name);
fFileNameLength = (uint16_t)strlen(name);
fFileName = new uint8_t[fFileNameLength+1];
if (fFileName == NULL) {
LOGW("Malloc failure in SetFileName %u", fFileNameLength);
@ -1388,7 +1388,7 @@ void OuterZip::CentralDirEntry::SetFileName(const char* name)
fFileNameLength = 0;
if (name != NULL) {
fFileNameLength = strlen(name);
fFileNameLength = (uint16_t)strlen(name);
fFileName = new uint8_t[fFileNameLength+1];
if (fFileName == NULL) {
LOGI("Malloc failure in SetFileName %u", fFileNameLength);

View File

@ -535,7 +535,7 @@ DIError DiskFSPascal::Format(DiskImg* pDiskImg, const char* volName)
PutShortLE(&blkBuf[0x00], 0); // start block
PutShortLE(&blkBuf[0x02], 6); // next block
PutShortLE(&blkBuf[0x04], 0); // "file" type
blkBuf[0x06] = strlen(volName);
blkBuf[0x06] = (uint8_t)strlen(volName);
memcpy(&blkBuf[0x07], volName, strlen(volName));
PutShortLE(&blkBuf[0x0e], (uint16_t) pDiskImg->GetNumBlocks());
PutShortLE(&blkBuf[0x10], 0); // num files
@ -1255,7 +1255,7 @@ DIError DiskFSPascal::RenameFile(A2File* pGenericFile, const char* newName)
goto bail;
}
pEntry[0x06] = strlen(normalName);
pEntry[0x06] = (uint8_t)strlen(normalName);
memcpy(&pEntry[0x07], normalName, A2FilePascal::kMaxFileName);
strcpy(pFile->fFileName, normalName);
@ -1339,7 +1339,7 @@ DIError DiskFSPascal::RenameVolume(const char* newName)
if (dierr != kDIErrNone)
goto bail;
fDirectory[0x06] = strlen(normalName);
fDirectory[0x06] = (uint8_t)strlen(normalName);
memcpy(&fDirectory[0x07], normalName, fDirectory[0x06]);
strcpy(fVolumeName, normalName);

View File

@ -30,7 +30,7 @@
const int kBlkSize = 512;
const int kVolHeaderBlock = 2; // block where Volume Header resides
const int kVolDirExpectedNumBlocks = 4; // customary #of volume header blocks
const int kFormatVolDirNumBlocks = 4; // #of volume header blocks for new volumes
const int kMinReasonableBlocks = 16; // min size for ProDOS volume
const int kExpectedBitmapStart = 6; // block# where vol bitmap should start
const int kMaxCatalogIterations = 1024; // theoretical max is 32768?
@ -360,8 +360,11 @@ DIError DiskFSProDOS::LoadVolHeader(void)
pEntry->fileName[nameLen] = '\0';
pEntry->fileType = kTypeDIR;
pEntry->keyPointer = kVolHeaderBlock;
pEntry->blocksUsed = kVolDirExpectedNumBlocks;
pEntry->eof = kVolDirExpectedNumBlocks * 512;
dierr = DetermineVolDirLen(GetShortLE(&blkBuf[0x02]), &pEntry->blocksUsed);
if (dierr != kDIErrNone) {
goto bail;
}
pEntry->eof = pEntry->blocksUsed * 512;
pEntry->createWhen = GetLongLE(&blkBuf[0x1c]);
pEntry->version = blkBuf[0x20];
pEntry->minVersion = blkBuf[0x21];
@ -375,8 +378,47 @@ DIError DiskFSProDOS::LoadVolHeader(void)
pFile->fSparseRsrcEof = -1;
AddFileToList(pFile);
pFile = NULL;
bail:
delete pFile;
return dierr;
}
DIError DiskFSProDOS::DetermineVolDirLen(uint16_t nextBlock, uint16_t* pBlocksUsed) {
DIError dierr = kDIErrNone;
uint8_t blkBuf[kBlkSize];
uint16_t blocksUsed = 1;
int iterCount = 0;
// Traverse the volume directory chain, counting blocks. Normally this will have 4, but
// variations are possible.
while (nextBlock != 0) {
blocksUsed++;
if (nextBlock < 2 || nextBlock >= fpImg->GetNumBlocks()) {
LOGI(" ProDOS ERROR: invalid volume dir link block %u", nextBlock);
dierr = kDIErrInvalidBlock;
goto bail;
}
dierr = fpImg->ReadBlock(nextBlock, blkBuf);
if (dierr != kDIErrNone) {
goto bail;
}
nextBlock = GetShortLE(&blkBuf[0x02]);
// Watch for infinite loop.
iterCount++;
if (iterCount > fpImg->GetNumBlocks()) {
LOGI(" ProDOS ERROR: infinite vol directory loop found");
dierr = kDIErrDirectoryLoop;
goto bail;
}
}
bail:
*pBlocksUsed = blocksUsed;
return dierr;
}
@ -552,7 +594,7 @@ DIError DiskFSProDOS::ScanVolBitmap(void)
}
/*
* Generate an empty block use map.
* Generate an empty block use map. Used by disk formatter.
*/
DIError DiskFSProDOS::CreateEmptyBlockMap(void)
{
@ -569,7 +611,7 @@ DIError DiskFSProDOS::CreateEmptyBlockMap(void)
*/
long block;
long firstEmpty =
kVolHeaderBlock + kVolDirExpectedNumBlocks + GetNumBitmapBlocks();
kVolHeaderBlock + kFormatVolDirNumBlocks + GetNumBitmapBlocks();
for (block = 0; block < firstEmpty; block++)
SetBlockUseEntry(block, true);
for ( ; block < fTotalBlocks; block++)
@ -1091,8 +1133,9 @@ DIError DiskFSProDOS::ScanFileUsage(void)
&sparseCount);
pFile->fSparseDataEof =
(di_off_t) pFile->fExtData.eof - sparseCount * kBlkSize;
//LOGI(" SparseCount %d dataEof %d '%s'",
// sparseCount, pFile->fSparseDataEof, pFile->fDirEntry.fileName);
//LOGI(" SparseCount %ld dataEof %ld -> %lld '%s'",
// sparseCount, pFile->fExtData.eof, pFile->fSparseDataEof,
// pFile->fDirEntry.fileName);
delete[] blockList;
blockList = NULL;
delete[] indexList;
@ -1126,9 +1169,9 @@ DIError DiskFSProDOS::ScanFileUsage(void)
&sparseCount);
pFile->fSparseDataEof =
(di_off_t) pFile->fDirEntry.eof - sparseCount * kBlkSize;
//LOGI(" +++ sparseCount=%ld blockCount=%ld sparseDataEof=%ld '%s'",
// sparseCount, blockCount, (long) pFile->fSparseDataEof,
// pFile->fDirEntry.fileName);
//LOGI(" +++ sparseCount=%ld blockCount=%ld sparseDataEof=%lld '%s'",
// sparseCount, blockCount, pFile->fSparseDataEof,
// pFile->fDirEntry.fileName);
delete[] blockList;
blockList = NULL;
@ -1494,10 +1537,10 @@ DIError DiskFSProDOS::Format(DiskImg* pDiskImg, const char* volName)
*/
int i;
memset(blkBuf, 0, sizeof(blkBuf));
for (i = kVolHeaderBlock+1; i < kVolHeaderBlock+kVolDirExpectedNumBlocks; i++)
for (i = kVolHeaderBlock+1; i < kVolHeaderBlock+kFormatVolDirNumBlocks; i++)
{
PutShortLE(&blkBuf[0x00], i-1);
if (i == kVolHeaderBlock+kVolDirExpectedNumBlocks-1)
if (i == kVolHeaderBlock+kFormatVolDirNumBlocks-1)
PutShortLE(&blkBuf[0x02], 0);
else
PutShortLE(&blkBuf[0x02], i+1);
@ -1529,7 +1572,7 @@ DIError DiskFSProDOS::Format(DiskImg* pDiskImg, const char* volName)
PutShortLE(&blkBuf[0x00], 0);
PutShortLE(&blkBuf[0x02], kVolHeaderBlock+1);
blkBuf[0x04] = strlen(upperName) | (A2FileProDOS::kStorageVolumeDirHeader << 4);
blkBuf[0x04] = (uint8_t)(strlen(upperName) | (A2FileProDOS::kStorageVolumeDirHeader << 4));
strncpy((char*) &blkBuf[0x05], upperName, A2FileProDOS::kMaxFileName);
PutLongLE(&blkBuf[0x16], A2FileProDOS::ConvertProDate(now));
PutShortLE(&blkBuf[0x1a], lcFlags);
@ -1540,7 +1583,7 @@ DIError DiskFSProDOS::Format(DiskImg* pDiskImg, const char* volName)
blkBuf[0x23] = 0x27; // entry_length: always $27
blkBuf[0x24] = 0x0d; // entries_per_block: always $0d
/* file_count is zero - does not include volume dir */
PutShortLE(&blkBuf[0x27], kVolHeaderBlock + kVolDirExpectedNumBlocks); // bit_map_pointer
PutShortLE(&blkBuf[0x27], kVolHeaderBlock + kFormatVolDirNumBlocks); // bit_map_pointer
PutShortLE(&blkBuf[0x29], (uint16_t) formatBlocks); // total_blocks
dierr = fpImg->WriteBlock(kVolHeaderBlock, blkBuf);
if (dierr != kDIErrNone) {
@ -1558,8 +1601,7 @@ DIError DiskFSProDOS::Format(DiskImg* pDiskImg, const char* volName)
/*
* Generate the initial block usage map. The only entries in use are
* right at the start of the disk. When we finish, scan what we just
* created into
* right at the start of the disk.
*/
CreateEmptyBlockMap();
@ -1973,7 +2015,7 @@ DIError DiskFSProDOS::CreateFile(const CreateParms* pParms, A2File** ppNewFile)
* are lower case. (Some parts of the original may have been stomped
* when the name was made unique, so we need to watch for that.)
*/
dirEntryPtr[0x00] = (pParms->storageType << 4) | strlen(upperName);
dirEntryPtr[0x00] = (uint8_t)((pParms->storageType << 4) | strlen(upperName));
strncpy((char*) &dirEntryPtr[0x01], upperName, A2FileProDOS::kMaxFileName);
if (pParms->fileType >= 0 && pParms->fileType <= 0xff)
dirEntryPtr[0x10] = (uint8_t) pParms->fileType;
@ -2229,7 +2271,7 @@ DIError DiskFSProDOS::AllocInitialFileStorage(const CreateParms* pParms,
/* fill in directory header fields */
// 0x00: prev, set to zero
// 0x02: next, set to zero
blkBuf[0x04] = (A2FileProDOS::kStorageSubdirHeader << 4) | strlen(upperName);
blkBuf[0x04] = (uint8_t)((A2FileProDOS::kStorageSubdirHeader << 4) | strlen(upperName));
strncpy((char*) &blkBuf[0x05], upperName, A2FileProDOS::kMaxFileName);
blkBuf[0x14] = 0x76; // 0x75 under old P8, 0x76 under GS/OS
PutLongLE(&blkBuf[0x1c], A2FileProDOS::ConvertProDate(pParms->createWhen));
@ -3470,7 +3512,7 @@ DIError DiskFSProDOS::RenameFile(A2File* pGenericFile, const char* newName)
dierr = kDIErrBadDirectory;
goto bail;
}
ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName);
ptr[0x00] = (uint8_t)((ptr[0x00] & 0xf0) | strlen(upperName));
memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName);
PutShortLE(&ptr[0x1c], lcFlags); // version/min_version
if (isAW)
@ -3485,7 +3527,7 @@ DIError DiskFSProDOS::RenameFile(A2File* pGenericFile, const char* newName)
dierr = kDIErrBadDirectory;
goto bail;
}
ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName);
ptr[0x00] = (uint8_t)((ptr[0x00] & 0xf0) | strlen(upperName));
memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName);
PutShortLE(&ptr[0x1c], lcFlags); // version/min_version
}
@ -3736,7 +3778,7 @@ DIError DiskFSProDOS::RenameVolume(const char* newName)
dierr = kDIErrBadDirectory;
goto bail;
}
ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName);
ptr[0x00] = (uint8_t)((ptr[0x00] & 0xf0) | strlen(upperName));
memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName);
PutShortLE(&ptr[0x16], lcFlags); // reserved fields
@ -4496,6 +4538,8 @@ DIError A2FDProDOS::Write(const void* buf, size_t len, size_t* pActual)
bool allocSparse = (pDiskFS->GetParameter(DiskFS::kParmProDOS_AllocSparse) != 0);
uint8_t blkBuf[kBlkSize];
uint16_t keyBlock;
bool allZero = true;
const uint8_t* scanPtr = (const uint8_t*)buf;
if (len >= 0x01000000) { // 16MB
assert(false);
@ -4531,13 +4575,32 @@ DIError A2FDProDOS::Write(const void* buf, size_t len, size_t* pActual)
keyBlock = pFile->fExtData.keyBlock;
}
/*
* See if the file is completely empty. This lets us do an optimization
* where we store it as a seedling. (GS/OS seems to do this, ProDOS 8
* v2.0.3 tends to allocate the first block.)
*/
for (unsigned int i = 0; i < len; ++i, ++scanPtr) {
if (*scanPtr != 0x00) {
allZero = false;
break;
}
}
if (allZero) {
LOGI("+++ found file filled with %zd zeroes", len);
}
/*
* Special-case seedling files. Just write the data into the key block
* and we're done.
*/
if (len <= (size_t)kBlkSize) {
if (allZero || len <= (size_t)kBlkSize) {
memset(blkBuf, 0, sizeof(blkBuf));
memcpy(blkBuf, buf, len);
if (!allZero) {
memcpy(blkBuf, buf, len);
} else {
LOGI("+++ ProDOS storing large but empty file as seedling");
}
dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, blkBuf);
if (dierr != kDIErrNone)
goto bail;
@ -4572,11 +4635,9 @@ DIError A2FDProDOS::Write(const void* buf, size_t len, size_t* pActual)
*/
const uint8_t* blkPtr;
long blockIdx;
bool allZero;
long progressCounter;
progressCounter = 0;
allZero = true;
blkPtr = (const uint8_t*) buf;
for (blockIdx = 0; blockIdx < fBlockCount; blockIdx++) {
long newBlock;
@ -4590,12 +4651,24 @@ DIError A2FDProDOS::Write(const void* buf, size_t len, size_t* pActual)
blkPtr = blkBuf;
}
if (allocSparse && IsEmptyBlock(blkPtr))
newBlock = 0;
else {
if (allocSparse && IsEmptyBlock(blkPtr)) {
if (blockIdx == 0) {
// Fix for issues #18 and #49. GS/OS appears to get confused
// if the first entry in the master index block for a "tree"
// file is zero. We can avoid the problem by always allocating
// the first data block, which causes allocation of the first
// index block. (The "all zeroes" case was handled earlier,
// so if we got here we know this won't be an empty seedling.)
LOGI("+++ allocating storage for empty first block");
newBlock = pDiskFS->AllocBlock();
fOpenBlocksUsed++;
} else {
// Sparse.
newBlock = 0;
}
} else {
newBlock = pDiskFS->AllocBlock();
fOpenBlocksUsed++;
allZero = false;
}
if (newBlock < 0) {
@ -4651,7 +4724,9 @@ DIError A2FDProDOS::Write(const void* buf, size_t len, size_t* pActual)
/*
* Now we have a full block map. Allocate any needed index blocks and
* write them.
*
*/
#if 0 // now done earlier
/*
* If our block map is empty, i.e. the entire file is sparse, then
* there's no need to create a sapling. We just leave the file in
* seedling form. This can only happen for a completely empty file.
@ -4665,7 +4740,9 @@ DIError A2FDProDOS::Write(const void* buf, size_t len, size_t* pActual)
goto bail;
fOpenStorageType = A2FileProDOS::kStorageSeedling;
fBlockList[0] = keyBlock;
} else if (fBlockCount <= 256) {
} else
#endif
if (fBlockCount <= 256) {
/* sapling file, write an index block into the key block */
//bool allzero = true; <-- should this be getting used?
assert(fBlockCount > 1);
@ -4972,12 +5049,27 @@ DIError A2FDProDOS::Close(void)
}
/*
* Find the #of sparse blocks.
* Find the #of sparse blocks. We do this to update the "sparse EOF",
* which determines the "compressed" size shown in the file list. We
* have two cases: normal file with sparse contents, and seedling file
* that is entirely sparse except for the first block.
*
* In the normal case, we walk through the list of data blocks,
* looking for gaps. In the seedling case, we just use the EOF.
*
* This is just for display. The value seen after adding a file should
* not change if you reload the disk image.
*/
int sparseCount = 0;
for (int i = 0; i < fBlockCount; i++) {
if (fBlockList[i] == 0)
sparseCount++;
int sparseBlocks = 0;
if (fBlockCount == 1 && fOpenEOF > kBlkSize) {
// 1023/1024 = 2 blocks = 1 sparse
// 1025 = 3 blocks = 2 sparse
sparseBlocks = (int)((fOpenEOF-1) / kBlkSize);
} else {
for (int i = 0; i < fBlockCount; i++) {
if (fBlockList[i] == 0)
sparseBlocks++;
}
}
/*
@ -4995,19 +5087,19 @@ DIError A2FDProDOS::Close(void)
pFile->fExtData.storageType = fOpenStorageType;
pFile->fExtData.blocksUsed = newBlocksUsed;
pFile->fExtData.eof = newEOF;
pFile->fSparseDataEof = (di_off_t) newEOF - (sparseCount * kBlkSize);
pFile->fSparseDataEof = (di_off_t) newEOF - (sparseBlocks * kBlkSize);
if (pFile->fSparseDataEof < 0)
pFile->fSparseDataEof = 0;
} else {
pFile->fExtRsrc.storageType = fOpenStorageType;
pFile->fExtRsrc.blocksUsed = newBlocksUsed;
pFile->fExtRsrc.eof = newEOF;
pFile->fSparseRsrcEof = (di_off_t) newEOF - (sparseCount * kBlkSize);
pFile->fSparseRsrcEof = (di_off_t) newEOF - (sparseBlocks * kBlkSize);
if (pFile->fSparseRsrcEof < 0)
pFile->fSparseRsrcEof = 0;
}
} else {
pFile->fSparseDataEof = (di_off_t) newEOF - (sparseCount * kBlkSize);
pFile->fSparseDataEof = (di_off_t) newEOF - (sparseBlocks * kBlkSize);
if (pFile->fSparseDataEof < 0)
pFile->fSparseDataEof = 0;
}

View File

@ -344,6 +344,9 @@ DIError DiskFSRDOS::ReadCatalog(void)
pFile = new A2FileRDOS(this);
memcpy(pFile->fRawFileName, dirPtr, A2FileRDOS::kMaxFileName);
pFile->fRawFileName[A2FileRDOS::kMaxFileName] = '\0';
memcpy(pFile->fFileName, dirPtr, A2FileRDOS::kMaxFileName);
pFile->fFileName[A2FileRDOS::kMaxFileName] = '\0';
pFile->FixFilename();
@ -521,6 +524,19 @@ DIError A2FileRDOS::Open(A2FileDescr** ppOpenFile, bool readOnly,
return kDIErrNone;
}
/*
* Returns the raw filename.
*
* If a pointer to a size_t is passed in, it will be filled with the
* raw filename length.
*/
const char* A2FileRDOS::GetRawFileName(size_t* size) const {
if (size) {
*size = strlen(fRawFileName);
}
return fRawFileName;
}
/*
* ===========================================================================

View File

@ -30,7 +30,7 @@ int TwoImgHeader::InitHeader(int imageFormat, uint32_t imageSize,
{
if (imageSize == 0)
return -1;
if (imageFormat < kImageFormatDOS || imageFormat > (int) kImageFormatNibble)
if (imageFormat < (int) kImageFormatDOS || imageFormat > (int) kImageFormatNibble)
return -1;
if (imageFormat != kImageFormatNibble &&

View File

@ -30,7 +30,27 @@ namespace DiskImgLib {
*/
class DISKIMG_API TwoImgHeader {
public:
TwoImgHeader(void) : fDOSVolumeNum(-1), fComment(NULL), fCreatorChunk(NULL)
TwoImgHeader(void) :
fMagic(0),
fCreator(0),
fHeaderLen(0),
fVersion(0),
fImageFormat(0),
fFlags(0),
fNumBlocks(0),
fDataOffset(0),
fDataLen(0),
fCmtOffset(0),
fCmtLen(0),
fCreatorOffset(0),
fCreatorLen(0),
fSpare(),
fDOSVolumeNum(-1),
fMagicStr(),
fCreatorStr(),
fComment(NULL),
fCreatorChunk(NULL)
{}
virtual ~TwoImgHeader(void) {
delete[] fComment;

View File

@ -119,7 +119,9 @@ private:
*/
class Win32VolumeAccess {
public:
Win32VolumeAccess(void) : fpBlockAccess(NULL)
Win32VolumeAccess(void) :
fTotalBlocks(-1),
fpBlockAccess(NULL)
{}
virtual ~Win32VolumeAccess(void) {
if (fpBlockAccess != NULL) {
@ -305,7 +307,11 @@ private:
*/
class PhysicalBlockAccess : public BlockAccess {
public:
PhysicalBlockAccess(void) : fHandle(NULL), fInt13Unit(-1) {}
PhysicalBlockAccess(void) :
fHandle(NULL),
fInt13Unit(-1),
fFloppyKind(kFloppyUnknown)
{}
virtual ~PhysicalBlockAccess(void) {}
virtual DIError Open(const WCHAR* deviceName, bool readOnly);

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -18,13 +18,13 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -18,15 +18,15 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">

View File

@ -13,6 +13,8 @@
#include <time.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "../diskimg/DiskImg.h"
using namespace DiskImgLib;
@ -97,7 +99,21 @@ CopyFiles(DiskFS* pDiskFS, int argc, char** argv)
};
argv--;
while (argc--) {
argv++;
// Confirm this is a regular file, and not a directory.
struct stat sb;
if (stat(*argv, &sb) != 0) {
fprintf(stderr, "Warning: unable to stat '%s'\n", *argv);
continue;
}
if ((sb.st_mode & S_IFREG) == 0) {
printf("--- Skipping '%s'\n", *argv);
continue;
}
printf("+++ Adding '%s'\n", *argv);
/*
@ -148,6 +164,11 @@ CopyFiles(DiskFS* pDiskFS, int argc, char** argv)
}
len = ftell(fp);
if (len >= 1L<<31) { // 2GB
fprintf(stderr, "Warning: file '%s' too large, skipping\n", *argv);
fclose(fp);
continue;
}
rewind(fp);
buf = new char[len];
@ -199,11 +220,6 @@ CopyFiles(DiskFS* pDiskFS, int argc, char** argv)
pNewFile->GetPathName(), DIStrError(dierr));
return -1;
}
/*
* On to the next file.
*/
argv++;
}
return 0;

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -19,13 +19,13 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@ -1,3 +1,8 @@
2017/09/21 ***** v3.1.0 shipped *****
2016/01/11 fadden
- Fix handling of disk images (broken by previous change).
2015/12/26 fadden
- Fix handling of entries with missing threads.
- Improve handling of Mac OS X file type attributes.

View File

@ -1586,6 +1586,9 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
needFakeData = false;
} else if (pThread->thThreadKind == kNuThreadKindRsrcFork) {
needFakeRsrc = false;
} else if (pThread->thThreadKind == kNuThreadKindDiskImage) {
/* needFakeRsrc shouldn't be set, but clear anyway */
needFakeData = needFakeRsrc = false;
}
err = Nu_ExtractThreadBulk(pArchive, &tmpRecord, pThread);
if (err == kNuErrSkipped) {
@ -1723,6 +1726,9 @@ static NuError Nu_ExtractRecordByPtr(NuArchive* pArchive, NuRecord* pRecord)
needFakeData = false;
} else if (pThread->thThreadKind == kNuThreadKindRsrcFork) {
needFakeRsrc = false;
} else if (pThread->thThreadKind == kNuThreadKindDiskImage) {
/* needFakeRsrc shouldn't be set, but clear anyway */
needFakeData = needFakeRsrc = false;
}
err = Nu_ExtractThreadBulk(pArchive, pRecord, pThread);
if (err == kNuErrSkipped) {

View File

@ -223,6 +223,9 @@ NuError Nu_ReadThreadHeaders(NuArchive* pArchive, NuRecord* pRecord,
needFakeData = false;
} else if (pThread->thThreadKind == kNuThreadKindRsrcFork) {
needFakeRsrc = false;
} else if (pThread->thThreadKind == kNuThreadKindDiskImage) {
/* needFakeRsrc shouldn't be set, but clear anyway */
needFakeData = needFakeRsrc = false;
}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -19,13 +19,14 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@ -24,6 +24,20 @@
* array of line records
* $ff $ff
* optional tags
*
* AppleWorks 5.0 introduced inverse and MouseText characters.
* These just use previously-unused byte ranges. The full set
* of values is thus:
* 00-1f special
* 20-7f plain ASCII
* 80-9f inverse upper (map to 40-5f)
* a0-bf inverse symbols/numbers (map to 20-3f)
* c0-df MouseText
* e0-ff inverse lower (map to 60-7f)
*
* We can output MouseText as Unicode symbols. Inverse text can use the Rich
* Text "highlight" feature; the "background color" feature doesn't seem to
* have any effect.
*/
/*
@ -55,6 +69,8 @@ int ReformatAWP::Process(const ReformatHolder* pHolder,
bool skipRecord;
uint8_t lineRecCode, lineRecData;
fMouseTextToASCII = pHolder->GetOption(ReformatHolder::kOptMouseTextToASCII) != 0;
if (srcLen > 65536)
fUseRTF = false;
@ -308,6 +324,7 @@ int ReformatAWP::HandleTextRecord(uint8_t lineRecData,
uint8_t byteCountPlusCR;
int byteCount = lineRecData;
bool noOutput = false;
bool inverse = false;
int ic;
tabFlags = Read8(pSrcPtr, pLength);
@ -372,40 +389,40 @@ int ReformatAWP::HandleTextRecord(uint8_t lineRecData,
break;
case kSpecialCharEnterKeyboard:
if (fShowEmbeds) {
RTFSetColor(kColorBlue);
TextColor oldColor = RTFSetColor(kColorBlue);
BufPrintf("<kdb-entry>");
RTFSetColor(kColorNone);
RTFSetColor(oldColor);
}
break;
case kSpecialCharPrintPageNumber:
if (fShowEmbeds) {
RTFSetColor(kColorBlue);
TextColor oldColor = RTFSetColor(kColorBlue);
BufPrintf("<page#>");
RTFSetColor(kColorNone);
RTFSetColor(oldColor);
}
break;
case kSpecialCharStickySpace:
/* MSWord uses "\~", but RichEdit ignores that */
BufPrintf(" ");
BufPrintf("\u00a0"); // Unicode NO-BREAK SPACE
break;
case kSpecialCharMailMerge:
if (fShowEmbeds) {
RTFSetColor(kColorBlue);
TextColor oldColor = RTFSetColor(kColorBlue);
BufPrintf("<mail-merge>");
RTFSetColor(kColorNone);
RTFSetColor(oldColor);
}
case kSpecialCharPrintDate:
if (fShowEmbeds) {
RTFSetColor(kColorBlue);
TextColor oldColor = RTFSetColor(kColorBlue);
BufPrintf("<date>");
RTFSetColor(kColorNone);
RTFSetColor(oldColor);
}
break;
case kSpecialCharPrintTime:
if (fShowEmbeds) {
RTFSetColor(kColorBlue);
TextColor oldColor = RTFSetColor(kColorBlue);
BufPrintf("<time>");
RTFSetColor(kColorNone);
RTFSetColor(oldColor);
}
break;
case kSpecialCharTab:
@ -421,19 +438,65 @@ int ReformatAWP::HandleTextRecord(uint8_t lineRecData,
default:
LOGI(" AWP unhandled special char 0x%02x", ic);
if (fShowEmbeds) {
RTFSetColor(kColorBlue);
TextColor oldColor = RTFSetColor(kColorBlue);
BufPrintf("^");
RTFSetColor(kColorNone);
RTFSetColor(oldColor);
}
}
} else {
if (fUseRTF)
RTFPrintChar(ic);
else
// Character.
bool wantInverse = false;
uint16_t mtLow = 0, mtHigh = 0;
if (ic >= 0x80 && ic <= 0x9f) {
// inverse upper; map 100x xxxx --> 010x xxxx
ic ^= 0xc0;
wantInverse = true;
} else if (ic >= 0xa0 && ic <= 0xbf || ic >= 0xe0 && ic <= 0xff) {
// inverse symbols; map 101x xxxx --> 001x xxxx
// inverse lower; map 111x xxxx --> 011x xxxx
ic ^= 0x80;
wantInverse = true;
} else if (ic >= 0xc0 && ic <= 0xdf) {
// MouseText characters
if (fMouseTextToASCII) {
ic = MouseTextToASCII(ic & 0x1f);
} else {
MouseTextToUTF16(ic & 0x1f, &mtLow, &mtHigh);
ic = '?';
}
} else {
// plain ASCII
}
if (wantInverse && !inverse) {
inverse = true;
RTFInverseOn();
} else if (!wantInverse && inverse) {
inverse = false;
RTFInverseOff();
}
if (fUseRTF) {
if (mtLow != 0) {
if (mtHigh != 0) {
RTFPrintUTF16Char(mtHigh);
}
RTFPrintUTF16Char(mtLow);
} else {
RTFPrintChar(ic);
}
} else {
// Plain text output.
BufPrintf("%c", PrintableChar(ic));
}
}
}
if (inverse) {
RTFInverseOff();
}
/* if there's a carriage return at the end of the line, output it now */
if (byteCountPlusCR & kCRatEOL) {
RTFNewPara();

View File

@ -16,7 +16,10 @@
*/
class ReformatAWP : public ReformatText {
public:
ReformatAWP(void) { fShowEmbeds = true; }
ReformatAWP(void)
: fShowEmbeds(true),
fMouseTextToASCII(false)
{}
virtual ~ReformatAWP(void) {}
virtual void Examine(ReformatHolder* pHolder) override;
@ -146,6 +149,7 @@ private:
FileHeader fFileHeader;
DocState fDocState;
bool fShowEmbeds;
bool fMouseTextToASCII;
};
/*

View File

@ -81,7 +81,11 @@ void ReformatSCAssem::Examine(ReformatHolder* pHolder)
long srcLen = pHolder->GetSourceLen(ReformatHolder::kPartData);
int len;
len = *ptr;
if (srcLen < 1) {
return false;
}
len = *ptr; // get length byte
if (len == 0 || len > srcLen)
return false; // should return an error, really
if (ptr[len-1] == 0x00) {

View File

@ -20,7 +20,7 @@
*/
class ReformatAsm : public ReformatText {
public:
ReformatAsm(void) {}
ReformatAsm(void) : fOutBuf(), fOutBufIndex(0) {}
virtual ~ReformatAsm(void) {}
void OutputStart(void) {
@ -129,7 +129,7 @@ private:
*/
class ReformatLISA3 : public ReformatAsm {
public:
ReformatLISA3(void) : fSymTab(NULL) {}
ReformatLISA3(void) : fSymTab(NULL), fSymCount(0) {}
virtual ~ReformatLISA3(void) {}
virtual void Examine(ReformatHolder* pHolder) override;
@ -197,7 +197,14 @@ private:
*/
class ReformatLISA4 : public ReformatAsm {
public:
ReformatLISA4(void) : fSymTab(NULL) {}
ReformatLISA4(void) :
fSymTab(NULL),
fSymCount(0),
fOpTab(0),
fAdTab(0),
fComTab(0),
fCpuType(0)
{}
virtual ~ReformatLISA4(void) { delete[] fSymTab; }
virtual void Examine(ReformatHolder* pHolder) override;

View File

@ -607,7 +607,7 @@ static const char gExtendedBusinessTokens[128*10] = {
/* 0xb8 */ "*error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 "
/* 0xc0 */ "*error*\0 *error*\0 *error*\0 STR$(\0 HEX$(\0 CHR$(\0 LEN(\0 VAL(\0 "
/* 0xc8 */ "ASC(\0 TEN(\0 *error*\0 *error*\0 CONV(\0 CONV&(\0 CONV$(\0 CONV%(\0 "
/* 0xd0 */ "LEFT$(\0 RIGHT$(\0 MID$(\0 INSTR$(\0 *error*\0 *error*\0 *error*\0 *error*\0 "
/* 0xd0 */ "LEFT$(\0 RIGHT$(\0 MID$(\0 INSTR(\0 *error*\0 *error*\0 *error*\0 *error*\0 "
/* 0xd8 */ "*error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 "
/* 0xe0 */ "*error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 "
/* 0xe8 */ "*error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 *error*\0 "
@ -738,7 +738,7 @@ int ReformatBusiness::Process(const ReformatHolder* pHolder,
(*srcPtr == 0xd0) || // LEFT$(
(*srcPtr == 0xd1) || // RIGHT$(
(*srcPtr == 0xd2) || // MID$(
(*srcPtr == 0xd3)) // INSTR$(
(*srcPtr == 0xd3)) // INSTR(
firstData = true;
else
firstData = false;

View File

@ -937,9 +937,10 @@ void ReformatDisasm16::PrintHeader(const OMFSegmentHeader* pSegHdr,
const char* versStr;
switch (pSegHdr->GetVersion()) {
case 0: versStr = "1.0"; break;
case 1: versStr = "2.0"; break;
case 2: versStr = "2.1"; break;
case 0: versStr = "0.0"; break;
case 1: versStr = "1.0"; break;
case 2: versStr = "2.0"; break;
case 0x82: versStr = "2.1"; break;
default: versStr = "(unknown)"; break;
}
@ -1058,8 +1059,9 @@ bool OMFSegmentHeader::Unpack(const uint8_t* srcBuf, long srcLen, int fileType)
return false;
}
fRevision = 0;
if (fVersion == 0) {
/* unpack OMF v1.0 */
/* unpack OMF v0.0 (not actually used for 16-bit code?) */
if (srcLen < kV0HdrMinSize)
return false;
@ -1086,7 +1088,7 @@ bool OMFSegmentHeader::Unpack(const uint8_t* srcBuf, long srcLen, int fileType)
else
fDispData = fDispName + fLabLen;
} else if (fVersion == 1) {
/* unpack OMF v2.0 */
/* unpack OMF v1.0 */
if (srcLen < kV1HdrMinSize)
return false;
fBlockCnt = Get32LE(srcBuf + 0x00);
@ -1124,7 +1126,7 @@ bool OMFSegmentHeader::Unpack(const uint8_t* srcBuf, long srcLen, int fileType)
fKind = 0;
fTempOrg = 0;
} else {
/* unpack OMF v2.1 */
/* unpack OMF v2.x */
if (srcLen < kV2HdrMinSize)
return false;
fByteCnt = Get32LE(srcBuf + 0x00);
@ -1144,7 +1146,13 @@ bool OMFSegmentHeader::Unpack(const uint8_t* srcBuf, long srcLen, int fileType)
fEntry = Get32LE(srcBuf + 0x24);
fDispName = Get16LE(srcBuf + 0x28);
fDispData = Get16LE(srcBuf + 0x2a);
fTempOrg = Get32LE(srcBuf + 0x2c);
if (fDispName > 0x2c) {
// v2.1 adds a 4-byte "tempOrg" field
fTempOrg = Get32LE(srcBuf + 0x2c);
fRevision = 1;
} else {
fTempOrg = 0;
}
fBlockCnt = 0;
fType = 0;
@ -1192,6 +1200,8 @@ bool OMFSegmentHeader::Unpack(const uint8_t* srcBuf, long srcLen, int fileType)
fLoadName[kLoadNameLen] = '\0';
segName += kLoadNameLen;
} else {
fLoadName[0] = '\0';
}
if (fLabLen == 0) {

View File

@ -227,7 +227,7 @@ public:
kTypePathName = 0x04,
kTypeLibraryDict = 0x08,
kTypeInit = 0x10,
kTypeAbsoluteBank = 0x11,
kTypeAbsoluteBank = 0x11, // v1.0 only
kTypeDPStack = 0x12,
} SegmentType;
typedef enum SegmentFlag {
@ -241,7 +241,7 @@ public:
kFlagDynamic,
} SegmentFlag;
uint8_t GetVersion(void) const { return fVersion; }
uint8_t GetVersion(void) const { return fVersion + (fRevision << 7); }
uint32_t GetSegmentLen(void) const { return fByteCnt; }
SegmentType GetSegmentType(void) const;
bool GetSegmentFlag(SegmentFlag flag) const;
@ -254,11 +254,11 @@ public:
// some of these must be public in VC++6.0
enum {
kMaxVersion = 2, // v0/1/2 == OMF 1.0 / 2.0 / 2.1
kMaxVersion = 2, // v0/1/2 == OMF 0.0 / 1.0 / 2.x
kLoadNameLen = 10,
kV0HdrMinSize = 0x25,
kV1HdrMinSize = 0x2c + kLoadNameLen,
kV2HdrMinSize = 0x30 + kLoadNameLen,
kV2HdrMinSize = kV1HdrMinSize, // 2.1 is slightly larger; handle that elsewhere
kHdrMinSize = kV0HdrMinSize, // smallest of the three
kExpectedNumLen = 4,
kExpectedBankSize = 65536,
@ -277,13 +277,14 @@ private:
}
uint32_t fBlockCnt; // v0/v1
uint32_t fByteCnt; // v2
uint32_t fByteCnt; // [v1]/v2
uint32_t fResSpc;
uint32_t fLength;
uint8_t fType; // v0/v1
uint8_t fLabLen;
uint8_t fNumLen; // (always 4)
uint8_t fVersion; // (0, 1, or 2)
uint8_t fRevision; // fictitious field; holds 0 or 1
uint32_t fBankSize; // (always 65536)
uint16_t fKind; // v2
uint32_t fOrg;

View File

@ -143,6 +143,7 @@ public:
kOptDHRAlgorithm,
kOptRelaxGfxTypeCheck,
kOptOneByteBrkCop,
kOptMouseTextToASCII,
kOptMAX // must be last
} OptionID;
@ -186,7 +187,7 @@ public:
* We want to know if it's DOS so we can relax some file-type checking,
* and we want to know if it's CP/M so we can adjust the way we think
* about text files. We want to know if it's Gutenberg because they only
* have one type of file, and it's indistingusihable from any other text file!
* have one type of file, and it's indistinguishable from any other text file!
*/
typedef enum SourceFormat {
kSourceFormatGeneric = 0,
@ -199,7 +200,16 @@ public:
/*
* Construct/destruct our object.
*/
ReformatHolder(void) {
ReformatHolder(void) :
fApplies(),
fFileType(0),
fAuxType(0),
fSourceFormat(kSourceFormatGeneric),
fNameExt(NULL),
fSourceBuf(),
fSourceLen(),
fErrorBuf()
{
int i;
for (int part = 0; part < kPartMAX; part++) {
if (part == kPartUnknown)
@ -207,7 +217,7 @@ public:
for (i = 0; i < kReformatMAX; i++)
fApplies[part][i] = kApplicUnknown;
fSourceBuf[part] = NULL;
fSourceLen[part] = NULL;
fSourceLen[part] = 0;
fErrorBuf[part] = NULL;
}
for (i = 0; i < kReformatMAX; i++) {
@ -215,10 +225,6 @@ public:
}
for (i = 0; i < kOptMAX; i++)
fOption[i] = 0;
fFileType = fAuxType = 0;
fSourceFormat = kSourceFormatGeneric;
fNameExt = NULL;
}
~ReformatHolder(void) {
LOGI("In ~ReformatHolder");
@ -355,7 +361,7 @@ private:
char* fNameExt; // guaranteed non-NULL
/* input goes here */
uint8_t* fSourceBuf[kPartMAX];
uint8_t* fSourceBuf[kPartMAX];
long fSourceLen[kPartMAX];
char* fErrorBuf[kPartMAX];

View File

@ -241,6 +241,28 @@ void ReformatText::RTFUnderlineOff(void)
}
}
void ReformatText::RTFInverseOn(void)
{
if (fInverseEnabled)
return;
if (fUseRTF) {
RTFSetColor(TextColor::kColorWhite);
BufPrintf("\\highlight1 "); // black
fInverseEnabled = true;
}
}
void ReformatText::RTFInverseOff(void)
{
if (!fInverseEnabled)
return;
if (fUseRTF) {
RTFSetColor(TextColor::kColorNone);
BufPrintf("\\highlight0 ");
fInverseEnabled = false;
}
}
void ReformatText::RTFOutlineOn(void)
{
if (fOutlineEnabled)
@ -321,14 +343,14 @@ void ReformatText::RTFSuperscriptOff(void)
}
}
void ReformatText::RTFSetColor(TextColor color)
ReformatText::TextColor ReformatText::RTFSetColor(TextColor color)
{
if (color == fTextColor)
return;
if (fUseRTF) {
TextColor oldColor = fTextColor;
if (color != fTextColor && fUseRTF) {
BufPrintf("\\cf%d ", color);
fTextColor = color;
}
return oldColor;
}
/*
@ -586,7 +608,7 @@ void ReformatText::ConvertEOL(const uint8_t* srcBuf, long srcLen,
*
* If "stripHiBits" is set, the high bit of each character is cleared before
* the value is considered.
*2
*
* If "stripNulls" is true, no null values will make it through.
*/
void ReformatText::ConvertEOL(const uint8_t* srcBuf, long srcLen,
@ -721,6 +743,61 @@ void ReformatText::BufHexDump(const uint8_t* srcBuf, long srcLen)
}
}
// Thanks to http://hoop-la.ca/apple2/docs/mousetext/unicode.html for Unicode.
// Thanks to Hugh Hood for extracting the ASCII conversions from SEG.WP.
static const struct {
uint32_t unicode; // UTF-16 single code point or surrogate pair
int8_t ascii; // 7-bit ASCII
} gMouseTextConv[32] = {
{ 0xd83cdf4e, '@' }, // 00 U+1f34e RED APPLE
{ 0xd83cdf4f, '@' }, // 01 U+1f34f GREEN APPLE
//{ 0x00002316, '^' }, // 02 U+2316 POSITION INDICATOR
{ 0x000025c4, '^' }, // 02 U+25c4 BLACK LEFT-POINTING POINTER
{ 0x000023f3, '&' }, // 03 U+23f3 HOURGLASS WITH FLOWING SAND
{ 0x00002713, '\'' }, // 04 U+2713 CHECK MARK
{ 0x00002705, '\'' }, // 05 U+2705 WHITE HEAVY CHECK MARK
{ 0x000023ce, '/' }, // 06 U+23ce RETURN SYMBOL
//{ 0xd83cdf54, ':' }, // 07 U+1f354 HAMBURGER
{ 0x00002630, ':' }, // 07 U+2630 TRIGRAM FOR HEAVEN (actually want 4 lines, not 3)
{ 0x00002190, '<' }, // 08 U+2190 LEFTWARDS ARROW
{ 0x00002026, '_' }, // 09 U+2026 HORIZONTAL ELLIPSIS
{ 0x00002193, 'v' }, // 0a U+2193 DOWNWARDS ARROW
{ 0x00002191, '^' }, // 0b U+2191 UPWARDS ARROW
{ 0x00002594, '-' }, // 0c U+2594 UPPER ONE EIGHTH BLOCK
{ 0x000021b5, '/' }, // 0d U+21b5 DOWNWARDS ARROW WITH CORNER LEFTWARDS
{ 0x00002589, '$' }, // 0e U+2589 LEFT SEVEN EIGHTHS BLOCK
{ 0x000021e4, '{' }, // 0f U+21e4 LEFTWARDS ARROW TO BAR
{ 0x000021e5, '}' }, // 10 U+21e5 RIGHTWARDS ARROW TO BAR
{ 0x00002913, 'v' }, // 11 U+2913 DOWNWARDS ARROW TO BAR
{ 0x00002912, '^' }, // 12 U+2912 UPWARDS ARROW TO BAR
{ 0x00002500, '-' }, // 13 U+2500 BOX DRAWINGS LIGHT HORIZONTAL
{ 0x0000231e, 'L' }, // 14 U+231e BOTTOM LEFT CORNER
{ 0x00002192, '>' }, // 15 U+2192 UPWARDS ARROW TO BAR
//{ 0xd83dde7e, '*' }, // 16 U+1f67e CHECKER BOARD
{ 0x00002591, '*' }, // 16 U+2591 LIGHT SHADE
//{ 0xd83dde7f, '*' }, // 17 U+1f67f REVERSE CHECKER BOARD
{ 0x00002592, '*' }, // 17 U+2592 MEDIUM SHADE
{ 0xd83ddcc1, '[' }, // 18 U+1f4c1 FILE FOLDER
{ 0xd83ddcc2, ']' }, // 19 U+1f4c2 OPEN FILE FOLDER
{ 0x00002595, '|' }, // 1a U+2595 RIGHT ONE EIGHTH BLOCK
{ 0x00002666, '#' }, // 1b U+2666 BLACK DIAMOND SUIT
{ 0x0000203e, '=' }, // 1c U+203e OVERLINE -- wrong, want top/bottom
{ 0x0000256c, '#' }, // 1d U+256c BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
//{ 0xd83ddcbe, 'O' }, // 1e U+1f4be FLOPPY DISK
{ 0x000022a1, 'O' }, // 1e U+22a1 SQUARED DOT OPERATOR (seems better than 25a3)
{ 0x0000258f, '|' }, // 1f U+258f LEFT ONE EIGHTH BLOCK
};
void ReformatText::MouseTextToUTF16(uint8_t mtVal, uint16_t* pLow, uint16_t* pHigh) {
ASSERT(mtVal < 32);
*pLow = gMouseTextConv[mtVal].unicode & 0xffff;
*pHigh = gMouseTextConv[mtVal].unicode >> 16;
}
int8_t ReformatText::MouseTextToASCII(uint8_t mtVal) {
ASSERT(mtVal < 32);
return gMouseTextConv[mtVal].ascii;
}
/*
* ==========================================================================
@ -786,11 +863,14 @@ void ReformatGraphics::SetResultBuffer(ReformatOutput* pOutput, MyDIBitmap* pDib
* Pass the destination buffer in "dst", source buffer in "src", source
* length in "srcLen", and expected sizes of output in "dstRem".
*
* Returns 0 on success, nonzero if the buffer is overfilled or underfilled.
* Returns the number of bytes unpacked on success, negative if the buffer is
* overfilled.
*/
int ReformatGraphics::UnpackBytes(uint8_t* dst, const uint8_t* src,
long dstRem, long srcLen)
{
const uint8_t* origDst = dst;
while (srcLen > 0) {
uint8_t flag = *src++;
int count = (flag & 0x3f) +1;
@ -884,13 +964,15 @@ int ReformatGraphics::UnpackBytes(uint8_t* dst, const uint8_t* src,
ASSERT(srcLen == 0);
/* require that we completely fill the buffer */
if (dstRem != 0) {
LOGI(" SHR unpack dstRem at %d", dstRem);
return -1;
if (false) {
/* require that we completely fill the buffer */
if (dstRem != 0) {
LOGI(" SHR unpack dstRem at %d", dstRem);
return -1;
}
}
return 0;
return dst - origDst;
}
/*

View File

@ -139,7 +139,7 @@ private:
/*
* Abstract base class for reformatting a graphics file into a
* device-independent bitmap..
* device-independent bitmap.
*/
class ReformatGraphics: public Reformat {
public:
@ -189,7 +189,8 @@ public:
};
ReformatText()
: fLeftMargin(0),
: fUseRTF(true),
fLeftMargin(0),
fRightMargin(0),
fPointSize(8),
fPreMultPointSize(8),
@ -197,6 +198,7 @@ public:
fBoldEnabled(false),
fItalicEnabled(false),
fUnderlineEnabled(false),
fInverseEnabled(false),
fOutlineEnabled(false),
fShadowEnabled(false),
fSuperscriptEnabled(false),
@ -304,6 +306,8 @@ protected:
void RTFItalicOff(void);
void RTFUnderlineOn(void);
void RTFUnderlineOff(void);
void RTFInverseOn(void);
void RTFInverseOff(void);
void RTFParaLeft(void);
void RTFParaRight(void);
void RTFParaCenter(void);
@ -316,7 +320,7 @@ protected:
void RTFOutlineOff(void);
void RTFShadowOn(void);
void RTFShadowOff(void);
void RTFSetColor(TextColor color);
TextColor RTFSetColor(TextColor color);
void RTFSetFont(RTFFont font);
void RTFSetFontSize(int points);
void RTFLeftMargin(int margin);
@ -381,9 +385,19 @@ protected:
fExpBuf.Printf("%c", ch);
}
// Converts a MouseText value (0-31) to a 16-bit UTF-16 value. If
// the character is in the BMP then only low is used. If it requires
// encoding as a surrogate pair, high will be nonzero.
void MouseTextToUTF16(uint8_t mtVal, uint16_t* pLow, uint16_t* pHigh);
// Converts a MouseText value (0-31) to an ASCII equivalent. This is not
// a 1:1 conversion, so it's not reversible.
int8_t MouseTextToASCII(uint8_t mtVal);
private:
DECLARE_COPY_AND_OPEQ(ReformatText)
int CreateWorkBuf(void);
enum { kRTFUnitsPerInch = 1440 }; // TWIPS
int fLeftMargin, fRightMargin; // for documents, in 1/10th inch
@ -393,6 +407,7 @@ private:
bool fBoldEnabled;
bool fItalicEnabled;
bool fUnderlineEnabled;
bool fInverseEnabled;
bool fOutlineEnabled;
bool fShadowEnabled;
bool fSuperscriptEnabled;

View File

@ -41,11 +41,6 @@
* color table is reversed, with color #15 appearing first in each table.
*/
/*
* Convert a SHRScreen struct to a 256-color DIB.
*
* This is a reasonably generic routine shared by SHR functions.
*/
MyDIBitmap* ReformatSHR::SHRScreenToBitmap8(const SHRScreen* pScreen)
{
return SHRDataToBitmap8(pScreen->pixels, pScreen->scb,
@ -55,61 +50,70 @@ MyDIBitmap* ReformatSHR::SHRScreenToBitmap8(const SHRScreen* pScreen)
MyDIBitmap* ReformatSHR::SHRDataToBitmap8(const uint8_t* pPixels,
const uint8_t* pSCB, const uint8_t* pColorTable,
int pixelBytesPerLine, int numScanLines,
int outputWidth, int outputHeight)
unsigned int bytesPerLine, unsigned int numScanLines,
unsigned int outputWidthPix, unsigned int outputHeightPix)
{
MyDIBitmap* pDib = new MyDIBitmap;
const uint8_t* pSCBStart = pSCB; // sanity check only
uint8_t* outBuf;
int line;
if (pDib == NULL)
goto bail;
// We can have an odd number of pixels, which results in 1-3 empty
// spaces in the last byte. We double the 4bpp pixels, so we're
// always outputting 4 pixels per byte.
if (outputWidthPix > bytesPerLine * 4 ||
outputWidthPix < bytesPerLine * 4 - 3) {
LOGW(" Invalid params: outputWidthPix=%u bytesPerLine=%u",
outputWidthPix, bytesPerLine);
ASSERT(false);
goto bail;
}
const uint8_t* pSCBStart = pSCB; // sanity check only
/*
* Set up a DIB to hold the data. "Create" returns a pointer to the
* pixel storage.
*/
outBuf = (uint8_t*) pDib->Create(outputWidth, outputHeight, 8,
kNumColorTables * kNumEntriesPerColorTable);
uint8_t* outBuf = (uint8_t*) pDib->Create(outputWidthPix, outputHeightPix,
8, kNumColorTables * kNumEntriesPerColorTable);
if (outBuf == NULL) {
delete pDib;
pDib = NULL;
goto bail;
}
int outputStride = pDib->GetPitch();
/*
* Convert color palette.
*/
const uint16_t* pClrTable;
pClrTable = (const uint16_t*) pColorTable;
int table;
for (table = 0; table < kNumColorTables; table++) {
for (int table = 0; table < kNumColorTables; table++) {
for (int entry = 0; entry < kNumEntriesPerColorTable; entry++) {
GSColor(*pClrTable++, &fColorTables[table][entry]);
}
}
pDib->SetColorTable((RGBQUAD*)fColorTables);
/*
LOGI(" SHR color table 0");
int ii;
for (ii = 0; ii < kNumEntriesPerColorTable; ii++) {
LOGI(" %2d: 0x%02x %02x %02x",
ii,
fColorTables[0][ii].rgbRed,
fColorTables[0][ii].rgbGreen,
fColorTables[0][ii].rgbBlue);
if (false) {
LOGI(" SHR color table 0");
for (int ii = 0; ii < kNumEntriesPerColorTable; ii++) {
LOGI(" %2d: 0x%02x %02x %02x",
ii,
fColorTables[0][ii].rgbRed,
fColorTables[0][ii].rgbGreen,
fColorTables[0][ii].rgbBlue);
}
}
*/
/*
* Set the pixels to palette indices.
*/
unsigned int line;
for (line = 0; line < numScanLines; line++) {
bool mode640, fillMode;
int colorTableOffset;
int byteCount, pixelByte;
unsigned int byteCount;
uint8_t pixelVal;
uint8_t colorIndex;
int x = 0;
@ -128,30 +132,27 @@ MyDIBitmap* ReformatSHR::SHRDataToBitmap8(const uint8_t* pPixels,
}
#define SetPix(x, y, colridx) \
outBuf[((outputHeight-1) - (y)) * outputWidth + (x)] = colridx
outBuf[((outputHeightPix-1) - (y)) * outputStride + (x)] = colridx
if (mode640) {
/* 320 mode, one byte becomes four non-doubled pixels (1:4) */
int actualBytesPerLine = outputWidth / 4;
ASSERT(actualBytesPerLine <= pixelBytesPerLine);
/* 640 mode, one byte becomes four non-doubled pixels (1:4) */
unsigned int fullBytesPerLine = outputWidthPix / 4;
ASSERT(fullBytesPerLine <= bytesPerLine);
for (byteCount = 0; byteCount < actualBytesPerLine; byteCount++) {
pixelByte = *pPixels++;
for (byteCount = 0; byteCount < fullBytesPerLine; byteCount++) {
uint8_t pixelByte = *pPixels++;
pixelVal = (pixelByte >> 6) & 0x03;
//rgbval = fColorLookup[colorTable][pixelVal + 12];
colorIndex = colorTableOffset + pixelVal + 8;
SetPix(x, line*2, colorIndex);
SetPix(x++, line*2+1, colorIndex);
pixelVal = (pixelByte >> 4) & 0x03;
//rgbval = fColorLookup[colorTable][pixelVal + 8];
colorIndex = colorTableOffset + pixelVal + 12;
SetPix(x, line*2, colorIndex);
SetPix(x++, line*2+1, colorIndex);
pixelVal = (pixelByte >> 2) & 0x03;
//rgbval = fColorLookup[colorTable][pixelVal + 4];
colorIndex = colorTableOffset + pixelVal + 0;
SetPix(x, line*2, colorIndex);
SetPix(x++, line*2+1, colorIndex);
@ -162,18 +163,38 @@ MyDIBitmap* ReformatSHR::SHRDataToBitmap8(const uint8_t* pPixels,
SetPix(x, line*2, colorIndex);
SetPix(x++, line*2+1, colorIndex);
}
for ( ; byteCount < pixelBytesPerLine; byteCount++)
pPixels++;
if (byteCount != bytesPerLine) {
// 1-3 pixels in last byte
uint8_t pixelByte = *pPixels++;
int rem = outputWidthPix - fullBytesPerLine * 4;
if (rem >= 3) {
pixelVal = (pixelByte >> 6) & 0x03;
colorIndex = colorTableOffset + pixelVal + 8;
SetPix(x, line * 2, colorIndex);
SetPix(x++, line * 2 + 1, colorIndex);
}
if (rem >= 2) {
pixelVal = (pixelByte >> 4) & 0x03;
colorIndex = colorTableOffset + pixelVal + 12;
SetPix(x, line * 2, colorIndex);
SetPix(x++, line * 2 + 1, colorIndex);
}
if (rem >= 1) {
pixelVal = (pixelByte >> 2) & 0x03;
colorIndex = colorTableOffset + pixelVal + 0;
SetPix(x, line * 2, colorIndex);
SetPix(x++, line * 2 + 1, colorIndex);
}
}
} else {
/* 320 mode, one byte becomes two doubled pixels (1:4) */
int actualBytesPerLine = outputWidth / 4;
ASSERT(actualBytesPerLine <= pixelBytesPerLine);
unsigned int fullBytesPerLine = outputWidthPix / 4;
ASSERT(fullBytesPerLine <= bytesPerLine);
for (byteCount = 0; byteCount < actualBytesPerLine; byteCount++) {
pixelByte = *pPixels++;
for (byteCount = 0; byteCount < fullBytesPerLine; byteCount++) {
uint8_t pixelByte = *pPixels++;
pixelVal = (pixelByte >> 4) & 0x0f;
//rgbval = fColorLookup[colorTable][pixelVal];
colorIndex = colorTableOffset + pixelVal;
SetPix(x, line*2, colorIndex);
SetPix(x++, line*2+1, colorIndex);
@ -181,27 +202,31 @@ MyDIBitmap* ReformatSHR::SHRDataToBitmap8(const uint8_t* pPixels,
SetPix(x++, line*2+1, colorIndex);
pixelVal = pixelByte & 0x0f;
//rgbval = fColorLookup[colorTable][pixelVal];
colorIndex = colorTableOffset + pixelVal;
SetPix(x, line*2, colorIndex);
SetPix(x++, line*2+1, colorIndex);
SetPix(x, line*2, colorIndex);
SetPix(x++, line*2+1, colorIndex);
}
for ( ; byteCount < pixelBytesPerLine; byteCount++)
pPixels++;
if (byteCount != bytesPerLine) {
// 1 pixel in last byte
uint8_t pixelByte = *pPixels++;
pixelVal = (pixelByte >> 4) & 0x0f;
colorIndex = colorTableOffset + pixelVal;
SetPix(x, line * 2, colorIndex);
SetPix(x++, line * 2 + 1, colorIndex);
SetPix(x, line * 2, colorIndex);
SetPix(x++, line * 2 + 1, colorIndex);
}
}
#undef SetPix
/* pixel bytes can be 0-7 larger because of 8-byte boundary req */
/* pixel count is 1x or 2x the pixel bytes */
/* output width is 1x or 2x the pixel count */
ASSERT(x >= outputWidth && x < outputWidth + (8*4));
ASSERT(x == outputWidthPix);
pSCB++;
}
ASSERT(line == outputHeight/2);
ASSERT(line == outputHeightPix/2);
ASSERT(pSCB == pSCBStart + numScanLines);
bail:
@ -441,7 +466,7 @@ int ReformatPaintworksSHR::Process(const ReformatHolder* pHolder,
pHolder->GetSourceBuf(part) + kPWDataOffset,
kPWOutputSize,
pHolder->GetSourceLen(part) - kPWDataOffset);
if (result != 0) {
if (result != kPWOutputSize) {
LOGI("WARNING: UnpackBytes wasn't happy");
#if 0
@ -523,7 +548,7 @@ int ReformatPackedSHR::Process(const ReformatHolder* pHolder,
if (UnpackBytes((uint8_t*) &fScreen,
pHolder->GetSourceBuf(part), kTotalSize,
pHolder->GetSourceLen(part)) != 0)
pHolder->GetSourceLen(part)) != kTotalSize)
{
LOGW(" SHR UnpackBytes failed");
goto bail;
@ -649,7 +674,9 @@ int ReformatAPFSHR::Process(const ReformatHolder* pHolder,
if (!haveGraphics)
goto bail;
if (is3200) {
// TODO: we don't currently handle MULTIPAL with anything other than
// a 320x200 image. Fortunately this is rare.
if (is3200 && !fNonStandard) {
Reformat3200SHR ref3200(&fScreen, multiPal);
pDib = ref3200.SHR3200ToBitmap24();
@ -699,11 +726,11 @@ int ReformatAPFSHR::UnpackMain(const uint8_t* srcPtr, long srcLen)
{
const int kColorTableSize = kNumEntriesPerColorTable * kColorTableEntrySize;
uint16_t masterMode;
int numColorTables;
int* packedDataLen = NULL;
unsigned int numColorTables;
uint16_t* packedDataLen = NULL;
int retval = -1;
if (srcLen < 256) {
if (srcLen < 64) {
/* can't possibly be this small */
LOGI(" APFSHR unlikely srcLen %d", srcLen);
goto bail;
@ -712,9 +739,7 @@ int ReformatAPFSHR::UnpackMain(const uint8_t* srcPtr, long srcLen)
masterMode = Read16(&srcPtr, &srcLen);
fPixelsPerScanLine = Read16(&srcPtr, &srcLen);
numColorTables = Read16(&srcPtr, &srcLen);
if (fPixelsPerScanLine < 8 || fPixelsPerScanLine > kMaxPixelsPerScan ||
(fPixelsPerScanLine & 0x01) != 0)
{
if (fPixelsPerScanLine == 0 || fPixelsPerScanLine > kMaxPixelsPerScan) {
LOGI(" APFSHR unsupported pixelsPerScanLine %d",
fPixelsPerScanLine);
goto bail;
@ -722,8 +747,10 @@ int ReformatAPFSHR::UnpackMain(const uint8_t* srcPtr, long srcLen)
LOGD(" APFSHR masterMode=0x%04x, ppsl=%d, nct=%d",
masterMode, fPixelsPerScanLine, numColorTables);
if (numColorTables <= 0 || numColorTables > kNumColorTables) {
LOGI(" APFSHR unexpected numColorTables %d", numColorTables);
if (numColorTables == 0 || numColorTables > kNumColorTables) {
// Zero is valid per the spec, but we don't know how to render that.
// Rather than showing an all-black bitmap, just fail.
LOGI(" APFSHR unsupported numColorTables %d", numColorTables);
goto bail;
}
@ -731,10 +758,9 @@ int ReformatAPFSHR::UnpackMain(const uint8_t* srcPtr, long srcLen)
* Load the color tables.
*/
memset(fScreen.colorTable, 0, sizeof(fScreen.colorTable));
int i;
for (i = 0; i < numColorTables; i++) {
for (unsigned int i = 0; i < numColorTables; i++) {
if (srcLen < kColorTableSize) {
LOGI(" APFSHR ran out while copying color tables");
LOGI(" APFSHR underrun while copying color tables");
goto bail;
}
@ -751,7 +777,7 @@ int ReformatAPFSHR::UnpackMain(const uint8_t* srcPtr, long srcLen)
* doubling so we can handle both 320 mode and 640 mode.
*/
fNumScanLines = Read16(&srcPtr, &srcLen);
if (fNumScanLines < 8 || fNumScanLines > kMaxScanLines) {
if (fNumScanLines == 0 || fNumScanLines > kMaxScanLines) {
LOGI(" APFSHR unsupported numScanLines %d", fNumScanLines);
goto bail;
}
@ -783,17 +809,6 @@ int ReformatAPFSHR::UnpackMain(const uint8_t* srcPtr, long srcLen)
fOutputWidth = fPixelsPerScanLine;
fPixelBytesPerLine = (fPixelsPerScanLine + 3) / 4; // "640 mode"
}
/*
* We want to create our storage such that the bytes per line is evenly
* divisible by 8. I have no idea why I'm doing this, but at this
* point I'm afraid to change it. Something with PackBytes? The APF
* filetype note doesn't say anything. It doesn't matter to the
* bitmap code, because we're feeding it in a pixel at a time, and any
* pitch requirememts are concealed within MyDIBitmap.
*
* Figure this out someday.
*/
fPixelBytesPerLine = ((fPixelBytesPerLine + 7) / 8) * 8;
fPixelStore = new uint8_t[fPixelBytesPerLine * fNumScanLines];
if (fPixelStore == NULL) {
LOGI(" APFSHR ERROR: alloc of %d bytes fPixelStore failed",
@ -813,12 +828,10 @@ int ReformatAPFSHR::UnpackMain(const uint8_t* srcPtr, long srcLen)
/*
* Get the per-scanline data.
*/
packedDataLen = new int[fNumScanLines];
packedDataLen = new uint16_t[fNumScanLines];
if (packedDataLen == NULL)
goto bail;
for (i = 0; i < fNumScanLines; i++) {
uint16_t mode;
for (unsigned int i = 0; i < fNumScanLines; i++) {
packedDataLen[i] = Read16(&srcPtr, &srcLen);
if (packedDataLen[i] > fPixelsPerScanLine) {
/* each pixel is 2 or 4 bits, so this is a 2-4x expansion */
@ -827,28 +840,42 @@ int ReformatAPFSHR::UnpackMain(const uint8_t* srcPtr, long srcLen)
goto bail;
}
mode = Read16(&srcPtr, &srcLen);
uint16_t mode = Read16(&srcPtr, &srcLen);
if (mode >> 8 == 0)
fSCBStore[i] = (uint8_t) mode;
else {
LOGI(" APFSHR odd mode 0x%04x on line %d", mode, i);
fSCBStore[i] = 0; // ?
}
}
/*
* Unpack the scan lines.
* Unpack the scan lines into the pixel storage. Some APF files
* use PackBytes in a not-quite-safe way, e.g. a 28x30 image with
* 14 bytes per line uses the 32-bit pattern repeat mode (0x3fff),
* yielding 16 bytes. We need to unpack to a temp buffer.
*
* I've found a few from 816/Paint that appear to have the wrong width
* value; they claim 320 but look like they're actually 640 (the image
* seems to be cut in half, and we unpack 2x as much data as we expect).
*/
for (i = 0; i < fNumScanLines; i++) {
for (unsigned int i = 0; i < fNumScanLines; i++) {
// PackBytes can generate 256 bytes from a single pair of bytes.
uint8_t tmpBuf[ReformatSHR::kMaxPixelsPerScan];
if (srcLen <= 0) {
LOGI(" APFSHR ran out of data while unpacking pixels");
goto bail;
}
if (UnpackBytes(&fPixelStore[i * fPixelBytesPerLine],
srcPtr, fPixelBytesPerLine, packedDataLen[i]) != 0)
{
LOGI(" APFSHR UnpackBytes failed on line %d", i);
int actual = UnpackBytes(tmpBuf, srcPtr, sizeof(tmpBuf), packedDataLen[i]);
if (actual < (int) fPixelBytesPerLine) { // includes actual < 0
LOGI(" APFSHR UnpackBytes failed on line %d (pbpl=%d actual=%d)",
i, fPixelBytesPerLine, actual);
goto bail;
}
//LOGD("+++ unpackbytes %d pbpl=%d pdl=%d --> %d",
// i, fPixelBytesPerLine, packedDataLen[i], actual);
memcpy(&fPixelStore[i * fPixelBytesPerLine], tmpBuf, fPixelBytesPerLine);
srcPtr += packedDataLen[i];
srcLen -= packedDataLen[i];
@ -1006,8 +1033,7 @@ int Reformat3200SHR::Process(const ReformatHolder* pHolder,
const uint16_t* pSrcTable = (const uint16_t*)
(pHolder->GetSourceBuf(part) + sizeof(fScreen.pixels));
uint16_t* pDstTable = (uint16_t*) fExtColorTable;
int table;
for (table = 0; table < kExtNumColorTables; table++) {
for (int table = 0; table < kExtNumColorTables; table++) {
int entry;
for (entry = 0; entry < kNumEntriesPerColorTable; entry++) {
pDstTable[(kNumEntriesPerColorTable-1) - entry] = *pSrcTable++;
@ -1057,8 +1083,7 @@ MyDIBitmap* Reformat3200SHR::SHR3200ToBitmap24(void)
*/
const uint16_t* pClrTable;
pClrTable = (const uint16_t*) fExtColorTable;
int table;
for (table = 0; table < kExtNumColorTables; table++) {
for (int table = 0; table < kExtNumColorTables; table++) {
for (int entry = 0; entry < kNumEntriesPerColorTable; entry++) {
GSColor(*pClrTable++, &colorLookup[table][entry]);
//if (!table) {
@ -1188,8 +1213,10 @@ int Reformat3201SHR::Process(const ReformatHolder* pHolder,
length -= srcBuf - (pHolder->GetSourceBuf(part) +4);
/* now unpack the PackBytes-format pixels */
if (UnpackBytes(fScreen.pixels, srcBuf, sizeof(fScreen.pixels), length) != 0)
if (UnpackBytes(fScreen.pixels, srcBuf, sizeof(fScreen.pixels), length)
!= sizeof(fScreen.pixels)) {
goto bail;
}
pDib = SHR3200ToBitmap24();
if (pDib == NULL)

View File

@ -69,11 +69,33 @@ public:
/* 16 palettes of 16 colors */
RGBQUAD fColorTables[kNumColorTables][kNumEntriesPerColorTable];
/*
* Convert a SHRScreen struct to a 256-color DIB.
*
* This is a reasonably generic routine shared by SHR functions.
*/
MyDIBitmap* SHRScreenToBitmap8(const SHRScreen* pScreen);
/*
* Convert tables of SHR data to an 8bpp bitmap. The expectation is
* that we double-up 320-mode pixels and double the height, so the
* output for a standard SHR image will be a 640x400 bitmap.
*
* "pPixels" is the 2-bit or 4-bit pixel data.
* "pSCB" points to an array of SCB values, one per scan line.
* "pColorTable" points to an array of 16 color tables (16 entries each).
* "bytesPerLine" is the number of whole bytes per line.
* "numScanLines" is the number of scan lines.
* "outputWidthPix" is the width, in pixels (640 for full screen).
* "outputHeightPix" is the height, in pixels (400 for full screen).
*
* If the source material has an odd width, part of the last byte will
* be empty.
*/
MyDIBitmap* SHRDataToBitmap8(const uint8_t* pPixels,
const uint8_t* pSCB, const uint8_t* pColorTable,
int pixelBytesPerLine, int numScanLines,
int outputWidth, int outputHeight);
unsigned int bytesPerLine, unsigned int numScanLines,
unsigned int outputWidthPix, unsigned int outputHeightPix);
};
/*
@ -185,11 +207,11 @@ private:
/* use this for non-standard-sized images */
uint8_t* fPixelStore;
uint8_t* fSCBStore;
int fNumScanLines; // #of scan lines in image
int fPixelsPerScanLine;
int fPixelBytesPerLine;
int fOutputWidth;
int fOutputHeight; // scan lines * 2
unsigned int fNumScanLines; // #of scan lines in image
unsigned int fPixelsPerScanLine;
unsigned int fPixelBytesPerLine;
unsigned int fOutputWidth;
unsigned int fOutputHeight; // scan lines * 2
};
/*

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -19,13 +19,13 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@ -23,7 +23,7 @@
*/
class CancelDialog : public ModelessDialog {
public:
CancelDialog(void) {}
CancelDialog(void) : fpCancelFlag(NULL) {}
virtual ~CancelDialog(void) {}
BOOL Create(bool* pCancelFlag, int dialogID, CWnd* pParentWnd = NULL) {

View File

@ -62,6 +62,9 @@ void* MyDIBitmap::Create(int width, int height, int bitsPerPixel, int colorsUsed
assert(bitsPerPixel == 24 || bitsPerPixel == 32 || colorsUsed > 0);
// should include a warning if line stride is not a multiple of 4 bytes
if ((width & 0x03) != 0) {
LOGW(" DIB stride must be multiple of 4 bytes (got %d)", width);
}
mBitmapInfoHdr.biSize = sizeof(mBitmapInfoHdr); // BITMAPINFOHEADER
mBitmapInfoHdr.biWidth = width;

View File

@ -67,6 +67,11 @@ public:
/*
* Creates a blank DIB with the requested dimensions.
*
* The DIB requires that the array of bytes defining the pixels of the
* bitmap be padded with zeroes to end on a "LONG data-type boundary",
* i.e. the start of each line must be 32-bit aligned. This is done
* automatically behind the scenes.
*
* Returns a pointer to the pixel storage on success, or NULL on failure.
*/
void* Create(int width, int height, int bitsPerPixel, int colorsUsed,

View File

@ -46,7 +46,8 @@ class SelectFilesDialog : public CFileDialog {
public:
SelectFilesDialog(const WCHAR* rctmpl, bool showHelp, CWnd* pParentWnd = NULL) :
CFileDialog(true, NULL, NULL, OFN_HIDEREADONLY, NULL, pParentWnd,
0, FALSE /*disable Vista style*/)
0, FALSE /*disable Vista style*/),
fPrevWndProc(NULL)
{
// Set flags. We specify ALLOWMULTISELECT but no filename buffer;
// we want the multi-select behavior but we don't want to return

View File

@ -362,7 +362,7 @@ void CreateSimpleFont(CFont* pFont, CWnd* pWnd, const WCHAR* typeFace,
void GetWin32ErrorString(DWORD err, CString* pStr)
{
DWORD count;
LPVOID lpMsgBuf;
LPVOID lpMsgBuf = NULL;
count = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
@ -417,6 +417,27 @@ void CheckedLoadString(CString* pString, UINT nID)
}
}
float GetDesktopScaleFactor()
{
// The current scale factor for controls is determined by the settings
// for the main display at the time the application was launched. If we
// don't do this, the controls will get all scrunched together if the
// scale is over 100% (issue #53). The settings API doesn't seem to
// allow scaling things down, so we're only worried about expansion here.
//
// https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/dpi-related-apis-and-registry-settings?view=windows-11#primary-display-dpi-scale-factor
// Get desktop dc
HDC desktopDc = ::GetDC(NULL);
// Get native resolution
int horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX);
int verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY);
float scaleFactor = horizontalDPI / 96.0f;
LOGD("Native DPI: %dx%d, scaleFactor=%.3f",
horizontalDPI, verticalDPI, scaleFactor);
return scaleFactor;
}
/*
* ===========================================================================
@ -486,6 +507,7 @@ void LogHexDump(const void* vbuf, long len)
cp = outBuf + strlen(outBuf);
}
ASSERT(cp != NULL);
sprintf(cp, "%02x ", *buf++);
cp += 3;
}
@ -757,7 +779,7 @@ bool MatchSemicolonList(const CString set, const CString match)
cp++;
}
LOGI("--- No match for '%ls' in '%ls'", (LPCWSTR) match, (LPCWSTR) set);
LOGD("--- No match for '%ls' in '%ls'", (LPCWSTR) match, (LPCWSTR) set);
return false;
}

View File

@ -199,6 +199,13 @@ bool IsWin9x(void);
*/
void CheckedLoadString(CString* pString, UINT nID);
/*
* Returns the desktop scaling factor (usually 1.0). Assumes vertical and
* horizontal scaling is identical.
*/
float GetDesktopScaleFactor();
/*
* ====================================
* Miscellaneous functions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -19,13 +19,13 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -19,13 +19,14 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>