Here is an AppleScript to simplify reading/writing X/ProFile CF cards.
I speculate the main advantages are:
- automagically calculates how much of the CF card is used for the STARs, and only that portion of the card is read, saving time and space.
- checks the specified volume was formatted by the X/ProFile, reducing the chance of overwriting the wrong thing
Use requires a Mac and a way to connect your CF card (or other X/ProFile media) to the Mac... typically one would use a USB CF card reader.
This was initially tested on Tiger (10.4) ... I imagine that can still be made to work, and most recently Mojave (10.14) and Monterey (12).
If you wish to port the code, note that AppleScript is 1 based, so reading bytes 9 to 12 (as in the getstarsize subroutine) gives you the 9th to 12th bytes.
To use, select & copy the following code, paste into a Script Editor document, and run it.
-- Created by James MacPhail for free distribution in the public domain.
-- Use at your own risk.
--
-- Please post improvements and bug reports to the "XProFile CF Card Image Tool" thread at LisaList2.com
--
-- this applescript is used to read/write an image of an X/ProFile CF card from/to a physical CF card using dd
-- (although developed for CF cards, this should work with any X/ProFile media including IDE drives attached to the computer)
--
-- administrator privileges will be requested for accessing the device, which increases the potential extent of problems when something goes wrong, so please pay attention
-- - For later versions of OSX, you may need to assign privileges to the "Script Editor" application; eg. for "Files and Folders" and/or "Full Disk Access" in order for this script to be able to access the device for reading or writing...
-- - To do this, open System Preferences, select the "Security & Privacy" panel, select the "Privacy" tab, scroll down to "Files and Folders" or "Full Disk Access", "Click the lock to make changes", click "+" and locate "Script Editor" - usually it is in Applications/Utilities. Although some of the names of these Preferences items differ for varying versions of OSX, they are generally the same.
--
-- the CF card is first examined to make sure it has already been "prepared" by the X/ProFile.
-- - This is to ensure the correct device has been located, but may seem like a nuisance step when you want to use fresh media, so the following feature was added in v1.4:
-- New in v1.4: if you wish to use media (eg. a CF card) that hasn't been "prepared" by the X/ProFile first, you can do so by:
-- - naming the disk in the Finder as XPROFILE and making sure it has no files or folders on it
-- - note that in the case of media that has multiple partitions on it (more than just the volume named XPROFILE ), the media is completely overwritten since the X/ProFile needs exclusive use of it. Hence it is critical that you name the correct disk/volume of the desired media, any other volumes on the same media will be erased; if you are unsure, prepare the media with the X/ProFile first!
--
-- the image created from reading an XProFile CF card contains both STARs and the X/ProFile disk image preamble
-- when reading, the image size is adjusted to suit the size and Type of the larger STAR
-- (so you'll have a 20-40 MB image if you have one 10MB STAR and one 5MB STAR on a 2GB CF card)
--
-- Usage Notes:
-- When inserting a CF card to read/write, it may take a while until the OS has found it; trying to access it too soon will fail with "X/ProFile CF card not found"
-- no compression or data error detection is used for the images, so zipping an image will be beneficial when sending via email etc.
-- when writing to a CF card, the file selected to write is not validated as an XProFile image, it is blindly written to the target
--
-- 1.4 : Saturday, July 12, 2025 at 1:00:51 PM : add provision to write to a new device that hasn't been prepared by an X/ProFile
-- 1.3 : Tuesday, January 28, 2025 at 2:35:54 PM : check xprofile volume hasn't moved before writing to it
-- 1.2 : Saturday, May 16, 2020 at 2:44:04 PM : Corrected error message for touching new image to read into
-- 1.1 : Friday, April 26, 2019 3:49:25 PM : Extended timeouts for read and write operations
-- 1.0 : 2017-08-12 12:55pm : First version distributed for beta testing
--
property versiondate : "Saturday, July 12, 2025 at 1:04:00 PM"
property thisversion : 1.4
property newmediamessage : "To use new media, you may either:
a) Prepare the media in the actual X/ProFile first, or
b) name the media XPROFILE in the Finder and delete
all files and folders on it"
property expected : "This is an image of a ProFile hard disk in a proprietary format. This file is used by the ProFile emulator for the Apple ][, Apple ///, Apple Lisa, and Macintosh XL. http://SigmaSevenSystems.com"
--
set cancelB to " Cancel "
--
set disk to my getXPROFILEdevice()
if disk = "" then return -- error message already shown
--
-- read signature from card to verify it was formatted by X/ProFile
try
set chktexteven to do shell script ("dd bs=1 skip=97320 count=194 if=/dev/" & disk) with administrator privileges
set chktextodd to do shell script ("dd bs=1 skip=97832 count=194 if=/dev/" & disk) with administrator privileges
on error err number errno
set de to my displayerror(err, errno, "Failed to read from XPROFILE CF card.")
return
end try
if not (chktexteven = expected or chktextodd = expected) then
set ddns to display dialog "The X/ProFile signature was not found on the XPROFILE device volume." & return & return & "If it was initialized by an X/ProFile then this indicates a problem reading the correct device. Data read may be invalid and data loss may occur upon writing. Continue regardless?" buttons {"Continue", cancelB} default button cancelB
if button returned of ddns is not "Continue" then return
end if
--
-- determine function
set ddfn to display dialog "Read from CF card or Write to CF card?" buttons {cancelB, "Write", "Read"} default button "Read"
set operation to button returned of ddfn
if operation is cancelB then
return
else if operation is "Read" then
-- read from card to create image
set {haseven, evensize, hasodd, oddsize} to {false, 0, false, 0}
-- read STAR headers from card
try
set starinfoeven to do shell script ("dd bs=1 skip=97744 count=48 if=/dev/" & disk) with administrator privileges
set starinfoodd to do shell script ("dd bs=1 skip=98256 count=48 if=/dev/" & disk) with administrator privileges
on error err number errno
set de to my displayerror(err, errno, "Failed to read STAR info from XPROFILE CF card.")
return
end try
set sig5aa5 to (ASCII character (90)) & (ASCII character (165)) -- $5A A5
if starinfoeven begins with sig5aa5 then set haseven to true
if starinfoodd begins with sig5aa5 then set hasodd to true
--
-- extract disk space used in number of blocks
if haseven then set evensize to my getstarsize(starinfoeven)
if hasodd then set oddsize to my getstarsize(starinfoodd)
--
-- determine larger space used
set readsize to evensize
if oddsize > readsize then set readsize to oddsize
if readsize = 0 then
set dd to display dialog ("Image size cannot be determined. Read entire card?") buttons {"OK", cancelB} default button cancelB
if button returned of dd is cancelB then return
set countspec to ""
set promptspec to "Name the image file (size unknown)"
else
set countspec to " count=" & (readsize + 2) -- correct size because count is 1 based, STAR last sector was zero based
set promptspec to "Name the image file (" & (round ((readsize * 512) / 10000)) / 100 & " MB)"
end if
--
-- select output file
set thefile to choose file name with prompt promptspec
--
set fp to quoted form of POSIX path of thefile
-- if file does not exist, create it without administrator privileges so it will have the user as the owner
set crf to "touch " & fp
try
set crfr to do shell script crf without administrator privileges -- using administrator privileges would make it a system file the user can't overwrite
on error err number errno
set de to my displayerror(err, errno, "Failed to access or create destination image file.")
error err
end try
--
set starttime to current date
--
-- read CF card to image file
set rtoi to "dd bs=0x200" & countspec & " if=/dev/" & disk & " of=" & fp
try
with timeout of 6000 seconds
set rtoir to do shell script rtoi with administrator privileges
end timeout
on error err number errno
set de to my displayerror(err, errno, "Failed when reading XPROFILE CF card / writing image.")
end try
--
set endtime to current date
--
beep
set dd to display dialog "Read XPROFILE to file completed after " & endtime - starttime & " seconds." buttons {"OK", "Eject"} default button "Eject" giving up after 50
--
else if operation is "Write" then
--
if not (chktexteven = expected or chktextodd = expected) then
-- do further checks when writing to a device not previously prepared by X/ProFile
-- is the volume empty of visible files & folders?
set countfiles to do shell script "find /Volumes/XPROFILE/* -type f 2>/dev/null | wc -l"
set countfolders to do shell script "find /Volumes/XPROFILE/* -type d 2>/dev/null | wc -l"
set itemcount to (countfiles as number) + (countfolders as number)
if itemcount > 0 then
set ddic to display dialog "The XPROFILE volume is not empty." & return & return & "Delete all the items and try again." buttons {cancelB} default button cancelB
return
end if
-- check for multiple volumes on one device
set dul2 to do shell script "diskutil list | grep " & disk & "s"
if (count paragraphs of dul2) > 1 then
set ddmv to display dialog "The device appears to have more than one volume. Are you sure you want to erase them all?" buttons {"Erase them!", cancelB} default button cancelB
if button returned of ddmv is not "Erase them!" then return
end if
end if
--
-- unmount device
set duu to "diskutil unmountDisk force /dev/" & disk
try
set duur to do shell script duu with administrator privileges
on error err number errno
set de to my displayerror(err, errno, "Failed to unmount XPROFILE device.")
return
end try
--
-- ask for image to write to card
try
set thefile to choose file with prompt "Select an X/ProFile image file to write to the XPROFILE media"
on error err number errno
if errno = -128 then -- user canceled
set dmd to "diskutil mountDisk /dev/" & disk
try
set dmdr to do shell script dmd with administrator privileges
return
on error err number errno
set de to my displayerror(err, errno, "Failed to (re-)mount XPROFILE device.")
return
end try
else
error err number errno
end if
end try
set fp to quoted form of POSIX path of thefile
--
-- confirm
set dd to display dialog "Ready to overwrite the XPROFILE media / CF card; are you sure? (Writing may take a few minutes)" buttons {"Continue", cancelB}
if button returned of dd is not "Continue" then return
--
-- check device has not changed
if not (disk = my getXPROFILEdevice()) then
display dialog "XPROFILE device has changed unexpectedly." buttons cancelB default button cancelB
return
end if
--
set starttime to current date
--
-- write image to device
set ddc to ("sudo dd if=" & fp & " of=/dev/" & disk)
try
with timeout of 6000 seconds
set ddr to do shell script ddc with administrator privileges
end timeout
on error err number errno
set de to my displayerror(err, errno, "Failed when writing image to XPROFILE CF card.")
return
end try
--
set endtime to current date
--
beep
set dd to display dialog "Write to XPROFILE media completed after " & endtime - starttime & " seconds." buttons {"OK", "Eject"} default button "Eject" giving up after 50
end if
if button returned of dd is "Eject" then tell application "Finder" to eject "XPROFILE"
set summary to (starttime as text) & return & operation & " " & disk & return & thefile
return summary
--
--
to getXPROFILEdevice()
-- ask diskutil if there is an X/ProFile volume
try
set dul to do shell script "diskutil list | grep XPROFILE"
on error err number errno
display dialog "XPROFILE media / CF card not found." & return & return & newmediamessage & return & return & "... then try again." buttons " Cancel " default button " Cancel "
return ""
end try
--
-- ensure there is only one
if (count paragraphs of dul) > 1 then
display dialog "More than one XPROFILE volume is attached: too ambiguous to continue." buttons " Cancel " default button " Cancel "
return ""
end if
--
-- extract device of X/ProFile card
set thesubdisk to last word of dul
set thedisk to (characters 1 through -3 of thesubdisk) as text
return thedisk
end getXPROFILEdevice
--
--
to getstarsize(starinfo)
set starsize to 0
repeat with i from 9 to 12
set starsize to starsize * 256 + (ASCII number (character i of starinfo))
end repeat
return starsize
end getstarsize
--
--
to displayerror(err, errno, msg)
beep
set dd to display dialog (msg & " Error " & errno & ": " & err) buttons " Cancel " default button " Cancel "
return 1
end displayerror
--
-- END
edit: updated to version 1.4, which implements a method to write to new media (eg. CF cards) that have not been prepared by the X/ProFile in advance.