Thursday, August 02, 2007

Daedalus PSP under OSX

I mentioned a few days ago that I've recently bought a Macbook Pro. I've never owned a Mac before so it's been a really interesting experience learning my way around. Initially I was planing on dual booting Windows XP via Boot Camp, but I quickly found that I could do almost everything I need to in OSX. I did install Parallels Desktop, I rarely find myself running any Windows apps.

One of the main things I need for day to day 'work' is the ability to compile and run Daedalus. The rest of this article describes the process of setting up the PSPSDK under OSX, and compiling Daedalus PSP for the first time. This post is really aimed at people who are interested in compiling Daedalus for themselves on OSX. Hopefully it will also be useful for other PSP homebrew developers who have been having problems getting the PSPSDK set up under OSX.

To install the PSPSDK I largely followed this guide on the ps2dev.org forums. I already had XCode and fink installed. Fink complained when I tried to install all the listed packages, and I had to remove one of them from the command line (I think it was autogen, but I can't really remember now.)

I've been using the most recent psptoolchain script, which was updated a few weeks ago, and I had to make a couple of modifications. In depends/check-ncurses.sh I had to change the check for ncurses to look for the OSX .dyliib file:


## Check for a ncurses library.
ls /usr/lib/libncurses.a 1> /dev/null ||
ls /usr/lib/libncurses.dll.a ||
{ echo "ERROR: Install ncurses before continuing."; exit 1; }


became:


## Check for a ncurses library.
ls /usr/lib/libncurses.a 1> /dev/null ||
ls /usr/lib/libncurses.dll.a ||
ls /usr/lib/libncurses.dylib ||
{ echo "ERROR: Install ncurses before continuing."; exit 1; }


Secondly I had to make this change to scripts/001-binutils-2.16.1.sh. As urchin mentions on the ps2dev.org forum, ".m" is the extension for Objective C files in OSX. The '-r' tells make to ignore the built-in implicit rules, and everything works fine:

So:


## Compile and install.
make clean && make -j 2 && make install && make clean || { exit 1; }


became:


## Compile and install.
make clean && make -r -j 2 && make install && make clean || { exit 1; }


(note the '-r' flag on the second invocation of make.)

I left the psptoolchain script doing its stuff for a couple of hours, and when I came back to it everything seemed to have completed and installed correctly.

The next step was to get Daedalus PSP compiling. Somewhat naively I assumed Daedalus PSP would compile out of the box on OSX. As it turns out, I had to make a few small changes to get everything compiling nicely.

Firstly, I had to update the makefile so that it directly referenced psp-gcc and psp-g++. Normally, I build Daedalus PSP through a Visual Studio Makefile project, and I had used a couple of scripts from the ps2dev.org forums to format GCC's output into a format that Visual Studio understands, so that double clicking on an error in the output opens the corresponding file in the editor. I found a better way to handle this, so I changed the CC/CXX macros to refer to the original pspsdk tools.

The main problem I encountered was my arbitrary use of backslashes instead of forward slashes in #include directives, e.g.:


#include "Core\CPU.h"


should be:


#include "Core/CPU.h"


Another subtle error came from the way that I was instantiating static functions from templated classes which are defined in a namespace. An example will probably help explain. Here's the basic outline of the class I use to implement the singleton pattern:


namespace daedalus
{
template< class T>
class CSingleton
{
public:
static bool Create();

static T * Get() { return mpInstance; }

private:
T * mpInstance;
};
}


The Create method for the singleton class is then implemented like this:


template<> bool CSingleton< CController >::Create()
{
DAEDALUS_ASSERT_Q(mpInstance == NULL);

mpInstance = new IController();

return true;
}


For some reason this started failing when compiling Daedalus PSP under OSX:


Source/Core/PIF.cpp: At global scope:
Source/Core/PIF.cpp:250: error: specialization of 'static bool
daedalus::CSingleton::Create() [with T = CController]' in different namespace
Source/Core/PIF.cpp:250: error: from definition of 'static bool
daedalus::CSingleton::Create() [with T = CController]'


Rather than being an OSX issue, I suspect that the reason this error started occurring was actually due to the PSPSDK using an updated version of GCC which is a bit stricter than the version I was using on Windows. Regardless, the fix was easy - the code just needed to be wrapped in the 'daedalus' namespace:


namespace daedalus
{
template<> bool CSingleton< CController >::Create()
{
DAEDALUS_ASSERT_Q(mpInstance == NULL);

mpInstance = new IController();

return true;
}
}


(I've recently been going off the singleton pattern, but that's another story :)

With these changes Daedalus PSP compiles perfectly under OSX. On my 2.4 GHz Macbook Pro it takes just under 50 seconds. On my 2.4GHz Windows machine it takes over 2 minutes to compile, so I'm very impressed with the results.

I believe I've checked in all the required changes to the Daedalus SVN repository on SourceForge. If you decide to try compiling Daedalus PSP under OSX, let me know how you get on via the comments page (I'll be rejecting any off-topic comments to try and keep the discussion constructive)

-StrmnNrmn

12 comments:

XG917 said...

thanks for posting this. i too have a mac. i am running mac os x 10.4.10. i have installed xcode and all the things i need to get the toolchain running. but i have this one problem when trying to start toolchain.

i open a window in terminal, i type in cd psptoolchain, then i type in: sudo ./toolchain.sh
and this is the message i get:
ls: /usr/lib/libncurses.a: No such file or directory
ls: /usr/lib/libncurses.dll.a: No such file or directory
ERROR: Install ncurses before continuing.
../depends/check-ncurses.sh: Failed.

i have installed ncurses and everything else before this. do you think you can help?

Anonymous said...

HAHAHA everyone that says they buy a mac to use windows as the primary OS ends up using OSX instead.

However,
I tried compiling it and i got an error as shown below

Source/PSPGraphics/DrawText.cpp:51: warning: 'METRICS_NAME' defined but not used
psp-g++ -I. -I/usr/local/pspdev/psp/sdk/include -g -O3 -G0 -Wall -DDAEDALUS_PSP -DDAEDALUS_RELEASE_BUILD -DNDEBUG -DDAEDALUS_PUBLIC_RELEASE -fno-exceptions -fno-rtti -iquote../DaedCommon/Include -iquote./Source -iquote../DaedCommon -c -o Source/PSPGraphics/GraphicsContext.o Source/PSPGraphics/GraphicsContext.cpp
Source/PSPGraphics/GraphicsContext.cpp: In member function 'void IGraphicsContext::SaveScreenshot(const char*, s32, s32, u32, u32)':
Source/PSPGraphics/GraphicsContext.cpp:287: error: invalid conversion from 'int' to 'int*'
Source/PSPGraphics/GraphicsContext.cpp:287: error: initializing argument 4 of 'int sceDisplayGetFrameBuf(void**, int*, int*, int*)'
make: *** [Source/PSPGraphics/GraphicsContext.o] Error 1

After Redownloading the source i still get the error.

:/

Wally

Ranguvar said...

Funny- I got my RSoD around the same time you did, I just sent out my 360 to be serviced ^_^

While my 360 was gone, I started tinkering with my Xbox... softmodded it with Ndure and put on XBMC.

One of the big things I was trying to do was play Zelda OoT N64 on it.

I've had success with Surreal64 using UltraHLE, but there are audio bugs (I can live with those) and metallic textures don't display (again, I can live with it). There's one thing I can't live with though - the lack of metallic textures playing means that heart containers and heart pieces don't display - at all. Not good. The emerald, sapphire, and ruby parts of the gems also don't display. Gold Skulltula tokens have a wierd square bluish box around them.

I was wondering, since you were porting Daedelus to Xbox for a while, would you know why this is? And, if there is anything I can do to fix it? I'm definetly a power-user, but I can't code :(

Otherwise, I'll have to buy an N64.

Thanks very much for both your emulators, and have a great day ^_^

Coda Highland said...

Be aware that Apple gcc has its default warning level set considerably higher than most. I do my fair share of cross-platform development, and my Mac builds always point out sloppy code that Windows and Linux both happily ignore. Since you're using PSP libraries instead of system libraries, you won't encounter some of the other problems I've had -- the standard libraries are mostly from BSD instead of from GNU (that is, what's used for Linux, Cygwin, and MinGW), which can lead to subtle differences in places.

StrmnNrmn said...

xg917: I had to edit the depends/check-ncurses.sh script to fix this error - search for 'ncurses' in my blog post.

StrmnNrmn said...

@wally: Make sure you have the latest version of the Daedalus source from Subversion. In the latest version of the pspsdk they changed the prototype for sceDisplayGetFrameBuf() so that it takes a int value for the 4th argument rather than an int pointer.

This is fixed in the svn repository, but not in the source for R12.

StrmnNrmn said...

@coda: Well the pspsdk includes its own version of gcc (psp-gcc) so fortunately it's essentially identical across different operating systems.

I have been looking at getting Daedalus compiling under OSX (i.e. Daedalus OSX, not Daedalus PSP :) and have noticed a few differences with Apple's version of gcc as you mention. Good advice on the libraries though - I'll keep an eye out for that.

Anonymous said...

Just Discovered My SDK was out of date (Few months i guess)

All working fine now.

Aether said...

Hey! Thanks for your guide but I keep getting this error when I try to do the final sh ./toolchain.sh command after following all your instructions:

alexanders-computer:~/psptoolchain Alexander$ sh ./toolchain.sh
ls: /usr/lib/libncurses.a: No such file or directory
ls: /usr/lib/libncurses.dll.a: No such file or directory
/usr/lib/libncurses.dylib
ERROR: Add /usr/local/pspdev/bin to your path before continuing.
../depends/check-pspdev.sh: Failed.

If you could point out what idiotic mistake I'm making, I would be very grateful!

XG917 said...

i know this doesnt have anything to do with compiling daedalus on OS X but do you think of porting daedalus emu for windows to OS X? just s curiousity :)

StrmnNrmn said...

@aether: You need to add the following to your .bash_profile (should be in your home directory, i.e. ~/.bash_profile)

export PSPDEV="/usr/local/pspdev"
export PSPSDK="$PSPDEV/psp/sdk"
export PSPPATH="$PSPDEV/bin:$PSPDEV/psp/bin:$PSPSDK/bin"
export PATH="/sw/bin:$PATH:$PSPPATH"

Make sure you check out the pspdev forum post on this topic.

StrmnNrmn said...

@xg917: I have looked into this a little bit. I've been cleaning up the source code and adding some support for various platform-specific things (mostly stuff under the daedcommon/ subdirectory). I've not really looked into it too seriously though - the PSP version is my main consideration for the time being.