aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--morphos/Makefile41
-rw-r--r--morphos/MorphOS.readme13
-rw-r--r--morphos/morphos.cpp1933
-rw-r--r--morphos/morphos_sound.cpp288
4 files changed, 2275 insertions, 0 deletions
diff --git a/morphos/Makefile b/morphos/Makefile
new file mode 100644
index 0000000000..e8c183b8fe
--- /dev/null
+++ b/morphos/Makefile
@@ -0,0 +1,41 @@
+vpath %.cpp ../:../sound/
+
+CC = g++
+CFLAGS = -Wno-multichar -fstrength-reduce -O2
+DEFINES =
+LDFLAGS := -noixemul -s
+INCLUDES:= -I../ -I../sound
+CPPFLAGS= $(DEFINES) $(INCLUDES)
+LIBS = -lamiga -lamigastubs
+ZIPFILE := scummvm-`date '+%Y-%m-%d'`.zip
+
+INCS = ../scumm.h ../scummsys.h ../stdafx.h
+
+OBJS = actor.o akos.o boxes.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 script_v1.o script_v2.o debug.o gui.o \
+ imuse.o fmopl.o adlib.o gmidi.o debugrl.o vars.o insane.o
+
+DISTFILES=$(OBJS:.o=.cpp) Makefile scumm.h scummsys.h stdafx.h stdafx.cpp \
+ windows.cpp debugrl.h whatsnew.txt readme.txt copying.txt \
+ scummvm.dsp scummvm.dsw sound/fmopl.h
+
+.cpp.o:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
+
+all: scummvm
+
+scummvm: $(OBJS)
+ $(CC) $(LDFLAGS) -o $(@) $(OBJS) $(LIBS)
+
+#$(OBJS): Makefile
+
+clean:
+ rm -f $(OBJS) scummvm
+
+dist:
+ rm -f $(ZIPFILE)
+ zip -q $(ZIPFILE) $(DISTFILES)
+
+check:
+$(OBJS): $(INCS)
diff --git a/morphos/MorphOS.readme b/morphos/MorphOS.readme
new file mode 100644
index 0000000000..693ae324c4
--- /dev/null
+++ b/morphos/MorphOS.readme
@@ -0,0 +1,13 @@
+This directory contains the source for the MorphOS port of ScummVM. To build, you
+must have a proper Geek Gadgets installation. Just type "make" in the MorphOS
+subdirectory. If you don't have the includes for AMidi 2 and cdda.library, check
+my webpage. If they aren't uploaded yet, feel free to e-mail me.
+
+You don't have to build ScummVM yourself. The latest official and CVS binaries are
+available from my website at:
+
+http://www.muenster.de/~tomjoad/scummvm.html
+
+Ruediger Hanke
+tomjoad@muenster.de
+
diff --git a/morphos/morphos.cpp b/morphos/morphos.cpp
new file mode 100644
index 0000000000..bc4bc63ed6
--- /dev/null
+++ b/morphos/morphos.cpp
@@ -0,0 +1,1933 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 Rüdiger Hanke
+ *
+ * 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.
+ *
+ * MorphOS interface
+ */
+
+#include <devices/timer.h>
+
+#include "stdafx.h"
+#include "scumm.h"
+#include "gui.h"
+#include "sound.h"
+
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <exec/libraries.h>
+#include <exec/semaphores.h>
+#include <dos/dostags.h>
+#include <intuition/screens.h>
+#include <cybergraphics/cybergraphics.h>
+#include <devices/inputevent.h>
+#include <intuition/intuition.h>
+#include <workbench/startup.h>
+
+#define NO_PPCINLINE_STDARG
+#define NO_PPCINLINE_VARARGS
+#include <clib/alib_protos.h>
+#include <proto/exec.h>
+#include <proto/dos.h>
+#include <proto/graphics.h>
+#include <proto/icon.h>
+#include <proto/intuition.h>
+#include <proto/keymap.h>
+#include <proto/timer.h>
+#include <proto/cdda.h>
+#include <proto/cybergraphics.h>
+
+#ifdef __MORPHOS__
+#include <emul/emulinterface.h>
+#endif
+
+#include <time.h>
+
+extern "C" struct WBStartup *_WBenchMsg;
+
+Scumm scumm;
+ScummDebugger debugger;
+Gui gui;
+
+SoundEngine sound;
+SOUND_DRIVER_TYPE snd_driv;
+
+typedef void (*ScalerFunc)( uint32 src_x, uint32 src_y, uint32 width, uint32 height );
+
+void Super2xSaI( uint32 src_x, uint32 src_y, uint32 width, uint32 height );
+void SuperEagle( uint32 src_x, uint32 src_y, uint32 width, uint32 height );
+void PointScaler( uint32 src_x, uint32 src_y, uint32 width, uint32 height );
+
+static struct Screen *ScummScreen = NULL;
+static struct Window *ScummWindow = NULL;
+static APTR ScummBuffer = NULL;
+static struct ScreenBuffer *ScummScreenBuffer[ 2 ] = { NULL, NULL };
+static struct BitMap *ScummRenderTo = NULL;
+static ULONG ScummPaintBuffer;
+static UWORD *ScummNoCursor = NULL;
+static struct Process *ScummMusicThread = NULL;
+static ScalerFunc ScummScaler = &Super2xSaI;
+static ULONG ScummColors[256];
+static USHORT ScummColors16[256];
+static WORD ScummWinX = -1;
+static WORD ScummWinY = -1;
+static bool ScummOrigMouse = false;
+
+static struct MsgPort *TimerMsgPort = NULL;
+static struct timerequest *TimerIORequest = NULL;
+static bool TimerStarted = false;
+
+static char*ScummStory = NULL;
+static char*ScummPath = NULL;
+static char ScummWndTitle[ 125 ];
+static int ScummDepth = 0;
+static int ScummScale = 1;
+static bool Scumm16ColFmt16 = false;
+static int ScummScrWidth = 0;
+static int ScummScrHeight = 0;
+static LONG ScummMidiUnit = 0;
+static LONG ScummMidiVolume = 0;
+static LONG ScummMidiTempo = 0;
+
+struct Library *CDDABase = NULL;
+static CDRIVEPTR CDrive = NULL;
+static struct TagItem FindCDTags[] = { { CDFA_VolumeName, (ULONG)"LoomCD" },
+ { TAG_DONE, 0 } };
+
+static struct TagItem PlayTags[] = { { CDPA_StartTrack, 1 },
+ { CDPA_StartFrame, 0 },
+ { CDPA_EndTrack, 1 },
+ { CDPA_EndFrame, 0 },
+ { TAG_DONE, 0 }
+ };
+static ULONG CDDATrackOffset = 0;
+
+
+static struct RDArgs *ScummArgs = NULL;
+static BPTR OrigDirLock = 0;
+
+struct GfxScaler
+{
+ STRPTR gs_Name;
+ ScalerFunc gs_Function;
+};
+
+static struct GfxScaler ScummScalers[] = { { "none", NULL },
+ { "Point", PointScaler },
+ { "SuperEagle", SuperEagle },
+ { "Super2xSaI", Super2xSaI },
+ { NULL, NULL },
+ { NULL, NULL },
+ { NULL, NULL },
+ { NULL, NULL },
+ { NULL, NULL },
+ { NULL, NULL }
+ };
+
+// For command line parsing
+static STRPTR usageTemplate = "STORY/A,DATAPATH/K,WBWINDOW/S,SCALER/K,MIDIUNIT/K/N,NOMUSIC/S,VOLUME/K/N,TEMPO/K,NOSUBTITLES=NST/S";
+typedef enum { USG_STORY = 0, USG_DATAPATH, USG_WBWINDOW, USG_SCALER, USG_MIDIUNIT, USG_NOMUSIC, USG_VOLUME, USG_TEMPO, USG_NOSUBTITLES } usageFields;
+static LONG args[ 9 ] = { (ULONG)NULL, (ULONG)NULL, FALSE, (ULONG)NULL, (ULONG)NULL, false, (ULONG)NULL, (ULONG)NULL, false };
+
+// These are for the scaling engine
+static uint32 colorMask = 0xF7DEF7DE;
+static uint32 lowPixelMask = 0x08210821;
+static uint32 qcolorMask = 0xE79CE79C;
+static uint32 qlowpixelMask = 0x18631863;
+static uint32 redblueMask = 0xF81F;
+static uint32 greenMask = 0x7E0;
+static int PixelsPerMask = 2;
+static byte *src_line[4];
+static byte *dst_line[2];
+
+struct EmulFunc MyEmulFunc;
+struct TagItem musicProcTags[] = { { NP_Entry, (ULONG)&MyEmulFunc.Trap },
+ { NP_Name, (ULONG)"ScummVM Music Thread" },
+ { NP_StackSize, 16000 },
+ { NP_Priority, 30 },
+ { TAG_DONE, 0 }
+ };
+
+extern int morphos_music_thread( Scumm *s, ULONG MidiUnit, bool NoMusic );
+
+extern struct SignalSemaphore ScummMusicThreadRunning;
+
+struct Library *CyberGfxBase = NULL;
+struct Device *TimerBase = NULL;
+
+static int current_shake_pos;
+
+void updateScreen(Scumm *s);
+
+void BoxTest(int num)
+{
+ /* Debug only, remove */
+}
+
+int GetTicks()
+{
+/* unsigned long long time64;
+ ULONG ClockTicks;
+ struct EClockVal ClockVal;
+
+ ClockTicks = ReadEClock( &ClockVal );
+ time64 = ClockVal.ev_hi;
+
+ time64 = (time64 << 32) | ClockVal.ev_lo;
+ return (time64/ClockTicks)*1000;*/
+
+ int ticks = clock();
+ ticks *= (1000/CLOCKS_PER_SEC);
+ return ticks;
+}
+
+/*void cd_playtrack( int track, int offset, int delay )
+{
+ if( !CDrive && CDDABase )
+ {
+ CDrive = CDDA_FindNextDrive( NULL, FindCDTags );
+ if( CDrive )
+ {
+ if( !CDDA_ObtainDrive( CDrive, CDDA_SHARED_ACCESS, NULL ) )
+ CDrive = NULL;
+ }
+ }
+
+ if( CDrive && offset && delay )
+ {
+ double offs, del;
+ offs = offset;
+ del = delay;
+ PlayTags[ 1 ].ti_Data = (ULONG)((offs * 7.5) - CDDATrackOffset);
+ PlayTags[ 3 ].ti_Data = PlayTags[ 1 ].ti_Data + (ULONG)(del * 7.5);
+ CDDA_Play( CDrive, PlayTags );
+ }
+}*/
+
+static int cd_track = 0, cd_num_loops = 0, cd_start_frame = 0;
+static ULONG cd_end_time = 0;
+static ULONG cd_stop_time = 0;
+
+void cd_play( int track, int num_loops, int start_frame, int length )
+{
+ if( CDrive && start_frame >= 0 )
+ {
+ struct CDS_TrackInfo ti;
+
+ if( start_frame > 0 )
+ start_frame -= CDDATrackOffset;
+
+ cd_track = track;
+ cd_num_loops = num_loops;
+ cd_start_frame = start_frame;
+
+ PlayTags[ 0 ].ti_Data = track;
+ PlayTags[ 1 ].ti_Data = start_frame;
+ PlayTags[ 2 ].ti_Data = (length == 0) ? track+1 : track;
+ PlayTags[ 3 ].ti_Data = length ? start_frame+length : 0;
+ CDDA_Play( CDrive, PlayTags );
+ cd_stop_time = 0;
+
+ CDDA_GetTrackInfo( CDrive, track, 0, &ti );
+ cd_end_time = GetTicks() + ti.ti_TrackLength.tm_Format.tm_Frame * 1000 / 75;
+ }
+}
+
+// Schedule the music to be stopped after 1/10 sec, unless another
+// track is started in the meantime.
+void cd_stop()
+{
+ cd_stop_time = GetTicks() + 100;
+ cd_num_loops = 0;
+}
+
+int cd_is_running()
+{
+ ULONG status;
+
+ if( CDrive == NULL )
+ return 0;
+
+ CDDA_GetAttr( CDDA_Status, CDrive, &status );
+ return (cd_num_loops != 0 && (GetTicks() < cd_end_time || status != CDDA_Status_Ready));
+}
+
+void cd_music_loop()
+{
+ if( CDrive )
+ {
+ if( cd_stop_time != 0 && GetTicks() >= cd_stop_time )
+ {
+ CDDA_Stop( CDrive );
+ cd_num_loops = 0;
+ cd_stop_time = 0;
+ return;
+ }
+ if( cd_num_loops == 0 || GetTicks() < cd_end_time )
+ return;
+
+ ULONG status;
+ CDDA_GetAttr( CDDA_Status, CDrive, &status );
+ if( cd_num_loops != 1 && status != CDDA_Status_Ready )
+ {
+ // Wait another second for it to be done
+ cd_end_time += 1000;
+ return;
+ }
+
+ if( cd_num_loops > 0 )
+ cd_num_loops--;
+
+ if( cd_num_loops != 0 )
+ {
+ struct CDS_TrackInfo ti;
+
+ PlayTags[ 0 ].ti_Data = cd_track;
+ PlayTags[ 1 ].ti_Data = cd_start_frame;
+ CDDA_Play( CDrive, PlayTags );
+
+ CDDA_GetTrackInfo( CDrive, cd_track, 0, &ti );
+ cd_end_time = GetTicks() + ti.ti_TrackLength.tm_Format.tm_Frame * 1000 / 75;
+ }
+ }
+}
+
+void closeResources()
+{
+ if( ScummMusicThread )
+ {
+ Signal( (struct Task *)ScummMusicThread, SIGBREAKF_CTRL_F );
+ ObtainSemaphore( &ScummMusicThreadRunning ); /* Wait for thread to finish */
+ ReleaseSemaphore( &ScummMusicThreadRunning );
+ }
+
+ if( TimerStarted )
+ {
+ AbortIO( (struct IORequest *)TimerIORequest );
+ WaitIO( (struct IORequest *)TimerIORequest );
+ }
+
+ if( TimerIORequest )
+ {
+ CloseDevice( (struct IORequest *)TimerIORequest );
+ DeleteIORequest( (struct IORequest *)TimerIORequest );
+ }
+
+ if( TimerMsgPort )
+ DeleteMsgPort( TimerMsgPort );
+
+ if( OrigDirLock )
+ CurrentDir( OrigDirLock );
+
+ if( ScummPath )
+ FreeVec( ScummPath );
+
+ if( ScummStory )
+ FreeVec( ScummStory );
+
+ if( ScummArgs )
+ FreeArgs( ScummArgs );
+
+ if( ScummNoCursor )
+ FreeVec( ScummNoCursor );
+
+ if( ScummBuffer )
+ FreeVec( ScummBuffer );
+
+ if( ScummRenderTo && !ScummScreen )
+ FreeBitMap( ScummRenderTo );
+
+ if( ScummWindow )
+ CloseWindow( ScummWindow );
+
+ if( ScummScreen )
+ {
+ if( ScummScreenBuffer[ 0 ] )
+ FreeScreenBuffer( ScummScreen, ScummScreenBuffer[ 0 ] );
+ if( ScummScreenBuffer[ 1 ] )
+ FreeScreenBuffer( ScummScreen, ScummScreenBuffer[ 1 ] );
+ CloseScreen( ScummScreen );
+ }
+
+ if( CDDABase )
+ {
+ if( CDrive && CDDABase )
+ {
+ CDDA_Stop( CDrive );
+ CDDA_ReleaseDrive( CDrive );
+ }
+ CloseLibrary( CDDABase );
+ }
+
+ if( CyberGfxBase )
+ CloseLibrary( CyberGfxBase );
+}
+
+uint32 makeColForPixFmt( int pixfmt, int r, int g, int b )
+{
+ uint32 col = 0;
+
+ switch( pixfmt )
+ {
+ case PIXFMT_RGB15:
+ case PIXFMT_RGB15PC:
+ col = (((r*31)/255) << 10) | (((g*31)/255) << 5) | ((b*31)/255);
+ break;
+
+ case PIXFMT_BGR15:
+ case PIXFMT_BGR15PC:
+ col = (((b*31)/255) << 10) | (((g*31)/255) << 5) | ((r*31)/255);
+ break;
+
+ case PIXFMT_RGB16:
+ case PIXFMT_RGB16PC:
+ col = (((r*31)/255) << 11) | (((g*63)/255) << 5) | ((b*31)/255);
+ break;
+
+ case PIXFMT_BGR16:
+ case PIXFMT_BGR16PC:
+ col = (((b*31)/255) << 11) | (((g*63)/255) << 5) | ((r*31)/255);
+ break;
+
+ case PIXFMT_RGB24:
+ case PIXFMT_ARGB32:
+ col = (r << 16) | (g << 8) | b;
+ break;
+
+ case PIXFMT_BGR24:
+ col = (b << 16) | (g << 8) | r;
+ break;
+
+ case PIXFMT_BGRA32:
+ col = (b << 24) | (g << 16) | (r << 8);
+ break;
+
+ case PIXFMT_RGBA32:
+ col = (r << 24) | (g << 16) | (b << 8);
+ break;
+
+ default:
+ error( "Unsupported pixel format: %d. Please contact author at tomjoad@muenster.de.", pixfmt );
+ exit( 1 );
+ }
+
+ if( pixfmt == PIXFMT_RGB15PC || pixfmt == PIXFMT_BGR15PC ||
+ pixfmt == PIXFMT_RGB16PC || pixfmt == PIXFMT_BGR16PC
+ )
+ col = ((col >> 8) & 0xff) | ((col << 8) & 0xff00);
+
+
+ return col;
+}
+
+#define CVT8TO32( byte ) ((byte<<24) | (byte<<16) | (byte<<8) | byte)
+
+void updatePalette( Scumm *s )
+{
+ int first = s->_palDirtyMin;
+ int num = s->_palDirtyMax - first + 1;
+ int i;
+ byte *data = s->_currentPalette;
+
+ data += first*3;
+ for( i = first; i < first+num; i++, data+=3 )
+ {
+ if( ScummDepth == 8 )
+ SetRGB32( &ScummScreen->ViewPort, i, CVT8TO32( data[ 0 ] ), CVT8TO32( data[ 1 ] ), CVT8TO32( data[ 2 ] ) );
+ ScummColors16[ i ] = Scumm16ColFmt16 ? (((data[ 0 ]*31)/255) << 11) | (((data[ 1 ]*63)/255) << 5) | ((data[ 2 ]*31)/255) : (((data[ 0 ]*31)/255) << 10) | (((data[ 1 ]*31)/255) << 5) | ((data[ 2 ]*31)/255);
+ ScummColors[ i ] = (data[ 0 ] << 16) | (data[ 1 ] << 8) | data[ 2 ];
+ }
+
+ s->_palDirtyMax = -1;
+ s->_palDirtyMin = 0x3E8;
+}
+
+typedef enum { CSDSPTYPE_WINDOWED, CSDSPTYPE_FULLSCREEN, CSDSPTYPE_TOGGLE } CS_DSPTYPE;
+
+void createScreen( CS_DSPTYPE dspType )
+{
+ ULONG mode = INVALID_ID;
+ int depths[] = { 8, 15, 16, 24, 32, 0 };
+ int i;
+ struct Screen *wb = NULL;
+ bool fullScreen;
+
+ fullScreen = (dspType == CSDSPTYPE_FULLSCREEN) || (dspType == CSDSPTYPE_TOGGLE && ScummScreen == NULL);
+
+ if( ScummRenderTo && !ScummScreen )
+ FreeBitMap( ScummRenderTo );
+ ScummRenderTo = NULL;
+
+ if( ScummWindow )
+ {
+ if( ScummScreen == NULL )
+ {
+ ScummWinX = ScummWindow->LeftEdge;
+ ScummWinY = ScummWindow->TopEdge;
+ }
+ CloseWindow( ScummWindow );
+ ScummWindow = NULL;
+ }
+
+ if( ScummScreen )
+ {
+ if( ScummScreenBuffer[ 0 ] )
+ FreeScreenBuffer( ScummScreen, ScummScreenBuffer[ 0 ] );
+ if( ScummScreenBuffer[ 1 ] )
+ FreeScreenBuffer( ScummScreen, ScummScreenBuffer[ 1 ] );
+ CloseScreen( ScummScreen );
+ ScummScreen = NULL;
+ }
+
+ ScummScrWidth = 320 << ScummScale;
+ ScummScrHeight = 200 << ScummScale;
+
+ if( fullScreen )
+ {
+ UBYTE depthstr[ 10 ];
+ if( (ScummScale == 1) && (GetVar( "SCUMMVM_DEPTH", depthstr, 10, GVF_GLOBAL_ONLY ) > 0) )
+ {
+ ScummDepth = atoi( (char *)depthstr );
+ mode = BestCModeIDTags( CYBRBIDTG_NominalWidth, ScummScrWidth,
+ CYBRBIDTG_NominalHeight, ScummScrHeight,
+ CYBRBIDTG_Depth, ScummDepth,
+ TAG_DONE
+ );
+ }
+ else
+ {
+ for( i = ScummScale; mode == INVALID_ID && depths[ i ]; i++ )
+ mode = BestCModeIDTags( CYBRBIDTG_NominalWidth, ScummScrWidth,
+ CYBRBIDTG_NominalHeight, ScummScrHeight,
+ CYBRBIDTG_Depth, depths[ i ],
+ TAG_DONE
+ );
+ ScummDepth = depths[ i-1 ];
+ }
+
+ if( mode == INVALID_ID )
+ {
+ error( "Could not find suitable screenmode" );
+ exit(1);
+ }
+
+ ScummScreen = OpenScreenTags( NULL, SA_AutoScroll, TRUE,
+ SA_Depth, ScummDepth,
+ SA_Width, ScummScrWidth,
+ SA_Height, ScummScrHeight,
+ SA_DisplayID, mode,
+ SA_ShowTitle, FALSE,
+ SA_Type, CUSTOMSCREEN,
+ SA_Title, "ScummVM MorphOS",
+ TAG_DONE
+ );
+
+ if( ScummScreen == NULL )
+ {
+ error( "Failed to open screen" );
+ exit( 1 );
+ }
+
+ ScummScreenBuffer[ 0 ] = AllocScreenBuffer( ScummScreen, NULL, SB_SCREEN_BITMAP );
+ ScummScreenBuffer[ 1 ] = AllocScreenBuffer( ScummScreen, NULL, 0 );
+ ScummRenderTo = ScummScreenBuffer[ 1 ]->sb_BitMap;
+ ScummPaintBuffer = 1;
+
+ if( ScummScreenBuffer[ 0 ] == NULL || ScummScreenBuffer[ 1 ] == NULL )
+ {
+ error( "Failed to allocate screen buffer" );
+ exit( 1 );
+ }
+
+ if( ScummDepth == 8 )
+ {
+ for( int color = 0; color < 256; color++ )
+ {
+ ULONG r, g, b;
+
+ r = (ScummColors[ color ] >> 16) & 0xff;
+ g = (ScummColors[ color ] >> 8) & 0xff;
+ b = (ScummColors[ color ] >> 0) & 0xff;
+ SetRGB32( &ScummScreen->ViewPort, color, CVT8TO32( r ), CVT8TO32( g ), CVT8TO32( b ) );
+ }
+ }
+ }
+ else
+ {
+ wb = LockPubScreen( NULL );
+ if( wb == NULL )
+ {
+ error( "Could not lock default public screen" );
+ exit( 1 );
+ }
+
+ ScreenToFront( wb );
+ }
+
+ ScummWindow = OpenWindowTags( NULL, WA_Left, (wb && ScummWinX >= 0) ? ScummWinX : 0,
+ WA_Top, wb ? ((ScummWinY >= 0) ? ScummWinY : wb->BarHeight+1) : 0,
+ WA_InnerWidth, ScummScrWidth,
+ WA_InnerHeight, ScummScrHeight,
+ WA_Activate, TRUE,
+ WA_Title, wb ? ScummWndTitle : NULL,
+ WA_ScreenTitle, wb ? ScummWndTitle : NULL,
+ WA_Borderless, fullScreen,
+ WA_CloseGadget, !fullScreen,
+ WA_DepthGadget, !fullScreen,
+ WA_DragBar, !fullScreen,
+ WA_ReportMouse, TRUE,
+ WA_RMBTrap, TRUE,
+ WA_IDCMP, IDCMP_RAWKEY |
+ IDCMP_MOUSEMOVE |
+ IDCMP_CLOSEWINDOW |
+ IDCMP_MOUSEBUTTONS,
+ WA_CustomScreen, fullScreen ? (ULONG)ScummScreen : (ULONG)wb,
+ TAG_DONE
+ );
+
+ if( wb )
+ UnlockPubScreen( NULL, wb );
+
+ if( ScummWindow == NULL )
+ {
+ error( "Failed to open window" );
+ exit(1);
+ }
+
+ SetPointer( ScummWindow, ScummNoCursor, 1, 1, 0, 0 );
+ ScummOrigMouse = false;
+
+ if( ScummScreen == NULL )
+ {
+ ScummDepth = GetCyberMapAttr( ScummWindow->RPort->BitMap, CYBRMATTR_DEPTH );
+ if( ScummDepth == 8 )
+ {
+ error( "Workbench screen must be running in 15 bit or higher" );
+ exit( 1 );
+ }
+
+ ScummRenderTo = AllocBitMap( ScummScrWidth, ScummScrHeight, ScummDepth, BMF_MINPLANES, ScummWindow->RPort->BitMap );
+ if( ScummRenderTo == NULL )
+ {
+ error( "Failed to allocate bitmap" );
+ exit( 1 );
+ }
+ }
+
+ if( ScummScale )
+ {
+ /* Initialize scaling stuff */
+ int minr, ming, minb;
+
+ if( ScummDepth > 16 )
+ {
+ minr = 1 << 16;
+ ming = 1 << 8;
+ minb = 1;
+ }
+ else
+ {
+ minr = 1 << ((ScummDepth == 15) ? 10 : 11);
+ ming = 1 << 5;
+ minb = 1;
+
+ if( (ScummDepth == 15 && Scumm16ColFmt16) || (ScummDepth == 16 && !Scumm16ColFmt16) )
+ {
+ for( int col = 0; col < 256; col++ )
+ {
+ int r = (ScummColors[ col ] >> 16) & 0xff;
+ int g = (ScummColors[ col ] >> 8) & 0xff;
+ int b = ScummColors[ col ] & 0xff;
+ ScummColors16[ col ] = (Scumm16ColFmt16 == false) ? (((r*31)/255) << 11) | (((g*63)/255) << 5) | ((b*31)/255) : (((r*31)/255) << 10) | (((g*31)/255) << 5) | ((b*31)/255);
+ }
+ }
+
+ Scumm16ColFmt16 = (ScummDepth == 16);
+ }
+
+ int pixfmt = GetCyberMapAttr( ScummRenderTo, CYBRMATTR_PIXFMT );
+
+ debug( 1, "Pixelformat = %d", pixfmt );
+
+ colorMask = (makeColForPixFmt( pixfmt, 255, 0, 0 ) - minr) | (makeColForPixFmt( pixfmt, 0, 255, 0 ) - ming) | (makeColForPixFmt( pixfmt, 0, 0, 255 ) - minb);
+ lowPixelMask = minr | ming | minb;
+ qcolorMask = (makeColForPixFmt( pixfmt, 255, 0, 0 ) - 3*minr) | (makeColForPixFmt( pixfmt, 0, 255, 0) - 3*ming) | (makeColForPixFmt( pixfmt, 0, 0, 255 ) - 3*minb);
+ qlowpixelMask = (minr * 3) | (ming * 3) | (minb * 3);
+ redblueMask = makeColForPixFmt( pixfmt, 255, 0, 255 );
+ greenMask = makeColForPixFmt( pixfmt, 0, 255, 0 );
+
+ PixelsPerMask = (ScummDepth <= 16) ? 2 : 1;
+
+ if( PixelsPerMask == 2 )
+ {
+ colorMask |= (colorMask << 16);
+ qcolorMask |= (qcolorMask << 16);
+ lowPixelMask |= (lowPixelMask << 16);
+ qlowpixelMask |= (qlowpixelMask << 16);
+ }
+ }
+}
+
+int old_mouse_x, old_mouse_y;
+int old_mouse_h, old_mouse_w;
+bool has_mouse,hide_mouse;
+
+#define BAK_WIDTH 40
+#define BAK_HEIGHT 40
+byte old_backup[ BAK_WIDTH*BAK_HEIGHT*2 ];
+
+void SwitchScalerTo( ScalerFunc newScaler )
+{
+ if( newScaler == NULL && ScummScale )
+ {
+ ScummScale = false;
+ ScummScaler = NULL;
+ createScreen( ScummScreen ? CSDSPTYPE_FULLSCREEN : CSDSPTYPE_WINDOWED );
+ }
+ else
+ {
+ if( !ScummScale )
+ {
+ ScummScale = true;
+ createScreen( ScummScreen ? CSDSPTYPE_FULLSCREEN : CSDSPTYPE_WINDOWED );
+ }
+
+ if( ScummScaler != newScaler )
+ ScummScaler = newScaler;
+ }
+}
+
+void waitForTimer( Scumm *s, int msec_delay )
+{
+ struct IntuiMessage *ScummMsg;
+ ULONG signals;
+ bool AllDone = false;
+
+ if (s->_fastMode&2)
+ msec_delay = 0;
+ else if (s->_fastMode&1)
+ msec_delay = 10;
+
+ TimerIORequest->tr_node.io_Command = TR_ADDREQUEST;
+ TimerIORequest->tr_time.tv_secs = 0;
+ TimerIORequest->tr_time.tv_micro = (msec_delay > 0 ? msec_delay : 1)*1000;
+ SendIO( (struct IORequest *)TimerIORequest );
+ TimerStarted = true;
+
+ do
+ {
+ while( ScummMsg = (struct IntuiMessage *)GetMsg( ScummWindow->UserPort ) )
+ {
+ switch( ScummMsg->Class )
+ {
+ case IDCMP_RAWKEY:
+ {
+ struct InputEvent FakedIEvent;
+ char charbuf;
+
+ memset( &FakedIEvent, 0, sizeof( struct InputEvent ) );
+ FakedIEvent.ie_Class = IECLASS_RAWKEY;
+ FakedIEvent.ie_Code = ScummMsg->Code;
+
+ if( ScummMsg->Code >= 0x50 && ScummMsg->Code <= 0x59 )
+ {
+ // Function key
+ s->_keyPressed = (ScummMsg->Code-0x50)+315;
+ }
+ else if( MapRawKey( &FakedIEvent, &charbuf, 1, NULL ) == 1 )
+ {
+ if( charbuf >= '0' && charbuf <= '9' && !(ScummMsg->Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) )
+ {
+ s->_saveLoadSlot = charbuf - '0';
+ if( ScummMsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) )
+ {
+ sprintf(s->_saveLoadName, "Quicksave %d", s->_saveLoadSlot);
+ s->_saveLoadFlag = 1;
+ }
+ else if( ScummMsg->Qualifier & IEQUALIFIER_CONTROL )
+ s->_saveLoadFlag = 2;
+ s->_keyPressed = charbuf;
+ s->_saveLoadCompatible = false;
+ }
+ else if( ScummMsg->Qualifier & IEQUALIFIER_CONTROL )
+ {
+ switch( charbuf )
+ {
+ case 'z':
+ ReplyMsg( (struct Message *)ScummMsg );
+ exit(1);
+
+ case 'd':
+ debugger.attach(s);
+ break;
+
+ case 's':
+ s->resourceStats();
+ break;
+ }
+ }
+ else if( ScummMsg->Qualifier & (IEQUALIFIER_RALT | IEQUALIFIER_LALT) )
+ {
+ if( charbuf >= '0' && charbuf <= '9' && ScummScalers[ charbuf-'0' ].gs_Name )
+ {
+ ReplyMsg( (struct Message *)ScummMsg );
+ ScummMsg = NULL;
+ SwitchScalerTo( ScummScalers[ charbuf-'0' ].gs_Function );
+ }
+ else if( charbuf == 0x0d )
+ {
+ ReplyMsg( (struct Message *)ScummMsg );
+ ScummMsg = NULL;
+ createScreen( CSDSPTYPE_TOGGLE );
+ }
+ }
+ else
+ s->_keyPressed = charbuf;
+ }
+ break;
+ }
+
+ case IDCMP_MOUSEMOVE:
+ {
+ int newx,newy;
+
+ newx = (ScummMsg->MouseX-ScummWindow->BorderLeft) >> ScummScale;
+ newy = (ScummMsg->MouseY-ScummWindow->BorderTop) >> ScummScale;
+
+ if (newx != s->mouse.x || newy != s->mouse.y)
+ {
+ if( newx < 0 || newx > 320 ||
+ newy < 0 || newy > 200
+ )
+ {
+ if( !ScummOrigMouse )
+ {
+ ScummOrigMouse = true;
+ ClearPointer( ScummWindow );
+ }
+ }
+ else if( ScummOrigMouse )
+ {
+ ScummOrigMouse = false;
+ SetPointer( ScummWindow, ScummNoCursor, 1, 1, 0, 0 );
+ }
+ s->mouse.x = newx;
+ s->mouse.y = newy;
+ s->drawMouse();
+ }
+ break;
+ }
+
+ case IDCMP_MOUSEBUTTONS:
+ switch( ScummMsg->Code )
+ {
+ case SELECTDOWN:
+ s->_leftBtnPressed |= msClicked|msDown;
+ break;
+
+ case SELECTUP:
+ s->_leftBtnPressed &= ~msDown;
+ break;
+
+ case MENUDOWN:
+ s->_rightBtnPressed |= msClicked|msDown;
+ break;
+
+ case MENUUP:
+ s->_rightBtnPressed &= ~msDown;
+ break;
+ }
+ break;
+
+ case IDCMP_CLOSEWINDOW:
+ ReplyMsg( (struct Message *)ScummMsg );
+ exit(1);
+ break;
+ }
+
+ if( ScummMsg )
+ ReplyMsg( (struct Message *)ScummMsg );
+
+ cd_music_loop();
+
+ if( GetMsg( TimerMsgPort ) )
+ {
+ TimerStarted = false;
+ AllDone = true;
+ break;
+ }
+ }
+
+ if( !AllDone )
+ {
+ signals = Wait( (1 << (ScummWindow->UserPort->mp_SigBit)) | (1 << (TimerMsgPort->mp_SigBit) ) );
+
+ if( signals & (1 << (TimerMsgPort->mp_SigBit)) )
+ {
+ AllDone = true;
+ TimerStarted = false;
+ GetMsg( TimerMsgPort );
+ }
+ }
+ } while ( !AllDone );
+}
+
+#define MAX(a,b) (((a)<(b)) ? (b) : (a))
+#define MIN(a,b) (((a)>(b)) ? (b) : (a))
+
+void setShakePos( Scumm *s, int shake_pos )
+{
+ int old_shake_pos = current_shake_pos;
+ int dirty_height, dirty_blackheight;
+ int dirty_top, dirty_blacktop;
+
+ if( shake_pos != old_shake_pos )
+ {
+ current_shake_pos = shake_pos;
+
+ /* Old shake pos was current_shake_pos, new is shake_pos.
+ * Move the screen up or down to account for the change.
+ */
+ MovePixelArray( 0, old_shake_pos << ScummScale, ScummWindow->RPort, 0, shake_pos << ScummScale, ScummScrWidth, ScummScrHeight );
+
+ /* Also adjust the mouse pointer backup Y coordinate.
+ * There is a minor mouse glitch when the mouse is moved
+ * at the blackness of the shake area, but it's hardly noticable
+ */
+ old_mouse_y += shake_pos - old_shake_pos;
+
+ /* Refresh either the upper part of the screen,
+ * or the lower part
+ */
+ if( shake_pos > old_shake_pos )
+ {
+ dirty_height = MIN(shake_pos, 0) - MIN(old_shake_pos,0);
+ dirty_top = -MIN(shake_pos,0);
+ dirty_blackheight = MAX(shake_pos,0) - MAX(old_shake_pos,0);
+ dirty_blacktop = MAX(old_shake_pos,0);
+ }
+ else
+ {
+ dirty_height = MAX(old_shake_pos,0) - MAX(shake_pos, 0);
+ dirty_top = 200 - MAX(old_shake_pos,0);
+ dirty_blackheight = MIN(old_shake_pos,0) - MIN(shake_pos,0);
+ dirty_blacktop = 200 + MIN(shake_pos,0);
+ }
+
+ /* Fill the dirty area with blackness or the scumm image */
+ {
+ FillPixelArray( ScummWindow->RPort, 0, dirty_blacktop << ScummScale, ScummScrWidth, dirty_blackheight << ScummScale, 0 );
+ s->redrawLines(dirty_top, dirty_top + dirty_height);
+ }
+ }
+}
+
+#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D))
+
+#define INTERPOLATE(A, B) (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask))
+
+#define Q_INTERPOLATE(A, B, C, D) ((A & qcolorMask) >> 2) + ((B & qcolorMask) >> 2) + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2) + ((((A & qlowpixelMask) + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask)) >> 2) & qlowpixelMask)
+
+void Super2xSaI( uint32 src_x, uint32 src_y, uint32 width, uint32 height )
+{
+ unsigned int x, y;
+ unsigned long color[16];
+ byte *src;
+ byte *dest;
+ uint32 dest_bpp;
+ uint32 dest_pitch;
+ APTR handle;
+
+ if( (handle = LockBitMapTags( ScummRenderTo, LBMI_BYTESPERPIX, &dest_bpp, LBMI_BYTESPERROW, &dest_pitch, LBMI_BASEADDRESS, &dest, TAG_DONE )) == 0 )
+ return;
+
+ src = ((byte *)ScummBuffer)+src_y*320+src_x;
+
+ /* Point to the first 3 lines. */
+ src_line[0] = src;
+ src_line[1] = src;
+ src_line[2] = src + 320;
+ src_line[3] = src + 320 * 2;
+
+ dst_line[0] = dest+src_y*2*dest_pitch+src_x*2*dest_bpp;
+ dst_line[1] = dst_line[0]+dest_pitch;
+
+ x = 0, y = 0;
+
+ if( PixelsPerMask == 2 )
+ {
+ byte *sbp;
+ sbp = src_line[0];
+ color[0] = ScummColors16[ *sbp ]; color[1] = color[0]; color[2] = color[0]; color[3] = color[0];
+ color[4] = color[0]; color[5] = color[0]; color[6] = ScummColors16[ *(sbp + 1) ]; color[7] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[2];
+ color[8] = ScummColors16[ *sbp ]; color[9] = color[8]; color[10] = ScummColors16[ *(sbp + 1) ]; color[11] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[3];
+ color[12] = ScummColors16[ *sbp ]; color[13] = color[12]; color[14] = ScummColors16[ *(sbp + 1) ]; color[15] = ScummColors16[ *(sbp + 2) ];
+ }
+ else
+ {
+ byte *lbp;
+ lbp = src_line[0];
+ color[0] = ScummColors[ *lbp ]; color[1] = color[0]; color[2] = color[0]; color[3] = color[0];
+ color[4] = color[0]; color[5] = color[0]; color[6] = ScummColors[ *(lbp + 1) ]; color[7] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[2];
+ color[8] = ScummColors[ *lbp ]; color[9] = color[8]; color[10] = ScummColors[ *(lbp + 1) ]; color[11] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[3];
+ color[12] = ScummColors[ *lbp ]; color[13] = color[12]; color[14] = ScummColors[ *(lbp + 1) ]; color[15] = ScummColors[ *(lbp + 2) ];
+ }
+
+ for (y = 0; y < height; y++)
+ {
+ /* Todo: x = width - 2, x = width - 1 */
+ for( x = 0; x < width; x++ )
+ {
+ unsigned long product1a, product1b, product2a, product2b;
+
+//--------------------------------------- B0 B1 B2 B3 0 1 2 3
+// 4 5* 6 S2 -> 4 5* 6 7
+// 1 2 3 S1 8 9 10 11
+// A0 A1 A2 A3 12 13 14 15
+//--------------------------------------
+ if( color[9] == color[6] && color[5] != color[10] )
+ {
+ product2b = color[9];
+ product1b = product2b;
+ }
+ else if( color[5] == color[10] && color[9] != color[6] )
+ {
+ product2b = color[5];
+ product1b = product2b;
+ }
+ else if( color[5] == color[10] && color[9] == color[6] )
+ {
+ int r = 0;
+
+ r += GET_RESULT(color[6], color[5], color[8], color[13]);
+ r += GET_RESULT(color[6], color[5], color[4], color[1]);
+ r += GET_RESULT(color[6], color[5], color[14], color[11]);
+ r += GET_RESULT(color[6], color[5], color[2], color[7]);
+
+ if (r > 0)
+ product1b = color[6];
+ else if (r < 0)
+ product1b = color[5];
+ else
+ product1b = INTERPOLATE(color[5], color[6]);
+
+ product2b = product1b;
+
+ }
+ else
+ {
+ if( color[6] == color[10] && color[10] == color[13] && color[9] != color[14] && color[10] != color[12] )
+ product2b = Q_INTERPOLATE(color[10], color[10], color[10], color[9]);
+ else if( color[5] == color[9] && color[9] == color[14] && color[13] != color[10] && color[9] != color[15] )
+ product2b = Q_INTERPOLATE(color[9], color[9], color[9], color[10]);
+ else
+ product2b = INTERPOLATE(color[9], color[10]);
+
+ if (color[6] == color[10] && color[6] == color[1] && color[5] != color[2] && color[6] != color[0])
+ product1b = Q_INTERPOLATE(color[6], color[6], color[6], color[5]);
+ else if (color[5] == color[9] && color[5] == color[2] && color[1] != color[6] && color[5] != color[3])
+ product1b = Q_INTERPOLATE(color[6], color[5], color[5], color[5]);
+ else
+ product1b = INTERPOLATE(color[5], color[6]);
+ }
+
+ if (color[5] == color[10] && color[9] != color[6] && color[4] == color[5] && color[5] != color[14])
+ product2a = INTERPOLATE(color[9], color[5]);
+ else if (color[5] == color[8] && color[6] == color[5] && color[4] != color[9] && color[5] != color[12])
+ product2a = INTERPOLATE(color[9], color[5]);
+ else
+ product2a = color[9];
+
+ if (color[9] == color[6] && color[5] != color[10] && color[8] == color[9] && color[9] != color[2])
+ product1a = INTERPOLATE(color[9], color[5]);
+ else if (color[4] == color[9] && color[10] == color[9] && color[8] != color[5] && color[9] != color[0])
+ product1a = INTERPOLATE(color[9], color[5]);
+ else
+ product1a = color[5];
+
+ if (PixelsPerMask == 2)
+ {
+ *((unsigned long *) (&dst_line[0][x * 4])) = (product1a << 16) | product1b;
+ *((unsigned long *) (&dst_line[1][x * 4])) = (product2a << 16) | product2b;
+ }
+ else
+ {
+ *((unsigned long *) (&dst_line[0][x * 8])) = product1a;
+ *((unsigned long *) (&dst_line[0][x * 8 + 4])) = product1b;
+ *((unsigned long *) (&dst_line[1][x * 8])) = product2a;
+ *((unsigned long *) (&dst_line[1][x * 8 + 4])) = product2b;
+ }
+
+ /* Move color matrix forward */
+ color[0] = color[1]; color[4] = color[5]; color[8] = color[9]; color[12] = color[13];
+ color[1] = color[2]; color[5] = color[6]; color[9] = color[10]; color[13] = color[14];
+ color[2] = color[3]; color[6] = color[7]; color[10] = color[11]; color[14] = color[15];
+
+ if (x < width - 3)
+ {
+ x += 3;
+ if (PixelsPerMask == 2)
+ {
+ color[3] = ScummColors16[ *(src_line[0] + x) ];
+ color[7] = ScummColors16[ *(src_line[1] + x) ];
+ color[11] = ScummColors16[ *(src_line[2] + x) ];
+ color[15] = ScummColors16[ *(src_line[3] + x) ];
+ }
+ else
+ {
+ color[3] = ScummColors[ *(src_line[0] + x) ];
+ color[7] = ScummColors[ *(src_line[1] + x) ];
+ color[11] = ScummColors[ *(src_line[2] + x) ];
+ color[15] = ScummColors[ *(src_line[3] + x) ];
+ }
+ x -= 3;
+ }
+ }
+
+ /* We're done with one line, so we shift the source lines up */
+ src_line[0] = src_line[1];
+ src_line[1] = src_line[2];
+ src_line[2] = src_line[3];
+
+ /* Read next line */
+ if (y + 3 >= height)
+ src_line[3] = src_line[2];
+ else
+ src_line[3] = src_line[2] + 320;
+
+ /* Then shift the color matrix up */
+ if (PixelsPerMask == 2)
+ {
+ byte *sbp;
+ sbp = src_line[0];
+ color[0] = ScummColors16[ *sbp ]; color[1] = color[0]; color[2] = ScummColors16[ *(sbp + 1) ]; color[3] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[1];
+ color[4] = ScummColors16[ *sbp ]; color[5] = color[4]; color[6] = ScummColors16[ *(sbp + 1) ]; color[7] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[2];
+ color[8] = ScummColors16[ *sbp ]; color[9] = color[8]; color[10] = ScummColors16[ *(sbp + 1) ]; color[11] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[3];
+ color[12] = ScummColors16[ *sbp ]; color[13] = color[12]; color[14] = ScummColors16[ *(sbp + 1) ]; color[15] = ScummColors16[ *(sbp + 2) ];
+
+ if( src_x > 0 )
+ {
+ color[0] = ScummColors16[ src_line[0][-1] ];
+ color[4] = ScummColors16[ src_line[1][-1] ];
+ color[8] = ScummColors16[ src_line[2][-1] ];
+ color[12] = ScummColors16[ src_line[3][-1] ];
+ }
+ }
+ else
+ {
+ byte *lbp;
+ lbp = src_line[0];
+ color[0] = ScummColors[ *lbp ]; color[1] = color[0]; color[2] = ScummColors[ *(lbp + 1) ]; color[3] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[1];
+ color[4] = ScummColors[ *lbp ]; color[5] = color[4]; color[6] = ScummColors[ *(lbp + 1) ]; color[7] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[2];
+ color[8] = ScummColors[ *lbp ]; color[9] = color[8]; color[10] = ScummColors[ *(lbp + 1) ]; color[11] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[3];
+ color[12] = ScummColors[ *lbp ]; color[13] = color[12]; color[14] = ScummColors[ *(lbp + 1) ]; color[15] = ScummColors[ *(lbp + 2) ];
+ }
+
+ if (y < height - 1)
+ {
+ dst_line[0] = dst_line[1]+dest_pitch;
+ dst_line[1] = dst_line[0]+dest_pitch;
+ }
+ }
+
+ UnLockBitMap( handle );
+}
+
+void SuperEagle( uint32 src_x, uint32 src_y, uint32 width, uint32 height )
+{
+ unsigned int x, y;
+ unsigned long color[12];
+ byte *src;
+ byte *dest;
+ uint32 dest_bpp;
+ uint32 dest_pitch;
+ APTR handle;
+
+ if( (handle = LockBitMapTags( ScummRenderTo, LBMI_BYTESPERPIX, &dest_bpp, LBMI_BYTESPERROW, &dest_pitch, LBMI_BASEADDRESS, &dest, TAG_DONE )) == 0 )
+ return;
+
+ src = (byte *)ScummBuffer+src_y*320+src_x;
+
+ /* Point to the first 3 lines. */
+ src_line[0] = src;
+ src_line[1] = src;
+ src_line[2] = src + 320;
+ src_line[3] = src + 320 * 2;
+
+ dst_line[0] = dest+src_y*2*dest_pitch+src_x*2*dest_bpp;
+ dst_line[1] = dst_line[0]+dest_pitch;
+
+ x = 0, y = 0;
+
+ if (PixelsPerMask == 2)
+ {
+ byte *sbp;
+ sbp = src_line[0];
+ color[0] = ScummColors16[ *sbp ]; color[1] = color[0]; color[2] = color[0]; color[3] = color[0];
+ color[4] = ScummColors16[ *(sbp + 1) ]; color[5] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[2];
+ color[6] = ScummColors16[ *sbp ]; color[7] = color[6]; color[8] = ScummColors16[ *(sbp + 1) ]; color[9] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[3];
+ color[10] = ScummColors16[ *sbp ]; color[11] = ScummColors16[ *(sbp + 1) ];
+ }
+ else
+ {
+ byte *lbp;
+ lbp = src_line[0];
+ color[0] = ScummColors[ *lbp ]; color[1] = color[0]; color[2] = color[0]; color[3] = color[0];
+ color[4] = ScummColors[ *(lbp + 1) ]; color[5] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[2];
+ color[6] = ScummColors[ *lbp ]; color[7] = color[6]; color[8] = ScummColors[ *(lbp + 1) ]; color[9] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[3];
+ color[10] = ScummColors[ *lbp ]; color[11] = ScummColors[ *(lbp + 1) ];
+ }
+
+ for (y = 0; y < height; y++)
+ {
+ /* Todo: x = width - 2, x = width - 1 */
+
+ for (x = 0; x < width; x++)
+ {
+ unsigned long product1a, product1b, product2a, product2b;
+
+//--------------------------------------- B1 B2 0 1
+// 4 5 6 S2 -> 2 3 4 5
+// 1 2 3 S1 6 7 8 9
+// A1 A2 10 11
+
+ if (color[7] == color[4] && color[3] != color[8])
+ {
+ product1b = product2a = color[7];
+
+ if ((color[6] == color[7]) || (color[4] == color[1]))
+ product1a = INTERPOLATE(color[7], INTERPOLATE(color[7], color[3]));
+ else
+ product1a = INTERPOLATE(color[3], color[4]);
+
+ if ((color[4] == color[5]) || (color[7] == color[10]))
+ product2b = INTERPOLATE(color[7], INTERPOLATE(color[7], color[8]));
+ else
+ product2b = INTERPOLATE(color[7], color[8]);
+ }
+ else if (color[3] == color[8] && color[7] != color[4])
+ {
+ product2b = product1a = color[3];
+
+ if ((color[0] == color[3]) || (color[5] == color[9]))
+ product1b = INTERPOLATE(color[3], INTERPOLATE(color[3], color[4]));
+ else
+ product1b = INTERPOLATE(color[3], color[1]);
+
+ if ((color[8] == color[11]) || (color[2] == color[3]))
+ product2a = INTERPOLATE(color[3], INTERPOLATE(color[3], color[2]));
+ else
+ product2a = INTERPOLATE(color[7], color[8]);
+
+ }
+ else if (color[3] == color[8] && color[7] == color[4])
+ {
+ register int r = 0;
+
+ r += GET_RESULT(color[4], color[3], color[6], color[10]);
+ r += GET_RESULT(color[4], color[3], color[2], color[0]);
+ r += GET_RESULT(color[4], color[3], color[11], color[9]);
+ r += GET_RESULT(color[4], color[3], color[1], color[5]);
+
+ if (r > 0)
+ {
+ product1b = product2a = color[7];
+ product1a = product2b = INTERPOLATE(color[3], color[4]);
+ }
+ else if (r < 0)
+ {
+ product2b = product1a = color[3];
+ product1b = product2a = INTERPOLATE(color[3], color[4]);
+ }
+ else
+ {
+ product2b = product1a = color[3];
+ product1b = product2a = color[7];
+ }
+ }
+ else
+ {
+ product2b = product1a = INTERPOLATE(color[7], color[4]);
+ product2b = Q_INTERPOLATE(color[8], color[8], color[8], product2b);
+ product1a = Q_INTERPOLATE(color[3], color[3], color[3], product1a);
+
+ product2a = product1b = INTERPOLATE(color[3], color[8]);
+ product2a = Q_INTERPOLATE(color[7], color[7], color[7], product2a);
+ product1b = Q_INTERPOLATE(color[4], color[4], color[4], product1b);
+ }
+
+ if (PixelsPerMask == 2)
+ {
+ *((unsigned long *) (&dst_line[0][x * 4])) = (product1a << 16) | product1b;
+ *((unsigned long *) (&dst_line[1][x * 4])) = (product2a << 16) | product2b;
+ }
+ else
+ {
+ *((unsigned long *) (&dst_line[0][x * 8])) = product1a;
+ *((unsigned long *) (&dst_line[0][x * 8 + 4])) = product1b;
+ *((unsigned long *) (&dst_line[1][x * 8])) = product2a;
+ *((unsigned long *) (&dst_line[1][x * 8 + 4])) = product2b;
+ }
+
+ /* Move color matrix forward */
+ color[0] = color[1];
+ color[2] = color[3]; color[3] = color[4]; color[4] = color[5];
+ color[6] = color[7]; color[7] = color[8]; color[8] = color[9];
+ color[10] = color[11];
+
+ if (x < width - 2)
+ {
+ x += 2;
+ if (PixelsPerMask == 2)
+ {
+ color[1] = ScummColors16[ *(src_line[0] + x) ];
+ if( x < width-1 )
+ {
+ color[5] = ScummColors16[ *(src_line[1] + x + 1) ];
+ color[9] = ScummColors16[ *(src_line[2] + x + 1) ];
+ }
+ color[11] = ScummColors16[ *(src_line[3] + x) ];
+ }
+ else
+ {
+ color[1] = ScummColors[ *(src_line[0] + x) ];
+ if( x < width-1 )
+ {
+ color[5] = ScummColors[ *(src_line[1] + x + 1) ];
+ color[9] = ScummColors[ *(src_line[2] + x + 1) ];
+ }
+ color[11] = ScummColors[ *(src_line[3] + x) ];
+ }
+ x -= 2;
+ }
+ }
+
+ /* We're done with one line, so we shift the source lines up */
+ src_line[0] = src_line[1];
+ src_line[1] = src_line[2];
+ src_line[2] = src_line[3];
+
+ /* Read next line */
+ if (y + 3 >= height)
+ src_line[3] = src_line[2];
+ else
+ src_line[3] = src_line[2] + 320;
+
+ /* Then shift the color matrix up */
+ if (PixelsPerMask == 2)
+ {
+ byte *sbp;
+ sbp = src_line[0];
+ color[0] = ScummColors16[ *sbp ]; color[1] = ScummColors16[ *(sbp + 1) ];
+ sbp = src_line[1];
+ color[2] = ScummColors16[ *sbp ]; color[3] = color[2]; color[4] = ScummColors16[ *(sbp + 1) ]; color[5] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[2];
+ color[6] = ScummColors16[ *sbp ]; color[7] = color[6]; color[8] = ScummColors16[ *(sbp + 1) ]; color[9] = ScummColors16[ *(sbp + 2) ];
+ sbp = src_line[3];
+ color[10] = ScummColors16[ *sbp ]; color[11] = ScummColors16[ *(sbp + 1) ];
+ }
+ else
+ {
+ byte *lbp;
+ lbp = src_line[0];
+ color[0] = ScummColors[ *lbp ]; color[1] = ScummColors[ *(lbp + 1) ];
+ lbp = src_line[1];
+ color[2] = ScummColors[ *lbp ]; color[3] = color[2]; color[4] = ScummColors[ *(lbp + 1) ]; color[5] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[2];
+ color[6] = ScummColors[ *lbp ]; color[7] = color[6]; color[8] = ScummColors[ *(lbp + 1) ]; color[9] = ScummColors[ *(lbp + 2) ];
+ lbp = src_line[3];
+ color[10] = ScummColors[ *lbp ]; color[11] = ScummColors[ *(lbp + 1) ];
+ }
+
+
+ if (y < height - 1)
+ {
+ dst_line[0] = dst_line[1]+dest_pitch;
+ dst_line[1] = dst_line[0]+dest_pitch;
+ }
+ }
+
+ UnLockBitMap( handle );
+}
+
+void PointScaler( uint32 src_x, uint32 src_y, uint32 width, uint32 height )
+{
+ byte *src;
+ byte *dest;
+ uint32 dest_bpp;
+ uint32 dest_pixfmt;
+ uint32 dest_pitch;
+ uint32 color;
+ uint32 r, g, b;
+ uint32 x, y;
+ APTR handle;
+
+ if( (handle = LockBitMapTags( ScummRenderTo, LBMI_BYTESPERPIX, &dest_bpp,
+ LBMI_BYTESPERROW, &dest_pitch,
+ LBMI_BASEADDRESS, &dest,
+ LBMI_PIXFMT, &dest_pixfmt,
+ TAG_DONE )) == 0 )
+ return;
+
+ src = (byte *)ScummBuffer+src_y*320+src_x;
+
+ dst_line[0] = dest+src_y*2*dest_pitch+src_x*2*dest_bpp;
+ dst_line[1] = dst_line[0]+dest_pitch;
+
+ for( y = 0; y < height; y++ )
+ {
+ for( x = 0; x < width; x++ )
+ {
+ r = (ScummColors[ *(src+x) ] >> 16) & 0xff;
+ g = (ScummColors[ *(src+x) ] >> 8) & 0xff;
+ b = ScummColors[ *(src+x) ] & 0xff;
+
+ color = makeColForPixFmt( dest_pixfmt, r, g, b );
+ if( PixelsPerMask == 2 )
+ {
+ *((unsigned long *) (&dst_line[0][x * 4])) = (color << 16) | color;
+ *((unsigned long *) (&dst_line[1][x * 4])) = (color << 16) | color;
+ }
+ else
+ {
+ *((unsigned long *) (&dst_line[0][x * 8])) = color;
+ *((unsigned long *) (&dst_line[0][x * 8 + 4])) = color;
+ *((unsigned long *) (&dst_line[1][x * 8])) = color;
+ *((unsigned long *) (&dst_line[1][x * 8 + 4])) = color;
+ }
+ }
+
+ src += 320;
+
+ if (y < height - 1)
+ {
+ dst_line[0] = dst_line[1]+dest_pitch;
+ dst_line[1] = dst_line[0]+dest_pitch;
+ }
+ }
+
+ UnLockBitMap( handle );
+}
+
+/* Copy part of bitmap */
+void blitToScreen(Scumm *s, byte *src, int x, int y, int w, int h)
+{
+ byte *dst;
+
+ hide_mouse = true;
+ if( has_mouse )
+ s->drawMouse();
+
+ /* Account for the shaking and do Y clipping */
+ y += current_shake_pos;
+ if( y < 0 )
+ {
+ h += y;
+ src -= y*320;
+ y = 0;
+ }
+
+ if( h > 200 - y )
+ h = 200 - y;
+
+ if( h<=0 )
+ return;
+
+ dst = (byte *)ScummBuffer+y*320 + x;
+ do
+ {
+ memcpy( dst, src, w );
+ dst += 320;
+ src += 320;
+ } while( --h );
+}
+
+void updateScreen(Scumm *s)
+{
+ if( s->_fastMode & 2 )
+ return;
+
+ if( hide_mouse )
+ {
+ hide_mouse = false;
+ s->drawMouse();
+ }
+
+ if(s->_palDirtyMax != -1)
+ updatePalette(s);
+
+ if( !ScummScale )
+ {
+ struct RastPort rp;
+
+ InitRastPort( &rp );
+ rp.BitMap = ScummRenderTo;
+
+ if( ScummDepth == 8 )
+ WritePixelArray( ScummBuffer, 0, 0, 320, &rp, 0, 0, 320, 200, RECTFMT_LUT8 );
+ else
+ WriteLUTPixelArray( ScummBuffer, 0, 0, 320, &rp, ScummColors, 0, 0, 320, 200, CTABFMT_XRGB8 );
+ }
+ else
+ (*ScummScaler)( 0, 0, 320, 200 );
+
+ if( ScummScreen )
+ {
+ while( !ChangeScreenBuffer( ScummScreen, ScummScreenBuffer[ ScummPaintBuffer ] ) );
+ WaitTOF();
+ ScummPaintBuffer = !ScummPaintBuffer;
+ ScummRenderTo = ScummScreenBuffer[ ScummPaintBuffer ]->sb_BitMap;
+ }
+ else
+ {
+ BltBitMapRastPort( ScummRenderTo, 0, 0, ScummWindow->RPort, ScummWindow->BorderLeft, ScummWindow->BorderTop, ScummScrWidth, ScummScrHeight, ABNC | ABC );
+ WaitBlit();
+ }
+}
+
+void drawMouse( Scumm *s, int xdraw, int ydraw, int w, int h, byte *buf, bool visible )
+{
+ int x,y;
+ byte *dst,*bak;
+ byte color;
+
+ if( hide_mouse )
+ visible = false;
+
+ assert( w<=BAK_WIDTH && h<=BAK_HEIGHT );
+
+ if( has_mouse )
+ {
+ dst = (byte*)ScummBuffer + old_mouse_y*320 + old_mouse_x;
+ bak = old_backup;
+
+ for( y = 0; y < old_mouse_h; y++, bak+=BAK_WIDTH, dst+=320 )
+ {
+ if( (uint)(old_mouse_y + y) < 200 )
+ {
+ for( x=0; x < old_mouse_w; x++ )
+ {
+ if( (uint)(old_mouse_x + x) < 320 )
+ dst[ x ] = bak[ x ];
+ }
+ }
+ }
+ }
+
+ if( visible )
+ {
+ ydraw += current_shake_pos;
+
+ dst = (byte*)ScummBuffer + ydraw*320 + xdraw;
+ bak = old_backup;
+
+ for( y = 0; y < h; y++, dst += 320, bak += BAK_WIDTH, buf += w )
+ {
+ if( (uint)(ydraw+y) < 200 )
+ {
+ for( x=0; x<w; x++ )
+ {
+ if( (uint)(xdraw+x)<320 )
+ {
+ bak[x] = dst[x];
+ if( (color=buf[x])!=0xFF )
+ dst[ x ] = color;
+ }
+ }
+ }
+ }
+ }
+
+ if( has_mouse )
+ has_mouse = false;
+
+ if( visible )
+ {
+ has_mouse = true;
+ old_mouse_x = xdraw;
+ old_mouse_y = ydraw;
+ old_mouse_w = w;
+ old_mouse_h = h;
+ }
+}
+
+
+void launcherLoop()
+{
+#if 0
+ int last_time, new_time;
+ int delta = 0;
+ last_time = GetTicks();
+
+ gui.launcher();
+ do
+ {
+ updateScreen(&scumm);
+
+ new_time = GetTicks();
+ waitForTimer( &scumm, delta * 15 + last_time - new_time );
+ last_time = GetTicks();
+
+ if (gui._active)
+ {
+ gui.loop();
+ delta = 5;
+ } else
+ error("gui closed!");
+ } while(1);
+#endif
+};
+
+void setWindowName( Scumm *s )
+{
+ /* this is done in initGraphics() ... */
+}
+
+void initGraphics( Scumm *s, bool fullScreen, unsigned int scaleFactor )
+{
+ ScummNoCursor = (UWORD *)AllocVec( 16, MEMF_CHIP | MEMF_CLEAR );
+
+ /*
+ * Allocate image buffer
+ */
+ ScummBuffer = AllocVec( 320*200, MEMF_ANY | MEMF_CLEAR );
+
+ if( ScummBuffer == NULL )
+ {
+ puts( "Couldn't allocate image buffer" );
+ exit( 1 );
+ }
+
+ memset( ScummColors, 0, 256*sizeof( ULONG ) );
+
+ char *gameName;
+ sprintf( ScummWndTitle, "ScummVM MorphOS - %s", gameName = s->getGameName());
+ free( gameName );
+
+ createScreen( args[ USG_WBWINDOW ] ? CSDSPTYPE_WINDOWED : CSDSPTYPE_FULLSCREEN );
+
+ InitSemaphore( &ScummMusicThreadRunning );
+
+ // Prepare for CD audio if game is Loom CD version
+ if( (s->_features & GF_AUDIOTRACKS) && !args[ USG_NOMUSIC ] )
+ {
+ FindCDTags[ 0 ].ti_Data = (ULONG)((s->_gameId == GID_LOOM256) ? "LoomCD" : "Monkey1CD");
+ CDDABase = OpenLibrary( "cdda.library", 0 );
+ if( CDDABase )
+ {
+ CDrive = CDDA_FindNextDrive( NULL, FindCDTags );
+ if( CDrive )
+ {
+ if( !CDDA_ObtainDrive( CDrive, CDDA_SHARED_ACCESS, NULL ) )
+ {
+ CDrive = NULL;
+ warning( "Failed to obtain CD drive - music will not play" );
+ }
+ else if( s->_gameId == GID_LOOM256 )
+ {
+ // Offset correction *may* be required
+ struct CDS_TrackInfo ti;
+
+ if( CDDA_GetTrackInfo( CDrive, 1, 0, &ti ) )
+ CDDATrackOffset = ti.ti_TrackStart.tm_Format.tm_Frame-22650;
+ }
+ }
+ else
+ warning( "Could not find game CD inserted in CD-ROM drive - music will not play" );
+ }
+ else
+ warning( "Failed to open cdda.library - music will not play" );
+ args[ USG_NOMUSIC ] = TRUE; // this avoids AMidi being opened ...
+ }
+
+ // Create Music Thread
+ MyEmulFunc.Trap = TRAP_FUNC;
+ MyEmulFunc.Address = (ULONG)&morphos_music_thread;
+ MyEmulFunc.StackSize = 8192;
+ MyEmulFunc.Extension = 0;
+ MyEmulFunc.Arg1 = (ULONG)&scumm;
+ MyEmulFunc.Arg2 = (ULONG)ScummMidiUnit;
+ MyEmulFunc.Arg3 = (ULONG)args[ USG_NOMUSIC ];
+ ScummMusicThread = CreateNewProc( musicProcTags );
+ if( !ScummMusicThread )
+ {
+ puts( "Failed to create music thread" );
+ exit( 1 );
+ }
+}
+
+static bool FindScaler( const char *ScalerName )
+{
+ int scaler = 0;
+
+ while( ScummScalers[ scaler ].gs_Name )
+ {
+ if( !stricmp( ScalerName, ScummScalers[ scaler ].gs_Name ) )
+ {
+ ScummScaler = ScummScalers[ scaler ].gs_Function;
+ break;
+ }
+ scaler++;
+ }
+
+ if( ScummScalers[ scaler ].gs_Name == NULL )
+ {
+ puts( "Invalid scaler name. Please use one of the following:" );
+ for( scaler = 0; ScummScalers[ scaler ].gs_Name != NULL; scaler++ )
+ printf( " %s\n", ScummScalers[ scaler ].gs_Name );
+ return false;
+ }
+
+ ScummScaler = ScummScalers[ scaler ].gs_Function;
+ if( ScummScaler == NULL )
+ ScummScale = 0;
+ else
+ ScummScale = 1;
+
+ return true;
+}
+
+static void ReadToolTypes( STRPTR OfFile )
+{
+ struct DiskObject *dobj;
+ char *ToolValue;
+
+ dobj = GetDiskObject( OfFile );
+ if( dobj == NULL )
+ return;
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "STORY" ) )
+ {
+ if( ScummStory )
+ FreeVec( ScummStory );
+ ScummStory = (char *)AllocVec( strlen( ToolValue )+1, MEMF_PUBLIC );
+ strcpy( ScummStory, ToolValue );
+ }
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "DATAPATH" ) )
+ {
+ if( ScummPath )
+ FreeVec( ScummPath );
+ ScummPath = (char *)AllocVec( strlen( ToolValue )+4, MEMF_PUBLIC );
+ strcpy( ScummPath, "-p" );
+ strcat( ScummPath, ToolValue );
+ }
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "WBWINDOW" ) )
+ {
+ if( MatchToolValue( ToolValue, "YES" ) )
+ args[ USG_WBWINDOW ] = TRUE;
+ else if( MatchToolValue( ToolValue, "NO" ) )
+ args[ USG_WBWINDOW ] = FALSE;
+ }
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "SCALER" ) )
+ {
+ if( !FindScaler( ToolValue ) )
+ {
+ FreeDiskObject( dobj );
+ exit( 1 );
+ }
+ }
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "MUSIC" ) )
+ {
+ if( MatchToolValue( ToolValue, "YES" ) )
+ args[ USG_NOMUSIC ] = FALSE;
+ else if( MatchToolValue( ToolValue, "NO" ) )
+ args[ USG_NOMUSIC ] = TRUE;
+ }
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "MIDIUNIT" ) )
+ ScummMidiUnit = atoi( ToolValue );
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "VOLUME" ) )
+ {
+ int vol = atoi( ToolValue );
+ if( vol >= 0 && vol <= 100 )
+ {
+ ScummMidiVolume = vol;
+ args[ USG_VOLUME ] = (ULONG)&ScummMidiVolume;
+ }
+ }
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "TEMPO" ) )
+ {
+ ScummMidiTempo = atoi( ToolValue );
+ args[ USG_TEMPO ] = (ULONG)&ScummMidiTempo;
+ }
+
+ if( ToolValue = (char *)FindToolType( dobj->do_ToolTypes, "SUBTITLES" ) )
+ {
+ if( MatchToolValue( ToolValue, "YES" ) )
+ args[ USG_NOSUBTITLES ] = FALSE;
+ else if( MatchToolValue( ToolValue, "NO" ) )
+ args[ USG_NOSUBTITLES ] = TRUE;
+ }
+
+ FreeDiskObject( dobj );
+}
+
+#undef main
+
+int main( int argc, char *argv[] )
+{
+ int delta;
+ int last_time, new_time;
+
+ CyberGfxBase = OpenLibrary( "cybergraphics.library", 41 );
+ if( CyberGfxBase == NULL )
+ {
+ puts( "Failed to open cybergraphics.library" );
+ exit( 1 );
+ }
+
+ atexit( &closeResources );
+
+ TimerMsgPort = CreateMsgPort();
+ if( TimerMsgPort == NULL )
+ {
+ puts( "Failed to create message port" );
+ exit( 1 );
+ }
+
+ TimerIORequest = (struct timerequest *)CreateIORequest( TimerMsgPort, sizeof( struct timerequest ) );
+ if( TimerIORequest == NULL )
+ {
+ puts( "Failed to create IO request" );
+ exit( 1 );
+ }
+
+ if( OpenDevice( "timer.device", UNIT_MICROHZ, (struct IORequest *)TimerIORequest, 0 ) )
+ {
+ DeleteIORequest( (struct IORequest *)TimerIORequest );
+ TimerIORequest = NULL;
+ puts( "Failed to open timer device" );
+ exit( 1 );
+ }
+
+ TimerBase = TimerIORequest->tr_node.io_Device;
+
+ if( _WBenchMsg == NULL )
+ {
+ /* Parse the command line here */
+ ScummArgs = ReadArgs( usageTemplate, args, NULL );
+ if( ScummArgs == NULL )
+ {
+ puts( "Error in command line - type \"ScummVM ?\" for usage.\n" );
+ exit( 1 );
+ }
+
+ if( args[ USG_STORY ] )
+ {
+ ScummStory = (char *)AllocVec( strlen( (char *)args[ USG_STORY ] )+1, MEMF_PUBLIC );
+ strcpy( ScummStory, (char *)args[ USG_STORY ] );
+ }
+
+ if( args[ USG_DATAPATH ] )
+ {
+ ScummPath = (char *)AllocVec( strlen( (char *)args[ USG_DATAPATH ] )+4, MEMF_PUBLIC );
+ strcpy( ScummPath, "-p" );
+ strcat( ScummPath, (char *)args[ USG_DATAPATH ] );
+ }
+
+ if( args[ USG_SCALER ] )
+ {
+ if( !FindScaler( (char *)args[ USG_SCALER ] ) )
+ exit( 1 );
+ }
+
+ if( args[ USG_MIDIUNIT ] )
+ ScummMidiUnit = *((LONG *)args[ USG_MIDIUNIT ]);
+
+ if( args[ USG_TEMPO ] )
+ ScummMidiTempo = *((LONG *)args[ USG_TEMPO ]);
+
+ if( args[ USG_VOLUME ] )
+ ScummMidiVolume = *((LONG *)args[ USG_VOLUME ]);
+ }
+ else
+ {
+ /* We've been started from Workbench */
+ ReadToolTypes( (char *)_WBenchMsg->sm_ArgList[ 0 ].wa_Name );
+ if( _WBenchMsg->sm_NumArgs > 1 )
+ {
+ ReadToolTypes( (char *)_WBenchMsg->sm_ArgList[ 1 ].wa_Name );
+ OrigDirLock = CurrentDir( _WBenchMsg->sm_ArgList[ 1 ].wa_Lock );
+ }
+ }
+
+ if( ScummPath )
+ {
+ char c = ScummPath[ strlen( ScummPath )-1 ];
+ if( c != '/' && c != ':' )
+ strcat( ScummPath, "/" );
+ }
+
+ scumm._gui = &gui;
+ sound.initialize( &scumm, &snd_driv );
+ char *argvfake[] = { "ScummVM", (char *)ScummStory, "-e5", (char *)ScummPath };
+ scumm.scummMain( ScummPath ? 4 : 3, argvfake);
+
+ /* Fix up argument flags */
+ if( args[ USG_NOSUBTITLES ] )
+ scumm._noSubtitles = true;
+ if( args[ USG_VOLUME ] )
+ {
+ int vol = *(LONG *)args[ USG_VOLUME ];
+ if( vol >= 0 && vol <= 100 )
+ sound.set_music_volume( vol );
+ }
+ if( args[ USG_TEMPO ] )
+ scumm._gameTempo = *(LONG *)args[ USG_TEMPO ];
+
+ gui.init(&scumm);
+
+ last_time = GetTicks();
+ delta = 0;
+ do
+ {
+ updateScreen( &scumm );
+
+ new_time = GetTicks();
+ waitForTimer( &scumm, delta * 15 + last_time - new_time );
+ last_time = GetTicks();
+
+ if( gui._active )
+ {
+ gui.loop();
+ delta = 5;
+ }
+ else
+ delta = scumm.scummLoop( delta );
+ } while( 1 );
+
+ return 0;
+}
+
diff --git a/morphos/morphos_sound.cpp b/morphos/morphos_sound.cpp
new file mode 100644
index 0000000000..b99fb3efed
--- /dev/null
+++ b/morphos/morphos_sound.cpp
@@ -0,0 +1,288 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 Rüdiger Hanke
+ *
+ * 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.
+ *
+ * MorphOS sound support
+ */
+
+#include <devices/timer.h>
+
+#include "stdafx.h"
+#include "scumm.h"
+#include "sound.h"
+
+#include <dos/dos.h>
+#include <exec/memory.h>
+#include <devices/ahi.h>
+#include <devices/amidi.h>
+
+#define NO_PPCINLINE_STDARG
+#define NO_PPCINLINE_VARARGS
+#include <clib/alib_protos.h>
+#include <proto/exec.h>
+#include <proto/dos.h>
+#include <proto/ahi.h>
+
+extern int GetTicks();
+extern Scumm scumm;
+extern SoundEngine sound;
+extern SOUND_DRIVER_TYPE snd_driv;
+
+#define AHI_BUF_SIZE (8*1024)
+
+struct SignalSemaphore ScummMusicThreadRunning;
+
+static struct MsgPort *ahiPort = NULL;
+static struct AHIRequest *ahiReq[ 2 ] = { NULL, NULL };
+static UWORD ahiCurBuf = 0;
+static BOOL ahiReqSent[ 2 ] = { FALSE, FALSE };
+static BYTE ahiDevice = -1;
+ UBYTE ahiUnit = AHI_DEFAULT_UNIT;
+static char *ahiBuf[ 2 ] = { NULL, NULL };
+
+static struct MsgPort *ScummMidiPort = NULL;
+ struct IOMidiRequest *ScummMidiRequest = NULL;
+
+bool init_morphos_sound( ULONG MidiUnit, bool NoMusic )
+{
+ if( !NoMusic )
+ {
+ ScummMidiPort = CreateMsgPort();
+ if( ScummMidiPort )
+ {
+ ScummMidiRequest = (struct IOMidiRequest *)CreateIORequest( ScummMidiPort, sizeof( struct IOMidiRequest ) );
+ if( ScummMidiRequest )
+ {
+ ScummMidiRequest->amr_Version = 2;
+ if( OpenDevice( "amidi.device", MidiUnit, (struct IORequest *)ScummMidiRequest, AMIDIF_MIDISERVER ) )
+ {
+ DeleteIORequest( (struct IORequest *)ScummMidiRequest );
+ DeleteMsgPort( ScummMidiPort );
+ ScummMidiRequest = NULL;
+ ScummMidiPort = NULL;
+ }
+ }
+ else
+ {
+ DeleteMsgPort( ScummMidiPort );
+ ScummMidiPort = NULL;
+ }
+ }
+
+ if( !ScummMidiRequest )
+ warning( "Could not open AMidi - music will not play" );
+ }
+
+ if( !(ahiPort = CreateMsgPort()) )
+ return false;
+
+ if( !(ahiReq[ 0 ] = (struct AHIRequest *)CreateIORequest( ahiPort, sizeof( struct AHIRequest ) )) )
+ {
+ DeleteMsgPort( ahiPort );
+ ahiPort = NULL;
+ return false;
+ }
+
+ if( !(ahiReq[ 1 ] = (struct AHIRequest *)AllocVec( sizeof( struct AHIRequest ), MEMF_ANY | MEMF_PUBLIC )) )
+ {
+ DeleteIORequest( ahiReq[ 0 ] );
+ DeleteMsgPort( ahiPort );
+ ahiReq[ 0 ] = NULL;
+ ahiPort = NULL;
+ return false;
+ }
+
+ if( !(ahiBuf[ 0 ] = (char *)AllocVec( 2*AHI_BUF_SIZE, MEMF_ANY | MEMF_PUBLIC )) )
+ {
+ FreeVec( ahiReq[ 1 ] );
+ DeleteIORequest( ahiReq[ 0 ] );
+ DeleteMsgPort( ahiPort );
+ ahiReq[ 0 ] = NULL;
+ ahiReq[ 1 ] = NULL;
+ ahiPort = NULL;
+ return false;
+ }
+ ahiBuf[ 1 ] = &ahiBuf[ 0 ][ AHI_BUF_SIZE ];
+
+ ahiReq[ 0 ]->ahir_Version = 4;
+ if( ahiDevice = OpenDevice( AHINAME, 0, (struct IORequest *)ahiReq[ 0 ], 0 ) )
+ {
+ FreeVec( ahiBuf[ 0 ] );
+ FreeVec( ahiReq[ 1 ] );
+ DeleteIORequest( ahiReq[ 0 ] );
+ DeleteMsgPort( ahiPort );
+ ahiBuf[ 0 ] = NULL;
+ ahiReq[ 0 ] = NULL;
+ ahiReq[ 1 ] = NULL;
+ ahiPort = NULL;
+ return false;
+ }
+
+ CopyMem( ahiReq[ 0 ], ahiReq[ 1 ], sizeof( struct AHIRequest ) );
+
+ return true;
+}
+
+
+void exit_morphos_sound()
+{
+ if( ScummMidiRequest )
+ {
+ CloseDevice( (struct IORequest *)ScummMidiRequest );
+ DeleteIORequest( (struct IORequest *)ScummMidiRequest );
+ DeleteMsgPort( ScummMidiPort );
+ }
+
+ if( ahiReq[ 1 ] )
+ FreeVec( ahiReq[ 1 ] );
+
+ if( ahiReq[ 0 ] )
+ {
+ CloseDevice( (struct IORequest *)ahiReq[ 0 ] );
+ DeleteIORequest( ahiReq[ 0 ] );
+ }
+
+ if( ahiBuf[ 0 ] )
+ FreeVec( (APTR)ahiBuf[ 0 ] );
+
+ if( ahiPort )
+ DeleteMsgPort( ahiPort );
+}
+
+
+#ifdef __MORPHOS__
+int morphos_music_thread( Scumm *s, ULONG MidiUnit, bool NoMusic )
+#else
+int morphos_music_thread()
+#endif
+{
+ int old_time, cur_time;
+ bool initialized;
+ bool TimerAvailable = false;
+ struct MsgPort *TimerMsgPort;
+ struct timerequest *TimerIORequest;
+
+ ObtainSemaphore( &ScummMusicThreadRunning );
+
+ initialized = init_morphos_sound( MidiUnit, NoMusic );
+ if( !initialized )
+ warning( "Sound could not be initialized" );
+
+ TimerMsgPort = CreateMsgPort();
+ if( TimerMsgPort )
+ {
+ TimerIORequest = (struct timerequest *)CreateIORequest( TimerMsgPort, sizeof( struct timerequest ) );
+ if( TimerIORequest )
+ {
+ if( OpenDevice( "timer.device", UNIT_MICROHZ, (struct IORequest *)TimerIORequest, 0 ) == 0 )
+ TimerAvailable = true;
+ else
+ {
+ DeleteIORequest( (struct IORequest *)TimerIORequest );
+ DeleteMsgPort( TimerMsgPort );
+ }
+ }
+ else
+ DeleteMsgPort( TimerMsgPort );
+ }
+
+ if( !TimerAvailable )
+ {
+ warning( "ScummVM Music Thread: no timer available! Sound and music will be disabled" );
+ Wait( SIGBREAKF_CTRL_F );
+ }
+ else
+ {
+ old_time = GetTicks();
+
+ for(;;)
+ {
+ if( CheckSignal( SIGBREAKF_CTRL_F ) )
+ {
+ if( ahiReqSent[ ahiCurBuf ] )
+ {
+ AbortIO( (struct IORequest *)ahiReq[ ahiCurBuf ] );
+ WaitIO ( (struct IORequest *)ahiReq[ ahiCurBuf ] );
+ }
+ break;
+ }
+
+ if( !snd_driv.wave_based() )
+ {
+ cur_time = GetTicks();
+ while( old_time < cur_time )
+ {
+ old_time += 10;
+ sound.on_timer();
+ }
+/* TimerIORequest->tr_time.tv_micro = (old_time-cur_time)*1000;
+ if( TimerIORequest->tr_time.tv_micro == 0 )
+ TimerIORequest->tr_time.tv_micro = 100;*/
+ TimerIORequest->tr_time.tv_micro = 10000;
+ }
+ else
+ TimerIORequest->tr_time.tv_micro = 10000;
+
+ TimerIORequest->tr_node.io_Command = TR_ADDREQUEST;
+ TimerIORequest->tr_time.tv_secs = 0;
+ DoIO( (struct IORequest *)TimerIORequest );
+
+ if( !initialized )
+ continue;
+
+ if( !ahiReqSent[ ahiCurBuf ] || CheckIO( (struct IORequest *)ahiReq[ ahiCurBuf ] ) )
+ {
+ struct AHIRequest *req = ahiReq[ ahiCurBuf ];
+ UWORD ahiOtherBuf = !ahiCurBuf;
+
+ if( ahiReqSent[ ahiCurBuf ] )
+ WaitIO( (struct IORequest *)req );
+
+ if( CheckSignal( SIGBREAKF_CTRL_F ) )
+ break;
+
+ scumm.mixWaves( (int16 *)ahiBuf[ ahiCurBuf ], AHI_BUF_SIZE >> 1 );
+
+ req->ahir_Std.io_Message.mn_Node.ln_Pri = 0;
+ req->ahir_Std.io_Command = CMD_WRITE;
+ req->ahir_Std.io_Data = ahiBuf[ ahiCurBuf ];
+ req->ahir_Std.io_Length = AHI_BUF_SIZE;
+ req->ahir_Type = AHIST_M16S;
+ req->ahir_Frequency = SAMPLES_PER_SEC/2;
+ req->ahir_Position = 0x8000;
+ req->ahir_Volume = 0x10000;
+ req->ahir_Link = (ahiReqSent[ ahiOtherBuf ] && !CheckIO( (struct IORequest *)ahiReq[ ahiOtherBuf ] )) ? ahiReq[ ahiOtherBuf ] : NULL;
+ SendIO( (struct IORequest *)req );
+
+ ahiReqSent[ ahiCurBuf ] = TRUE;
+ ahiCurBuf = ahiOtherBuf;
+ }
+ }
+ }
+
+ if( TimerAvailable )
+ {
+ CloseDevice( (struct IORequest *)TimerIORequest );
+ DeleteIORequest( (struct IORequest *)TimerIORequest );
+ DeleteMsgPort( TimerMsgPort );
+ }
+
+ exit_morphos_sound();
+
+ ReleaseSemaphore( &ScummMusicThreadRunning );
+ return 0;
+}
+