From 492c65009cb186024f52ec1970617028c3d09efe Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 24 Jun 2006 12:33:52 +0000 Subject: 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 --- backends/platform/morphos/morphos_timer.cpp | 234 ++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 backends/platform/morphos/morphos_timer.cpp (limited to 'backends/platform/morphos/morphos_timer.cpp') 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 +#include +#include +#include + +#include +#include +#include + +#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); + } +} + -- cgit v1.2.3