barotto / IBMulator

The IBM PS/1 emulator.
https://barotto.github.io/IBMulator
GNU General Public License v3.0
111 stars 4 forks source link

Running symlinked binary results in error: Cannot find the assets #61

Closed andornaut closed 3 years ago

andornaut commented 3 years ago

Steps to reproduce

  1. Download and unzip PS1_2011_ROM_US.zip into /opt/ibmps1/roms/2011
  2. Install ibmulator v0.12 release to /opt/ibmps1/ibmulator
  3. Symlink binary: sudo ln -s /opt/ibmps1/ibmulator/bin/ibmulator /usr/local/bin/
  4. Run ibmulator, exit
  5. Edit ~/.config/ibmulator/ibmulator.ini, set: romset=/opt/ibmps1/roms/2011/FC0000.BIN
  6. Run ibmulator

Expected results

IBMulator starts successfully

Actual results

$ ibmulator 
[INF0] prg | IBMulator 0.12 started
[ERR0] prg | Cannot find the assets!
[INF0] prg | Program stop

or

$ /usr/local/bin/ibmulator 
[INF0] prg | IBMulator 0.12 started
[ERR0] prg | Cannot find the assets!
[INF0] prg | Program stop

Observations

Running the binary directly (not via a symlink) works as expected:

$ /opt/ibmps1/ibmulator/bin/ibmulator 
[INF0] prg | IBMulator 0.12 started
[INF0] prg | Calibrating...
[INF0] prg | This system has high precision timing. Impressive, very nice.
[INF0] mch | Loading ROM file '/opt/ibmps1/roms/2011/FC0000.BIN'
[...]

Environment

IBMulator version: 0.12 OS: Linux Distribution: Ubuntu 20.10 Kernel: 5.8.0-53-generic

barotto commented 3 years ago

Hi, first of all thank you for testing IBMulator on Linux.

The "Cannot find the assets!" error is about the missing ibmulator directory in share (I guess it should be a bit more descriptive). IBMulator's file structure follows the common unix convention of bin and share dirs so the executable looks into ../share/ibmulator/ for its assets at launch.

I think the solution for you would be to create a symlink in /usr/local/share/ to /opt/ibmps1/ibmulator/share/ibmulator.

About the first step in "Steps to reproduce", there's no need to unzip the romset. And actually for international romsets splitted in 2 bin files it would not even work, they must be kept zipped.

andornaut commented 3 years ago

I think the solution for you would be to create a symlink in /usr/local/share/ to /opt/ibmps1/ibmulator/share/ibmulator.

That may work.

Do note that it does work without that workaround if I execute ibmulator from /opt/ibmps1/ibmulator/bin/ibmulator. This suggests to me that one of the searched paths (for share) is a relative path from the location of the binary, which is why it finds /opt/ibmps1/ibmulator/share if executed as /opt/ibmps1/ibmulator/bin/ibmulator. I believe that this could be fixed by resolving/following the symlink prior to deriving the relative paths. "realpath /usr/local/bin/ibmulator".

I worked around this issue by creating a bash script in /usr/local/bin/ibmulator instead of a symlink:

#!/bin/bash
cd /opt/ibmps1/ibmulator
./bin/ibmulator

About the first step in "Steps to reproduce", there's no need to unzip the romset.

Thanks for letting me know! :smile:

barotto commented 3 years ago

one of the searched paths (for share) is a relative path from the location of the binary

Yes, that's exactly what it does. Another (undocumented) way to specify the assets dir is by using an environment variable called DATA_HOME. A third one is by placing the assets in $XDG_DATA_HOME/ibmulator, when the XDG base dir spec is followed by the OS. (now thinking of it I should also add $HOME/.local/share/ibmulator to the mix...)

I believe that this could be fixed by resolving/following the symlink prior to deriving the relative paths.

This is a good suggestion. I actually call realpath() at a later stage but the path needs to be resolved for the binary first. I'll fix this on the next version. Thanks!

andornaut commented 3 years ago

A third one is by placing the assets in $XDG_DATA_HOME/ibmulator, when the XDG base dir spec is followed by the OS. (now thinking of it I should also add $HOME/.local/share/ibmulator to the mix...)

$XDG_DATA_HOME defaults to (and is usually) set to $HOME/.local/share.

Just a minor note: I think you'd want to include $HOME/.local/share only if $XDG_DATA_HOME is undefined or empty, and otherwise use the path denoted by $XDG_DATA_HOME without also adding $HOME/.local/share.

No biggie either way, though.

barotto commented 3 years ago

I think you'd want to include $HOME/.local/share only if $XDG_DATA_HOME is undefined or empty

Yep, I agree. Fixed on unstable. Thanks again.