stella-emu / stella

A multi-platform Atari 2600 Emulator
https://stella-emu.github.io
GNU General Public License v2.0
609 stars 112 forks source link

MacOS arguments passed to app #649

Open andrew-davie opened 4 years ago

andrew-davie commented 4 years ago

This is a bit bizarre, and probably an error on my part. So I'm using MacOS and I wanted to pass arguments to stella.app via command line instantiation. So here's what I had...

open -a /Applications/Stella.app ./BoulderDash3E+.bin --args -rd B -ld A

This was working (or appeared to be) for quite some time (weeks). But recently I found the stella debugger was failing in that it could not associate labels with addresses. In the screenshot you see that I've done a reset, but instead of showing F000 as the reset address (in the disassembly) it starts at 5000. And of course none of the labels are there. No idea where that 5000 came from.

Screen Shot 2020-06-02 at 7 18 11 pm

In any case, if I change the run command to this...

open -a /Applications/Stella.app ./BoulderDash3E+.bin

... then it all works just as expected. Reset address disassembly F000, and the symbols are present. I expect, as I said, I'm the cause of this but thought it worth reporting. I'm attaching the relevant binary/symbol files in case needed.

BD.zip

Summary: with the "arguments" added to the open command for Stella, disassembly fails with incorrect PC address shown.

sa666666 commented 4 years ago

The 'open' command seems to be somewhat borked in Catalina at least. The following doesn't work: open src/macos/DerivedData/Build/Products/Release/Stella.app/ --args -help

while using the application directly is fine: src/macos/DerivedData/Build/Products/Release/Stella.app/Contents/MacOS/Stella -help

To me, this says that Stella is correctly processing the commandline (the second case), but that open isn't properly passing the argument (first case).

andrew-davie commented 4 years ago

Would be handy to see what exactly Stella is "seeing" when arguments are passed this way. I don't really have the nous how to check this, though.

andrew-davie commented 4 years ago

Also, that trailing "/" in the first example... seems a bit odd.

andrew-davie commented 4 years ago

Here is my functional solution - this is what my makefile has to get everything working on MacOS...

osascript -e 'quit app "Stella"'
/Applications/Stella.app/Contents/MacOS/Stella ./BoulderDash3E+.bin -rd B -ld A &
osascript -e 'tell application "stella" to activate'

First, kill previous stella instance, if any Next, run as advised above, with arguments as required. Note the & on the end - this runs as a background task. Why? Because it otherwise waits at that point for stella to exit, which is not what we want. Next, bring stella to the foreground of the GUI. Otherwise it's hidden in the background.

This seems to be working for me. Sharing in case others have the same problem.

thrust26 commented 4 years ago

I find it strange, that Stella seems to load the .lst and .sym files but somehow fails when parsing them.

andrew-davie commented 4 years ago

I find it strange, that Stella seems to load the .lst and .sym files but somehow fails when parsing them.

Yes I agree and noticed that too. That's why I'd love to see the command line arguments that Stella is getting. What is causing it to "mangle" the disassembly to 5000?

thrust26 commented 4 years ago

I think somehow the parsing of the files fails, not the parsing of the command line.

sa666666 commented 4 years ago

It's easy enough to see the args that Stella gets. In src/common/main.cxx, right after the line parseCommandLine(ac, av, globalOpts, localOpts);, it has generated two maps: globalOpts and localOpts. You can walk through these two maps to see everything that Stella sees.

sa666666 commented 4 years ago

I added the following code below the line in the last message:

cerr << "GLOBAL\n";
for(const auto& i: globalOpts)
  cerr << "  " << i.first << " -> " << i.second << endl;
cerr << "LOCAL\n";
for(const auto& i: localOpts)
  cerr << "  " << i.first << " -> " << i.second << endl;

When I run Stella with ./Stella.app/Contents/MacOS/Stella -help, I get the following output:

GLOBAL
LOCAL
  ROMFILE ->
  help -> 1

... (plus all the help text) ...

So that shows the 'help' commandline argument is being received by Stella, and set to '1'.

When I run with open Stella.app --args -help, I don't get any output. Stella doesn't even start and enter main. So again, it's something related to open.

andrew-davie commented 4 years ago

When I run with open Stella.app --args -help, I don't get any output. Stella doesn't even start and enter main. So again, it's something related to open.

To be clear, you're saying stella doesn't run at all when you do this? Because, if so, you're doing it wrong. The open command definitely opens stella. I think you're missing the '-a' parameter...?

open -a Stella.app --args -help

andrew-davie commented 4 years ago

I added your code and tested. No output. Nonetheless, I do not believe "open" to be so broken that --args is not passed as documented. Something else is happening.

andrew-davie commented 4 years ago

A bit of a clue that something is happening, albeit strange. This will not open stella...

open -a Stella.app --args -help

This will open stella...

open -a Stella.app --args -helq

Again, no output though.

andrew-davie commented 4 years ago

... and now after rebuilding with XCODE and with the diagnostic code you posted -- even though I am not getting any output to the terminal window, it is all working properly.

That is,

open -a /Applications/Stella.app ./BoulderDash3E+.bin --args -rd B -ld A

is now working once again. Symbols are OK. Everything is OK. Bizarre.

DirtyHairy commented 4 years ago

The issue is not the open command, but rather different code paths that are taken depending on the way the application is called. Please check out https://github.com/stella-emu/stella/blob/79a12351ce9551953131a8575f302035e2548512/src/macos/SDLMain.m#L62

If Stella is called from the command line or by simply opening it, we pass argv and argc unmodified from the main() entrypoint to stellaMain.

If a file is opened from the GUI (or with open it seems), a Cocoa application is signalled for each file by calling a method on the application delegate for each file. We track the last file in the bunch and then later fudge the command line arguments for stellaMain, ignoring any original command line argument. This is the portion of code I linked above.

I think we should revise this at some point, but to do this properly, we first need to do research on the way MacOS handles this process on different OS versions. In the meantime, if you want to call Stella from the command line, I think the best way is to call the binary in the bundle directly (Stella.app/MacOS/Stella). If you install Stella with homebrew, you'll get a symlink in /usr/local/bin to the binary for free 😏