Add DeRez post

This commit is contained in:
Wesley Moore 2023-03-20 15:21:36 +10:00
parent b00ee88e86
commit ef87a7283c
No known key found for this signature in database
10 changed files with 201 additions and 17 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View file

@ -1,13 +0,0 @@
+++
title = "How to use DeRez"
date = 2023-03-19T19:09:53+10:00
#[extra]
#updated = 2023-03-01T21:54:06+10:00
+++
As part of my efforts to use a modern programming language to write classic Mac OS
software
<!-- more -->

View file

@ -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`.
<!-- more -->
{{ 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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -183,6 +183,9 @@ figure {
.figure-border img { .figure-border img {
border: 1px solid #AAA; border: 1px solid #AAA;
} }
.figure-pixelated img {
image-rendering: pixelated;
}
figcaption { figcaption {
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;

View file

@ -1,8 +1,11 @@
{% set figure_class = ["text-center"] %}
{% if border %} {% if border %}
<figure class="text-center figure-border"> {% set figure_class = figure_class | concat(with="figure-border") %}
{% else %}
<figure class="text-center">
{% endif %} {% endif %}
{% if pixelated %}
{% set figure_class = figure_class | concat(with="figure-pixelated") %}
{% endif %}
<figure class="{{ figure_class | join(sep=" ") }}">
<a href="{{ config.base_url }}/{{ link }}"> <a href="{{ config.base_url }}/{{ link }}">
{% if resize_width %} {% if resize_width %}
{% set image = resize_image(path=image, width=resize_width, op="fit_width", quality=quality | default(value=75)) %} {% set image = resize_image(path=image, width=resize_width, op="fit_width", quality=quality | default(value=75)) %}

View file

@ -1,4 +1,13 @@
{% if poster %}
{% else %}
{% set poster = "jpg" %}
{% endif %}
{% if preload %}
{% else %}
{% set preload = "none" %}
{% endif %}
<figure class="text-center"> <figure class="text-center">
<video controls preload="none" src="{{ config.base_url }}/{{ video }}" poster="{{ config.base_url }}/{{ video }}.jpg" style="max-height: {{ height }}px"></video> <video controls preload="{{ preload }}" src="{{ config.base_url }}/{{ video }}" poster="{{ config.base_url }}/{{ video }}.{{ poster }}" style="max-height: {{ height }}px"></video>
<figcaption>{{ caption }}</figcaption> <figcaption>{{ caption }}</figcaption>
</figure> </figure>