mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-07-08 12:29:01 +00:00
- ADB has its own interrupt flag, INTFLAG_ADB
- ADBMouseMoved(), ADBMouseDown/Up() and ADBKeyDown/Up() trigger the ADB interrupt - ADB mutex is only used for mouse movement (the only input state where it matters) - adb.cpp: toggling relative mouse mode resets mouse_x/y - PrimeTime(0) schedules a timer task with 0 delay time; this is still not the correct implementation, but it makes MacSyndicate work... - Unix: pthreads are preferred to POSIX.4 timers for 60Hz ticks because the timers drift badly under Linux and the thread can compensate for drifting well enough - Unix: moved GetTicks_usec() and Delay_usec() to timer_unix.cpp - video_x.cpp: X mouse acceleration is disabled in relative mouse mode because MacOS does its own acceleration - video_x.cpp: palette[].pixel and palette[].flags are always preset - video_x.cpp: decoupled X event handling from 60Hz video refresh cycle by using select() with a timeout on the X fd
This commit is contained in:
parent
8d733ed691
commit
5868a40a37
@ -7,10 +7,15 @@ V1.0 (snapshot) - <date>
|
|||||||
thread-safe mouse handling
|
thread-safe mouse handling
|
||||||
- the TIME_OFFSET constant has been replaced by a (portable) function
|
- the TIME_OFFSET constant has been replaced by a (portable) function
|
||||||
TimeToMacTime(); file dates in ExtFS should now be correct
|
TimeToMacTime(); file dates in ExtFS should now be correct
|
||||||
|
- ADBInterrupt() is no longer called from the 60Hz interrupt but has
|
||||||
|
its own interrupt flag, potentially increasing the smoothness of
|
||||||
|
mouse movement
|
||||||
- Unix: windowed display mode supports different resolutions and color
|
- Unix: windowed display mode supports different resolutions and color
|
||||||
depth, which can be switched on-the-fly
|
depths, which can be switched on-the-fly
|
||||||
- Unix: Ctrl-F5 grabs mouse in windowed mode (enhanced compatibility
|
- Unix: Ctrl-F5 grabs mouse in windowed mode (enhanced compatibility
|
||||||
with games like flight simulators)
|
with games like flight simulators)
|
||||||
|
- Unix: X11 events are handled as soon as they arrive, outside of the
|
||||||
|
60Hz video refresh raster
|
||||||
- Unix: audio sample rate, bit depth and channel count are adjustable
|
- Unix: audio sample rate, bit depth and channel count are adjustable
|
||||||
in the MacOS "Sound" control panel
|
in the MacOS "Sound" control panel
|
||||||
|
|
||||||
|
@ -616,9 +616,14 @@ Keyboard:
|
|||||||
On PC-style keyboards, "Alt" is the Mac "Command" key, while the "Windows"
|
On PC-style keyboards, "Alt" is the Mac "Command" key, while the "Windows"
|
||||||
key is the Mac "Option" key.
|
key is the Mac "Option" key.
|
||||||
|
|
||||||
|
Mouse:
|
||||||
|
Under Unix, press Ctrl-F5 while the Basilisk II window is active will grab
|
||||||
|
the mouse. This is needed for compatibility with some MacOS programs,
|
||||||
|
especially games. Press Ctrl-F5 again to return to normal mouse operation.
|
||||||
|
|
||||||
Floppy:
|
Floppy:
|
||||||
Basilisk II can only handle 1.44MB MFM floppies. Depending on your platform,
|
Basilisk II can only handle 1.44MB MFM floppies. Depending on your platform,
|
||||||
flopyy disk changes might not be detected automatically. Under Linux, press
|
floppy disk changes might not be detected automatically. Under Unix, press
|
||||||
Ctrl-F1 to mount a floppy. Under BeOS, select the appropriate "Mount" menu
|
Ctrl-F1 to mount a floppy. Under BeOS, select the appropriate "Mount" menu
|
||||||
item or press Ctrl-F1 to mount a floppy. Under Windows, press Ctrl-Shift-F11.
|
item or press Ctrl-F1 to mount a floppy. Under Windows, press Ctrl-Shift-F11.
|
||||||
|
|
||||||
|
@ -475,7 +475,28 @@ int main(int argc, char **argv)
|
|||||||
sigaction(SIGINT, &sigint_sa, NULL);
|
sigaction(SIGINT, &sigint_sa, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
|
#if defined(HAVE_PTHREADS)
|
||||||
|
|
||||||
|
// POSIX threads available, start 60Hz thread
|
||||||
|
pthread_attr_init(&tick_thread_attr);
|
||||||
|
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
|
||||||
|
if (geteuid() == 0) {
|
||||||
|
pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
|
||||||
|
pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
|
||||||
|
struct sched_param fifo_param;
|
||||||
|
fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
|
||||||
|
pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
|
||||||
|
if (!tick_thread_active) {
|
||||||
|
sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
|
||||||
|
ErrorAlert(str);
|
||||||
|
QuitEmulator();
|
||||||
|
}
|
||||||
|
D(bug("60Hz thread started\n"));
|
||||||
|
|
||||||
|
#elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
|
||||||
|
|
||||||
// POSIX.4 timers and real-time signals available, start 60Hz timer
|
// POSIX.4 timers and real-time signals available, start 60Hz timer
|
||||||
sigemptyset(&timer_sa.sa_mask);
|
sigemptyset(&timer_sa.sa_mask);
|
||||||
@ -506,27 +527,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
D(bug("60Hz timer started\n"));
|
D(bug("60Hz timer started\n"));
|
||||||
|
|
||||||
#elif defined(HAVE_PTHREADS)
|
|
||||||
|
|
||||||
// POSIX threads available, start 60Hz thread
|
|
||||||
pthread_attr_init(&tick_thread_attr);
|
|
||||||
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
|
|
||||||
if (geteuid() == 0) {
|
|
||||||
pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
|
|
||||||
pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
|
|
||||||
struct sched_param fifo_param;
|
|
||||||
fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
|
|
||||||
pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
|
|
||||||
if (!tick_thread_active) {
|
|
||||||
sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
|
|
||||||
ErrorAlert(str);
|
|
||||||
QuitEmulator();
|
|
||||||
}
|
|
||||||
D(bug("60Hz thread started\n"));
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Start 60Hz timer
|
// Start 60Hz timer
|
||||||
@ -575,10 +575,7 @@ void QuitEmulator(void)
|
|||||||
Exit680x0();
|
Exit680x0();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
|
#if defined(HAVE_PTHREADS)
|
||||||
// Stop 60Hz timer
|
|
||||||
timer_delete(timer);
|
|
||||||
#elif defined(HAVE_PTHREADS)
|
|
||||||
// Stop 60Hz thread
|
// Stop 60Hz thread
|
||||||
if (tick_thread_active) {
|
if (tick_thread_active) {
|
||||||
tick_thread_cancel = true;
|
tick_thread_cancel = true;
|
||||||
@ -587,6 +584,9 @@ void QuitEmulator(void)
|
|||||||
#endif
|
#endif
|
||||||
pthread_join(tick_thread, NULL);
|
pthread_join(tick_thread, NULL);
|
||||||
}
|
}
|
||||||
|
#elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
|
||||||
|
// Stop 60Hz timer
|
||||||
|
timer_delete(timer);
|
||||||
#else
|
#else
|
||||||
struct itimerval req;
|
struct itimerval req;
|
||||||
req.it_interval.tv_sec = req.it_value.tv_sec = 0;
|
req.it_interval.tv_sec = req.it_value.tv_sec = 0;
|
||||||
@ -849,6 +849,8 @@ static void one_tick(...)
|
|||||||
#ifdef HAVE_PTHREADS
|
#ifdef HAVE_PTHREADS
|
||||||
static void *tick_func(void *arg)
|
static void *tick_func(void *arg)
|
||||||
{
|
{
|
||||||
|
uint64 start = GetTicks_usec();
|
||||||
|
int64 ticks = 0;
|
||||||
uint64 next = GetTicks_usec();
|
uint64 next = GetTicks_usec();
|
||||||
while (!tick_thread_cancel) {
|
while (!tick_thread_cancel) {
|
||||||
one_tick();
|
one_tick();
|
||||||
@ -858,110 +860,15 @@ static void *tick_func(void *arg)
|
|||||||
Delay_usec(delay);
|
Delay_usec(delay);
|
||||||
else if (delay < -16625)
|
else if (delay < -16625)
|
||||||
next = GetTicks_usec();
|
next = GetTicks_usec();
|
||||||
|
ticks++;
|
||||||
}
|
}
|
||||||
|
uint64 end = GetTicks_usec();
|
||||||
|
D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get current value of microsecond timer
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint64 GetTicks_usec(void)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
|
||||||
struct timespec t;
|
|
||||||
clock_gettime(CLOCK_REALTIME, &t);
|
|
||||||
return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000;
|
|
||||||
#else
|
|
||||||
struct timeval t;
|
|
||||||
gettimeofday(&t, NULL);
|
|
||||||
return (uint64)t.tv_sec * 1000000 + t.tv_usec;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delay by specified number of microseconds (<1 second)
|
|
||||||
* (adapted from SDL_Delay() source; this function is designed to provide
|
|
||||||
* the highest accuracy possible)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(linux)
|
|
||||||
// Linux select() changes its timeout parameter upon return to contain
|
|
||||||
// the remaining time. Most other unixen leave it unchanged or undefined.
|
|
||||||
#define SELECT_SETS_REMAINING
|
|
||||||
#elif defined(__FreeBSD__) || defined(__sun__)
|
|
||||||
#define USE_NANOSLEEP
|
|
||||||
#elif defined(HAVE_PTHREADS) && defined(sgi)
|
|
||||||
// SGI pthreads has a bug when using pthreads+signals+nanosleep,
|
|
||||||
// so instead of using nanosleep, wait on a CV which is never signalled.
|
|
||||||
#define USE_COND_TIMEDWAIT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Delay_usec(uint32 usec)
|
|
||||||
{
|
|
||||||
int was_error;
|
|
||||||
|
|
||||||
#if defined(USE_NANOSLEEP)
|
|
||||||
struct timespec elapsed, tv;
|
|
||||||
#elif defined(USE_COND_TIMEDWAIT)
|
|
||||||
// Use a local mutex and cv, so threads remain independent
|
|
||||||
pthread_cond_t delay_cond = PTHREAD_COND_INITIALIZER;
|
|
||||||
pthread_mutex_t delay_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
struct timespec elapsed;
|
|
||||||
uint64 future;
|
|
||||||
#else
|
|
||||||
struct timeval tv;
|
|
||||||
#ifndef SELECT_SETS_REMAINING
|
|
||||||
uint64 then, now, elapsed;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set the timeout interval - Linux only needs to do this once
|
|
||||||
#if defined(SELECT_SETS_REMAINING)
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = usec;
|
|
||||||
#elif defined(USE_NANOSLEEP)
|
|
||||||
elapsed.tv_sec = 0;
|
|
||||||
elapsed.tv_nsec = usec * 1000;
|
|
||||||
#elif defined(USE_COND_TIMEDWAIT)
|
|
||||||
future = GetTicks_usec() + usec;
|
|
||||||
elapsed.tv_sec = future / 1000000;
|
|
||||||
elapsed.tv_nsec = (future % 1000000) * 1000;
|
|
||||||
#else
|
|
||||||
then = GetTicks_usec();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
do {
|
|
||||||
errno = 0;
|
|
||||||
#if defined(USE_NANOSLEEP)
|
|
||||||
tv.tv_sec = elapsed.tv_sec;
|
|
||||||
tv.tv_nsec = elapsed.tv_nsec;
|
|
||||||
was_error = nanosleep(&tv, &elapsed);
|
|
||||||
#elif defined(USE_COND_TIMEDWAIT)
|
|
||||||
was_error = pthread_mutex_lock(&delay_mutex);
|
|
||||||
was_error = pthread_cond_timedwait(&delay_cond, &delay_mutex, &elapsed);
|
|
||||||
was_error = pthread_mutex_unlock(&delay_mutex);
|
|
||||||
#else
|
|
||||||
#ifndef SELECT_SETS_REMAINING
|
|
||||||
// Calculate the time interval left (in case of interrupt)
|
|
||||||
now = GetTicks_usec();
|
|
||||||
elapsed = now - then;
|
|
||||||
then = now;
|
|
||||||
if (elapsed >= usec)
|
|
||||||
break;
|
|
||||||
usec -= elapsed;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = usec;
|
|
||||||
#endif
|
|
||||||
was_error = select(0, NULL, NULL, NULL, &tv);
|
|
||||||
#endif
|
|
||||||
} while (was_error && (errno == EINTR));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if !EMULATED_68K
|
#if !EMULATED_68K
|
||||||
/*
|
/*
|
||||||
* Virtual 68k interrupt handler
|
* Virtual 68k interrupt handler
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "macos_util.h"
|
#include "macos_util.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
@ -196,3 +198,101 @@ int32 timer_host2mac_time(tm_time_t hosttime)
|
|||||||
return -t; // Time in negative microseconds
|
return -t; // Time in negative microseconds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get current value of microsecond timer
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint64 GetTicks_usec(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
|
struct timespec t;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &t);
|
||||||
|
return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000;
|
||||||
|
#else
|
||||||
|
struct timeval t;
|
||||||
|
gettimeofday(&t, NULL);
|
||||||
|
return (uint64)t.tv_sec * 1000000 + t.tv_usec;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delay by specified number of microseconds (<1 second)
|
||||||
|
* (adapted from SDL_Delay() source; this function is designed to provide
|
||||||
|
* the highest accuracy possible)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(linux)
|
||||||
|
// Linux select() changes its timeout parameter upon return to contain
|
||||||
|
// the remaining time. Most other unixen leave it unchanged or undefined.
|
||||||
|
#define SELECT_SETS_REMAINING
|
||||||
|
#elif defined(__FreeBSD__) || defined(__sun__)
|
||||||
|
#define USE_NANOSLEEP
|
||||||
|
#elif defined(HAVE_PTHREADS) && defined(sgi)
|
||||||
|
// SGI pthreads has a bug when using pthreads+signals+nanosleep,
|
||||||
|
// so instead of using nanosleep, wait on a CV which is never signalled.
|
||||||
|
#define USE_COND_TIMEDWAIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Delay_usec(uint32 usec)
|
||||||
|
{
|
||||||
|
int was_error;
|
||||||
|
|
||||||
|
#if defined(USE_NANOSLEEP)
|
||||||
|
struct timespec elapsed, tv;
|
||||||
|
#elif defined(USE_COND_TIMEDWAIT)
|
||||||
|
// Use a local mutex and cv, so threads remain independent
|
||||||
|
pthread_cond_t delay_cond = PTHREAD_COND_INITIALIZER;
|
||||||
|
pthread_mutex_t delay_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
struct timespec elapsed;
|
||||||
|
uint64 future;
|
||||||
|
#else
|
||||||
|
struct timeval tv;
|
||||||
|
#ifndef SELECT_SETS_REMAINING
|
||||||
|
uint64 then, now, elapsed;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set the timeout interval - Linux only needs to do this once
|
||||||
|
#if defined(SELECT_SETS_REMAINING)
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = usec;
|
||||||
|
#elif defined(USE_NANOSLEEP)
|
||||||
|
elapsed.tv_sec = 0;
|
||||||
|
elapsed.tv_nsec = usec * 1000;
|
||||||
|
#elif defined(USE_COND_TIMEDWAIT)
|
||||||
|
future = GetTicks_usec() + usec;
|
||||||
|
elapsed.tv_sec = future / 1000000;
|
||||||
|
elapsed.tv_nsec = (future % 1000000) * 1000;
|
||||||
|
#else
|
||||||
|
then = GetTicks_usec();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do {
|
||||||
|
errno = 0;
|
||||||
|
#if defined(USE_NANOSLEEP)
|
||||||
|
tv.tv_sec = elapsed.tv_sec;
|
||||||
|
tv.tv_nsec = elapsed.tv_nsec;
|
||||||
|
was_error = nanosleep(&tv, &elapsed);
|
||||||
|
#elif defined(USE_COND_TIMEDWAIT)
|
||||||
|
was_error = pthread_mutex_lock(&delay_mutex);
|
||||||
|
was_error = pthread_cond_timedwait(&delay_cond, &delay_mutex, &elapsed);
|
||||||
|
was_error = pthread_mutex_unlock(&delay_mutex);
|
||||||
|
#else
|
||||||
|
#ifndef SELECT_SETS_REMAINING
|
||||||
|
// Calculate the time interval left (in case of interrupt)
|
||||||
|
now = GetTicks_usec();
|
||||||
|
elapsed = now - then;
|
||||||
|
then = now;
|
||||||
|
if (elapsed >= usec)
|
||||||
|
break;
|
||||||
|
usec -= elapsed;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = usec;
|
||||||
|
#endif
|
||||||
|
was_error = select(0, NULL, NULL, NULL, &tv);
|
||||||
|
#endif
|
||||||
|
} while (was_error && (errno == EINTR));
|
||||||
|
}
|
||||||
|
@ -80,7 +80,7 @@ enum {
|
|||||||
// Constants
|
// Constants
|
||||||
const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
|
const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
|
||||||
|
|
||||||
static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | StructureNotifyMask;
|
static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask | StructureNotifyMask;
|
||||||
static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask;
|
static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask;
|
||||||
|
|
||||||
|
|
||||||
@ -429,12 +429,17 @@ public:
|
|||||||
virtual void toggle_mouse_grab(void) {}
|
virtual void toggle_mouse_grab(void) {}
|
||||||
virtual void mouse_moved(int x, int y) { ADBMouseMoved(x, y); }
|
virtual void mouse_moved(int x, int y) { ADBMouseMoved(x, y); }
|
||||||
|
|
||||||
|
void disable_mouse_accel(void);
|
||||||
|
void restore_mouse_accel(void);
|
||||||
|
|
||||||
virtual void grab_mouse(void) {}
|
virtual void grab_mouse(void) {}
|
||||||
virtual void ungrab_mouse(void) {}
|
virtual void ungrab_mouse(void) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool init_ok; // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer)
|
bool init_ok; // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer)
|
||||||
Window w; // The window we draw into
|
Window w; // The window we draw into
|
||||||
|
|
||||||
|
int orig_accel_numer, orig_accel_denom, orig_threshold; // Original mouse acceleration
|
||||||
};
|
};
|
||||||
|
|
||||||
class driver_window;
|
class driver_window;
|
||||||
@ -478,11 +483,13 @@ driver_base::driver_base()
|
|||||||
{
|
{
|
||||||
the_buffer = NULL;
|
the_buffer = NULL;
|
||||||
the_buffer_copy = NULL;
|
the_buffer_copy = NULL;
|
||||||
|
XGetPointerControl(x_display, &orig_accel_numer, &orig_accel_denom, &orig_threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_base::~driver_base()
|
driver_base::~driver_base()
|
||||||
{
|
{
|
||||||
ungrab_mouse();
|
ungrab_mouse();
|
||||||
|
restore_mouse_accel();
|
||||||
|
|
||||||
if (w) {
|
if (w) {
|
||||||
XUnmapWindow(x_display, w);
|
XUnmapWindow(x_display, w);
|
||||||
@ -535,6 +542,18 @@ void driver_base::update_palette(void)
|
|||||||
XSync(x_display, false);
|
XSync(x_display, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable mouse acceleration
|
||||||
|
void driver_base::disable_mouse_accel(void)
|
||||||
|
{
|
||||||
|
XChangePointerControl(x_display, True, False, 1, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore mouse acceleration to original value
|
||||||
|
void driver_base::restore_mouse_accel(void)
|
||||||
|
{
|
||||||
|
XChangePointerControl(x_display, True, True, orig_accel_numer, orig_accel_denom, orig_threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Windowed display driver
|
* Windowed display driver
|
||||||
@ -728,9 +747,9 @@ void driver_window::grab_mouse(void)
|
|||||||
Delay_usec(100000);
|
Delay_usec(100000);
|
||||||
}
|
}
|
||||||
if (result == GrabSuccess) {
|
if (result == GrabSuccess) {
|
||||||
ADBSetRelMouseMode(mouse_grabbed = true);
|
|
||||||
XStoreName(x_display, w, GetString(STR_WINDOW_TITLE_GRABBED));
|
XStoreName(x_display, w, GetString(STR_WINDOW_TITLE_GRABBED));
|
||||||
XSync(x_display, false);
|
ADBSetRelMouseMode(mouse_grabbed = true);
|
||||||
|
disable_mouse_accel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,6 +760,7 @@ void driver_window::ungrab_mouse(void)
|
|||||||
XUngrabPointer(x_display, CurrentTime);
|
XUngrabPointer(x_display, CurrentTime);
|
||||||
XStoreName(x_display, w, GetString(STR_WINDOW_TITLE));
|
XStoreName(x_display, w, GetString(STR_WINDOW_TITLE));
|
||||||
ADBSetRelMouseMode(mouse_grabbed = false);
|
ADBSetRelMouseMode(mouse_grabbed = false);
|
||||||
|
restore_mouse_accel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,6 +856,7 @@ void driver_dga::suspend(void)
|
|||||||
#endif
|
#endif
|
||||||
XUngrabPointer(x_display, CurrentTime);
|
XUngrabPointer(x_display, CurrentTime);
|
||||||
XUngrabKeyboard(x_display, CurrentTime);
|
XUngrabKeyboard(x_display, CurrentTime);
|
||||||
|
restore_mouse_accel();
|
||||||
XUnmapWindow(x_display, w);
|
XUnmapWindow(x_display, w);
|
||||||
wait_unmapped(w);
|
wait_unmapped(w);
|
||||||
|
|
||||||
@ -865,6 +886,7 @@ void driver_dga::resume(void)
|
|||||||
XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
|
XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
|
||||||
XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||||
XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
|
XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
|
||||||
|
disable_mouse_accel();
|
||||||
#ifdef ENABLE_XF86_DGA
|
#ifdef ENABLE_XF86_DGA
|
||||||
XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
|
XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
|
||||||
XF86DGASetViewPort(x_display, screen, 0, 0);
|
XF86DGASetViewPort(x_display, screen, 0, 0);
|
||||||
@ -1011,6 +1033,7 @@ driver_fbdev::driver_fbdev(const video_mode &mode)
|
|||||||
XGrabPointer(x_display, w, True,
|
XGrabPointer(x_display, w, True,
|
||||||
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
|
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
|
||||||
GrabModeAsync, GrabModeAsync, w, None, CurrentTime);
|
GrabModeAsync, GrabModeAsync, w, None, CurrentTime);
|
||||||
|
disable_mouse_accel();
|
||||||
|
|
||||||
// Calculate bytes per row
|
// Calculate bytes per row
|
||||||
int bytes_per_row = TrivialBytesPerRow(mode.x, mode.depth);
|
int bytes_per_row = TrivialBytesPerRow(mode.x, mode.depth);
|
||||||
@ -1150,6 +1173,7 @@ driver_xf86dga::driver_xf86dga(const video_mode &mode)
|
|||||||
XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
|
XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
|
||||||
XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||||
XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
|
XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
|
||||||
|
disable_mouse_accel();
|
||||||
|
|
||||||
int v_width, v_bank, v_size;
|
int v_width, v_bank, v_size;
|
||||||
XF86DGAGetVideo(x_display, screen, (char **)&the_buffer, &v_width, &v_bank, &v_size);
|
XF86DGAGetVideo(x_display, screen, (char **)&the_buffer, &v_width, &v_bank, &v_size);
|
||||||
@ -1344,12 +1368,18 @@ static bool video_open(const video_mode &mode)
|
|||||||
--bloss;
|
--bloss;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preset palette pixel values for gamma table
|
// Preset palette pixel values for CLUT or gamma table
|
||||||
if (color_class == DirectColor) {
|
if (color_class == DirectColor) {
|
||||||
int num = vis->map_entries;
|
int num = vis->map_entries;
|
||||||
for (int i=0; i<num; i++) {
|
for (int i=0; i<num; i++) {
|
||||||
int c = (i * 256) / num;
|
int c = (i * 256) / num;
|
||||||
palette[i].pixel = map_rgb(c, c, c);
|
palette[i].pixel = map_rgb(c, c, c);
|
||||||
|
palette[i].flags = DoRed | DoGreen | DoBlue;
|
||||||
|
}
|
||||||
|
} else if (color_class == PseudoColor) {
|
||||||
|
for (int i=0; i<256; i++) {
|
||||||
|
palette[i].pixel = i;
|
||||||
|
palette[i].flags = DoRed | DoGreen | DoBlue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1360,9 +1390,6 @@ static bool video_open(const video_mode &mode)
|
|||||||
palette[i].red = c * 0x0101;
|
palette[i].red = c * 0x0101;
|
||||||
palette[i].green = c * 0x0101;
|
palette[i].green = c * 0x0101;
|
||||||
palette[i].blue = c * 0x0101;
|
palette[i].blue = c * 0x0101;
|
||||||
if (color_class == PseudoColor)
|
|
||||||
palette[i].pixel = i;
|
|
||||||
palette[i].flags = DoRed | DoGreen | DoBlue;
|
|
||||||
}
|
}
|
||||||
if (cmap[0] && cmap[1]) {
|
if (cmap[0] && cmap[1]) {
|
||||||
XStoreColors(x_display, cmap[0], palette, num);
|
XStoreColors(x_display, cmap[0], palette, num);
|
||||||
@ -1371,7 +1398,7 @@ static bool video_open(const video_mode &mode)
|
|||||||
|
|
||||||
#ifdef ENABLE_VOSF
|
#ifdef ENABLE_VOSF
|
||||||
// Load gray ramp to 8->16/32 expand map
|
// Load gray ramp to 8->16/32 expand map
|
||||||
if (!IsDirectMode(mode) && (color_class == TrueColor || color_class == DirectColor))
|
if (!IsDirectMode(mode) && xdepth > 8)
|
||||||
for (int i=0; i<256; i++)
|
for (int i=0; i<256; i++)
|
||||||
ExpandMap[i] = map_rgb(i, i, i);
|
ExpandMap[i] = map_rgb(i, i, i);
|
||||||
#endif
|
#endif
|
||||||
@ -1722,15 +1749,12 @@ void video_set_palette(uint8 *pal, int num_in)
|
|||||||
p->red = pal[c*3 + 0] * 0x0101;
|
p->red = pal[c*3 + 0] * 0x0101;
|
||||||
p->green = pal[c*3 + 1] * 0x0101;
|
p->green = pal[c*3 + 1] * 0x0101;
|
||||||
p->blue = pal[c*3 + 2] * 0x0101;
|
p->blue = pal[c*3 + 2] * 0x0101;
|
||||||
if (color_class == PseudoColor)
|
|
||||||
p->pixel = i;
|
|
||||||
p->flags = DoRed | DoGreen | DoBlue;
|
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_VOSF
|
#ifdef ENABLE_VOSF
|
||||||
// Recalculate pixel color expansion map
|
// Recalculate pixel color expansion map
|
||||||
if (!IsDirectMode(VideoMonitor.mode) && (color_class == TrueColor || color_class == DirectColor)) {
|
if (!IsDirectMode(VideoMonitor.mode) && xdepth > 8) {
|
||||||
for (int i=0; i<256; i++) {
|
for (int i=0; i<256; i++) {
|
||||||
int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
|
int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
|
||||||
ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
|
ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
|
||||||
@ -1943,6 +1967,7 @@ static void handle_events(void)
|
|||||||
XNextEvent(x_display, &event);
|
XNextEvent(x_display, &event);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
|
||||||
// Mouse button
|
// Mouse button
|
||||||
case ButtonPress: {
|
case ButtonPress: {
|
||||||
unsigned int button = event.xbutton.button;
|
unsigned int button = event.xbutton.button;
|
||||||
@ -1975,6 +2000,12 @@ static void handle_events(void)
|
|||||||
drv->mouse_moved(event.xmotion.x, event.xmotion.y);
|
drv->mouse_moved(event.xmotion.x, event.xmotion.y);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Mouse entered window
|
||||||
|
case EnterNotify:
|
||||||
|
if (event.xcrossing.mode != NotifyGrab && event.xcrossing.mode != NotifyUngrab)
|
||||||
|
drv->mouse_moved(event.xmotion.x, event.xmotion.y);
|
||||||
|
break;
|
||||||
|
|
||||||
// Keyboard
|
// Keyboard
|
||||||
case KeyPress: {
|
case KeyPress: {
|
||||||
int code = -1;
|
int code = -1;
|
||||||
@ -2311,12 +2342,6 @@ static void video_refresh_dga(void)
|
|||||||
{
|
{
|
||||||
// Quit DGA mode if requested
|
// Quit DGA mode if requested
|
||||||
possibly_quit_dga_mode();
|
possibly_quit_dga_mode();
|
||||||
|
|
||||||
// Handle X events
|
|
||||||
handle_events();
|
|
||||||
|
|
||||||
// Handle palette changes
|
|
||||||
handle_palette_changes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_VOSF
|
#ifdef ENABLE_VOSF
|
||||||
@ -2326,12 +2351,6 @@ static void video_refresh_dga_vosf(void)
|
|||||||
// Quit DGA mode if requested
|
// Quit DGA mode if requested
|
||||||
possibly_quit_dga_mode();
|
possibly_quit_dga_mode();
|
||||||
|
|
||||||
// Handle X events
|
|
||||||
handle_events();
|
|
||||||
|
|
||||||
// Handle palette changes
|
|
||||||
handle_palette_changes();
|
|
||||||
|
|
||||||
// Update display (VOSF variant)
|
// Update display (VOSF variant)
|
||||||
static int tick_counter = 0;
|
static int tick_counter = 0;
|
||||||
if (++tick_counter >= frame_skip) {
|
if (++tick_counter >= frame_skip) {
|
||||||
@ -2350,12 +2369,6 @@ static void video_refresh_window_vosf(void)
|
|||||||
// Ungrab mouse if requested
|
// Ungrab mouse if requested
|
||||||
possibly_ungrab_mouse();
|
possibly_ungrab_mouse();
|
||||||
|
|
||||||
// Handle X events
|
|
||||||
handle_events();
|
|
||||||
|
|
||||||
// Handle palette changes
|
|
||||||
handle_palette_changes();
|
|
||||||
|
|
||||||
// Update display (VOSF variant)
|
// Update display (VOSF variant)
|
||||||
static int tick_counter = 0;
|
static int tick_counter = 0;
|
||||||
if (++tick_counter >= frame_skip) {
|
if (++tick_counter >= frame_skip) {
|
||||||
@ -2375,12 +2388,6 @@ static void video_refresh_window_static(void)
|
|||||||
// Ungrab mouse if requested
|
// Ungrab mouse if requested
|
||||||
possibly_ungrab_mouse();
|
possibly_ungrab_mouse();
|
||||||
|
|
||||||
// Handle X events
|
|
||||||
handle_events();
|
|
||||||
|
|
||||||
// Handle_palette changes
|
|
||||||
handle_palette_changes();
|
|
||||||
|
|
||||||
// Update display (static variant)
|
// Update display (static variant)
|
||||||
static int tick_counter = 0;
|
static int tick_counter = 0;
|
||||||
if (++tick_counter >= frame_skip) {
|
if (++tick_counter >= frame_skip) {
|
||||||
@ -2394,12 +2401,6 @@ static void video_refresh_window_dynamic(void)
|
|||||||
// Ungrab mouse if requested
|
// Ungrab mouse if requested
|
||||||
possibly_ungrab_mouse();
|
possibly_ungrab_mouse();
|
||||||
|
|
||||||
// Handle X events
|
|
||||||
handle_events();
|
|
||||||
|
|
||||||
// Handle_palette changes
|
|
||||||
handle_palette_changes();
|
|
||||||
|
|
||||||
// Update display (dynamic variant)
|
// Update display (dynamic variant)
|
||||||
static int tick_counter = 0;
|
static int tick_counter = 0;
|
||||||
tick_counter++;
|
tick_counter++;
|
||||||
@ -2435,32 +2436,69 @@ static void VideoRefreshInit(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function is called on non-threaded platforms from a timer interrupt
|
||||||
void VideoRefresh(void)
|
void VideoRefresh(void)
|
||||||
{
|
{
|
||||||
// We need to check redraw_thread_active to inhibit refreshed during
|
// We need to check redraw_thread_active to inhibit refreshed during
|
||||||
// mode changes on non-threaded platforms
|
// mode changes on non-threaded platforms
|
||||||
if (redraw_thread_active)
|
if (!redraw_thread_active)
|
||||||
video_refresh();
|
return;
|
||||||
|
|
||||||
|
// Handle X events
|
||||||
|
handle_events();
|
||||||
|
|
||||||
|
// Handle palette changes
|
||||||
|
handle_palette_changes();
|
||||||
|
|
||||||
|
// Update display
|
||||||
|
video_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int VIDEO_REFRESH_HZ = 60;
|
||||||
|
const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ;
|
||||||
|
|
||||||
#ifdef HAVE_PTHREADS
|
#ifdef HAVE_PTHREADS
|
||||||
static void *redraw_func(void *arg)
|
static void *redraw_func(void *arg)
|
||||||
{
|
{
|
||||||
|
int fd = ConnectionNumber(x_display);
|
||||||
|
|
||||||
uint64 start = GetTicks_usec();
|
uint64 start = GetTicks_usec();
|
||||||
int64 ticks = 0;
|
int64 ticks = 0;
|
||||||
uint64 next = GetTicks_usec();
|
uint64 next = GetTicks_usec() + VIDEO_REFRESH_DELAY;
|
||||||
|
|
||||||
while (!redraw_thread_cancel) {
|
while (!redraw_thread_cancel) {
|
||||||
video_refresh();
|
|
||||||
next += 16667;
|
|
||||||
int64 delay = next - GetTicks_usec();
|
int64 delay = next - GetTicks_usec();
|
||||||
if (delay > 0)
|
if (delay < -VIDEO_REFRESH_DELAY) {
|
||||||
Delay_usec(delay);
|
|
||||||
else if (delay < -16667)
|
// We are lagging far behind, so we reset the delay mechanism
|
||||||
next = GetTicks_usec();
|
next = GetTicks_usec();
|
||||||
ticks++;
|
|
||||||
|
} else if (delay <= 0) {
|
||||||
|
|
||||||
|
// Delay expired, refresh display
|
||||||
|
handle_events();
|
||||||
|
handle_palette_changes();
|
||||||
|
video_refresh();
|
||||||
|
next += VIDEO_REFRESH_DELAY;
|
||||||
|
ticks++;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// No display refresh pending, check for X events
|
||||||
|
fd_set readfds;
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(fd, &readfds);
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = delay;
|
||||||
|
if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0)
|
||||||
|
handle_events();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 end = GetTicks_usec();
|
uint64 end = GetTicks_usec();
|
||||||
// printf("%Ld ticks in %Ld usec = %Ld ticks/sec\n", ticks, end - start, ticks * 1000000 / (end - start));
|
D(bug("%Ld refreshes in %Ld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -57,7 +57,7 @@ static uint8 mouse_reg_3[2] = {0x63, 0x01}; // Mouse ADB register 3
|
|||||||
static uint8 key_reg_2[2] = {0xff, 0xff}; // Keyboard ADB register 2
|
static uint8 key_reg_2[2] = {0xff, 0xff}; // Keyboard ADB register 2
|
||||||
static uint8 key_reg_3[2] = {0x62, 0x05}; // Keyboard ADB register 3
|
static uint8 key_reg_3[2] = {0x62, 0x05}; // Keyboard ADB register 3
|
||||||
|
|
||||||
// ADB mouse input state lock (for platforms that use separate input thread)
|
// ADB mouse motion lock (for platforms that use separate input thread)
|
||||||
static B2_mutex *mouse_lock;
|
static B2_mutex *mouse_lock;
|
||||||
|
|
||||||
|
|
||||||
@ -231,6 +231,8 @@ void ADBMouseMoved(int x, int y)
|
|||||||
mouse_x = x; mouse_y = y;
|
mouse_x = x; mouse_y = y;
|
||||||
}
|
}
|
||||||
B2_unlock_mutex(mouse_lock);
|
B2_unlock_mutex(mouse_lock);
|
||||||
|
SetInterruptFlag(INTFLAG_ADB);
|
||||||
|
TriggerInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -240,21 +242,21 @@ void ADBMouseMoved(int x, int y)
|
|||||||
|
|
||||||
void ADBMouseDown(int button)
|
void ADBMouseDown(int button)
|
||||||
{
|
{
|
||||||
B2_lock_mutex(mouse_lock);
|
|
||||||
mouse_button[button] = true;
|
mouse_button[button] = true;
|
||||||
B2_unlock_mutex(mouse_lock);
|
SetInterruptFlag(INTFLAG_ADB);
|
||||||
|
TriggerInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First mouse button released
|
* Mouse button released
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ADBMouseUp(int button)
|
void ADBMouseUp(int button)
|
||||||
{
|
{
|
||||||
B2_lock_mutex(mouse_lock);
|
|
||||||
mouse_button[button] = false;
|
mouse_button[button] = false;
|
||||||
B2_unlock_mutex(mouse_lock);
|
SetInterruptFlag(INTFLAG_ADB);
|
||||||
|
TriggerInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -264,7 +266,10 @@ void ADBMouseUp(int button)
|
|||||||
|
|
||||||
void ADBSetRelMouseMode(bool relative)
|
void ADBSetRelMouseMode(bool relative)
|
||||||
{
|
{
|
||||||
relative_mouse = relative;
|
if (relative_mouse != relative) {
|
||||||
|
relative_mouse = relative;
|
||||||
|
mouse_x = mouse_y = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -280,6 +285,10 @@ void ADBKeyDown(int code)
|
|||||||
|
|
||||||
// Set key in matrix
|
// Set key in matrix
|
||||||
key_states[code >> 3] |= (1 << (~code & 7));
|
key_states[code >> 3] |= (1 << (~code & 7));
|
||||||
|
|
||||||
|
// Trigger interrupt
|
||||||
|
SetInterruptFlag(INTFLAG_ADB);
|
||||||
|
TriggerInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -295,6 +304,10 @@ void ADBKeyUp(int code)
|
|||||||
|
|
||||||
// Clear key in matrix
|
// Clear key in matrix
|
||||||
key_states[code >> 3] &= ~(1 << (~code & 7));
|
key_states[code >> 3] &= ~(1 << (~code & 7));
|
||||||
|
|
||||||
|
// Trigger interrupt
|
||||||
|
SetInterruptFlag(INTFLAG_ADB);
|
||||||
|
TriggerInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -440,7 +440,6 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
|||||||
if (HasMacStarted()) {
|
if (HasMacStarted()) {
|
||||||
|
|
||||||
// Mac has started, execute all 60Hz interrupt functions
|
// Mac has started, execute all 60Hz interrupt functions
|
||||||
ADBInterrupt();
|
|
||||||
TimerInterrupt();
|
TimerInterrupt();
|
||||||
VideoInterrupt();
|
VideoInterrupt();
|
||||||
|
|
||||||
@ -457,7 +456,6 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
|||||||
|
|
||||||
if (InterruptFlags & INTFLAG_1HZ) {
|
if (InterruptFlags & INTFLAG_1HZ) {
|
||||||
ClearInterruptFlag(INTFLAG_1HZ);
|
ClearInterruptFlag(INTFLAG_1HZ);
|
||||||
|
|
||||||
if (HasMacStarted()) {
|
if (HasMacStarted()) {
|
||||||
SonyInterrupt();
|
SonyInterrupt();
|
||||||
DiskInterrupt();
|
DiskInterrupt();
|
||||||
@ -480,11 +478,16 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
|||||||
AudioInterrupt();
|
AudioInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (InterruptFlags & INTFLAG_ADB) {
|
||||||
|
ClearInterruptFlag(INTFLAG_ADB);
|
||||||
|
if (HasMacStarted())
|
||||||
|
ADBInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
if (InterruptFlags & INTFLAG_NMI) {
|
if (InterruptFlags & INTFLAG_NMI) {
|
||||||
ClearInterruptFlag(INTFLAG_NMI);
|
ClearInterruptFlag(INTFLAG_NMI);
|
||||||
if (HasMacStarted()) {
|
if (HasMacStarted())
|
||||||
TriggerNMI();
|
TriggerNMI();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -66,7 +66,8 @@ enum {
|
|||||||
INTFLAG_ETHER = 8, // Ethernet driver
|
INTFLAG_ETHER = 8, // Ethernet driver
|
||||||
INTFLAG_AUDIO = 16, // Audio block read
|
INTFLAG_AUDIO = 16, // Audio block read
|
||||||
INTFLAG_TIMER = 32, // Time Manager
|
INTFLAG_TIMER = 32, // Time Manager
|
||||||
INTFLAG_NMI = 64 // NMI
|
INTFLAG_ADB = 64, // ADB
|
||||||
|
INTFLAG_NMI = 128 // NMI
|
||||||
};
|
};
|
||||||
|
|
||||||
extern uint32 InterruptFlags; // Currently pending interrupts
|
extern uint32 InterruptFlags; // Currently pending interrupts
|
||||||
|
@ -249,10 +249,8 @@ int16 PrimeTime(uint32 tm, int32 time)
|
|||||||
|
|
||||||
//!! PrimeTime(0) means continue previous delay
|
//!! PrimeTime(0) means continue previous delay
|
||||||
// (save wakeup time in RmvTime?)
|
// (save wakeup time in RmvTime?)
|
||||||
if (time == 0) {
|
if (time == 0)
|
||||||
printf("FATAL: Unsupported PrimeTime(0)\n");
|
printf("WARNING: Unsupported PrimeTime(0)\n");
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Yes, calculate wakeup time relative to last scheduled time
|
// Yes, calculate wakeup time relative to last scheduled time
|
||||||
tm_time_t wakeup;
|
tm_time_t wakeup;
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
* SEE ALSO
|
* SEE ALSO
|
||||||
* Inside Macintosh: Devices, chapter 1 "Device Manager"
|
* Inside Macintosh: Devices, chapter 1 "Device Manager"
|
||||||
* Designing Cards and Drivers for the Macintosh Family, Second Edition
|
* Designing Cards and Drivers for the Macintosh Family, Second Edition
|
||||||
|
* Designing PCI Cards and Drivers for Power Macintosh Computers
|
||||||
|
* Display Device Driver Guide
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user