Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
654 lines (555 sloc) 29.5 KB
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
PortSystem 1.0
# Please keep the minivmac and minivmac-devel ports as similar as possible.
set my_name minivmac
set my_suffix {}
name ${my_name}${my_suffix}
set my_subport [regsub -- {-devel$} ${subport} {}]
conflicts [lsearch -all -inline -not -exact [list ${my_subport} ${my_subport}-devel] ${subport}]
version 3.5.8
set my_version [strsed ${version} {g/^.*-20//}]
categories emulators aqua
maintainers {ryandesign @ryandesign}
license GPL-2
platforms macosx
dist_subdir ${my_name}
description an emulator of the Macintosh Plus and other \
early Macintosh models
long_description Mini vMac emulates early Macintosh computers \
that use Motorola's 680x0 processors, sold by \
Apple from 1984 to 1996.
options my_variations
default my_variations {}
if {${my_subport} eq ${my_name}} {
livecheck.type regex
livecheck.url ${homepage}doc/download.html
livecheck.regex ${my_name}-(\[0-9.\]+)\\.src
long_description-append The best-tested variation emulates a Macintosh \
Plus, but it can also emulate a Macintosh \
128K, 512K, 512Ke, SE, SE FDHD, Classic, or \
Macintosh II.
revision 1
supported_archs noarch
depends_run port:${my_name}-plus${my_suffix}
use_configure no
build {}
destroot {
xinstall -d ${destroot}${prefix}/share/doc/${my_subport}
system "echo ${subport} is a stub port > ${destroot}${prefix}/share/doc/${my_subport}/README"
notes "
The ${subport} stub port is not meant to be installed. Instead,\
install one (or more) of the available subports corresponding to the\
Macintosh model(s) you wish to emulate. Use `port info --subports\
${subport}\' to see the list of available subports.
} else {
livecheck.type none
revision 4
supported_archs i386 ppc x86_64
distname ${my_name}-${my_version}
use_zip yes
master_sites${my_version}/:minivmacsource \
sourceforge:project/minivmac/minivmac-extras/extras6:minivmacextras6 \
sourceforge:project/minivmac/minivmac-extras/extras11:minivmacextras11 \ \
set my_src ${distname}.src
set my_src_distfile ${my_src}.zip
set my_bootstrap_distfile ${my_name}
set my_icons icnsosx-1.0.0
set my_icons_distfile ${my_icons}.zip
set my_autoquit autquit7-1.3.1
set my_autoquit_distfile ${my_autoquit}.zip
set my_system_disk_container System_7.0.1.smi
set my_system_disk_container_distfile ${my_system_disk_container}.bin
distfiles ${my_src_distfile}:minivmacsource \
${my_bootstrap_distfile}:bootstrap \
${my_icons_distfile}:minivmacextras6 \
${my_autoquit_distfile}:minivmacextras11 \
extract.only ${my_src_distfile} \
${my_bootstrap_distfile} \
${my_icons_distfile} \
checksums ${my_src_distfile} \
rmd160 818b45d1ee993c28ab36be3370f059b32ba8f1f9 \
sha256 9cf58688772d1cd0b4c061148b01f3c6ee32567b07773cc2ed63246d2fb3af61 \
size 677097 \
${my_bootstrap_distfile} \
rmd160 a15361b4b0d765e55ed84525593639b38e4a71fd \
sha256 ad08da6cfdf616d67664520eb2dd787632c502c43ff6355ac6e3a7fc8d53e811 \
size 148787 \
${my_icons_distfile} \
rmd160 cef6d7d7578464538d0042b0d98379ae7f18fab7 \
sha256 968a0bad51903c9cd3b08476ec5a6572856dc44eedf9ff9b174eb9c59b7b7117 \
size 60373 \
${my_autoquit_distfile} \
rmd160 949ce06752fbcfa9a92787497dace45e7299eb41 \
sha256 a9aad37cfd2d6dbd4db5e307b8598348ba25aa5504aac968b8d570d5927e576a \
size 52341 \
${my_system_disk_container_distfile} \
rmd160 89fc3780c9c5d575a8da4068dc810c1f56c70211 \
sha256 d78e1c52a6f16ba14907cbe816a22a43f8aa8e1a9c4f664d3b7d5d982a9baab2 \
size 5147648
depends_extract port:bsdiff
depends_build port:timeout
depends_skip_archcheck bsdiff \
set my_app_dir "${applications_dir}/Mini vMac"
set my_rom_dir "~/Library/Preferences/Gryphel/mnvm_rom"
set my_bootstrap_app "Mini vMac"
set my_rom_file vMac.ROM
set mnvm_target(i386) imch
set mnvm_target(ppc) mach
set mnvm_target(x86_64) mc64
# Options that are the same for every variation.
configure.pre_args -maintainer MacPorts \
-homepage \
-cl \
-eol unx \
-api cco \
-sony-sum 1 \
-sony-tag 1
if [info exists xcodeversion] {
set xcodeversion_split [concat [split ${xcodeversion} {.}] {0 0 0}]
configure.pre_args-append \
-e xcd \
-ev [lindex ${xcodeversion_split} 0][string range [join [lrange ${xcodeversion_split} 1 end] {}] 0 2]
# Options set by variations.
# Options set by variants.
# The number of seconds to wait before killing the bootstrap process, in
# case it gets stuck.
set my_bootstrap_timeout 30
pre-extract {
if {[my_real_rom_file] eq ""} {
ui_msg "****************************************************************"
ui_msg "To build Mini vMac, you will need a ROM file from a Macintosh"
ui_msg "Plus or 512Ke. And to run it, you need a ROM file from the type"
ui_msg "of Mac you want to emulate. ROM files are not included with this"
ui_msg "package because they are copyrighted Apple software."
ui_msg "To create a ROM file, download the CopyRoms program from"
ui_msg ""
ui_msg "and transfer it to a real physical early Macintosh that you own."
ui_msg "Run the CopyRoms program there, then transfer the ROM file back"
ui_msg "to this Mac and put it in ${my_rom_dir}"
ui_msg "(which can be an alias or symlink if desired) or"
ui_msg "${my_app_dir}."
ui_msg "****************************************************************"
return -code error "${my_rom_file} not found"
worksrcdir configure
build.dir ${workpath}/build
extract.mkdir yes
set mnvm_data_dir ${worksrcpath}/${my_bootstrap_app}/Contents/mnvm_dat
set mnvm_output_dir ${mnvm_data_dir}/out
post-extract {
# Decompress the system disk container image.
ui_debug "Decompressing ${my_system_disk_container_distfile}."
set my_system_disk_container_decompressed "[file rootname ${my_system_disk_container}].dmg"
system -W ${worksrcpath} "hdiutil convert '${distpath}/${my_system_disk_container_distfile}' -format UDRO -o '${my_system_disk_container_decompressed}'"
# The images on the container image. Images we don't need are commented out for future reference.
set my_images {
{Disk Tools.image} 58368 eb1979132c843560ebab490faeb7520d9a94757ecef3121a21abace8d3ae63ff
# {Fonts.image} 427264 8b06f086a96b75bd23b16ae018bd334696239cb56e65bfa20166ea00d14cdef0
# {Install 1.image} 796160 8c3ea898eeb88b795041108cd8a09bf4ebdf920d7d4763e4419df14713dbd952
# {Install 2.image} 1165056 0fc558475df55f3aed217d2eceebfa29e4a465a795807cd627b258740a9ec55b
# {Printing.image} 1533952 246cbf69ad1c2e588ee482fddec781135a67fbfe02734bb0f732eb055faa15fa
# {Tidbits.image} 1902848 3e3600bed1b5c7c595bc176b5eaadcc8c1517032489efc548b9b781c0ee1f062
# Extract the disk images from the system disk container image. `hdiutil` on OS X 10.8 Mountain Lion
# does not mount this disk image correctly, so extract the files manually using `dd`.
foreach {my_image_filename my_image_offset my_image_sha256} ${my_images} {
ui_debug "Extracting ${my_image_filename} from ${my_system_disk_container_decompressed}."
system -W ${worksrcpath} "dd if='${my_system_disk_container_decompressed}' bs=4 count=368661 skip=${my_image_offset} of='${my_image_filename}'"
if {${my_image_sha256} ne [sha256 file ${worksrcpath}/${my_image_filename}]} {
return -code error "extract failed"
# Delete temporary files we no longer need.
delete ${worksrcpath}/${my_system_disk_container_decompressed}
# Symlink the ROM file into the data directory.
ln -s [my_real_rom_file] ${mnvm_data_dir}
# Use the prettier icon on the bootstrap app.
copy -force ${worksrcpath}/${my_icons}/icons/AppIcon.icns ${worksrcpath}/${my_bootstrap_app}/Contents/Resources/ICONAPPO.icns
post-patch {
# See in the files directory for instructions
# on recreating these binary patchfiles.
# Modify the AutQuit7 disk to have an alias "app" pointing to the MnvM_b35
# application and an 8192-byte TeachText file called "doc" (containing
# "@START@", 8180 periods and spaces, and "@END@").
system -W ${worksrcpath}/${my_autoquit} "${prefix}/bin/bspatch '${my_autoquit}.dsk' '${my_autoquit}.dsk.tmp' '${filespath}/patch-${my_autoquit}.dsk.bsdiff'"
move -force "${worksrcpath}/${my_autoquit}/${my_autoquit}.dsk.tmp" "${worksrcpath}/${my_autoquit}/${my_autoquit}.dsk"
# Modify the Disk Tools disk to have an alias of AutQuit7 in the Startup
# Items folder.
system -W ${worksrcpath} "${prefix}/bin/bspatch 'Disk Tools.image' 'Disk Tools.image.tmp' '${filespath}/patch-Disk Tools.image.bsdiff'"
move -force "${worksrcpath}/Disk Tools.image.tmp" "${worksrcpath}/Disk Tools.image"
configure {
set my_variation_dirs {}
# Delete remnants from possible previous run.
delete ${build.dir}
# Copy the disk images into the data directory with sequentially-numbered
# names so Mini vMac will find them and automatically mount them.
copy -force "${worksrcpath}/Disk Tools.image" ${mnvm_data_dir}/disk1.dsk
copy -force ${worksrcpath}/${my_src}/${my_src}.dsk ${mnvm_data_dir}/disk3.dsk
# Configure all variations.
foreach my_arch [get_canonical_archs] {
file mkdir ${build.dir}/${my_arch}
foreach {my_machine my_variation_options} ${my_variations} {
set my_variation ${my_version}_${revision}-[strsed [string tolower ${my_machine}] {g/[^a-z0-9_-]//}]-$mnvm_target(${my_arch})
ui_debug "Configuring ${my_variation}"
configure.args -t $mnvm_target(${my_arch}) \
-n ${my_variation} \
set max_configure_args_length 8192
set all_configure_args [concat ${configure.pre_args} ${configure.args} ${configure.post_args}]
set padded_configure_args [format "%-${max_configure_args_length}s" ${all_configure_args}]
if {[string length ${padded_configure_args}] > ${max_configure_args_length}} {
return -code error "configure args too long"
# Write the configure args into the "doc" file on the AutQuit7 disk image.
copy -force ${worksrcpath}/${my_autoquit}/${my_autoquit}.dsk ${mnvm_data_dir}/disk2.dsk
reinplace -locale C "s|@START@\[ .\]*@END@|${padded_configure_args}|" ${mnvm_data_dir}/disk2.dsk
# Launch the bootstrap Mini vMac to run the configuration. When it's done
# it should automatically quit, but if not, we time out after awhile.
exec -ignorestderr ${prefix}/bin/timeout ${my_bootstrap_timeout} "${worksrcpath}/${my_bootstrap_app}/Contents/MacOS/minivmac" 2>/dev/null
set my_src_tarball ${mnvm_output_dir}/${my_variation}.tar
if {[file isfile ${my_src_tarball}]} {
set my_variation_dir ${my_arch}/${my_machine}
lappend my_variation_dirs [strsed ${my_variation_dir} {g/ /\\\\ /}]
# Untar the configured source code.
system -W ${build.dir} "tar xf '${my_src_tarball}'"
move ${build.dir}/${my_variation} ${build.dir}/${my_variation_dir}
if {${my_subport} eq "${my_name}-bootstrap"} {
# Change the "export" function so that exported files
# are written to the "out" directory instead of
# prompting for a location.
system -W ${build.dir}/${my_variation_dir} "patch -p0 < ${filespath}/SaveDialogDisable.patch"
# Don't require the discrete GPU.
system -W ${build.dir}/${my_variation_dir} "patch -p0 < ${filespath}/AutomaticGraphicsSwitching.patch"
# Truncate icon to save space.
close [open ${build.dir}/${my_variation_dir}/src/ICONAPPO.icns w]
} else {
# Use prettier icons.
foreach icon {App Dsk Rom} {
copy -force ${worksrcpath}/${my_icons}/icons/${icon}Icon.icns \
${build.dir}/${my_variation_dir}/src/ICON[string toupper ${icon}]O.icns
# Use the right compiler.
reinplace "s|gcc|${}|g" ${build.dir}/${my_variation_dir}/Makefile
# Use the right deployment target.
reinplace -E {s|-mmacosx-version-min=[0-9.]+||g} ${build.dir}/${my_variation_dir}/Makefile
# Use the right SDK.
if {${configure.sdkroot} eq {}} {
set sdkflags {}
} else {
set sdkflags "-isysroot${configure.sdkroot}"
reinplace -E "s|-isysroot *\[^ \]+|${sdkflags}|g" ${build.dir}/${my_variation_dir}/Makefile
# Enable Retina display support.
system -W ${build.dir}/${my_variation_dir} "patch -p0 < ${filespath}/Retina.patch"
# Prevent merge error.
if {[variant_exists universal] && [variant_isset universal]} {
reinplace "s|$mnvm_target(${my_arch})|umch|" ${build.dir}/${my_variation_dir}/src/Info.plist
# If no variation directories were produced by configuration, something went
# horribly wrong.
if {${my_variation_dirs} eq ""} {
return -code error "configuration failed!"
# Set up the global Makefile.
xinstall ${filespath}/ ${build.dir}/Makefile
reinplace "s|@SUBDIRS@|[join ${my_variation_dirs}]|" ${build.dir}/Makefile
destroot {
foreach my_arch [get_canonical_archs] {
if {[variant_exists universal] && [variant_isset universal]} {
set my_dest ${workpath}/pre-dest/${my_arch}
} else {
set my_dest ${destroot}
xinstall -d ${my_dest}${my_app_dir}
foreach {my_machine unused} ${my_variations} {
copy ${build.dir}/${my_arch}/${my_machine}/ \
"${my_dest}${my_app_dir}/Mini vMac ${my_machine}.app"
if {[variant_exists universal] && [variant_isset universal]} {
merge ${workpath}/pre-dest
foreach {my_machine unused} ${my_variations} {
set my_dest_mnvm_dat "${destroot}${my_app_dir}/Mini vMac ${my_machine}.app/Contents/mnvm_dat"
file mkdir ${my_dest_mnvm_dat}
destroot.keepdirs-append ${my_dest_mnvm_dat}
pre-activate {
if {![catch {set installed [lindex [registry_active ${name}] 0]}]} {
set installed_version [lindex ${installed} 1]
set installed_revision [lindex ${installed} 2]
set installed_epoch [lindex ${installed} 5]
if {[vercmp ${installed_epoch} 0] == 0 && (
[vercmp ${installed_version} 3.5.8] < 0 || (
[vercmp ${installed_version} 3.5.8] == 0 && [vercmp ${installed_revision} 1] < 0
)} {
registry_deactivate_composite ${name} "" [list ports_nodepcheck 1]
set default_screen_size 512x342
set default_speed 8x
subport ${my_name}-128k${my_suffix} {
my_variations {128K} {-m 128K}
subport ${my_name}-512k${my_suffix} {
my_variations {512K} {-m 128K -mem 512K}
subport ${my_name}-512ke${my_suffix} {
my_variations {512Ke} {-m 512Ke}
subport ${my_name}-plus${my_suffix} {
my_variations {Plus} {-m Plus}
default_variants +icon_master
subport ${my_name}-se${my_suffix} {
my_variations {SE} {-m SE}
subport ${my_name}-sefdhd${my_suffix} {
my_variations {SE FDHD} {-m SEFDHD}
subport ${my_name}-classic${my_suffix} {
my_variations {Classic} {-m Classic}
subport ${my_name}-ii${my_suffix} {
my_variations {II} {-m II}
set default_color_depth 256
set default_screen_size 640x480
set default_speed 4x
subport ${my_name}-custom${my_suffix} {
long_description-append This subport allows the user to compile custom \
variations of Mini vMac.
set custom_conf_name custom.conf
set custom_conf ${prefix}/etc/${my_name}/${custom_conf_name}
set local_custom_conf ${worksrcpath}/${custom_conf_name}
pre-configure {
if {[file exists ${custom_conf}]} {
copy -force ${custom_conf} ${local_custom_conf}
} else {
delete ${local_custom_conf}
pre-destroot {
proc custom_variation_error {err} {
global name
ui_error "For instructions, see"
ui_error "${name}/files/"
return -code error ${err}
proc add_custom_variation {variation_name variation_options} {
if {${variation_options} ne {}} {
my_variations-append ${variation_name} ${variation_options}
proc setup_custom_variations {} {
global custom_conf custom_conf_name local_custom_conf filespath
if {![file exists ${local_custom_conf}]} {
ui_error "This subport allows you to compile custom variations. Copy"
ui_error " ${filespath}/${custom_conf_name}.sample"
ui_error "to"
ui_error " ${custom_conf}"
ui_error "and then edit ${custom_conf_name}."
custom_variation_error "missing ${custom_conf_name}"
set fp [open ${local_custom_conf} r]
set custom_data [read ${fp}]
close ${fp}
set custom_lines [split ${custom_data} "\n"]
set custom_name {Custom}
set custom_options {}
set custom_line_number 0
set custom_line_continue no
foreach custom_line ${custom_lines} {
incr custom_line_number
if [regexp -- {^\s*[;#]} ${custom_line}] {
} elseif ${custom_line_continue} {
set custom_line_continue [regsub -- {^(.*)\\$} ${custom_line} {\1} custom_line]
append custom_${custom_key} " [string trim ${custom_line}]"
} elseif [regexp -- {^([^=]+)=(.*)$} ${custom_line} -> custom_key custom_value] {
set custom_line_continue [regsub -- {^(.*)\\$} ${custom_value} {\1} custom_value]
set custom_key [string trim ${custom_key}]
set custom_${custom_key} [string trim ${custom_value}]
} elseif [regexp -- {^\s*\[([^\]]+)\]\s*$} ${custom_line} -> new_custom_name] {
add_custom_variation ${custom_name} ${custom_options}
set custom_name ${new_custom_name}
set custom_options {}
} elseif ![regexp -- {^\s*$} ${custom_line}] {
ui_error "Syntax error on line ${custom_line_number} of ${custom_conf_name}: '${custom_line}'"
custom_variation_error "syntax error in ${custom_conf_name}"
add_custom_variation ${custom_name} ${custom_options}
if {[option my_variations] eq {}} {
ui_error "No custom variations defined in ${custom_conf_name}."
custom_variation_error "no variations in ${custom_conf_name}"
# To build the bootstrap application, use:
# sudo port destroot minivmac bootstrap=yes subport=minivmac-bootstrap
# The subport is hidden because it is useful only to the port maintainer.
if {[tbool bootstrap]} {
subport ${my_name}-bootstrap${my_suffix} {
my_variations {Bootstrap} {-m Plus -as 0 -bg 1 -mf 1 -sound 0 -speed a -var-fullscreen 0}
description Mini vMac Bootstrap
long_description A copy of Mini vMac specially configured to be \
used to build other copies of Mini vMac.
depends_build-append port:p7zip
depends_skip_archcheck-append \
if {${os.major} < 11} {
default_variants +universal
configure.universal_archs \
macosx_deployment_target 10.4
set output_archive ${workpath}/${my_name}-bootstrap-${version}_${revision}.zip
post-destroot {
exec 7za a ${output_archive} ${destroot}${my_app_dir}/${my_bootstrap_app}
ui_msg "The distribution zip file has been created:"
ui_msg "${output_archive}"
if {[variant_exists universal] && [variant_isset universal] && [lsort ${configure.universal_archs}] eq [lsort ${supported_archs}]} {
ui_msg "This file contains all the necessary architectures and"
ui_msg "can be distributed."
} else {
ui_warn "DON'T DISTRIBUTE THIS FILE! It doesn't contain all the"
ui_warn "necessary architectures. To build a distributable"
ui_warn "bootstrap app, use the universal variant and build on"
ui_warn "Mac OS X Leopard or Snow Leopard."
if {${my_subport} ni [list "${my_name}" "${my_name}-bootstrap" "${my_name}-custom"]} {
description a Macintosh [lindex ${my_variations} 0] emulator
long_description-append This subport emulates a Macintosh \
[lindex ${my_variations} 0].
if {[lindex ${my_variations} 0] eq "Plus"} {
long_description-append This is the best-tested variation.
long_description-append There are other subports that emulate other Macintosh \
variant icon_master description {Take ownership of disk image files and ROM image files; at most one copy of Mini vMac should do this} {
configure.post_args-append \
-im 1
variant min_extensions description {Disable extensions not needed for most situations, including clipboard import/export and file/disk image creation} {
configure.post_args-append \
if {${my_subport} eq "${my_name}-ii"} {
set color_depths {
0 bw {Black and white only}
1 4 {4 colors or black and white}
2 16 {16 colors or black and white}
3 256 {256 colors or black and white}
4 thousands {Thousands of colors or black and white}
5 millions {Millions of colors or black and white}
foreach {color_depth color_depth_name color_depth_description} ${color_depths} {
lappend color_depth_variants colors_${color_depth_name}
set set_default_color_depth_variant yes
foreach {color_depth color_depth_name color_depth_description} ${color_depths} {
set color_depth_variant colors_${color_depth_name}
variant ${color_depth_variant} conflicts {*}[lsearch -all -inline -not -exact ${color_depth_variants} ${color_depth_variant}] description ${color_depth_description} "
configure.post_args-append -depth ${color_depth}
if [variant_isset ${color_depth_variant}] {
set set_default_color_depth_variant no
if ${set_default_color_depth_variant} {
default_variants +colors_${default_color_depth}
set screen_sizes {512x342 512x384}
if {${my_subport} ne "${my_name}-128k"} {
lappend screen_sizes 640x480 800x600 1024x768
foreach screen_size ${screen_sizes} {
lappend screen_size_variants screen_${screen_size}
set set_default_screen_size_variant yes
foreach screen_size ${screen_sizes} {
set screen_hres [lindex [split ${screen_size} {x}] 0]
set screen_vres [lindex [split ${screen_size} {x}] 1]
set screen_size_variant screen_${screen_size}
variant ${screen_size_variant} conflicts {*}[lsearch -all -inline -not -exact ${screen_size_variants} ${screen_size_variant}] description "Screen size ${screen_size}" "
configure.post_args-append -hres ${screen_hres} -vres ${screen_vres}
if [variant_isset ${screen_size_variant}] {
set set_default_screen_size_variant no
if ${set_default_screen_size_variant} {
default_variants +screen_${default_screen_size}
set speeds {z 1x 1 2x 2 4x 3 8x 4 16x 5 32x a unlimited}
foreach {speed speed_name} ${speeds} {
lappend speed_variants speed_${speed_name}
set set_default_speed_variant yes
foreach {speed speed_name} ${speeds} {
set speed_variant speed_${speed_name}
variant ${speed_variant} conflicts {*}[lsearch -all -inline -not -exact ${speed_variants} ${speed_variant}] description "Default CPU speed ${speed_name}" "
configure.post_args-append -speed ${speed}
if [variant_isset ${speed_variant}] {
set set_default_speed_variant no
if ${set_default_speed_variant} {
default_variants +speed_${default_speed}
# Returns the full path to the ROM file, wherever the user has it,
# or the empty string if the user doesn't have it.
proc my_real_rom_file {} {
global my_app_dir my_rom_dir my_rom_file
if {[file exists ${my_app_dir}/${my_rom_file}]} {
return ${my_app_dir}/${my_rom_file}
set my_real_rom_dir [my_read_alias ${my_rom_dir}]
if {[file exists ${my_real_rom_dir}/${my_rom_file}]} {
return ${my_real_rom_dir}/${my_rom_file}
return ""
# Resolves a Mac OS X alias.
proc my_read_alias {file} {
global filespath
return [exec osascript ${filespath}/readalias.applescript [file normalize ${file}]]
You can’t perform that action at this time.