diff --git a/v2/content/posts/2023/derez/DITL.png b/v2/content/posts/2023/derez/DITL.png new file mode 100644 index 0000000..278c24e Binary files /dev/null and b/v2/content/posts/2023/derez/DITL.png differ diff --git a/v2/content/posts/2023/derez/Dialog.png b/v2/content/posts/2023/derez/Dialog.png new file mode 100644 index 0000000..9513ea5 Binary files /dev/null and b/v2/content/posts/2023/derez/Dialog.png differ diff --git a/v2/content/posts/2023/derez/MPW.png b/v2/content/posts/2023/derez/MPW.png new file mode 100644 index 0000000..b0d62ec Binary files /dev/null and b/v2/content/posts/2023/derez/MPW.png differ diff --git a/v2/content/posts/2023/derez/index.md b/v2/content/posts/2023/derez/index.md new file mode 100644 index 0000000..556cb16 --- /dev/null +++ b/v2/content/posts/2023/derez/index.md @@ -0,0 +1,182 @@ ++++ +title = "How to use DeRez" +date = 2023-03-20T12:44:38+10:00 + +#[extra] +#updated = 2023-03-01T21:54:06+10:00 ++++ + +After my post on trying to run +[Rust on Classic Mac OS post](@/posts/2023/rust-on-ppc-classic-mac-os/index.md) I continued trying to +find a modern language that I can use to build classic Mac OS software. I've +had some success with [Nim] and built a little +[temperature converter application][nim-temp-src]. As part of this I wanted to be able to use +[ResEdit] to edit the layout of the dialog. The problem was that I need a way +to convert the modified resources back into the textual representation used in +the source code. In this post I describe how I did this with `DeRez`. + + + +{{ video(video="posts/2023/derez/mac-nim-temp.mp4", height=227, poster="png", preload="auto", alt="Video of the temperature converter application.", caption="Video of the temperature converter application.") }} + +To build the temperature converter I started with the [Dialog sample] from +[Retro68], which looks like this: + +{{ figure(image="posts/2023/derez/Dialog.png", link="posts/2023/derez/Dialog.png", pixelated=true, alt="TODO", caption="Dialog Sample") }} + +I opened it up in ResEdit and edited the `DITL` (Dialog Template) resource to +add the icon and temperature fields. I also added a new `ICON` resource and +drew a little thermometer: + +{{ figure(image="posts/2023/derez/DITL.png", link="posts/2023/derez/DITL.png", pixelated=true, alt="Screenshot of the ResEdit DITL editor editing the DITL resource for my temperature converter.", caption="Editing DITL resource in ResEdit") }} + +With the changes made, I now wanted to convert the binary resources stored in +the resource fork back into the [textual format used in the source code][dialog.r]. +I believe the format is called `Rez`, here's a snippet of it: + +``` +resource 'DITL' (128) { + { + { 190-10-20, 320-10-80, 190-10, 320-10 }, + Button { enabled, "Quit" }; + + { 190-10-20-5, 320-10-80-5, 190-10+5, 320-10+5 }, + UserItem { enabled }; + + { 10, 10, 30, 310 }, + StaticText { enabled, "Static Text Item" }; + + { 40, 10, 56, 310 }, + EditText { enabled, "Edit Text Item" }; + + { 70, 10, 86, 310 }, + CheckBox { enabled, "Check Box" }; + + { 90, 10, 106, 310 }, + RadioButton { enabled, "Radio 1" }; + + { 110, 10, 126, 310 }, + RadioButton { enabled, "Radio 2" }; + } +}; +``` + +This turned out to be a bit of journey and the motivation for this blog post. +As part of the [Macintosh Programmers Workshop][mpw] (MPW) theres is a tool +called `DeRez` that does what I want. First up I had to work out how to operate +MPW. It's an editable shell where you run commands with ⌘-Return. Once I worked +that out I could run `DeRez` on my edited application but I only got the +fullback hexadecimal representation of the resources, not the structured output +I wanted: + +``` +data 'DITL' (128) { + $"0007 0000 0000 00A0 00E6 00B4 0136 0404" /* ....... .æ.´.6.. */ + $"5175 6974 0000 0000 009B 00E1 00B9 013B" /* Quit.....›.á.¹.; */ + $"0000 0000 0000 0046 000A 005A 0136 0808" /* .......F...Z.6.. */ + $"4865 6C6C 6F20 5E30 0000 0000 001E 000A" /* Hello ^0........ */ + $"003E 002A A002 0597 0000 0000 0014 0032" /* .>.* ..—.......2 */ + $"0024 007D 8807 4365 6C73 6975 7300 0000" /* .$.}ˆ.Celsius... */ + $"0000 0014 00AA 0024 00F5 8809 4661 7265" /* .....ª.$.õˆÆFare */ + $"6E68 6569 7400 0000 0000 0029 0036 0039" /* nheit......).6.9 */ + $"0081 1009 4564 6974 2054 6578 7400 0000" /* ..ÆEdit Text... */ + $"0000 002B 00AE 003B 00F9 1009 4564 6974" /* ...+.®.;.ù.ÆEdit */ + $"2054 6578 7400" /* Text. */ +}; +``` + +`Help DeRez` in MPW didn't shed much light on the problem but after a lot of +searching online I eventually found some extra details in the [man page for +`DeRez`][DeRez man] shipped on Mac OS X. Specifically: + +> The type declarations for the standard +> Macintosh resources are contained in the `Carbon.r` resource header file, +> contained in the Carbon framework. You may use the ${RIncludes} shell +> environment variable to define a default path to resource header files. +> If you do not specify any type declaration files, `DeRez` produces data +> statements in hexadecimal form. + +and + +> You can also specify resource description +> files containing type declarations. For each type declaration file on +> the command line, DeRez applies the following search rules: +> +> 1. DeRez tries to open the file with the name specified as is. +> +> 2. If rule 1 fails and the filename contains no colons or begins with a +> colon, DeRez appends the filename to each of the pathnames specified by +> the {RIncludes} environment variable and tries to open the file. + +With this information I was able to construct a command that worked: + + +``` +DeRez -i 'Macintosh HD:MPW-GM:Interfaces&Libraries:Interfaces:RIncludes:' "Macintosh HD:Retro68:Retro68App" Carbon.r +``` + +`-i` sets the include path for type declarations and `Carbon.r` tells it to use +that file for resource descriptions. Running the command I was now rewarded +with textual resources: + +{{ figure(image="posts/2023/derez/MPW.png", link="posts/2023/derez/MPW.png", pixelated=true, alt="TODO", caption="DeRez output in MPW") }} + +To get the text out of the VM I copied and pasted it into a new document in +[BBEdit] (version 5.0) and saved it with Unix line endings to the Unix folder +that [SheepShaver] shares with the host and with that I was able to update the +[resource file in my temperature converter project][my dialog.r]. + +### Honorable Mention + +Whilst trying to work out how to do all this I was also reminded of Ninji's +[mpw-emu] project ([detailed write-up on their blog][mpw-emu-blog]). It +combines an emulator with implementations of library functions in order to be +able to run MPW tools directly (outside a Mac OS emulator). It has gained +support for `DeRez` so you can run `DeRez` directly on a host system like +Linux. + +I [MacBinaried][MacBinary] `DeRez` in SheepShaver and copied it to my Linux host. Then with a bit +of fussing with `mpw-emu` Rust code I was able to run it: + +``` +$ mpw-emu ~/Documents/Classic\ Mac/Shared\ 2/DeRez.bin +[2023-03-20T02:11:07Z ERROR emulator] Unimplemented call to InterfaceLib::SetFScaleDisable @10012C6C +[2023-03-20T02:11:07Z ERROR stdio] Unimplemented format character: P +[2023-03-20T02:11:07Z ERROR emulator] Unimplemented call to InterfaceLib::SecondsToDate @1000B2A4 +### /home/wmoore/Documents/Classic Mac/Shared 2/DeRez.bin - No filename to de-compile was specified. +### /home/wmoore/Documents/Classic Mac/Shared 2/DeRez.bin - Usage: /home/wmoore/Documents/Classic Mac/Shared 2/DeRez.bin resourceFile [-c] [-d name[=value]] [-e] [-i path] [-m n] [-noResolve [output | include]] [-only type[(id[:id])]] [-p] [-rd] [-s type[(id[:id])]] [-script japanese | tradChinese | simpChinese | korean] [-u name] [file…]. +``` + +Amazing! + +Unfortunately I don't think `DeRez` will work this way outside a macOS host. It +needs to be able to read the resource fork of the application I edited with +ResEdit and that is not preserved on Linux: + +``` +$ mpw-emu ~/Documents/Classic\ Mac/Shared\ 2/DeRez.bin Dialog.APPL +[2023-03-20T02:14:05Z ERROR emulator] Unimplemented call to InterfaceLib::SetFScaleDisable @10012C6C +[2023-03-20T02:14:05Z ERROR stdio] Unimplemented format character: P +[2023-03-20T02:14:05Z ERROR emulator] Unimplemented call to InterfaceLib::SecondsToDate @1000B2A4 +### /home/wmoore/Documents/Classic Mac/Shared 2/DeRez.bin - The resource fork of "Dialog.APPL" is empty and uninitialized. +``` + +If you're on macOS I think that this would actually work. Although now I think +about it Xcode ships (or at least used to) a native version of `DeRez` so now +I'm not sure what Ninji's motivation for making it work in `mpw-emu` was. +Perhaps it is possible to use on Linux somehow... + +[Nim]: https://nim-lang.org/ +[ResEdit]: https://en.wikipedia.org/wiki/ResEdit +[Retro68]: https://github.com/autc04/Retro68 +[Dialog sample]: https://github.com/autc04/Retro68/tree/5f882506013a0a8a4335350197a1b7c91763494e/Samples/Dialog +[dialog.r]: https://github.com/autc04/Retro68/blob/5f882506013a0a8a4335350197a1b7c91763494e/Samples/Dialog/dialog.r +[DeRez man]: https://www.manpagez.com/man/1/DeRez/ +[BBEdit]: http://www.barebones.com/products/bbedit/index.html +[SheepShaver]: https://sheepshaver.cebix.net/ +[my dialog.r]: https://github.com/wezm/classic-mac-nim/blob/39e6ed7c2b31c20b775782319cde8ae5a43e1512/dialog.r +[mpw-emu]: https://github.com/Treeki/mpw-emu +[mpw-emu-blog]: https://wuffs.org/blog/emulating-mac-compilers +[mpw]: https://en.wikipedia.org/wiki/Macintosh_Programmer%27s_Workshop +[MacBinary]: https://en.wikipedia.org/wiki/MacBinary +[nim-temp-src]: https://github.com/wezm/classic-mac-nim/tree/39e6ed7c2b31c20b775782319cde8ae5a43e1512 diff --git a/v2/content/posts/2023/derez/mac-nim-temp.mp4 b/v2/content/posts/2023/derez/mac-nim-temp.mp4 new file mode 100644 index 0000000..6b74beb Binary files /dev/null and b/v2/content/posts/2023/derez/mac-nim-temp.mp4 differ diff --git a/v2/content/posts/2023/derez/mac-nim-temp.png b/v2/content/posts/2023/derez/mac-nim-temp.png new file mode 100644 index 0000000..6c6406e Binary files /dev/null and b/v2/content/posts/2023/derez/mac-nim-temp.png differ diff --git a/v2/sass/screen.scss b/v2/sass/screen.scss index 13ba41a..3418ba2 100644 --- a/v2/sass/screen.scss +++ b/v2/sass/screen.scss @@ -183,6 +183,9 @@ figure { .figure-border img { border: 1px solid #AAA; } +.figure-pixelated img { + image-rendering: pixelated; +} figcaption { font-size: 16px; font-weight: 500; diff --git a/v2/templates/shortcodes/figure.html b/v2/templates/shortcodes/figure.html index b862396..c8044e2 100644 --- a/v2/templates/shortcodes/figure.html +++ b/v2/templates/shortcodes/figure.html @@ -1,8 +1,11 @@ +{% set figure_class = ["text-center"] %} {% if border %} -
-{% else %} -
+ {% set figure_class = figure_class | concat(with="figure-border") %} {% endif %} +{% if pixelated %} + {% set figure_class = figure_class | concat(with="figure-pixelated") %} +{% endif %} +
{% if resize_width %} {% set image = resize_image(path=image, width=resize_width, op="fit_width", quality=quality | default(value=75)) %} diff --git a/v2/templates/shortcodes/video.html b/v2/templates/shortcodes/video.html index 56c187e..c28941d 100644 --- a/v2/templates/shortcodes/video.html +++ b/v2/templates/shortcodes/video.html @@ -1,4 +1,13 @@ +{% if poster %} +{% else %} + {% set poster = "jpg" %} +{% endif %} +{% if preload %} +{% else %} + {% set preload = "none" %} +{% endif %} +
- +
{{ caption }}