Update on resource fork writing, ResEdit, and resource ‘dcmp’ decompressors

Resource write support status

So, the plan since last update was to do some work on resource write support, and there was indeed some progress. The nature of how resource forks are handled on disk compared to memory is quite interesting; After the resource map is read into memory, the resource fork on disk only needs to preserve resource data, and thus the resource manager has quite free hands on how it can move data around in the resource fork:

  • When a new resource is added using AddResource, it gets both a resource entry in the in-memory resource map, AND the resource fork gets expanded (to reserve space on disk), and on-disk location for the resource is appended after the current data area on the disk
  • When ChangedResource is called on existing resource, its size is checked to see if it grows or shrinks. Shrinking is more simple, as its data length just gets shorter, and does not need space allocation. However, if a resource grows, it needs more space allocated to it, so while the resource file is open, the resource manager simply allocates new space at end of resource fork, like it does in AddResource, and leaves the old location as “gap” in the file. This feature actually is why apple warns in the Inside Macintosh documentation, that calling ChangedResource often without calling UpdateResFile may lead to large amount of disk space used, as each new allocation expands the file size by the new allocation length!
  • When WriteResource is called, a resource with resChanged flag will get contents of its handle written to the location specified by resource entry in the resource map
  • UpdateResFile does the real “house-keeping” of resource fork, as it will iterate through all resources, removing any gaps in the resource fork, moving data to the proper places (a process called “compating” of resource fork). After this, the resource map is written at end of the resource fork (after the data section), and file size is truncated to minimum required, releasing the extra disk space.

Currently, most of write support is in place, except that resource fork compacting still needs finalization to make it work properly

Extended resources and ‘dcmp’ decompression

Of course a natural way to stress-test resource manager is to try ResEdit, which I think uses literally almost all of resource manager features. However, an interesting surprise was that ResEdit seems to utilize resource compression on a large number of its own resource, which led to the following MacTech article:

http://preserve.mactech.com/articles/mactech/Vol.09/09.01/ResCompression/index.html

Which had nice, although brief, insight on ‘dcmp’ resources and their role in resource decompression. Adding the parsing of extended resource headers was not that difficult, and luckily ResEdit contains its own ‘dcmp’ decompressors, so they could be immediately be tested, resulting in following type of logs:

Debug log of ResEdit’s ‘PACK’ resource ID=1 decompression.

This snippet of debug log shows ResEdit’s ‘PACK’ resource ID=1 decompression procedure, when Get1IndResource was called. This shows how on-disk compressed data of 19568 bytes gets decompressed into 27200 bytes in memory, using a ‘dcmp’ ID=0 decompressor which is contained within ResEdit as 68k code.

ResEdit

And of course, with the decompression working, and with a lot of fixes to file manager, list manager and various other places, ResEdit magically appears to be starting to work, one bit at a time 🙂 In this test case, we made a copy of ResEdit itself as “Test File” file, which was hard-coded for now as reply to CustomGetFile call to get it open. And this is what we got so far:

Naturally there’s still a lot to fix, but surprisingly many features seem to work out-of-the box. But at least the following problems were immediately noticeable:

  • The actual resource writing does not yet work properly
  • List Manager still has some calls which are not properly implemented which leads to a number of assertions, and most likely causes the missing icons in ‘ICN#’ editor.
  • Font scaling has issues which is why dialog texts appear weird in the preview of ‘ALRT’ editor
  • A couple IconDispatch/ScriptUtil calls which need to implemented for resource file info dialog (mostly to get Finder labels, and format the file dates)
  • Proper multi-select support for List Manager
  • A bunch of other minor issues, such as text missing from a couple places, etc.
  • Probably other issues in features not yet tested

It’s still a bit too early to start testing the actual resource write support, but it won’t be far away from now after ResEdit is made more stable first.

Package Manager update

One small, but important thing which was fixed in this update is an actual, proper ‘PACK’ resource support. This is because ResEdit uses Apple’s ‘PACK’ ID=1 to implement its “BitEdit” graphic editor (used at least in ‘ICN#’ resource editor). Until this point, all packages could be implemented as regular dispatcher calls, but for the ResEdit to work we actually had to load the ‘PACK’ resource in InitPack, and register it as one of the AppPacks in low memory globals. A quite small change, but one which ResEdit seems to be happy with, for now 🙂

Ps. As another interesting side effect, with bug fixes done to toolbox HyperCard can now both close files properly (allowing us to navigate back to Home stack), and also HyperTalk editing seems to work well enough that changes to the script source actually affect behaviour of the stack 🙂