diff options
author | Ruediger Hanke | 2002-08-09 10:48:47 +0000 |
---|---|---|
committer | Ruediger Hanke | 2002-08-09 10:48:47 +0000 |
commit | a30b9aa5f9eab1d800a3cc63ad80fa547211a758 (patch) | |
tree | 54d9daaedc5672eb3dcf805152b9bb3d11345ce6 /morphos | |
parent | 40a8a7ce1a13d9fc187024d6daf7caf5a3aa58e6 (diff) | |
download | scummvm-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/Makefile | 6 | ||||
-rw-r--r-- | morphos/morphos.cpp | 46 | ||||
-rw-r--r-- | morphos/morphos.h | 9 | ||||
-rw-r--r-- | morphos/morphos_start.cpp | 17 | ||||
-rw-r--r-- | morphos/morphos_timer.cpp | 241 |
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); +} + |