{"id":40809,"date":"2023-10-17T11:05:43","date_gmt":"2023-10-17T15:05:43","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=40809"},"modified":"2023-10-17T11:05:43","modified_gmt":"2023-10-17T15:05:43","slug":"building-a-classic-mac-os-app-in-rust","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2023\/10\/17\/building-a-classic-mac-os-app-in-rust\/","title":{"rendered":"Building a Classic Mac OS App in Rust"},"content":{"rendered":"<p><a href=\"https:\/\/www.wezm.net\/v2\/posts\/2023\/rust-classic-mac-os-app\/\">Wesley Moore<\/a>:<\/p>\n<blockquote cite=\"https:\/\/www.wezm.net\/v2\/posts\/2023\/rust-classic-mac-os-app\/\">\n<p>The first challenge was finding a decent specification for the three versions\nof MacBinary. I was eventually I was able to dig up the following:<\/p>\n<ul>\n<li><a href=\"https:\/\/web.archive.org\/web\/20050307030202\/http:\/\/www.lazerware.com\/formats\/macbinary\/macbinary.html\">MacBinary I<\/a><\/li>\n<li><a href=\"https:\/\/web.archive.org\/web\/20050305042909\/http:\/\/www.lazerware.com\/formats\/macbinary\/macbinary_ii.html\">MacBinary II<\/a><\/li>\n<li><a href=\"https:\/\/web.archive.org\/web\/20050305044255\/http:\/\/www.lazerware.com\/formats\/macbinary\/macbinary_iii.html\">MacBinary III<\/a><\/li>\n<\/ul>\n<p>I then set about building the parser. I reused the binary parser code from\n<a href=\"https:\/\/github.com\/yeslogic\/allsorts\">Allsorts<\/a> since I was already familiar with that code. I hit another roadblock\nwhen it came to the CRC in the header. Nothing describes the actual CRC\nalgorithm used. I tried the CRC reversing tool <a href=\"https:\/\/reveng.sourceforge.io\/\">CRC RevEng<\/a> without\nsuccess. A lot of existing code seemed to use an implementation that originated\nin a late 80&rsquo;s UNIX utility, <a href=\"https:\/\/web.mit.edu\/~mkgray\/jik\/sipbsrc\/src\/mcvert\/mcvert.c\">mcvert<\/a>, that has unclear licensing. I wanted to\nuse the Rust <a href=\"https:\/\/lib.rs\/crates\/crc\">crc crate<\/a> instead.<\/p>\n<p>[&#8230;]<\/p>\n<p>Due to its heritage most of the Mac OS toolbox functions use the Pascal calling\nconvention, <a href=\"https:\/\/github.com\/llvm\/llvm-project\/blob\/bd20a344bbf813b2c39b57ad1a5248bff915ce25\/clang\/lib\/CodeGen\/CGCall.cpp#L60\">which LLVM does not support<\/a>. To bridge the C (and\nRust) world to this Pascal world I had to create <a href=\"https:\/\/en.wikipedia.org\/wiki\/Trampoline_(computing)\">trampoline functions<\/a> in C\nfor each toolbox function that I wanted to call from Rust[&#8230;]<\/p>\n<p>[&#8230;]<\/p>\n<p>I used the &ldquo;Downloading a URL With HTTP&rdquo; example from the <a href=\"https:\/\/developer.apple.com\/library\/archive\/documentation\/mac\/NetworkingOT\/NetworkingOpenTransport.pdf\">Networking With Open Transport<\/a>\nbook as a guide for the functions I needed.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/10\/11\/rescuing-files-from-classic-mac-os-with-swift\/\">Rescuing Files From Classic Mac OS...with Swift<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Wesley Moore: The first challenge was finding a decent specification for the three versions of MacBinary. I was eventually I was able to dig up the following: MacBinary I MacBinary II MacBinary III I then set about building the parser. I reused the binary parser code from Allsorts since I was already familiar with that [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2023-10-17T15:05:46Z","apple_news_api_id":"79b50a54-6e38-4ae3-bc85-244ebdc2c530","apple_news_api_modified_at":"2023-10-17T15:05:46Z","apple_news_api_revision":"AAAAAAAAAAD\/\/\/\/\/\/\/\/\/\/w==","apple_news_api_share_url":"https:\/\/apple.news\/AebUKVG44SuO8hSROvcLFMA","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[733,30,923,270,330,759,408,1231],"class_list":["post-40809","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-emulator","tag-mac","tag-mac-os-8","tag-parser","tag-pascal","tag-resource-fork","tag-rust-lang","tag-webassembly"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/40809","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=40809"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/40809\/revisions"}],"predecessor-version":[{"id":40810,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/40809\/revisions\/40810"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=40809"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=40809"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=40809"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}