<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>MagerValp</title>
 <link href="http://magervalp.github.io/atom.xml" rel="self"/>
 <link href="http://magervalp.github.io/"/>
 <updated>2018-09-24T10:41:36+00:00</updated>
 <id>http://magervalp.github.io/</id>
 <author>
   <name>Per Olofsson</name>
   <email>magervalp@fastmail.fm</email>
 </author>

 
 <entry>
   <title>AutoDMG v1.9</title>
   <link href="http://magervalp.github.io/2019/09/24/autodmg-v1.9.html"/>
   <updated>2019-09-24T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2019/09/24/autodmg-v1.9</id>
   <content type="html">&lt;p&gt;AutoDMG v1.9 is out! Apple unfortunately introduced a couple of OS installer bugs in Mojave beta 4 that are still unresolved. I’ve implemented a workaround for one of them, but one still remains:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added 10.14 support. &lt;br /&gt; ⚠️ To successfully build on Mojave the installer must be on an external volume, see issue &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/issues/222&quot;&gt;#222&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Removed 10.10 and 10.11 support.&lt;/li&gt;
  &lt;li&gt;Removed HFS+ support for 10.14+.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll find the download on the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.8.1</title>
   <link href="http://magervalp.github.io/2018/04/24/autodmg-v1.8.1.html"/>
   <updated>2018-04-24T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2018/04/24/autodmg-v1.8.1</id>
   <content type="html">&lt;p&gt;I’ve released AutoDMG 1.8.1, which includes the following bugfixes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add App Transport Security exception for &lt;code class=&quot;highlighter-rouge&quot;&gt;cdn-apple.com&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Show a helpful error message when an &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ#9-what-are-incomplete-installers&quot;&gt;incomplete installer&lt;/a&gt; is used.&lt;/li&gt;
  &lt;li&gt;Better error messages when image building fails.&lt;/li&gt;
  &lt;li&gt;Fail but don’t crash if a profile is bad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll find the download on the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>defaults write with double slash</title>
   <link href="http://magervalp.github.io/2018/01/30/defaults-write-double-slash.html"/>
   <updated>2018-01-30T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2018/01/30/defaults-write-double-slash</id>
   <content type="html">&lt;p&gt;My ass has been bitten twice by this now, so I figured a blog post to warn others might be in order. Say you’re writing a package postinstall script where you want to set a preference, and you dutifully use &lt;code class=&quot;highlighter-rouge&quot;&gt;$3&lt;/code&gt; to target the installation volume. You might write a script along these lines:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-sh&quot;&gt;#!/bin/bash
# This is buggy, don't use it. A working script is at the bottom of this post.

defaults write &quot;$3/Library/Preferences/com.tyrell.nexussix&quot; lifespan -int 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next thing you know some of your replicants grow old and decide to kill you, as when an app tries to read the preference it gets an unexpected result:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-py&quot;&gt;#!/usr/bin/python

from __future__ import unicode_literals
from __future__ import print_function
from Foundation import CFPreferencesCopyAppValue

print(CFPreferencesCopyAppValue(&quot;lifespan&quot;, &quot;com.tyrell.nexussix&quot;)) # sometimes None, sometimes 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yet if we look with the defaults command, everything seems fine:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;# &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;defaults read /Library/Preferences/com.tyrell.nexussix&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;{
    lifespan = 4;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To make things even more confusing, CFPreferences suddenly sees the value now. To untangle this mess, let’s investigate what happens in our postinstall script when we’re installing the package on the current system, with &lt;code class=&quot;highlighter-rouge&quot;&gt;$3&lt;/code&gt; expanded to &lt;code class=&quot;highlighter-rouge&quot;&gt;/&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;# &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;defaults write //Library/Preferences/com.tyrell.nexussix lifespan -int 4&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;# &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;defaults write /Library/Preferences/com.tyrell.nexusseven lifespan -int 4&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;# &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;ls -lf /Library/Preferences/com.tyrell.nexus*&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;-rw-------  1 root  wheel  57 30 Jan 12:38 /Library/Preferences/com.tyrell.nexussix.plist
-rw-r--r--  1 root  wheel  57 30 Jan 12:38 /Library/Preferences/com.tyrell.nexusseven.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The extra slash causes &lt;code class=&quot;highlighter-rouge&quot;&gt;defaults&lt;/code&gt; to make the preference file readable only by root, making it sometimes visible through &lt;code class=&quot;highlighter-rouge&quot;&gt;cfprefsd&lt;/code&gt;, depending on access permissions and caching. My guess is the slash triggers &lt;code class=&quot;highlighter-rouge&quot;&gt;defaults&lt;/code&gt;’ codepath for writing to user libraries, where preference files shouldn’t be readable by other users.&lt;/p&gt;

&lt;p&gt;So how should we be writing our postinstall scripts? I’m glad you asked. I’ve been using the following in my scripts:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-sh&quot;&gt;#!/bin/bash

if [[ &quot;$3&quot; == &quot;/&quot; ]]; then
    TARGET=&quot;&quot;
else
    TARGET=&quot;$3&quot;
fi

defaults write &quot;$TARGET/Library/Preferences/com.tyrell.nexussix&quot; lifespan -int 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what happens if you install this package on a system image with AutoDMG? Well the pref plist will only be readable by root, but as far as I can tell apps can still access their preference keys, presumably since &lt;code class=&quot;highlighter-rouge&quot;&gt;cfprefsd&lt;/code&gt; caches everything when the system boots — at least I haven’t been able to reproduce the problem this way.&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/MagerValp/CreateUserPkg/pull/52&quot;&gt;https://github.com/MagerValp/CreateUserPkg/pull/52&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/munkireport/munkireport-php/pull/949&quot;&gt;https://github.com/munkireport/munkireport-php/pull/949&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.8</title>
   <link href="http://magervalp.github.io/2017/09/26/autodmg-1.8.html"/>
   <updated>2017-09-26T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2017/09/26/autodmg-1.8</id>
   <content type="html">&lt;p&gt;10.13 was released yesterday, and today I’m releasing the final build of AutoDMG 1.8 with full support for building both APFS and HFS+ images. Apple has made a lot of breaking changes in this cycle, to the point where we haven’t been able to get 100% support for 10.13 on launch day in my organization. As a result I’ve had to bump a few outstanding AutoDMG issues to the next release, but they mainly concern usability and shouldn’t stop anyone from using 1.8.&lt;/p&gt;

&lt;p&gt;This release also means that 10.9 support is dropped, and 10.10 is marked as deprecated. AutoDMG will launch and you can build 10.10 images, but there are no new updates from Apple.&lt;/p&gt;

&lt;p&gt;Full changelog:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added 10.13 and APFS support.&lt;/li&gt;
  &lt;li&gt;Added APFS/HFS+ selection to the Advanced Options window.&lt;/li&gt;
  &lt;li&gt;Added &lt;code class=&quot;highlighter-rouge&quot;&gt;-F&lt;/code&gt;/&lt;code class=&quot;highlighter-rouge&quot;&gt;--filesystem&lt;/code&gt; option to CLI.&lt;/li&gt;
  &lt;li&gt;Added &lt;code class=&quot;highlighter-rouge&quot;&gt;Filesystem&lt;/code&gt; option to templates.&lt;/li&gt;
  &lt;li&gt;Removed 10.9 support.&lt;/li&gt;
  &lt;li&gt;Fixed crash when CLI build can’t eject image.&lt;/li&gt;
  &lt;li&gt;Fixed crash when unchecking updates without a source.&lt;/li&gt;
  &lt;li&gt;Fixed Unicode handling of paths for additional packages.&lt;/li&gt;
  &lt;li&gt;Slightly improved app launch time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll find the download on the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.7.3</title>
   <link href="http://magervalp.github.io/2016/12/19/autodmg-v1.7.3.html"/>
   <updated>2016-12-19T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2016/12/19/autodmg-v1.7.3</id>
   <content type="html">&lt;p&gt;This week I’ve rounded up some bugfixes together with a few minor new features. First off, after a successful build you’ll find a few machine parsable statements in the log, to help people who automate builds. You’ll also see a warning if the build number changes, as it does these days when you install a security update:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;15 december 2016 11:35:55 GMT−5  Build success: OUTPUT_PATH='/Users/Shared/osx_updated_161216-10.11.6-15G31.hfs.dmg'
15 december 2016 11:35:55 GMT−5  Build success: OUTPUT_OSNAME='Mac OS X'
15 december 2016 11:35:55 GMT−5  Build success: OUTPUT_OSVERSION='10.11.6'
15 december 2016 11:35:55 GMT−5  Build success: OUTPUT_OSBUILD='15G1212'
15 december 2016 11:35:55 GMT−5  Build success: Notice: OS version changed from Mac OS X 10.11.6 15G31 to Mac OS X 10.11.6 15G1212
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Secondly I’ve added a deprecation warning if you’re building an OS that is no longer supported by Apple, as is the case now with 10.9. This also means that I will remove support for it in AutoDMG in the not too distant future, most likely in the next major release.&lt;/p&gt;

&lt;p&gt;Full changelog:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Display warning if Apple has stopped updating the target OS.&lt;/li&gt;
  &lt;li&gt;Only update the profile if the running OS is supported.&lt;/li&gt;
  &lt;li&gt;Handle already mounted &lt;code class=&quot;highlighter-rouge&quot;&gt;InstallESD.dmg&lt;/code&gt; if installer app was moved afterwards.&lt;/li&gt;
  &lt;li&gt;Abort the build if disk image creation fails.&lt;/li&gt;
  &lt;li&gt;Print warning in log when build number changes during install.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll find the download on the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.7.2</title>
   <link href="http://magervalp.github.io/2016/12/19/autodmg-v1.7.2.html"/>
   <updated>2016-12-19T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2016/12/19/autodmg-v1.7.2</id>
   <content type="html">&lt;p&gt;1.7.2 was pulled due to a crash on startup for new users, please use &lt;a href=&quot;autodmg-v1.7.3&quot;&gt;1.7.3&lt;/a&gt; instead.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.7.1</title>
   <link href="http://magervalp.github.io/2016/12/08/autodmg-v1.7.1.html"/>
   <updated>2016-12-08T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2016/12/08/autodmg-v1.7.1</id>
   <content type="html">&lt;p&gt;Hot on the heels of last week’s release, here’s AutoDMG 1.7.1 where I’ve focused on polish and bugfixing. This release brings the list of open issues down to zero, which feels really good! Unfortunately that also meant closing a few older feature requests that I wanted to implement, but when push came to shove if there’s a simple one-line workaround in the Terminal, it’s hard to motivate spending half a day on implementation and regression testing. Here’s what did make the cut:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Now displays the current OS name and placeholder icon.&lt;/li&gt;
  &lt;li&gt;New menu item to select an installer, &lt;code class=&quot;highlighter-rouge&quot;&gt;⌘I&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;⌘⌥I&lt;/code&gt; will pick the first installer it finds in &lt;code class=&quot;highlighter-rouge&quot;&gt;/Applications&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Log window wraps long lines and shows colorful warnings.&lt;/li&gt;
  &lt;li&gt;Preserve &lt;code class=&quot;highlighter-rouge&quot;&gt;TMPDIR&lt;/code&gt; when running CLI builds without &lt;code class=&quot;highlighter-rouge&quot;&gt;sudo&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Better error handling when ejecting the temporary build image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll find the download on the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CreateUserPkg is up for adoption</title>
   <link href="http://magervalp.github.io/2016/12/07/createuserpkg-up-for-adoption.html"/>
   <updated>2016-12-07T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2016/12/07/createuserpkg-up-for-adoption</id>
   <content type="html">&lt;figure&gt;
    &lt;a href=&quot;/images/se-tripel.jpg&quot;&gt;&lt;img src=&quot;/images/se-tripel.jpg&quot; alt=&quot;SE Tripel&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;As some of you might know, I’ve been on a leave of absence this autumn, and I’ve basically been fortunate enough to have the days to myself. I’ve spent most of it on bike rides around Columbus, playing around with the laser cutter at the &lt;a href=&quot;http://www.columbusideafoundry.com/&quot;&gt;Columbus Idea Foundry&lt;/a&gt;, or preparing for the talk I gave at &lt;a href=&quot;https://github.com/MagerValp/MacTech-2016&quot;&gt;MacTech&lt;/a&gt;, but over these last couple of weeks I’ve been catching up on some of my open source projects.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/CreateUserPkg-icon.png&quot; alt=&quot;CreateUserPkg icon&quot; style=&quot;float:right; margin-left: 0.5em; width: 9ex;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Even with all this copious free time, I’ve had to realize that I have more projects than I have time for, and when January comes around I’ll be back to working full time again. The project that is in the most dire need of an overhaul is &lt;a href=&quot;https://itunes.apple.com/us/app/createuserpkg/id540673598?mt=12&quot;&gt;CreateUserPkg&lt;/a&gt;. It was one of my first Cocoa projects, where I learned how to do document based apps, sandboxing, and how to publish in the App Store. I had to resort to some &lt;a href=&quot;https://github.com/MagerValp/CreateUserPkg/blob/ce3d3039927b1eb597a7f8f8cd4632df250e343f/CreateUserPkg/create_package.py#L108-L160&quot;&gt;really crazy antics&lt;/a&gt; to generate packages without requiring root. Good times. But that was then, this is now, and a lot has changed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;macOS ships with &lt;a href=&quot;https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/pkgbuild.1.html&quot;&gt;pkgbuild&lt;/a&gt; and &lt;a href=&quot;https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/productbuild.1.html&quot;&gt;productbuild&lt;/a&gt;, replacing the need for most of the horror show in &lt;a href=&quot;https://github.com/MagerValp/CreateUserPkg/blob/ce3d3039927b1eb597a7f8f8cd4632df250e343f/CreateUserPkg/create_package.py&quot;&gt;create_package.py&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;10.5/10.6 support is no longer needed, so the &lt;a href=&quot;https://github.com/MagerValp/CreateUserPkg#security-notes&quot;&gt;SHA1 shadow hash&lt;/a&gt; needs to be eliminated in favor of &lt;a href=&quot;https://en.wikipedia.org/wiki/PBKDF2&quot;&gt;PBKDF2&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;.pkg&lt;/code&gt; as the document type was just a bad design desicion, I should have made a separate document format and then exported to &lt;code class=&quot;highlighter-rouge&quot;&gt;.pkg&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.apple.com/profilemanager/mac/5.2/#/apdA38473F4-C7B3-4BCC-B80D-E6F0220E8CD0&quot;&gt;MDM payloads can create users&lt;/a&gt;, maybe we should be generating those instead?&lt;/li&gt;
  &lt;li&gt;The app desperately needs a better name too. I’ve always been bad at naming things. Fortunately Greg saved my bacon with &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/blob/master/AutoDMG/en.lproj/Credits.rtf&quot;&gt;AutoDMG&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of it all the project is small enough that it’s &lt;em&gt;begging&lt;/em&gt; for a Swift rewrite. But not by me. If you’re looking for an excuse to get into Cocoa development, here’s a great opportunity. There are &lt;a href=&quot;https://github.com/MagerValp/CreateUserPkg/issues&quot;&gt;a dozen suggested enhancements&lt;/a&gt; on GitHub you want to go further.&lt;/p&gt;

&lt;p&gt;So please, &lt;a href=&quot;https://github.com/MagerValp/CreateUserPkg&quot;&gt;fork the repo&lt;/a&gt;, or maybe just start over from a clean slate. The Apache license means that you can basically do what you want with the code. The only thing I request is that you give your app a better name.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.7</title>
   <link href="http://magervalp.github.io/2016/12/01/autodmg-v1.7.html"/>
   <updated>2016-12-01T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2016/12/01/autodmg-v1.7</id>
   <content type="html">&lt;p&gt;I was planning a small bugfix release, but I felt that the changes were large enough for a major version bump. The AppleScript trampoline that I used to kick off the privileged OS install task has been replaced by the much nicer &lt;a href=&quot;https://github.com/sveinbjornt/STPrivilegedTask&quot;&gt;STPrivilegedTask&lt;/a&gt;. If you have automation set up to run AutoDMG, please test this release carefully.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Rewrote launch code for the privileged task that runs the OS installer.&lt;/li&gt;
  &lt;li&gt;Fixed beachballing during finalize task.&lt;/li&gt;
  &lt;li&gt;Fixed language detection for Setup Assistant on 10.12.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll find the download on the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.6</title>
   <link href="http://magervalp.github.io/2016/09/19/autodmg-v1.6.html"/>
   <updated>2016-09-19T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2016/09/19/autodmg-v1.6</id>
   <content type="html">&lt;p&gt;Just in time for macOS Sierra we have AutoDMG 1.6:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added 10.12 support.&lt;/li&gt;
  &lt;li&gt;Removed 10.8 support.&lt;/li&gt;
  &lt;li&gt;AutoDMG will not try to remount already mounted images, fixing 10.12 installer.&lt;/li&gt;
  &lt;li&gt;Added advanced option to skip asr imagescan (thanks @timsutton).&lt;/li&gt;
  &lt;li&gt;AutoDMG will not relaunch on login (thanks @nmcspadden).&lt;/li&gt;
  &lt;li&gt;Fixed volume size setting not being saved to templates (thanks @timsutton).&lt;/li&gt;
  &lt;li&gt;Fixed handling of relative package paths on the command line (thanks @timsutton).&lt;/li&gt;
  &lt;li&gt;Fixed usage of base image as source on the command line (thanks @timsutton).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.6 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.5.5</title>
   <link href="http://magervalp.github.io/2016/01/22/autodmg-v1.5.5.html"/>
   <updated>2016-01-22T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2016/01/22/autodmg-v1.5.5</id>
   <content type="html">&lt;p&gt;I released AutoDMG 1.5.5 with a few bug fixes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Respect &lt;code class=&quot;highlighter-rouge&quot;&gt;TMPDIR&lt;/code&gt; when building images on 10.9+.&lt;/li&gt;
  &lt;li&gt;Avoid occasional error messages on program exit.&lt;/li&gt;
  &lt;li&gt;Fixed handling of packages where size can’t be calculated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.5.5 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.5.4</title>
   <link href="http://magervalp.github.io/2015/11/27/autodmg-v1.5.4.html"/>
   <updated>2015-11-27T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/11/27/autodmg-v1.5.4</id>
   <content type="html">&lt;p&gt;Some of the changes I’ve planned for AutoDMG 1.6 are taking way too long, so after some gentle nudging I rolled up the latest bug fixes into a 1.5.4 release:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added &lt;code class=&quot;highlighter-rouge&quot;&gt;⌘B&lt;/code&gt; keyboard shortcut to build (thanks @zuhl).&lt;/li&gt;
  &lt;li&gt;Added &lt;code class=&quot;highlighter-rouge&quot;&gt;-s&lt;/code&gt;/&lt;code class=&quot;highlighter-rouge&quot;&gt;--size&lt;/code&gt; option to CLI (thanks @timsutton).&lt;/li&gt;
  &lt;li&gt;Fixed error handling of bad Additional Packages paths.&lt;/li&gt;
  &lt;li&gt;Display confirmation dialog when updating profiles.&lt;/li&gt;
  &lt;li&gt;Disable profile update checking while images build.&lt;/li&gt;
  &lt;li&gt;Fixed handling of large error messages from the build script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.5.4 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have questions or need help, you can join us in &lt;a href=&quot;https://macadmins.slack.com/archives/autodmg&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;#autodmg&lt;/code&gt;&lt;/a&gt; on &lt;a href=&quot;http://macadmins.org&quot;&gt;Slack MacAdmins&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDSNBI 1.1</title>
   <link href="http://magervalp.github.io/2015/11/03/autodsnbi-1.1.html"/>
   <updated>2015-11-03T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/11/03/autodsnbi-1.1</id>
   <content type="html">&lt;p&gt;I updated AutoDSNBI to support DeployStudio 1.6.17. Big thanks to Rich Trouton for pointing out the new sysbuilder script. Download 1.1 from the new repo here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/MagerValp/AutoDSNBI&quot;&gt;AutoDSNBI 1.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>System Center 2012 Endpoint Protection + Outlook 2011 = Crash</title>
   <link href="http://magervalp.github.io/2015/08/17/scep-outlook-crash.html"/>
   <updated>2015-08-17T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/08/17/scep-outlook-crash</id>
   <content type="html">&lt;p&gt;Starting in July we’ve had a steady trickle of support cases regarding Outlook 2011 crashing on startup:&lt;/p&gt;

&lt;pre class=&quot;out&quot;&gt;
Microsoft Error Reporting log version: 2.0

Error Signature:
Exception: EXC_BAD_ACCESS
Date/Time: 2015-08-11 11:38:17 +0000
Application Name: Microsoft Database Daemon
Application Bundle ID: com.microsoft.outlook.databasedaemon
Application Signature: MDlr
Application Version: 14.5.3.150624
Crashed Module Name: libobjc.A.dylib
Crashed Module Version: unknown
Crashed Module Offset: 0x000010a7
Blame Module Name: Microsoft Database Daemon
Blame Module Version: 14.5.3.150624
Blame Module Offset: 0x000c1368
Application LCID: 1053
Extra app info: Reg=en Loc=0x041d
Crashed thread: 0
&lt;/pre&gt;

&lt;p&gt;We tried the usual incantations — rebuilding the database, creating a fresh identity, nuking prefs, and so on — but nothing offered more than temporary respite. Only creating a fresh home directory seemed to help, but that’s a classic example of the cure being worse than the disease.&lt;/p&gt;

&lt;p&gt;We’re fortunate enough to have a Microsoft Premier Support contract so after banging our heads against the wall for a few days we decided to call it in. Impressively they managed to track down the issue in less than 24 hours. It turns out that a recent-ish update to System Center 2012 Endpoint Protection accidentally changes the ownership of &lt;code class=&quot;highlighter-rouge&quot;&gt;~/Library/Preferences/loginwindow.plist&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;root:wheel&lt;/code&gt;. Through a series of &lt;a href=&quot;https://www.youtube.com/watch?v=qybUFnY7Y8w&quot;&gt;Rube Goldberg&lt;/a&gt;-like events this then causes Outlook’s database daemon to crash on startup.&lt;/p&gt;

&lt;p&gt;Restoring ownership magically makes the crash go away, so we sent out the following script to all our macs:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-sh&quot;&gt;#!/bin/bash

# Restore ownership of user preference files.
for preffolder in /Users/*/Library/Preferences; do
    if [[ -d &quot;$preffolder&quot; ]]; then
        uidgid=$(stat -f &quot;%u:%g&quot; &quot;$preffolder&quot;)
        chown -hR &quot;$uidgid&quot; &quot;$preffolder&quot;
    fi
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I think SCEP is just a rebranded &lt;a href=&quot;http://www.eset.com/us/home/products/cyber-security/&quot;&gt;ESET/NOD32&lt;/a&gt;, so chances are that the same problem can affect clients running that too.&lt;/p&gt;

&lt;p&gt;I haven’t been able to reproduce the issue by just changing loginwindow’s ownership on a non-crashy Outlook, so something else is also playing a part here, but at least it fixes the cases that have been brought it. Don’t hesitate contact me if you can shed more light on it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ultima IV Remastered v2.2.1</title>
   <link href="http://magervalp.github.io/2015/05/29/u4-remastered-v2.2.1.html"/>
   <updated>2015-05-29T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/05/29/u4-remastered-v2.2.1</id>
   <content type="html">&lt;figure&gt;
    &lt;a href=&quot;/images/u4-intro-5.png&quot;&gt;&lt;img src=&quot;/images/u4-intro-5.png&quot; alt=&quot;Ultima IV Remastered&quot; style=&quot;border: 1px solid #444;&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;I apparently managed to screw up the end game graphics while preparing the 2.2 release, which &lt;a href=&quot;http://csdb.dk/scener/?id=8378&quot;&gt;Trurl&lt;/a&gt; brought to my attention. Sorry folks!&lt;/p&gt;

&lt;h2 id=&quot;whats-new-in-v221&quot;&gt;What’s New in v2.2.1&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/u4-magincia.png&quot; alt=&quot;Outside Magincia&quot; style=&quot;float:right; margin-left: 1em;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fixed graphics corruption and potential crash during ending.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For older changes see the full &lt;a href=&quot;https://raw.githubusercontent.com/MagerValp/u4remastered/master/Changelog.txt&quot;&gt;changelog&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;download--source-code&quot;&gt;Download &amp;amp; Source Code&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;You can download the game from its CSDb entry: &lt;a href=&quot;http://csdb.dk/release/index.php?id=138772&quot;&gt;Ultima IV Remastered v2.2.1&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The source code is available &lt;a href=&quot;https://github.com/MagerValp/u4remastered&quot;&gt;on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Ultima IV Remastered v2.2</title>
   <link href="http://magervalp.github.io/2015/04/22/u4-remastered-v2.2.html"/>
   <updated>2015-04-22T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/04/22/u4-remastered-v2.2</id>
   <content type="html">&lt;figure&gt;
    &lt;a href=&quot;/images/u4-intro-3.png&quot;&gt;&lt;img src=&quot;/images/u4-intro-3.png&quot; alt=&quot;Ultima IV Remastered&quot; style=&quot;border: 1px solid #444;&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;A few more bugs &lt;a href=&quot;http://www.lemon64.com/forum/viewtopic.php?p=670851#670851&quot;&gt;were reported&lt;/a&gt; (thank you!), and I really wanted to get my list of known bugs down to zero. Unless people discover even more bugs this is likely to be the final release.&lt;/p&gt;

&lt;h2 id=&quot;atari--apple-ii-ports&quot;&gt;Atari &amp;amp; Apple II ports&lt;/h2&gt;

&lt;p&gt;Users from the other 6502 platforms have also shown some interest in remastered versions. I don’t have any contacts in the Apple or Atari cracking scene, so I thought I’d put a note in here. If you’re interested let me know and I can help you navigate the project.&lt;/p&gt;

&lt;h2 id=&quot;whats-new-in-v22&quot;&gt;What’s New in v2.2&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/u4-magincia.png&quot; alt=&quot;Outside Magincia&quot; style=&quot;float:right; margin-left: 1em;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The game no longer hangs when playing the 1541 version and answering questions wrong in the codex.&lt;/li&gt;
  &lt;li&gt;Attacking static NPCs such as Ankhs, castle lords &amp;amp; ladies, the water in Castle Britannia, or the camp fire in Yew no longer leads to a glitching enemy in combat. Attacking chests dropped by townespeople is no longer possible.&lt;/li&gt;
  &lt;li&gt;Fixed stack handling for main menu, when being attacked by monsters, when dying, and the end game. This hopefully eliminates any crashes to the ready prompt.&lt;/li&gt;
  &lt;li&gt;The avoid combat trainer now works in dungeons too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For older changes see the full &lt;a href=&quot;https://raw.githubusercontent.com/MagerValp/u4remastered/master/Changelog.txt&quot;&gt;changelog&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;download--source-code&quot;&gt;Download &amp;amp; Source Code&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;You can download the game from its CSDb entry: &lt;a href=&quot;http://csdb.dk/release/index.php?id=138772&quot;&gt;Ultima IV Remastered v2.2.1&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The source code is available &lt;a href=&quot;https://github.com/MagerValp/u4remastered&quot;&gt;on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/u4-cards.png&quot; alt=&quot;Ultima IV Remastered&quot; /&gt;
&lt;/figure&gt;
</content>
 </entry>
 
 <entry>
   <title>Ultima IV Remastered on GitHub</title>
   <link href="http://magervalp.github.io/2015/04/12/u4-remastered-on-github.html"/>
   <updated>2015-04-12T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/04/12/u4-remastered-on-github</id>
   <content type="html">&lt;p&gt;One of the primary reasons for getting back into Ultima IV was that I wanted to clean up my old Ultima IV Gold sources. Remastering was the result of sliding down that slippery slope of just fixing one more thing.&lt;/p&gt;

&lt;p&gt;The restarted project was born out of nice, clean, structured source but when crunch time came ideals were abanonded and compromises were made. Sadly the project isn’t in as nice a shape as I’d like and there are some nasty gotchas in there, but if I don’t release it now I risk having the project rot away in my private repo again, and bringing us back to square one. You can check out the source, warts and all, from &lt;a href=&quot;https://github.com/MagerValp/u4remastered&quot;&gt;u4remastered on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For C64 programmers there are some reusable parts like the IFFL and EasyFlash loaders and LZMV compression (of which I have more, in the repo is just the pack tool and the stream decruncher).&lt;/p&gt;

&lt;p&gt;My work should also be portable to the Apple II and Atari versions if anyone is up for it, and the dialogue fixes should be adaptable to the DOS/Amiga/ST versions as well.&lt;/p&gt;

&lt;p&gt;Finally, for the curious I’ll be keeping continued bugfixing and development on GitHub if you want to follow along. I’ll start moving my todo list into the project’s &lt;a href=&quot;https://github.com/MagerValp/u4remastered/issues&quot;&gt;issue tracker&lt;/a&gt; later today.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ultima IV Dialogue</title>
   <link href="http://magervalp.github.io/2015/04/10/u4-talk.html"/>
   <updated>2015-04-10T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/04/10/u4-talk</id>
   <content type="html">&lt;p&gt;One step on the road to &lt;a href=&quot;/2015/03/30/u4-remastered.html&quot;&gt;remastering Ultima IV&lt;/a&gt; was extracting all dialogue from various ports and looking at the differences. I have published the json dumps, my tools, a comparision, and a full changelog &lt;a href=&quot;https://github.com/MagerValp/u4talk&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ultima IV Remastered v2.1</title>
   <link href="http://magervalp.github.io/2015/04/09/u4-remastered-v2.1.html"/>
   <updated>2015-04-09T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/04/09/u4-remastered-v2.1</id>
   <content type="html">&lt;figure&gt;
    &lt;a href=&quot;/images/u4-remastered-trinity-large.png&quot;&gt;&lt;img src=&quot;/images/u4-remastered-trinity-large.png&quot; alt=&quot;Ultima IV Remastered&quot; /&gt;&lt;/a&gt;
    &lt;h1&gt;Ultima IV Remastered v2.1&lt;/h1&gt;
&lt;/figure&gt;

&lt;p&gt;I had a deadline set for the release of Ultima IV Remastered, which really helped me finish the project. Unfortunately it also meant that I had to release it with a few known bugs, and, as it turns out, a few unknown bugs too.&lt;/p&gt;

&lt;p&gt;A big thank you to all who sent me bug reports and posted feedback, keep it coming!&lt;/p&gt;

&lt;h2 id=&quot;whats-new-in-v21&quot;&gt;What’s New in v2.1&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Saving to EasyFlash cartridges that don’t use Am29F040 chips (including Chameleon) now works.&lt;/li&gt;
  &lt;li&gt;Exit solo mode if character leaves combat.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2015/04/02/u4-dungeon-frigate.html&quot;&gt;Don’t spawn a ship&lt;/a&gt; when pressing B while standing on a ladder in a dungeon.&lt;/li&gt;
  &lt;li&gt;Joshua courage -&amp;gt; canrage typo.&lt;/li&gt;
  &lt;li&gt;Fixed east/west start positions in Destard rooms on level 8.&lt;/li&gt;
  &lt;li&gt;Removed glitch when attacking sick people in townes.&lt;/li&gt;
  &lt;li&gt;Play correct music after dying and being resurrected by Lord British.&lt;/li&gt;
  &lt;li&gt;Fixed wind status after loading a game in a dungeon and then exiting.&lt;/li&gt;
  &lt;li&gt;Clarified the recommendation for emulator users when flipping d64s.&lt;/li&gt;
  &lt;li&gt;Proper error message in editor if no savegame is found in cartridge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;download&quot;&gt;Download&lt;/h2&gt;

&lt;p&gt;You can download the game from its CSDb entry: &lt;a href=&quot;http://csdb.dk/release/index.php?id=138772&quot;&gt;Ultima IV Remastered v2.2.1&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;known-bugs&quot;&gt;Known Bugs&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;If you’re playing the 1541 version and answer a question wrong during the ending the game is supposed to throw you out to Britannia, but instead it hangs. Play the 1571, 1581, or EasyFlash version instead to avoid this issue, or just make sure you get all the answers right.&lt;/li&gt;
  &lt;li&gt;The crack intro is out of sync and glitches a bit on NTSC, but should otherwise work fine.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Ultima IV Dungeon Ladder Frigates</title>
   <link href="http://magervalp.github.io/2015/04/02/u4-dungeon-frigate.html"/>
   <updated>2015-04-02T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/04/02/u4-dungeon-frigate</id>
   <content type="html">&lt;p&gt;I released &lt;a href=&quot;http://magervalp.github.io/2015/03/30/u4-remastered.html&quot;&gt;Ultima IV Remastered&lt;/a&gt; to great fanfare last weekend and it warms my heart to hear that you’re all enjoying it. I just received a bug report though that I thought was neat enough to share. As &lt;a href=&quot;http://www.lemon64.com/forum/viewtopic.php?p=669455#669455&quot;&gt;Codetsu reported on Lemon64&lt;/a&gt; if you press the B key while standing by a ladder going up in a dungeon, the game rather unexpectedly responds with “Board frigate!” (screenshot from the original Ultima IV port):&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-dungeon-board-bug-dungeon.png&quot;&gt;&lt;img src=&quot;/images/u4-dungeon-board-bug-dungeon.png&quot; alt=&quot;Ultima IV pressing B in dungeon&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;I don't see a frigate. Do you see a frigate?&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The game continues to play normally but you get a nasty surprise as you exit the dungeon:&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-dungeon-board-bug-surface.png&quot;&gt;&lt;img src=&quot;/images/u4-dungeon-board-bug-surface.png&quot; alt=&quot;Ultima IV exiting dungeon after boarding frigate&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;Oh &lt;em&gt;there&lt;/em&gt; it is!&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;You can exit the ship and walk away from the dungeon, but reentering is impossible until you move far enough away (roughly 30 steps, or use the teleport cheat) that the game’s object buffer is cleared for that part of the map. Unless you’re exiting Covetous, in which case you can just sail off since there is water right next to the dungeon entrance - a fairly handy way to spawn a ship in the original game with no cheats. But I digress.&lt;/p&gt;

&lt;p&gt;What’s really happening here though? Let’s look at the game’s code. The &lt;a href=&quot;https://gist.github.com/MagerValp/fcf47ebe597af1a3424a&quot;&gt;raw disassembly&lt;/a&gt; is a little tough to read so I’ve added labels:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;; Disassembly starting at $4769:

cmd_board:
	lda player_transport        ; This is $00, so we branch to @onfoot.
	cmp #$1f
	beq @onfoot
	jsr j_primm
	.byte &quot;Board &amp;lt;-&quot;, $00

	jmp print_cant

@onfoot:
	lda tile_under_player       ; If the player is next to a ladder going up
	cmp #$14                    ; the current tile is $10.
	beq board_horse
	cmp #$15
	beq board_horse
	jsr j_primm                 ; It's not a horse so the game prints &quot;Board &quot;.
	.byte &quot;Board &quot;, $00

	lda tile_under_player
	cmp #$10                    ; As it happens the ladder up dungeon tile is
	beq @ship                   ; the same as a ship facing left on the
	cmp #$11                    ; surface, $10, so we branch to @ship.
	beq @ship
	cmp #$12
	beq @ship
	cmp #$13
	beq @ship
	cmp #$18
	bne @unknown
	jmp board_balloon

@unknown:
	jmp cmd_unknown

@ship:
	lda #$10                    ; Now it tries to remove $10 from the object
	jsr board_find_object       ; table. No object is found, but the current
	jsr j_primm                 ; player_transport is still set to $10 by
	.byte &quot;frigate!&quot;, $8d       ; board_find_object (see below).
	.byte $00

	lda player_xpos             ; A new ship is spawned facing left at the
	cmp player_ship_xpos        ; player's current surface coordinate.
	bne @newship
	lda player_ypos
	cmp player_ship_ypos
	bne @newship
	jmp cmd_done

@newship:
	lda #$50
	sta ship_hull
	jmp cmd_done


; Disassembly starting at $480b:

board_find_object:
	sta board_object_id
	ldx #$1f
@checkobject:
	lda object_tile,x           ; The object_tile table doesn't contain any
	and #$fc                    ; ships, so this compare will always fail.
	cmp board_object_id
	bne @next
	lda object_xpos,x
	cmp player_xpos
	bne @next
	lda object_ypos,x
	cmp player_ypos
	beq @foundobject
@next:
	dex
	cpx #$08
	bcs @checkobject
	bcc @noobject
@foundobject:
	lda #$00
	sta object_tile,x
	sta map_status,x
@noobject:
	lda tile_under_player       ; After exhausting the table it ends up here,
	sta player_transport        ; where it still updates player_transport to
	rts                         ; whatever is on the map under the player.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What’s the actual bug here? IMHO the game shouldn’t assume that just because the player is on foot, it could board something — it also needs to check that the player is on the surface. The cleanest way to do so would be at the very beginning, but when you insert a binary patch you don’t want to add or remove any bytes to the program, as that breaks everything coming afterwards. It’s best if we can find a jmp or jsr that can be changed to point to a patched routine. Following the code we see that no game state is being changed before it jumps to the &lt;code class=&quot;highlighter-rouge&quot;&gt;board_find_object&lt;/code&gt; subroutine, so let’s redirect that:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;patch_board_dungeon:
	.byte 2                     ; Patch two bytes.
	.addr $47b1                 ; Address to patch.
	.addr board_ship_check      ; The new vector.
	.byte 0                     ; End of patch.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’ve added a short routine to the game’s startup that takes a table with patches such as this, making it relatively painless to modify the game without having to recreate the whole source. Now we can insert a small stub with a surface check:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;board_ship_check:
	lda current_location        ; Location $00 is Britannia surface.
	beq @in_britannia           ; If zero, continue as normal.

	pla                         ; Otherwise we pop the jsr return address and
	pla                         ; jump to printing &quot;what?&quot;, just as if no
	jmp cmd_unknown             ; object was found.

@in_britannia:
	jmp board_find_object&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s compile the project and see how this plays out:&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-dungeon-board-bug-fixed.png&quot;&gt;&lt;img src=&quot;/images/u4-dungeon-board-bug-fixed.png&quot; alt=&quot;Error message when trying to board in a dungeon&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;No more phantom ships hanging around dungeon ladders.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;With that bug squashed and the code commited to a new bugfix branch it’s time for regression testing. Since we just changed the code for the board command, let’s make sure we didn’t add any new board related bugs. Pop up to the surface, spawn a horse, a ship, and a ballon, and try to board them.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-dungeon-board-bug-regression.png&quot;&gt;&lt;img src=&quot;/images/u4-dungeon-board-bug-regression.png&quot; alt=&quot;Two ships regression&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;I only spawned one ship, so why are there two?&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Boarding a ship and sailing away leaves another copy of the ship on the map. With larger changes hunting down regressions can be a pretty daunting task, but with a change this small it’s bound to be something stupid. And it is: when &lt;code class=&quot;highlighter-rouge&quot;&gt;board_find_object&lt;/code&gt; is called, the object to find is in the A register, but the first thing we do in our patch is clobbering A with &lt;code class=&quot;highlighter-rouge&quot;&gt;current_location&lt;/code&gt;. Let’s change it to X which isn’t used when calling &lt;code class=&quot;highlighter-rouge&quot;&gt;board_find_object&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;board_ship_check:
	ldx current_location        ; Location $00 is Britannia surface.
	beq @in_britannia           ; If zero, continue as normal.

	pla                         ; Otherwise we pop the jsr return address and
	pla                         ; jump to printing &quot;what?&quot;, just as if no
	jmp cmd_unknown             ; object was found.

@in_britannia:
	jmp board_find_object&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Compile, re-test, and this time there are no obvious regressions:&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-dungeon-board-bug-final.png&quot;&gt;&lt;img src=&quot;/images/u4-dungeon-board-bug-final.png&quot; alt=&quot;Board working correctly&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;With a game the size of Ultima IV there are dozens of little bugs like this that weren’t caught before release. To the best of my knowledge there were no tools for testing 6502 code in 1985 and even revision control systems were rare, so it’s impressive that there aren’t more of them. Not counting conversation bugs this is the seventh bug I’ve fixed, and out of them only the shrine bug has any real effect on the game — even so it’s fairly minor and was patched in a later update.&lt;/p&gt;

&lt;p&gt;Anyway, the branch is merged and the fix will be included in the next update of Ultima IV Remastered. Let me know if you find any other bugs!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ultima IV Remastered</title>
   <link href="http://magervalp.github.io/2015/03/30/u4-remastered.html"/>
   <updated>2015-03-30T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/03/30/u4-remastered</id>
   <content type="html">&lt;p&gt;I’m proud to announce that my remastered port of Ultima IV for the C64 has been released.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-remastered-trinity-large.png&quot;&gt;&lt;img src=&quot;/images/u4-remastered-trinity-large.png&quot; alt=&quot;Ultima IV Remastered&quot; /&gt;&lt;/a&gt;
    &lt;h1&gt;Ultima IV Remastered for the C64&lt;/h1&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;download&quot;&gt;Download&lt;/h2&gt;

&lt;p&gt;You can download the game from its CSDb entry: &lt;a href=&quot;http://csdb.dk/release/index.php?id=138772&quot;&gt;Ultima IV Remastered v2.2.1&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;documentation&quot;&gt;Documentation&lt;/h2&gt;

&lt;p&gt;Scanned documentation can be found here: &lt;a href=&quot;https://paradroid.automac.se/u4/docs.html&quot;&gt;Ultima IV Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;screenshots&quot;&gt;Screenshots&lt;/h2&gt;

&lt;p&gt;You can download screenshots of U4 Remastered and the original for comparison here: &lt;a href=&quot;/data/u4screenshots.zip&quot;&gt;Ultima IV Remastered screenshots&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;source-code&quot;&gt;Source Code&lt;/h2&gt;

&lt;p&gt;The source code is available &lt;a href=&quot;/2015/04/12/u4-remastered-on-github.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;game-changes&quot;&gt;Game Changes&lt;/h2&gt;

&lt;h3 id=&quot;graphics-overhaul&quot;&gt;Graphics Overhaul&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Character creation intro has new graphics drawn by Vanja ‘Mermaid’ Utne.&lt;/li&gt;
  &lt;li&gt;The tileset has been updated with new and more colorful tiles, mainly backported from Ultima V.&lt;/li&gt;
  &lt;li&gt;When peering at a gem or casting view the map is now in color.&lt;/li&gt;
  &lt;li&gt;The dungeon renderer has been sped up, and items and monsters are drawn in color.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;text-overhaul&quot;&gt;Text Overhaul&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;NPC dialogue and game text now uses mixed case.&lt;/li&gt;
  &lt;li&gt;Many dialogue bugs have been fixed:
    &lt;ul&gt;
      &lt;li&gt;Fixed broken question trigger and added missing dialogue for Thevel in Britain.&lt;/li&gt;
      &lt;li&gt;Added missing dialogue for Serpent’s Hold gate guards.&lt;/li&gt;
      &lt;li&gt;Changed keyword for Michelle to avoid conflict with health in Serpent’s Hold.&lt;/li&gt;
      &lt;li&gt;Fixed broken message trigger for Water in Castle British.&lt;/li&gt;
      &lt;li&gt;Fixed misspelled keyword for Estro in the Lycaeum.&lt;/li&gt;
      &lt;li&gt;Fixed misspelled keyword for a poor beggar in Yew.&lt;/li&gt;
      &lt;li&gt;Fixed broken message trigger for Alkerion in Minoc.&lt;/li&gt;
      &lt;li&gt;Fixed broken message trigger for Shamino in Skara Brae.&lt;/li&gt;
      &lt;li&gt;Fixed broken message trigger for Charm in Cove.&lt;/li&gt;
      &lt;li&gt;Dozens of minor fixes to spelling, grammar, and formatting.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;new-game-features&quot;&gt;New Game Features&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Select active character in combat with 1-8, 0 returns to party mode.&lt;/li&gt;
  &lt;li&gt;You can quit and save in dungeons.&lt;/li&gt;
  &lt;li&gt;If you move outside the border of a towne, castle, or keep, the game asks if you want to exit to Britannia.&lt;/li&gt;
  &lt;li&gt;Joystick control.&lt;/li&gt;
  &lt;li&gt;Dungeons get darker when a torch is close to burning out.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;bug-fixes&quot;&gt;Bug Fixes&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Meditating at shrines now gives different hints for 1, 2, and 3 cycles.&lt;/li&gt;
  &lt;li&gt;Hythloth dungeon rooms on level 6 are now accessible.&lt;/li&gt;
  &lt;li&gt;Character creation no longer suffers from random hangs.&lt;/li&gt;
  &lt;li&gt;Loading a saved game restores balloon flying mode.&lt;/li&gt;
  &lt;li&gt;Allow backspace when giving gold or using stones.&lt;/li&gt;
  &lt;li&gt;Don’t enter locations when flying in balloon.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;technical-enhancements&quot;&gt;Technical Enhancements&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Fastloader with support for 1541, 1571, 1581, CMD FD, and CMD HD.&lt;/li&gt;
  &lt;li&gt;Runs from a single disk, no disk swapping when playing.&lt;/li&gt;
  &lt;li&gt;EasyFlash cartridge version.&lt;/li&gt;
  &lt;li&gt;Music is not interrupted when data is loaded from disk.&lt;/li&gt;
  &lt;li&gt;SuperCPU support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;game-cheats&quot;&gt;Game Cheats&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;A save game editor is bundled with the game.&lt;/li&gt;
  &lt;li&gt;Unlimited magic.&lt;/li&gt;
  &lt;li&gt;Unlimited food.&lt;/li&gt;
  &lt;li&gt;Unlimited torches.&lt;/li&gt;
  &lt;li&gt;Unlimited keys.&lt;/li&gt;
  &lt;li&gt;Unlimited gems.&lt;/li&gt;
  &lt;li&gt;Avoid combat.&lt;/li&gt;
  &lt;li&gt;Control balloon.&lt;/li&gt;
  &lt;li&gt;Idle without pass.&lt;/li&gt;
  &lt;li&gt;Teleportation system, press T in Britannia and then (T)owne, (D)ungeon, (S)hrine, (L)ocation, or (C)oordinate.&lt;/li&gt;
  &lt;li&gt;Create transport if you try to (B)oard an empty tile, select (H)orse, (S)hip, or (B)alloon.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;additional-changes-since-ultima-iv-gold&quot;&gt;Additional Changes Since Ultima IV Gold&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Disk drive no longer spins when there is no disk activity, and the game loads faster.&lt;/li&gt;
  &lt;li&gt;Balloon cheat has several bugs fixed.&lt;/li&gt;
  &lt;li&gt;Swapped lat/long for teleport cheat.&lt;/li&gt;
  &lt;li&gt;Added unlimited gems and idle cheats.&lt;/li&gt;
  &lt;li&gt;Fixed reagent editing in save game editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;known-bugs&quot;&gt;Known Bugs&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;If you’re playing the 1541 version and answer a question wrong during the ending the game is supposed to throw you out to Britannia, but instead it hangs. Play the 1571, 1581, or EasyFlash version instead to avoid this issue, or just make sure you get all the answers right.&lt;/li&gt;
  &lt;li&gt;The crack intro is out of sync and glitches a bit on NTSC, but should otherwise work fine.&lt;/li&gt;
  &lt;li&gt;Blue border doesn’t get redrawn properly around wind status after you exit a dungeon.&lt;/li&gt;
  &lt;li&gt;If you die and teleport back to Lord British the wrong music plays in Castle Britannia, until you klimb down the ladder or talk to Lord British.&lt;/li&gt;
  &lt;li&gt;If the savegame editor is started from cartridge and has problems accessing the flash saves you get an error asking you to insert a disk in device #239.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Ultima IV Remastered (teaser trailer)</title>
   <link href="http://magervalp.github.io/2015/03/28/u4-remastered-teaser.html"/>
   <updated>2015-03-28T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/03/28/u4-remastered-teaser</id>
   <content type="html">&lt;p&gt;My development projects are usually more or less in the open. As soon as I have something that might be of interest to others I tend to publish the repo on &lt;a href=&quot;https://github.com/MagerValp&quot;&gt;GitHub&lt;/a&gt;, where it either &lt;a href=&quot;https://github.com/MagerValp/NewLogLines&quot;&gt;sinks&lt;/a&gt; or &lt;a href=&quot;https://github.com/MagerValp/AutoDMG&quot;&gt;swims&lt;/a&gt;. For the last couple of months though I’ve been working quietly on my own. I have dropped a &lt;a href=&quot;https://twitter.com/MagerValp/status/580331352110837760&quot;&gt;couple&lt;/a&gt; of &lt;a href=&quot;http://www.amibay.com/showthread.php?70120-UK1541-user-feedback&amp;amp;p=675660&amp;amp;viewfull=1#post675660&quot;&gt;screenshots&lt;/a&gt; but I don’t think anyone noticed… As I’ve been &lt;em&gt;itching&lt;/em&gt; to talk about it it’s with great relief that I’m finally able to announce:&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-remastered-trinity-large.png&quot;&gt;&lt;img src=&quot;/images/u4-remastered-trinity-large.png&quot; alt=&quot;Ultima IV Remastered&quot; /&gt;&lt;/a&gt;
    &lt;h1&gt;Ultima IV Remastered for the C64&lt;/h1&gt;
&lt;/figure&gt;

&lt;p&gt;Ultima IV has a special place in my heart.&lt;/p&gt;

&lt;p&gt;Back in 1987 when I bought my first computer, I started trading games on tape with my friends, and dabbled a bit in basic and machine code programming. But after my friend visited his uncle he came back raving about this marvelous game that let you walk around on a world map, explore dungeons, and talk to people in towns and castles. The game would even save your progress so you could continue the next day. The only snag was that you needed a disk drive to play it, which none of us had.&lt;/p&gt;

&lt;p&gt;It took me another year before I could save up enough money to buy a second hand disk drive, but when I did the first game I bought was Ultima IV. I spent countless hours exploring Britannia, reading through the faux leather cover manuals, and once I learned how to access raw sectors from the disk drive I started decoding the game’s data to print maps on the screen.&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/u4-map.png&quot; alt=&quot;Ultima IV Map&quot; width=&quot;256&quot; height=&quot;256&quot; /&gt;
    &lt;figcaption&gt;My home away from home.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Later on I took a proper look at disassembling the game and figuring out how it worked. I ended up rewriting the game’s loader to work on larger disk drives, and fixed the game so it didn’t run too fast with a &lt;a href=&quot;http://en.wikipedia.org/wiki/SuperCPU&quot;&gt;SuperCPU&lt;/a&gt; accelerator. After about four years worth of spare time it was released in 2006 as Ultima IV Gold. My intention was always to clean up the source a bit and release an updated version, but as with most projects it ended up sitting in a backup archive of my old Windows PC instead. My development environment slowly mutated, as it tends to do, so the archive turned into an uncompilable mess of old Perl scripts and jumbled Makefiles that somehow made sense at the time, but only now only produces a fountain of error messages.&lt;/p&gt;

&lt;p style=&quot;width: 100%; text-align: center; font-size: 24px&quot;&gt;&amp;#x2625;&lt;/p&gt;

&lt;p&gt;Some &lt;a href=&quot;http://csdb.dk/event/?id=2314&quot;&gt;recent events&lt;/a&gt; in the C64 scene made a few people ask if maybe the Ultima IV Gold loader was available, but it saddened me to have to tell them that I couldn’t even get it to work myself. This, combined with a week off work, made me decide that I might as well take a look at the mess. In the end it only took about a day’s work, and after that I was hooked again. With a fresh Makefile written from scratch (if you’re a programmer and haven’t read &lt;a href=&quot;https://www.google.se/search?q=recursive+make+considered+harmful&quot;&gt;Recursive Make Considered Harmful&lt;/a&gt;, go do so immediately after this) and all the support tools rewritten in Python the project came back to life.&lt;/p&gt;

&lt;p&gt;I made a little research and compiled what I think is a fairly complete list of bugs in the 6502 ports (the C64 and Atari 800 versions share over 90% of the source code and data with the Apple II original), and it was a joy to hunt down every last one of them. The DOS version has received &lt;a href=&quot;http://ultima.wikia.com/wiki/Ultima_IV_Upgrade_Patch&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;http://wiki.ultimacodex.com/wiki/U4-Hythloth-L6-Room-7&quot;&gt;patches&lt;/a&gt; too, and since the file formats are virtually identical I could backport those patches too.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-hythloth-l6-large.png&quot;&gt;&lt;img src=&quot;/images/u4-hythloth-l6-large.png&quot; alt=&quot;Hythloth level 6&quot; width=&quot;312&quot; height=&quot;206&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;This room can't be reached in the original.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The largest job though was fixing the dialogue, simply because there is so much of it. The early releases were littered with typos and downright bugs where some paths of the dialogue were inaccessible. Fortunately it got progressively better with each port and the last DOS version provided a good starting point. Interestingly the 68k ports were &lt;a href=&quot;http://ultima.wikia.com/wiki/Computer_Ports_of_Ultima_IV#The_16-bit_Ports&quot;&gt;independently fixed&lt;/a&gt; and differ both in style and how the bugs have been fixed.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-serpents-hold-guard-large.png&quot;&gt;&lt;img src=&quot;/images/u4-serpents-hold-guard-large.png&quot; alt=&quot;Serpent's Hold Guard&quot; width=&quot;312&quot; height=&quot;206&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;These guards used to reply with Sentri's dialogue.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;While &lt;a href=&quot;http://www.mobygames.com/developer/sheet/view/developerId,4623/&quot;&gt;Chuck Bueche&lt;/a&gt; did a good job porting Ultima III and IV to the C64, not least with a great interpretation of &lt;a href=&quot;https://www.youtube.com/watch?v=2aHO6V2s_6s&quot;&gt;Ken Arnold’s music&lt;/a&gt;, he didn’t use the hardware to its fullest potential. For Ultima V they hired &lt;a href=&quot;http://www.mobygames.com/developer/sheet/view/developerId,491/&quot;&gt;David Shapiro&lt;/a&gt; who was a lot more experienced with the platform - not that it’s fair to compare with the earlier releases, there is a world of difference between C64 games in 1985 and 1988.&lt;/p&gt;

&lt;p&gt;Disregarding the massive leaps forward that the core game engine did in U5, the most obvious change is probably that of the graphical richness that Shapiro managed to bring to the game, considering that it uses the same graphics mode as U3 and U4. The thought struck me that if I could just find 0x300 bytes for the extra color tables there’s no reason U4 couldn’t look just as good. Since memory was already full in my 2006 release it would need a lot of restructuring, as the color tables need unbroken pages of 0x100 bytes and there were only scraps here and there. It’s always a little unnerving to rearrange memory when you’re working with someone else’s code, since what looks like free space might be used at a later point in the game, but by relocating some of my own patch code to gaps in lower memory I could transplant the tileset and color tables from Ultima V. It’s impossible to port the full tileset, since the engine in Ultima V can handle 512 tiles and Ultima IV is limited to 256, but it still brings a marked improvement.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-a2-c64-remastered-large.png&quot;&gt;&lt;img src=&quot;/images/u4-a2-c64-remastered-large.png&quot; alt=&quot;Ultima IV for Apple II, C64, Remastered&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;Ultima IV on the Apple II, the original C64 port, and my remastered version.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I also decided to backport one of the best improvements in the U5 engine, where you can select an active character in combat — this makes a world of difference when exploring dungeon rooms.&lt;/p&gt;

&lt;p&gt;Of course, after replacing the tileset the character creation intro graphics really sticks out like a sore thumb. The original port has a very primitive conversion of &lt;a href=&quot;http://www.mobygames.com/developer/sheet/view/developerId,11350/&quot;&gt;Marsha Meuse’s&lt;/a&gt; Apple II graphics, and the C64 is capable of so much better. I checked with my friends in &lt;a href=&quot;http://csdb.dk/group/?id=396&quot;&gt;Genesis Project&lt;/a&gt; and to my great joy &lt;a href=&quot;http://csdb.dk/scener/?id=19&quot;&gt;Vanja ‘Mermaid’ Utne&lt;/a&gt; was interested in taking on the massive job of redrawing the intro graphics. The difference is, to say the least, stunning.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/images/u4-mermaid-intro-large.png&quot;&gt;&lt;img src=&quot;/images/u4-mermaid-intro-large.png&quot; alt=&quot;Intro graphics&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;The original intro graphics, and Vanja's replacement (based on the FM Towns version).&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Since I was on a roll I figured that I might as well fix one of my pet peeves with the game. For something that relies so heavily on telling a story with text, it has always baffled me that EVERYONE SHOUTS when you talk to them in the 6502 ports. The engine is perfectly capable of printing lower case characters, and it’s used everywhere else. Since I had already extracted all the dialogue as part of the earlier bug hunt it was an easy job to port a cleaned up version of the DOS dialogue back in. A minor change in string encoding also meant that I could free up 16 bytes in every conversation, allowing me to put back some punctuation that had to be cut due to a lack of the space in the original.&lt;/p&gt;

&lt;p style=&quot;width: 100%; text-align: center; font-size: 24px&quot;&gt;&amp;#x2625;&lt;/p&gt;

&lt;p&gt;Of course, it didn’t end there, but this blog post is already way too long. For the full details you’ll have to wait until it’s released at &lt;a href=&quot;http://csdb.dk/event/?id=2316&quot;&gt;Gubbdata&lt;/a&gt; this weekend. All told, I’ve had a great time revisiting this old project and I can’t wait to share it with the world!&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/u4-packed.jpg&quot; alt=&quot;Packed and ready to leave&quot; width=&quot;300&quot; height=&quot;400&quot; /&gt;
    &lt;figcaption&gt;C64s packed and ready to leave!&lt;/figcaption&gt;
&lt;/figure&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.5.3</title>
   <link href="http://magervalp.github.io/2015/03/24/autodmg-v1.5.3.html"/>
   <updated>2015-03-24T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2015/03/24/autodmg-v1.5.3</id>
   <content type="html">&lt;p&gt;I have released AutoDMG 1.5.3 which contains the following bugfixes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Include custom volume name when saving a template from the GUI.&lt;/li&gt;
  &lt;li&gt;Fixed resolving of certain aliases on 10.10.&lt;/li&gt;
  &lt;li&gt;Fixed error message when log file couldn’t be opened.&lt;/li&gt;
  &lt;li&gt;Fixed building when a mobile account is roaming and can’t look up its username.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.5.3 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.5.2</title>
   <link href="http://magervalp.github.io/2014/11/13/autodmg-v1.5.2.html"/>
   <updated>2014-11-13T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/11/13/autodmg-v1.5.2</id>
   <content type="html">&lt;p&gt;AutoDMG 1.5.2 has been released with a small bugfix:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fixed Setup Assistant country/language selection on 10.10.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.5.2 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.5.1</title>
   <link href="http://magervalp.github.io/2014/10/31/autodmg-v1.5.1.html"/>
   <updated>2014-10-31T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/10/31/autodmg-v1.5.1</id>
   <content type="html">&lt;p&gt;AutoDMG 1.5.1 has been released with a small bugfix:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fixed crash on startup when ~/Library/Logs has wrong permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.5.1 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.5</title>
   <link href="http://magervalp.github.io/2014/10/16/autodmg-v1.5.html"/>
   <updated>2014-10-16T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/10/16/autodmg-v1.5</id>
   <content type="html">&lt;p&gt;Apple just released 10.10, and here’s AutoDMG to go with it. Changelog is nice and short:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added 10.10 support.&lt;/li&gt;
  &lt;li&gt;Removed 10.7 support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy Yosemite day!&lt;/p&gt;

&lt;p&gt;You can download 1.5 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG 10.8 maintainer needed</title>
   <link href="http://magervalp.github.io/2014/10/15/autodmg-10.8-maintainer.html"/>
   <updated>2014-10-15T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/10/15/autodmg-10.8-maintainer</id>
   <content type="html">&lt;p&gt;Since I no longer support 10.8 at work I will not be able to stay on top of updates for AutoDMG. With the upcoming release of AutoDMG 1.5 I’ve removed support for 10.7 (stay on 1.4.4 to build 10.7 images), and unless 10.8 is to suffer the same fate someone needs to step up. It’s not particularly hard: fork &lt;a href=&quot;https://github.com/MagerValp/AutoDMGUpdateProfiles&quot;&gt;AutoDMGUpdateProfiles&lt;/a&gt;, follow the &lt;a href=&quot;https://github.com/MagerValp/AutoDMGUpdateProfiles#suggested-workflow&quot;&gt;suggested workflow&lt;/a&gt; and send pull requests on github.&lt;/p&gt;

&lt;p&gt;As always I will do my best to keep up with the latest release of OS X, and the one before, but pull requests are most welcome there too.&lt;/p&gt;

&lt;p&gt;Also, I’ve uploaded a &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;new beta of AutoDMG 1.5&lt;/a&gt;. I expect this build to become the final release version and I’m just waiting for the final GM to drop.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.4.4 and 1.5b</title>
   <link href="http://magervalp.github.io/2014/08/20/autodmg-v1.4.4.html"/>
   <updated>2014-08-20T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/08/20/autodmg-v1.4.4</id>
   <content type="html">&lt;p&gt;Thanks to our great community a few more AutoDMG bugs have been discovered. I rolled up the fixes today and released 1.4.4:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fixed crash when user has unicode characters in primary group name.&lt;/li&gt;
  &lt;li&gt;Better error handling when downloads fail or additional packages are moved.&lt;/li&gt;
  &lt;li&gt;Verify passwords in CLI to avoid failed builds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve also released a new beta of 1.5 for Yosemite testers. It contains the same fixes as 1.4.4.&lt;/p&gt;

&lt;p&gt;You can download 1.4.4 and 1.5b from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Swift Impressions</title>
   <link href="http://magervalp.github.io/2014/06/05/swift-impressions.html"/>
   <updated>2014-06-05T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/06/05/swift-impressions</id>
   <content type="html">&lt;p&gt;Of all the announcements at &lt;a href=&quot;https://developer.apple.com/wwdc/&quot;&gt;WWDC&lt;/a&gt; the one that got me the most excited was that of &lt;a href=&quot;https://developer.apple.com/swift/&quot;&gt;Swift&lt;/a&gt;, the new programming language. I looked at &lt;a href=&quot;http://golang.org/&quot;&gt;Go&lt;/a&gt; and &lt;a href=&quot;http://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt; earlier this year, and while I find them interesting I didn’t find a compelling reason to switch from Python, my trusty go-to language for the past few years. And even though I prefer Python for most projects, when you’re developing Cocoa applications you always feel like a second-class citizen. The &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/blob/76632b7568bb7079bc4ef02e6cbbfa6ffcfc026b/AutoDMG/IEDAppVersionController.py#L71&quot;&gt;crazy long&lt;/a&gt; method names are a small but ever-present annoyance, and I’ve spent way more time than I like trying to herd &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/commit/021cad4bff38a8d69cddd64a6567e1a6b04efdee#diff-6aadb2f63ce120533e6c25967a8fa3c6&quot;&gt;runaway exceptions&lt;/a&gt; in background threads.&lt;/p&gt;

&lt;p&gt;So I’ve been on the fence lately, thinking that maybe I should trade some of Python’s ease of development for Objective-C’s promise of a more stable code base down the road. Thus, the Swift announcement couldn’t have come at a better time. The stability and performance of a modern, type safe language, together with the automatic memory management and flexible container types that Python has spoiled me with. What’s not to love?&lt;/p&gt;

&lt;p&gt;I took the plunge and installed the Xcode 6 beta, and promptly lost a day futzing around with &lt;a href=&quot;https://developer.apple.com/library/prerelease/mac/recipes/xcode_help-IB_storyboard/AboutStoryboards.html&quot;&gt;Storyboards&lt;/a&gt; and &lt;a href=&quot;https://developer.apple.com/library/mac/documentation/userexperience/conceptual/AutolayoutPG/Introduction/Introduction.html&quot;&gt;Auto Layout&lt;/a&gt; - I really need to take the time to learn that stuff. But then I spent most of yesterday making a silly little app to display the status of the Absolute Manage agent and what packages it has queued for install, giving Swift a proper workout. My impressions:&lt;/p&gt;

&lt;h1 id=&quot;the-good&quot;&gt;The Good&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;The syntax is nice and consistent, with no obvious warts.&lt;/li&gt;
  &lt;li&gt;All the things you’d expect from a modern language, like type inference and closures.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_428&quot;&gt;Optionals&lt;/a&gt; provide an elegant and safe alternative to NULL pointers.&lt;/li&gt;
  &lt;li&gt;It’s refreshing to actually have to read the documentation, since there’s virtually nothing of substance on Google or StackOverflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;the-bad&quot;&gt;The Bad&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;It’s frustrating to actually have to read the documentation, since there’s virtually nothing of substance on Google or StackOverflow.&lt;/li&gt;
  &lt;li&gt;There’s no way to catch exceptions, yet we’re expected to call classes that &lt;a href=&quot;https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/Classes/NSTask_Class/Reference/Reference.html#//apple_ref/occ/instm/NSTask/launch&quot;&gt;can raise&lt;/a&gt; them.&lt;/li&gt;
  &lt;li&gt;I’m missing list comprehensions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;the-ugly&quot;&gt;The Ugly&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;The Xcode syntax highlighter keeps crashing and restarting.&lt;/li&gt;
  &lt;li&gt;I’ve managed to find no fewer than two bugs with array downcasting that causes the compiler to crash.&lt;/li&gt;
  &lt;li&gt;Error messages are rarely helpful:&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&quot;out&quot;&gt;AMSController.swift:52:38: error: cannot convert the expression's type 'AnyObject[]!' to type 'AnyObject[]!'&lt;/code&gt;
&lt;code class=&quot;prettyprint&quot;&gt;if let urls = fm.contentsOfDirectoryAtURL(dirURL, includingPropertiesForKeys: [], options: 0, error: &amp;amp;error) {&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;              ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;(I think &lt;code class=&quot;highlighter-rouge&quot;&gt;options: 0&lt;/code&gt; should be &lt;code class=&quot;highlighter-rouge&quot;&gt;options: nil&lt;/code&gt; since in Swift it’s a struct and not a bitmask - at least that makes the compiler happy.)&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;verdict&quot;&gt;Verdict&lt;/h1&gt;

&lt;p&gt;Overall the first impression is overwhelmingly positive, and whatever my next Cocoa project will be I’m certain that I’ll be writing it in Swift. The only problem is that the toolchain is currently too buggy for actual work, but I’m sure that will improve in the next couple of betas.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DS NetBoot sets from the command line</title>
   <link href="http://magervalp.github.io/2014/05/27/autodsnbi.html"/>
   <updated>2014-05-27T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/05/27/autodsnbi</id>
   <content type="html">&lt;p&gt;If you, like me, only build DeployStudio NetBoot sets once in a blue moon I’m guessing you also tend to forget all the configuration options in the assistant and have to look them up each time. With the torrent of &lt;a href=&quot;http://deploystudio.com/News/News.html&quot;&gt;recent DS releases&lt;/a&gt; (not that I’m complaining!) I found myself running the assistant one too many times and I figured that there must be a way to automate it. There was a hint in the forum a while back (&lt;a href=&quot;http://deploystudio.com/Forums/viewtopic.php?pid=21539#p21539&quot;&gt;post #5&lt;/a&gt;) and recently PaintedTurtle posted a &lt;a href=&quot;http://deploystudio.com/Forums/viewtopic.php?id=5945&quot;&gt;sample script&lt;/a&gt; showing that it’s actually pretty straightforward. I wrapped it up in a script with configuration options in the same order as the assistant to keep it nice and simple:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/MagerValp/AutoDSNBI&quot;&gt;AutoDSNBI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a bonus it accepts either a system volume or a system image, e.g. your latest &lt;a href=&quot;https://github.com/MagerValp/AutoDMG&quot;&gt;AutoDMG&lt;/a&gt; image.&lt;/p&gt;

&lt;p&gt;I’ve built a couple of NBIs with it now but I haven’t tested it extensively, so caveat emptor.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.4.1</title>
   <link href="http://magervalp.github.io/2014/05/15/autodmg-v1.4.1.html"/>
   <updated>2014-05-15T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/05/15/autodmg-v1.4.1</id>
   <content type="html">&lt;p&gt;AutoDMG 1.4.1 is out:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added support for &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/Templates#variables&quot;&gt;variables&lt;/a&gt; in templates (CLI only).&lt;/li&gt;
  &lt;li&gt;Fixed a crash when trying to mount certain dmgs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/jazzace&quot;&gt;Anthony Reimer&lt;/a&gt; for finding the dmg bug!&lt;/p&gt;

&lt;p&gt;You can download 1.4.1 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Implementing A* in 6502 assembler</title>
   <link href="http://magervalp.github.io/2014/05/07/astar-in-asm.html"/>
   <updated>2014-05-07T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/05/07/astar-in-asm</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;/2014/05/02/priority-qeue-in-asm.html&quot;&gt;Last time&lt;/a&gt; I implemented a priority queue using a heap, and this time I’m going to use it as the basis of implementing &lt;a href=&quot;http://theory.stanford.edu/~amitp/GameProgramming/&quot;&gt;A* pathfinding&lt;/a&gt; for my RPG (&lt;em&gt;&lt;a href=&quot;/images/Mutant-Combat.png&quot;&gt;1&lt;/a&gt; &lt;a href=&quot;/images/Mutant-World.png&quot;&gt;2&lt;/a&gt;&lt;/em&gt;). As always the code is available on GitHub: &lt;a href=&quot;https://github.com/MagerValp/AsmAstar&quot;&gt;AsmAstar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m not going to try to explain the algorithm here, but I’m going to focus on how I implemented it and the optimizations I chose. I recommend reading &lt;a href=&quot;http://theory.stanford.edu/~amitp/GameProgramming/AStarComparison.html&quot;&gt;Amit Patel’s Introduction to A*&lt;/a&gt; as it’s the best article on A* I’ve found. &lt;strong&gt;Update:&lt;/strong&gt; Amit wrote a new (interactive!) &lt;a href=&quot;http://www.redblobgames.com/pathfinding/a-star/introduction.html&quot;&gt;Introduction to A*&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/AstarPy.png&quot; alt=&quot;Astar.py&quot; style=&quot;float:right; margin-left: 15px&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;playing-with-a&quot;&gt;Playing with A*&lt;/h1&gt;

&lt;p&gt;This time I also started with a high level implementation to get the details right before writing low level code, and I’d been looking for an excuse to play with &lt;a href=&quot;http://omz-software.com/pythonista/&quot;&gt;Pythonista&lt;/a&gt;. I can’t say I enjoyed writing code on my iPhone though, a Bluetooth keyboard is a must before I try that again. Anyway, I shared the code as a gist if you want to play with it it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pythonista code: &lt;a href=&quot;https://gist.github.com/MagerValp/11369992&quot;&gt;Astar.py&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core of the algorithm is in &lt;code class=&quot;highlighter-rouge&quot;&gt;find()&lt;/code&gt;. Since writing code on my iPhone drained my patience it’s missing a few vital optimizations, making it perform quite badly. I can always claim that it’s slow so you can watch as the algorithm expands its search tree.&lt;/p&gt;

&lt;h1 id=&quot;the-open-set&quot;&gt;The open set&lt;/h1&gt;

&lt;p&gt;A* spends most of its time inserting and deleting nodes from the open set, which is why it’s important to choose the right data structure for it. Depending on what kinds of maps it’s traversing the ratio of insertions to deletions is going to vary, but it’s likely to be heavy on insertions. In my game, with 8 directions of movement in rooms that rarely have more than 10x10 tiles of open space, I’ve found that it inserts about twice as many nodes as it deletes. Fortunately the &lt;a href=&quot;/2014/05/02/priority-qeue-in-asm.html&quot;&gt;heap&lt;/a&gt; that I implemented in my last article has &lt;a href=&quot;http://bigocheatsheet.com/&quot;&gt;O(log n)&lt;/a&gt; complexity and is slightly faster at inserting than deleting, fitting the task nicely. It only needs to be widened so that instead of just maintaining a tree of single bytes it has parallel trees of priority, cost, xpos, and ypos that are all manipulated in tandem.&lt;/p&gt;

&lt;h1 id=&quot;the-closed-set&quot;&gt;The closed set&lt;/h1&gt;

&lt;p&gt;A* also needs to keep track of nodes that have already been explored, the set of closed nodes. To support large maps this needs to be a dynamic data structure that features fast lookups and doesn’t use too much RAM.&lt;/p&gt;

&lt;p&gt;One vital distinction that needs to be made is that &lt;em&gt;nodes&lt;/em&gt; in the A* search tree are not the same as map &lt;em&gt;coordinates&lt;/em&gt;. The same coordinates can be visited by multiple nodes when alternative paths are explored. There’s an optimization opportunity here though: only insert nodes for a coordinate if the cost is lower than that of previously visiting nodes. This has a large impact on the number of nodes that are inserted. Also, when grabbing a node from the open set, if the coordinate has been visited previously by a less costly node, there’s no need to examine it as all its children will be more expensive. Taken together they mean that even though there may be multiple nodes for a coordinate in the open set, instead of a set of closed nodes we only have to store a cost for each coordinate, and this can be done with a simple array. There are two values that need to be stored for each coordinate:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The lowest cost that it has been reached by.&lt;/li&gt;
  &lt;li&gt;Which neighbor the path came from.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since I allow 8 directions of movement 3 bits is enough to store the neighbor. My &lt;a href=&quot;http://en.wikipedia.org/wiki/Action_point&quot;&gt;action point&lt;/a&gt; system uses a cost of 5 for orthogonal movement and 7 for diagonal, but even if I used a cost of 2/3 I would need at least 6 bits to represent path cost. Thus the only option is to use at least two bytes of storage for each coordinate.&lt;/p&gt;

&lt;h1 id=&quot;sliding-window&quot;&gt;Sliding window&lt;/h1&gt;

&lt;p&gt;This has turned the problem from one of speed or complexity into one of size. I have a 4 kB buffer for map tiles, but there simply isn’t space to allocate another extra 8 kB. Fortunately I don’t have creatures moving across the whole map since combat is limited to one room at a time, and rooms are never larger than 21 x 21 tiles, neatly fitting them on a single screen. This means that I can have a window that slides across the map following the action and only need two 441 byte buffers for cost and direction.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/Mutant-Sliding-Window.png&quot; alt=&quot;Sliding Window&quot; /&gt;
&lt;em&gt;Current room borders (red) and sliding window (green).&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;from-c-to-assembly&quot;&gt;From C to assembly&lt;/h1&gt;

&lt;p&gt;I started out with everything except the heap in plain C and then worked out which functions took the most time. The low hanging fruit was array access to the map, cost, and direction buffers since it involved 16-bit multiplication, and they’re called several times for each node. The other function that was easy to optimize was the A* heuristic calculation (based on &lt;a href=&quot;http://en.wikipedia.org/wiki/Chebyshev_distance&quot;&gt;Chebyshev distance&lt;/a&gt; multiplied by 5 for orthogonal steps and 7 for diagonal steps), called once for each node insertion. Instead of relying on the C compiler’s generic 16-bit math I use hardcoded 8-bit multiplication with shifts and adds, making it an order of magnitude faster.&lt;/p&gt;

&lt;p&gt;With the micro optimizations out of the way I started looking at converting the code for examining neighbors and inserting them into the open set. The results were rather disappointing though — despite inlining the cost check/update and using registers instead of the stack to pass arguments the net result was a meagre 5% speedup. In the end keeping the code clear and maintainable is more important than squeezing out the last bit of performance, it’s a turn based game after all.&lt;/p&gt;

&lt;h1 id=&quot;sandbox-application&quot;&gt;Sandbox application&lt;/h1&gt;

&lt;p&gt;I developed a small sandbox application for testing. You can place unpassable boulders on a 21 x 21 map and watch as the algorithm tries to wiggle its way around them. The closed set is visualized with arrows displaying the direction from which it was added. You can download it here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Prebuilt binary: &lt;a href=&quot;/data/AsmAstar.d64&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;AsmAstar.d64&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Source code: &lt;a href=&quot;https://github.com/MagerValp/AsmAstar&quot;&gt;AsmAstar&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run it with &lt;code class=&quot;highlighter-rouge&quot;&gt;x64sc&lt;/code&gt; from the &lt;a href=&quot;http://vice-emu.sourceforge.net/index.html#download&quot;&gt;VICE Emulator Suite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/asmastar.png&quot; alt=&quot;AsmAstar&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Implementing a priority queue in 6502 assembler</title>
   <link href="http://magervalp.github.io/2014/05/02/priority-queue-in-asm.html"/>
   <updated>2014-05-02T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/05/02/priority-queue-in-asm</id>
   <content type="html">&lt;p&gt;I have an old game programming project (&lt;em&gt;obligatory screenshots: &lt;a href=&quot;/images/Mutant-Combat.png&quot;&gt;1&lt;/a&gt; &lt;a href=&quot;/images/Mutant-World.png&quot;&gt;2&lt;/a&gt;&lt;/em&gt;) that I have been playing with off and on for a few years now. It’s a turn based combat RPG for the C64 and the engine is a great playground for testing algorithms and experimenting with data structures. There’s a treasure trove of interesting problems to solve, like realtime &lt;a href=&quot;http://www.roguebasin.com/index.php?title=Field_of_Vision&quot;&gt;field of vision&lt;/a&gt;, combat &lt;a href=&quot;http://www.roguebasin.com/index.php?title=Line_of_Sight&quot;&gt;line of sight&lt;/a&gt;, and enemy &lt;a href=&quot;http://www.roguebasin.com/index.php?title=Category:AI&quot;&gt;AI&lt;/a&gt;. I did an implementation of &lt;a href=&quot;http://theory.stanford.edu/~amitp/GameProgramming/&quot;&gt;A* pathfinding&lt;/a&gt; in assembler a few years ago, but it was too inflexible to be reused, so I decided to start over. To get decent performance out of A* you need a fast &lt;a href=&quot;http://en.wikipedia.org/wiki/Priority_queue&quot;&gt;priority queue&lt;/a&gt;, so I figured that it would be a good first step.&lt;/p&gt;

&lt;p&gt;You might want to download the sample projects if you want to follow along:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Test project for Xcode: &lt;a href=&quot;https://github.com/MagerValp/CHeap&quot;&gt;CHeap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;6502 code: &lt;a href=&quot;https://github.com/MagerValp/AsmHeap&quot;&gt;AsmHeap&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;playing-with-priority-queues&quot;&gt;Playing with priority queues&lt;/h1&gt;

&lt;p&gt;A priority queue is an abstract data type like a stack or a queue, where you can insert elements that have an associated priority, and its unique selling point is that you can quickly pull out the element with the highest priority. It’s commonly implemented using a &lt;a href=&quot;http://en.wikipedia.org/wiki/Heap_%28data_structure%29&quot;&gt;heap&lt;/a&gt;. Python comes with a built-in module called &lt;a href=&quot;https://docs.python.org/2/library/heapq.html&quot;&gt;heapq&lt;/a&gt; which uses a standard list to store the heap’s binary tree, so we can take a look at how it behaves:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;python&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;Python 2.7.5 (default, Sep 12 2013, 21:33:34) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;import heapq&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;tree = []&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;for value in (6, 4, 7, 3, 8):&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;... &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;    heapq.heappush(tree, value)&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;... &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;&lt;/code&gt;                                                            3
&lt;code class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;tree&lt;/code&gt;                                                       / \    &lt;i&gt;Each child is&lt;/i&gt;
&lt;code class=&quot;out&quot;&gt;[3, 4, 7, 6, 8]&lt;/code&gt;&lt;!--             --&gt;                             &lt;i&gt;Tree structure:&lt;/i&gt;   4   7   &lt;i&gt;smaller than&lt;/i&gt;
&lt;code class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;while tree:&lt;/code&gt;                                              / \      &lt;i&gt;its parent.&lt;/i&gt;
&lt;code class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;    print heapq.heappop(tree)&lt;/code&gt;                           6   8
&lt;code class=&quot;prompt&quot;&gt;... &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;3&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;4&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;6&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;7&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;8&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;A nice side effect is that when you pull out each item in priority order you end up with sorted data, since a heap is at the base of &lt;a href=&quot;http://en.wikipedia.org/wiki/Heapsort&quot;&gt;heapsort&lt;/a&gt;. heapq implements a min-heap, so you get elements in ascending order.&lt;/p&gt;

&lt;h1 id=&quot;high-level-implementation&quot;&gt;High level implementation&lt;/h1&gt;

&lt;p&gt;Instead of hitting the metal right away I like to start with a high level implementation. Since I needed an excuse to play with unit testing in Xcode, Objective-C seemed like a good idea. An NSMutableArray is a comfortable choice for storing the tree, so let’s make a simple class interface:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint&quot;&gt;@interface CASMutableArrayHeap : NSObject

@property NSMutableArray *tree;

- (int)size;
- (void)push:(NSNumber *)value;
- (NSNumber *)pop;

@end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can find the class implementation in &lt;a href=&quot;https://github.com/MagerValp/CHeap/blob/master/CAstar/CASMutableArrayHeap.m&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;CASMutableArrayHeap.m&lt;/code&gt;&lt;/a&gt; on GitHub, since it’s a bit too big to paste here. It’s is based on chapter 10 in &lt;a href=&quot;https://www.google.com/search?q=Mastering+Algorithms+with+C+Kyle+Loudon&quot;&gt;Mastering Algorithms with C&lt;/a&gt; by Kyle Loudon (O’Reilly 1999) who explains the algorithm much better than I ever could.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/MagerValp/CHeap/blob/master/CAstarTests/CAstarMutableArrayHeapTests.m&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;CAstarMutableArrayHeapTests.m&lt;/code&gt;&lt;/a&gt; contains unit tests that confirms that the classes grows and shrinks as expected, and that it correctly sorts a list of random numbers.&lt;/p&gt;

&lt;h1 id=&quot;low-level-c-implementation&quot;&gt;Low level C implementation&lt;/h1&gt;

&lt;p&gt;The next step on the way down is to get rid of the high level types and automatic memory handling, so goodbye NSMutableArray. Instead let’s work with a fixed buffer. This loses a lot of flexibility but the speed gains are massive:&lt;/p&gt;

&lt;table style=&quot;width: 60%; margin-left: auto; margin-right: auto&quot;&gt;
  &lt;caption&gt;
    &lt;strong&gt;1000 * 128 push/pop&lt;/strong&gt;
  &lt;/caption&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Heap Implementation&lt;/th&gt;
      &lt;th&gt;Time&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;NSMutableArray&lt;/td&gt;&lt;td&gt;1431 ms&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Fixed memory buffer&lt;/td&gt;&lt;td&gt;28 ms&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;!--
CASMutableArrayHeap 1000 * 128 push/pop = 1430.63 ms
CASCArrayHeap 1000 * 128 push/pop = 27.95 ms
CASCAsmHeap 1000 * 128 push/pop = 45.71 ms
--&gt;

&lt;p&gt;This implementation can be found in &lt;a href=&quot;https://github.com/MagerValp/CHeap/blob/master/CAstar/CASCArrayHeap.m&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;CASCArrayHeap.m&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;pseudo-assembly&quot;&gt;Pseudo-assembly&lt;/h1&gt;

&lt;p&gt;This is where I’d normally start writing assembly code, but since I’m having so much fun with the unit tests I figured I might as well write some 6502 pseudo code in C. This means that while it’s still valid C code, all data is now manipulated 8 bits at a time, all arithmetic is done with a single variable called &lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt; and all indexed addressing is done with &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;y&lt;/code&gt;, mimicking the 6502 CPU registers. Readability has gone out the window, but it can be translated line by line into assembly and it’s nice to be able to test it for correctness before diving in. This version is in &lt;a href=&quot;https://github.com/MagerValp/CHeap/blob/master/CAstar/CASCAsmHeap.m&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;CASCAsmHeap.m&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;finally-the-promised-6502&quot;&gt;Finally the promised 6502&lt;/h1&gt;

&lt;p&gt;With a solid understanding of the implementation it’s time to bring it down to assembly level. I prefer working with the assembler from the &lt;a href=&quot;http://cc65.github.io/cc65/&quot;&gt;cc65&lt;/a&gt; compiler suite, so let’s create a public interface in &lt;code class=&quot;highlighter-rouge&quot;&gt;asmheap.h&lt;/code&gt; allowing the code to be called from C:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-c&quot;&gt;extern uint8_t asmheap_size;

void asmheap_init();
void __fastcall__ asmheap_push(uint8_t value);      /* Pass value argument in A/X instead of on the stack. */
uint8_t asmheap_pop(void);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation starts with allocating a buffer for the tree:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;	.align 128

tree:	.res 128	; Reserve 128 bytes for the tree, which allows
size:	.res 1		; us to use the N flag to check if it's full.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first function is &lt;code class=&quot;highlighter-rouge&quot;&gt;asmheap_init&lt;/code&gt;, which couldn’t be simpler:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;; Initialize an empty heap.
_asmheap_init:
	lda #0
	sta size
	rts&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For push and pop let’s use a small macro to help swap nodes in the tree:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;; Swap node at x with node at y.
  .macro swap
	lda tree,x
	sta @temp
	lda tree,y
	sta tree,x
@temp = * + 1
	lda #$5e		; Self mod.
	sta tree,y
  .endmacro&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Push:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;; Push a value into the tree.
_asmheap_push:
	ldx size
	; If the heap is full, overwrite the last node.
	bpl :+
	dex
	stx size
:	; Push A to the bottom of the heap.
	sta tree,x
	inc size

	; Set Y to the parent node = (X - 1) / 2.
	txa
	sec
	sbc #1
	lsr
	tay
@heapify:
	; If X is at the top of the heap, we're done.
	cpx #0
	beq @done
	; If X is larger than its parent Y, we're done.
	lda tree,x
	cmp tree,y
	bcs @done
	; Swap X with its parent Y.
	swap
	; Set X to point at its parent.
	tya
	tax
	; Set Y to the new parent node.
	sec
	sbc #1
	lsr
	tay
	jmp @heapify
@done:
	rts&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And pop:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-asm6502&quot;&gt;; Pop the lowest value from the tree.
_asmheap_pop:
	; Save the item at the top so we can return it.
	lda tree
	sta @return_value
	; Remove the item at the bottom of the tree.
	dec size
	beq @done
	ldy size
	lda tree,y
	; Move it to the top of the tree.
	sta tree
	; Heapify the tree.
	ldx #0
	stx @current_node
@heapify:
	; Left child is at x * 2 + 1.
	txa
	asl
	;clc		; X is always &amp;lt; 128
	adc #1
	tay
	; Check if we're at the bottom of the tree.
	cpy size
	bcs @done
	; Check if left child is smaller.
	lda tree,y
	cmp tree,x
	; If not skip to checking the right child.
	bcs @check_right
	; Since it was smaller let X point to the left child.
	tya
	tax
@check_right:
	; Right child is at x * 2 + 2, or left + 1.
	iny
	; Check if we're at the bottom of the tree.
	cpy size
	bcs @check_swap
	; Check if right child is smaller.
	lda tree,y
	cmp tree,x
	bcs @check_swap
	tya
	tax

@check_swap:
	; If either child was smaller X is different from the current node.
@current_node = * + 1
	cpx #$5e		; Self mod.
	; If not we're done.
	beq @done
	
	; Swap parent with child.
	ldy @current_node
	swap
	; Let the child be the new current node.
	stx @current_node
	; Repeat.
	jmp @heapify
@done:
	ldx #0
@return_value = * + 1
	lda #$5e		; Self mod.
	rts&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&quot;testing-and-benchmarking&quot;&gt;Testing and benchmarking&lt;/h1&gt;

&lt;p&gt;In order to verify that the final implementation works as intended I ended up writing a small test and benchmarking harness. You can find the heap implementation together with the tests on GitHub as &lt;a href=&quot;https://github.com/MagerValp/AsmHeap&quot;&gt;AsmHeap&lt;/a&gt;. For fun let’s run the benchmark and see how it fares:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/asmheap100.png&quot; alt=&quot;AsmHeap&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That’s about 86 seconds for 1000 * 128, which makes my 3.7 GHz Xeon E5 Mac Pro about 3000 times as fast as my C64.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.4</title>
   <link href="http://magervalp.github.io/2014/04/15/autodmg-v1.4.html"/>
   <updated>2014-04-15T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/04/15/autodmg-v1.4</id>
   <content type="html">&lt;p&gt;AutoDMG 1.4 is here, and with its release I consider it feature complete: it now supports every feature that InstaDMG has. The last missing piece of the puzzle was BaseOS caching, but instead of just copying the feature I have a slightly more generalized take on it. You can now use a previously generated image as the source, allowing you to update images as needed or cache them at any point. You’ll find the details in &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/Updating-Images&quot;&gt;the wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Changes in 1.4:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Support for using previously generated images as sources.&lt;/li&gt;
  &lt;li&gt;Added Advanced Options window for setting the volume’s name and size.&lt;/li&gt;
  &lt;li&gt;Drag &amp;amp; drop apps can be added to additional software, and will be copied to /Applications.&lt;/li&gt;
  &lt;li&gt;Apps and packages can be wrapped in a dmg.&lt;/li&gt;
  &lt;li&gt;You can now load and save of templates from the GUI.&lt;/li&gt;
  &lt;li&gt;The template used to build the image is saved to /var/log inside the image for future reference.&lt;/li&gt;
  &lt;li&gt;Improved error handling should allow saving of the log if the app crashes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/images/AutoDMG-1.4.png&quot; alt=&quot;AutoDMG 1.4&quot; /&gt;
&lt;em&gt;Cached image as source, advanced options, drag &amp;amp; drop app, pkg in dmg, and new crash handler&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can download 1.4 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.3.2</title>
   <link href="http://magervalp.github.io/2014/03/27/autodmg-v1.3.2.html"/>
   <updated>2014-03-27T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/03/27/autodmg-v1.3.2</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/uclara&quot;&gt;uclara&lt;/a&gt; discovered a &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/issues/46&quot;&gt;regression&lt;/a&gt; when building on 10.8.5.&lt;/p&gt;

&lt;p&gt;You can download 1.3.2 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.3.1</title>
   <link href="http://magervalp.github.io/2014/03/26/autodmg-v1.3.1.html"/>
   <updated>2014-03-26T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/03/26/autodmg-v1.3.1</id>
   <content type="html">&lt;p&gt;Here’s a quick release of 1.3.1 since a major feature didn’t make it in time for 1.3: thanks to the work of &lt;a href=&quot;https://github.com/FireAllianceNX&quot;&gt;FireAllianceNX&lt;/a&gt; 10.7 support has been re-enabled, and there’s an update profile available for 11G63.&lt;/p&gt;

&lt;p&gt;And as there was a lot of code added in 1.3, it also came with its fair share of bugs. Thanks to Tim Sutton, Anthony Reimer, and dhandy0 the following have been found and squashed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fixed a crash if building in CLI without UpdateProfiles.plist in Application Support.&lt;/li&gt;
  &lt;li&gt;Fixed handling of relative paths in the CLI.&lt;/li&gt;
  &lt;li&gt;Fixed build failing if the output path pointed to a nonexistent directory.&lt;/li&gt;
  &lt;li&gt;Fixed building with packages stored on network volumes.&lt;/li&gt;
  &lt;li&gt;Fixed inaccurate error message when a broken package was added.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.3.1 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.3</title>
   <link href="http://magervalp.github.io/2014/03/24/autodmg-v1.3.html"/>
   <updated>2014-03-24T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/03/24/autodmg-v1.3</id>
   <content type="html">&lt;p&gt;Following a few betas to test the waters AutoDMG 1.3 is finally ready for release. For those of you that like building with the GUI the only new feature is that the 32 GB limit is gone as AutoDMG will now automatically create a larger image if you add large packages. The biggest news is for everyone who likes automation and reproducible workflows, since AutoDMG finally has a proper command-line interface. Not that everyone has been sitting idly by, we’ve recently seen the release of some nice solutions from the folks at &lt;a href=&quot;https://code.google.com/p/google-macops/wiki/can_haz_image_manual&quot;&gt;Google&lt;/a&gt; and &lt;a href=&quot;https://github.com/chilcote/stew&quot;&gt;Adobe&lt;/a&gt;, and an interesting way of merging &lt;a href=&quot;http://www.afp548.com/2014/01/16/instaup2date-autodmg/&quot;&gt;InstaDMG’s workflow with AutoDMG&lt;/a&gt;. My hope is that 1.3 will integrate much smoother in workflows that require building large images, or when you need to build a lot of images repeatedly. The documentation on how to throw away the training wheels is in the wiki:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/Command-Line-Interface&quot;&gt;Command-Line Interface&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/Templates&quot;&gt;Templates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.3 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;

&lt;p&gt;It seems appropriate to end with a screenshot:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;cat 10.9.2.adtmpl&lt;/code&gt;
&lt;code class=&quot;out prettyprint lang-xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&amp;gt;
&amp;lt;plist version=&quot;1.0&quot;&amp;gt;
&amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;TemplateFormat&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;1.0&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;SourcePath&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;~/Desktop/Install OS X Mavericks.app&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;OutputPath&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;~/Desktop/BaseImage-10.9.2-13C64.dmg&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;VolumeName&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;Macintosh HD&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;ApplyUpdates&amp;lt;/key&amp;gt;
    &amp;lt;true/&amp;gt;
    &amp;lt;key&amp;gt;AdditionalPackages&amp;lt;/key&amp;gt;
    &amp;lt;array&amp;gt;
    &amp;lt;/array&amp;gt;
    &amp;lt;key&amp;gt;IncludeTemplates&amp;lt;/key&amp;gt;
    &amp;lt;array&amp;gt;
    &amp;lt;/array&amp;gt;
&amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;/Applications/AutoDMG.app/Contents/MacOS/AutoDMG -l autodmg-10.9.2-20140324.log -L 7 build 10.9.2.adtmpl&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;Installer: /Users/admin/Desktop/Install OS X Mavericks.app
Output Path: /Users/admin/Desktop/BaseImage-10.9.2-13C64.dmg
Volume Name: Macintosh HD
Accepted source /Users/admin/Desktop/Install OS X Mavericks.app: Mac OS X 10.9.2 13C64
Found installer: Mac OS X 10.9.2 13C64
Update: iBooks Update (14.6 MB)
Update: BookKit Update (78.5 kB)
Update: iTunes 11.1.5 (232.7 MB)
Password for admin: &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;********&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;Starting build
Using installer: Mac OS X 10.9.2 13C64
Using output path: /Users/admin/Desktop/BaseImage-10.9.2-13C64.dmg
Starting task with 1 phases
Starting phase: Preparing
phase: Preparing
Starting task with 7 phases
Starting phase: Starting install
phase: Starting install
Install task running
Script phase: sparseimage
Starting phase: Creating disk image
phase: Creating disk image
Script phase: install 0:/private/tmp/dmg.vXAs2G/Packages/OSInstall.mpkg
Starting phase: Installing OS
phase: Installing OS
Script phase: install 1:/Users/admin/Library/Application Support/AutoDMG/Updates/iBooksDelta.pkg
Starting phase: Installing iBooks Update
phase: Installing iBooks Update
Script phase: install 2:/Users/admin/Library/Application Support/AutoDMG/Updates/BookKitDelta.pkg
Starting phase: Installing BookKit Update
phase: Installing BookKit Update
Script phase: install 3:/private/tmp/dmg.XQKgax/Install iTunes.pkg
Starting phase: Installing iTunes 11.1.5
phase: Installing iTunes 11.1.5
Script phase: asr
Starting phase: Finalizing disk image
phase: Finalizing disk image
Starting task with 4 phases
Starting phase: Finalizing disk image
phase: Finalizing disk image
Finalize task running
Script phase: asr1
Starting phase: Finalizing disk image
phase: Finalizing disk image
Script phase: asr2
Starting phase: Finalizing disk image
phase: Finalizing disk image
Script phase: asr3
Starting phase: Finalizing disk image
phase: Finalizing disk image
Starting task with 1 phases
Starting phase: Finishing
phase: Finishing
Finish
Build finished successfully, image saved to /Users/admin/Desktop/BaseImage-10.9.2-13C64.dmg
Build successful&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 <entry>
   <title>Managing Java Security Site Exceptions With Deployment Rule Sets</title>
   <link href="http://magervalp.github.io/2014/02/11/creating-and-signing-deploymentruleset-jar.html"/>
   <updated>2014-02-11T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/02/11/creating-and-signing-deploymentruleset-jar</id>
   <content type="html">&lt;p&gt;Like many organization we have a few legacy systems that require Java to run, and as much as we’d like to replace them we’re not quite there yet. With 7u51 Oracle turned up the default security settings by another notch (undoubtedly a good thing!) and as a result it will no longer allow users to run unsigned applets without a security manifest. Users that have admin privileges can &lt;a href=&quot;https://blogs.oracle.com/java-platform-group/entry/upcoming_exception_site_list_in&quot;&gt;whitelist applets&lt;/a&gt; themselves, and there are some &lt;a href=&quot;http://derflounder.wordpress.com/2014/01/16/managing-oracles-java-exception-site-list/&quot;&gt;creative ways&lt;/a&gt; of managing site exceptions, but the officially supported way is to create a Deployment Rule Set. It’s not particularly complicated but if you’re not a Java developer it involves some tools that you’re probably not familiar with (at least I wasn’t). Here’s my annotated guide to creating, signing, and deploying &lt;code class=&quot;highlighter-rouge&quot;&gt;DeploymentRuleSet.jar&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1-get-a-jar-signing-certificate&quot;&gt;1. Get a jar signing certificate&lt;/h2&gt;

&lt;p&gt;First off we’ll create a new keystore, and generate a self signed certificate and keypair:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;keytool -genkey -alias MYORG -keyalg RSA -validity 1095 -keystore ~/MYORG_keystore&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;keytool&lt;/code&gt; will ask you to set a password for the keystore, and ask who the certificate is for. The certificate authority we use (&lt;a href=&quot;https://tcs.sunet.se/info/&quot;&gt;TERENA Certificate Service&lt;/a&gt;) didn’t accept DSA keys so I had to set the algorithm to RSA. I also selected a 3 year validity period, in the vain hope that we’ll have replaced those old legacy systems by then (hello to myself googling this again in 3 years).&lt;/p&gt;

&lt;p&gt;At this point you have two options:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Buy a code signing certificate from one of the &lt;a href=&quot;http://superuser.com/questions/55470/which-trusted-root-certificates-are-included-in-java&quot;&gt;CAs that are trusted by Java&lt;/a&gt;. Expect to pay at least $80/year.&lt;/li&gt;
  &lt;li&gt;Make your clients &lt;a href=&quot;https://blogs.oracle.com/java-platform-group/entry/self_signed_certificates_for_a&quot;&gt;trust a self-signed certficiate&lt;/a&gt;. Free, involves a little more work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you get a certificate signed by a trusted authority, create a &lt;a href=&quot;http://en.wikipedia.org/wiki/Certificate_signing_request&quot;&gt;CSR&lt;/a&gt; that we can send off to a certificate authority:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;keytool -certreq -alias MYORG -keystore ~/MYORG_keystore&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;Enter keystore password: &lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;-----BEGIN NEW CERTIFICATE REQUEST-----
MIIC+DCCAeACAQAwgYIxCzAJBgNVBAYTAlNFMRUwEwYDVQQIEwxZT1VSIENPVU5UUlkxEjAQBgNV
BAcTCVlPVVIgQ0lUWTEaMBgGA1UEChMRWU9VUiBPUkdBTklaQVRJT04xGDAWBgNVBAsTD1lPVVIg
REVQQVJUTUVOVDESMBAGA1UEAxMJWU9VUiBOQU1FMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAqx4D8UoKecvVcSDkJWkLBr94IOb+aZuW704dfteg/scNHtsklAza/Taj/qcQLUnH+/BC
QW4HeOibtKMnvtDoz9qo2Cx0O+qJ4+XYXO2wGAorh1nvqbfmFCy/nmgRTJcUgROCW99FI0knlB2Z
fkeXSKQuu2wnLadflra/RmFBVcECSigBcQVG4xUBpRjxxIsM84hh0bez1KZgjRW66o62AbFynIsn
NsMB11d+1rUmZFVBqFwNcZ+CiKJfpOrBgLxQayRed/Jxhv+IKT95vz7a7czvfTzoopr9OuTqK/rC
d3V04744kFFjIUhNahbU4rOZtkr4htMAF17HFe61OaxbUQIDAQABoDAwLgYJKoZIhvcNAQkOMSEw
HzAdBgNVHQ4EFgQUgQjjFrERujTjUjlSIl6ia6l47ykwDQYJKoZIhvcNAQELBQADggEBACSH03D+
QSDbMp350+nUVgiV1tseInJJLkTfEG3F9lZPnJcdeY4rpb/JUCubmqD58iM5gHojNsrIucyY2Opp
PDE5lqD0oth3e48gkTL4VDuMLAk4tyGFVTuWHTGASf3b446qX5eufTJD3ri6bk7mJ8qXt8eDm4uB
z5+aNZ4m/Oh/pTOZxcnfXWGmO7yxIGfUDkiROvQm46qZ5pFwE+THNcPqIWCPLoiaEfdVLbQS6/ie
KNbVqnG0TtnCnhCnTIdWs2JXpniuMt9bpZs5n2nsOQYq1BxstLh8uQx6VhnFhc2h8lJbaXjC+miD
gPfUMYEiUNun30VaYBtfEJQJQlpBbtI=
-----END NEW CERTIFICATE REQUEST-----&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Paste this into the CA’s request form, retrieve the signed certificate, and replace the self-signed one:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;keytool -importcert -file ~/Downloads/signed_cert.pem -trustcacerts -alias MYORG -keystore ~/MYORG_keystore&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should now have a valid code signing certificate in your keystore, and you’re ready to create and sign jar files.&lt;/p&gt;

&lt;h2 id=&quot;2-create-deploymentrulesetjar&quot;&gt;2. Create DeploymentRuleSet.jar&lt;/h2&gt;

&lt;p&gt;Oracle gives you a fair bit of control over how applets should run (refer to the &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/deployment_rules.html&quot;&gt;Deployment Rule Set documentation&lt;/a&gt; here), but here’s an example of a very simple whitelist for two sites, while leaving everything else to run with the default security policy:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;ruleset version=&quot;1.0+&quot;&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;id location=&quot;https://cruft.example.com&quot; /&amp;gt;
        &amp;lt;action permission=&quot;run&quot; /&amp;gt;
    &amp;lt;/rule&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;id location=&quot;https://dinosaur.example.com&quot; /&amp;gt;
        &amp;lt;action permission=&quot;run&quot; /&amp;gt;
    &amp;lt;/rule&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;id /&amp;gt;&amp;lt;!-- The last rule is the default policy and the id should be blank. --&amp;gt;
        &amp;lt;action permission=&quot;default&quot; /&amp;gt;
    &amp;lt;/rule&amp;gt;
&amp;lt;/ruleset&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we package ruleset.xml into DeploymentRuleSet.jar:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;jar cf DeploymentRuleSet.jar ruleset.xml&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and finally sign DeploymentRuleSet.jar with the certificate:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;jarsigner -tsa https://timestamp.geotrust.com/tsa DeploymentRuleSet.jar MYORG&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;3-distribute-deploymentrulesetjar-to-your-clients&quot;&gt;3. Distribute DeploymentRuleSet.jar to your clients&lt;/h2&gt;

&lt;p&gt;With the jar packaged and signed, all that’s left to do is distribute it to your clients. No fancy magic is needed here, just drop it in the appropriate path:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;OS&lt;/th&gt;
      &lt;th&gt;Path&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Windows&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;C:\Windows\Sun\Java\Deployment\DeploymentRuleSet.jar&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Mac OS X&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/Library/Application Support/Oracle/Java/Deployment/DeploymentRuleSet.jar&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Linux &amp;amp; Solaris&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/.java/deployment/DeploymentRuleSet.jar&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;4-add-a-reminder-for-when-the-certificate-expires&quot;&gt;4. Add a reminder for when the certificate expires&lt;/h2&gt;

&lt;p&gt;Remember that certificates expire, and you really don’t want to be caught with your pants down. I usually create a calendar reminder 3 months before it expires, with all the details needed to renew it.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://blogs.oracle.com/java-platform-group/entry/introducing_deployment_rule_sets&quot;&gt;Introducing Deployment Rule Sets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/deployment_rules.html&quot;&gt;Deployment Rule Set documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html&quot;&gt;keytool manual&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html&quot;&gt;jarsigner manual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>The joys of an Intel X25-M SSD in a MacBook Pro 15&quot; (Early 2011)</title>
   <link href="http://magervalp.github.io/2014/02/05/intel-ssd-mbpro15.html"/>
   <updated>2014-02-05T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2014/02/05/intel-ssd-mbpro15</id>
   <content type="html">&lt;p&gt;I got my shiny new Mac Pro the other week, and I finally finished migrating everything from my old machine. A nice side effect was that I could move the SSD over from my old Mac Pro to my laptop, since it’s the last of my machines suffering from spinning rust. Heck, even my C64s and Amigas have flash drives these days. The early 2011 15&quot; is easy enough to open up, and Thunderbolt target mode makes it easy to shuffle the data over.&lt;/p&gt;

&lt;p&gt;Unfortunately the machine refused to boot afterwards, and in recovery mode the SSD wasn’t even visible in Disk Utility or system_profiler, yet it showed up as a device in the Startup Manager and obviously worked in target mode. There are lots of threads on the discussion boards about trouble with SSDs in the 2011 MacBooks, apparently due to badly shielded SATA cables. It turned out to be a red herring though, as the actual problem turned out to be a firmware bug:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;(2CV102M3) This firmware revision fixes enumeration and slow boot issues […]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As soon as Spotlight and Dropbox stops fighting over who gets to index the drive first my laptop should finally join the ranks of snappy computers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And special thanks to Cpuroast in ##osx-server on helping me find the intel fw update.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.2.1</title>
   <link href="http://magervalp.github.io/2013/12/17/autodmg-v1.2.1.html"/>
   <updated>2013-12-17T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/12/17/autodmg-v1.2.1</id>
   <content type="html">&lt;p&gt;I’ve been working on implementing caching in AutoDMG, but the bugs kept piling up in the meantime. I decided to break the silence with a small bugfix release:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Allow renamed InstallESD images (but they still have to match &lt;code class=&quot;highlighter-rouge&quot;&gt;InstallESD*.dmg&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Fix message regarding deprecated installers on 10.8.&lt;/li&gt;
  &lt;li&gt;Fix a crash if the user’s primary GID doesn’t have a corresponding group.&lt;/li&gt;
  &lt;li&gt;Fix deletion of multiple additional packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also published new update profiles for 10.9.1 and 10.8.5 earlier today which should be downloaded automatically.&lt;/p&gt;

&lt;p&gt;You can download 1.2.1 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.2</title>
   <link href="http://magervalp.github.io/2013/11/14/autodmg-v1.2.html"/>
   <updated>2013-11-14T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/11/14/autodmg-v1.2</id>
   <content type="html">&lt;p&gt;What a week.&lt;/p&gt;

&lt;p&gt;Friday started with the new Retina MacBooks arriving, the ones that can’t be downgraded to 10.8. We have a working solution for upgrading machines to Mavericks but we’re still not ready with the deployment workflow for 10.9 since we’ve been spending the last few weeks chasing PHD sync bugs with NetApp. In the middle of getting the 13A2093 and 13A3017 builds ready my Mac Pro decided to keel over and die. It came back to life again, and I guess I should be only thankful for an excuse to get an &lt;a href=&quot;http://www.apple.com/mac-pro/&quot;&gt;Epic Thermos of Power&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then on Monday DeployStudio flaked out and the Finalize task started using 100% CPU taking down package installs with it. Our Absolute Manage server also decided that it’d had enough and started telling the clients to go away since it needed its beauty sleep.&lt;/p&gt;

&lt;p&gt;Tuesday started with a bit of relief as we got some help from Absolute tweaking the server settings, and it’s been behaving since. Profile Manager had been coughing and wheezing though and on Wednesday it crapped out totally. Today was spent migrating profiles out of Profile Manager and into Absolute Manage, something we’d been planning to do anyway as part of our move to 10.9, just not this week…&lt;/p&gt;

&lt;p&gt;Despite all this AutoDMG version 1.2 is out, but only with a few minor changes. Firstly I now set &lt;code class=&quot;highlighter-rouge&quot;&gt;CM_BUILD=CM_BUILD&lt;/code&gt; which makes &lt;code class=&quot;highlighter-rouge&quot;&gt;installer&lt;/code&gt; bypass packages’ volume checks. This means that you can create machine specific builds (like 13A2093 and 13A3017) without having to run AutoDMG on that particular hardware. It also makes it possible to install packages that are configured to only install on root volumes. This should bring AutoDMG in line with InstaDMG, for better or for worse.&lt;/p&gt;

&lt;p&gt;After being prodded by Tuomo Oksakivi I also took a look into why aliases didn’t always work with drag &amp;amp; drop. Turns out that when you’re working with paths you have to resolve aliases manually, but it was simple enough to fix. The idea here is that if you have a set of packages that you want to include in every image you build, you can create a folder with aliases for easy dragging &amp;amp; dropping. It’s not exactly a replacement for InstaDMG catalogs, but it might help you keep your builds a little more organized. I have an idea for image templates, but we’ll have to see if I have time to work on it.&lt;/p&gt;

&lt;p&gt;But enough rambling. You can download 1.2 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;

&lt;p&gt;Now I think I deserve &lt;a href=&quot;http://www.youtube.com/watch?v=g0Go1odOtRM&quot;&gt;a proper cup of tea&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.1</title>
   <link href="http://magervalp.github.io/2013/11/06/autodmg-v1.1.html"/>
   <updated>2013-11-06T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/11/06/autodmg-v1.1</id>
   <content type="html">&lt;p&gt;AutoDMG version 1.1 has been released, with the following changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added support for InstallESD.dmg as source from Timothy Sutton.&lt;/li&gt;
  &lt;li&gt;Better logging during package installs.&lt;/li&gt;
  &lt;li&gt;Fix packages failing if they were in a folder with non-ascii characters in the name (thanks to Darkomen78).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.1 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;

&lt;p&gt;If you report a bug, please save the log file and attach it to the issue, it’s almost impossible to diagnose problems without it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/AutoDMG-save-log.png&quot; alt=&quot;AutoDMG save log&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Accessing Kerberized Services with the Active Directory Computer Account</title>
   <link href="http://magervalp.github.io/2013/11/05/accessing-kerberized-services-with-ad-computer-acct.html"/>
   <updated>2013-11-05T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/11/05/accessing-kerberized-services-with-ad-computer-acct</id>
   <content type="html">&lt;p&gt;Back in May I posted an article on how to access kerberized services with the AD computer account. If the blog statistics are to be believed it’s a fairly popular post too. Well, it turns out that I’d basically just missed &lt;code class=&quot;highlighter-rouge&quot;&gt;-k&lt;/code&gt; when I read the man page for &lt;code class=&quot;highlighter-rouge&quot;&gt;kinit&lt;/code&gt;. I also managed to &lt;a href=&quot;/2013/09/13/irony-is-a-b.html&quot;&gt;expose the machine’s password&lt;/a&gt; in the process of doing so, making it even more embarrassing.&lt;/p&gt;

&lt;p&gt;I updated the &lt;a href=&quot;/2013/05/22/accessing-kerberized-services-with-ad-computer-acct.html&quot;&gt;original article&lt;/a&gt;, but for reference here’s a proper script:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-sh&quot;&gt;#!/bin/bash
#
# This script requires 10.7+ and root privileges.

# Get Kerberos ticket for the machine.
declare -r ADPLIST=$(echo &quot;/Library/Preferences/OpenDirectory/Configurations/Active Directory&quot;/*.plist)
declare -r ADCOMPACCT=$(/usr/libexec/PlistBuddy -c 'print :trustaccount' &quot;$ADPLIST&quot;)
kinit -k &quot;$ADCOMPACCT&quot;

# Access services with Kerberos credentials.
mount_smbfs //sharedfiles.server.com/SharedFolder /tmp/sharedfolder
curl --negotiate -u : http://server.example.com/protectedresource
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;I’ll go stand in the corner now.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG v1.0</title>
   <link href="http://magervalp.github.io/2013/11/01/autodmg-v1.0.html"/>
   <updated>2013-11-01T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/11/01/autodmg-v1.0</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/images/AutoDMG-1.0.png&quot; alt=&quot;AutoDMG 1.0&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’ve received some great feedback during the past few days, but since no major issues have been reported I’m feeling confident enough to release &lt;a href=&quot;https://github.com/MagerValp/AutoDMG&quot;&gt;AutoDMG&lt;/a&gt; version 1.0.&lt;/p&gt;

&lt;p&gt;A big thank you goes out to everyone who helped with the testing.&lt;/p&gt;

&lt;p&gt;The changes for 1.0 include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Polished UI.&lt;/li&gt;
  &lt;li&gt;Better logging.&lt;/li&gt;
  &lt;li&gt;Fix list of updates being refreshed after profiles updated.&lt;/li&gt;
  &lt;li&gt;Added warnings for deprecated installers.&lt;/li&gt;
  &lt;li&gt;Confirm to quit when building.&lt;/li&gt;
  &lt;li&gt;Added preferences for automatic updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download 1.0 from the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;AutoDMG releases&lt;/a&gt; page. If you have any questions join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; (but please check the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; and especially the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt; first).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Create Recovery Partition Installer v1.1</title>
   <link href="http://magervalp.github.io/2013/10/30/create-recovery-partition-installer-v1.1.html"/>
   <updated>2013-10-30T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/10/30/create-recovery-partition-installer-v1.1</id>
   <content type="html">&lt;p&gt;Timothy Sutton submitted a patch yesterday that brings 10.9 support to Create Recovery Partition Installer. Grab it on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/MagerValp/Create-Recovery-Partition-Installer/releases&quot;&gt;https://github.com/MagerValp/Create-Recovery-Partition-Installer/releases&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AutoDMG</title>
   <link href="http://magervalp.github.io/2013/10/29/autodmg.html"/>
   <updated>2013-10-29T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/10/29/autodmg</id>
   <content type="html">&lt;p&gt;Since &lt;a href=&quot;http://code.google.com/p/instadmg/&quot;&gt;InstaDMG&lt;/a&gt; has issues with 10.9 and &lt;a href=&quot;http://www.mondada.com.au/&quot;&gt;SIC&lt;/a&gt; is no more I took it upon myself to create a replacement, and the result is &lt;a href=&quot;https://github.com/MagerValp/AutoDMG&quot;&gt;AutoDMG&lt;/a&gt;. It uses the same mechanic as InstaDMG to generate never booted system images, and also applies the latest software updates and installs your own custom packages. The biggest change is that it’s a GUI application now:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://f.cloud.github.com/assets/404393/1420666/6dde1438-3fe3-11e3-8fed-b78aa74784a4.png&quot; alt=&quot;Autodmg-0.8-Log&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Today I’m releasing 0.8 which has matured a lot over the previous releases, and it’s the first version I feel is ready for serious testing. There are most likely still bugs lurking around which is why I’m not calling it 1.0 just yet, but it’s working well here for building images of 10.8.5 and 10.9.&lt;/p&gt;

&lt;p&gt;So, please &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/releases&quot;&gt;grab it&lt;/a&gt; and test it in your workflows. If you have any questions please check out the &lt;a href=&quot;https://github.com/MagerValp/AutoDMG/wiki&quot;&gt;documentation&lt;/a&gt; first (yes, I wrote some!) and join us in &lt;a href=&quot;http://webchat.freenode.net/?channels=##osx-server&quot;&gt;##osx-server&lt;/a&gt; to discuss it.&lt;/p&gt;

&lt;p&gt;I should also thank &lt;a href=&quot;http://www.mondada.com.au/&quot;&gt;Duncan McCracken&lt;/a&gt; for showing us how to install OS X on a disk image at &lt;a href=&quot;http://docs.macsysadmin.se/2013/2013doc.html&quot;&gt;MacSysAdmin&lt;/a&gt;, which was the seed that grew into AutoDMG. Also thanks to the unstoppable &lt;a href=&quot;http://managingosx.wordpress.com/&quot;&gt;Greg Neagle&lt;/a&gt; who came up with the name. Thanks guys!&lt;/p&gt;

&lt;p&gt;PS: If anyone’s wondering what’s up with &lt;a href=&quot;http://magervalp.github.io/CreateUserPkg/&quot;&gt;CreateUserPkg&lt;/a&gt;, there’s a beta of 1.2.4 hiding in the &lt;a href=&quot;https://github.com/MagerValp/CreateUserPkg/issues/31&quot;&gt;issue tracker&lt;/a&gt; that I’m going to package up and release as soon as AutoDMG settles down.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Irony is a B*tch</title>
   <link href="http://magervalp.github.io/2013/09/13/irony-is-a-b.html"/>
   <updated>2013-09-13T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/09/13/irony-is-a-b</id>
   <content type="html">&lt;p&gt;So yesterday I posted about a vulnerability is OS X where &lt;a href=&quot;/2013/09/12/os-x-passwords-leaked-during-login.html&quot;&gt;passwords are leaked during login&lt;/a&gt;, and by chance I happened to read my previous post on &lt;a href=&quot;/2013/05/22/accessing-kerberized-services-with-ad-computer-acct.html&quot;&gt;accessing kerberized services with the Active Directory computer account&lt;/a&gt; today. It prominently featured the following nugget:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-sh&quot;&gt;echo &quot;$ADCOMPPWD&quot; | kinit --password-file=STDIN &quot;$ADCOMPACCT&quot;&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Oh sweet irony. I updated the post with a &lt;a href=&quot;/2013/05/22/accessing-kerberized-services-with-ad-computer-acct.html&quot;&gt;fixed version&lt;/a&gt; that uses a temporary file instead of piping from &lt;code class=&quot;highlighter-rouge&quot;&gt;echo&lt;/code&gt; for the whole world to see.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>OS X Passwords Leaked During Login</title>
   <link href="http://magervalp.github.io/2013/09/12/os-x-passwords-leaked-during-login.html"/>
   <updated>2013-09-12T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/09/12/os-x-passwords-leaked-during-login</id>
   <content type="html">&lt;p&gt;&lt;em&gt;NOTE: This post was written May 17th but was withheld until Apple patched the vulnerability.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;

&lt;p&gt;When logging in on a machine running OS X 10.7 - 10.8.4 with a &lt;a href=&quot;http://www.apple.com/support/osxserver/profilemanager/&quot;&gt;configuration profile&lt;/a&gt; applied passwords are exposed in clear text to other logged in users.&lt;/p&gt;

&lt;p&gt;Apple has released &lt;a href=&quot;http://support.apple.com/kb/DL1675&quot;&gt;10.8.5&lt;/a&gt; &lt;a href=&quot;http://support.apple.com/kb/DL1676&quot;&gt;(combo)&lt;/a&gt; and &lt;a href=&quot;http://support.apple.com/kb/DL1677&quot;&gt;Security Update 2013-004&lt;/a&gt; for 10.7 with patches for the vulnerability.&lt;/p&gt;

&lt;h3 id=&quot;cve-id&quot;&gt;CVE-ID&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-1030&quot;&gt;CVE-2013-1030&lt;/a&gt; (&lt;a href=&quot;http://support.apple.com/kb/HT5880&quot;&gt;Apple’s summary&lt;/a&gt;)&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;I was writing a script today to automatically mount shared folders for our users when they log in. I wanted the script to wait for the desktop to appear before it runs, so users can see the status window in case there is a problem with the mount. The easiest way to accomplish this is to wait for a process to appear (e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;Finder.app&lt;/code&gt;) and then wait a couple of seconds more for good measure. To find out what processes appear during a typical login I wrote the following snippet and ran it in the background while I logged in with my test user:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint&quot;&gt;while true; do
    echo &quot;----------------&quot;
    ps auxww | grep [u]sername | cut -c70- | sort
    sleep 1
done&lt;/code&gt;
&lt;/pre&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;This confirmed my suspicion that the best option seems to be to wait for &lt;code class=&quot;highlighter-rouge&quot;&gt;Finder.app&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Dock.app&lt;/code&gt; to appear, but what nearly caused a [T&lt;/td&gt;
      &lt;td&gt;N&amp;gt;K](http://www.catb.org/jargon/html/C/CNK.html) were the first snapshots of the process table:&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;pre&gt;&lt;code class=&quot;out&quot;&gt;----------------------------------
/System/Library/CoreServices/FileSyncAgent.app/Contents/MacOS/FileSyncAgent -launchedByLaunchd -PHDPlist
/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/CVMCompiler
/System/Library/PrivateFrameworks/SystemMigration.framework/Resources/Tools/migCacheCleanup -JustPhotoStreamNudge
/System/Library/PrivateFrameworks/TCC.framework/Resources/tccd
/sbin/launchd
/usr/libexec/xpcd
/usr/sbin/cfprefsd agent
/usr/sbin/distnoted agent
----------------------------------
/System/Library/CoreServices/FileSyncAgent.app/Contents/MacOS/FileSyncAgent -launchedByLaunchd -PHDPlist
/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/CVMCompiler
/System/Library/PrivateFrameworks/SystemMigration.framework/Resources/Tools/migCacheCleanup -JustPhotoStreamNudge
/System/Library/PrivateFrameworks/TCC.framework/Resources/tccd
/sbin/launchd
/usr/libexec/mdmclient mcx_userlogin &lt;em&gt;testuser secretpwd&lt;/em&gt;
/usr/libexec/xpcd
/usr/sbin/cfprefsd agent
/usr/sbin/distnoted agent
----------------------------------
/System/Library/CoreServices/FileSyncAgent.app/Contents/MacOS/FileSyncAgent -launchedByLaunchd -PHDPlist
/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/CVMCompiler
/System/Library/PrivateFrameworks/SystemMigration.framework/Resources/Tools/migCacheCleanup -JustPhotoStreamNudge
/System/Library/PrivateFrameworks/TCC.framework/Resources/tccd
/sbin/launchd
/usr/libexec/xpcd
/usr/sbin/cfprefsd agent
/usr/sbin/distnoted agent&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s fascinating how jarring it is to see your password in clear text, the reaction is almost physical. I wrote up a quick bug report (&lt;a href=&quot;rdar://problem/13921614&quot;&gt;radar 13921614&lt;/a&gt;), contacted &lt;a href=&quot;mailto:product-security@apple.com&quot;&gt;product-security@apple.com&lt;/a&gt;, and confirmed that it’s present all the way back to 10.7, but a mitigating circumstance is that the machine needs to have a configuration profile applied, e.g. by being enrolled with &lt;a href=&quot;http://www.apple.com/support/osxserver/profilemanager/&quot;&gt;Profile Manager&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To test it, log into a machine with a configuration profile applied as a standard (unprivileged) user either over SSH or with fast user switching enabled, and execute:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in prettyprint&quot;&gt;while true; do ps auxww | grep '[m]dmclient mcx_userlogin'; done&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then log in with a different user account at the login window, and watch the shell’s output. It’s like nails on chalkboard.&lt;/p&gt;

&lt;p&gt;If you’re managing student labs or other public machines I’d recommend applying the appropriate patches ASAP.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Accessing Kerberized Services with the Active Directory Computer Account</title>
   <link href="http://magervalp.github.io/2013/05/22/accessing-kerberized-services-with-ad-computer-acct.html"/>
   <updated>2013-05-22T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/05/22/accessing-kerberized-services-with-ad-computer-acct</id>
   <content type="html">&lt;p&gt;The usual scenario when you’re in a kerberized environment is that your users get a Kerberos ticket on login and they use this to access protected services, such as their home directory. Sometimes you need to execute a task in the background, and not necessarily on behalf of a user or even with anyone logged in, but how do you guarantee that the connecting client is who it says it is? In these situations you can use the machine’s AD computer account for authentication:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prettyprint lang-sh&quot;&gt;#!/bin/bash
#
# This script requires 10.7+ and root privileges.

# Initialize Kerberos if needed.
#if ! klist -t 2&amp;gt;/dev/null; th ##########
#    # Read the AD configu ##################
#    declare -r ADPLIST= ######          ###### nces/OpenDirectory/Configurations/Active Directory&quot;/*.plist)
#    declare -r ADCOMP ####     ALWAYS      ##### dy -c 'print :trustaccount' &quot;$ADPLIST&quot;)
#    declare -r ADNO ####                 #### #### 'print :&quot;node name&quot;' &quot;$ADPLIST&quot;)
#                   ####    READ THE    ####    ####
#    # Read the com ###               ####       ### stem keychain.
#    declare -r SK ####  MAN PAGE   ####         #### n&quot;
#    declare -r TE ####           ####           ####
#    security find ####         ####   BEFORE    #### SKC&quot; 2&amp;gt;&amp;amp;1 &amp;gt;/dev/null | cut -d\&quot; -f2 &amp;gt; &quot;$TEMPFILE&quot;
#    # 10.8+ suppor ###       ####               ###
#    #security find ####    ####    POSTING     #### &quot;$SKC&quot; &amp;gt; &quot;$TEMPFILE&quot;
#                    #### ####                 ####
#    # Use the compute #####     !!!!!!      #### d get a Kerberos TGT.
#    kinit --password-fi ######          ###### &quot;$TEMPFILE&quot;
#    rm -f &quot;$TEMPFILE&quot;     ##################
#fi                            ##########

# Get Kerberos ticket for the machine.
declare -r ADPLIST=$(echo &quot;/Library/Preferences/OpenDirectory/Configurations/Active Directory&quot;/*.plist)
declare -r ADCOMPACCT=$(/usr/libexec/PlistBuddy -c 'print :trustaccount' &quot;$ADPLIST&quot;)
kinit -k &quot;$ADCOMPACCT&quot;

# Access services with Kerberos credentials.
mount_smbfs //sharedfiles.server.com/SharedFolder /tmp/sharedfolder
curl --negotiate -u : http://server.example.com/protectedresource
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Fixed &lt;code class=&quot;highlighter-rouge&quot;&gt;security find-generic-password&lt;/code&gt; which doesn’t accept -w on 10.7, thanks &lt;a href=&quot;https://twitter.com/RegalWeasel/status/337288903570644992&quot;&gt;@RegalWeasel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt; Fixed &lt;a href=&quot;/2013/09/13/irony-is-a-b.html&quot;&gt;ironic&lt;/a&gt; exposure of computer account password in process table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 3:&lt;/strong&gt; &lt;a href=&quot;/2013/11/05/accessing-kerberized-services-with-ad-computer-acct.html&quot;&gt;Read the man page and removed 14 lines of bash.&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CreateUserPkg v1.2.3</title>
   <link href="http://magervalp.github.io/2013/04/05/CreateUserPkg-v1.2.3.html"/>
   <updated>2013-04-05T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/04/05/CreateUserPkg-v1.2.3</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://magervalp.github.io/CreateUserPkg/&quot;&gt;CreateUserPkg&lt;/a&gt; v1.2.3 is now available in the &lt;a href=&quot;https://itunes.apple.com/app/id540673598&quot;&gt;App Store&lt;/a&gt; and on the &lt;a href=&quot;http://magervalp.github.io/CreateUserPkg/&quot;&gt;project homepage&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Making the Impossible Possible</title>
   <link href="http://magervalp.github.io/2013/03/31/making-the-impossible-possible.html"/>
   <updated>2013-03-31T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/03/31/making-the-impossible-possible</id>
   <content type="html">&lt;p&gt;There’s an old joke in the Commodore 64 scene that if you want to see something done, just claim that it’s impossible and make sure &lt;a href=&quot;http://csdb.dk/scener/?id=8056&quot;&gt;Crossbow&lt;/a&gt; hears you say it. The C64 celebrated its 30th birthday last year, and the limits of this unassuming little brown box are still nowhere to be found.&lt;/p&gt;

&lt;p&gt;Back in 2006 while I was working on &lt;a href=&quot;http://csdb.dk/release/?id=39893&quot;&gt;Ultima IV Gold&lt;/a&gt; I’d established that none of the available loader systems met the requirements for the project, the biggest issue being that I needed to squeeze almost 800 files into a disk format that only has &lt;a href=&quot;http://en.wikipedia.org/wiki/Commodore_1541#Media&quot;&gt;683&lt;/a&gt; physical sectors. So armed with &lt;a href=&quot;http://covertbitops.c64.org/&quot;&gt;Lasse Öörni’s rants&lt;/a&gt; and &lt;a href=&quot;http://www.pagetable.com/?p=630&quot;&gt;Inside Commodore DOS&lt;/a&gt; I sat down and eventually managed to create my own system, retronymed Uload. In the following year I also tackled &lt;a href=&quot;http://csdb.dk/release/?id=51363&quot;&gt;Ultima III Gold&lt;/a&gt;, and with lots of help from &lt;a href=&quot;http://csdb.dk/scener/?id=8104&quot;&gt;Krill&lt;/a&gt; I experimented with fast GCR decoding and network transfer tools. So armed with knowledge and experience I inevitably performed the fatal mistake, &lt;a href=&quot;http://csdb.dk/forums/index.php?roomid=11&amp;amp;topicid=43923&amp;amp;showallposts=1#45912&quot;&gt;documented on the internet for all eternity&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“1541 isn’t fast enough to decode in realtime.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, shucks. While Crossbow wasn’t listening, it turns out that &lt;a href=&quot;http://csdb.dk/scener/?id=16473&quot;&gt;LFT&lt;/a&gt; was. He released &lt;a href=&quot;http://csdb.dk/release/?id=117358&quot;&gt;Shards of Fancy&lt;/a&gt; today, and the accompanying article on &lt;a href=&quot;http://linusakesson.net/programming/gcr-decoding/index.php&quot;&gt;GCR decoding on the fly&lt;/a&gt; is now up. Hats off to you, Linus.&lt;/p&gt;

&lt;p&gt;-&lt;/p&gt;

&lt;p&gt;Bonus anectode: Having misinterpreted the JPEG spec back in the 90s I argued quite vehemently that you couldn’t decode it on a C64, due to a lack of RAM. The result of course was &lt;a href=&quot;http://www.ffd2.com/fridge/jpeg/&quot;&gt;Juddpeg&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Poking Around in Mac App Store Receipts</title>
   <link href="http://magervalp.github.io/2013/03/19/poking-around-in-masreceipts.html"/>
   <updated>2013-03-19T00:00:00+00:00</updated>
   <id>http://magervalp.github.io/2013/03/19/poking-around-in-masreceipts</id>
   <content type="html">&lt;p&gt;Yngve Åström asked if anyone knew how to tell which Apple ID installed an app store app on the &lt;a href=&quot;https://groups.google.com/forum/?fromgroups=#!topic/macenterprise/-w3tHkdNfSs&quot;&gt;MacEnterprise&lt;/a&gt; mailing list:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Is it  just me or have anyone been able to read something useful out of the app/Contents/_MASReceipt/receipt?
I’m looking for a way to find out which account was used to by an app, the _MASreceipt library looked like the right place to look.
Doesn’t matter how I trie to read the receipt all I get is bits of readable info that makes very little sense to me.
Looks  like binary peaces of certs but nothing close to an AppStore account.
The /Users/myuser/Library/Preferences/com.apple.storeagent.plist AppleID will tell me what account I’m using now but that’s it.
Where can I find which account was used to by a particular app? In this case Server.app…
Is it even possible to find out?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s poke around and see what’s inside those receipt files the Mac App Store puts inside every app bundle. The receipt file itself is a &lt;a href=&quot;http://en.wikipedia.org/wiki/PKCS&quot;&gt;PKCS #7&lt;/a&gt; container, as defined by &lt;a href=&quot;http://tools.ietf.org/html/rfc2315&quot;&gt;RFC2315&lt;/a&gt;, with its payload encoded using &lt;a href=&quot;http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One&quot;&gt;ASN.1&lt;/a&gt;. We can look at its certificates using openssl’s pkcs7 command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;openssl pkcs7 -inform der -in /Applications/Xcode.app/Contents/_MASReceipt/receipt -print_certs -text&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            18:59:43:21:72:74:9c:fc
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=US, O=Apple Inc., OU=Apple Worldwide Developer Relations, CN=Apple Worldwide Developer Relations Certification Authority
        Validity
            Not Before: Nov 11 21:58:01 2010 GMT
            Not After : Nov 11 21:58:01 2015 GMT
        Subject: CN=Mac App Store Receipt Signing, OU=Apple Worldwide Developer Relations, O=Apple Inc., C=US&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;[...]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You’ll see that it contains a certificate chain with Apple’s root CA, the developer CA, and the receipt signing certificate. There’s a signed payload in the receipt as well, which we can see if we dump the ASN.1 data using openssl’s asn1parse command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;openssl asn1parse -inform der -in /Applications/Xcode.app/Contents/_MASReceipt/receipt&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;    0:d=0  hl=4 l=4701 cons: SEQUENCE          
    4:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-signedData
   15:d=1  hl=4 l=4686 cons: cont [ 0 ]        
   19:d=2  hl=4 l=4682 cons: SEQUENCE          
   23:d=3  hl=2 l=   1 prim: INTEGER           :01
   26:d=3  hl=2 l=  11 cons: SET               
   28:d=4  hl=2 l=   9 cons: SEQUENCE          
   30:d=5  hl=2 l=   5 prim: OBJECT            :sha1
   37:d=5  hl=2 l=   0 prim: NULL              
   39:d=3  hl=4 l= 526 cons: SEQUENCE          
   43:d=4  hl=2 l=   9 prim: OBJECT            :pkcs7-data
   54:d=4  hl=4 l= 511 cons: cont [ 0 ]        
   58:d=5  hl=4 l= 507 prim: OCTET STRING      [HEX DUMP]:318201F7300A0201120201&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
0104021600300A02011302010104020C00300B02010E0201010403020101300C02010A0201010404&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
1602342B300C02010B0201010404020207D3300C02010D0201010404020227D9300E020101020101&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
040602041DABD29B300E020104020101040602043D83F593300E0201090201010406020450323132&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
300E0201100201010406020400DE7D2B300F02010302010104070C05342E362E31301002010F0201&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
01040802063C079CDD8EF6301B02010002010104130C1150726F64756374696F6E52656365697074&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
301C02010202010104140C12636F6D2E6170706C652E64742E58636F6465301C0201050201010414&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
80594D99A2FC354866BD2E624356CAA402371E8B301E02010802010104161614323031332D30332D&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
31355430363A31373A32365A301E02010C02010104161614323031332D30332D31355430363A3137&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
3A32365A3047020107020101043FA2F2AB232A8EE238211B3976878A67518DE97316756762D19CBD&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
6BAF021269B097CB4557693759139ECBDCC0526F788B2FB055E68B60B3555320FA64AE5905306102&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
01060201010459706C1F223E8C5CA8B556E292C13C6A1669C0BF7BC47B7B268C017B2D37F6BEA7BF&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
D4B4FFF5FF56DBEC269CCA6EEABFC6BC24C0185FFD7F9538088B0E6A99DA608B3129C81A64966151&lt;code class=&quot;prompt&quot;&gt;↩&lt;/code&gt;
E4C5B3931ECBF73EE7040949A1F46884
  569:d=3  hl=4 l=3669 cons: cont [ 0 ]        
  573:d=4  hl=4 l=1387 cons: SEQUENCE          
  577:d=5  hl=4 l=1107 cons: SEQUENCE          
  581:d=6  hl=2 l=   3 cons: cont [ 0 ]        
  583:d=7  hl=2 l=   1 prim: INTEGER           :02
  586:d=6  hl=2 l=   8 prim: INTEGER           :1859432172749CFC
  596:d=6  hl=2 l=  13 cons: SEQUENCE          
  598:d=7  hl=2 l=   9 prim: OBJECT            :sha1WithRSAEncryption&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;[...]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first big blob of hex is a payload signed with sha1. This payload is also encoded using ASN.1, so let’s decode it and save it as a separate file, &lt;code class=&quot;highlighter-rouge&quot;&gt;payload.asn&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;openssl asn1parse -inform der -in /Applications/Xcode.app/Contents/_MASReceipt/receipt | grep -m 1 'OCTET STRING' | cut -d: -f4 | xxd -r -p &amp;gt; payload.asn&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With it saved to disk let’s see what asn1parse has to say about it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;openssl asn1parse -inform der -in payload.asn&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;    0:d=0  hl=4 l= 503 cons: SET               
    4:d=1  hl=2 l=  10 cons: SEQUENCE          
    6:d=2  hl=2 l=   1 prim: INTEGER           :12
    9:d=2  hl=2 l=   1 prim: INTEGER           :01
   12:d=2  hl=2 l=   2 prim: OCTET STRING      [HEX DUMP]:1600
   16:d=1  hl=2 l=  10 cons: SEQUENCE          
   18:d=2  hl=2 l=   1 prim: INTEGER           :13
   21:d=2  hl=2 l=   1 prim: INTEGER           :01
   24:d=2  hl=2 l=   2 prim: OCTET STRING      [HEX DUMP]:0C00
   28:d=1  hl=2 l=  11 cons: SEQUENCE          
   30:d=2  hl=2 l=   1 prim: INTEGER           :0E
   33:d=2  hl=2 l=   1 prim: INTEGER           :01
   36:d=2  hl=2 l=   3 prim: OCTET STRING      [HEX DUMP]:020101&lt;/code&gt;
&lt;code class=&quot;prompt&quot;&gt;[...]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see that the payload is composed of a set of attributes, defined by two integers and an octet string. The first integer is the attribute type, the second its version (so far always 1), and the octet string its value. How the octet string is interpreted depends on the attribute type, and Apple has reserved most for private use, but a few are public:&lt;/p&gt;

&lt;table&gt;
  &lt;!--
  &lt;caption&gt;
    &lt;strong&gt;Receipt attribute types&lt;/strong&gt;
  &lt;/caption&gt;
  --&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Definition&lt;/th&gt;
      &lt;th&gt;Value Interpretation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;&lt;td&gt;Bundle identifier&lt;/td&gt;&lt;td&gt;UTF8STRING.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;&lt;td&gt;Application version&lt;/td&gt;&lt;td&gt;UTF8STRING.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;&lt;td&gt;Opaque value&lt;/td&gt;&lt;td&gt;A series of bytes.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;&lt;td&gt;SHA-1 hash&lt;/td&gt;&lt;td&gt;20-byte SHA-1 digest value.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;17&lt;/td&gt;&lt;td&gt;In-app purchase receipt&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;http://developer.apple.com/library/mac/#releasenotes/General/ValidateAppStoreReceipt/#//apple_ref/doc/uid/TP40010573-CH1-SW23&quot;&gt;Further down the ASN.1 rabbit hole.&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Bundle ID and app version are self explanatory, and the SHA-1 hash is used to verify that the app bundle hasn’t been modified. IAPs have their own receipt following the same principle as the main receipt, leaving only the mysteriously named “Opaque value”:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;[...]&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;  114:d=1  hl=2 l=  14 cons: SEQUENCE          
  116:d=2  hl=2 l=   1 prim: INTEGER           :04
  119:d=2  hl=2 l=   1 prim: INTEGER           :01
  122:d=2  hl=2 l=   6 prim: OCTET STRING      [HEX DUMP]:02043D840EE2
&lt;/code&gt;&lt;code class=&quot;prompt&quot;&gt;[...]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From &lt;a href=&quot;http://developer.apple.com/library/mac/#releasenotes/General/ValidateAppStoreReceipt/#//apple_ref/doc/uid/TP40010573-CH1-SW5&quot;&gt;Apple’s documentation&lt;/a&gt; we can see that it’s used together with the computer’s GUID in computing the verification hash. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Basic_Encoding_Rules#Identifier_octets&quot;&gt;ASN.1 specification&lt;/a&gt; tells us that it’s an integer (0x02) and that it’s four bytes long (0x04). Let’s print it as a decimal integer:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;printf &quot;%d\n&quot; 0x$(openssl asn1parse -inform der -in payload.asn | grep -A 2 ':04$' | tail -1 | cut -d: -f4 | cut -c5-)&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;1032064738&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Still pretty opaque. Haven’t I seen that integer somewhere else though? Indeed I have:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;prompt&quot;&gt;$ &lt;/code&gt;&lt;code class=&quot;in&quot;&gt;defaults read com.apple.storeagent&lt;/code&gt;
&lt;code class=&quot;out&quot;&gt;{
    AccountKind = 0;
    AccountURLBagType = production;
    AppleID = &quot;magervalp@mac.com&quot;;
    CreditDisplayString = &quot;&quot;;
    DSPersonID = 1032064738;
    DownloadLocation = &quot;/Users/pelle/Library/Application Support/AppStore&quot;;
    EligibilityCheckDate = &quot;2013-03-18 22:26:53 +0000&quot;;
    ISBadgeValues =     {
    };
    ISLastUpdatesQueueCheck = &quot;2013-03-15 06:17:25 +0000&quot;;
    KnownAccounts =     (
                {
            AccountKind = 0;
            AccountURLBagType = production;
            CreditDisplayString = &quot;&quot;;
            DSPersonID = 1032064738;
        }
    );
    LastAuthTime = &quot;2013-03-14 21:18:37 +0000&quot;;
    LastSynchedStoreFront = &quot;143456,12&quot;;
    PurchasesInflight = 0;
    Storefront = &quot;143456-17,13&quot;;
    UserNotificationDate = &quot;2013-03-15 06:45:07 +0000&quot;;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bingo - it’s the numeric app store user ID tied to my Apple ID. While we can’t directly determine which Apple ID installed a certain app, we can build a list of DSPersonIDs and their corresponding Apple IDs and get it that way.&lt;/p&gt;

&lt;h3 id=&quot;references&quot;&gt;References:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://developer.apple.com/library/mac/#releasenotes/General/ValidateAppStoreReceipt/&quot;&gt;http://developer.apple.com/library/mac/#releasenotes/General/ValidateAppStoreReceipt/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/PKCS&quot;&gt;http://en.wikipedia.org/wiki/PKCS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://tools.ietf.org/html/rfc2315&quot;&gt;http://tools.ietf.org/html/rfc2315&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One&quot;&gt;http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 
</feed>
