jorio / Nanosaur

Nanosaur source port 🦖
https://pangeasoft.net/nano
Other
371 stars 23 forks source link

How do .rsrc work? #3

Closed fordcars closed 3 years ago

fordcars commented 3 years ago

Hi,

I've recently fell upon your repo, and wow! Coincidentally, I am working on the exact same concept; porting Nanosaur to modern systems. My approach is considerably more crude, having no intention of publicly publishing it, but I am super glad to see somebody else having done this, and in a much cleaner way.

I had a question; I've spent a lot of time on writing tools for reading data stored in those .rsrc files (resource fork on HFS+ filesystems) and I was curious how your port dealt with resource files? Does Quesa support .rsrc files directly? And what about those pesky sound effects stored in those .rsrc (See Main.sounds.rsrc)?

Thank you so much for your time!

jorio commented 3 years ago

Hi!

Happy to talk about the technical challenges of this port, maybe I should write a proper post-mortem eventually! So, here's what I did with the resource forks. I had two options when I started working on Nanosaur:

I went with the second alternative, because my ultimate goal was to come up with a framework to port other Classic Mac games (Pomme). And I gotta admit I enjoy the spelunking :)

How to obtain the .rsrc files: I took the latest classic version of the game floating around, nanosaur134.bin. I extracted that with unar, explicitly telling it to keep the resource forks for every file and store them in separate AppleDouble files — those are the .rsrc files you're seeing. AppleDouble is basically a simple wrapper designed to concatenate arbitrary forks in a data file. In practice, they just contain a resource fork. Tidbit: AppleDouble is still in use today in macOS's built-in file zipper — if you've ever received a zip file from a Mac user and it contains a folder named __MACOSX when you extract it on Windows or Linux, that's where the resource forks are stored as AppleDouble.

How to deal with the .rsrc files: I wrote a compatibility layer called "Pomme" that implements old Mac APIs so I wouldn't need to modify too much of the game's original code. One of Pomme's jobs is to deal with the resource forks transparently. For example, when the game calls FSpOpenResFile, Pomme will parse the resource file and load in the resource map. Once that's done, the game can ask for any resource it likes and Pomme will fetch it from the file. You can find out more about the resource fork format by looking at how FSpOpenResFile is implemented in Resources.cpp. I also recommend reading the relevant sections of "More Macintosh Toolbox", it's been helpful to me.

About the old formats themselves (PICT, snd...): Pomme has parsers for all graphics and sound formats in use by the game (except 3DMF, which is handled by Quesa). These are a bit messy, since they're not really "file formats" inasmuch as they are series of commands that drive the graphics or sound managers of the Mac Toolbox. For example, PICTs are actually a series of QuickDraw 2D opcodes, and 'snd 's are actually a series of commands for the Sound Manager. So, there's a lot of boilerplate code to get to the specific opcodes we're interested in before we can get to the sound/pixel data itself. If you're interested, I recommend you look at PICT.cpp and SoundManager.cpp

One last thing: if you're working on your own port of Nano, may I point you to my fork of Quesa instead of the upstream version for the time being. It might save you some time — there were some issues specific to Nanosaur that I've ironed out in my version of Quesa. Good luck and have fun! :)

fordcars commented 3 years ago

Hi,

I have to say, Pomme looks amazing. I'm thoroughly impressed on how you've implemented so many features of the classic Macintosh Toolbox. When thinking of porting Nanosaur to modern systems, I never considered implementing Macintosh Toolbox API elements, because the task looked quite daunting to me. Seeing Pomme definitely gives hope of porting other games in the future that relied on the Macintosh Toolbox, which is super exciting!

For my port, I had instead chosen to use a little game engine I had written a while back, converting the resources one by one beforehand so my game engine could handle them correctly. This involved using a slightly obscure tool (AccuTrans 3D) to convert 3DMF files to .obj, aswell as writing a resource extractor and a 'snd ' converter. As you can imagine, this labor is quite exhausting, and is not a very clean solution ;)

I will definitely be keeping Pomme in sight for the rest of my little Nano port, aswell as future projects!

Thank you very much for your detailed post!