Attached is a patch to SheepShaver, to fix a problem where the ROM file can only be found on the first boot.
When a user creates a new SheepShaver machine, there is no preference file, so there is not ROM path preference. SheepShaver has logic so that in this case, it will look for a ROM file named "ROM" or "Mac OS ROM" in the current directory.
The user starts SheepShaver in order to get to the built-in Preferences Editor, and changes various settings (such as creation of a hard disk). Then the user reboots.
If the user forgot to set the ROM path at this time, then SheepShaver can no longer boot. The only recourse is for the user to find and delete the preferences file, or use an external preferences editor to set the ROM path.
The fix is to change SheepShaver to use the default ROM names when either the rom path is null (no preference) OR an empty string (preference exists with no rom path).
Attached is a patch to SheepShaver, to fix a SIGSEGV crash that occurs when booting a new machine with OS 7.5.
One of the bytes in the xPRAM portion of the NVRAM controls which version of the system memory manager is used by OS 7.5: the legacy 680x0 memory manager or the PPC memory manager (aka the "Modern Memory Manager"). OS 7.5 is supposed to be able to use either one, but for some reason SheepShaver crashes on boot if the 680x0 version is used.
Later Mac OS versions don't have this problem. They don't support the 680x0 version, so they force the PPC version to be used.
The fix is to have SheepShaver initialize the NVRAM to use the PPC memory manager. Note: This is supposed to be the default in OS 7.5.
This affects when a new NVRAM file is used, or when it is initialized after doing zapping the PRAM.
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
Attached is a set of patches to port the precise timer that is currently used in the Linux and BeOS builds of SheepShaver to Mac OS X (and any other Mach-based operating systems).
Currently, the Linux build uses the clock_gettime() function to get nanosecond-precision time, and falls back on gettimeofday() if it is not present. Unfortunately, Mac OS X does not currently support clock_gettime(), and gettimeofday() has only microsecond granularity. The Mach kernel, however, has a clock_get_time() function that does very nearly the same thing as clock_gettime(). The patches to BasiliskII cause the timing functions such as timer_current_time() to use clock_get_time() instead of gettimeofday() on Mach-based systems that do not support clock_gettime().
The changes to SheepShaver involve the precise timer. The existing code for Linux uses pthreads and real-time signals to handle the timing. Mac OS X unfortunately does not seem to support real-time signals, so Mach calls are again used to suspend and resume the timer thread in order to attempt to duplicate the Linux and BeOS versions of the timer. The code is somewhat ugly right now, as I decided to leave alone the pre-existing style of the source file, which unfortunately involves #ifdefs scattered throughout the file and some duplication of code. A future patch may want to clean this up to separate out the OS-specific code and put it all together at the top of the file. However, for the time being, this seems to work.
This has not been extensively tested, because I have not been able to get my hands on a good test-case app for the classic Mac OS that would run inside the emulator and try out the timer. However, performance does seem to be better than with the pre-existing code, and nothing seems to have blown up as far as I can tell. I did find a game via a Google search - Cap'n Magneto - that is known to have problems with Basilisk/SheepShaver's legacy 60 Hz timer, and the opening fade-to-color for this game appears to run much more smoothly with the precise timer code in place.
Here is a patch to allow compiling of SS and B2 with an SDL Framework. You can
get this by downloading from:
http://www.libsdl.org/release/SDL-1.2.13.dmg
Here is how I tested on an intel 32-bit mac with Mac OS X 10.5.6:
SS ./autogen.sh --disable-standalone-gui --enable-vosf --enable-sdl-framework --enable-sdl-framework-prefix=/Users/mzs/Library/Frameworks --enable-sdl-video --disable-sdl-audio --enable-addressing=real
--without-esd --without-gtk --without-mon --without-x
SS /autogen.sh --disable-standalone-gui --enable-vosf --disable-sdl-framework --disable-sdl-video --disable-sdl-audio --enable-addressing=real --without-esd --without-gtk --without-mon --with-x
B2 ./autogen.sh --disable-standalone-gui --enable-vosf --enable-sdl-framework --enable-sdl-framework-prefix=/Users/mzs/Library/Frameworks --enable-sdl-video --enable-sdl-audio --enable-addressing=real --without-esd --without-gtk --without-mon --without-x --enable-jit-compiler
B2 ./autogen.sh --disable-standalone-gui --enable-vosf --disable-sdl-framework --disable-sdl-video --disable-sdl-audio --enable-addressing=real --with-esd --without-gtk --without-mon --with-x --enable-jit-compiler
(esound does not really work on mac, it needs some better coreaudio patches.)
configure.ac for SS has two little additional fixes so that the Cocoa prefs gui
does not get built if you are building for X11 and so that you can use esd, sdl,
or coreaudio for sound.
I was testing some other SS patches and I noticed that when I ran an X11
build of SS there were not all the video modes I expected in the the
control strip. Mac OS X 10.5 changed the form of the DISPLAY environment
variable. The reason for this is that the DISPLAY variable looks like
this in Leopard:
/tmp/launch-XXXXXX/:0
The Xs are like in mktemp.
Here is a patch that has a shell script cpr.sh to recursively copy directories but
discarding things that cause problems at least on 10.4 when making the .app bundles.
This first patch gets B2 and SS to build under Leopard and Tiger.
I tested this on a 32-bit intel 10.5.6 mac like so:
B2
./autogen.sh --disable-standalone-gui --enable-vosf --enable-sdl-video --enable-sdl-audio --enable-addressing=real --without-esd --without-gtk --without-mon --without-x
SS
./autogen.sh --disable-standalone-gui --enable-vosf -enable-sdl-video --disable-sdl-audio --enable-addressing=real --without-esd --without-gtk --without-mon --without-x --enable-jit
There is also a little tweak so that you can use sdl audio in SheepShaver when building for Mac OS X.
Makes SheepShaver compatible with Ubuntu Intrepid and
other distros that bundle the gcc-4.3 compiler.
The patch changes two things:
1. Renames the block_cache where its name collides with its class
definition.
2. Fixes the "explicit template specialization cannot have a storage
class" error in the ppc-dyngen-ops.cpp file.
Software cursor mode is now supported, although currently the existing hardware
cursor mode is used whenever possible. (Software mode will be used if you are
running with a recent version of SDL's Quartz video driver, since a bug in SDL
1.2.11 and later prevents the hardware cursor from working properly with that
driver.)
In hardware cursor mode, the hot-spot is now determined heuristically. Formerly
it could not be determined and was always (1,1), an annoyance for many cursors
other than the arrow.
In hardware cursor mode, the cursor will now be hidden when requested by the
emulated OS (such as when you are typing in a text field).
In hardware cursor mode, some cursor image formats that the code does not handle
correctly will now be rejected, causing the emulated OS to revert temporarily to
software cursor mode. Formerly you would just end up with random garbage for a
cursor. This typically happened for grayscale or color cursors; rejecting images
with rowBytes != 2 eliminates the worst cases.
clicks to right-clicks and option-clicks to middle-clicks, a feature intended
for Mac users with single-button mice who are running SDL-based games that
require a multi-button mouse. This is unhelpful in SheepShaver, where we want
command-clicks and option-clicks to be passed through unchanged to the emulated
Mac OS. We can disable the unwanted behavior by setting an environment variable
SDL_HAS3BUTTONMOUSE intended for this very purpose.
A similar change in main_windows.cpp is NOT required, because only the Quartz
video implementation is involved.
By SDL convention, putenv is used in preference to setenv, although for Unix
platforms it doesn't matter.
to cache the CPU context pointer to a register and thus rendering generated
code CPU context independent. Not useful to SheepShaver, but it is for
another project for threads emulation on plain x86-32.
Note: AltiVec performance may drop a little on x86 but this will be restored
(and even improved) in the future.
set to 0 until generated code is optimized enough (current slow down factor
is 3x vs. previous core, expectations are about 50% slower FP code).
The main benefit is exception bits are accurate. All glibc test-fenv,
test-arith{,f}, test-double, test-float pass on ppc, and mostly on x86_64
with gcc 4.0.1. Yes, this is also compiler dependent.
FIXME: find a real Mac application that depends on precise FPSCR bits... I
think I don't want to care optimizing yet until someone shows me a real world
application.
68k or MacOS code, so they don't need to be a termination point. i.e. don't
split into two basic blocks and thus avoid a full hash search.
Also add missing NQD_unknown_hook NativeOp from previous commit.
SheepShaver since we are typically translating SDL_QUIT events to PowerOff()
on MacOS side. And, if MacOS is not fully booted, it's not really convenient
to shut it down, even with ctrl-C. i.e. you had to kill -9 it.
OpenFirmware check for OldWorld 604-based machines?
XXX I have code pending that makes it possible to use PowerMac ID #3035 and
model 510 (PowerMac G3 Series). However, I have a regression with one of my
MacOS 8.6 disks. This is non-standard anyway since it was installed from the
iMac DV 8.6 discs ("yellow" not generic) with MOL -- SheepShaver can't cope
with it.
So I am not surprised it breaks. Otherwise, 8.5 -> 9.0.4 were fine with it.
BTW, the "regression" is Native Resource Manager is not installed and the
boot gets mad later. FWIW, it's the same as for MacOS 9.1. A resource is
very likely not loaded.
1 GB of Mac memory. Only tested on Linux/x86_64 so far but with a somewhat
interesting (MacOS, ROM, RAM size) matrix.
XXX: It should be possible to allocate up to 1.5 GB by relocating the ROM
base to something like 0x60800000.
- 'boot' 3: set boot stack pointer only once at the correct place
- 'gpch' 750: fix FE0A opcode replacement (selector #$0a is virt2phys on pgidx)
- 'gpch' 750: remove bogus patch for SonyVars
- Mark patches "9.0" verified accordingly vs. 8.6
be useful to fix a bug in the AppleShare extension (see DRVR .AFPTranslator
in Basilisk II)
Unrelated improvement: call sheepshaver_cpu::get_resource() directly, don't
get it through another global function.
Others changes include:
- Factor out STR_SIG_INSTALL_ERR messages
- Process command line arguments early (prior to calling PrefsInit())
- GUI: set start_clicked only if the "Start" button was clicked
- GUI: save changes to the "Input" pane when the "Start" button was clicked
templates. This avoids mis-aligninment of the stack, and useless reservation
of space on it for function args. Indeed, we now pre-allocate 16 stack-slots
in op_execute() for this purpose.
positives in GCC detection, i.e. knowingly cause a syntax error if #error
was not good enough (MIPSpro CC). Fix dyngen g++ version detection if
main compiler is not g++
CC=cc CXX=CC ./configure --with-dgcc=g++
Also merge MIPSPro optimization flags from Basilisk II tree.
Note that I only verified the emulator works through the testsuite
(all tests passed, including AltiVec emulation)
generate target code without executing it, and not comparing results
- Fix aligned_vector_t, we can't rely on THIS pointer to be 16-byte aligned
- Also fix dummy_vector alignment
(likewise for -mmmx vs. mmx registers). Instead, since GCC won't generate
MMX/SSE code without explicit intrinsics use of vectorization, we know
those register won't be clobbered outside of the __asm__ code. So, it's safe
as is (we could also remove all sse/mmx clobbers).
this one for all cases but I'd prefer keep it that way. i.e. the old
driver in REAL_ADDRESSING mode (with the D(bug()) facility), and the new
NDRV for DIRECT_ADDRESSING mode (e.g. Windows).
migrate the Ethernet driver to the MacOS side. This is enabled for
DIRECT_ADDRESSING cases. I didn't want to alter much of ether.cpp (as it
would have required to support that mode). Of course, in REAL_ADDRESSING
mode (the default) and for debugging purposes, the old driver is still
available.
NewWorld ROM. That may be 8.1.0 included but original iMac had a NewWorld
ROM compatible system.
Otherwise we will crash because the boot routine is trying to execute code
through unitialized descriptor that points to 0x13ff, which is obviously
wrong (and unaligned on word-boundaries for 68k code).
code and re-enable it on Linux platforms (they have clock_nanosleep). Why
did I trigger an interrupt inside a held lock? Hmmm, we should probably
add an _ack semaphore like we do e.g. for ethernet.
EXEC_RETURN | HANDLE_INTERRUPT. And then, we handled the interrupt, but
EXEC_RETURN was set so we returned very quickly without completing the
interrupt routine. As a side effect, this occasionnaly hung the emulator
most likely with {ethernet,audio}-based applications that trigger a lot
of interrupts.
The fix is to always honour EXEC_RETURN flag at first, of course.
(idle_wait) until events arrived and notified through TriggerInterrupt().
i.e. we no longer sleep a fixed amount of time on platforms that support
a thread wait/signal mechanism.
the Ethernet interrupt. The BeOS version does that, likewise for MOL. Otherwise,
we end up into an infinite loop reporting the memory allocation failure.
I think this is now the expected behavior as we wouldn't have stats
(num_rx_no_mem) for it if we couldn't get out of the EtherIRQ. ;-) Besides,
the packet will be resent for reliable networks.
i.e. it returned EPERM and ran into stack corruption to eventually crash the
emulator. This is noticeable in !hw_mac_cursor_accl mode (e.g. fullscreen DGA).
In order to the sigalstack() to be effective, we must kludge the kernel to
think it's running on another stack. In practise, we provide another stack
for the SIGUSR2 handler. sigusr2_handler_init() fulfills that purpose.
I hope this fixes remaining issues forever. At some point, I had multiple
*_init() handlers in case this is necessary.
- Restore r13 on EMUL_RETURN, though I never saw r13 clobbered
- Increase stack frame allocated to EmulOp processing on par with BeOS
- Factor GetResource wrappers with a macro + restore r13 too
for systems that use a global r2 as the TLS register, e.g. Linux/ppc with
newer glibc. Also remove the syscall junk which were simply workarounds
for this bug. Remove a duplicate r2 restoration in EmulOp.
BTW, it's possible to get SheepShaver running on Linux/ppc systems with
NPTL rather than SheepThreads.
because fb visual was Direct Color instead of True Color). We used to
initialize the_buffer* even if !open_display. Report that gracefully with
the dedicated STR_OPEN_WINDOW_ERR.
- Enable VidMode extension with FBDev DGA graphics.
- Factor out FBDev/XF86 DGA code.
- Fix pointer grab in fbdev DGA mode, thus fixing scrolling screens in
lower VidModes.
- Only select VidModes that match the requested resolutions, exactly.
- Fix VideoQuitFullScreen() in non FBDev mode.
DGA mode. In other words, root user can now use FBDev DGA though it's always
recommended to run SheepShaver with a normal user. Increase "ramsize" bounds
in the GUI and fully migrate to new "screen" modes. Remove "windowmodes" and
"screenmodes" defaults.
to /dev/mem is required on Linux to use XF86 DGA mode. Otherwise, there is
now a fallback to fbdev.
- Forward port some features from Basilisk II (set_window_name,
disable_mouse_accel).
- Don't SIGSTOP the emulation thread on suspend since that would completely
stop the process on Linux. Use a frame buffer lock instead (as B2 does)
could have caused some rounding thus alterations to integer registers on
context switches when lfd/stfd instructions were used. e.g. cygwin compilers
defaulted to i686 code generation and exhibed this behaviour, you could also
see this behavior with -march=i586 -mtune=pentiumpro. GCC is perfectly right
to do those optimizations.
sort of barrier synchronisation? Anyhow, the current implementation looks
reasonable enough now when using old LinuxThreads without TLS.
XXX: in the past, the sem_post in sigsuspend_handler would not release the
calling thread thus entering into a mutual waiting condition.
aka avoid use of (possibly broken) GCC intrinsics. Add some SSE2 optimizations.
Translate VSLDOI, MFVSCR, MTVSCR instructions. AltiVec Fractal Carbon now
shows more than 1 GFlops performance!