From 27ea39a7be9f2756fd9ff3aebc6afb67a83117a2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 3 Jun 2002 21:13:27 +0000 Subject: [PATCH] checkin of mutle's current work - note that this won't build right now, it needs some work first svn-id: r4397 --- mac/Carbon.r | 8 +- mac/mac.cpp | 2374 ++++++++++++++++++++++++++++++----------------- mac/scummvm.mcp | Bin 158716 -> 158716 bytes 3 files changed, 1512 insertions(+), 870 deletions(-) diff --git a/mac/Carbon.r b/mac/Carbon.r index 5104573275b..a296c97b26e 100644 --- a/mac/Carbon.r +++ b/mac/Carbon.r @@ -70,8 +70,10 @@ resource 'MENU'(999) { "Zak McKracken and the Alien Mindbenders (256)", noIcon, noKey, noMark, plain, "Loom", noIcon, noKey, noMark, plain, "Monkey Island 1 (EGA)", noIcon, noKey, noMark, plain, + "Monkey Island 1 (256 color Floppy version)", noIcon, noKey, noMark, plain, "Loom (256 color CD version)", noIcon, noKey, noMark, plain, "Monkey Island 1", noIcon, noKey, noMark, plain, + "Monkey Island 1 (alt)", noIcon, noKey, noMark, plain, "Monkey Island 2: LeChuck's revenge", noIcon, noKey, noMark, plain, "Indiana Jones 4 and the Fate of Atlantis", noIcon, noKey, noMark, plain, "Indiana Jones 4 and the Fate of Atlantis (Demo)", noIcon, noKey, noMark, plain, @@ -81,7 +83,11 @@ resource 'MENU'(999) { "Sam & Max (Demo)", noIcon, noKey, noMark, plain, "Full Throttle", noIcon, noKey, noMark, plain, "The Dig", noIcon, noKey, noMark, plain, - "The Curse of Monkey Island", noIcon, noKey, noMark, plain + "The Curse of Monkey Island", noIcon, noKey, noMark, plain, + "-", noIcon, noKey, noMark, plain, + "Simon the Sorcerer 1 (DOS)", noIcon, noKey, noMark, plain, + "Simon the Sorcerer 1 (Windows)", noIcon, noKey, noMark, plain, + "Simon the Sorcerer 2 (Windows)", noIcon, noKey, noMark, plain } }; diff --git a/mac/mac.cpp b/mac/mac.cpp index 0f89434adeb..1339e3b031a 100644 --- a/mac/mac.cpp +++ b/mac/mac.cpp @@ -1,6 +1,6 @@ /* ScummVM - Scumm Interpreter * Copyright (C) 2001 Ludvig Strigeus - * Copyright (C) 2002 Mutwin Kraus (Mac Port) + * Copyright (C) 2001/2002 Mutwin Kraus (Mac Port) and 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 @@ -21,61 +21,203 @@ */ #include -#include - #include -#include -#include - #include "stdafx.h" #include "scumm.h" -#include "gui.h" -#include "cdmusic.h" +#include "mididrv.h" #include "gameDetector.h" +//#include "mp3_cd.h" +#include "gui.h" +//#include "gameDetector.h" -#define SRC_WIDTH 320 -#define SRC_HEIGHT 200 -#define SRC_PITCH (320) +#define MAX(a,b) (((a)<(b)) ? (b) : (a)) +#define MIN(a,b) (((a)>(b)) ? (b) : (a)) -#define MS_PER_TICK (1000.0/60.0) +class OSystem_MAC : public OSystem { +public: + // Set colors of the palette + void set_palette(const byte *colors, uint start, uint num); -int Time() -{ - UnsignedWide ms; + // Set the size of the video bitmap. + // Typically, 320x200 + void init_size(uint w, uint h); + + // Draw a bitmap to screen. + // The screen will not be updated to reflect the new bitmap + void copy_rect(const byte *buf, int pitch, int x, int y, int w, int h); + + // Update the dirty areas of the screen + void update_screen(); + + // Either show or hide the mouse cursor + bool show_mouse(bool visible); - Microseconds(&ms); - //return(ms.lo * MS_PER_TICK); - return(ms.lo / 1000); -} + // Set the position of the mouse cursor + void set_mouse_pos(int x, int y); + + // Set the bitmap that's used when drawing the cursor. + void set_mouse_cursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y); + + // Shaking is used in SCUMM. Set current shake position. + void set_shake_pos(int shake_pos); + + // Get the number of milliseconds since the program was started. + uint32 get_msecs(); + + // Delay for a specified amount of milliseconds + void delay_msecs(uint msecs); + + // Create a thread + void *create_thread(ThreadProc *proc, void *param); + + // Get the next event. + // Returns true if an event was retrieved. + bool poll_event(Event *event); + + // Set function that generates samples + bool set_sound_proc(void *param, SoundProc *proc, byte sound); + + // Poll cdrom status + // Returns true if cd audio is playing + bool poll_cdrom(); -int DEST_WIDTH, DEST_HEIGHT; -static bool shutdown; + // Play cdrom audio track + void play_cdrom(int track, int num_loops, int start_frame, int end_frame); -KeyMap fKeyMap; + // Stop cdrom audio track + void stop_cdrom(); -Rect srcRect, dstRect; + // Update cdrom audio status + void update_cdrom(); -enum -{ - kNewGameCmd = 'newG', - kQuitCmd = kHICommandQuit, - kOpenGameCmd = 'opnG', - kSaveGameCmd = 'savG', - kPrefsCmd = kHICommandPreferences, - kAboutCmd = 'abtG' + // Add a new callback timer + void set_timer(int timer, int (*callback)(int)) + { + // FIXME - TODO + } + + // Quit + void quit(); + + // Set a parameter + uint32 property(int param, Property *value); + + static OSystem *create(int gfx_mode, bool full_screen); + + void sound_callback(SndChannel *chan, SndCommand *cmd_passed); +private: + typedef void TwoXSaiProc(uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, + uint8 *dstPtr, uint32 dstPitch, int width, int height); + + GWorldPtr screenBuf; + WindowRef wref; + CTabHandle pal; + Rect blit_rect; + + enum { + DF_WANT_RECT_OPTIM = 1 << 0, + DF_REAL_8BIT = 1 << 1, + DF_SEPARATE_TEMPSCREEN = 1 << 2, + DF_UPDATE_EXPAND_1_PIXEL = 1 << 3 + }; + + int _mode; + bool _full_screen; + bool _mouse_visible; + bool _mouse_drawn; + uint32 _mode_flags; + byte _internal_scaling; + + bool force_full; //Force full redraw on next update_screen + bool cksum_valid; + + enum { + NUM_DIRTY_RECT = 100, + + MAX_MOUSE_W = 40, + MAX_MOUSE_H = 40, + MAX_SCALING = 3 + }; + + int SCREEN_WIDTH, SCREEN_HEIGHT, CKSUM_NUM; + Rect *dirty_rect_list; + int num_dirty_rects; + uint32 *dirty_checksums; + + int scaling; + + /* CD Audio */ + int cd_track, cd_num_loops, cd_start_frame, cd_end_frame; + uint32 cd_end_time, cd_stop_time, cd_next_second; + + struct MousePos { + int16 x,y,w,h; + }; + + byte *_ms_buf; + byte *_ms_backup; + MousePos _ms_cur; + MousePos _ms_old; + int16 _ms_hotspot_x; + int16 _ms_hotspot_y; + int _current_shake_pos; + + byte* _gfx_buf; /* Graphics memory */ + int16 *_sai_buf, *_tmp_buf; + uint _palette_changed_first, _palette_changed_last; + + TwoXSaiProc *_sai_func; + + void add_dirty_rgn_auto(const byte *buf); + void mk_checksums(const byte *buf); + + static void fill_sound(void *userdata, uint8 * stream, int len); + + void add_dirty_rect(int x, int y, int w, int h); + + void draw_mouse(); + void undraw_mouse(); + + void load_gfx_mode(); + void unload_gfx_mode(); + + void hotswap_gfx_mode(); + + void get_320x200_image(byte *buf); + + void init_mac_stuff(); + void set_scaling(); + void blit_to_screen(); + void update_rects(); + + static uint32 autosave(uint32); + + UInt8 *buffer[2]; + CmpSoundHeader header; + SndChannelPtr channel; + int size; + SoundProc *sndProc; + void * parameter; }; -static unsigned char *CToPascal(char *str); +int Init_2xSaI (uint32 BitFormat); +void _2xSaI(uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, uint8 *dstPtr, + uint32 dstPitch, int width, int height); +void Super2xSaI(uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, + uint8 *dstPtr, uint32 dstPitch, int width, int height); +void SuperEagle(uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, + uint8 *dstPtr, uint32 dstPitch, int width, int height); +void AdvMame2x(uint8 *srcPtr, uint32 srcPitch, uint8 *null, + uint8 *dstPtr, uint32 dstPitch, int width, int height); +void Normal1x(uint8 *srcPtr, uint32 srcPitch, uint8 *null, + uint8 *dstPtr, uint32 dstPitch, int width, int height); +void Normal2x(uint8 *srcPtr, uint32 srcPitch, uint8 *null, + uint8 *dstPtr, uint32 dstPitch, int width, int height); +void Normal3x(uint8 *srcPtr, uint32 srcPitch, uint8 *null, + uint8 *dstPtr, uint32 dstPitch, int width, int height); -Boolean OptionKeyDown() -{ - GetKeys(fKeyMap); // get info - if (fKeyMap[1] & 4) - return true; - else - return false; -} +KeyMap fKeyMap; Boolean CommandKeyDown() { @@ -86,78 +228,31 @@ Boolean CommandKeyDown() return false; } +static unsigned char *CToPascal(char *str) { + register char *p,*q; + register long len; -Boolean ShiftKeyDown() -{ - GetKeys(fKeyMap); // get info - if (fKeyMap[1] & 1) - return true; - else - return false; + len = strlen(str); + if (len > 255) len = 255; + p = str + len; + q = p-1; + while (p != str) + *p-- = *q--; + *str = len; + return((unsigned char *)str); } +static char *PascalToC(unsigned char *str) { + register unsigned char *p,*q,*end; -// Fast macro for testing key codes. -#define KeyCode(x,y) (BitTst(&(x), (y) ^ 0x07)) + end = str + *str; + q = (p=str) + 1; -Boolean IsKeyDown(unsigned short key) -{ - GetKeys(fKeyMap); // get info - return (KeyCode(fKeyMap, key)); -} + while (p < end) + *p++ = *q++; + *p = '\0'; - -class WndMan -{ - bool terminated; -public: - byte *_vgabuf; - GWorldPtr screenBuf; - WindowRef wPtr; - CTabHandle pal; - bool newPal; - CCrsrHandle theCrsr; - bool fullscreen; - StringPtr gameName; - int scale; - GWorldPtr workSrcMap, backSrcMap; - GDHandle thisGDevice; - - void init(); - - void ChangeScaling(short scaling); - bool handleMessage(); - void run(); - void writeToScreen(); - void setPalette(byte *ctab, int first, int num); -}; - -int sel; -Scumm *scumm; -ScummDebugger debugger; -Gui gui; -IMuse sound; -SOUND_DRIVER_TYPE snd_driv; -OSystem _system; -GameDetector detector; - -WndMan wm[1]; -byte veryFastMode; - -void About(); -void Preferences(); - -void Quit() -{ - QuitApplicationEventLoop(); - ExitToShell(); -} - -void Error(const char* msg) -{ - - //DebugStr((const unsigned char*)msg); - //ExitToShell(); + return((char *)str); } const EventTypeSpec kCmdEvents[] = @@ -178,617 +273,23 @@ const EventTypeSpec kWindowEvents[] = pascal OSErr QuitEventHandler(const AppleEvent *theEvent, AppleEvent *theReply, SInt32 refCon) { - Quit(); + //OSystem_MAC::quit(); return(noErr); } -static pascal OSStatus WindowEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* userData ) +enum { - OSStatus result = eventNotHandledErr; - - if(GetEventClass(inEvent) == kEventClassWindow) - { - switch(GetEventKind(inEvent)) - { - case kEventWindowDrawContent: - wm->writeToScreen(); - break; - - case kEventWindowHandleContentClick: - if(CommandKeyDown()) - scumm->_rightBtnPressed |= msClicked|msDown; - else - scumm->_leftBtnPressed |= msClicked|msDown; - - if(wm->wPtr != FrontWindow()) - { - ActivateWindow(wm->wPtr, true); - BringToFront(wm->wPtr); - } - break; - - case kEventWindowClose: - Quit(); - break; - } - } - return result; -} - -char mapKey(char key, char code, byte mod) -{ - switch(code) - { - case 0x35: - key = 27; - break; - - case 0x31: - key = 32; - break; - - case 0x60: - key = 601; - } - return key; -} - -static pascal OSStatus EventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* userData ) -{ - OSStatus result = eventNotHandledErr; - HICommand command; - Point mouse; - - GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, - sizeof( HICommand ), NULL, &command ); - - switch(GetEventClass(inEvent)) - { - case kEventClassCommand: - switch(command.commandID) - { - case kNewGameCmd: - - break; - - case kOpenGameCmd: - scumm->_saveLoadSlot = 0; - scumm->_saveLoadFlag = 2; - break; - - case kSaveGameCmd: - scumm->_saveLoadSlot = 0; - sprintf(scumm->_saveLoadName, "Quicksave %d", scumm->_saveLoadSlot); - scumm->_saveLoadFlag = 1; - break; - - case kQuitCmd: - Quit(); - break; - - case kPrefsCmd: - Preferences(); - break; - - case kAboutCmd: - About(); - break; - } - break; - break; - - case kEventClassKeyboard: - if(GetEventKind(inEvent) == kEventRawKeyDown) - { - char key; - UInt32 mod, code; - - GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &code); - GetEventParameter(inEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key); - GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &mod); - scumm->_keyPressed = (int)mapKey(key, code, mod); - } - break; - - case kEventClassMouse: - switch(GetEventKind(inEvent)) - { - case kEventMouseDown: - WindowRef theWin; - - GetEventParameter(inEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), - NULL, &theWin); - if(theWin != FrontWindow()) - { - ActivateWindow(theWin, true); - BringToFront(theWin); - } - break; - - case kEventMouseUp: - scumm->_rightBtnPressed &= ~msDown; - scumm->_leftBtnPressed &= ~msDown; - break; - - case kEventMouseMoved: - GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mouse); - Rect winRect; - - GetWindowBounds(wm->wPtr, kWindowContentRgn, &winRect); - if(PtInRect(mouse, &winRect)) - { - CGrafPtr oldPort; - - GetPort(&oldPort); - SetPortWindowPort(wm->wPtr); - GlobalToLocal(&mouse); - scumm->mouse.x = mouse.h/wm->scale; - scumm->mouse.y = mouse.v/wm->scale; - } - Point offset = {0, 0}; - ShieldCursor(&winRect, offset); - break; - } - break; - } - return result; -} - -pascal void DoGameLoop(EventLoopTimerRef theTimer, void *userData) -{ - scumm->mainRun(); - QuitApplicationEventLoop(); -} - -void WndMan::init() -{ - Rect rectWin; - - scumm->_scale = scale; - - DEST_WIDTH = 320 * scumm->_scale; - DEST_HEIGHT = 200 * scumm->_scale; - - MenuRef AppleMenu = GetMenu(1000); - InsertMenu(AppleMenu, 0); - SetMenuItemCommandID(AppleMenu, 1, kAboutCmd); - MenuRef FileMenu = GetMenu(1001); - SetMenuItemCommandID(FileMenu, 1, kNewGameCmd); - SetMenuItemCommandID(FileMenu, 2, kOpenGameCmd); - SetMenuItemCommandID(FileMenu, 3, kSaveGameCmd); - SetMenuItemCommandID(FileMenu, 5, kQuitCmd); - DeleteMenuItems(FileMenu, CountMenuItems(FileMenu)-1, 2); - InsertMenu(FileMenu, 0); - MenuRef windMenu; - CreateStandardWindowMenu(0, &windMenu); - InsertMenu(windMenu, 0); - EnableMenuCommand(NULL, kPrefsCmd); - DrawMenuBar(); - - SetRect(&rectWin, 0, 0, DEST_WIDTH, DEST_HEIGHT); - UInt32 WinAttrib = (kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | - kWindowInWindowMenuAttribute | kWindowStandardHandlerAttribute); - - if(noErr != CreateNewWindow(kDocumentWindowClass, WinAttrib, &rectWin, &wPtr)) - { - Error("Couldn't create Window!"); - } - - RepositionWindow(wPtr, NULL, kWindowCenterOnMainScreen); - - Str255 WindowTitle = "\pScummVM"; - SetWTitle(wPtr, WindowTitle); - - SetPortWindowPort(wPtr); - ShowWindow(wPtr); - - SetRect(&dstRect, 0, 0, DEST_WIDTH, DEST_HEIGHT); - SetRect(&srcRect, 0, 0, SRC_WIDTH, SRC_HEIGHT); - - InstallApplicationEventHandler(NewEventHandlerUPP(EventHandler), - GetEventTypeCount(kCmdEvents), kCmdEvents, 0, NULL); - InstallStandardEventHandler(GetWindowEventTarget(wPtr)); - InstallWindowEventHandler(wPtr, NewEventHandlerUPP(WindowEventHandler), - GetEventTypeCount(kWindowEvents), kWindowEvents, 0, NULL); - - OSStatus err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitEventHandler), 0L, false); - - EventLoopTimerRef theTimer; - InstallEventLoopTimer(GetCurrentEventLoop(), 0, 0, NewEventLoopTimerUPP(DoGameLoop), - NULL, &theTimer); - - NewGWorldFromPtr(&screenBuf, 8, &srcRect, pal, nil, 0, (char *)_vgabuf, SRC_WIDTH); -} - -void WndMan::ChangeScaling(short scaling) -{ - scumm->_scale = scaling; - scale = scaling; - - Rect rectWin; - - DEST_WIDTH = 320 * scumm->_scale; - DEST_HEIGHT = 200 * scumm->_scale; - - SetRect(&rectWin, 0, 0, DEST_WIDTH, DEST_HEIGHT); - - SetWindowBounds(wPtr, kWindowContentRgn, &rectWin); - RepositionWindow(wPtr, NULL, kWindowCenterOnMainScreen); - dstRect = rectWin; -} - -bool WndMan::handleMessage() -{ - EventRef theEvent; - EventTargetRef theTarget; - OSStatus theErr; - - theTarget = GetEventDispatcherTarget(); - theErr = ReceiveNextEvent(GetEventTypeCount(kCmdEvents), kCmdEvents, kEventDurationNoWait,true, &theEvent); - if(theErr == noErr && theEvent != NULL) - { - SendEventToEventTarget (theEvent, theTarget); - ReleaseEvent(theEvent); - } -} - -void WndMan::run() -{ -} - -void WndMan::writeToScreen() -{ - CopyBits(GetPortBitMapForCopyBits(screenBuf), - GetPortBitMapForCopyBits(GetWindowPort(wPtr)), - &srcRect, &dstRect, srcCopy, 0L); -} - -void waitForTimer(Scumm *s, int delay) -{ - uint32 start_time; - - if(s->_fastMode&2) - delay = 0; - else if(s->_fastMode&1) - delay = 10; - - start_time = Time(); - do { - wm->handleMessage(); - if(Time() >= start_time + delay) - break; - } while (1); -} - -void WndMan::setPalette(byte *ctab, int first, int num) -{ - pal = (CTabHandle)NewHandleClear(sizeof(ColorTable) + 255 * sizeof(ColorSpec)); - (*pal)->ctSeed = TickCount(); - (*pal)->ctFlags = 0; - (*pal)->ctSize = 256; - for(int i = 0; i < 256; i++, ctab +=3) - { - (*pal)->ctTable[i].value = i; - (*pal)->ctTable[i].rgb.red = ctab[0]<<8; - (*pal)->ctTable[i].rgb.green = ctab[1]<<8; - (*pal)->ctTable[i].rgb.blue = ctab[2]<<8; - } - NewGWorldFromPtr(&screenBuf, 8, &srcRect, pal, nil, 0, (char *)_vgabuf, SRC_WIDTH); -} - -void blitToScreen(Scumm *s, byte *src,int x, int y, int w, int h) -{ - byte *dst; - int i; - - dst = (byte*)wm->_vgabuf + y*320 + x; - - do { - memcpy(dst, src, w); - dst += 320; - src += 320; - } while (--h); -} - -void updateScreen(Scumm *s) -{ - if (s->_palDirtyMax != -1) { - wm->setPalette(s->_currentPalette, 0, 256); - s->_palDirtyMax = -1; - } - - wm->writeToScreen(); - s->drawMouse(); -} - - -void initGraphics(Scumm *s, bool fullScreen, unsigned int scaleFactor) { - s->_scale = scaleFactor; - wm->init(); -} - -static unsigned char *CToPascal(char *str) -{ - register char *p,*q; - register long len; - - len = strlen(str); - if (len > 255) len = 255; - p = str + len; - q = p-1; - while (p != str) *p-- = *q--; - *str = len; - return((unsigned char *)str); -} - -static char *PascalToC(unsigned char *str) -{ - register unsigned char *p,*q,*end; - - end = str + *str; - q = (p=str) + 1; - while (p < end) *p++ = *q++; - *p = '\0'; - return((char *)str); -} - -ControlRef popUpControlRef, checkBoxControlRef; -char *gameTitle; - -void LaunchGame(int id) -{ - switch(id) - { - case 6: - gameTitle = "indy3"; - break; - - case 7: - gameTitle = "zak256"; - break; - - case 8: - gameTitle = "loom"; - break; - - case 9: - gameTitle = "monkeyEGA"; - break; - - case 10: - gameTitle = "loomcd"; - break; - - case 11: - gameTitle = "monkey"; - break; - - case 12: - gameTitle = "monkey2"; - break; - - case 13: - gameTitle = "atlantis"; - break; - - case 14: - gameTitle = "playfate"; - break; - - case 15: - gameTitle = "tentacle"; - break; - - case 16: - gameTitle = "dottdemo"; - break; - - case 17: - gameTitle = "samnmax"; - break; - - case 18: - gameTitle = "snmdemo"; - break; - - case 19: - gameTitle = "ft"; - break; - - case 20: - gameTitle = "dig"; - } -} - -OSStatus dialogEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef, - void *userData) -{ - OSStatus result = eventNotHandledErr; - UInt32 eventClass; - UInt32 eventKind; - ControlRef controlRef; - ControlID controlID; - - eventClass = GetEventClass(eventRef); - eventKind = GetEventKind(eventRef); - - if(eventClass == kEventClassControl) - { - if(eventKind == kEventControlHit) - { - GetEventParameter(eventRef,kEventParamDirectObject,typeControlRef,NULL, - sizeof(ControlRef),NULL,&controlRef); - - GetControlID(controlRef,&controlID); - if(controlID.id == 'okay') - { - QuitAppModalLoopForWindow((WindowRef)userData); - LaunchGame(GetControlValue(popUpControlRef)); - wm->scale = 2; - - DisposeWindow((WindowRef)userData); - result = noErr; - } - else if(controlID.id == 'cncl') - { - QuitAppModalLoopForWindow((WindowRef)userData); - DisposeWindow((WindowRef)userData); - ExitToShell(); - } - } - } - return result; -} - -void SelectGame() -{ - WindowRef aboutWin; - OSStatus osError = noErr; - Rect rect = { 0,0,120,350 }; - Rect pushButtonRect = { 75,250,96,330 }; - Rect popupRect = { 10, 10, 26, 330 }; - ControlID controlID; - ControlRef controlRef; - Rect checkboxRect = { 36, 10, 50, 80 }; - EventTypeSpec dialogEvents[] = { kEventClassControl, kEventControlHit }; - - osError = CreateNewWindow(kMovableModalWindowClass,kWindowStandardHandlerAttribute,&rect, &aboutWin); - SetWTitle(aboutWin, "\pPlease Select a GameÉ"); - RepositionWindow(aboutWin,FrontWindow(),kWindowAlertPositionOnMainScreen); - SetThemeWindowBackground(aboutWin,kThemeBrushDialogBackgroundActive,false); - CreateRootControl(aboutWin,&controlRef); - - CreatePushButtonControl(aboutWin,&pushButtonRect,CFSTR("OK"),&controlRef); - SetWindowDefaultButton(aboutWin,controlRef); - controlID.id = 'okay'; - SetControlID(controlRef,&controlID); - AutoEmbedControl(controlRef,aboutWin); - - OffsetRect(&pushButtonRect, -100, 0); - CreatePushButtonControl(aboutWin,&pushButtonRect,CFSTR("Cancel"),&controlRef); - SetWindowCancelButton(aboutWin,controlRef); - controlID.id = 'cncl'; - SetControlID(controlRef,&controlID); - AutoEmbedControl(controlRef,aboutWin); - - CreatePopupButtonControl(aboutWin, &popupRect, CFSTR("Game: "), 999, false, -1, 0, NULL, &popUpControlRef); - SetWindowDefaultButton(aboutWin,popUpControlRef); - controlID.id = 'game'; - SetControlID(popUpControlRef,&controlID); - - AutoEmbedControl(controlRef,aboutWin); - - InstallWindowEventHandler(aboutWin, NewEventHandlerUPP((EventHandlerProcPtr) dialogEventHandler), - GetEventTypeCount(dialogEvents),dialogEvents,aboutWin,NULL); - ShowWindow(aboutWin); - osError = RunAppModalLoopForWindow(aboutWin); -} - -static void DrawCenteredStringAt(Str255 theString, short yLocation) -{ - Rect portRect; - CGrafPtr thePort = GetQDGlobalsThePort(); - - GetPortBounds(thePort, &portRect); - - MoveTo(portRect.left + ((portRect.right-portRect.left) >> 1) - - (StringWidth(theString) >> 1), yLocation); - DrawString(theString); - -} - -void DrawAboutText(WindowRef win) -{ - CGrafPtr oldPort; - - GetPort(&oldPort); - SetPortWindowPort(win); - - TextFont(systemFont); - TextSize(12); - - DrawCenteredStringAt("\pAbout ScummVMÉ", 32); - - TextFont(applFont); - TextSize(9); - - DrawCenteredStringAt("\pScummVM", 50); - DrawCenteredStringAt("\pLet's you run all your favourite Scumm Games", 65); - DrawCenteredStringAt("\pon MacOS 9 and X", 80); - - SetPort(oldPort); -} - -OSStatus aboutEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef, - void *userData) -{ - OSStatus result = eventNotHandledErr; - UInt32 eventClass; - UInt32 eventKind; - ControlRef controlRef; - ControlID controlID; - - eventClass = GetEventClass(eventRef); - eventKind = GetEventKind(eventRef); - - if(eventClass == kEventClassControl) - { - if(eventKind == kEventControlHit) - { - GetEventParameter(eventRef,kEventParamDirectObject,typeControlRef,NULL, - sizeof(ControlRef),NULL,&controlRef); - - GetControlID(controlRef,&controlID); - if(controlID.id == 'okay') - { - QuitAppModalLoopForWindow((WindowRef)userData); - DisposeWindow((WindowRef)userData); - result = noErr; - } - } - } - else if(eventClass == kEventClassWindow) - { - if(eventKind == kEventWindowUpdate) - { - DrawAboutText((WindowRef)userData); - } - } - return result; -} - -void About() -{ - WindowRef aboutWin; - OSStatus osError = noErr; - Rect rect = { 0,0,150,300 }; - Rect pushButtonRect = { 125,125,145,175 }; - ControlID controlID; - ControlRef controlRef; - EventTypeSpec dialogEvents[] = { { kEventClassControl, kEventControlHit }, - { kEventClassWindow, kEventWindowUpdate} }; - - osError = CreateNewWindow(kMovableModalWindowClass,kWindowStandardHandlerAttribute,&rect, &aboutWin); - SetWTitle(aboutWin, "\pAbout ScummVMÉ"); - RepositionWindow(aboutWin,FrontWindow(),kWindowAlertPositionOnMainScreen); - SetThemeWindowBackground(aboutWin,kThemeBrushDialogBackgroundActive,false); - CreateRootControl(aboutWin,&controlRef); - - DrawAboutText(aboutWin); - - CreatePushButtonControl(aboutWin,&pushButtonRect,CFSTR("OK"),&controlRef); - SetWindowDefaultButton(aboutWin,controlRef); - controlID.id = 'okay'; - SetControlID(controlRef,&controlID); - AutoEmbedControl(controlRef,aboutWin); - - InstallWindowEventHandler(aboutWin, NewEventHandlerUPP((EventHandlerProcPtr) aboutEventHandler), - GetEventTypeCount(dialogEvents),dialogEvents,aboutWin,NULL); - ShowWindow(aboutWin); - osError = RunAppModalLoopForWindow(aboutWin); -} + kNewGameCmd = 'newG', + kQuitCmd = kHICommandQuit, + kOpenGameCmd = 'opnG', + kSaveGameCmd = 'savG', + kPrefsCmd = kHICommandPreferences, + kAboutCmd = 'abtG' +}; ControlRef radioGroupRef, musicVolumeSlider, masterVolumeSlider; +char *gameTitle; +ControlRef popUpControlRef, checkBoxControlRef; OSStatus prefsEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef, void *userData) @@ -812,7 +313,7 @@ OSStatus prefsEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef even GetControlID(controlRef,&controlID); if(controlID.id == 'okay') { - scumm->_noSubtitles = (Boolean)!GetControlValue(checkBoxControlRef); + /*scumm->_noSubtitles = (Boolean)!GetControlValue(checkBoxControlRef); short scale = GetControlValue(radioGroupRef); if(scale != scumm->_scale) wm->ChangeScaling(scale); @@ -821,7 +322,7 @@ OSStatus prefsEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef even sound.set_music_volume(music_vol); short master_vol = GetControlValue(masterVolumeSlider); if(master_vol != sound.get_master_volume()) - sound.set_master_volume(master_vol); + sound.set_master_volume(master_vol);*/ QuitAppModalLoopForWindow((WindowRef)userData); DisposeWindow((WindowRef)userData); result = noErr; @@ -864,7 +365,7 @@ void Preferences() CreateCheckBoxControl(prefsWin,&rect, CFSTR("Subtitles"), 1, true, &checkBoxControlRef); AutoEmbedControl(checkBoxControlRef, prefsWin); - if(scumm->_noSubtitles) + //if(scumm->_noSubtitles) SetControlValue(checkBoxControlRef, false); OffsetRect(&rect, 0, 20); @@ -893,17 +394,17 @@ void Preferences() CreateRadioButtonControl(prefsWin, &RadioButtonRect, CFSTR("Scaling 3x"), 0, true, &radioButton); AutoEmbedControl(radioButton, prefsWin); - SetControlValue(radioGroupRef, scumm->_scale); + //SetControlValue(radioGroupRef, scumm->_scale); SetRect(&rect, 5, 110, 175, 146); - CreateSliderControl(prefsWin, &rect, sound.get_music_volume(), 1, 100, + CreateSliderControl(prefsWin, &rect, 100, 1, 100, kControlSliderPointsDownOrRight, 10, false, NULL, &musicVolumeSlider); AutoEmbedControl(musicVolumeSlider, prefsWin); OffsetRect(&rect, 0, 36); - CreateSliderControl(prefsWin, &rect, sound.get_master_volume(), 1, 100, + CreateSliderControl(prefsWin, &rect, 100, 1, 100, kControlSliderPointsDownOrRight, 10, false, NULL, &masterVolumeSlider); AutoEmbedControl(masterVolumeSlider, prefsWin); @@ -923,72 +424,147 @@ void Preferences() osError = RunAppModalLoopForWindow(prefsWin); } -/* FIXME: CD Music Stubs */ -void cd_playtrack(int track, int offset, int delay) {;} -void cd_play(Scumm *s, int track, int num_loops, int start_frame, int end_frame) {;} -void cd_stop() {;} -int cd_is_running() {return 0;} - -void launcherLoop() { - /* No launcher an Mac yet, probably there won't ever be one, as */ - /* there is a nice Mac-like Launcher already. */ -} - -void BoxTest(int num) { -} - -void setShakePos(Scumm *s, int shake_pos) {} - -void drawMouse(int xdraw, int ydraw, int w, int h, byte *buf, bool visible) +void LaunchGame(int id) { - int x, y; - byte *mask, *src, *dst; - byte color; - Point mouse; - GrafPtr oldPort; - Rect r, r2; - - if(visible) + switch(id) { - GWorldPtr gw, gw2; + case 6: + gameTitle = "indy3"; + break; - src = buf; - mask = (byte*)malloc(sizeof(byte) * w * h); - dst = mask; - for(y = 0; y < h; y++, dst += w, src += w) - { - if((uint)y < h) - { - for(x = 0; x < w; x++) - { - if((uint)x < w) - { - if(src[x] != 0xFF) - dst[x] = 0xFF; - else - dst[x] = 0x00; - } - } - } - } + case 7: + gameTitle = "zak256"; + break; + + case 8: + gameTitle = "loom"; + break; - SetRect(&r, 0, 0, w, h); + case 9: + gameTitle = "monkeyEGA"; + break; - NewGWorldFromPtr(&gw, 8, &r, wm->pal, nil, 0, (char *)buf, w); - NewGWorldFromPtr(&gw2, 8, &r, NULL, nil, 0, (char *)mask, w); - SetRect(&r2, (s->mouse.x - w / 2) * s->_scale, (s->mouse.y - h / 2) * s->_scale, - (s->mouse.x + w / 2) * s->_scale, (s->mouse.y + h / 2) * s->_scale); - CopyMask(GetPortBitMapForCopyBits(gw), GetPortBitMapForCopyBits(gw2), - GetPortBitMapForCopyBits(GetWindowPort(wm->wPtr)), - &r, &r, &r2); + case 10: + gameTitle = "monkeyVGA"; + break; + + case 11: + gameTitle = "loomcd"; + break; + + case 12: + gameTitle = "monkey"; + break; + + case 13: + gameTitle = "monkey1"; + break; + + case 14: + gameTitle = "monkey2"; + break; + + case 15: + gameTitle = "atlantis"; + break; + + case 16: + gameTitle = "playfate"; + break; + + case 17: + gameTitle = "tentacle"; + break; + + case 18: + gameTitle = "dottdemo"; + break; + + case 19: + gameTitle = "samnmax"; + break; + + case 20: + gameTitle = "snmdemo"; + break; + + case 21: + gameTitle = "ft"; + break; + + case 22: + gameTitle = "dig"; + break; + + case 25: + gameTitle = "simon1dos"; + break; + + case 26: + gameTitle = "simon1win"; + break; + + case 27: + gameTitle = "simon2win"; + break; } } -void InitMacStuff() +OSStatus dialogEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef, + void *userData) { - InitCursor(); - - SIOUXSettings.autocloseonquit = true; + OSStatus result = eventNotHandledErr; + UInt32 eventClass; + UInt32 eventKind; + ControlRef controlRef; + ControlID controlID; + + eventClass = GetEventClass(eventRef); + eventKind = GetEventKind(eventRef); + + if(eventClass == kEventClassControl) + { + if(eventKind == kEventControlHit) + { + + GetEventParameter(eventRef,kEventParamDirectObject,typeControlRef,NULL, + sizeof(ControlRef),NULL,&controlRef); + + GetControlID(controlRef,&controlID); + if(controlID.id == 'okay') + { + QuitAppModalLoopForWindow((WindowRef)userData); + LaunchGame(GetControlValue(popUpControlRef)); + + DisposeWindow((WindowRef)userData); + result = noErr; + } + else if(controlID.id == 'cncl') + { + QuitAppModalLoopForWindow((WindowRef)userData); + DisposeWindow((WindowRef)userData); + ExitToShell(); + } + } + } + return result; +} + +char* SelectGame() +{ + WindowRef aboutWin; + OSStatus osError = noErr; + Rect rect = { 0,0,120,350 }; + Rect pushButtonRect = { 75,250,96,330 }; + Rect popupRect = { 10, 10, 26, 330 }; + ControlID controlID; + ControlRef controlRef; + Rect checkboxRect = { 36, 10, 50, 80 }; + EventTypeSpec dialogEvents[] = { kEventClassControl, kEventControlHit }; + + InitCursor(); + + SIOUXSettings.autocloseonquit = true; SIOUXSettings.asktosaveonclose = false; SIOUXSettings.showstatusline = false; SIOUXSettings.fontsize = 9; @@ -997,70 +573,783 @@ void InitMacStuff() SIOUXSettings.setupmenus = false; SIOUXSettings.toppixel = 40; SIOUXSettings.leftpixel = 5; + + osError = CreateNewWindow(kMovableModalWindowClass,kWindowStandardHandlerAttribute,&rect, &aboutWin); + SetWTitle(aboutWin, "\pPlease Select a GameÉ"); + RepositionWindow(aboutWin,FrontWindow(),kWindowAlertPositionOnMainScreen); + SetThemeWindowBackground(aboutWin,kThemeBrushDialogBackgroundActive,false); + CreateRootControl(aboutWin,&controlRef); + + CreatePushButtonControl(aboutWin,&pushButtonRect,CFSTR("OK"),&controlRef); + SetWindowDefaultButton(aboutWin,controlRef); + controlID.id = 'okay'; + SetControlID(controlRef,&controlID); + AutoEmbedControl(controlRef,aboutWin); + + OffsetRect(&pushButtonRect, -100, 0); + CreatePushButtonControl(aboutWin,&pushButtonRect,CFSTR("Cancel"),&controlRef); + SetWindowCancelButton(aboutWin,controlRef); + controlID.id = 'cncl'; + SetControlID(controlRef,&controlID); + AutoEmbedControl(controlRef,aboutWin); + + CreatePopupButtonControl(aboutWin, &popupRect, CFSTR("Game: "), 999, false, -1, 0, NULL, &popUpControlRef); + SetWindowDefaultButton(aboutWin,popUpControlRef); + controlID.id = 'game'; + + SetControlID(popUpControlRef,&controlID); + + AutoEmbedControl(controlRef,aboutWin); + + InstallWindowEventHandler(aboutWin, NewEventHandlerUPP((EventHandlerProcPtr) dialogEventHandler), + GetEventTypeCount(dialogEvents),dialogEvents,aboutWin,NULL); + ShowWindow(aboutWin); + osError = RunAppModalLoopForWindow(aboutWin); + return gameTitle; } -void InitScummStuff() +OSystem *OSystem_MAC::create(int gfx_mode, bool full_screen) { + Rect rectWin; + OSystem_MAC *syst = new OSystem_MAC(); + syst->_mode = gfx_mode; + syst->_full_screen = full_screen; + + /* Macintosh init */ + syst->init_mac_stuff(); + + return syst; +} + +uint32 OSystem_MAC::autosave(uint32 interval) { - detector.detectMain(2, &gameTitle); - - if(detector._features & GF_OLD256) - scumm = new Scumm_v3; - else - if(detector._features & GF_SMALL_HEADER) // this force loomCD as v4 - scumm = new Scumm_v4; - else - if(detector._features & GF_AFTER_V7) - scumm = new Scumm_v7; - else - if(detector._features & GF_AFTER_V6) // this force SamnmaxCD as v6 - scumm = new Scumm_v6; - else - scumm = new Scumm_v5; - - scumm->_fullScreen = detector._fullScreen; - scumm->_debugMode = detector._debugMode; - scumm->_bootParam = detector._bootParam; - scumm->_scale = detector._scale; - scumm->_gameDataPath = detector._gameDataPath; - scumm->_gameTempo = detector._gameTempo; - scumm->_videoMode = detector._videoMode; - scumm->_exe_name = detector._exe_name; - scumm->_gameId = detector._gameId; - scumm->_gameText = detector._gameText; - scumm->_features = detector._features; - scumm->_soundCardType = detector._soundCardType; - scumm->_noSubtitles = detector._noSubtitles; - scumm->_midi_driver = detector._midi_driver; - scumm->_cdrom = detector._cdrom; - - scumm->delta=6; - scumm->_gui = &gui; - sound.initialize(scumm,&snd_driv); - - scumm->delta=0; - scumm->_system = &_system; + g_scumm->_doAutosave = true; + + return interval; } -void setWindowName(Scumm *scumm) +OSystem *OSystem_MAC_create(int gfx_mode, bool full_screen) { + return OSystem_MAC::create(gfx_mode, full_screen); +} + +void OSystem_MAC::set_palette(const byte *colors, uint start, uint num) { + const byte *b = colors; + + (*pal)->ctSeed = TickCount(); + for(int i = start; i < num; i++, b += 4) { + (*pal)->ctTable[i].value = i; + (*pal)->ctTable[i].rgb.red = b[0]<<8; + (*pal)->ctTable[i].rgb.green = b[1]<<8; + (*pal)->ctTable[i].rgb.blue = b[2]<<8; + } + + CTabChanged(pal); + + if(_sai_func) + UpdateGWorld(&screenBuf, 16, &blit_rect, NULL, NULL, 0); + else + UpdateGWorld(&screenBuf, 8, &blit_rect, pal, NULL, 0); + + if(start < _palette_changed_first) + _palette_changed_first = start; + + if(start + num > _palette_changed_last) + _palette_changed_last = start + num; +} + +void OSystem_MAC::load_gfx_mode() { + force_full = true; + scaling = 1; + _internal_scaling = 1; + _mode_flags = 0; + _sai_func = NULL; + + switch(_mode) { + case GFX_2XSAI: + _sai_func = _2xSaI; + break; + + case GFX_SUPER2XSAI: + _sai_func = Super2xSaI; + break; + + case GFX_SUPEREAGLE: + _sai_func = SuperEagle; + break; + + case GFX_ADVMAME2X: + _sai_func = AdvMame2x; + break; + + case GFX_DOUBLESIZE: + scaling = 2; + _internal_scaling = 2; + _mode_flags = DF_WANT_RECT_OPTIM; + break; + + case GFX_TRIPLESIZE: + if (_full_screen) { + warning("full screen in useless in triplesize mode, reverting to normal mode"); + goto normal_mode; + } + scaling = 3; + _internal_scaling = 3; + _mode_flags = DF_WANT_RECT_OPTIM; + break; + + case GFX_NORMAL: + normal_mode:; + _mode_flags = DF_WANT_RECT_OPTIM; + break; + + } + + if(_sai_func) + { + _mode_flags = DF_WANT_RECT_OPTIM | DF_SEPARATE_TEMPSCREEN | DF_UPDATE_EXPAND_1_PIXEL; + + Init_2xSaI(565); + _tmp_buf = (int16*)calloc((SCREEN_WIDTH+3)*(SCREEN_HEIGHT+3), sizeof(int16)); + + scaling = 2; + } + else + { + switch(scaling) { + case 3: + _sai_func = Normal3x; + break; + case 2: + _sai_func = Normal2x; + break; + case 1: + _sai_func = Normal1x; + break; + } + + _mode_flags = DF_WANT_RECT_OPTIM | DF_REAL_8BIT; + } + + set_scaling(); +} + +void OSystem_MAC::unload_gfx_mode() { + //warning("STUB: unload_gfx_mode()"); /* FIXME: Must free data here */ + +} + +void OSystem_MAC::init_size(uint w, uint h) { + //if (w != SCREEN_WIDTH && h != SCREEN_HEIGHT) + // error("320x200 is the only game resolution supported"); + + SCREEN_WIDTH = w; + SCREEN_HEIGHT = h; + CKSUM_NUM = (SCREEN_WIDTH * SCREEN_HEIGHT / (8*8)); + dirty_rect_list = (Rect*)calloc(NUM_DIRTY_RECT, sizeof(Rect)); + _ms_backup = (byte*)malloc(MAX_MOUSE_W * MAX_MOUSE_H * MAX_SCALING); + dirty_checksums = (uint32*)calloc(CKSUM_NUM*2, sizeof(uint32)); + + load_gfx_mode(); +} + +void OSystem_MAC::copy_rect(const byte *buf, int pitch, int x, int y, int w, int h) { + if (pitch == SCREEN_WIDTH && x==0 && y==0 && w==SCREEN_WIDTH && h==SCREEN_HEIGHT && _mode_flags&DF_WANT_RECT_OPTIM) { + /* Special, optimized case for full screen updates. + * It tries to determine what areas were actually changed, + * and just updates those, on the actual display. */ + add_dirty_rgn_auto(buf); + } else { + /* Clip the coordinates */ + if (x < 0) { w+=x; buf-=x; x = 0; } + + if (y < 0) { h+=y; buf-=y*pitch; y = 0; } + if (w >= SCREEN_WIDTH-x) { w = SCREEN_WIDTH - x; } + if (h >= SCREEN_HEIGHT-y) { h = SCREEN_HEIGHT - y; } + + if (w<=0 || h<=0) + return; + + cksum_valid = false; + add_dirty_rect(x, y, w, h); + } + + /* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */ + if (_mouse_drawn) + undraw_mouse(); + + byte *dst = (byte*)buf + y * SCREEN_WIDTH + x; + do { + memcpy(dst, buf, w); + dst += SCREEN_WIDTH; + buf += pitch; + } while(--h); +} + +void OSystem_MAC::add_dirty_rect(int x, int y, int w, int h) { + if (force_full) + return; + + if (num_dirty_rects == NUM_DIRTY_RECT) + force_full = true; + else { + Rect *r = &dirty_rect_list[num_dirty_rects++]; + + /* Update the dirty region by 1 pixel for graphics drivers + * that "smear" the screen */ + if (_mode_flags & DF_UPDATE_EXPAND_1_PIXEL) { + x--; + y--; + w+=2; + h+=2; + } + + /* clip */ + if (x<0) { w+=x; x=0; } + if (y<0) { h+=y; y=0; } + if (w>=SCREEN_WIDTH-x) { w=SCREEN_WIDTH-x; } + if (h>=SCREEN_HEIGHT-y) { h=SCREEN_HEIGHT-y; } + + if (_internal_scaling != 1) { + x *= _internal_scaling; + y *= _internal_scaling; + w *= _internal_scaling; + h *= _internal_scaling; + } + + r->left = x; + r->top = y; + r->right = x + w; + r->bottom = y + h; + } +} + +#define ROL(a,n) a = (a<<(n)) | (a>>(32-(n))) +#define DOLINE(x) a ^= ((uint32*)buf)[0+(x)*(SCREEN_WIDTH/4)]; b ^= ((uint32*)buf)[1+(x)*(SCREEN_WIDTH/4)] +void OSystem_MAC::mk_checksums(const byte *buf) { + uint32 *sums = dirty_checksums; + uint x,y; + + /* the 8x8 blocks in buf are enumerated starting in the top left corner and + * reading each line at a time from left to right */ + for(y=0; y!=SCREEN_HEIGHT/8; y++,buf+=SCREEN_WIDTH*(8-1)) + for(x=0; x!=SCREEN_WIDTH/8; x++,buf+=8) { + uint32 a = x; + uint32 b = y; + + DOLINE(0); ROL(a,13); ROL(b,11); + DOLINE(2); ROL(a,13); ROL(b,11); + DOLINE(4); ROL(a,13); ROL(b,11); + DOLINE(6); ROL(a,13); ROL(b,11); + + a*=0xDEADBEEF; + b*=0xBAADF00D; + + DOLINE(1); ROL(a,13); ROL(b,11); + DOLINE(3); ROL(a,13); ROL(b,11); + DOLINE(5); ROL(a,13); ROL(b,11); + DOLINE(7); ROL(a,13); ROL(b,11); + + /* output the checksum for this block */ + *sums++=a+b; + } +} +#undef DOLINE +#undef ROL + + +void OSystem_MAC::add_dirty_rgn_auto(const byte *buf) { + assert( ((uint32)buf & 3) == 0); + + /* generate a table of the checksums */ + mk_checksums(buf); + +if (!cksum_valid) { + force_full = true; + cksum_valid = true; + } + + /* go through the checksum list, compare it with the previous checksums, + and add all dirty rectangles to a list. try to combine small rectangles + into bigger ones in a simple way */ + if (!force_full) { + uint x,y,w; + uint32 *ck = dirty_checksums; + + for(y=0; y!=SCREEN_HEIGHT/8; y++) { + for(x=0; x!=SCREEN_WIDTH/8; x++,ck++) { + if (ck[0] != ck[CKSUM_NUM]) { + /* found a dirty 8x8 block, now go as far to the right as possible, + and at the same time, unmark the dirty status by setting old to new. */ + w=0; + do { + ck[w+CKSUM_NUM] = ck[w]; + w++; + } while (x+w != SCREEN_WIDTH/8 && ck[w] != ck[w+CKSUM_NUM]); + + add_dirty_rect(x*8, y*8, w*8, 8); + + if (force_full) + goto get_out; + } + } + } + } else { + get_out:; + /* Copy old checksums to new */ + memcpy(dirty_checksums + CKSUM_NUM, dirty_checksums, CKSUM_NUM * sizeof(uint32)); + } +} + +void OSystem_MAC::update_screen() { +#if 0 + /* First make sure the mouse is drawn, if it should be drawn. */ + draw_mouse(); + + if (_palette_changed_last != 0) { + //warning("MAC: Palette should be uploaded!");/* FIXME: Add Palette changing code */ + + /*GDevice **odisplay; + odisplay = GetGDevice(); + SetGDevice(GetMainDevice()); + SetEntries(0, (**pal).ctSize, (ColorSpec *)&(**pal).ctTable); + SetGDevice(odisplay);*/ + + /*_palette_changed_last = 0; + if (_mode_flags & DF_FORCE_FULL_ON_PALETTE) + */force_full = true; + } + + /* force a full redraw, accomplish that by adding one big rect to the dirty + * rect list */ + if (force_full) { + num_dirty_rects = 1; + + dirty_rect_list[0].left = 0; + dirty_rect_list[0].top = 0; + dirty_rect_list[0].right = SCREEN_WIDTH; + dirty_rect_list[0].bottom = SCREEN_HEIGHT; + } + + if (num_dirty_rects > 0) + { + Rect *r; + uint32 srcPitch, dstPitch; + Rect *last_rect = dirty_rect_list + num_dirty_rects; + + /* Convert appropriate parts of the image into 16bpp */ + if ((_mode_flags & DF_REAL_8BIT) == 0) { + Rect dst; + for(r=dirty_rect_list; r!=last_rect; ++r) { + dst = *r; + dst.left++; + dst.top++; + dst.right++; + dst.bottom++; + } + } + + /*srcPitch = sdl_tmpscreen->pitch; + dstPitch = sdl_hwscreen->pitch;*/ + + if ((_mode_flags & DF_REAL_8BIT) == 0) { + for(r=dirty_rect_list; r!=last_rect; ++r) { + register int dst_y = r->y + _current_shake_pos; + register int dst_h = 0; + if (dst_y < SCREEN_HEIGHT) { + dst_h = r->h; + if (dst_h > SCREEN_HEIGHT - dst_y) + dst_h = SCREEN_HEIGHT - dst_y; + + r->x <<= 1; + dst_y <<= 1; + + _sai_func((byte*)sdl_tmpscreen->pixels + (r->x+2) + (r->y+1)*srcPitch, srcPitch, NULL, + (byte*)sdl_hwscreen->pixels + r->x*scaling + dst_y*dstPitch, dstPitch, r->w, dst_h); + } + + r->y = dst_y; + r->w <<= 1; + r->h = dst_h << 1; + } + } else { + for(r=dirty_rect_list; r!=last_rect; ++r) { + register int dst_y = r->y + _current_shake_pos; + register int dst_h = 0; + if (dst_y < SCREEN_HEIGHT) { + dst_h = r->h; + if (dst_h > SCREEN_HEIGHT - dst_y) + dst_h = SCREEN_HEIGHT - dst_y; + + dst_y *= scaling; + + _sai_func((byte*)sdl_tmpscreen->pixels + r->x + r->y*srcPitch, srcPitch, NULL, + (byte*)sdl_hwscreen->pixels + r->x*scaling + dst_y*dstPitch, dstPitch, r->w, dst_h); + } + + r->x *= scaling; + r->y = dst_y; + r->w *= scaling; + r->h = dst_h * scaling; + } + } + + if (force_full) { + dirty_rect_list[0].y = 0; + dirty_rect_list[0].h = SCREEN_HEIGHT * scaling; + } + } + + /*if(_mode_flags & DF_2xSAI) + { + Rect *r; + uint32 area = 0; + + Rect *dr = dirty_rect_list + num_dirty_rects; + + for(r = dirty_rect_list; r != dr; r++) + { + GWorldPtr gw; + Rect rec; + SetRect(&rec, 0, 0, 320, 200); + NewGWorldFromPtr(&gw, 16, &rec, NULL, NULL, 0, (char*)_tmp_buf, rec.right); + CopyBits(GetPortBitMapForCopyBits(gw), GetPortBitMapForCopyBits(screenBuf), + r, r, srcCopy, 0L); + } + + for(r = dirty_rect_list; r != dr; r++) + { + _sai_func((byte*)_tmp_buf + r->left * 2 + r->top * 640, 640, NULL, + (byte*)_sai_buf + r->left * 4 + r->top * 640 * 4, 640 * 2, + r->right - r->left, r->bottom - r->top); + + area += (r->right - r->left) * (r->bottom - r->top); + + r->left <<= 1; + r->right <<= 1; + r->top <<= 1; + r->bottom <<= 1; + } + }*/ + + update_rects(); + //blit_to_screen(); + + num_dirty_rects = 0; + +#endif +} + +bool OSystem_MAC::show_mouse(bool visible) { + if (_mouse_visible == visible) + return visible; + + bool last = _mouse_visible; + _mouse_visible = visible; + + if (visible) + draw_mouse(); + else + undraw_mouse(); + + return last; +} + +void OSystem_MAC::set_mouse_pos(int x, int y) { + if (x != _ms_cur.x || y != _ms_cur.y) { + _ms_cur.x = x; + _ms_cur.y = y; + undraw_mouse(); + } +} + +void OSystem_MAC::set_mouse_cursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y) { + _ms_cur.w = w; + _ms_cur.h = h; + + _ms_hotspot_x = hotspot_x; + _ms_hotspot_y = hotspot_y; + + _ms_buf = (byte*)buf; + + undraw_mouse(); +} + +void OSystem_MAC::set_shake_pos(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; + force_full = true; + + /* Old shake pos was current_shake_pos, new is shake_pos. + * Move the screen up or down to account for the change. + */ + //SDL_Rect dstr = { 0, shake_pos*scaling, 320*scaling, 200*scaling }; + //SDL_Rect srcr = { 0, old_shake_pos*scaling, 320*scaling, 200*scaling }; + //SDL_BlitSurface(sdl_screen, &srcr, sdl_screen, &dstr); + /* Rect srcr, dstr; + + SetRect(&srcr, 0, old_shake_pos * scaling, 320 * scaling, 200 * scaling); + SetRect(&dstr, 0, shake_pos * scaling, 320 * scaling, 200 * scaling); + + CopyBits(GetPortBitMapForCopyBits(screenBuf), GetPortBitMapForCopyBits(GetWindowPort(wref)), + &srcr, &dstr, srcCopy, 0L); + + /* 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 */ + //SDL_Rect blackrect = {0, dirty_blacktop*scaling, 320*scaling, dirty_blackheight*scaling}; + //SDL_FillRect(sdl_screen, &blackrect, 0); + + /* FIXME: Um, screen seems to glitch since this + 'not needed' function was removed */ + //g_scumm->redrawLines(dirty_top, dirty_top + dirty_height); +/* }*/ +} + +uint32 OSystem_MAC::get_msecs() { + UnsignedWide ms; + + Microseconds(&ms); + return(ms.lo / 1000); +} + +void OSystem_MAC::delay_msecs(uint msecs) { + uint32 start = get_msecs(); + Event dummy; + + do { + poll_event(&dummy); /* Do something to avoid CPU lock */ + if(get_msecs() >= start + msecs) + break; + } while (1); +} + +void *OSystem_MAC::create_thread(ThreadProc *proc, void *param) { + warning("MAC: Stub create_thread()"); + //NewThread(kCooperativeThread, (void*)proc, param, 0L, kCreateIfNeeded, NULL, NULL); +} + +int mapKey(int key, byte code, byte mod) { - char buf[512], *gameName; + switch(code) { + case 0x35: + key = 27; + break; + case 0x31: + key = 32; + break; + case 0x60: + key = 601; + break; + } - sprintf(buf, "ScummVM - %s", gameName = detector.getGameName()); - free(gameName); - StringPtr gameText = CToPascal(buf); - SetWTitle(wm->wPtr, gameText); + return key; +} + +bool OSystem_MAC::poll_event(Event *event) +{ + EventRef theEvent; + EventTargetRef theTarget; + OSStatus theErr; + + OSStatus result = eventNotHandledErr; + HICommand command; + Point mouse; + + theTarget = GetEventDispatcherTarget(); + theErr = ReceiveNextEvent(GetEventTypeCount(kCmdEvents), kCmdEvents, kEventDurationNoWait,true, &theEvent); + + GetEventParameter( theEvent, kEventParamDirectObject, typeHICommand, NULL, + sizeof( HICommand ), NULL, &command ); + + switch(GetEventClass(theEvent)) + { + case kEventClassWindow: + switch(GetEventKind(theEvent)) + { + case kEventWindowDrawContent: + break; + + case kEventWindowHandleContentClick: + EventMouseButton btn; + + GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, + sizeof(EventMouseButton), NULL, &btn); + + if(btn == kEventMouseButtonPrimary) + event->event_code = EVENT_RBUTTONDOWN; + else if(btn == kEventMouseButtonSecondary) + event->event_code = EVENT_LBUTTONDOWN; + + debug(1, "Mouse down!"); + + if(wref != FrontWindow()) + { + ActivateWindow(wref, true); + BringToFront(wref); + } + return true; + break; + + case kEventWindowClose: + quit(); + break; + } + break; + + case kEventClassCommand: + switch(command.commandID) + { + case kNewGameCmd: + + break; + + case kOpenGameCmd: + //scumm->_saveLoadSlot = 0; + //scumm->_saveLoadFlag = 2; + break; + + case kSaveGameCmd: + //scumm->_saveLoadSlot = 0; + //sprintf(scumm->_saveLoadName, "Quicksave %d", scumm->_saveLoadSlot); + //scumm->_saveLoadFlag = 1; + break; + + case kQuitCmd: + quit(); + break; + + case kPrefsCmd: + //Preferences(); + break; + + case kAboutCmd: + //About(); + break; + } + break; + + case kEventClassKeyboard: + if(GetEventKind(theEvent) == kEventRawKeyDown) + { + char key; + UInt32 mod, code; + + GetEventParameter(theEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &code); + GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key); + GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &mod); + + event->event_code = EVENT_KEYDOWN; + event->kbd.keycode = code; + event->kbd.ascii = mapKey(key, code, mod); + debug(1, "Key down: %c", event->kbd.ascii); + return true; + } + break; + + case kEventClassMouse: + EventMouseButton btn; + Rect winRect; + + switch(GetEventKind(theEvent)) + { + case kEventMouseDown: + WindowRef theWin; + + GetEventParameter(theEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), + NULL, &theWin); + if(theWin != FrontWindow()) + { + ActivateWindow(theWin, true); + BringToFront(theWin); + } + + GetEventParameter(theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mouse); + + GetWindowBounds(wref, kWindowContentRgn, &winRect); + if(PtInRect(mouse, &winRect)) + { + GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, + sizeof(EventMouseButton), NULL, &btn); + + if(btn == kEventMouseButtonPrimary) + event->event_code = EVENT_RBUTTONDOWN; + else if(btn == kEventMouseButtonSecondary) + event->event_code = EVENT_LBUTTONDOWN; + + debug(1, "Mouse down!"); + } + break; + + case kEventMouseUp: + + GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, + sizeof(EventMouseButton), NULL, &btn); + + if(btn == kEventMouseButtonPrimary) + event->event_code = EVENT_RBUTTONUP; + else if(btn == kEventMouseButtonSecondary) + event->event_code = EVENT_LBUTTONUP; + + debug(1, "Mouse up!"); + + return true; + break; + + case kEventMouseMoved: + GetEventParameter(theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mouse); + + GetWindowBounds(wref, kWindowContentRgn, &winRect); + if(PtInRect(mouse, &winRect)) + { + CGrafPtr oldPort; + + GetPort(&oldPort); + SetPortWindowPort(wref); + GlobalToLocal(&mouse); + + event->event_code = EVENT_MOUSEMOVE; + event->mouse.x = mouse.h / scaling; + event->mouse.y = mouse.v / scaling; + + //scumm->mouse.x = mouse.h/wm->scale; + //scumm->mouse.y = mouse.v/wm->scale; + } + Point offset = {0, 0}; + ShieldCursor(&winRect, offset); + return true; + break; + } + break; + } + + if(theErr == noErr && theEvent != NULL) { + SendEventToEventTarget (theEvent, theTarget); + ReleaseEvent(theEvent); + } } -UInt8 *buffer[2]; -CmpSoundHeader header; -SndChannelPtr channel; -int size; - -void fill_sound(uint8 *stream, int len) { - scumm->mixWaves((int16*)stream, len>>1); +pascal void sound_callback(SndChannel *chan, SndCommand *cmd_passed) +{ + OSystem_MAC* syst = (OSystem_MAC*)chan->userInfo; + syst->sound_callback(chan, cmd_passed); } -pascal void callBackProc (SndChannel *chan, SndCommand *cmd_passed) +void OSystem_MAC::sound_callback(SndChannel *chan, SndCommand *cmd_passed) { UInt32 fill_me, play_me; SndCommand cmd; @@ -1077,7 +1366,8 @@ pascal void callBackProc (SndChannel *chan, SndCommand *cmd_passed) SndDoCommand(chan, &cmd, 0); memset(buffer[fill_me], 0, size); - fill_sound(buffer[fill_me], size); + //sndProc(parameter, buffer[fill_me], size); + //SoundMixer::on_generate_samples(parameter, buffer[fill_me], size); cmd.cmd = callBackCmd; cmd.param1 = 0; @@ -1086,13 +1376,13 @@ pascal void callBackProc (SndChannel *chan, SndCommand *cmd_passed) SndDoCommand(chan, &cmd, 0); } -void InitSound() +bool OSystem_MAC::set_sound_proc(void *param, SoundProc *proc, byte format) { SndCallBackUPP callback; int sample_size; memset(&header, 0, sizeof(header)); - callback = NewSndCallBackUPP(callBackProc); + callback = NewSndCallBackUPP(::sound_callback); size = ((0x9010 & 0xFF) / 8) * 2048; sample_size = size / 2048 * 8; header.numChannels = 1; @@ -1109,56 +1399,402 @@ void InitSound() channel = (SndChannelPtr)malloc(sizeof(*channel)); channel->qLength = 128; + channel->userInfo = (long)this; SndNewChannel(&channel, sampledSynth, initMono, callback); SndCommand cmd; cmd.cmd = callBackCmd; cmd.param2 = 0; SndDoCommand(channel, &cmd, 0); + + sndProc = proc; + parameter = param; + + return true; } -void main(void) -{ - InitMacStuff(); - SelectGame(); - - wm->_vgabuf = (byte*)calloc(320,200); - - InitScummStuff(); - - scumm->launch(); - - gui.init(scumm); - - setWindowName(scumm); - - InitSound(); - - RunApplicationEventLoop(); - - return; -} -OSystem::OSystem() +/* retrieve the 320x200 bitmap currently being displayed */ +void OSystem_MAC::get_320x200_image(byte *buf) { - last_time = Time(); -} + /* make sure the mouse is gone */ + undraw_mouse(); + + byte *src; + int x,y; -int OSystem::waitTick(int delta) -{ - do - { - updateScreen(scumm); - new_time = Time(); - waitForTimer(scumm, delta * 15 + last_time - new_time); - last_time = Time(); - if(gui._active) - { - gui.loop(scumm); - delta = 5; + switch(_internal_scaling) { + case 1: + memcpy(buf, _gfx_buf, 320*200); + break; + + case 2: + src = (byte*)_gfx_buf; + for(y=0; y!=200; y++) { + for(x=0; x!=320; x++) + buf[x] = src[x*2]; + buf += 320; + src += 320 * 2 * 2; } - sound.on_timer(); - } while(gui._active); + break; + + case 3: + src = (byte*)_gfx_buf; + for(y=0; y!=200; y++) { + for(x=0; x!=320; x++) + buf[x] = src[x*3]; + buf += 320; + src += 320 * 3 * 3; + } + break; + } +} + +void OSystem_MAC::hotswap_gfx_mode() +{ + /* hmm, need to allocate a 320x200 bitmap + * which will contain the "backup" of the screen during the change. + * then draw that to the new screen right after it's setup. + */ + + byte *bak_mem = (byte*)malloc(320*200); + + get_320x200_image(bak_mem); + + unload_gfx_mode(); + load_gfx_mode(); + + force_full = true; + + /* reset palette ? */ + pal = (CTabHandle)NewHandleClear(sizeof(ColorTable) + 255 * sizeof(ColorSpec)); + (*pal)->ctFlags = 0; + (*pal)->ctSize = 255; + + /* blit image */ + copy_rect(bak_mem, 320, 0, 0, 320, 200); + free(bak_mem); + + update_screen(); +} + +uint32 OSystem_MAC::property(int param, Property *value) { + switch(param) { + case PROP_TOGGLE_FULLSCREEN: + _full_screen ^= true; + return 1; + + case PROP_SET_WINDOW_CAPTION: + StringPtr gameText = CToPascal((char*)value->caption); + SetWTitle(wref, gameText); + return 1; + + case PROP_OPEN_CD: + break; + + case PROP_SET_GFX_MODE: + if(value->gfx_mode >= 7) + return 0; + _mode = value->gfx_mode; + hotswap_gfx_mode(); + return 1; + + + case PROP_SHOW_DEFAULT_CURSOR: + break; + + case PROP_GET_SAMPLE_RATE: + return SAMPLES_PER_SEC; + break; + } + + return 0; +} - return(delta); +void OSystem_MAC::quit() { + unload_gfx_mode(); + + QuitApplicationEventLoop(); + ExitToShell(); +} + +void OSystem_MAC::draw_mouse() { + if (_mouse_drawn || !_mouse_visible) + return; + _mouse_drawn = true; + + const int ydraw = _ms_cur.y + _current_shake_pos - _ms_hotspot_y; + const int xdraw = _ms_cur.x - _ms_hotspot_x; + const int w = _ms_cur.w; + const int h = _ms_cur.h; + int x,y; + byte color; + byte *dst, *bak = _ms_backup; + byte *buf = _ms_buf; + + _ms_old.w = w; + _ms_old.h = h; + _ms_old.x = xdraw; + _ms_old.y = ydraw; + + byte *src; + if(_sai_func) + src = (byte*)_tmp_buf; + else + src = _gfx_buf; + + switch(_internal_scaling) { + case 1: + dst = (byte *)src + ydraw * 320 + xdraw; + + for (y = 0; y < h; y++, dst += 320, bak += MAX_MOUSE_W, 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; + } + } + } + } + } + break; + + case 2: + dst = (byte *)src + ydraw * 640 * 2 + xdraw * 2; + + for (y = 0; y < h; y++, dst += 640 * 2, bak += MAX_MOUSE_W * 2, buf += w) { + if ((uint) (ydraw + y) < 200) { + for (x = 0; x < w; x++) { + if ((uint) (xdraw + x) < 320) { + bak[x * 2] = dst[x * 2]; + bak[x * 2 + 1] = dst[x * 2 + 1]; + if ((color = buf[x]) != 0xFF) { + dst[x * 2] = color; + dst[x * 2 + 1] = color; + dst[x * 2 + 640] = color; + dst[x * 2 + 1 + 640] = color; + } + } + } + } + } + break; + + case 3: + dst = (byte *)src + ydraw * 960 * 3 + xdraw * 3; + + for (y = 0; y < h; y++, dst += 960 * 3, bak += MAX_MOUSE_W * 3, buf += w) { + if ((uint) (ydraw + y) < 200) { + for (x = 0; x < w; x++) { + if ((uint) (xdraw + x) < 320) { + bak[x * 3] = dst[x * 3]; + bak[x * 3 + 1] = dst[x * 3 + 1]; + bak[x * 3 + 2] = dst[x * 3 + 2]; + if ((color = buf[x]) != 0xFF) { + dst[x * 3] = color; + dst[x * 3 + 1] = color; + dst[x * 3 + 2] = color; + dst[x * 3 + 960] = color; + dst[x * 3 + 1 + 960] = color; + dst[x * 3 + 2 + 960] = color; + dst[x * 3 + 960 + 960] = color; + dst[x * 3 + 1 + 960 + 960] = color; + dst[x * 3 + 2 + 960 + 960] = color; + } + } + } + } + } + break; + } + + add_dirty_rect(xdraw,ydraw,w,h); +} + +void OSystem_MAC::undraw_mouse() { + if (!_mouse_drawn) + return; + _mouse_drawn = false; + + byte *dst, *bak = _ms_backup; + byte *src; + const int old_mouse_x = _ms_old.x; + const int old_mouse_y = _ms_old.y; + const int old_mouse_w = _ms_old.w; + const int old_mouse_h = _ms_old.h; + int x,y; + + if(_sai_func) + src = (byte*)_tmp_buf; + else + src = _gfx_buf; + + switch(_internal_scaling) { + case 1: + dst = (byte *)src + old_mouse_y * 320 + old_mouse_x; + + for (y = 0; y < old_mouse_h; y++, bak += MAX_MOUSE_W, 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]; + } + } + } + } + break; + + case 2: + dst = (byte *)src + old_mouse_y * 640 * 2 + old_mouse_x * 2; + + for (y = 0; y < old_mouse_h; y++, bak += MAX_MOUSE_W * 2, dst += 640 * 2) { + if ((uint) (old_mouse_y + y) < 200) { + for (x = 0; x < old_mouse_w; x++) { + if ((uint) (old_mouse_x + x) < 320) { + dst[x * 2 + 640] = dst[x * 2] = bak[x * 2]; + dst[x * 2 + 640 + 1] = dst[x * 2 + 1] = bak[x * 2 + 1]; + } + } + } + } + break; + + case 3: + dst = (byte *)src + old_mouse_y * 960 * 3 + old_mouse_x * 3; + + for (y = 0; y < old_mouse_h; y++, bak += MAX_MOUSE_W * 3, dst += 960 * 3) { + if ((uint) (old_mouse_y + y) < 200) { + for (x = 0; x < old_mouse_w; x++) { + if ((uint) (old_mouse_x + x) < 320) { + dst[x * 3 + 960] = dst[x * 3 + 960 + 960] = dst[x * 3] = + bak[x * 3]; + dst[x * 3 + 960 + 1] = dst[x * 3 + 960 + 960 + 1] = + dst[x * 3 + 1] = bak[x * 3 + 1]; + dst[x * 3 + 960 + 2] = dst[x * 3 + 960 + 960 + 2] = + dst[x * 3 + 2] = bak[x * 3 + 2]; + } + } + } + } + break; + } + + add_dirty_rect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h); +} + +void OSystem_MAC::stop_cdrom() { +} + +void OSystem_MAC::play_cdrom(int track, int num_loops, int start_frame, int end_frame) { + /* Reset sync count */ + g_scumm->_vars[g_scumm->VAR_MI1_TIMER] = 0; +} + +bool OSystem_MAC::poll_cdrom() { +} + +void OSystem_MAC::update_cdrom() { +} + + + +/*************************************************************/ +/** Mac specific code ****************************************/ +void OSystem_MAC::set_scaling() { + Rect rectWin; + SetRect(&rectWin, 0, 0, 320 * scaling, 200 * scaling); + HideWindow(wref); + SetWindowBounds(wref, kWindowContentRgn, &rectWin); + RepositionWindow(wref, NULL, kWindowCenterOnMainScreen); + ShowWindow(wref); + blit_rect = rectWin; + + if(_sai_func) + { + Rect r; + + //SetRect(&r, 0, 0, 320, 240); + _sai_buf = (int16*)malloc((320 * 200) * 2 * sizeof(int16)); + + NewGWorldFromPtr(&screenBuf, 16, &blit_rect, NULL, nil, 0, (char *)_sai_buf, blit_rect.right); + } + else + { + _gfx_buf = (byte*)malloc((320 * 200) * scaling * sizeof(byte)); + NewGWorldFromPtr(&screenBuf, 8, &blit_rect, pal, nil, 0, (char *)_gfx_buf, blit_rect.right); + } + + //NewGWorldFromPtr(&screenBuf, 8, &blit_rect, pal, nil, 0, (char *)_gfx_buf, blit_rect.right); + + //if(screenBuf != NULL) + // UpdateGWorld(&screenBuf, 8, &blit_rect, pal, NULL, NULL); +} + +void OSystem_MAC::blit_to_screen() +{ + CopyBits(GetPortBitMapForCopyBits(screenBuf), + GetPortBitMapForCopyBits(GetWindowPort(wref)), &blit_rect, &blit_rect, srcCopy, 0L); +} + +void OSystem_MAC::init_mac_stuff() +{ + Rect rectWin; + + + MenuRef AppleMenu = GetMenu(1000); + InsertMenu(AppleMenu, 0); + SetMenuItemCommandID(AppleMenu, 1, kAboutCmd); + MenuRef FileMenu = GetMenu(1001); + SetMenuItemCommandID(FileMenu, 1, kNewGameCmd); + SetMenuItemCommandID(FileMenu, 2, kOpenGameCmd); + SetMenuItemCommandID(FileMenu, 3, kSaveGameCmd); + SetMenuItemCommandID(FileMenu, 5, kQuitCmd); + DeleteMenuItems(FileMenu, CountMenuItems(FileMenu)-1, 2); + InsertMenu(FileMenu, 0); + MenuRef windMenu; + CreateStandardWindowMenu(0, &windMenu); + InsertMenu(windMenu, 0); + EnableMenuCommand(NULL, kPrefsCmd); + DrawMenuBar(); + + SetRect(&rectWin, 0, 0, 320, 200); + UInt32 WinAttrib = (kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | + kWindowInWindowMenuAttribute | kWindowStandardHandlerAttribute); + + if(noErr != CreateNewWindow(kDocumentWindowClass, WinAttrib, &rectWin, &wref)) + { + //Error("Couldn't create Window!"); + } + + RepositionWindow(wref, NULL, kWindowCenterOnMainScreen); + + Str255 WindowTitle = "\pScummVM"; + SetWTitle(wref, WindowTitle); + + SetPortWindowPort(wref); + //ShowWindow(wref); + + InstallStandardEventHandler(GetWindowEventTarget(wref)); + + //OSStatus err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitEventHandler), 0L, false); + + blit_rect = rectWin; + pal = (CTabHandle)NewHandleClear(sizeof(ColorTable) + 255 * sizeof(ColorSpec)); + (*pal)->ctFlags = 0; + (*pal)->ctSize = 255; + //NewGWorld(&screenBuf, 8, &blit_rect, 0, 0, 0); +} + +void OSystem_MAC::update_rects() +{ + for(int i = 0; i < num_dirty_rects; i++) + { + Rect rec = dirty_rect_list[i]; + + CopyBits(GetPortBitMapForCopyBits(screenBuf), + GetPortBitMapForCopyBits(GetWindowPort(wref)), + &rec, &rec, srcCopy, 0L); + } } \ No newline at end of file diff --git a/mac/scummvm.mcp b/mac/scummvm.mcp index 35a051e06f922f6971902012758acca653fb6e83..f11c90083a2f4602c6d3c26925fc340d035db644 100644 GIT binary patch delta 2983 zcmZWr4Qx}_6@K?QcI-HD?9e2R6N2shLcnBMP$?UbtoeoDm{7(>w1g0n;84dVfi{Cl z$*QWY)@h1+S8iLjDs36vrfCa(2oF(pQHfgCRuH-r(1bSjqm~V{W!BF2zG$ybM(q67gK1VB!2sXr*t5Y4Rt^*ZKA;dN0!n~VpbS_E6a%XO zKM+jT4-`~@)G_=39Y7l30PMUWqjPKv*j9it>VYPp8E64ofo(t-Xa^#|PN0K^LOTkK zYg)PsgDv^R8a%W-jY`+Fe88-LTp&z8W_O#WjV*GYGq>2vWRr2L4w4H2RlKV+ zgMY)B!6R9D#c4FI*_cc-XL^VtyEVqEvxEGmC!7DtS;;56eSEz$#CK)h=H2f7{3BP8 zmt}_d*PI@nlevOl?#|=Ao)ABF+?5O$5jEPg-Hcx;e}{h|J6C+`W9CjqGWfL1${%|v z$@jZ@x$)H+(vy))K0lmeT*>LOHN>I^qM_bILK}(3;zR#qBVQjeotn{+9+?p9iAtTi z92kDYlw;A+zG1#tkjvK3xnvh`o&i_DdPdwV)@x9mr;$4{X|inHr3?pXBPs^A%pkpRW3@ zaCfpM9Q`6($s%KO?c-U7wYpF@P8n`XG7{jMYhA{b`bQ}G1B-EQS4oM{((bVE)i(}4E-fy;^du_S zY&AMlehk>>)cM(SKTgfvVXs*D%&}r))rD@GF?KRbH=e#YvcWjDu$Yk=D`&Ho)GO(% zz?Qn}VDDK{mvh)fi#VUhDupATOURhkmY-J*X!mwek)8?5meOj3pzv zPsT$m6%Xn0&)0Zf)3gjNb|gXHN4zSQnxm3j#OXbwoz2>*WU;iF7J+| zFSP(ZKc9797I#vD8^cCnm&Hq8g#SHJ+pDk9D~^eMy?RIw+QdY!p69FjDN@(Q5+mqi zxlIGemT^N&_v%f0`RghB0sU>py2NZB@~iO$vmZ$e_w{S>>|Y@FhRokMdZJ(NVw**G zzn5uI5AZ)q{onr){sGcy@%PE$chcT}D0Nq!hzwx(QMegWPX82Kt=svW z7^m*pZzA@N9RBt*;4~eYr$bB)=(&a3BFay@D-+(@2jwownzruO;uZ~HS-|pVeqT2DKS{;O?GUpEv3}ZpyPWAiBSYw{M=D{n|dnXGqjEXPt-)qPz1kI8u-AIsyI`sn8!1 zK6n8)=voRHKn zB*8C}s%d?niaOG>UWOBt%ZSqs&60{b-V_P5|7&n^q`rrq_4}mac+ZGQQ>Uw;>U@`W alz`@*7PHXvN^#k>K{@{vo``mh)c*nkT8O9s delta 2945 zcmbVOZE#dq8NTQ4_h;^=*-f%b!X}$0fxw2rl!moU*kltD2z6VuR2X5iNk}%h*-bVd zEtvtF>7dikET?k7Y6p?2PN%g=Z)GcXN))FurBkC~VOmA3otkMG8*SBA(#GfPJ+b_7 z{NX$EocDRpbI$vobMCo!ckz;C@see_&P395jj7)7RY{We(U_^uF$&fWtN_O8W2Syf z25bmOQoT867y%omv*ueZV_;^$l?~U?g%Q0$Mo>ZnrwJaSq(@tK?7_B^ne901C2Cd-IWZ1H359oCLj#70ui7MXa_a}9Y80r zMWk=$D+D@uYS;vDNRmvQ+C~s(Lfd=BlF7Tb`L~5z{k4(4_!w1e0a|Ad(t$~Z?z5HB zm`(BX#UTe87@B-So?ZGPZ@xqoyRY~&jp%u=FgkBrFd271m`turCrckgba^@R`MITfnEEZl9Rzbb8^=S#aH$;7>VBf*|@T1qB* z6TKtj8t+aF<;nVcGu??i%OsMiq0D`m&jM{EX3^nNcW6gqs5do{=}N?dL~1TYy#|0<;0`z-FL>?yvD# zCSJI{;hCkS@0Y889l1{E@l{2ZB)X;~Y2X?4k98jt`e)ZG>YHmz$dPAlbgJHhwR`EC z(}Vdv*eYEXeS2pYe>Lc6rp8-GFPXFI)vX$ zzZN*0ZE2GnWCJwEw89sS^Ud$Q4W$l;>Blk3&C zlXE)um5+&%jat=12U&HFzD3H7^p>Yx#tny;mS#+-eY=6z@yY6`W<^JzKm8P~m?%+C z%@}mq=&1VsnMaLf|LYBt)Nen&K-34%Wp2r@Avf_p@fcOt(ltH3{*jXVy@^5qH;3I+D8!qy=jx@3>9#X@`+@#hJ!pU^A{cduOw6X)mq=rOT6IXBd zlbiXsxt%@2!-qxK!46cAD*my?XH^wzH4~3|rAN&a8#RuP()o>2lBcc(o1e ziXREKtwgoPe6^h`NPvy4BqvCim#pG%Pz$e`XRWLWQOd42iTz=_}6;IwU9a~to3M1I^^c(uEbLdx) zHUWP_eXAL(HTZp%*Cf*!%+bwboG|O#Y_>;kmmNRI znS1455MpO@eHh5;y@QmTM|R4;22Zks;3SKdu#*q*&|u{XC9*^Jt#fzuel zKdmt9RW`L3S!_iJyqaEr9Q-N(vjy2K=9lvGa^~fsnbqKLaZ!>!`WIW^(+dtGxUA_H zKLmf9t2mPr%-;{)t{^DV(%;E*y~9|)V=q~8y2)nwBr;9}plH`pOQy&8{AdPPe= ze+2wp0H*9_)BUpBM`UbCe@z?katz8fF5~~lF?Kbd-~hHirxj>6L-*t8Y`rEp||EB4#%Ph_HTCQuyH?(*sI6nhe;fw49*XtfY za73%`Edc)qS0$hcnLx}ZSm0M@PU($5jX*Qccl`4cynmpVGJ}cxYw!o)P;9s5YNlh>5 zf%Y>^x5t@(5YtcM*Vdy|e?10??-}L@vFISCJMKWB>8b5U!C&SouFwz$;jy)p>Ro2E3XdCQW{mDf@VxG~%G9|0D~}F9+;9 z53)^Mck;Vcscj?0Pl&&Su!0avbG?ACvryA_oC5zfSE0w)iM-A)qgdyKi{KnEWsc23 S_uLgjFsRj^z6bnuK>9b~GpF|e