- first version to run natively on NetBSD/m68k

This commit is contained in:
cebix 2000-07-13 13:47:12 +00:00
parent 322bb38408
commit ff5fcd83a7
15 changed files with 1681 additions and 561 deletions

View File

@ -29,7 +29,7 @@ INSTALL_DATA = @INSTALL_DATA@
SRCS = ../main.cpp main_unix.cpp ../prefs.cpp prefs_unix.cpp sys_unix.cpp \
../rom_patches.cpp ../slot_rom.cpp ../rsrc_patches.cpp ../emul_op.cpp \
../macos_util.cpp ../xpram.cpp xpram_unix.cpp ../timer.cpp timer_unix.cpp \
clip_unix.cpp ../adb.cpp ../serial.cpp serial_unix.cpp ../ether.cpp ../sony.cpp \
clip_unix.cpp ../adb.cpp ../serial.cpp ../ether.cpp ../sony.cpp \
../disk.cpp ../cdrom.cpp ../scsi.cpp ../video.cpp video_x.cpp ../audio.cpp \
../extfs.cpp extfs_unix.cpp ../user_strings.cpp user_strings_unix.cpp \
$(SYSSRCS) $(CPUSRCS)

View File

@ -1,4 +1,48 @@
/* Additional defines for autoheader. */
/* acconfig.h
This file is in the public domain.
Descriptive text for the C preprocessor macros that
the distributed Autoconf macros can define.
No software package will use all of them; autoheader copies the ones
your configure.in uses into your configuration header file templates.
The entries are in sort -df order: alphabetical, case insensitive,
ignoring punctuation (such as underscores). Although this order
can split up related entries, it makes it easier to check whether
a given entry is in the file.
Leave the following blank line there!! Autoheader needs it. */
/* Define to 'off_t' if <sys/types.h> doesn't define. */
#undef loff_t
/* Define if using ESD. */
#undef ENABLE_ESD
/* Define if using DGA with framebuffer device. */
#undef ENABLE_FBDEV_DGA
/* Define if using GTK. */
#undef ENABLE_GTK
/* Define if using "mon". */
#undef ENABLE_MON
/* Define if using native 68k mode. */
#undef ENABLE_NATIVE_M68K
/* Define if using XFree86 DGA extension. */
#undef ENABLE_XF86_DGA
/* Define if using XFree86 VidMode extension. */
#undef ENABLE_XF86_VIDMODE
/* Define if pthreads are available. */
#undef HAVE_PTHREADS
/* Leave that blank line there!! Autoheader needs it.
If you're adding to this file, keep in mind:
The entries are in sort -df order: alphabetical, case insensitive,
ignoring punctuation (such as underscores). */

View File

@ -0,0 +1,246 @@
/*
* asm_support.s - Utility functions in assemmbly language
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
.file "asm_support.s"
.text
.globl _m68k_sync_icache
.globl _Start680x0__Fv
.globl _SetInterruptFlag__FUi
.globl _ClearInterruptFlag__FUi
.globl _Execute68k
.globl _Execute68kTrap
.globl _Scod060Patch1
.globl _Scod060Patch2
.globl _ThInitFPUPatch
.globl _EmulOpTrampoline
.globl _RAMBaseHost
.globl _ROMBaseHost
.globl _EmulOp__FUsP13M68kRegisters
.globl _EmulatedSR
.globl _InterruptFlags
.globl _TriggerInterrupt__Fv
/*
* Call m68k_sync_icache() (NetBSD, the version in libm68k is broken)
*/
.type _m68k_sync_icache,@function
_m68k_sync_icache:
movl sp@(8),d1
movl sp@(4),a1
movl #0x80000004,d0
trap #12
rts
/*
* Jump to Mac ROM, start emulation
*/
.type _Start680x0__Fv,@function
_Start680x0__Fv:
movl _RAMBaseHost,a0
addl #0x8000,a0
movl a0,sp
movl _ROMBaseHost,a0
lea a0@(0x2a),a0
jmp a0@
/*
* Set/clear interrupt flag (atomically)
*/
.type _SetInterruptFlag__FUi,@function
_SetInterruptFlag__FUi:
movl sp@(4),d0
orl d0,_InterruptFlags
rts
.type _ClearInterruptFlag__FUi,@function
_ClearInterruptFlag__FUi:
movl sp@(4),d0
notl d0
andl d0,_InterruptFlags
rts
/*
* Execute 68k subroutine (must be ended with rts)
* r->a[7] and r->sr are unused!
*/
/* void Execute68k(uint32 addr, M68kRegisters *r); */
.type _Execute68k,@function
_Execute68k: movl sp@(4),d0 |Get arguments
movl sp@(8),a0
movml d2-d7/a2-a6,sp@- |Save registers
movl a0,sp@- |Push pointer to M68kRegisters on stack
pea exec68kret |Push return address on stack
movl d0,sp@- |Push pointer to 68k routine on stack
movml a0@,d0-d7/a0-a6 |Load registers from M68kRegisters
rts |Jump into 68k routine
exec68kret: movl a6,sp@- |Save a6
movl sp@(4),a6 |Get pointer to M68kRegisters
movml d0-d7/a0-a5,a6@ |Save d0-d7/a0-a5 to M68kRegisters
movl sp@+,a6@(56) |Save a6 to M68kRegisters
addql #4,sp |Remove pointer from stack
movml sp@+,d2-d7/a2-a6 |Restore registers
rts
/*
* Execute MacOS 68k trap
* r->a[7] and r->sr are unused!
*/
/* void Execute68kTrap(uint16 trap, M68kRegisters *r); */
.type _Execute68kTrap,@function
_Execute68kTrap:
movl sp@(4),d0 |Get arguments
movl sp@(8),a0
movml d2-d7/a2-a6,sp@- |Save registers
movl a0,sp@- |Push pointer to M68kRegisters on stack
movw d0,sp@- |Push trap word on stack
subql #8,sp |Create fake A-Line exception frame
movml a0@,d0-d7/a0-a6 |Load registers from M68kRegisters
movl a2,sp@- |Save a2 and d2
movl d2,sp@-
lea exectrapret,a2 |a2 points to return address
movw sp@(16),d2 |Load trap word into d2
jmp zpc@(0x28:w)@(10) |Jump into MacOS A-Line handler
exectrapret: movl a6,sp@- |Save a6
movl sp@(6),a6 |Get pointer to M68kRegisters
movml d0-d7/a0-a5,a6@ |Save d0-d7/a0-a5 to M68kRegisters
movl sp@+,a6@(56) |Save a6 to M68kRegisters
addql #6,sp |Remove pointer and trap word from stack
movml sp@+,d2-d7/a2-a6 |Restore registers
rts
/*
* Call EmulOp() after return from SIGILL handler, registers are pushed on stack
*/
.type _EmulOpTrampoline,@function
_EmulOpTrampoline:
movl sp,a0 |Get pointer to registers
movw _EmulatedSR,d0 |Save EmulatedSR, disable interrupts
movw d0,sp@-
oriw #0x0700,d0
movw d0,_EmulatedSR
movl a0,sp@- |Push pointer to registers
movl a0@(66),a1 |Get saved PC
addql #2,a0@(66) |Skip EMUL_OP opcode
movw a1@,sp@- |Push opcode word
clrw sp@-
jbsr _EmulOp__FUsP13M68kRegisters
addql #8,sp
movw sp@+,d0 |Restore interrupts, trigger pending interrupt
movw d0,_EmulatedSR
andiw #0x0700,d0
bne eot1
tstl _InterruptFlags
beq eot1
jbsr _TriggerInterrupt__Fv
eot1: moveml sp@+,d0-d7/a0-a6 |Restore registers
addql #4,sp |Skip saved SP
rtr
/*
* Process Manager 68060 FPU patches
*/
.type _Scod060Patch1,@function
_Scod060Patch1: fsave sp@- |Save FPU state
tstb sp@(2) |Null?
beqs sc1
fmovemx fp0-fp7,sp@- |No, save FPU registers
fmovel fpi,sp@-
fmovel fpsr,sp@-
fmovel fpcr,sp@-
pea -1 |Push "FPU state saved" flag
sc1: movl d1,sp@-
movl d0,sp@-
bsrs sc3 |Switch integer registers and stack
addql #8,sp
tstb sp@(2) |New FPU state null or "FPU state saved" flag set?
beqs sc2
addql #4,sp |Flag set, skip it
fmovel sp@+,fpcr |Restore FPU registers and state
fmovel sp@+,fpsr
fmovel sp@+,fpi
fmovemx sp@+,fp0-fp7
sc2: frestore sp@+
movml sp@+,d0-d1
rts
sc3: movl sp@(4),a0 |Switch integer registers and stack
movw sr,sp@-
movml d2-d7/a2-a6,sp@-
cmpw #0,a0
beqs sc4
movl sp,a0@
sc4: movl sp@(0x36),a0
movml a0@+,d2-d7/a2-a6
movw a0@+,sr
movl a0,sp
rts
.type _Scod060Patch2,@function
_Scod060Patch2: movl d0,sp@- |Create 68060 null frame on stack
movl d0,sp@-
movl d0,sp@-
frestore sp@+ |and load it
rts
/*
* Thread Manager 68060 FPU patches
*/
.type _ThInitFPUPatch,@function
_ThInitFPUPatch:
tstb a4@(0x40)
bnes th1
moveq #0,d0 |Create 68060 null frame on stack
movl d0,a3@-
movl d0,a3@-
movl d0,a3@-
th1: rts

View File

@ -41,7 +41,7 @@
#include "audio.h"
#include "audio_defs.h"
#if ENABLE_ESD
#ifdef ENABLE_ESD
#include <esd.h>
#endif
@ -138,7 +138,7 @@ bool audio_init_dsp(void)
// Init using ESD, returns false on error
bool audio_init_esd(void)
{
#if ENABLE_ESD
#ifdef ENABLE_ESD
printf("Using ESD audio output\n");
// ESD audio format
@ -195,7 +195,7 @@ void AudioInit(void)
// Try to open /dev/dsp
audio_fd = open(DSP_NAME, O_WRONLY);
if (audio_fd < 0) {
#if ENABLE_ESD
#ifdef ENABLE_ESD
if (!audio_init_esd())
return;
#else

View File

@ -31,6 +31,30 @@
/* Define to 'off_t' if <sys/types.h> doesn't define. */
#undef loff_t
/* Define if using ESD. */
#undef ENABLE_ESD
/* Define if using DGA with framebuffer device. */
#undef ENABLE_FBDEV_DGA
/* Define if using GTK. */
#undef ENABLE_GTK
/* Define if using "mon". */
#undef ENABLE_MON
/* Define if using native 68k mode. */
#undef ENABLE_NATIVE_M68K
/* Define if using XFree86 DGA extension. */
#undef ENABLE_XF86_DGA
/* Define if using XFree86 VidMode extension. */
#undef ENABLE_XF86_VIDMODE
/* Define if pthreads are available. */
#undef HAVE_PTHREADS
/* The number of bytes in a int. */
#undef SIZEOF_INT
@ -67,6 +91,12 @@
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <history.h> header file. */
#undef HAVE_HISTORY_H
/* Define if you have the <readline.h> header file. */
#undef HAVE_READLINE_H
/* Define if you have the <readline/history.h> header file. */
#undef HAVE_READLINE_HISTORY_H
@ -87,3 +117,6 @@
/* Define if you have the readline library (-lreadline). */
#undef HAVE_LIBREADLINE
/* Define if you have the termcap library (-ltermcap). */
#undef HAVE_LIBTERMCAP

File diff suppressed because it is too large Load Diff

View File

@ -20,22 +20,52 @@ AC_PROG_CXX
AC_PROG_MAKE_SET
AC_PROG_INSTALL
dnl Check for i386 target CPU.
HAVE_I386=no
AC_MSG_CHECKING(for x86 target CPU)
AC_EGREP_CPP(yes,
[
#ifdef __i386__
yes
#endif
], [AC_MSG_RESULT(yes); HAVE_I386=yes], AC_MSG_RESULT(no))
dnl Check for SPARC target CPU.
HAVE_SPARC=no
AC_MSG_CHECKING(for SPARC target CPU)
AC_EGREP_CPP(yes,
[
#ifdef __sparc__
yes
#endif
], [AC_MSG_RESULT(yes); HAVE_SPARC=yes], AC_MSG_RESULT(no))
dnl Check for m68k target CPU.
HAVE_M68K=no
AC_MSG_CHECKING(for m68k target CPU)
AC_EGREP_CPP(yes,
[
#ifdef __m68k__
yes
#endif
], [AC_MSG_RESULT(yes); HAVE_M68K=yes], AC_MSG_RESULT(no))
dnl We use mon if possible.
MONSRCS=
if [[ "x$WANT_MON" = "xyes" ]]; then
AC_MSG_CHECKING(for mon)
if grep mon_init ../../../mon/src/mon.h >/dev/null 2>/dev/null; then
AC_MSG_RESULT(yes)
DEFINES="$DEFINES -DENABLE_MON=1"
AC_DEFINE(ENABLE_MON)
MONSRCS="../../../mon/src/mon.cpp ../../../mon/src/mon_6502.cpp ../../../mon/src/mon_68k.cpp ../../../mon/src/mon_8080.cpp ../../../mon/src/mon_cmd.cpp ../../../mon/src/mon_ppc.cpp ../../../mon/src/mon_x86.cpp"
CXXFLAGS="$CXXFLAGS -I../../../mon/src"
AC_CHECK_LIB(readline, readline)
AC_CHECK_HEADERS(readline/readline.h readline/history.h)
AC_CHECK_LIB(termcap, tputs)
AC_CHECK_HEADERS(readline.h history.h readline/readline.h readline/history.h)
else
AC_MSG_RESULT(no)
AC_MSG_WARN([Could not find mon, ignoring --with-mon.])
WANT_MON=no
DEFINES="$DEFINES -DENABLE_MON=0"
fi
fi
@ -51,25 +81,32 @@ CFLAGS="$CFLAGS $X_CFLAGS"
CXXFLAGS="$CXXFLAGS $X_CFLAGS"
LIBS="$LIBS $X_PRE_LIBS $X_LIBS -lX11 -lXext $X_EXTRA_LIBS"
dnl We need pthreads. Try libpthread first, then libc_r (FreeBSD), then PTL.
dnl We want pthreads. Try libpthread first, then libc_r (FreeBSD), then PTL.
HAVE_PTHREADS=yes
AC_CHECK_LIB(pthread, pthread_create, , [
AC_CHECK_LIB(c_r, pthread_create, , [
AC_CHECK_LIB(PTL, pthread_create, , [
AC_MSG_ERROR([You need pthreads to run Basilisk II.])
HAVE_PTHREADS=no
])
])
])
if [[ "x$HAVE_PTHREADS" = "xyes" ]]; then
AC_DEFINE(HAVE_PTHREADS)
fi
AC_CHECK_FUNCS(pthread_cancel)
dnl If POSIX.4 semaphores are not available, we emulate them with pthread mutexes.
SEMSRCS=
SEMSRC=
AC_CHECK_FUNCS(sem_init, , [
SEMSRCS=posix_sem.cpp
if [ "x$HAVE_PTHREADS" = "xyes" ]; then
SEMSRC=posix_sem.cpp
fi
])
dnl We use DGA (XFree86 or fbdev) if possible.
if [[ "x$WANT_XF86_DGA" = "xyes" ]]; then
AC_CHECK_LIB(Xxf86dga, XF86DGAQueryExtension, [
DEFINES="$DEFINES -DENABLE_XF86_DGA=1"
AC_DEFINE(ENABLE_XF86_DGA)
LIBS="$LIBS -lXxf86dga"
if [[ "x$WANT_FBDEV_DGA" = "xyes" ]]; then
AC_MSG_WARN([Cannot have both --enable-xf86-dga and --enable-fbdev-dga, ignoring --enable-fbdev-dga.])
@ -78,26 +115,20 @@ if [[ "x$WANT_XF86_DGA" = "xyes" ]]; then
], [
AC_MSG_WARN([Could not find XFree86 DGA extension, ignoring --enable-xf86-dga.])
WANT_XF86_DGA=no
DEFINES="$DEFINES -DENABLE_XF86_DGA=0"
])
else
DEFINES="$DEFINES -DENABLE_XF86_DGA=0"
fi
if [[ "x$WANT_FBDEV_DGA" = "xyes" ]]; then
DEFINES="$DEFINES -DENABLE_FBDEV_DGA=1"
else
DEFINES="$DEFINES -DENABLE_FBDEV_DGA=0"
AC_DEFINE(ENABLE_FBDEV_DGA)
fi
dnl We use XFree86 VidMode if possible.
if [[ "x$WANT_XF86_VIDMODE" = "xyes" ]]; then
AC_CHECK_LIB(Xxf86vm, XF86VidModeQueryExtension, [
DEFINES="$DEFINES -DENABLE_XF86_VIDMODE=1"
AC_DEFINE(ENABLE_XF86_VIDMODE)
LIBS="$LIBS -lXxf86vm"
], [
AC_MSG_WARN([Could not find XFree86 VidMode extension, ignoring --enable-xf86-vidmode.])
WANT_XF86_VIDMODE=no
DEFINES="$DEFINES -DENABLE_XF86_VIDMODE=0"
])
fi
@ -105,7 +136,7 @@ dnl We use GTK+ if possible.
UISRCS=../dummy/prefs_editor_dummy.cpp
if [[ "x$WANT_GTK" = "xyes" ]]; then
AM_PATH_GTK(1.2.0, [
DEFINES="$DEFINES -DENABLE_GTK=1"
AC_DEFINE(ENABLE_GTK)
CFLAGS="$CFLAGS $GTK_CFLAGS"
CXXFLAGS="$CXXFLAGS $GTK_CFLAGS"
LIBS="$LIBS $GTK_LIBS"
@ -113,21 +144,19 @@ if [[ "x$WANT_GTK" = "xyes" ]]; then
], [
AC_MSG_WARN([Could not find GTK+, disabling user interface.])
WANT_GTK=no
DEFINES="$DEFINES -DENABLE_GTK=0"
])
fi
dnl We use ESD if possible.
if [[ "x$WANT_ESD" = "xyes" ]]; then
AM_PATH_ESD(0.2.8, [
DEFINES="$DEFINES -DENABLE_ESD=1"
AC_DEFINE(ENABLE_ESD)
CFLAGS="$CFLAGS $ESD_CFLAGS"
CXXFLAGS="$CXXFLAGS $ESD_CFLAGS"
LIBS="$LIBS $ESD_LIBS"
], [
AC_MSG_WARN([Could not find ESD, disabling ESD support.])
WANT_ESD=no
DEFINES="$DEFINES -DENABLE_ESD=0"
])
fi
@ -152,83 +181,83 @@ AC_STRUCT_TM
dnl Checks for library functions.
AC_CHECK_FUNCS(strdup cfmakeraw)
AC_CHECK_FUNCS(nanosleep clock_gettime timer_create)
AC_CHECK_FUNCS(pthread_cancel)
dnl Select system-dependant source files.
SYSSRCS="../dummy/ether_dummy.cpp ../dummy/scsi_dummy.cpp ../dummy/audio_dummy.cpp"
if MACHINE=`uname -a 2>/dev/null`; then
SERIALSRC=serial_unix.cpp
ETHERSRC=../dummy/ether_dummy.cpp
SCSISRC=../dummy/scsi_dummy.cpp
AUDIOSRC=../dummy/audio_dummy.cpp
EXTRASYSSRCS=
SUPPORTS_NATIVE_M68K=no
if MACHINE=`uname -s 2>/dev/null`; then
case "$MACHINE" in
Linux*)
SYSSRCS="Linux/ether_linux.cpp Linux/scsi_linux.cpp audio_oss_esd.cpp"
ETHERSRC=Linux/ether_linux.cpp
SCSISRC=Linux/scsi_linux.cpp
AUDIOSRC=audio_oss_esd.cpp
;;
FreeBSD*3.*)
AUDIOSRC=audio_oss_esd.cpp
DEFINES="$DEFINES -DBSD_COMP"
dnl Check for the CAM library
AC_CHECK_LIB(cam, cam_open_btl, HAVE_LIBCAM=yes, HAVE_LIBCAM=no)
if [[ "x$HAVE_LIBCAM" = "xno" ]]; then
AC_MSG_ERROR([Cannot find libcam for SCSI management.])
AC_MSG_WARN([Cannot find libcam for SCSI management, disabling SCSI support.])
else
dnl Check for the sys kernel includes
AC_CHECK_HEADER(/sys/cam/cam.h)
if [[ "x$ac_cv_header__sys_cam_cam_h" = "xno" ]]; then
dnl In this case I should fix this thing including a "patch"
dnl to access directly to the functions in the kernel :) --Orlando
AC_MSG_ERROR([Cannot find kernel includes for CAM library.])
AC_MSG_WARN([Cannot find kernel includes for CAM library, disabling SCSI support.])
else
SCSISRC=FreeBSD/scsi_freebsd.cpp
CXXFLAGS="$CXXFLAGS -I/sys"
CFLAGS="$CFLAGS -I/sys"
LIBS="$LIBS -lcam"
DEFINES="$DEFINES -DCAM"
fi
SYSSRCS="../dummy/ether_dummy.cpp FreeBSD/scsi_freebsd.cpp audio_oss_esd.cpp"
CXXFLAGS="$CXXFLAGS -I/sys"
CFLAGS="$CFLAGS -I/sys"
LIBS="$LIBS -lcam"
DEFINES="$DEFINES -DBSD_COMP -DCAM"
fi
;;
FreeBSD*)
DEFINES="$DEFINES -DBSD_COMP"
dnl Check for the SCSI library
AC_CHECK_LIB(scsi, scsi_open, HAVE_LIBSCSI=yes, HAVE_LIBSCSI=no)
if [[ "x$HAVE_LIBSCSI" = "xno" ]]; then
AC_MSG_ERROR([Cannot find libscsi for SCSI management.])
AC_MSG_WARN([Cannot find libscsi for SCSI management, disabling SCSI support.])
else
dnl Check for the sys kernel includes
AC_CHECK_HEADER(scsi.h sys/scsiio.h)
if [[ "x$ac_cv_header_scsi_h" = "xno" ]]; then
AC_MSG_ERROR([Cannot find includes for the SCSI library.])
AC_MSG_WARN([Cannot find includes for the SCSI library, disabling SCSI support.])
else
SCSISRC=FreeBSD/scsi_freebsd.cpp
LIBS="$LIBS -lscsi"
fi
SYSSRCS="../dummy/ether_dummy.cpp FreeBSD/scsi_freebsd.cpp ../dummy/audio_dummy.cpp"
LIBS="$LIBS -lscsi"
DEFINES="$DEFINES -DBSD_COMP"
fi
;;
NetBSD*)
SUPPORTS_NATIVE_M68K=yes
;;
SunOS*)
SYSSRCS="../dummy/ether_dummy.cpp ../dummy/scsi_dummy.cpp Solaris/audio_solaris.cpp"
AUDIOSRC=Solaris/audio_solaris.cpp
DEFINES="$DEFINES -DBSD_COMP -D_POSIX_PTHREAD_SEMANTICS"
;;
IRIX*)
SYSSRCS="../dummy/ether_dummy.cpp ../dummy/scsi_dummy.cpp ../dummy/audio_dummy.cpp Irix/unaligned.c"
EXTRASYSSRCS=Irix/unaligned.c
DEFINES="$DEFINES -DCRTSCTS=CNEW_RTSCTS -DB230400=B115200"
LIBS="$LIBS -lm"
;;
esac
fi
SYSSRCS="$SYSSRCS $SEMSRCS $UISRCS $MONSRCS"
dnl Check for i386 CPU.
HAVE_I386=no
AC_MSG_CHECKING(for x86 target CPU)
AC_EGREP_CPP(yes,
[
#ifdef __i386__
yes
#endif
], [AC_MSG_RESULT(yes); HAVE_I386=yes], AC_MSG_RESULT(no))
dnl Check for SPARC CPU.
HAVE_SPARC=no
AC_MSG_CHECKING(for SPARC target CPU)
AC_EGREP_CPP(yes,
[
#ifdef __sparc__
yes
#endif
], [AC_MSG_RESULT(yes); HAVE_SPARC=yes], AC_MSG_RESULT(no))
if [[ "x$HAVE_PTHREADS" = "xno" ]]; then
dnl Serial, ethernet and audio support needs pthreads
AC_MSG_WARN([You don't have pthreads, disabling serial, ethernet and audio support.])
SERIALSRC=../dummy/serial_dummy.cpp
ETHERSRC=../dummy/ether_dummy.cpp
AUDIOSRC=../dummy/audio_dummy.cpp
fi
SYSSRCS="$SERIALSRC $ETHERSRC $SCSISRC $AUDIOSRC $SEMSRC $UISRCS $MONSRCS $EXTRASYSSRCS"
dnl Check for GAS.
HAVE_GAS=no
@ -249,8 +278,8 @@ AC_EGREP_CPP(yes,
#endif
], [AC_MSG_RESULT(yes); HAVE_GCC27=yes], AC_MSG_RESULT(no))
dnl Set "-fomit-frame-pointer" on GCC 2.7 or higher.
if [[ "x$HAVE_GCC27" = "xyes" ]]; then
dnl Set "-fomit-frame-pointer" on i386 GCC 2.7 or higher.
if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_I386" = "xyes" ]]; then
CFLAGS="$CFLAGS -fomit-frame-pointer"
CXXFLAGS="$CXXFLAGS -fomit-frame-pointer"
fi
@ -259,6 +288,7 @@ dnl Select appropriate CPU source and REGPARAM define.
WANT_X86_ASSEMBLY=no
WANT_SPARC_V8_ASSEMBLY=no
WANT_SPARC_V9_ASSEMBLY=no
WANT_NATIVE_M68K=no
CPUSRCS="cpuemu1.cpp cpuemu2.cpp cpuemu3.cpp cpuemu4.cpp cpuemu5.cpp cpuemu6.cpp cpuemu7.cpp cpuemu8.cpp"
if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_I386" = "xyes" ]]; then
dnl i386 CPU
@ -291,11 +321,21 @@ elif [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_SPARC" = "xyes" -a "x$HAVE_GAS" = "xy
esac
;;
esac
elif [[ "x$HAVE_M68K" = "xyes" -a "x$SUPPORTS_NATIVE_M68K" = "xyes" ]]; then
dnl Native m68k, no emulation
CPUSRCS=""
AC_DEFINE(ENABLE_NATIVE_M68K)
WANT_NATIVE_M68K=yes
fi
dnl UAE CPU sources for all architectures.
CPUINCLUDES="-I../uae_cpu"
CPUSRCS="../uae_cpu/basilisk_glue.cpp ../uae_cpu/memory.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp ../uae_cpu/fpp.cpp cpustbl.cpp cpudefs.cpp $CPUSRCS"
dnl UAE CPU sources for all non-m68k-native architectures.
if [[ "x$WANT_NATIVE_M68K" = "xno" ]]; then
CPUINCLUDES="-I../cpu_cpu"
CPUSRCS="../uae_cpu/basilisk_glue.cpp ../uae_cpu/memory.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp ../uae_cpu/fpp.cpp cpustbl.cpp cpudefs.cpp $CPUSRCS"
else
CPUINCLUDES="-I../native_cpu"
CPUSRCS="asm_support.s"
fi
dnl Generate Makefile.
AC_SUBST(DEFINES)
@ -317,5 +357,6 @@ echo mon debugger support ............. : $WANT_MON
echo i386 assembly optimizations ...... : $WANT_X86_ASSEMBLY
echo SPARC V8 assembly optimizations .. : $WANT_SPARC_V8_ASSEMBLY
echo SPARC V9 assembly optimizations .. : $WANT_SPARC_V9_ASSEMBLY
echo Running m68k code natively ....... : $WANT_NATIVE_M68K
echo
echo "Configuration done. Now type \"make\"."
echo "Configuration done. Now type \"make\" (or \"gmake\")."

View File

@ -22,8 +22,40 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <X11/Xlib.h>
#ifdef HAVE_PTHREADS
# include <pthread.h>
#endif
#if defined(USE_MAPPED_MEMORY) || REAL_ADDRESSING
# include <sys/mman.h>
#endif
#if !EMULATED_68K && defined(__NetBSD__)
# include <m68k/sync_icache.h>
# include <m68k/frame.h>
# include <sys/param.h>
# include <sys/sysctl.h>
struct sigstate {
int ss_flags;
struct frame ss_frame;
struct fpframe ss_fpstate;
};
# define SS_FPSTATE 0x02
# define SS_USERREGS 0x04
#endif
#ifdef ENABLE_GTK
# include <gtk/gtk.h>
#endif
#ifdef ENABLE_XF86_DGA
# include <X11/Xutil.h>
# include <X11/extensions/xf86dga.h>
#endif
#include "cpu_emulation.h"
#include "sys.h"
@ -31,6 +63,7 @@
#include "xpram.h"
#include "timer.h"
#include "video.h"
#include "emul_op.h"
#include "prefs.h"
#include "prefs_editor.h"
#include "macos_util.h"
@ -38,34 +71,29 @@
#include "version.h"
#include "main.h"
#define DEBUG 0
#ifdef ENABLE_MON
# include "mon.h"
#endif
#define DEBUG 1
#include "debug.h"
#include <X11/Xlib.h>
#if ENABLE_GTK
#include <gtk/gtk.h>
#endif
#if ENABLE_XF86_DGA
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86dga.h>
#endif
#if ENABLE_MON
#include "mon.h"
#endif
#ifdef USE_MAPPED_MEMORY
#include <sys/mman.h>
extern char *address_space, *good_address_map;
#endif
// Constants
const char ROM_FILE_NAME[] = "ROM";
const int SIG_STACK_SIZE = SIGSTKSZ; // Size of signal stack
const int SCRATCH_MEM_SIZE = 0x10000; // Size of scratch memory area
#if !EMULATED_68K
// RAM and ROM pointers
uint32 RAMBaseMac; // RAM base (Mac address space)
uint8 *RAMBaseHost; // RAM base (host address space)
uint32 RAMSize; // Size of RAM
uint32 ROMBaseMac; // ROM base (Mac address space)
uint8 *ROMBaseHost; // ROM base (host address space)
uint32 ROMSize; // Size of ROM
#endif
// CPU and FPU type, addressing mode
@ -79,6 +107,13 @@ bool TwentyFourBitAddressing;
static char *x_display_name = NULL; // X11 display name
Display *x_display = NULL; // X11 display handle
static int zero_fd = -1; // FD of /dev/zero
static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped
static uint8 last_xpram[256]; // Buffer for monitoring XPRAM changes
#ifdef HAVE_PTHREADS
static pthread_t emul_thread; // Handle of MacOS emulation thread (main thread)
static bool xpram_thread_active = false; // Flag: XPRAM watchdog installed
static volatile bool xpram_thread_cancel = false; // Flag: Cancel XPRAM thread
static pthread_t xpram_thread; // XPRAM watchdog
@ -88,24 +123,46 @@ static volatile bool tick_thread_cancel = false; // Flag: Cancel 60Hz thread
static pthread_t tick_thread; // 60Hz thread
static pthread_attr_t tick_thread_attr; // 60Hz thread attributes
#if EMULATED_68K
static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect InterruptFlags
#endif
#endif
#if !EMULATED_68K
#define SIG_IRQ SIGUSR1
static struct sigaction sigirq_sa; // Virtual 68k interrupt signal
static struct sigaction sigill_sa; // Illegal instruction
static void *sig_stack = NULL; // Stack for signal handlers
uint16 EmulatedSR; // Emulated bits of SR (supervisor bit and interrupt mask)
uint32 ScratchMem = NULL; // Scratch memory for Mac ROM writes
#endif
static struct sigaction timer_sa; // sigaction used for timer
#if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
#define SIG_TIMER SIGRTMIN
static struct sigaction timer_sa; // sigaction used for timer
static timer_t timer; // 60Hz timer
static timer_t timer; // 60Hz timer
#endif
#if ENABLE_MON
static struct sigaction sigint_sa; // sigaction for SIGINT handler
#ifdef ENABLE_MON
static struct sigaction sigint_sa; // sigaction for SIGINT handler
static void sigint_handler(...);
#endif
#ifdef USE_MAPPED_MEMORY
extern char *address_space, *good_address_map;
#endif
// Prototypes
static void *xpram_func(void *arg);
static void *tick_func(void *arg);
static void one_tick(...);
#if !EMULATED_68K
static void sigirq_handler(int sig, int code, struct sigcontext *scp);
static void sigill_handler(int sig, int code, struct sigcontext *scp);
extern "C" void EmulOpTrampoline(void);
#endif
/*
@ -132,6 +189,8 @@ char *strdup(const char *s)
int main(int argc, char **argv)
{
char str[256];
// Initialize variables
RAMBaseHost = NULL;
ROMBaseHost = NULL;
@ -161,12 +220,12 @@ int main(int argc, char **argv)
QuitEmulator();
}
#if ENABLE_XF86_DGA && !ENABLE_MON
#if defined(ENABLE_XF86_DGA) && !defined(ENABLE_MON)
// Fork out, so we can return from fullscreen mode when things get ugly
XF86DGAForkApp(DefaultScreen(x_display));
#endif
#if ENABLE_GTK
#ifdef ENABLE_GTK
// Init GTK
gtk_set_locale();
gtk_init(&argc, &argv);
@ -183,6 +242,14 @@ int main(int argc, char **argv)
if (!PrefsEditor())
QuitEmulator();
// Open /dev/zero
zero_fd = open("/dev/zero", O_RDWR);
if (zero_fd < 0) {
sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
// Read RAM size
RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary
if (RAMSize < 1024*1024) {
@ -190,18 +257,36 @@ int main(int argc, char **argv)
RAMSize = 1024*1024;
}
#if REAL_ADDRESSING
// Create Low Memory area (0x0000..0x2000)
if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
lm_area_mapped = true;
#endif
#if !EMULATED_68K
// Allocate scratch memory
ScratchMem = (uint32)malloc(SCRATCH_MEM_SIZE);
if (ScratchMem == NULL) {
ErrorAlert(GetString(STR_NO_MEM_ERR));
QuitEmulator();
}
ScratchMem += SCRATCH_MEM_SIZE/2; // ScratchMem points to middle of block
#endif
// Create areas for Mac RAM and ROM
#ifdef USE_MAPPED_MEMORY
int fd = open("/dev/zero", O_RDWR);
good_address_map = (char *)mmap(NULL, 1<<24, PROT_READ, MAP_PRIVATE, fd, 0);
address_space = (char *)mmap(NULL, 1<<24, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
#if defined(USE_MAPPED_MEMORY)
good_address_map = (char *)mmap(NULL, 1<<24, PROT_READ, MAP_PRIVATE, zero_fd, 0);
address_space = (char *)mmap(NULL, 1<<24, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
if ((int)address_space < 0 || (int)good_address_map < 0) {
ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
QuitEmulator();
}
RAMBaseHost = (uint8 *)mmap(address_space, RAMSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0);
ROMBaseHost = (uint8 *)mmap(address_space + 0x00400000, 0x80000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0);
close(fd);
RAMBaseHost = (uint8 *)mmap(address_space, RAMSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
ROMBaseHost = (uint8 *)mmap(address_space + 0x00400000, 0x80000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
char *nam = tmpnam(NULL);
int good_address_fd = open(nam, O_CREAT | O_RDWR, 0600);
char buffer[4096];
@ -216,6 +301,12 @@ int main(int argc, char **argv)
RAMBaseHost = new uint8[RAMSize];
ROMBaseHost = new uint8[0x100000];
#endif
#if REAL_ADDRESSING && !EMULATED_68K
RAMBaseMac = (uint32)RAMBaseHost;
ROMBaseMac = (uint32)ROMBaseHost;
#endif
D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
// Get rom file path from preferences
const char *rom_path = PrefsFindString("rom");
@ -240,27 +331,116 @@ int main(int argc, char **argv)
QuitEmulator();
}
#if !EMULATED_68K
// Get CPU model
int mib[2] = {CTL_HW, HW_MODEL};
char *model;
size_t model_len;
sysctl(mib, 2, NULL, &model_len, NULL, 0);
model = (char *)malloc(model_len);
sysctl(mib, 2, model, &model_len, NULL, 0);
D(bug("Model: %s\n", model));
// Set CPU and FPU type
CPUIs68060 = false;
if (strstr(model, "020"))
CPUType = 2;
else if (strstr(model, "030"))
CPUType = 3;
else if (strstr(model, "040"))
CPUType = 4;
else if (strstr(model, "060")) {
CPUType = 4;
CPUIs68060 = true;
} else {
printf("WARNING: Cannot detect CPU type, assuming 68020\n");
CPUType = 2;
}
FPUType = 0; //!!
TwentyFourBitAddressing = false;
#endif
// Initialize everything
if (!InitAll())
QuitEmulator();
D(bug("Initialization complete\n"));
// Start XPRAM watchdog thread
xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
#ifdef HAVE_PTHREADS
// Get handle of main thread
emul_thread = pthread_self();
#endif
#if !EMULATED_68K
// (Virtual) supervisor mode, disable interrupts
EmulatedSR = 0x2700;
// Create and install stack for signal handlers
sig_stack = malloc(SIG_STACK_SIZE);
D(bug("Signal stack at %p\n", sig_stack));
if (sig_stack == NULL) {
ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
QuitEmulator();
}
stack_t new_stack;
new_stack.ss_sp = sig_stack;
new_stack.ss_flags = 0;
new_stack.ss_size = SIG_STACK_SIZE;
if (sigaltstack(&new_stack, NULL) < 0) {
sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
// Install SIGILL handler for emulating privileged instructions and
// executing A-Trap and EMUL_OP opcodes
sigemptyset(&sigill_sa.sa_mask); // Block virtual 68k interrupts during SIGILL handling
sigaddset(&sigill_sa.sa_mask, SIG_IRQ);
sigaddset(&sigill_sa.sa_mask, SIGALRM);
sigill_sa.sa_handler = (void (*)(int))sigill_handler;
sigill_sa.sa_flags = SA_ONSTACK;
if (sigaction(SIGILL, &sigill_sa, NULL) < 0) {
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGILL", strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
// Install virtual 68k interrupt signal handler
sigemptyset(&sigirq_sa.sa_mask);
sigaddset(&sigirq_sa.sa_mask, SIGALRM);
sigirq_sa.sa_handler = (void (*)(int))sigirq_handler;
sigirq_sa.sa_flags = SA_ONSTACK | SA_RESTART;
if (sigaction(SIG_IRQ, &sigirq_sa, NULL) < 0) {
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_IRQ", strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
#endif
#ifdef ENABLE_MON
// Setup SIGINT handler to enter mon
sigemptyset(&sigint_sa.sa_mask);
sigint_sa.sa_handler = sigint_handler;
sigint_sa.sa_flags = 0;
sigaction(SIGINT, &sigint_sa, NULL);
#endif
#if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
// Start 60Hz timer
// POSIX.4 timers and real-time signals available, start 60Hz timer
sigemptyset(&timer_sa.sa_mask);
timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
timer_sa.sa_sigaction = one_tick;
timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) {
printf("FATAL: cannot set up timer signal handler\n");
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
struct sigevent timer_event;
timer_event.sigev_notify = SIGEV_SIGNAL;
timer_event.sigev_signo = SIG_TIMER;
if (timer_create(CLOCK_REALTIME, &timer_event, &timer) < 0) {
printf("FATAL: cannot create timer\n");
sprintf(str, GetString(STR_TIMER_CREATE_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
struct itimerspec req;
@ -269,13 +449,15 @@ int main(int argc, char **argv)
req.it_interval.tv_sec = 0;
req.it_interval.tv_nsec = 16625000;
if (timer_settime(timer, 0, &req, NULL) < 0) {
printf("FATAL: cannot start timer\n");
sprintf(str, GetString(STR_TIMER_SETTIME_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
D(bug("60Hz timer started\n"));
#else
#elif defined(HAVE_PTHREADS)
// Start 60Hz thread
// POSIX threads available, start 60Hz thread
pthread_attr_init(&tick_thread_attr);
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
if (geteuid() == 0) {
@ -288,20 +470,40 @@ int main(int argc, char **argv)
#endif
tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
if (!tick_thread_active) {
printf("FATAL: cannot create tick thread\n");
sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
D(bug("60Hz thread started\n"));
#else
// Start 60Hz timer
sigemptyset(&timer_sa.sa_mask); // Block virtual 68k interrupts during SIGARLM handling
sigaddset(&timer_sa.sa_mask, SIG_IRQ);
timer_sa.sa_handler = one_tick;
timer_sa.sa_flags = SA_ONSTACK | SA_RESTART;
if (sigaction(SIGALRM, &timer_sa, NULL) < 0) {
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGALRM", strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
struct itimerval req;
req.it_interval.tv_sec = req.it_value.tv_sec = 0;
req.it_interval.tv_usec = req.it_value.tv_usec = 16625;
setitimer(ITIMER_REAL, &req, NULL);
#endif
#if ENABLE_MON
// Setup SIGINT handler to enter mon
sigemptyset(&sigint_sa.sa_mask);
sigint_sa.sa_flags = 0;
sigint_sa.sa_handler = sigint_handler;
sigaction(SIGINT, &sigint_sa, NULL);
#ifdef HAVE_PTHREADS
// Start XPRAM watchdog thread
memcpy(last_xpram, XPRAM, 256);
xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
D(bug("XPRAM thread started\n"));
#endif
// Start 68k and jump to ROM boot routine
D(bug("Starting emulation...\n"));
Start680x0();
QuitEmulator();
@ -315,13 +517,17 @@ int main(int argc, char **argv)
void QuitEmulator(void)
{
D(bug("QuitEmulator\n"));
#if EMULATED_68K
// Exit 680x0 emulation
Exit680x0();
#endif
#if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
// Stop 60Hz timer
timer_delete(timer);
#else
#elif defined(HAVE_PTHREADS)
// Stop 60Hz thread
if (tick_thread_active) {
tick_thread_cancel = true;
@ -330,8 +536,14 @@ void QuitEmulator(void)
#endif
pthread_join(tick_thread, NULL);
}
#else
struct itimerval req;
req.it_interval.tv_sec = req.it_value.tv_sec = 0;
req.it_interval.tv_usec = req.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &req, NULL);
#endif
#ifdef HAVE_PTHREADS
// Stop XPRAM watchdog thread
if (xpram_thread_active) {
xpram_thread_cancel = true;
@ -340,6 +552,7 @@ void QuitEmulator(void)
#endif
pthread_join(xpram_thread, NULL);
}
#endif
// Deinitialize everything
ExitAll();
@ -350,6 +563,22 @@ void QuitEmulator(void)
// Delete RAM area
delete[] RAMBaseHost;
#if !EMULATED_68K
// Delete scratch memory area
if (ScratchMem)
free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
#endif
#if REAL_ADDRESSING
// Delete Low Memory area
if (lm_area_mapped)
munmap((char *)0x0000, 0x2000);
#endif
// Close /dev/zero
if (zero_fd > 0)
close(zero_fd);
// Exit system routines
SysExit();
@ -369,26 +598,30 @@ void QuitEmulator(void)
* or a dynamically recompiling emulator)
*/
#if EMULATED_68K
void FlushCodeCache(void *start, uint32 size)
{
}
#if !EMULATED_68K && defined(__NetBSD__)
m68k_sync_icache(start, size);
#endif
}
/*
* SIGINT handler, enters mon
*/
#if ENABLE_MON
extern void m68k_dumpstate(uaecptr *nextpc);
#ifdef ENABLE_MON
static void sigint_handler(...)
{
#if EMULATED_68K
uaecptr nextpc;
extern void m68k_dumpstate(uaecptr *nextpc);
m68k_dumpstate(&nextpc);
#else
char *arg[2] = {"rmon", NULL};
mon(1, arg);
QuitEmulator();
#endif
}
#endif
@ -399,35 +632,104 @@ static void sigint_handler(...)
uint32 InterruptFlags = 0;
#if EMULATED_68K
void SetInterruptFlag(uint32 flag)
{
#ifdef HAVE_PTHREADS
pthread_mutex_lock(&intflag_lock);
InterruptFlags |= flag;
pthread_mutex_unlock(&intflag_lock);
#else
InterruptFlags |= flag; // Pray that this is an atomic operation...
#endif
}
void ClearInterruptFlag(uint32 flag)
{
#ifdef HAVE_PTHREADS
pthread_mutex_lock(&intflag_lock);
InterruptFlags &= ~flag;
pthread_mutex_unlock(&intflag_lock);
#else
InterruptFlags &= ~flag;
#endif
}
#endif
#if !EMULATED_68K
void TriggerInterrupt(void)
{
#if defined(HAVE_PTHREADS)
pthread_kill(emul_thread, SIG_IRQ);
#else
raise(SIG_IRQ);
#endif
}
#endif
/*
* XPRAM watchdog thread (saves XPRAM every minute)
*/
static void xpram_watchdog(void)
{
if (memcmp(last_xpram, XPRAM, 256)) {
memcpy(last_xpram, XPRAM, 256);
SaveXPRAM();
}
}
#ifdef HAVE_PTHREADS
static void *xpram_func(void *arg)
{
while (!xpram_thread_cancel) {
for (int i=0; i<60 && !xpram_thread_cancel; i++) {
#ifdef HAVE_NANOSLEEP
struct timespec req = {1, 0};
nanosleep(&req, NULL);
#else
usleep(1000000);
#endif
}
xpram_watchdog();
}
return NULL;
}
#endif
/*
* 60Hz thread (really 60.15Hz)
*/
static void one_second(void)
{
// Pseudo Mac 1Hz interrupt, update local time
WriteMacInt32(0x20c, TimerDateTime());
#ifndef HAVE_PTHREADS
static int second_counter = 0;
if (++second_counter > 60) {
second_counter = 0;
xpram_watchdog();
}
#endif
}
static void one_tick(...)
{
static int tick_counter = 0;
// Pseudo Mac 1Hz interrupt, update local time
if (++tick_counter > 60) {
tick_counter = 0;
WriteMacInt32(0x20c, TimerDateTime());
one_second();
}
#ifndef HAVE_PTHREADS
// No threads available, perform video refresh from here
VideoRefresh();
#endif
// Trigger 60Hz interrupt
if (ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted()) {
SetInterruptFlag(INTFLAG_60HZ);
@ -435,6 +737,7 @@ static void one_tick(...)
}
}
#ifdef HAVE_PTHREADS
static void *tick_func(void *arg)
{
while (!tick_thread_cancel) {
@ -452,40 +755,294 @@ static void *tick_func(void *arg)
}
return NULL;
}
#endif
#if !EMULATED_68K
/*
* Virtual 68k interrupt handler
*/
static void sigirq_handler(int sig, int code, struct sigcontext *scp)
{
// Interrupts disabled? Then do nothing
if (EmulatedSR & 0x0700)
return;
struct sigstate *state = (struct sigstate *)scp->sc_ap;
M68kRegisters *regs = (M68kRegisters *)&state->ss_frame;
// Set up interrupt frame on stack
uint32 a7 = regs->a[7];
a7 -= 2;
WriteMacInt16(a7, 0x64);
a7 -= 4;
WriteMacInt32(a7, scp->sc_pc);
a7 -= 2;
WriteMacInt16(a7, scp->sc_ps | EmulatedSR);
scp->sc_sp = regs->a[7] = a7;
// Set interrupt level
EmulatedSR |= 0x2100;
// Jump to MacOS interrupt handler on return
scp->sc_pc = ReadMacInt32(0x64);
}
/*
* XPRAM watchdog thread (saves XPRAM every minute)
* SIGILL handler, for emulation of privileged instructions and executing
* A-Trap and EMUL_OP opcodes
*/
void *xpram_func(void *arg)
static void sigill_handler(int sig, int code, struct sigcontext *scp)
{
uint8 last_xpram[256];
memcpy(last_xpram, XPRAM, 256);
struct sigstate *state = (struct sigstate *)scp->sc_ap;
uint16 *pc = (uint16 *)scp->sc_pc;
uint16 opcode = *pc;
M68kRegisters *regs = (M68kRegisters *)&state->ss_frame;
while (!xpram_thread_cancel) {
for (int i=0; i<60 && !xpram_thread_cancel; i++) {
#ifdef HAVE_NANOSLEEP
struct timespec req = {1, 0};
nanosleep(&req, NULL);
#else
usleep(1000000);
#define INC_PC(n) scp->sc_pc += (n)
#define GET_SR (scp->sc_ps | EmulatedSR)
#define STORE_SR(v) \
scp->sc_ps = (v) & 0xff; \
EmulatedSR = (v) & 0x2700; \
if (((v) & 0x0700) == 0 && InterruptFlags) \
TriggerInterrupt();
//printf("opcode %04x at %p, sr %04x, emul_sr %04x\n", opcode, pc, scp->sc_ps, EmulatedSR);
if ((opcode & 0xf000) == 0xa000) {
// A-Line instruction, set up A-Line trap frame on stack
uint32 a7 = regs->a[7];
a7 -= 2;
WriteMacInt16(a7, 0x28);
a7 -= 4;
WriteMacInt32(a7, (uint32)pc);
a7 -= 2;
WriteMacInt16(a7, GET_SR);
scp->sc_sp = regs->a[7] = a7;
// Jump to MacOS A-Line handler on return
scp->sc_pc = ReadMacInt32(0x28);
} else if ((opcode & 0xff00) == 0x7100) {
// Extended opcode, push registers on user stack
uint32 a7 = regs->a[7];
a7 -= 4;
WriteMacInt32(a7, (uint32)pc);
a7 -= 2;
WriteMacInt16(a7, scp->sc_ps);
for (int i=7; i>=0; i--) {
a7 -= 4;
WriteMacInt32(a7, regs->a[i]);
}
for (int i=7; i>=0; i--) {
a7 -= 4;
WriteMacInt32(a7, regs->d[i]);
}
scp->sc_sp = regs->a[7] = a7;
// Jump to EmulOp trampoline code on return
scp->sc_pc = (uint32)EmulOpTrampoline;
} else switch (opcode) { // Emulate privileged instructions
case 0x40e7: // move sr,-(sp)
regs->a[7] -= 2;
WriteMacInt16(regs->a[7], GET_SR);
scp->sc_sp = regs->a[7];
INC_PC(2);
break;
case 0x46df: { // move (sp)+,sr
uint16 sr = ReadMacInt16(regs->a[7]);
STORE_SR(sr);
regs->a[7] += 2;
scp->sc_sp = regs->a[7];
INC_PC(2);
break;
}
case 0x007c: { // ori #xxxx,sr
uint16 sr = GET_SR | pc[1];
scp->sc_ps = sr & 0xff; // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR
EmulatedSR = sr & 0x2700;
INC_PC(4);
break;
}
case 0x027c: { // andi #xxxx,sr
uint16 sr = GET_SR & pc[1];
STORE_SR(sr);
INC_PC(4);
break;
}
case 0x46fc: // move #xxxx,sr
STORE_SR(pc[1]);
INC_PC(4);
break;
case 0x46ef: { // move (xxxx,sp),sr
uint16 sr = ReadMacInt16(regs->a[7] + (int32)(int16)pc[1]);
STORE_SR(sr);
INC_PC(4);
break;
}
case 0x46d8: // move (a0)+,sr
case 0x46d9: { // move (a1)+,sr
uint16 sr = ReadMacInt16(regs->a[opcode & 7]);
STORE_SR(sr);
regs->a[opcode & 7] += 2;
INC_PC(2);
break;
}
case 0x40f8: // move sr,xxxx.w
WriteMacInt16(pc[1], GET_SR);
INC_PC(4);
break;
case 0x40d0: // move sr,(a0)
case 0x40d1: // move sr,(a1)
case 0x40d2: // move sr,(a2)
case 0x40d3: // move sr,(a3)
case 0x40d4: // move sr,(a4)
case 0x40d5: // move sr,(a5)
case 0x40d6: // move sr,(a6)
case 0x40d7: // move sr,(sp)
WriteMacInt16(regs->a[opcode & 7], GET_SR);
INC_PC(2);
break;
case 0x40c0: // move sr,d0
case 0x40c1: // move sr,d1
case 0x40c2: // move sr,d2
case 0x40c3: // move sr,d3
case 0x40c4: // move sr,d4
case 0x40c5: // move sr,d5
case 0x40c6: // move sr,d6
case 0x40c7: // move sr,d7
regs->d[opcode & 7] = GET_SR;
INC_PC(2);
break;
case 0x46c0: // move d0,sr
case 0x46c1: // move d1,sr
case 0x46c2: // move d2,sr
case 0x46c3: // move d3,sr
case 0x46c4: // move d4,sr
case 0x46c5: // move d5,sr
case 0x46c6: // move d6,sr
case 0x46c7: { // move d7,sr
uint16 sr = regs->d[opcode & 7];
STORE_SR(sr);
INC_PC(2);
break;
}
case 0xf327: // fsave -(sp)
goto ill; //!!
case 0xf35f: // frestore (sp)+
goto ill; //!!
case 0x4e73: { // rte (only handles format 0)
uint32 a7 = regs->a[7];
uint16 sr = ReadMacInt16(a7);
a7 += 2;
scp->sc_ps = sr & 0xff;
EmulatedSR = sr & 0x2700;
scp->sc_pc = ReadMacInt32(a7);
a7 += 6;
scp->sc_sp = regs->a[7] = a7;
break;
}
case 0x4e7a: // movec cr,x
switch (pc[1]) {
case 0x8801: // movec vbr,a0
regs->a[0] = 0;
break;
case 0x9801: // movec vbr,a1
regs->a[1] = 0;
break;
case 0x0002: // movec cacr,d0
regs->d[0] = 0x3111;
break;
case 0x1002: // movec cacr,d1
regs->d[1] = 0x3111;
break;
case 0x0003: // movec tc,d0
regs->d[0] = 0;
break;
case 0x1003: // movec tc,d1
regs->d[1] = 0;
break;
default:
goto ill;
}
INC_PC(4);
break;
case 0x4e7b: // movec x,cr
switch (pc[1]) {
case 0x0801: // movec d0,vbr
break;
case 0x0002: // movec d0,cacr
case 0x1002: // movec d1,cacr
FlushCodeCache(NULL, 0);
break;
default:
goto ill;
}
INC_PC(4);
break;
case 0xf478: // cpusha dc
case 0xf4f8: // cpusha dc/ic
FlushCodeCache(NULL, 0);
INC_PC(2);
break;
default:
ill: printf("SIGILL num %d, code %d\n", sig, code);
printf(" context %p:\n", scp);
printf(" onstack %08x\n", scp->sc_onstack);
printf(" sp %08x\n", scp->sc_sp);
printf(" fp %08x\n", scp->sc_fp);
printf(" pc %08x\n", scp->sc_pc);
printf(" opcode %04x\n", opcode);
printf(" sr %08x\n", scp->sc_ps);
printf(" state %p:\n", state);
printf(" flags %d\n", state->ss_flags);
for (int i=0; i<8; i++)
printf(" d%d %08x\n", i, state->ss_frame.f_regs[i]);
for (int i=0; i<8; i++)
printf(" a%d %08x\n", i, state->ss_frame.f_regs[i+8]);
#ifdef ENABLE_MON
char *arg[2] = {"rmon", NULL};
mon(1, arg);
#endif
}
if (memcmp(last_xpram, XPRAM, 256)) {
memcpy(last_xpram, XPRAM, 256);
SaveXPRAM();
}
QuitEmulator();
break;
}
return NULL;
}
#endif
/*
* Display alert
*/
#if ENABLE_GTK
#ifdef ENABLE_GTK
static void dl_destroyed(void)
{
gtk_main_quit();
@ -530,7 +1087,7 @@ void display_alert(int title_id, int prefix_id, int button_id, const char *text)
void ErrorAlert(const char *text)
{
#if ENABLE_GTK
#ifdef ENABLE_GTK
if (PrefsFindBool("nogui") || x_display == NULL) {
printf(GetString(STR_SHELL_ERROR_PREFIX), text);
return;
@ -549,7 +1106,7 @@ void ErrorAlert(const char *text)
void WarningAlert(const char *text)
{
#if ENABLE_GTK
#ifdef ENABLE_GTK
if (PrefsFindBool("nogui") || x_display == NULL) {
printf(GetString(STR_SHELL_WARNING_PREFIX), text);
return;

View File

@ -25,10 +25,12 @@
* with mutex. Seems to be working correctly now.
*/
#include <stdio.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#include "semaphore.h"
extern "C" {
@ -62,7 +64,6 @@ int sem_destroy(sem_t* sem)
}
pthread_mutex_destroy(&sem->sem_lock);
sem->sem_waiting = 0;
sem->sem_lock = NULL;
sem->sem_value = 0;
return 0;
}

View File

@ -525,7 +525,7 @@ static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
static int display_type;
static int dis_width, dis_height;
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
static GtkWidget *w_fbdev_name, *w_fbdevice_file;
static GtkWidget *l_fbdev_name, *l_fbdevice_file;
static char fbdev_name[256];
@ -537,7 +537,7 @@ static void hide_show_graphics_widgets(void)
switch (display_type) {
case DISPLAY_WINDOW:
gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
@ -545,7 +545,7 @@ static void hide_show_graphics_widgets(void)
break;
case DISPLAY_SCREEN:
gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
@ -588,7 +588,7 @@ static void parse_graphics_prefs(void)
display_type = DISPLAY_WINDOW;
dis_width = 512;
dis_height = 384;
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
fbdev_name[0] = 0;
#endif
@ -596,7 +596,7 @@ static void parse_graphics_prefs(void)
if (str) {
if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
display_type = DISPLAY_WINDOW;
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
#else
else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
@ -622,7 +622,7 @@ static void read_graphics_settings(void)
sprintf(pref, "win/%d/%d", dis_width, dis_height);
break;
case DISPLAY_SCREEN:
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
sprintf(pref, "dga/%s", str);
#else
@ -746,7 +746,7 @@ static void create_graphics_pane(GtkWidget *top)
gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
w_display_y = GTK_COMBO(combo)->entry;
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
gtk_widget_show(l_fbdev_name);
gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
@ -1021,6 +1021,7 @@ static void create_memory_pane(GtkWidget *top)
}
make_option_menu(box, STR_MODELID_CTRL, model_options, active);
#if EMULATED_68K
static const opt_desc cpu_options[] = {
{STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
{STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
@ -1038,6 +1039,7 @@ static void create_memory_pane(GtkWidget *top)
case 4: active = 4;
}
make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
#endif
w_rom_file = make_entry(box, STR_ROM_FILE_CTRL, "rom");

View File

@ -42,7 +42,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
@ -60,18 +59,34 @@
#endif
/* Are the Mac and the host address space the same? */
#ifdef ENABLE_NATIVE_M68K
/* Mac and host address space are the same */
#define REAL_ADDRESSING 1
/* Using 68k natively */
#define EMULATED_68K 0
/* Mac ROM is not write protected */
#define ROM_IS_WRITE_PROTECTED 0
#else
/* Mac and host address space are distinct */
#define REAL_ADDRESSING 0
/* Are we using a 68k emulator or the real thing? */
/* Using 68k emulator */
#define EMULATED_68K 1
/* Is the Mac ROM write protected? */
/* Mac ROM is write protected */
#define ROM_IS_WRITE_PROTECTED 1
#endif
/* ExtFS is supported */
#define SUPPORTS_EXTFS 1
/* Data types */
typedef unsigned char uint8;
typedef signed char int8;

View File

@ -24,6 +24,11 @@
#define DEBUG 0
#include "debug.h"
// For NetBSD with broken pthreads headers
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif
/*
* Return microseconds since boot (64 bit)

View File

@ -37,6 +37,13 @@ user_string_def platform_strings[] = {
{STR_NO_FBDEVICE_FILE_ERR, "Cannot open frame buffer device specification file %s (%s)."},
{STR_FBDEV_NAME_ERR, "The %s frame buffer is not supported in %d bit mode."},
{STR_FBDEV_MMAP_ERR, "Cannot mmap() the frame buffer memory (%s)."},
{STR_NO_DEV_ZERO_ERR, "Cannot open /dev/zero (%s)."},
{STR_LOW_MEM_MMAP_ERR, "Cannot map Low Memory Globals (%s)."},
{STR_SIGALTSTACK_ERR, "Cannot install alternate signal stack (%s)."},
{STR_SIG_INSTALL_ERR, "Cannot install %s handler (%s)."},
{STR_TIMER_CREATE_ERR, "Cannot create timer (%s)."},
{STR_TIMER_SETTIME_ERR, "Cannot start timer (%s)."},
{STR_TICK_THREAD_ERR, "Cannot create 60Hz thread (%s)."},
{STR_NO_SHEEP_NET_DRIVER_WARN, "Cannot open %s (%s). Ethernet will not be available."},
{STR_SHEEP_NET_ATTACH_WARN, "Cannot attach to Ethernet card (%s). Ethernet will not be available."},

View File

@ -28,6 +28,13 @@ enum {
STR_NO_FBDEVICE_FILE_ERR,
STR_FBDEV_NAME_ERR,
STR_FBDEV_MMAP_ERR,
STR_NO_DEV_ZERO_ERR,
STR_LOW_MEM_MMAP_ERR,
STR_SIGALTSTACK_ERR,
STR_SIG_INSTALL_ERR,
STR_TIMER_CREATE_ERR,
STR_TIMER_SETTIME_ERR,
STR_TICK_THREAD_ERR,
STR_NO_SHEEP_NET_DRIVER_WARN,
STR_SHEEP_NET_ATTACH_WARN,

View File

@ -34,9 +34,24 @@
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <errno.h>
#ifdef HAVE_PTHREADS
# include <pthread.h>
#endif
#ifdef ENABLE_XF86_DGA
# include <X11/extensions/xf86dga.h>
#endif
#ifdef ENABLE_XF86_VIDMODE
# include <X11/extensions/xf86vmode.h>
#endif
#ifdef ENABLE_FBDEV_DGA
# include <sys/mman.h>
#endif
#include "cpu_emulation.h"
#include "main.h"
#include "adb.h"
@ -48,19 +63,6 @@
#define DEBUG 1
#include "debug.h"
#if ENABLE_XF86_DGA
#include <X11/extensions/xf86dga.h>
#endif
#if ENABLE_XF86_VIDMODE
#include <X11/extensions/xf86vmode.h>
#endif
#if ENABLE_FBDEV_DGA
#include <sys/mman.h>
#endif
// Display types
enum {
@ -80,9 +82,12 @@ static int16 mouse_wheel_lines = 3;
static int display_type = DISPLAY_WINDOW; // See enum above
static uint8 *the_buffer; // Mac frame buffer
#ifdef HAVE_PTHREADS
static bool redraw_thread_active = false; // Flag: Redraw thread installed
static volatile bool redraw_thread_cancel = false; // Flag: Cancel Redraw thread
static pthread_t redraw_thread; // Redraw thread
#endif
static bool has_dga = false; // Flag: Video DGA capable
static bool has_vidmode = false; // Flag: VidMode extension available
@ -112,9 +117,11 @@ static int eventmask;
static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask;
static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
static pthread_mutex_t palette_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect palette
static XColor palette[256]; // Color palette for 8-bit mode
static bool palette_changed = false; // Flag: Palette changed, redraw thread must set new colors
#ifdef HAVE_PTHREADS
static pthread_mutex_t palette_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect palette
#endif
// Variables for window mode
static GC the_gc;
@ -136,13 +143,15 @@ static int sm_no_boxes[] = {1,8,32,64,128,300};
static int current_dga_cmap; // Number (0 or 1) of currently installed DGA colormap
static Window suspend_win; // "Suspend" window
static void *fb_save = NULL; // Saved frame buffer for suspend
#ifdef HAVE_PTHREADS
static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect frame buffer
#endif
// Variables for fbdev DGA mode
const char FBDEVICE_FILE_NAME[] = "/dev/fb";
static int fbdev_fd;
#if ENABLE_XF86_VIDMODE
#ifdef ENABLE_XF86_VIDMODE
// Variables for XF86 VidMode support
static XF86VidModeModeInfo **x_video_modes; // Array of all available modes
static int num_x_video_modes;
@ -168,37 +177,52 @@ extern void SysMountFirstFloppy(void);
// Set VideoMonitor according to video mode
void set_video_monitor(int width, int height, int bytes_per_row, bool native_byte_order)
{
#if !REAL_ADDRESSING
int layout = FLAYOUT_DIRECT;
switch (depth) {
case 1:
layout = FLAYOUT_DIRECT;
VideoMonitor.mode = VMODE_1BIT;
break;
case 8:
layout = FLAYOUT_DIRECT;
VideoMonitor.mode = VMODE_8BIT;
break;
case 15:
layout = FLAYOUT_HOST_555;
VideoMonitor.mode = VMODE_16BIT;
break;
case 16:
layout = FLAYOUT_HOST_565;
VideoMonitor.mode = VMODE_16BIT;
break;
case 24:
case 32:
layout = FLAYOUT_HOST_888;
break;
}
if (native_byte_order)
MacFrameLayout = layout;
else
MacFrameLayout = FLAYOUT_DIRECT;
#endif
switch (depth) {
case 1:
VideoMonitor.mode = VMODE_1BIT;
break;
case 8:
VideoMonitor.mode = VMODE_8BIT;
break;
case 15:
VideoMonitor.mode = VMODE_16BIT;
break;
case 16:
VideoMonitor.mode = VMODE_16BIT;
break;
case 24:
case 32:
VideoMonitor.mode = VMODE_32BIT;
break;
}
VideoMonitor.x = width;
VideoMonitor.y = height;
VideoMonitor.bytes_per_row = bytes_per_row;
if (native_byte_order)
MacFrameLayout = layout;
else
MacFrameLayout = FLAYOUT_DIRECT;
}
// Trap SHM errors
@ -340,7 +364,6 @@ static bool init_window(int width, int height)
#if REAL_ADDRESSING
VideoMonitor.mac_frame_base = (uint32)the_buffer;
MacFrameLayout = FLAYOUT_DIRECT;
#else
VideoMonitor.mac_frame_base = MacFrameBaseMac;
#endif
@ -350,7 +373,7 @@ static bool init_window(int width, int height)
// Init fbdev DGA display
static bool init_fbdev_dga(char *in_fb_name)
{
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
// Find the maximum depth available
int ndepths, max_depth(0);
int *depths = XListDepths(x_display, screen, &ndepths);
@ -476,7 +499,6 @@ static bool init_fbdev_dga(char *in_fb_name)
set_video_monitor(width, height, bytes_per_row, true);
#if REAL_ADDRESSING
VideoMonitor.mac_frame_base = (uint32)the_buffer;
MacFrameLayout = FLAYOUT_DIRECT;
#else
VideoMonitor.mac_frame_base = MacFrameBaseMac;
#endif
@ -490,11 +512,11 @@ static bool init_fbdev_dga(char *in_fb_name)
// Init XF86 DGA display
static bool init_xf86_dga(int width, int height)
{
#if ENABLE_XF86_DGA
#ifdef ENABLE_XF86_DGA
// Set relative mouse mode
ADBSetRelMouseMode(true);
#if ENABLE_XF86_VIDMODE
#ifdef ENABLE_XF86_VIDMODE
// Switch to best mode
if (has_vidmode) {
int best = 0;
@ -652,7 +674,7 @@ bool VideoInit(bool classic)
// Get screen depth
xdepth = DefaultDepth(x_display, screen);
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
// Frame buffer name
char fb_name[20];
@ -663,7 +685,7 @@ bool VideoInit(bool classic)
has_dga = false;
#endif
#if ENABLE_XF86_DGA
#ifdef ENABLE_XF86_DGA
// DGA available?
int dga_event_base, dga_error_base;
if (XF86DGAQueryExtension(x_display, &dga_event_base, &dga_error_base)) {
@ -674,7 +696,7 @@ bool VideoInit(bool classic)
has_dga = false;
#endif
#if ENABLE_XF86_VIDMODE
#ifdef ENABLE_XF86_VIDMODE
// VidMode available?
int vm_event_base, vm_error_base;
has_vidmode = XF86VidModeQueryExtension(x_display, &vm_event_base, &vm_error_base);
@ -747,7 +769,7 @@ bool VideoInit(bool classic)
if (mode_str) {
if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
display_type = DISPLAY_WINDOW;
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
else if (has_dga && sscanf(mode_str, "dga/%19s", fb_name) == 1) {
#else
else if (has_dga && sscanf(mode_str, "dga/%d/%d", &width, &height) == 2) {
@ -771,7 +793,7 @@ bool VideoInit(bool classic)
return false;
break;
case DISPLAY_DGA:
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
if (!init_fbdev_dga(fb_name))
#else
if (!init_xf86_dga(width, height))
@ -780,8 +802,10 @@ bool VideoInit(bool classic)
break;
}
#ifdef HAVE_PTHREADS
// Lock down frame buffer
pthread_mutex_lock(&frame_buffer_lock);
#endif
#if !REAL_ADDRESSING
// Set variables for UAE memory mapping
@ -793,12 +817,17 @@ bool VideoInit(bool classic)
MacFrameLayout = FLAYOUT_NONE;
#endif
// Start redraw/input thread
XSync(x_display, false);
#ifdef HAVE_PTHREADS
// Start redraw/input thread
redraw_thread_active = (pthread_create(&redraw_thread, NULL, redraw_func, NULL) == 0);
if (!redraw_thread_active)
if (!redraw_thread_active) {
printf("FATAL: cannot create redraw thread\n");
return redraw_thread_active;
return false;
}
#endif
return true;
}
@ -808,6 +837,7 @@ bool VideoInit(bool classic)
void VideoExit(void)
{
#ifdef HAVE_PTHREADS
// Stop redraw thread
if (redraw_thread_active) {
redraw_thread_cancel = true;
@ -817,15 +847,18 @@ void VideoExit(void)
pthread_join(redraw_thread, NULL);
redraw_thread_active = false;
}
#endif
#ifdef HAVE_PTHREADS
// Unlock frame buffer
pthread_mutex_unlock(&frame_buffer_lock);
#endif
// Close window and server connection
if (x_display != NULL) {
XSync(x_display, false);
#if ENABLE_XF86_DGA
#ifdef ENABLE_XF86_DGA
if (display_type == DISPLAY_DGA) {
XF86DGADirectVideo(x_display, screen, 0);
XUngrabPointer(x_display, CurrentTime);
@ -833,12 +866,12 @@ void VideoExit(void)
}
#endif
#if ENABLE_XF86_VIDMODE
#ifdef ENABLE_XF86_VIDMODE
if (has_vidmode && display_type == DISPLAY_DGA)
XF86VidModeSwitchToMode(x_display, screen, x_video_modes[0]);
#endif
#if ENABLE_FBDEV_DGA
#ifdef ENABLE_FBDEV_DGA
if (display_type == DISPLAY_DGA) {
XUngrabPointer(x_display, CurrentTime);
XUngrabKeyboard(x_display, CurrentTime);
@ -888,10 +921,12 @@ void VideoInterrupt(void)
if (emerg_quit)
QuitEmulator();
#ifdef HAVE_PTHREADS
// Temporarily give up frame buffer lock (this is the point where
// we are suspended when the user presses Ctrl-Tab)
pthread_mutex_unlock(&frame_buffer_lock);
pthread_mutex_lock(&frame_buffer_lock);
#endif
}
@ -901,7 +936,9 @@ void VideoInterrupt(void)
void video_set_palette(uint8 *pal)
{
#ifdef HAVE_PTHREDS
pthread_mutex_lock(&palette_lock);
#endif
// Convert colors to XColor array
for (int i=0; i<256; i++) {
@ -915,7 +952,9 @@ void video_set_palette(uint8 *pal)
// Tell redraw thread to change palette
palette_changed = true;
#ifdef HAVE_PTHREADS
pthread_mutex_unlock(&palette_lock);
#endif
}
@ -923,7 +962,7 @@ void video_set_palette(uint8 *pal)
* Suspend/resume emulator
*/
#if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
static void suspend_emul(void)
{
if (display_type == DISPLAY_DGA) {
@ -931,8 +970,10 @@ static void suspend_emul(void)
ADBKeyUp(0x36);
ctrl_down = false;
#ifdef HAVE_PTHREADS
// Lock frame buffer (this will stop the MacOS thread)
pthread_mutex_lock(&frame_buffer_lock);
#endif
// Save frame buffer
fb_save = malloc(VideoMonitor.y * VideoMonitor.bytes_per_row);
@ -940,7 +981,7 @@ static void suspend_emul(void)
memcpy(fb_save, the_buffer, VideoMonitor.y * VideoMonitor.bytes_per_row);
// Close full screen display
#if ENABLE_XF86_DGA
#ifdef ENABLE_XF86_DGA
XF86DGADirectVideo(x_display, screen, 0);
#endif
XUngrabPointer(x_display, CurrentTime);
@ -981,7 +1022,7 @@ static void resume_emul(void)
XSync(x_display, false);
XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
#if ENABLE_XF86_DGA
#ifdef ENABLE_XF86_DGA
XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
XF86DGASetViewPort(x_display, screen, 0, 0);
#endif
@ -994,14 +1035,16 @@ static void resume_emul(void)
fb_save = NULL;
}
#ifdef ENABLE_XF86_DGA
if (depth == 8)
#if ENABLE_XF86_DGA
XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
#endif
#ifdef HAVE_PTHREADS
// Unlock frame buffer (and continue MacOS thread)
pthread_mutex_unlock(&frame_buffer_lock);
emul_suspended = false;
#endif
}
#endif
@ -1063,7 +1106,7 @@ static int kc_decode(KeySym ks)
case XK_period: case XK_greater: return 0x2f;
case XK_slash: case XK_question: return 0x2c;
#if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
case XK_Tab: if (ctrl_down) {suspend_emul(); return -1;} else return 0x30;
#else
case XK_Tab: return 0x30;
@ -1242,7 +1285,7 @@ static void handle_events(void)
if (code == 0x36)
ctrl_down = true;
} else {
#if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
if (code == 0x31)
resume_emul(); // Space wakes us up
#endif
@ -1378,72 +1421,69 @@ static void update_display(int ticker)
* Thread for screen refresh, input handling etc.
*/
void VideoRefresh(void)
{
#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
// Quit DGA mode if requested
if (quit_full_screen) {
quit_full_screen = false;
if (display_type == DISPLAY_DGA) {
#ifdef ENABLE_XF86_DGA
XF86DGADirectVideo(x_display, screen, 0);
#endif
XUngrabPointer(x_display, CurrentTime);
XUngrabKeyboard(x_display, CurrentTime);
XUnmapWindow(x_display, the_win);
XSync(x_display, false);
}
}
#endif
// Handle X events
handle_events();
// Handle palette changes
#ifdef HAVE_PTHREADS
pthread_mutex_lock(&palette_lock);
#endif
if (palette_changed) {
palette_changed = false;
if (depth == 8) {
XStoreColors(x_display, cmap[0], palette, 256);
XStoreColors(x_display, cmap[1], palette, 256);
#ifdef ENABLE_XF86_DGA
if (display_type == DISPLAY_DGA) {
current_dga_cmap ^= 1;
XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
}
#endif
}
}
#ifdef HAVE_PTHREADS
pthread_mutex_unlock(&palette_lock);
#endif
// In window mode, update display
static int tick_counter = 0;
if (display_type == DISPLAY_WINDOW) {
tick_counter++;
update_display(tick_counter);
}
}
#ifdef HAVE_PTHREADS
static void *redraw_func(void *arg)
{
int tick_counter = 0;
while (!redraw_thread_cancel) {
// Wait
#ifdef HAVE_NANOSLEEP
struct timespec req = {0, 16666667};
nanosleep(&req, NULL);
#else
usleep(16667);
#endif
#if ENABLE_XF86_DGA
// Quit DGA mode if requested
if (quit_full_screen) {
quit_full_screen = false;
if (display_type == DISPLAY_DGA) {
XF86DGADirectVideo(x_display, screen, 0);
XUngrabPointer(x_display, CurrentTime);
XUngrabKeyboard(x_display, CurrentTime);
XUnmapWindow(x_display, the_win);
XSync(x_display, false);
}
}
#endif
#if ENABLE_FBDEV_DGA
// Quit DGA mode if requested
if (quit_full_screen) {
quit_full_screen = false;
if (display_type == DISPLAY_DGA) {
XUngrabPointer(x_display, CurrentTime);
XUngrabKeyboard(x_display, CurrentTime);
XUnmapWindow(x_display, the_win);
XSync(x_display, false);
}
}
#endif
// Handle X events
handle_events();
// Handle palette changes
pthread_mutex_lock(&palette_lock);
if (palette_changed) {
palette_changed = false;
if (depth == 8) {
XStoreColors(x_display, cmap[0], palette, 256);
XStoreColors(x_display, cmap[1], palette, 256);
#if ENABLE_XF86_DGA
if (display_type == DISPLAY_DGA) {
current_dga_cmap ^= 1;
XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
}
#endif
}
}
pthread_mutex_unlock(&palette_lock);
// In window mode, update display
if (display_type == DISPLAY_WINDOW) {
tick_counter++;
update_display(tick_counter);
}
VideoRefresh();
}
return NULL;
}
#endif