diff options
-rw-r--r-- | mac/Carbon.r | 8 | ||||
-rw-r--r-- | mac/mac.cpp | 2252 | ||||
-rw-r--r-- | mac/scummvm.mcp | bin | 158716 -> 158716 bytes |
3 files changed, 1451 insertions, 809 deletions
diff --git a/mac/Carbon.r b/mac/Carbon.r index 5104573275..a296c97b26 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 0f89434ade..1339e3b031 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 <Carbon.h> -#include <CarbonEvents.h> - #include <sioux.h> -#include <string.h> -#include <assert.h> - #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; -} - - -// Fast macro for testing key codes. -#define KeyCode(x,y) (BitTst(&(x), (y) ^ 0x07)) - -Boolean IsKeyDown(unsigned short key) -{ - GetKeys(fKeyMap); // get info - return (KeyCode(fKeyMap, key)); + 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; -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(); + end = str + *str; + q = (p=str) + 1; -void Quit() -{ - QuitApplicationEventLoop(); - ExitToShell(); -} + while (p < end) + *p++ = *q++; + *p = '\0'; -void Error(const char* msg) -{ - - //DebugStr((const unsigned char*)msg); - //ExitToShell(); + return((char *)str); } const EventTypeSpec kCmdEvents[] = @@ -178,363 +273,157 @@ 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; -} + kNewGameCmd = 'newG', + kQuitCmd = kHICommandQuit, + kOpenGameCmd = 'opnG', + kSaveGameCmd = 'savG', + kPrefsCmd = kHICommandPreferences, + kAboutCmd = 'abtG' +}; -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; -} +ControlRef radioGroupRef, musicVolumeSlider, masterVolumeSlider; +char *gameTitle; +ControlRef popUpControlRef, checkBoxControlRef; -static pascal OSStatus EventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* userData ) +OSStatus prefsEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef, + 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; -} + OSStatus result = eventNotHandledErr; + UInt32 eventClass; + UInt32 eventKind; + ControlRef controlRef; + ControlID controlID; -pascal void DoGameLoop(EventLoopTimerRef theTimer, void *userData) -{ - scumm->mainRun(); - QuitApplicationEventLoop(); -} + eventClass = GetEventClass(eventRef); + eventKind = GetEventKind(eventRef); -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); + if(eventClass == kEventClassControl) + { + if(eventKind == kEventControlHit) + { + GetEventParameter(eventRef,kEventParamDirectObject,typeControlRef,NULL, + sizeof(ControlRef),NULL,&controlRef); - 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); + GetControlID(controlRef,&controlID); + if(controlID.id == 'okay') + { + /*scumm->_noSubtitles = (Boolean)!GetControlValue(checkBoxControlRef); + short scale = GetControlValue(radioGroupRef); + if(scale != scumm->_scale) + wm->ChangeScaling(scale); + short music_vol = GetControlValue(musicVolumeSlider); + if(music_vol != sound.get_music_volume()) + sound.set_music_volume(music_vol); + short master_vol = GetControlValue(masterVolumeSlider); + if(master_vol != sound.get_master_volume()) + sound.set_master_volume(master_vol);*/ + QuitAppModalLoopForWindow((WindowRef)userData); + DisposeWindow((WindowRef)userData); + result = noErr; + } + } + } } -void WndMan::ChangeScaling(short scaling) +void Preferences() { - 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); + WindowRef prefsWin; + OSStatus osError = noErr; + Rect rect = { 0,0,210,300 }; + Rect okButtonRect; + ControlID controlID; + ControlRef controlRef; + EventTypeSpec dialogEvents[] = { kEventClassControl, kEventControlHit }; + + osError = CreateNewWindow(kMovableModalWindowClass,kWindowStandardHandlerAttribute,&rect, &prefsWin); + SetWTitle(prefsWin, "\pPreferences"); + RepositionWindow(prefsWin,FrontWindow(),kWindowAlertPositionOnMainScreen); + SetThemeWindowBackground(prefsWin,kThemeBrushDialogBackgroundActive,false); + CreateRootControl(prefsWin,&controlRef); - SetWindowBounds(wPtr, kWindowContentRgn, &rectWin); - RepositionWindow(wPtr, NULL, kWindowCenterOnMainScreen); - dstRect = rectWin; -} - -bool WndMan::handleMessage() -{ - EventRef theEvent; - EventTargetRef theTarget; - OSStatus theErr; + SetRect(&rect, 5, 5, 150, 21); - 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; + CreateStaticTextControl(prefsWin, &rect, CFSTR("ScummVM Preferences"), NULL, &controlRef); + AutoEmbedControl(controlRef, prefsWin); - if(s->_fastMode&2) - delay = 0; - else if(s->_fastMode&1) - delay = 10; + SetRect(&okButtonRect, 225, 180, 295, 200); - 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; - } + CreatePushButtonControl(prefsWin,&okButtonRect,CFSTR("OK"),&controlRef); + SetWindowDefaultButton(prefsWin,controlRef); + controlID.id = 'okay'; + SetControlID(controlRef,&controlID); + AutoEmbedControl(controlRef,prefsWin); + + SetRect(&rect, 150, 35, 260, 51); + + CreateCheckBoxControl(prefsWin,&rect, CFSTR("Subtitles"), 1, true, &checkBoxControlRef); + AutoEmbedControl(checkBoxControlRef, prefsWin); + + //if(scumm->_noSubtitles) + SetControlValue(checkBoxControlRef, false); + + OffsetRect(&rect, 0, 20); + + CreateCheckBoxControl(prefsWin,&rect, CFSTR("Fullscreen"), 0, true, &controlRef); + AutoEmbedControl(controlRef, prefsWin); + DeactivateControl(controlRef); + + Rect RadioGroupRect; + SetRect(&RadioGroupRect, 5, 35, 120, 100); + CreateRadioGroupControl(prefsWin, &RadioGroupRect, &radioGroupRef); + AutoEmbedControl(radioGroupRef, prefsWin); + + ControlRef radioButton; + + Rect RadioButtonRect; + SetRect(&RadioButtonRect, 5, 35, 120, 51); + CreateRadioButtonControl(prefsWin, &RadioButtonRect, CFSTR("Scaling 1x"), 0, true, &radioButton); + AutoEmbedControl(radioButton, prefsWin); + + OffsetRect(&RadioButtonRect, 0, 20); + CreateRadioButtonControl(prefsWin, &RadioButtonRect, CFSTR("Scaling 2x"), 0, true, &radioButton); + AutoEmbedControl(radioButton, prefsWin); + + OffsetRect(&RadioButtonRect, 0, 20); + CreateRadioButtonControl(prefsWin, &RadioButtonRect, CFSTR("Scaling 3x"), 0, true, &radioButton); + AutoEmbedControl(radioButton, prefsWin); + + //SetControlValue(radioGroupRef, scumm->_scale); + + SetRect(&rect, 5, 110, 175, 146); + + CreateSliderControl(prefsWin, &rect, 100, 1, 100, + kControlSliderPointsDownOrRight, 10, false, NULL, &musicVolumeSlider); + AutoEmbedControl(musicVolumeSlider, prefsWin); + + OffsetRect(&rect, 0, 36); + + CreateSliderControl(prefsWin, &rect, 100, 1, 100, + kControlSliderPointsDownOrRight, 10, false, NULL, &masterVolumeSlider); + AutoEmbedControl(masterVolumeSlider, prefsWin); + + OffsetRect(&rect, 180, -36); + + CreateStaticTextControl(prefsWin, &rect, CFSTR("Music Volume"), NULL, &controlRef); + AutoEmbedControl(controlRef, prefsWin); - 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); + OffsetRect(&rect, 0, 36); + + CreateStaticTextControl(prefsWin, &rect, CFSTR("Master Volume"), NULL, &controlRef); + AutoEmbedControl(controlRef, prefsWin); + + InstallWindowEventHandler(prefsWin, NewEventHandlerUPP((EventHandlerProcPtr) prefsEventHandler), + GetEventTypeCount(dialogEvents),dialogEvents,prefsWin,NULL); + ShowWindow(prefsWin); + osError = RunAppModalLoopForWindow(prefsWin); } -ControlRef popUpControlRef, checkBoxControlRef; -char *gameTitle; - void LaunchGame(int id) { switch(id) @@ -546,7 +435,7 @@ void LaunchGame(int id) case 7: gameTitle = "zak256"; break; - + case 8: gameTitle = "loom"; break; @@ -556,47 +445,68 @@ void LaunchGame(int id) break; case 10: - gameTitle = "loomcd"; + gameTitle = "monkeyVGA"; break; case 11: - gameTitle = "monkey"; + gameTitle = "loomcd"; break; case 12: - gameTitle = "monkey2"; + gameTitle = "monkey"; break; case 13: - gameTitle = "atlantis"; + gameTitle = "monkey1"; break; case 14: - gameTitle = "playfate"; + gameTitle = "monkey2"; break; case 15: - gameTitle = "tentacle"; + gameTitle = "atlantis"; break; case 16: - gameTitle = "dottdemo"; + gameTitle = "playfate"; break; case 17: - gameTitle = "samnmax"; + gameTitle = "tentacle"; break; case 18: - gameTitle = "snmdemo"; + gameTitle = "dottdemo"; break; case 19: - gameTitle = "ft"; + 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; } } @@ -616,6 +526,7 @@ OSStatus dialogEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eve { if(eventKind == kEventControlHit) { + GetEventParameter(eventRef,kEventParamDirectObject,typeControlRef,NULL, sizeof(ControlRef),NULL,&controlRef); @@ -624,7 +535,6 @@ OSStatus dialogEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eve { QuitAppModalLoopForWindow((WindowRef)userData); LaunchGame(GetControlValue(popUpControlRef)); - wm->scale = 2; DisposeWindow((WindowRef)userData); result = noErr; @@ -640,7 +550,7 @@ OSStatus dialogEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eve return result; } -void SelectGame() +char* SelectGame() { WindowRef aboutWin; OSStatus osError = noErr; @@ -652,6 +562,18 @@ void SelectGame() Rect checkboxRect = { 36, 10, 50, 80 }; EventTypeSpec dialogEvents[] = { kEventClassControl, kEventControlHit }; + InitCursor(); + + SIOUXSettings.autocloseonquit = true; + SIOUXSettings.asktosaveonclose = false; + SIOUXSettings.showstatusline = false; + SIOUXSettings.fontsize = 9; + GetFNum("\pMonaco",&SIOUXSettings.fontid); + SIOUXSettings.standalone = false; + 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); @@ -663,7 +585,7 @@ void SelectGame() controlID.id = 'okay'; SetControlID(controlRef,&controlID); AutoEmbedControl(controlRef,aboutWin); - + OffsetRect(&pushButtonRect, -100, 0); CreatePushButtonControl(aboutWin,&pushButtonRect,CFSTR("Cancel"),&controlRef); SetWindowCancelButton(aboutWin,controlRef); @@ -674,393 +596,760 @@ void SelectGame() 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; } -static void DrawCenteredStringAt(Str255 theString, short yLocation) -{ - Rect portRect; - CGrafPtr thePort = GetQDGlobalsThePort(); +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; - GetPortBounds(thePort, &portRect); - - MoveTo(portRect.left + ((portRect.right-portRect.left) >> 1) - - (StringWidth(theString) >> 1), yLocation); - DrawString(theString); + /* Macintosh init */ + syst->init_mac_stuff(); + return syst; } -void DrawAboutText(WindowRef win) +uint32 OSystem_MAC::autosave(uint32 interval) { - CGrafPtr oldPort; - - GetPort(&oldPort); - SetPortWindowPort(win); + g_scumm->_doAutosave = true; + + return interval; +} + +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; - TextFont(systemFont); - TextSize(12); + (*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; + } - DrawCenteredStringAt("\pAbout ScummVMÉ", 32); + CTabChanged(pal); - TextFont(applFont); - TextSize(9); + if(_sai_func) + UpdateGWorld(&screenBuf, 16, &blit_rect, NULL, NULL, 0); + else + UpdateGWorld(&screenBuf, 8, &blit_rect, pal, NULL, 0); - DrawCenteredStringAt("\pScummVM", 50); - DrawCenteredStringAt("\pLet's you run all your favourite Scumm Games", 65); - DrawCenteredStringAt("\pon MacOS 9 and X", 80); + if(start < _palette_changed_first) + _palette_changed_first = start; - SetPort(oldPort); + if(start + num > _palette_changed_last) + _palette_changed_last = start + num; } -OSStatus aboutEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef, - void *userData) -{ - OSStatus result = eventNotHandledErr; - UInt32 eventClass; - UInt32 eventKind; - ControlRef controlRef; - ControlID controlID; +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; - eventClass = GetEventClass(eventRef); - eventKind = GetEventKind(eventRef); + 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; + } - if(eventClass == kEventClassControl) - { - if(eventKind == kEventControlHit) - { - GetEventParameter(eventRef,kEventParamDirectObject,typeControlRef,NULL, - sizeof(ControlRef),NULL,&controlRef); + _mode_flags = DF_WANT_RECT_OPTIM | DF_REAL_8BIT; + } + + set_scaling(); +} - 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 OSystem_MAC::unload_gfx_mode() { + //warning("STUB: unload_gfx_mode()"); /* FIXME: Must free data here */ + } -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); +void OSystem_MAC::init_size(uint w, uint h) { + //if (w != SCREEN_WIDTH && h != SCREEN_HEIGHT) + // error("320x200 is the only game resolution supported"); - DrawAboutText(aboutWin); + 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(); - 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); + byte *dst = (byte*)buf + y * SCREEN_WIDTH + x; + do { + memcpy(dst, buf, w); + dst += SCREEN_WIDTH; + buf += pitch; + } while(--h); } -ControlRef radioGroupRef, musicVolumeSlider, masterVolumeSlider; +void OSystem_MAC::add_dirty_rect(int x, int y, int w, int h) { + if (force_full) + return; -OSStatus prefsEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef, - void *userData) -{ - OSStatus result = eventNotHandledErr; - UInt32 eventClass; - UInt32 eventKind; - ControlRef controlRef; - ControlID controlID; + 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; + } - eventClass = GetEventClass(eventRef); - eventKind = GetEventKind(eventRef); + /* 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; + } - if(eventClass == kEventClassControl) - { - if(eventKind == kEventControlHit) - { - GetEventParameter(eventRef,kEventParamDirectObject,typeControlRef,NULL, - sizeof(ControlRef),NULL,&controlRef); + r->left = x; + r->top = y; + r->right = x + w; + r->bottom = y + h; + } +} - GetControlID(controlRef,&controlID); - if(controlID.id == 'okay') - { - scumm->_noSubtitles = (Boolean)!GetControlValue(checkBoxControlRef); - short scale = GetControlValue(radioGroupRef); - if(scale != scumm->_scale) - wm->ChangeScaling(scale); - short music_vol = GetControlValue(musicVolumeSlider); - if(music_vol != sound.get_music_volume()) - sound.set_music_volume(music_vol); - short master_vol = GetControlValue(masterVolumeSlider); - if(master_vol != sound.get_master_volume()) - sound.set_master_volume(master_vol); - QuitAppModalLoopForWindow((WindowRef)userData); - DisposeWindow((WindowRef)userData); - result = noErr; - } - } - } +#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 Preferences() -{ - WindowRef prefsWin; - OSStatus osError = noErr; - Rect rect = { 0,0,210,300 }; - Rect okButtonRect; - ControlID controlID; - ControlRef controlRef; - EventTypeSpec dialogEvents[] = { kEventClassControl, kEventControlHit }; - - osError = CreateNewWindow(kMovableModalWindowClass,kWindowStandardHandlerAttribute,&rect, &prefsWin); - SetWTitle(prefsWin, "\pPreferences"); - RepositionWindow(prefsWin,FrontWindow(),kWindowAlertPositionOnMainScreen); - SetThemeWindowBackground(prefsWin,kThemeBrushDialogBackgroundActive,false); - CreateRootControl(prefsWin,&controlRef); - - SetRect(&rect, 5, 5, 150, 21); - - CreateStaticTextControl(prefsWin, &rect, CFSTR("ScummVM Preferences"), NULL, &controlRef); - AutoEmbedControl(controlRef, prefsWin); - - SetRect(&okButtonRect, 225, 180, 295, 200); - - CreatePushButtonControl(prefsWin,&okButtonRect,CFSTR("OK"),&controlRef); - SetWindowDefaultButton(prefsWin,controlRef); - controlID.id = 'okay'; - SetControlID(controlRef,&controlID); - AutoEmbedControl(controlRef,prefsWin); - - SetRect(&rect, 150, 35, 260, 51); - - CreateCheckBoxControl(prefsWin,&rect, CFSTR("Subtitles"), 1, true, &checkBoxControlRef); - AutoEmbedControl(checkBoxControlRef, prefsWin); - - if(scumm->_noSubtitles) - SetControlValue(checkBoxControlRef, false); - - OffsetRect(&rect, 0, 20); - - CreateCheckBoxControl(prefsWin,&rect, CFSTR("Fullscreen"), 0, true, &controlRef); - AutoEmbedControl(controlRef, prefsWin); - DeactivateControl(controlRef); - - Rect RadioGroupRect; - SetRect(&RadioGroupRect, 5, 35, 120, 100); - CreateRadioGroupControl(prefsWin, &RadioGroupRect, &radioGroupRef); - AutoEmbedControl(radioGroupRef, prefsWin); - - ControlRef radioButton; - - Rect RadioButtonRect; - SetRect(&RadioButtonRect, 5, 35, 120, 51); - CreateRadioButtonControl(prefsWin, &RadioButtonRect, CFSTR("Scaling 1x"), 0, true, &radioButton); - AutoEmbedControl(radioButton, prefsWin); - - OffsetRect(&RadioButtonRect, 0, 20); - CreateRadioButtonControl(prefsWin, &RadioButtonRect, CFSTR("Scaling 2x"), 0, true, &radioButton); - AutoEmbedControl(radioButton, prefsWin); - - OffsetRect(&RadioButtonRect, 0, 20); - CreateRadioButtonControl(prefsWin, &RadioButtonRect, CFSTR("Scaling 3x"), 0, true, &radioButton); - AutoEmbedControl(radioButton, prefsWin); - - SetControlValue(radioGroupRef, scumm->_scale); - - SetRect(&rect, 5, 110, 175, 146); - - CreateSliderControl(prefsWin, &rect, sound.get_music_volume(), 1, 100, - kControlSliderPointsDownOrRight, 10, false, NULL, &musicVolumeSlider); - AutoEmbedControl(musicVolumeSlider, prefsWin); - - OffsetRect(&rect, 0, 36); - - CreateSliderControl(prefsWin, &rect, sound.get_master_volume(), 1, 100, - kControlSliderPointsDownOrRight, 10, false, NULL, &masterVolumeSlider); - AutoEmbedControl(masterVolumeSlider, prefsWin); - - OffsetRect(&rect, 180, -36); - - CreateStaticTextControl(prefsWin, &rect, CFSTR("Music Volume"), NULL, &controlRef); - AutoEmbedControl(controlRef, prefsWin); + +void OSystem_MAC::add_dirty_rgn_auto(const byte *buf) { + assert( ((uint32)buf & 3) == 0); - OffsetRect(&rect, 0, 36); - - CreateStaticTextControl(prefsWin, &rect, CFSTR("Master Volume"), NULL, &controlRef); - AutoEmbedControl(controlRef, prefsWin); - - InstallWindowEventHandler(prefsWin, NewEventHandlerUPP((EventHandlerProcPtr) prefsEventHandler), - GetEventTypeCount(dialogEvents),dialogEvents,prefsWin,NULL); - ShowWindow(prefsWin); - osError = RunAppModalLoopForWindow(prefsWin); -} + /* generate a table of the checksums */ + mk_checksums(buf); -/* 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;} +if (!cksum_valid) { + force_full = true; + cksum_valid = true; + } -void launcherLoop() { - /* No launcher an Mac yet, probably there won't ever be one, as */ - /* there is a nice Mac-like Launcher already. */ + /* 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 BoxTest(int num) { -} +void OSystem_MAC::update_screen() { +#if 0 + /* First make sure the mouse is drawn, if it should be drawn. */ + draw_mouse(); -void setShakePos(Scumm *s, int shake_pos) {} + 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; + } -void drawMouse(int xdraw, int ydraw, int w, int h, byte *buf, bool visible) -{ - int x, y; - byte *mask, *src, *dst; - byte color; - Point mouse; - GrafPtr oldPort; - Rect r, r2; + /* 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(visible) + if (num_dirty_rects > 0) { - GWorldPtr gw, gw2; - - 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; - } + 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; - SetRect(&r, 0, 0, w, h); + 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); + } - 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); + 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; -void InitMacStuff() -{ - InitCursor(); + _ms_hotspot_x = hotspot_x; + _ms_hotspot_y = hotspot_y; + + _ms_buf = (byte*)buf; + + undraw_mouse(); +} - SIOUXSettings.autocloseonquit = true; - SIOUXSettings.asktosaveonclose = false; - SIOUXSettings.showstatusline = false; - SIOUXSettings.fontsize = 9; - GetFNum("\pMonaco",&SIOUXSettings.fontid); - SIOUXSettings.standalone = false; - SIOUXSettings.setupmenus = false; - SIOUXSettings.toppixel = 40; - SIOUXSettings.leftpixel = 5; +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; -void InitScummStuff() -{ - detector.detectMain(2, &gameTitle); + Microseconds(&ms); + return(ms.lo / 1000); +} - 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; +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); } -void setWindowName(Scumm *scumm) +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; -UInt8 *buffer[2]; -CmpSoundHeader header; -SndChannelPtr channel; -int size; + 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); + } +} -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) + +/* retrieve the 320x200 bitmap currently being displayed */ +void OSystem_MAC::get_320x200_image(byte *buf) { - InitMacStuff(); - SelectGame(); + /* make sure the mouse is gone */ + undraw_mouse(); - wm->_vgabuf = (byte*)calloc(320,200); + byte *src; + int x,y; + + 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; + } + 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. + */ - InitScummStuff(); + 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; - scumm->launch(); + /* 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; - gui.init(scumm); + case PROP_GET_SAMPLE_RATE: + return SAMPLES_PER_SEC; + break; + } - setWindowName(scumm); + return 0; +} + +void OSystem_MAC::quit() { + unload_gfx_mode(); + + QuitApplicationEventLoop(); + ExitToShell(); +} + +void OSystem_MAC::draw_mouse() { + if (_mouse_drawn || !_mouse_visible) + return; + _mouse_drawn = true; - InitSound(); + 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; - RunApplicationEventLoop(); + 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; - return; + 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() { } -OSystem::OSystem() + + +/*************************************************************/ +/** 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() { - last_time = Time(); + 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); } -int OSystem::waitTick(int delta) +void OSystem_MAC::update_rects() { - do + for(int i = 0; i < num_dirty_rects; i++) { - updateScreen(scumm); - new_time = Time(); - waitForTimer(scumm, delta * 15 + last_time - new_time); - last_time = Time(); - if(gui._active) - { - gui.loop(scumm); - delta = 5; - } - sound.on_timer(); - } while(gui._active); + Rect rec = dirty_rect_list[i]; - return(delta); + 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 Binary files differindex 35a051e06f..f11c90083a 100644 --- a/mac/scummvm.mcp +++ b/mac/scummvm.mcp |