aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/morphos/morphos_timer.cpp
diff options
context:
space:
mode:
authorMax Horn2006-06-24 12:33:52 +0000
committerMax Horn2006-06-24 12:33:52 +0000
commit492c65009cb186024f52ec1970617028c3d09efe (patch)
tree8e4f89975ccd8bc094161c73c128d92706880a73 /backends/platform/morphos/morphos_timer.cpp
parentdc41d02ac73109add30a3456bc44d558f29d2f8d (diff)
downloadscummvm-rg350-492c65009cb186024f52ec1970617028c3d09efe.tar.gz
scummvm-rg350-492c65009cb186024f52ec1970617028c3d09efe.tar.bz2
scummvm-rg350-492c65009cb186024f52ec1970617028c3d09efe.zip
Started to move 'monolithic' parts of our ports to the new 'background/platform' directory (see also the 'Modular_Backends' page in our Wiki)
svn-id: r23293
Diffstat (limited to 'backends/platform/morphos/morphos_timer.cpp')
-rw-r--r--backends/platform/morphos/morphos_timer.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/backends/platform/morphos/morphos_timer.cpp b/backends/platform/morphos/morphos_timer.cpp
new file mode 100644
index 0000000000..b558c7fd66
--- /dev/null
+++ b/backends/platform/morphos/morphos_timer.cpp
@@ -0,0 +1,234 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002-2006 The ScummVM Team
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "common/stdafx.h"
+#include "base/engine.h"
+
+#include <exec/memory.h>
+#include <exec/semaphores.h>
+#include <dos/dostags.h>
+#include <emul/emulinterface.h>
+
+#include <proto/exec.h>
+#include <proto/dos.h>
+#include <proto/timer.h>
+
+#include "morphos.h"
+#include "timer.h"
+
+Timer::Timer(Engine * engine)
+{
+ if ((TimerServicePort = CreateMsgPort()))
+ {
+ TimerServiceStartup.mn_Node.ln_Type = NT_MESSAGE;
+ TimerServiceStartup.mn_ReplyPort = TimerServicePort;
+ TimerServiceStartup.mn_Length = sizeof(TimerServiceStartup);
+
+ TimerServiceThread = CreateNewProcTags(NP_Entry, (ULONG) TimerService,
+ NP_CodeType, CODETYPE_PPC,
+ NP_Name, (ULONG) "ScummVM Timer Service",
+ NP_Priority, 0,
+ NP_StartupMsg, &TimerServiceStartup,
+ NP_PPC_Arg1, (ULONG) this,
+ NP_PPC_Arg2, (ULONG) engine,
+ TAG_DONE
+ );
+ }
+}
+
+Timer::~Timer()
+{
+ if (TimerServiceThread)
+ {
+ Signal((Task *) TimerServiceThread, SIGBREAKF_CTRL_C);
+ WaitPort(TimerServicePort);
+ DeleteMsgPort(TimerServicePort);
+ TimerServiceThread = NULL;
+ }
+}
+
+bool Timer::init()
+{
+ return TimerServiceThread != NULL;
+}
+
+void Timer::release()
+{
+}
+
+bool Timer::installTimerProc(TimerProc procedure, int32 interval)
+{
+ return SendMsg(TSM_MSGID_ADDTIMER, procedure, interval);
+}
+
+void Timer::removeTimerProc(TimerProc procedure)
+{
+ SendMsg(TSM_MSGID_REMTIMER, procedure, 0);
+}
+
+bool Timer::SendMsg(ULONG msg_id, TimerProc procedure, LONG interval)
+{
+ if (TimerServiceThread == NULL)
+ return false;
+
+ TimerServiceMessage *tmsg = (TimerServiceMessage *) AllocVec(sizeof (TimerServiceMessage), MEMF_PUBLIC | MEMF_CLEAR);
+ if (tmsg == NULL)
+ return false;
+
+ tmsg->tsm_Message.mn_Node.ln_Type = NT_MESSAGE;
+ tmsg->tsm_Message.mn_ReplyPort = NULL;
+ tmsg->tsm_Message.mn_Length = sizeof (TimerServiceMessage);
+ tmsg->tsm_MsgID = msg_id;
+ tmsg->tsm_Callback = procedure;
+ tmsg->tsm_Interval = interval;
+ PutMsg(&TimerServiceThread->pr_MsgPort, (Message*) tmsg);
+
+ return true;
+}
+
+void Timer::TimerService(Timer *this_ptr, Engine *engine)
+{
+ MsgPort *port = &((Process *) FindTask(NULL))->pr_MsgPort;
+ ULONG port_bit = 1 << port->mp_SigBit;
+ ULONG signal_mask = SIGBREAKF_CTRL_C | port_bit;
+ ULONG timer_bits = 0, signals;
+ ULONG interval, t;
+ timeval start_callback, end_callback;
+
+ ULONG timers = 0;
+ TimerSlot timer_slots[MAX_TIMERS];
+
+ for (;;)
+ {
+ signals = Wait(signal_mask);
+
+ GetSysTime(&start_callback);
+
+ if (signals & port_bit)
+ {
+ TimerServiceMessage *tmsg;
+
+ while ((tmsg = (TimerServiceMessage *) GetMsg(port)))
+ {
+ if (tmsg->tsm_Message.mn_Length == sizeof (TimerServiceMessage))
+ {
+ switch (tmsg->tsm_MsgID)
+ {
+ case TSM_MSGID_ADDTIMER:
+ if (timers < MAX_TIMERS)
+ {
+ ULONG unit = UNIT_MICROHZ;
+
+ if (tmsg->tsm_Interval >= 1000000)
+ unit = UNIT_VBLANK;
+ if (OSystem_MorphOS::OpenATimer(&timer_slots[timers].ts_Port, (IORequest **) &timer_slots[timers].ts_IORequest, unit))
+ {
+ timer_slots[timers].ts_Callback = tmsg->tsm_Callback;
+ timer_slots[timers].ts_Interval = tmsg->tsm_Interval;
+ timer_slots[timers].ts_SignalBit = 1 << timer_slots[timers].ts_Port->mp_SigBit;
+
+ signal_mask |= timer_slots[timers].ts_SignalBit;
+ timer_bits |= timer_slots[timers].ts_SignalBit;
+
+ timerequest *req = timer_slots[timers].ts_IORequest;
+ interval = timer_slots[timers].ts_Interval;
+ req->tr_node.io_Command = TR_ADDREQUEST;
+ req->tr_time.tv_secs = interval/1000000;
+ req->tr_time.tv_micro = interval%1000000;
+ SendIO((IORequest*) req);
+
+ timers++;
+ }
+ }
+ break;
+
+ case TSM_MSGID_REMTIMER:
+ {
+ for (t = 0; t < timers; t++)
+ {
+ if (timer_slots[t].ts_Callback == tmsg->tsm_Callback)
+ {
+ AbortIO((IORequest *) timer_slots[t].ts_IORequest);
+ WaitIO((IORequest *) timer_slots[t].ts_IORequest);
+ signal_mask &= ~timer_slots[t].ts_SignalBit;
+ timer_bits &= ~timer_slots[t].ts_SignalBit;
+ CloseDevice((IORequest *) timer_slots[t].ts_IORequest);
+ DeleteIORequest((IORequest *) timer_slots[t].ts_IORequest);
+ DeleteMsgPort(timer_slots[t].ts_Port);
+ if (t < timers-1)
+ memmove(&timer_slots[t], &timer_slots[t+1], sizeof (TimerSlot)*(timers-t-1));
+ timers--;
+ continue;
+ }
+ }
+ break;
+ }
+
+ default:
+ warning("MorphOS TimerService received message of unknown type.");
+ }
+ }
+
+ if (tmsg->tsm_Message.mn_ReplyPort)
+ ReplyMsg((Message *) tmsg);
+ else
+ FreeVec((Message *) tmsg);
+ }
+ }
+
+ if (signals & SIGBREAKF_CTRL_C)
+ break;
+
+ if (signals & timer_bits)
+ {
+ for (t = 0; t < timers; t++)
+ {
+ if (signals & timer_slots[t].ts_SignalBit)
+ {
+ timerequest *req = timer_slots[t].ts_IORequest;
+ WaitIO((IORequest *) req);
+ interval = timer_slots[t].ts_Interval;
+ (*timer_slots[t].ts_Callback)(engine);
+ GetSysTime(&end_callback);
+ SubTime(&end_callback, &start_callback);
+ interval -= end_callback.tv_sec*1000000+end_callback.tv_micro/1000000+40000;
+ if (interval < 0)
+ interval = 0;
+
+ req->tr_node.io_Command = TR_ADDREQUEST;
+ req->tr_time.tv_secs = interval/1000000;
+ req->tr_time.tv_micro = interval%1000000;
+ SendIO((IORequest*) req);
+ }
+ }
+ }
+ }
+
+ for (t = 0; t < timers; t++)
+ {
+ AbortIO((IORequest *) timer_slots[t].ts_IORequest);
+ WaitIO((IORequest *) timer_slots[t].ts_IORequest);
+ CloseDevice((IORequest *) timer_slots[t].ts_IORequest);
+ DeleteIORequest((IORequest *) timer_slots[t].ts_IORequest);
+ DeleteMsgPort(timer_slots[t].ts_Port);
+ }
+}
+