2016-04-24 09:45:29 +00:00
|
|
|
/*
|
|
|
|
* UAE - The Un*x Amiga Emulator
|
|
|
|
*
|
|
|
|
* Event stuff
|
|
|
|
*
|
|
|
|
* Copyright 1995-2002 Bernd Schmidt
|
|
|
|
* Copyright 1995 Alessandro Bissacco
|
|
|
|
* Copyright 2000-2012 Toni Wilen
|
|
|
|
*/
|
2020-06-17 23:41:23 +02:00
|
|
|
|
|
|
|
#include "sysconfig.h"
|
2016-04-24 09:45:29 +00:00
|
|
|
#include "sysdeps.h"
|
|
|
|
|
|
|
|
#include "options.h"
|
2020-08-17 18:56:05 +02:00
|
|
|
#include "events.h"
|
2020-06-17 23:41:23 +02:00
|
|
|
#include "memory.h"
|
2016-04-24 09:45:29 +00:00
|
|
|
#include "newcpu.h"
|
2020-05-22 13:08:45 +02:00
|
|
|
#include "xwin.h"
|
2020-06-17 23:41:23 +02:00
|
|
|
#include "audio.h"
|
2017-03-30 21:21:31 +02:00
|
|
|
|
2020-05-24 00:03:17 +02:00
|
|
|
static const int pissoff_nojit_value = 256 * CYCLE_UNIT;
|
|
|
|
|
2017-12-04 15:49:40 +01:00
|
|
|
unsigned long int nextevent, currcycle;
|
2020-05-22 13:08:45 +02:00
|
|
|
int is_syncline, is_syncline_end;
|
2018-01-20 18:14:12 +01:00
|
|
|
|
2017-03-30 21:21:31 +02:00
|
|
|
frame_time_t vsyncmintime, vsyncmaxtime, vsyncwaittime;
|
2016-08-27 20:39:53 +02:00
|
|
|
int vsynctimebase;
|
2016-04-24 09:45:29 +00:00
|
|
|
|
2019-01-26 22:48:59 +01:00
|
|
|
static void events_fast(void)
|
|
|
|
{
|
|
|
|
cycles_do_special();
|
|
|
|
}
|
|
|
|
|
|
|
|
void events_reset_syncline(void)
|
|
|
|
{
|
|
|
|
is_syncline = 0;
|
|
|
|
events_fast();
|
|
|
|
}
|
|
|
|
|
2019-01-17 18:54:30 +01:00
|
|
|
void events_schedule(void)
|
2016-04-24 09:45:29 +00:00
|
|
|
{
|
2019-01-17 18:54:30 +01:00
|
|
|
unsigned long int mintime = ~0L;
|
2019-08-31 17:30:51 +02:00
|
|
|
for (auto& i : eventtab)
|
|
|
|
{
|
|
|
|
if (i.active)
|
|
|
|
{
|
|
|
|
auto eventtime = i.evtime - currcycle;
|
2019-01-17 18:54:30 +01:00
|
|
|
if (eventtime < mintime)
|
|
|
|
mintime = eventtime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nextevent = currcycle + mintime;
|
2016-04-24 09:45:29 +00:00
|
|
|
}
|
|
|
|
|
2020-08-17 18:56:05 +02:00
|
|
|
extern void vsync_event_done(void);
|
|
|
|
|
2019-01-26 22:48:59 +01:00
|
|
|
static bool event_check_vsync(void)
|
|
|
|
{
|
|
|
|
/* Keep only CPU emulation running while waiting for sync point. */
|
2020-05-24 00:03:17 +02:00
|
|
|
if (is_syncline == -1
|
|
|
|
|| is_syncline == -2
|
|
|
|
|| is_syncline == -3
|
|
|
|
|| is_syncline > 0
|
|
|
|
|| is_syncline <= -100) {
|
2020-05-22 13:08:45 +02:00
|
|
|
|
|
|
|
if (!isvsync_chipset()) {
|
|
|
|
events_reset_syncline();
|
|
|
|
return false;
|
|
|
|
}
|
2020-08-16 22:57:49 +02:00
|
|
|
// wait for vblank
|
|
|
|
audio_finish_pull();
|
2020-08-17 18:56:05 +02:00
|
|
|
int done = vsync_isdone(NULL);
|
|
|
|
if (!done)
|
|
|
|
{
|
|
|
|
if (currprefs.cachesize)
|
|
|
|
pissoff = pissoff_value;
|
|
|
|
else
|
|
|
|
pissoff = pissoff_nojit_value;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
vsync_event_done();
|
2020-05-22 13:08:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (is_syncline == -10) {
|
|
|
|
|
|
|
|
// wait is_syncline_end
|
|
|
|
//if (event_wait) {
|
|
|
|
int rpt = read_processor_time();
|
|
|
|
int v = rpt - is_syncline_end;
|
|
|
|
if (v < 0)
|
|
|
|
{
|
2020-05-24 00:03:17 +02:00
|
|
|
if (currprefs.cachesize)
|
2020-08-14 22:07:43 +02:00
|
|
|
pissoff = pissoff_value;
|
2020-05-24 00:03:17 +02:00
|
|
|
else
|
2020-08-14 22:07:43 +02:00
|
|
|
pissoff = pissoff_nojit_value;
|
2020-05-22 13:08:45 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//}
|
|
|
|
events_reset_syncline();
|
|
|
|
}
|
|
|
|
else if (is_syncline < -10) {
|
|
|
|
|
|
|
|
// wait is_syncline_end/vsyncmintime
|
|
|
|
//if (event_wait) {
|
|
|
|
int rpt = read_processor_time();
|
|
|
|
int v = rpt - vsyncmintime;
|
|
|
|
int v2 = rpt - is_syncline_end;
|
|
|
|
if (v > vsynctimebase || v < -vsynctimebase) {
|
|
|
|
v = 0;
|
|
|
|
}
|
|
|
|
if (v < 0 && v2 < 0) {
|
2020-05-24 00:03:17 +02:00
|
|
|
if (currprefs.cachesize)
|
2020-08-14 22:07:43 +02:00
|
|
|
pissoff = pissoff_value;
|
2020-05-24 00:03:17 +02:00
|
|
|
else
|
2020-08-14 22:07:43 +02:00
|
|
|
pissoff = pissoff_nojit_value;
|
2020-05-22 13:08:45 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//}
|
2019-01-26 22:48:59 +01:00
|
|
|
events_reset_syncline();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-08-31 17:30:51 +02:00
|
|
|
void do_cycles_cpu_fastest(uae_u32 cycles_to_add)
|
2016-04-24 09:45:29 +00:00
|
|
|
{
|
2020-08-17 18:56:05 +02:00
|
|
|
if (!currprefs.cpu_thread) {
|
|
|
|
if ((pissoff -= cycles_to_add) >= 0)
|
2019-08-31 17:30:51 +02:00
|
|
|
return;
|
2020-08-17 18:56:05 +02:00
|
|
|
|
|
|
|
cycles_to_add = -pissoff;
|
|
|
|
pissoff = 0;
|
|
|
|
} else {
|
|
|
|
pissoff = 0x40000000;
|
2019-08-31 17:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
while ((nextevent - currcycle) <= cycles_to_add)
|
|
|
|
{
|
2020-08-17 18:56:05 +02:00
|
|
|
if (is_syncline)
|
|
|
|
{
|
|
|
|
if (event_check_vsync())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-08-31 17:30:51 +02:00
|
|
|
cycles_to_add -= (nextevent - currcycle);
|
|
|
|
currcycle = nextevent;
|
|
|
|
|
|
|
|
for (auto& i : eventtab)
|
|
|
|
{
|
|
|
|
if (i.active && i.evtime == currcycle)
|
|
|
|
{
|
2020-08-17 18:56:05 +02:00
|
|
|
if (i.handler == nullptr)
|
|
|
|
i.active = false;
|
|
|
|
else
|
|
|
|
(*i.handler)();
|
2019-08-31 17:30:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
events_schedule();
|
|
|
|
}
|
|
|
|
currcycle += cycles_to_add;
|
2016-04-24 09:45:29 +00:00
|
|
|
}
|
|
|
|
|
2019-08-31 17:30:51 +02:00
|
|
|
void do_cycles_cpu_norm(uae_u32 cycles_to_add)
|
2016-04-25 17:12:37 +00:00
|
|
|
{
|
2019-08-31 17:30:51 +02:00
|
|
|
while ((nextevent - currcycle) <= cycles_to_add)
|
|
|
|
{
|
|
|
|
cycles_to_add -= (nextevent - currcycle);
|
|
|
|
currcycle = nextevent;
|
|
|
|
|
|
|
|
for (auto& i : eventtab)
|
|
|
|
{
|
|
|
|
if (i.active && i.evtime == currcycle)
|
|
|
|
{
|
|
|
|
(*i.handler)();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
events_schedule();
|
|
|
|
}
|
|
|
|
currcycle += cycles_to_add;
|
2016-04-25 17:12:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do_cycles_func do_cycles = do_cycles_cpu_norm;
|
|
|
|
|
2016-04-24 09:45:29 +00:00
|
|
|
void MISC_handler(void)
|
|
|
|
{
|
2017-12-12 22:06:51 +01:00
|
|
|
static bool dorecheck;
|
|
|
|
bool recheck;
|
2017-12-04 15:49:40 +01:00
|
|
|
int i;
|
2019-08-31 17:30:51 +02:00
|
|
|
evt mintime;
|
|
|
|
evt ct = get_cycles();
|
|
|
|
static int recursive;
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2019-08-31 17:30:51 +02:00
|
|
|
if (recursive)
|
|
|
|
{
|
2017-12-12 22:06:51 +01:00
|
|
|
dorecheck = true;
|
2019-08-31 17:30:51 +02:00
|
|
|
return;
|
2017-12-04 15:49:40 +01:00
|
|
|
}
|
2019-08-31 17:30:51 +02:00
|
|
|
recursive++;
|
|
|
|
eventtab[ev_misc].active = false;
|
2017-12-12 22:06:51 +01:00
|
|
|
recheck = true;
|
2019-08-31 17:30:51 +02:00
|
|
|
while (recheck)
|
|
|
|
{
|
2017-12-12 22:06:51 +01:00
|
|
|
recheck = false;
|
2019-08-31 17:30:51 +02:00
|
|
|
mintime = ~0L;
|
|
|
|
for (i = 0; i < ev2_max; i++)
|
|
|
|
{
|
|
|
|
if (eventtab2[i].active)
|
|
|
|
{
|
|
|
|
if (eventtab2[i].evtime == ct)
|
|
|
|
{
|
|
|
|
eventtab2[i].active = false;
|
|
|
|
eventtab2[i].handler(eventtab2[i].data);
|
|
|
|
if (dorecheck || eventtab2[i].active)
|
|
|
|
{
|
2017-12-12 22:06:51 +01:00
|
|
|
recheck = true;
|
|
|
|
dorecheck = false;
|
2019-08-31 17:30:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto eventtime = eventtab2[i].evtime - ct;
|
|
|
|
if (eventtime < mintime)
|
|
|
|
mintime = eventtime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-30 21:21:31 +02:00
|
|
|
}
|
2019-08-31 17:30:51 +02:00
|
|
|
if (mintime != ~0UL)
|
|
|
|
{
|
2017-12-04 15:49:40 +01:00
|
|
|
eventtab[ev_misc].active = true;
|
2020-08-17 18:56:05 +02:00
|
|
|
eventtab[ev_misc].oldcycles = ct;
|
2019-08-31 17:30:51 +02:00
|
|
|
eventtab[ev_misc].evtime = ct + mintime;
|
|
|
|
events_schedule();
|
|
|
|
}
|
|
|
|
recursive--;
|
2017-03-30 21:21:31 +02:00
|
|
|
}
|
2017-12-12 22:06:51 +01:00
|
|
|
|
|
|
|
|
2019-08-31 17:30:51 +02:00
|
|
|
void event2_newevent_xx(int no, evt t, uae_u32 data, evfunc2 func)
|
2017-12-12 22:06:51 +01:00
|
|
|
{
|
|
|
|
static int next = ev2_misc;
|
|
|
|
|
2019-08-31 17:30:51 +02:00
|
|
|
auto et = t + get_cycles();
|
|
|
|
if (no < 0)
|
|
|
|
{
|
2017-12-12 22:06:51 +01:00
|
|
|
no = next;
|
2019-08-31 17:30:51 +02:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (!eventtab2[no].active)
|
|
|
|
{
|
2017-12-12 22:06:51 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (eventtab2[no].evtime == et && eventtab2[no].handler == func && eventtab2[no].data == data)
|
|
|
|
break;
|
|
|
|
no++;
|
|
|
|
if (no == ev2_max)
|
|
|
|
no = ev2_misc;
|
2019-08-31 17:30:51 +02:00
|
|
|
if (no == next)
|
|
|
|
{
|
|
|
|
write_log(_T("out of event2's!\n"));
|
2017-12-12 22:06:51 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
next = no;
|
|
|
|
}
|
|
|
|
eventtab2[no].active = true;
|
|
|
|
eventtab2[no].evtime = et;
|
|
|
|
eventtab2[no].handler = func;
|
|
|
|
eventtab2[no].data = data;
|
2019-08-31 17:30:51 +02:00
|
|
|
MISC_handler();
|
2017-12-12 22:06:51 +01:00
|
|
|
}
|
2020-08-17 18:56:05 +02:00
|
|
|
|
|
|
|
void event2_newevent_x_replace(evt t, uae_u32 data, evfunc2 func)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < ev2_max; i++) {
|
|
|
|
if (eventtab2[i].active && eventtab2[i].handler == func) {
|
|
|
|
eventtab2[i].active = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (((int)t) <= 0) {
|
|
|
|
func(data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event2_newevent_xx(-1, t * CYCLE_UNIT, data, func);
|
|
|
|
}
|