Mac OS 9 Lives

Classic Mac OS Software => Hacking the System, Mac OS 9.3, and Beyond ! => Topic started by: classicmacreborn7 on January 06, 2019, 06:43:54 PM

Title: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: classicmacreborn7 on January 06, 2019, 06:43:54 PM
I've been working on this project for about a week.  Burying my head for countless hours in Inside Macintosh.

The ultimate goal is to build an OS9 emulator wrapper which is so seamless that the user is not even aware (or at least not reminded) that they are using an emulator.

One of the first challenges is getting the application to load at boot and the OS to shut down when the application is quit.  Of course, you could use Startup Items or AppleScript to load the application, but there are a number of huge problems with this:

- When the application quits, it goes back to the OS9 desktop instead of shutting down and closing the emulator.
- Startup Items is notorious for breaking aliases and destabilizing the wrap.
- The user can select the Finder from the top menu and get access to the desktop, which kills the seamless experience.
- Boot time is longer when the Finder has to launch.
- You can use an AppleScript to check if the application is running and issue a shutdown command to Finder if it has been closed, but sometimes Finder ignores it or displays an alert if there are applications running.

The best solution is to replace the Finder with the desired application.  This keeps the application as the only thing that can be run by the user after the emulator is launched.  It's also a lot more reliable.  However, the app will not quit or shut down the OS when you select a quit option or press Cmd-Q.

The best way to fix this is with a custom Finder that launches the application and issues a shutdown call when it has been closed.  Since most scripts rely on the Finder to launch an application or shut down, the only solution is to build a Finder from scratch that directly calls the Toolbox.

Right now, I have it working in MPW script- which of course requires ToolServer (sigh), but I'm implementing it in C++.  Shutdown works, but I'm still trying to get LaunchApplication from the processes interface working.  LaunchApplication is a bit of a headache lol.
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: ELN on January 07, 2019, 12:58:27 AM
I have had some success with a similar problem that I encountered when building some code with MPW. I wanted to produce disk images that would start up, run an MPW script (or run interactively), then shut down when MPW quit.

In the end I cheated by bin-patching the ExitToShell code in one of the Process Manager ‘scod’ resources. It issues a ShutDwnPower call. Unfortunately a different patch would be required for the native Process Manager in Mac OS 9.

Sounds like a cool project. Good luck!
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: classicmacreborn7 on January 07, 2019, 01:09:39 AM
Hah that's a really good idea actually.  Right now I have it set up to constantly call the Process Manager for IDs to check if the application is running and then call ShutDwnPower.  But having ExitToShell always issue a shut down call would eliminate the need for an endless loop running in the background.  It would also be more reliable- as I know for sure that when the application is quit it will issue a shut down call 100% of the time and not wait for some next iteration of a loop.  The only disadvantage would be that it would lose the portability for a drag-and-drop finder.

I wonder if there's a way to change the ExitToShell routine at runtime.  Probably not, but worth looking into.
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: ELN on January 07, 2019, 03:10:14 AM
It would be tempting to patch the ExitToShell (A9F4) trap using an INIT. Unfortunately, INIT code runs before the Process Manager loads, so your patch wouldn’t do anything.

I can think of one other way. Patch the SetOSTrapAddress routine, which the Process Manager uses to set the address of its ExitToShell routine. Your patch should check for when ExitToShell is patched, and in turn apply its own patch to ExitToShell. Complicated but doable, and I would be happy to help out.
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: classicmacreborn7 on January 07, 2019, 02:33:23 PM
That would be really cool actually.  I put it on GitHub and added you to contributors if you want:
https://github.com/classicmacreborn/WrapperFinder
(I knew your GitHub from someone else's post about BuildCubeE)

I've just managed to get LaunchApplication working.  I spent so long just figuring out that you have to convert strings to Pascal-style strings in order to pass them to functions in the C interfaces lol.  It works perfectly when launched as an application, but when it runs as a Finder it crashes the OS immediately after boot.  I'm guessing there's some services that haven't been launched yet when it tries to launch the application.

I looked into the Trap Manager documentation.  It's awesome that you can patch routines at runtime.  It would be way better to do it this way than to run an infinite loop.  This would also allow the Finder to be exited after the application is launched and still have the app shut down the machine when it is quit- meaning no finder in the menu.  Also, if it's a head patch then it won't display the desktop AT ALL when the application is quit.  So much more seamlessness.  8) 8) 8) 8)

I don't seem to be nearly as versed as you in OS9 traps yet.  This is going to be awesome to learn though.  There's a lot of potential projects I could make utilizing patching at runtime.  Of course, any help is greatly appreciated.
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: ELN on January 08, 2019, 08:13:12 PM
It sounds like this overall project needs both a startup-time component and a run-time component to work properly. A system extension might be able to provide both of these, if in addition to patching ExitToShell it also patches SysTask. Thoughts?

I am not well versed in CodeWarrior so working on your repo might be a struggle. But I can cook up an ExitToShell-patching INIT resource (would use BuildCubeE), if you think that would be a good start?
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: classicmacreborn7 on January 09, 2019, 01:47:15 PM
Hmm.. let me see if I can get BuildCubeE working on my end so we can work in the same repo.  Otherwise we'll just be building two separate systems  :(
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: Daniel on January 09, 2019, 02:19:38 PM
Looking at the CubeE Process Manager (which may or may not use the same algorithm as the PowerPC Process Manager), the Finder is relaunched by getting it's filename from the FinderName global. If the first Finder App changes FinderName to point to a shutdown App, then the next time the "Finder" is relaunched, it will relaunch that App instead.

FinderName starts at 0x2E0 and is a 16-byte Pascal string. The boot code sets it using BlockMove().
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: classicmacreborn7 on January 09, 2019, 03:53:31 PM
I could use some help getting BuildCubeE running.

I've got machfs set up, I've got vMac set up.  I switched the Codewarrior project over to MPW.  I'm sure I'm using BuildCubeE improperly, but here is the command I'm using and the error I'm getting:

Code: [Select]
Macbooks-MBP-8:BuildCubeE macbook$ ./Build -e src/vmac -v src/WrapperFinder.cp -c "BuildProgram WrapperFinder"
Copying source tree
Traceback (most recent call last):
  File "./Build", line 88, in <module>
    shutil.rmtree(treedest)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 513, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 374, in _rmtree_unsafe
    onerror(os.scandir, path, sys.exc_info())
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 371, in _rmtree_unsafe
    with os.scandir(path) as scandir_it:
NotADirectoryError: [Errno 20] Not a directory: 'src/WrapperFinder.cp/BuildImage'
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: Daniel on January 09, 2019, 04:10:04 PM
Set the source to the directory your sources are in, not the source file itself.

You may have to create .idump files for each file you have. WrapperFinder.cp.idump should consist of the string "TEXTMPS ", as should every other text file you are using.
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: classicmacreborn7 on January 09, 2019, 05:47:37 PM
Ah thanks.. that was pretty obvious *slaps forehead*.  I also had to point it directly to the executable instead of the .app package.  It seems to be launching vMac now.  It complains that the version of MPW only works with a 68020 processor or later, so I'll have to find another romfile..  I'll keep working on it.

Thanks for all your guys' help.
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: ELN on January 09, 2019, 06:19:07 PM
Ooh, MPW compatibility with CPUs is something I hadn’t thought of! Sorry it’s gotten under your skin :/. A Mac II build of Mini vMac should be fine. Basilisk II also works, but you need to wrap it in a shell script because it does not treat its command line arguments as disk image paths. I might actually submit a patch to change this, if I can ever figure out how to build it.

Ultimately, I think BuildCubeE will need to offer a small handful of System/MPW versions that are carefully tuned to boot everything from a Plus to a G4. Classic Mac emulators can be thought of as a precious and limited resource, to be used to their maximum potential.
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: classicmacreborn7 on January 09, 2019, 07:05:07 PM
Hah it works!

This is really cool!  I just got MPW's output on my host OS terminal  8)

It actually wasn't BuildCubeE that was giving me a headache (it was super easy to set up).  It was because I had to have a special build of vMac that runs Mac II roms.  Anyways, now that I got it working I'll get the MPW Makefile.  Also, I think the CtoPstr function that converts C strings in Pascal-style strings doesn't work in MPW, so I'll have to find a replacement.  Or probably just write a replacement function.

So cool that this actually builds a classic mac compatible HFS image.  Love it!
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: ELN on January 09, 2019, 07:37:39 PM
I’m glad to see it being useful! You might come to hate me for foisting MPW on you, though. I plan to extend machfs and BuildCubeE in the future, but the .idump and .rdump formats will remain compatible. (By the way, remember that files with a TEXT type will have their LF/CR line endings inverted.)
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: classicmacreborn7 on January 09, 2019, 08:55:21 PM
It actually doesn't make a huge difference to me whether it's Codewarrior or MPW.  But I'd much rather be able to write code in the host OS than in emulation.  It seems like BuildCubeE will theoretically work in any emulator.  I'm guessing it saves the MPW output to a file which is then read by BuildCubeE and displayed in the host terminal.  I've thought about having a system like this for a while but it looks like you've pretty much already completed it.  Maybe some day I'd like to integrate the MPW references into a host-side IDE.  Project for another time.

Anyways, back to coding, thanks for building this...
Title: Re: WrapperFinder - A Replacement Finder for OS9 App Ports
Post by: ELN on January 10, 2019, 03:41:14 AM
Good luck! In a while, I’ll see what I can do about an INIT. By the way, this was my first attempt at such a system: https://github.com/elliotnunn/empw. Still in use, and I will maintain it.