mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-09-07 16:54:28 +00:00
- first version to run natively on NetBSD/m68k
This commit is contained in:
parent
322bb38408
commit
ff5fcd83a7
@ -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)
|
||||
|
@ -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). */
|
||||
|
246
BasiliskII/src/Unix/asm_support.s
Normal file
246
BasiliskII/src/Unix/asm_support.s
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
710
BasiliskII/src/Unix/configure
vendored
710
BasiliskII/src/Unix/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -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\")."
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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."},
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user