mdbtxt1
mdbtxt2
Proceed to Safety

The BasiliskII Macintosh 680x0 Emulator    

I use a lot of old Mac software that I wrote myself (see the page, Macintosh Software by Robert Munafo), and much of it is still very useful to me, but not exactly worth the effort of re-writing from scratch. Apple has (for various reasons) made old software obsolete several times in the 25-plus-year history of the Macintosh and derived products1.

Fortunately Mac owners have emulators which they can use to easily and cleanly run their own software. The main subject of this page is the 680x0 emulator Basilisk II, but there is also much on here that is relevant to SheepShaver, a more recent development that allows running slightly newer (but still really old) Mac software in a PowerPC environment.

Contents

Getting the Source and Building

     Building BasiliskII

Other Tasks

     Rebuilding a Single Module

     Building SheepShaver

Compile and Runtime Error Messages

     ranlib ... libSDL has no symbols

     The JIT compiler temp register bug

     X11 error "cannot open display"

     NSQuickDrawView has been deprecated

     C compiler cannot create executables

My Improvements to the Emulators

     Fixing 'nocdrom true' on MacOS host

Benchmarks

Footnotes and Links


Getting the Source and Building

Prerequisites

These instructions assume you have an Intel Macintosh with the "Snow Leopard" (10.6) version of Mac OS X. It is important first to install the Developer Tools. My systems came with Developer Tools on a DVD, which was a version of Xcode 3.x. I may have updated it, but did not move to Xcode 4.x. My current Xcode is 3.2.6, the last "full" version of Xcode (rather than the stripped-down single-application version that you get through the Mac App Store). If you have one of the Mac App Store versions (Xcode 4.x), you may need to install the "Command Line Tools" (from the Downloads tab in Preferences). It has also been established that the GCC compiler version 4.0 (located at /usr/bin/gcc-4.0) must be present.

You might also need the X11 (X Window System server) which comes as an optional installation on the Snow Leopard install DVD. This is needed if you are going to use an X11 version of SDL (as described below).

I also assume you already have an "official" release of BasiliskII and/or SheepShaver running, with a working bootable emulated MacOS. There are several steps to this and it is far beyond the scope of this discussion. This page is intended only for those who already have BasiliskII and/or SheepShaver set up and want to start trying to fix bugs or improve functionality. I explain how to build both, if you only use one or the other then you can skip the part you don't need.

I do everything in a Terminal session. No Xcode project needs to be created, although that is possible, but I will not discuss it any further.

I create a directory in which to do my building:

cd mkdir devt

Here it is called "devt" and is in the home directory. You can put it elsewhere if you want.

Which SDL?

The first step is to get the source code. The normal instructions (see [3]) include getting a copy of SDL (the Simple DirectMedia Layer) suitable for developing a program that links to an SDL library to do its user interface (like making a window and getting events from the keyboard and mouse).

There are two choices each with advantages and disadvantages. The standard method for building BasiliskII uses the SDL version 1.2.15 from libsdl.org. To get it:

cd cd devt curl 'http://www.libsdl.org/release/SDL-1.2.15.zip' > ./SDL-1.2.15.zip unzip ./SDL-1.2.15.zip

Anyone using a computer with an Intel- or AMD-based CPU manufactured within the past 5 years needs to select whether they are compiling for "32-bit" or "64-bit". BasiliskII seems to only work in 32-bit at present, so SDL and BasiliskII both have to be compiled and linked for the 32-bit IA-32 architecture (using -arch i386). In addition, the normal build scripts want to use the -g and -O2 options. To get this to happen we need to set some environment variables:

export CFLAGS="-g -O2 -arch i386" export CXXFLAGS="-g -O2 -arch i386" export LDFLAGS="-arch i386"

Then we can build SDL:

cd cd devt/SDL-1.2.15 ./autogen.sh ./configure --disable-shared --prefix=`pwd` make make install export PATH=`pwd`/bin:$PATH

That last command export PATH=`pwd`/bin:$PATH affects the rest of the build process; if you start a new shell session later you have to repeat it:

cd cd devt/SDL-1.2.15 export PATH=`pwd`/bin:$PATH

Alternately, you may put something in your .login or .profile that sets $PATH. There is only one binary in SDL-1.2.15/bin, called sdl-config and I have a personal ~/bin directory, so I created a symlink in that directory pointing to the sdl-config in SDL-1.2.15/bin.

BasiliskII and SheepShaver development has been hampered by bugs in SDL (e.g. memory leaks), and some older versions of SDL have used the deprecated NSQuickDrawView drawing method, which Apple is trying to get rid of.

The other choice is to use the SDL that comes from MacPorts, which is based on the X11 server. This gives two advantages: the emulator is a little more independent of the Apple APIs; and you don't have to install your own SDL or set the path (as shown above) to build BasiliskII and SheepShaver.

To sum up:

choice advantage(s) disadvantage(s)
Quartz SDL Mac-native, no need for X11 You have to build an extra piece; more Mac-specific
X11 SDL More compatible with Linux version; no need to install a separate SDL Need to run X11 app

I knew that I already had the X11-based SDL because I have installed many things with MacPorts (notably FFmpeg, OpenCV and WxWidgets).

Therefore I did not install SDL, but simply verified that I have it installed:

sdl-config --version

The version of my SDL is 1.2.14, which is fine for Basilisk.

If you're using a MacPorts-derived version of SDL, you'll need to be running the X11 server, which comes as an optional installation on the Snow Leopard install DVD.

Getting the Source

With SDL out of the way, one then proceeds to get the BasiliskII and SheepShaver source:

cd cd devt cvs -d :pserver:anoncvs@cvs.cebix.net:/home/cvs/cebix login

When prompted for a password, enter anoncvs. You won't see what you're typing.

cd cd devt cvs -d :pserver:anoncvs@cvs.cebix.net:/home/cvs/cebix checkout BasiliskII cvs -d :pserver:anoncvs@cvs.cebix.net:/home/cvs/cebix checkout SheepShaver

Building BasiliskII

BasiliskII will build, but will fail to run, with the GCC compiler version 4.2.1 that comes with the Snow Leopard Xcode tools (see the JIT compiler temp register bug for details). There is an older GCC compiler, and you need to select it using the commands export CC=/usr/bin/gcc-4.0 and export CXX=/usr/bin/g++-4.0 shown in the instructions below.

To build BasiliskII the first time:

cd cd devt cd BasiliskII/src/Unix export CC=/usr/bin/gcc-4.0 export CFLAGS="-g -O2 -arch i386" export CXX=/usr/bin/g++-4.0 export CXXFLAGS="-g -O2 -arch i386" export LDFLAGS="-arch i386" NO_CONFIGURE=1 ./autogen.sh ./configure --enable-sdl-video --enable-sdl-audio --disable-vosf --enable-jit-compiler make clean make make BasiliskII_app

Running BasiliskII

Because I am using the X Windows version of SDL, I need to have the X11 server running. If it is installed it will be in [Boot Drive] > Applications > Utilities > X11.app and you can launch it from the Finder. Since I'm a Terminal geek I type:

/Applications/Utilities/X11.app/Contents/MacOS/X11.bin

Also, if launching BasiliskII from the Terminal (useful for seeing its debugging output), I also need to set the DISPLAY environment variable:

export DISPLAY=:1.0

Then to actually run BasiliskII (remembering that I have already have another copy of BasiliskII working, so I've set up the preferences file, a boot drive image, etc.) I can type:

cd cd devt/BasiliskII/src/Unix ./BasiliskII.app/Contents/MacOS/BasiliskII


Other Tasks

Rebuilding a Single Module

The Makefiles generated by the BasiliskII and SheepShaver builds do not have all their dependency information set up. Sometimes to rebuild just one module, I have to manually remove the object:

cd cd devt/BasiliskII/src/Unix rm obj/compemu_support.o make make BasiliskII_app ./BasiliskII.app/Contents/MacOS/BasiliskII

Building SheepShaver

To build SheepShaver for the first time involves a slightly different set of steps:

cd cd devt cd SheepShaver make links cd src/Unix NO_CONFIGURE=1 ./autogen.sh ./configure --enable-sdl-audio --enable-sdl-video --disable-vosf make make SheepShaver_app

Notice I am not setting the CC, CXX, CFLAGS, etc. environment variables. I did not find any need to do this, because SheepShaver's JIT compiler has already been fixed in a manner that addresses the JIT compiler temp register bug. However it is important that SDL has been compiled the same way as SheepShaver (otherwise you're likely to get an error message like libSDLmain.a ... not the architecture being linked (i386) or integer constant too large for unsigned long


Bugs

ranlib ... libSDL has no symbols

When building the recommended SDL-1.2.15, messages like these appear:

/usr/bin/ranlib: file: build/.libs/libSDL.a(SDL_audiodev.o) has no symbols ... ranlib: file: build/.libs/libSDL.a(SDL_audiodev.o) has no symbols

I found that these messages are okay and do not indicate a significant problem.


main_unix.cpp:29:18: error: SDL.h: No such file or directory

If the make command for BasiliskII or SheepShaver gives an error beginning with a line like this:

main_unix.cpp:29:18: error: SDL.h: No such file or directory

then it is most likely because the build was not configured (or re-configured if applicable) to find the SDL header files. This will happen if you switch from one SDL to another (as I discuss above). To resolve this, re-start the BasiliskII build instructions or the SheepShaver build instructions from the beginning (so that the NO_CONFIGURE=1 ./autogen.sh and subsequent steps have a chance to notice that you have a different SDL)


libSDLmain.a ... not the architecture being linked (i386)

On systems capable of building for either the 32-bit IA-32 CPUs (-arch i386) or 64-bit x86_64 CPUs (-arch x86_64), you may encounter this error or one like it:

ld: warning: in /Users/munafo/devt/SDL-1.2.15/lib/libSDLmain.a, file was built for unsupported file format which is not the architecture being linked (i386)

This is particularly prevalent on Snow Leopard systems, the first version of MacOS X in which 64-bit building is the default, but where many users and developers try to keep some things in 32-bit.

I fixed this error by building everything with the target architecture explicitly specified. In my particular case I want everything to be a 32-bit binary, so I choose the i386 architecture. The complete steps to build BasiliskII then become:

cd cd devt export CFLAGS="-g -O2 -arch i386" export CXXFLAGS="-g -O2 -arch i386" export LDFLAGS="-arch i386" cd SDL-1.2.15 ./autogen.sh ./configure --disable-shared --prefix=`pwd` make clean make make install echo $PATH # export PATH=`pwd`/bin:$PATH # If necessary    cd ../BasiliskII/src/Unix export CC=/usr/bin/gcc-4.0 export CXX=/usr/bin/g++-4.0 NO_CONFIGURE=1 ./autogen.sh ./configure --enable-sdl-video --enable-sdl-audio --disable-vosf --enable-jit-compiler make clean make

At the present writing (March 2012), BasiliskII cannot be built for the x86_64 target, but SheepShaver can. SheepShaver runs about 50% faster as an x86_64 program. To change from i386 to x86_64 or vice versa you need to rebuild SDL and then SheepShaver.

If you're routinely building BasiliskII for 32-bit and SheepShaver for 64-bit, then you'll find that SDL needs to be rebuilt each time to match (in this situation it's better to have two local SDL builds, and just redefine your $PATH when necessary).


libSDLmain.a ... not the architecture being linked (i386)

If you did not build SDL, but instead are trying to use the SDL that is installed by MacPorts or from some other type of software installation, you can also encounter the error:

ld: warning: in /opt/local/lib/libSDLmain.a, file was built for unsupported file format which is not the architecture being linked (i386)

I got this on one of my Snow Leopard systems despite having installed SDL through MacPorts and building BasiliskII in the standard way, with configure supposedly solving any compatibility problems for me. The issue is that I didn't have the "universal binary" version of SDL, and unfortunately configure is not able to handle this common problem.

In MacPorts, you can find out what you have (universal or not) with the command:

port installed | grep sdl

If you see a line like this:

libsdl @1.2.14_9+universal+x11 (active)

then the BasiliskII link should work. But if the output is missing the text "universal", like this:

libsdl @1.2.14_9+x11 (active)

then it can't link because the SDL library is for X86-64 only and BasiliskII wants an IA-32 version of the library.

If your SDL was installed through something other than MacPorts, you have to discover what it was compiled for manually. Begin with the command sdl-config --libs, which lists out the libraries in your currently-installed SDL. You'll get output like this (I've broken it up into mutiple lines):

-L/Users/fred/devt/SDL-1.2.15/lib \ /Users/fred/devt/SDL-1.2.15/lib/libSDLmain.a \ /Users/fred/devt/SDL-1.2.15/lib/libSDL.a \ -Wl,-framework,OpenGL -Wl,-framework,Cocoa \ -Wl,-framework,ApplicationServices -Wl,-framework,Carbon \ -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,IOKit

The two items ending in a ".a" filename are the SDL libraries. Now use the command otool -vh [pathname] and look in the cputype column:

$ otool -vh /Users/fred/devt/SDL-1.2.15/lib/libSDLmain.a Archive : /Users/fred/devt/SDL-1.2.15/lib/libSDLmain.a /Users/fred/devt/SDL-1.2.15/lib/libSDLmain.a(SDLMain.o): Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags MH_MAGIC I386 ALL 0x00 OBJECT 3 2744 SUBSECTIONS_VIA_SYMBOLS

The presence of "I386" in the cputype column indicates that this SDL library is 32-bit.

Whatever type of SDL you have, the solution to the "... not the architecture ..." build error is to rebuild BasiliskII or SheepShaver the same way.


integer constant is too large for ‘unsigned long’ type

Another error apparently caused by mixing 32-bit and 64-bit build is the following:

video_blit.h:131: error: integer constant is too large for ‘unsigned long’ type

I was able to fix it by making sure that CFLAGS, CXXFLAGS and LDFLAGS are all set to agree with each other, then rebuilding SDL and BasiliskII from the start, repeating all the steps including the ./autogen.sh and ./configure commands.


The JIT compiler temp register bug

This problem shows up in BasiliskII if you try to build it with its JIT compiler option (or perhaps if you just try to use the JIT compiler setting in .basilisk_ii_prefs). If you launch BasiliskII from the Finder you might see nothing, or perhaps a window appears briefly and immediately disappears: BasiliskII has crashed.

There is also an error message, visible if launching BasiliskII from the Terminal:

$ ./BasiliskII.app/Contents/MacOS/BasiliskII Basilisk II V1.0 by Christian Bauer et al. Reading ROM file... Using SDL/coreaudio audio output <JIT compiler> : enable runtime disassemblers : no <JIT compiler> : compile FPU instructions : yes <JIT compiler> : requested translation cache size : 8192 KB x86-64 implementations are bound to have CMOV! Abort trap

The last two lines are an error. What we would expect to see is something like the following (on a Sandy Bridge CPU):

Max CPUID level=13 Processor is GenuineIntel [PentiumPro] Target CPU defines all flags on BSF instruction <JIT compiler> : target processor has CMOV instructions : yes ...

The "x86-64 implementations are bound to have CMOV" message basically means "I think I'm running on an Intel processor that does not implement the CMOVxx instructions". The way BasiliskII (or any well-behaved program for x86 machines) finds out about CMOVxx is by using a special instruction called CPUID.

So the error results from the CPUID command failing. That in turn happens because BasiliskII is trying to use its own JIT compiler to generate the code that is used to call CPUID.

As it happens, BasiliskII's JIT compiler tries to "assemble" operations in a virtual machine (like a 68040) into Intel x86 code by gluing together snippets of code corresponding to operations like "move this register to the stack" or "add this register to that register". Each of these instructions is turned into one or more Intel machine language bytes by using the GCC compiler, at the time that you do the build.

As it happens, the GCC compiler 4.0 worked fine for BasiliskII's purposes. However, with GCC 4.2, some registers (including some that BasiliskII's JIT compiler is using as temporary registers) can no longer be used as temporary registers. So instead of giving us something like:

MOV r0, 7 ; put 7 in register R0

GCC 4.2 is giving us:

PUSH r0 ; save MOV r0, 7 ; put 7 in register R0 POP r0 ; restore

This causes the intended action (putting 7 into R0) to have no effect.

The fix is to use the GCC 4.0 compiler, which is accomplished by the export CC=... and export CXX=... steps in the above instructions.


X11 error "cannot open display"

If you get the error like this:

Gtk-WARNING **: cannot open display: :1.0

then X11 has set a different root display address. Type:

ps x | grep nolisten | grep -v xinit | grep -v grep

and look for a line like this:

12345 ?? S 0:00.00 /usr/X11/bin/X :1 -nolisten tcp -auth /Users/me/.serverauth.1234

The ":1" after /usr/X11/bin/X is the display address. If you see ":2" you sould set DISPLAY accordingly:

export DISPLAY=:2.0

Then launch the app from the Terminal as described earlier.

You can also avoid this complication by going into the running X11 application, starting a new xterm window from its Applications menu, and launching BasiliskII.app from the shell in that xterm window.


NSQuickDrawView has been deprecated

Some versions of SheepShaver have been built with a version of the SDL library that uses the old Apple QuickDraw API. If you launch SheepShaver from a terminal (shell), you'll see:

SheepShaver[123:456] Warning once: This application, or a library it uses, is using NSQuickDrawView, which has been deprecated. Apps should cease use of QuickDraw and move to Quartz.

Apple decided way back in MacOS X 10.4 Tiger to start telling applications developers to switch to its replacement, which is Quartz 2D (using NSView instead of NSQuickDrawView). Unfortunately, Quartz 2D has never been capable of the speed or flexibility of QuickDraw, and as of MacOS X 10.7 Lion, applications that use NSQuickDrawView still work (provided they were compiled to run under MacOS 10.6 Snow Leopard), although they print this message to their stdout.


C compiler cannot create executables

Someone who was using one of the 4.x versions of XCode reported this error to me.

I use Xcode 3.2.6, which is the last "full" version of Xcode including all of the API headers and libraries and all of the command-line tools, including a full GCC cross-compiler. I found the following suggestion at 2, which might solve the problem:

If you've installed Xcode 4.3.x, you need to launch it, go into its preferences, select the Downloads tab, and click "Install" next to the Command Line Tools package.

Another contributor in the same discussion suggested:

Turns out that /usr/local had the wrong permissions set. To fix it, I did the following:

      sudo chmod -R 755 /usr/local

It seems to me (based on Google searches for this error) that BasiliskII and SheepShaver are trying to use obscure cross-compilation features of the GCC compiler, which require certain runtime libraries, and these runtime libraries (such as crt1.10.5.o which is implicated in one of the comments at 2) are what prevents the configure test from working.

I haven't tested either of these suggestions, because I have never had the "C compiler cannot create executables" problem.


My Improvements to the Emulators

Fixing nocdrom true on MacOS host

I found a fix to the problem that made it impossible to eject CD-ROMs if you have the preferences nocdrom flag set to true.

For the original message and followup discussion, see this thread on the Emaculation forum (posted on the 21st April 2012).

Subject: Leggo my Eggo! (The CD-ROM eject fix)

This affects both BasiliskII and SheepShaver, on Mac OS X host systems, when the "nocdrom" setting is set to "true".

I keep lots of old files archived on CD-ROMs, and I often use these CD-ROMs while BasiliskII or SheepShaver is running. The CD-ROMs are for MacOS X, they wouldn't work in the emulator even if I tried, so I have "nocdrom true" in both my .basilisk_ii_prefs and .sheepshaver_prefs files.

There has been a bug for many years that causes this setting to only partly work. "nocdrom true" prevents the emulator from emulating the CD-ROM, but if you insert a disc after launching the emulator, it still grabs onto the CD-ROM as if it were being used, and it never lets go. If you try to eject the CD-ROM, the Finder removes the icon from the desktop but it doesn't eject. Disk Utility tells you it can't be unmounted. You have to quit BasiliskII or SheepShaver before it will actually eject.

A little searching through the source code turns up the routine SysMediaArrived, which is defined in sys_unix.cpp and invoked from sys_darwin.cpp. As you can see, it does perform an appropriate test:

   if (type == MEDIA_CD && !PrefsFindBool("nocdrom"))

but this test only affects whether or not it does the following PrefsReplaceString("cdrom", path); step.

The rest of the actions, including in particular the call to cdrom_open(fh, path), are performed regardless of the "nocdrom" setting.

This makes it open the CD-ROM device (such as "/dev/disk1" on one of the systems I tested) which is why the disc cannot be ejected. Unfortunately, there is no way to get it to close the device later. Because CD-ROM is turned off, the disc never appears inside the emulated MacOS, and so there is no way to ask the emulated Mac to eject it.

The fix I decided to try is relatively simple. If "nocdrom" is true, the entire SysMediaArrived routine is superfluous. So I added a test at the very beginning of SysMediaArrived that exits:

if ((type == MEDIA_CD) && PrefsFindBool("nocdrom")) { // Do nothing return; }

With this change I am able to insert and eject as many CD-ROMs as I want while SheepShaver is running, without having to make SheepShaver quit.

There are probably other ways to fix this. SysMediaArrived is called from media_arrived in sys_darwin.cpp, and media_arrived is installed by a call to IOServiceAddMatchingNotification. I suspect that one could put a test of PrefsFindBool("nocdrom") somewhere in here to prevent installing the notification handler in the first place. But I don't know what else that might affect (there might be other media that can arrive apart from CDROMs). UPDATE: see note 1

Also, the presence of the incorrect code in sys_unix.cpp makes it look like this bug might also affect Linux users.

Comments welcome...

1. UPDATE: Other BasiliskII developers, far more experienced than I, have confirmed that in fact SysMediaArrived has no function other than handling the insertion of a CD-ROM on a Mac OS X host. Furthermore, there is no impact on Linux or any other BasiliskII/SheepShaver implementations, and indeed, the problem can be (and has been) fixed at the source by making the call to IOServiceAddMatchingNotification conditional upon PrefsFindBool("nocdrom").


Benchmarks

These figures compare the speed of physical CPUs with emulated CPUs. They are ordered by increasing Whetstone speed.

host emulator Whetstone Dhrystone
20 MHz 68030 w/ 68882 - 1330 K 2.1 MIPs
33 MHz 68040 - 5570 K 19.5 MIPs
60 Mhz PPC 601 - 22,990 K 40.9 MIPs
120 Mhz PPC 604 - 53,100 K 129.8 MIPs
Core i7-2720QM BasiliskII 64-bit no JIT 90,200 K 98.9 MIPs
233 Mhz PPC G3 - 109,300 K
Core i7-2720QM SheepShaver 32-bit JIT enabled 303,000 K 863 MIPs
'' SheepShaver 64-bit JIT enabled 328,500 K 848 MIPs
'' BasiliskII 32-bit JIT enabled 890,000 K 1302 MIPs

The final entry for Basilisk II, with 890,000 KWhets and 1302 MIPs, is equivalent to about a "12 GHz" 68030 + 68882.


Footnotes

1 : : Most recently, Apple abandoned "Rosetta" (emulation of PowerPC binaries in MacOS), perhaps to ease cross-development between MacOS for Intel and iOS for A4/A5/A5X processors.

2 : : stackoverflow, configure: error: C compiler cannot create executables (discussion thread), 2012.

Links

[3] : Emaculation forum, Compiling BasiliskII and SheepShaver for various host environments, web page (forum thread), 2011.


Robert Munafo's home pages on AWS    © 1996-2024 Robert P. Munafo.    about    contact
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. Details here.

This page was written in the "embarrassingly readable" markup language RHTF, and was last updated on 2012 Aug 18. s.27