aboutsummaryrefslogtreecommitdiff
path: root/morphos
diff options
context:
space:
mode:
authorRuediger Hanke2002-08-09 10:48:47 +0000
committerRuediger Hanke2002-08-09 10:48:47 +0000
commita30b9aa5f9eab1d800a3cc63ad80fa547211a758 (patch)
tree54d9daaedc5672eb3dcf805152b9bb3d11345ce6 /morphos
parent40a8a7ce1a13d9fc187024d6daf7caf5a3aa58e6 (diff)
downloadscummvm-rg350-a30b9aa5f9eab1d800a3cc63ad80fa547211a758.tar.gz
scummvm-rg350-a30b9aa5f9eab1d800a3cc63ad80fa547211a758.tar.bz2
scummvm-rg350-a30b9aa5f9eab1d800a3cc63ad80fa547211a758.zip
Switched MorphOS port to threaded timers
svn-id: r4720
Diffstat (limited to 'morphos')
-rw-r--r--morphos/Makefile6
-rw-r--r--morphos/morphos.cpp46
-rw-r--r--morphos/morphos.h9
-rw-r--r--morphos/morphos_start.cpp17
-rw-r--r--morphos/morphos_timer.cpp241
5 files changed, 254 insertions, 65 deletions
diff --git a/morphos/Makefile b/morphos/Makefile
index 53909bec93..4e18cf7387 100644
--- a/morphos/Makefile
+++ b/morphos/Makefile
@@ -2,7 +2,7 @@ vpath %.cpp ../:../sound/:../v3/:../v4/:../simon/:../gui/
vpath %.h ../
CC = g++
-CFLAGS = -Wno-multichar -fstrength-reduce -O2
+CFLAGS = -Wno-multichar -fstrength-reduce -fno-rtti -O2
DEFINES = -DNO_PPCINLINE_STDARG -DNO_PPCINLINE_VARARGS
LDFLAGS := -noixemul -s
INCLUDES:= -I../ -I../sound
@@ -18,10 +18,10 @@ SIMONOBJS = midi.o simon.o simondebug.o simonitems.o simonres.o simonsys.o simon
OBJS = actor.o akos.o boxes.o config-file.o costume.o gfx.o object.o resource.o \
saveload.o script.o scummvm.o sound.o string.o sys.o verbs.o \
- morphos.o morphos_sound.o morphos_start.o script_v1.o script_v2.o debug.o gui.o \
+ morphos.o morphos_sound.o morphos_start.o morphos_timer.o script_v1.o script_v2.o debug.o gui.o \
imuse.o fmopl.o mixer.o mididrv.o debugrl.o vars.o insane.o \
gameDetector.o init.o resource_v3.o resource_v4.o util.o main.o \
- bundle.o timer.o $(GUIOBJS) $(SIMONOBJS)
+ bundle.o $(GUIOBJS) $(SIMONOBJS)
DISTFILES=$(OBJS:.o=.cpp) Makefile scumm.h scummsys.h stdafx.h stdafx.cpp \
windows.cpp debugrl.h whatsnew.txt readme.txt copying.txt \
diff --git a/morphos/morphos.cpp b/morphos/morphos.cpp
index 1b08b0c715..de1c5ff643 100644
--- a/morphos/morphos.cpp
+++ b/morphos/morphos.cpp
@@ -21,8 +21,6 @@
*
*/
-#include <devices/timer.h>
-
#include "stdafx.h"
#include "scumm.h"
@@ -125,13 +123,10 @@ OSystem_MorphOS::OSystem_MorphOS( int game_id, SCALERTYPE gfx_mode, bool full_sc
strcpy( ScummWndTitle, "ScummVM MorphOS" );
TimerMsgPort = NULL;
TimerIORequest = NULL;
- SaveTimerMsgPort = NULL;
- SaveTimerIORequest = NULL;
- SaveTimerRun = false;
OpenATimer( &TimerMsgPort, (struct IORequest **)&TimerIORequest, UNIT_MICROHZ );
- OpenATimer( &SaveTimerMsgPort, (struct IORequest **)&SaveTimerIORequest, UNIT_VBLANK );
+ TimerBase = TimerIORequest->tr_node.io_Device;
ScummNoCursor = (UWORD *)AllocVec( 16, MEMF_CHIP | MEMF_CLEAR );
}
@@ -152,21 +147,6 @@ OSystem_MorphOS::~OSystem_MorphOS()
if( TimerMsgPort )
DeleteMsgPort( TimerMsgPort );
- if( SaveTimerRun )
- {
- AbortIO( (struct IORequest *)SaveTimerIORequest );
- WaitIO( (struct IORequest *)SaveTimerIORequest );
- }
-
- if( SaveTimerIORequest )
- {
- CloseDevice( (struct IORequest *)SaveTimerIORequest );
- DeleteIORequest( (struct IORequest *)SaveTimerIORequest );
- }
-
- if( SaveTimerMsgPort )
- DeleteMsgPort( SaveTimerMsgPort );
-
if( ScummMusicThread )
{
Signal( (struct Task *)ScummMusicThread, SIGBREAKF_CTRL_C );
@@ -245,22 +225,7 @@ void OSystem_MorphOS::delay_msecs(uint msecs)
void OSystem_MorphOS::set_timer(int timer, int (*callback)(int))
{
- if( timer )
- {
- SaveTimerRun = true;
- TimerCallback = callback;
- TimerInterval = timer;
-
- SaveTimerIORequest->tr_node.io_Command = TR_ADDREQUEST;
- SaveTimerIORequest->tr_time.tv_secs = timer/1000;
- SaveTimerIORequest->tr_time.tv_micro = timer%1000;
- SendIO( (struct IORequest *)SaveTimerIORequest );
- }
- else
- {
- SaveTimerRun = false;
- TimerInterval = 0;
- }
+ warning("set_timer() unexpectedly called");
}
void *OSystem_MorphOS::create_thread(ThreadProc *proc, void *param)
@@ -734,13 +699,6 @@ bool OSystem_MorphOS::poll_event( Event *event )
{
struct IntuiMessage *ScummMsg;
- if( SaveTimerRun && CheckIO( (struct IORequest *)SaveTimerIORequest ) )
- {
- WaitIO( (struct IORequest *)SaveTimerIORequest );
- TimerInterval = (*TimerCallback)( TimerInterval );
- set_timer( TimerInterval, TimerCallback );
- }
-
if( ScummMsg = (struct IntuiMessage *)GetMsg( ScummWindow->UserPort ) )
{
switch( ScummMsg->Class )
diff --git a/morphos/morphos.h b/morphos/morphos.h
index 752a007179..d0d05ea10d 100644
--- a/morphos/morphos.h
+++ b/morphos/morphos.h
@@ -105,6 +105,8 @@ class OSystem_MorphOS : public OSystem
static OSystem_MorphOS *create ( int game_id, SCALERTYPE gfx_scaler, bool full_screen );
static uint32 make_color( int pixfmt, int r, int g, int b );
+ static void OpenATimer( struct MsgPort **port, struct IORequest **req, ULONG unit );
+
static SCALERTYPE FindScaler ( const char *ScalerName );
private:
@@ -130,8 +132,6 @@ class OSystem_MorphOS : public OSystem
void draw_mouse();
void undraw_mouse();
- void OpenATimer( struct MsgPort **port, struct IORequest **req, ULONG unit );
-
/* Display-related attributes */
struct Screen *ScummScreen;
struct Window *ScummWindow;
@@ -196,11 +196,6 @@ class OSystem_MorphOS : public OSystem
/* Timer-related attributes */
struct MsgPort *TimerMsgPort;
struct timerequest *TimerIORequest;
- struct MsgPort *SaveTimerMsgPort;
- struct timerequest *SaveTimerIORequest;
- int (*TimerCallback)(int);
- bool SaveTimerRun;
- int TimerInterval;
/* Game-related attributes */
int GameID;
diff --git a/morphos/morphos_start.cpp b/morphos/morphos_start.cpp
index 3cd8d28fdd..ea013fb53a 100644
--- a/morphos/morphos_start.cpp
+++ b/morphos/morphos_start.cpp
@@ -22,6 +22,7 @@
*/
#include <exec/types.h>
+#include <exec/devices.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <workbench/startup.h>
@@ -58,7 +59,7 @@ static OSystem_MorphOS::SCALERTYPE ScummGfxScaler = OSystem_MorphOS::ST_INVALID;
static BPTR OrigDirLock = 0;
struct Library *CDDABase = NULL;
-struct Library *CyberGfxBase = NULL;
+struct Device *TimerBase = NULL;
OSystem_MorphOS *TheSystem = NULL;
@@ -92,6 +93,9 @@ void close_resources()
if( TheSystem )
delete TheSystem;
+ if( g_scumm )
+ delete g_scumm;
+
if( ScummPath )
FreeVec( ScummPath );
@@ -106,9 +110,6 @@ void close_resources()
if( CDDABase )
CloseLibrary( CDDABase );
-
- if( CyberGfxBase )
- CloseLibrary( CyberGfxBase );
}
static STRPTR FindMusicDriver( STRPTR argval )
@@ -247,13 +248,7 @@ int main()
InitSemaphore( &ScummSoundThreadRunning );
InitSemaphore( &ScummMusicThreadRunning );
- CyberGfxBase = OpenLibrary( "cybergraphics.library", 41 );
- if( CyberGfxBase == NULL )
- {
- puts( "Failed to open cybergraphics.library" );
- exit( 1 );
- }
-
+ g_scumm = NULL;
atexit( &close_resources );
if( _WBenchMsg == NULL )
diff --git a/morphos/morphos_timer.cpp b/morphos/morphos_timer.cpp
new file mode 100644
index 0000000000..ccec0b7468
--- /dev/null
+++ b/morphos/morphos_timer.cpp
@@ -0,0 +1,241 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "scumm.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"
+
+static TagItem TimerServiceTags[] = { { NP_Entry, 0 },
+ { NP_Name, (ULONG)"ScummVM Timer Service" },
+ { NP_Priority, 20 },
+ { TAG_DONE, 0 }
+ };
+
+Timer::Timer(Scumm * system)
+{
+ static EmulFunc ThreadEmulFunc;
+
+ InitSemaphore(&TimerServiceSemaphore);
+
+ ThreadEmulFunc.Trap = TRAP_FUNC;
+ ThreadEmulFunc.Address = (ULONG) &TimerService;
+ ThreadEmulFunc.StackSize = 16000;
+ ThreadEmulFunc.Extension = 0;
+ ThreadEmulFunc.Arg1 = (ULONG) this;
+ TimerServiceTags[0].ti_Data = (ULONG) &ThreadEmulFunc;
+ TimerServiceThread = CreateNewProc(TimerServiceTags);
+}
+
+Timer::~Timer()
+{
+ if (TimerServiceThread)
+ {
+ Signal((Task *) TimerServiceThread, SIGBREAKF_CTRL_C);
+ ObtainSemaphore(&TimerServiceSemaphore);
+ ReleaseSemaphore(&TimerServiceSemaphore);
+ }
+}
+
+bool Timer::init()
+{
+ return TimerServiceThread != NULL;
+}
+
+void Timer::release()
+{
+}
+
+bool Timer::installProcedure(int ((*procedure)(int)), int32 interval)
+{
+ return SendMsg(TSM_MSGID_ADDTIMER, procedure, interval);
+}
+
+void Timer::releaseProcedure(int ((*procedure)(int)))
+{
+ SendMsg(TSM_MSGID_REMTIMER, procedure, 0);
+}
+
+bool Timer::SendMsg(ULONG msg_id, int ((*procedure)(int)), LONG interval)
+{
+ if (TimerServiceThread == NULL)
+ return false;
+
+ TimerServiceMessage *tmsg = (TimerServiceMessage *) AllocVec(sizeof (TimerServiceMessage), MEMF_PUBLIC | MEMF_CLEAR);
+ if (tmsg == NULL)
+ return false;
+
+ MsgPort *reply_port = CreateMsgPort();
+ if (reply_port == NULL)
+ {
+ FreeVec(tmsg);
+ return false;
+ }
+
+ tmsg->tsm_Message.mn_Node.ln_Type = NT_MESSAGE;
+ tmsg->tsm_Message.mn_ReplyPort = reply_port;
+ tmsg->tsm_Message.mn_Length = sizeof (TimerServiceMessage);
+ tmsg->tsm_MsgID = msg_id;
+ tmsg->tsm_Callback = procedure;
+ tmsg->tsm_Interval = interval;
+ PutMsg(&TimerServiceThread->pr_MsgPort, tmsg);
+ WaitPort(reply_port);
+ GetMsg(reply_port);
+
+ FreeVec(tmsg);
+ DeleteMsgPort(reply_port);
+
+ return true;
+}
+
+void Timer::TimerService(Timer *this_ptr)
+{
+ 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];
+
+ ObtainSemaphore(&this_ptr->TimerServiceSemaphore);
+
+ 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 > 1000)
+ unit = UNIT_VBLANK;
+ 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/1000;
+ req->tr_time.tv_micro = (interval%1000)*1000;
+ SendIO(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;
+ 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.");
+ }
+ }
+
+ ReplyMsg((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)(interval);
+ GetSysTime(&end_callback);
+ SubTime(&end_callback, &start_callback);
+ interval -= end_callback.tv_sec*1000+end_callback.tv_micro/1000+20;
+
+ req->tr_node.io_Command = TR_ADDREQUEST;
+ req->tr_time.tv_secs = interval/1000;
+ req->tr_time.tv_micro = (interval%1000)*1000;
+ SendIO(req);
+ }
+ }
+ }
+ }
+
+ for (t = 0; t < timers; t++)
+ {
+ AbortIO((IORequest *) timer_slots[t].ts_IORequest);
+ WaitIO((IORequest *) timer_slots[t].ts_IORequest);
+ DeleteIORequest((IORequest *) timer_slots[t].ts_IORequest);
+ DeleteMsgPort(timer_slots[t].ts_Port);
+ }
+
+ ReleaseSemaphore(&this_ptr->TimerServiceSemaphore);
+ RemTask(NULL);
+}
+