diff options
author | Lionel Ulmer | 2002-04-20 17:41:42 +0000 |
---|---|---|
committer | Lionel Ulmer | 2002-04-20 17:41:42 +0000 |
commit | c673d1c760b43e7e011c0eaffd6028390a860438 (patch) | |
tree | c40a4d07b2927a9e75ad4326f9e4d6f4720f81ce | |
parent | 32d69e8c020271bfa6a3f3ab65aa9f17cc441d81 (diff) | |
download | scummvm-rg350-c673d1c760b43e7e011c0eaffd6028390a860438.tar.gz scummvm-rg350-c673d1c760b43e7e011c0eaffd6028390a860438.tar.bz2 scummvm-rg350-c673d1c760b43e7e011c0eaffd6028390a860438.zip |
Commit of the X11 driver using the new OSystem interface. Plus some warning fixes and gameDetector hacks.
svn-id: r4024
-rw-r--r-- | Makefile.x11 | 46 | ||||
-rw-r--r-- | gameDetector.cpp | 54 | ||||
-rw-r--r-- | script_v1.cpp | 1 | ||||
-rw-r--r-- | scummsys.h | 10 | ||||
-rw-r--r-- | simon/simon.h | 2 | ||||
-rw-r--r-- | sound/mididrv.cpp | 2 | ||||
-rw-r--r-- | system.h | 14 | ||||
-rw-r--r-- | x11.cpp | 977 |
8 files changed, 559 insertions, 547 deletions
diff --git a/Makefile.x11 b/Makefile.x11 new file mode 100644 index 0000000000..6028ebb451 --- /dev/null +++ b/Makefile.x11 @@ -0,0 +1,46 @@ +# $Header$ + +CC = gcc +CFLAGS = -g -O -Wall -Wstrict-prototypes -Wuninitialized -Wno-long-long -Wno-multichar -DCOMPRESSED_SOUND_FILE +DEFINES = -DUNIX_X11 +LDFLAGS := -L/usr/X11R6/lib -L/usr/local/lib +INCLUDES:= -I/usr/X11R6/include -I./ -I./sound -I/usr/local/include +CPPFLAGS= $(DEFINES) $(INCLUDES) + +# Add -lmad for -DCOMPRESSED_SOUND_FILE +LIBS = -lXext -lX11 -lncurses -lm -lmad -lpthread +ZIPFILE := scummvm-`date '+%Y-%m-%d'`.zip + +INCS = scumm.h scummsys.h stdafx.h + +OBJS = actor.o boxes.o costume.o gfx.o object.o resource.o \ + saveload.o script.o scummvm.o sound.o string.o \ + sys.o verbs.o script_v1.o script_v2.o debug.o gui.o \ + sound/imuse.o sound/fmopl.o sound/mixer.o debugrl.o \ + akos.o vars.o insane.o gameDetector.o init.o mp3_cd.o\ + v3/resource_v3.o v4/resource_v4.o 2xsai.o main.o \ + simon/midi.o simon/simon.o simon/simonsys.o sound/mididrv.o x11.o + +DISTFILES=$(OBJS:.o=.cpp) Makefile scumm.h scummsys.h stdafx.h stdafx.cpp \ + windows.cpp debugrl.h whatsnew.txt readme.txt copying.txt \ + scummvm.dsp scummvm.dsw sound/fmopl.h gui.h sound.h + +.cpp.o: + $(CC) $(CFLAGS) $(CPPFLAGS) -c $(<) -o $*.o + +all: scummvm + +scummvm: $(OBJS) + $(CC) $(LDFLAGS) -o $(@) $(OBJS) $(LIBS) + +$(OBJS): Makefile + +clean: + rm -f $(OBJS) scummvm + +dist: + rm -f $(ZIPFILE) + zip -q $(ZIPFILE) $(DISTFILES) + +check: +$(OBJS): $(INCS) diff --git a/gameDetector.cpp b/gameDetector.cpp index 91b118ff5f..416d4a439d 100644 --- a/gameDetector.cpp +++ b/gameDetector.cpp @@ -340,12 +340,21 @@ int GameDetector::detectMain(int argc, char **argv) _noSubtitles = 0; // use by default - should this depend on soundtrack? _gfx_mode = GFX_DOUBLESIZE; - _gfx_driver = GD_AUTO; - _sfx_volume = 100; -#ifdef USE_NULL_DRIVER +#if defined(USE_NULL_DRIVER) _gfx_driver = GD_NULL; +#elif defined(__DC__) + _gfx_driver = GD_DC; +#elif defined(UNIX_X11) + _gfx_driver = GD_X; +#elif defined(__MORPHOS__) + _gfx_driver = GD_MORPHOS; +#elif defined(WIN32_WCE) + _gfx_driver = GD_WINCE; +#else + /* SDL is the default driver for now */ + _gfx_driver = GD_SDL; #endif _gameDataPath = NULL; @@ -396,41 +405,26 @@ int GameDetector::detectMain(int argc, char **argv) } OSystem *GameDetector::createSystem() { -#ifdef __MORPHOS__ - _gfx_driver = GD_MORPHOS; -#endif /* auto is to use SDL */ switch(_gfx_driver) { -#ifdef __DC__ - case GD_AUTO: +#if defined(UNIX_X11) + case GD_X: + return OSystem_X11_create(); +#elif defined(__DC__) + case GD_DC: return OSystem_Dreamcast_create(); -#else - case GD_SDL: - case GD_AUTO: -#ifdef _WIN32_WCE +#elif defined(WIN32_WCE) + case GD_WINCE: return OSystem_WINCE3_create(); -#endif -#if !defined(__MORPHOS__) - return OSystem_SDL_create(_gfx_mode, _fullScreen); -#endif - case GD_WIN32: - /* not implemented yet */ - break; - - case GD_X: - /* not implemented yet */ - break; - +#elif defined(__MORPHOS__) case GD_MORPHOS: -#if defined(__MORPHOS__) return OSystem_MorphOS_create(_gameId, _gfx_mode, _fullScreen); -#endif - break; - -#ifdef USE_NULL_DRIVER +#elif defined(USE_NULL_DRIVER) case GD_NULL: return OSystem_NULL_create(); -#endif +#else + case GD_SDL: + return OSystem_SDL_create(_gfx_mode, _fullScreen); #endif } diff --git a/script_v1.cpp b/script_v1.cpp index 0bd9e47c6b..51362bc9d9 100644 --- a/script_v1.cpp +++ b/script_v1.cpp @@ -911,7 +911,6 @@ void Scumm::o5_cursorCommand() { int i, j, k; int16 table[16]; - byte origop = _opcode; switch ((_opcode = fetchScriptByte()) & 0x1F) { case 1: /* cursor show */ _cursorState = 1; diff --git a/scummsys.h b/scummsys.h index e19957555f..c095c7295c 100644 --- a/scummsys.h +++ b/scummsys.h @@ -102,12 +102,19 @@ typedef signed long int32; #define START_PACK_STRUCTS pack (push,1) #define END_PACK_STRUCTS pack(pop) -#elif (defined(UNIX) || defined(__APPLE__)) +#elif (defined(UNIX) || defined(__APPLE__) || defined(UNIX_X11)) #define scumm_stricmp strcasecmp #define CHECK_HEAP +#ifdef UNIX_X11 + +/* You need to set those manually */ +#define SCUMM_LITTLE_ENDIAN +/* #define SCUMM_NEED_ALIGNMENT */ + +#else /* need this for the SDL_BYTEORDER define */ #include <SDL_byteorder.h> @@ -119,6 +126,7 @@ typedef signed long int32; #else #error Neither SDL_BIG_ENDIAN nor SDL_LITTLE_ENDIAN is set. #endif +#endif #define FORCEINLINE inline #define CDECL diff --git a/simon/simon.h b/simon/simon.h index d44271dcfb..2a3a20230f 100644 --- a/simon/simon.h +++ b/simon/simon.h @@ -220,7 +220,7 @@ struct VgaFile1Struct0x6 { }; /* dummy typedefs to make it compile in *nix */ -#if defined(UNIX) || defined(__MORPHOS__) || defined(__DC__) +#if defined(UNIX) || defined(UNIX_X11) || defined(__MORPHOS__) || defined(__DC__) typedef void* HMIDISTRM; typedef void* HMIDIOUT; typedef uint32 UINT; diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp index 405242f50c..5e59e3f81f 100644 --- a/sound/mididrv.cpp +++ b/sound/mididrv.cpp @@ -781,7 +781,7 @@ void MidiDriver::midiInitNull() #ifdef WIN32 #include <winsock.h> -#elif defined(UNIX) +#elif (defined(UNIX) || defined(UNIX_X11)) #include <sys/time.h> #include <unistd.h> #include <sys/types.h> @@ -122,6 +122,7 @@ OSystem *OSystem_NULL_create(); OSystem *OSystem_MorphOS_create(int game_id, int gfx_driver, bool full_screen); OSystem *OSystem_Dreamcast_create(); OSystem *OSystem_WINCE3_create(); +OSystem *OSystem_X11_create(); enum { GFX_NORMAL = 0, @@ -135,13 +136,12 @@ enum { /* Graphics drivers */ enum { - GD_AUTO = 0, - GD_SDL = 1, - GD_WIN32 = 2, - GD_X = 3, - GD_NULL = 4, - GD_MORPHOS = 5, - GD_WINCE = 6 + GD_NULL = 0, + GD_SDL, + GD_X, + GD_MORPHOS, + GD_WINCE, + GD_DC }; @@ -23,8 +23,8 @@ #include "stdafx.h" #include "scumm.h" -#include "gui.h" -#include "cdmusic.h" +#include "mididrv.h" +#include "gameDetector.h" #include <sys/time.h> #include <unistd.h> @@ -45,52 +45,127 @@ #include <fcntl.h> #include <sys/ioctl.h> -Scumm scumm; -ScummDebugger debugger; -Gui gui; -IMuse sound; -SOUND_DRIVER_TYPE snd_driv; -static unsigned char *local_fb; - -static int window_width, window_height; -static int scumm_x, scumm_y; - -static int x11_socket = -1; -static Display *display; -static int screen; -static Window window; -static GC black_gc; -static XImage *image; -static pthread_t sound_thread; -static int old_mouse_x, old_mouse_y; -static int old_mouse_h, old_mouse_w; -static bool has_mouse, hide_mouse; - -static unsigned int scale; -static int fake_right_mouse = 0; -static int report_presses = 1; -static int current_shake_pos = 0; - -#define MAX_NUMBER_OF_DIRTY_SQUARES 32 +class OSystem_X11 : public OSystem { +public: + // Set colors of the palette + void set_palette(const byte *colors, uint start, uint num); + + // 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); + + // 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(); + + // Play cdrom audio track + void play_cdrom(int track, int num_loops, int start_frame, int end_frame); + + // Stop cdrom audio track + void stop_cdrom(); + + // Update cdrom audio status + void update_cdrom(); + + // Quit + void quit(); + + // Set a parameter + uint32 property(int param, uint32 value); + + static OSystem *create(int gfx_mode, bool full_screen); + +private: + OSystem_X11(); + + typedef struct { + int x, y, w, h; + } dirty_square; + + void create_empty_cursor(); + void undraw_mouse(); + void draw_mouse(); + void update_screen_helper(const dirty_square * d, dirty_square * dout); + + unsigned char *local_fb; + + int window_width, window_height; + int scumm_x, scumm_y; + + unsigned short palette[256]; + bool _palette_changed; + Display *display; + int screen; + Window window; + GC black_gc; + XImage *image; + pthread_t sound_thread; + + int fake_right_mouse; + int report_presses; + int current_shake_pos; + struct timeval start_time; + + enum { + MAX_NUMBER_OF_DIRTY_SQUARES = 32, + BAK_WIDTH = 40, + BAK_HEIGHT = 40 + }; + dirty_square ds[MAX_NUMBER_OF_DIRTY_SQUARES]; + int num_of_dirty_square; + + typedef struct { + int x, y; + int w, h; + int hot_x, hot_y; + } mouse_state; + mouse_state old_state, cur_state; + const byte *_ms_buf; + byte _ms_backup[BAK_WIDTH * BAK_HEIGHT]; + bool _mouse_drawn; + bool _mouse_visible; +}; + typedef struct { - int x, y, w, h; -} dirty_square; -static dirty_square ds[MAX_NUMBER_OF_DIRTY_SQUARES]; -static int num_of_dirty_square; - -/* Milisecond-based timer management */ -static struct timeval start_time; -static void init_timer(void) -{ - gettimeofday(&start_time, NULL); -} -static unsigned int get_ms_from_start(void) -{ - struct timeval current_time; - gettimeofday(¤t_time, NULL); - return (((current_time.tv_sec - start_time.tv_sec) * 1000) + - ((current_time.tv_usec - start_time.tv_usec) / 1000)); -} + OSystem::SoundProc *sound_proc; + void *param; + byte format; +} THREAD_PARAM; #define FRAG_SIZE 4096 static void *sound_and_music_thread(void *params) @@ -98,6 +173,8 @@ static void *sound_and_music_thread(void *params) /* Init sound */ int sound_fd, param, frag_size; unsigned char sound_buffer[FRAG_SIZE]; + OSystem::SoundProc *sound_proc = ((THREAD_PARAM *) params)->sound_proc; + void *proc_param = ((THREAD_PARAM *) params)->param; sound_fd = open("/dev/dsp", O_WRONLY); audio_buf_info info; @@ -153,7 +230,7 @@ static void *sound_and_music_thread(void *params) unsigned short *buf = (unsigned short *)sound_buffer; int size, written; - scumm.mixWaves((short *)sound_buffer, FRAG_SIZE >> 2); + sound_proc(proc_param, (byte *)sound_buffer, FRAG_SIZE >> 1); /* Now convert to stereo */ for (int i = ((FRAG_SIZE >> 2) - 1); i >= 0; i--) { buf[2 * i + 1] = buf[2 * i] = buf[i]; @@ -169,7 +246,7 @@ static void *sound_and_music_thread(void *params) } /* Function used to hide the mouse cursor */ -static void create_empty_cursor(Display * display, int screen, Window window) +void OSystem_X11::create_empty_cursor() { XColor bg; Pixmap pixmapBits; @@ -177,53 +254,43 @@ static void create_empty_cursor(Display * display, int screen, Window window) static const char data[] = { 0 }; bg.red = bg.green = bg.blue = 0x0000; - pixmapBits = - XCreateBitmapFromData(display, XRootWindow(display, screen), data, 1, 1); + pixmapBits = XCreateBitmapFromData(display, XRootWindow(display, screen), data, 1, 1); if (pixmapBits) { - cursor = XCreatePixmapCursor(display, pixmapBits, pixmapBits, - &bg, &bg, 0, 0); + cursor = XCreatePixmapCursor(display, pixmapBits, pixmapBits, &bg, &bg, 0, 0); XFreePixmap(display, pixmapBits); } XDefineCursor(display, window, cursor); } -/* No CD on the iPAQ => stub functions */ -void cd_play(Scumm *s, int track, int num_loops, int start_frame, - int end_frame) -{ - -#ifdef COMPRESSED_SOUND_FILE - mp3_cd_play(s, track, num_loops, start_frame, end_frame); -#endif -} -int cd_is_running(void) -{ - return 1; -} -void cd_stop(void) +OSystem *OSystem_X11_create(void) { + return OSystem_X11::create(0, 0); } -/* No debugger on the iPAQ => stub function */ -void BoxTest(int num) +OSystem *OSystem_X11::create(int gfx_mode, bool full_screen) { + OSystem_X11 *syst = new OSystem_X11(); + return syst; } -/* Initialize the graphics sub-system */ -void initGraphics(Scumm *s, bool fullScreen, unsigned int scaleFactor) +OSystem_X11::OSystem_X11() { - char buf[512], *gameName; + char buf[512]; static XShmSegmentInfo shminfo; XWMHints *wm_hints; XGCValues values; XTextProperty window_name; char *name = (char *)&buf; - scale = scaleFactor; // not implemented yet! ignored. + /* Some members initialization */ + fake_right_mouse = 0; + report_presses = 1; + current_shake_pos = 0; + _palette_changed = false; + num_of_dirty_square = MAX_NUMBER_OF_DIRTY_SQUARES; /* For the window title */ - sprintf(buf, "ScummVM - %s", gameName = s->getGameName()); - free(gameName); + sprintf(buf, "ScummVM"); display = XOpenDisplay(NULL); if (display == NULL) { @@ -231,7 +298,6 @@ void initGraphics(Scumm *s, bool fullScreen, unsigned int scaleFactor) exit(1); } screen = DefaultScreen(display); - x11_socket = ConnectionNumber(display); window_width = 320; window_height = 200; @@ -284,108 +350,56 @@ void initGraphics(Scumm *s, bool fullScreen, unsigned int scaleFactor) } } out_of_loop: - create_empty_cursor(display, screen, window); - - /* And finally start the music thread */ - pthread_create(&sound_thread, NULL, sound_and_music_thread, NULL); + create_empty_cursor(); /* Initialize the 'local' frame buffer */ local_fb = (unsigned char *)malloc(320 * 200 * sizeof(unsigned char)); + + /* And finally start the local timer */ + gettimeofday(&start_time, NULL); } -void setWindowName(Scumm *s) -{ - char buf[512], *gameName; - XTextProperty window_name; - char *name = (char *)&buf; +uint32 OSystem_X11::get_msecs() { + struct timeval current_time; + gettimeofday(¤t_time, NULL); + return (uint32) (((current_time.tv_sec - start_time.tv_sec) * 1000) + + ((current_time.tv_usec - start_time.tv_usec) / 1000)); +} - /* For the window title */ - sprintf(buf, "ScummVM - %s", gameName = s->getGameName()); - free(gameName); +void OSystem_X11::init_size(uint w, uint h) { + if ((w != 320) || (h != 200)) + error("320x200 is the only game resolution supported"); - XStringListToTextProperty(&name, 1, &window_name); - XSetWMProperties(display, window, &window_name, &window_name, - NULL /* argv */ , 0 /* argc */ , NULL /* size hints */ , - NULL /* WM hints */ , NULL /* class hints */ ); + /* Do nothing more for now... */ } -/* This simply shifts up or down the screen by 'shake pos' */ -void setShakePos(Scumm *s, int shake_pos) -{ - if (shake_pos != current_shake_pos) { - int dirty_top = 0, dirty_height = 0; - int line; - - /* This is to provoke a full redraw */ - num_of_dirty_square = MAX_NUMBER_OF_DIRTY_SQUARES; - - /* Update the mouse to prevent 'mouse droppings' */ - old_mouse_y += shake_pos - current_shake_pos; - - /* Handle the 'dirty part' of the screen */ - if (shake_pos > current_shake_pos) { - for (line = 199 + shake_pos; line >= -shake_pos; line--) { - int cur_pos, new_pos; - int cur_OK, new_OK; - - cur_pos = line + current_shake_pos; - new_pos = line + shake_pos; - - cur_OK = (cur_pos >= 0) && (cur_pos < 200); - new_OK = (new_pos >= 0) && (new_pos < 200); - if (cur_OK && new_OK) - memcpy(local_fb + new_pos * 320, local_fb + cur_pos * 320, 320); - else if (cur_OK) - memset(local_fb + cur_pos * 320, 0, 320); - else if (new_OK) - memset(local_fb + new_pos * 320, 0, 320); - } +bool OSystem_X11::set_sound_proc(void *param, SoundProc *proc, byte format) { + THREAD_PARAM thread_param; - if (current_shake_pos < 0) { - dirty_top = -shake_pos; - dirty_height = shake_pos - current_shake_pos; - if (dirty_top < 0) { - dirty_height += dirty_top; - dirty_top = 0; - } - if ((dirty_height + dirty_top) > 200) - dirty_height = 200 - dirty_top; - } else { - dirty_height = 0; - } - } else { - for (line = -current_shake_pos; line < 200 + current_shake_pos; line++) { - int cur_pos, new_pos; - int cur_OK, new_OK; - - cur_pos = line + current_shake_pos; - new_pos = line + shake_pos; - cur_OK = (cur_pos >= 0) && (cur_pos < 200); - new_OK = (new_pos >= 0) && (new_pos < 200); - - if (cur_OK && new_OK) - memcpy(local_fb + new_pos * 320, local_fb + cur_pos * 320, 320); - else if (cur_OK) - memset(local_fb + cur_pos * 320, 0, 320); - else if (new_OK) - memset(local_fb + new_pos * 320, 0, 320); - } + /* And finally start the music thread */ + thread_param.param = param; + thread_param.sound_proc = proc; + thread_param.format = format; - if (current_shake_pos <= 0) { - dirty_height = 0; - } else { - dirty_top = 200 - current_shake_pos; - dirty_height = current_shake_pos - shake_pos; - if ((dirty_height + dirty_top) > 200) - dirty_height = 200 - dirty_top; - } - } + if (format == SOUND_16BIT) + pthread_create(&sound_thread, NULL, sound_and_music_thread, (void *) &thread_param); + else + warning("Only support 16 bit sound for now. Disabling sound "); - /* And save the new shake position */ - current_shake_pos = shake_pos; - if (dirty_height > 0) - s->redrawLines(dirty_top, dirty_top + dirty_height); - } + return true; +} + +void OSystem_X11::set_palette(const byte *colors, uint start, uint num) { + const byte *data = colors; + unsigned short *pal = &(palette[start]); + + do { + *pal++ = ((data[0] & 0xF8) << 8) | ((data[1] & 0xFC) << 3) | (data[2] >> 3); + data += 4; + num--; + } while (num > 0); + + _palette_changed = true; } #define AddDirtyRec(xi,yi,wi,hi) \ @@ -396,14 +410,13 @@ void setShakePos(Scumm *s, int shake_pos) ds[num_of_dirty_square].h = hi; \ num_of_dirty_square++; \ } -void blitToScreen(Scumm *s, byte *src, int x, int y, int w, int h) -{ + +void OSystem_X11::copy_rect(const byte *buf, int pitch, int x, int y, int w, int h) { unsigned char *dst; - y += current_shake_pos; if (y < 0) { h += y; - src -= y * 320; + buf -= y * pitch; y = 0; } if (h > (200 - y)) { @@ -415,146 +428,21 @@ void blitToScreen(Scumm *s, byte *src, int x, int y, int w, int h) if (h <= 0) return; - hide_mouse = true; - if (has_mouse) { - s->drawMouse(); - } + if (_mouse_drawn) + undraw_mouse(); AddDirtyRec(x, y, w, h); while (h-- > 0) { - memcpy(dst, src, w); + memcpy(dst, buf, w); dst += 320; - src += 320; + buf += pitch; } } -#define BAK_WIDTH 40 -#define BAK_HEIGHT 40 -unsigned char old_backup[BAK_WIDTH * BAK_HEIGHT]; - -void drawMouse(int xdraw, int ydraw, int w, int h, byte *buf, - bool visible) -{ - unsigned char *dst, *bak; - - ydraw += current_shake_pos; - - if ((xdraw >= 320) || ((xdraw + w) <= 0) || - (ydraw >= 200) || ((ydraw + h) <= 0)) { - if (hide_mouse) - visible = false; - if (has_mouse) - has_mouse = false; - if (visible) - has_mouse = true; - return; - } - - if (hide_mouse) - visible = false; - - assert(w <= BAK_WIDTH && h <= BAK_HEIGHT); - - if (has_mouse) { - int old_h = old_mouse_h; - - has_mouse = false; - AddDirtyRec(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h); - - dst = local_fb + (old_mouse_y * 320) + old_mouse_x; - bak = old_backup; - - while (old_h > 0) { - memcpy(dst, bak, old_mouse_w); - bak += BAK_WIDTH; - dst += 320; - old_h--; - } - } - - if (visible) { - int real_w; - int real_h; - int real_h_2; - unsigned char *dst2; - - if (ydraw < 0) { - real_h = h + ydraw; - buf += (-ydraw) * w; - ydraw = 0; - } else { - real_h = (ydraw + h) > 200 ? (200 - ydraw) : h; - } - if (xdraw < 0) { - real_w = w + xdraw; - buf += (-xdraw); - xdraw = 0; - } else { - real_w = (xdraw + w) > 320 ? (320 - xdraw) : w; - } - - dst = local_fb + (ydraw * 320) + xdraw; - dst2 = dst; - bak = old_backup; - - has_mouse = true; - - AddDirtyRec(xdraw, ydraw, real_w, real_h); - old_mouse_x = xdraw; - old_mouse_y = ydraw; - old_mouse_w = real_w; - old_mouse_h = real_h; - - real_h_2 = real_h; - while (real_h_2 > 0) { - memcpy(bak, dst, real_w); - bak += BAK_WIDTH; - dst += 320; - real_h_2--; - } - while (real_h > 0) { - int width = real_w; - while (width > 0) { - unsigned char color = *buf; - if (color != 0xFF) { - *dst2 = color; - } - buf++; - dst2++; - width--; - } - buf += w - real_w; - dst2 += 320 - real_w; - real_h--; - } - } -} - -static unsigned short palette[256]; -static void update_palette(Scumm *s) -{ - int first = s->_palDirtyMin; - int num = s->_palDirtyMax - first + 1; - int i; - unsigned char *data = s->_currentPalette; - unsigned short *pal = &(palette[first]); - - data += first * 3; - for (i = 0; i < num; i++, data += 3) { - *pal++ = - ((data[0] & 0xF8) << 8) | ((data[1] & 0xFC) << 3) | (data[2] >> 3); - } - s->_palDirtyMax = -1; - s->_palDirtyMin = 0x3E8; -} - -static void update_screen(Scumm *s, const dirty_square * d, - dirty_square * dout) -{ +void OSystem_X11::update_screen_helper(const dirty_square * d, dirty_square * dout) { int x, y; unsigned char *ptr_src = local_fb + (320 * d->y) + d->x; - unsigned short *ptr_dst = - ((unsigned short *)image->data) + (320 * d->y) + d->x; + unsigned short *ptr_dst = ((unsigned short *)image->data) + (320 * d->y) + d->x; for (y = 0; y < d->h; y++) { for (x = 0; x < d->w; x++) { *ptr_dst++ = palette[*ptr_src++]; @@ -572,143 +460,251 @@ static void update_screen(Scumm *s, const dirty_square * d, dout->h = d->y + d->h; } -void updateScreen(Scumm *s) -{ +void OSystem_X11::update_screen() { bool full_redraw = false; bool need_redraw = false; static const dirty_square ds_full = { 0, 0, 320, 200 }; dirty_square dout = { 320, 200, 0, 0 }; + + /* First make sure the mouse is drawn, if it should be drawn. */ + draw_mouse(); - if (s->_fastMode & 2) - return; - - if (hide_mouse) { - hide_mouse = false; - s->drawMouse(); - } - - if (s->_palDirtyMax != -1) { - update_palette(s); + if (_palette_changed) { full_redraw = true; num_of_dirty_square = 0; + _palette_changed = false; } else if (num_of_dirty_square >= MAX_NUMBER_OF_DIRTY_SQUARES) { full_redraw = true; num_of_dirty_square = 0; } if (full_redraw) { - update_screen(s, &ds_full, &dout); + update_screen_helper(&ds_full, &dout); need_redraw = true; } else if (num_of_dirty_square > 0) { need_redraw = true; while (num_of_dirty_square > 0) { num_of_dirty_square--; - update_screen(s, &(ds[num_of_dirty_square]), &dout); + update_screen_helper(&(ds[num_of_dirty_square]), &dout); } } if (need_redraw == true) { XShmPutImage(display, window, DefaultGC(display, screen), image, - dout.x, dout.y, - scumm_x + dout.x, scumm_y + dout.y, - dout.w - dout.x, dout.h - dout.y, 0); + dout.x, dout.y, scumm_x + dout.x, scumm_y + dout.y, + dout.w - dout.x, dout.h - dout.y, 0); XFlush(display); } } -void launcherLoop() -{ - int last_time, new_time; - int delta = 0; - last_time = get_ms_from_start(); +bool OSystem_X11::show_mouse(bool visible) { + if (_mouse_visible == visible) + return visible; + + bool last = _mouse_visible; + _mouse_visible = visible; - gui.launcher(); - while (1) { - updateScreen(&scumm); + if (visible) + draw_mouse(); + else + undraw_mouse(); + + return last; +} + +void OSystem_X11::quit() { + exit(1); +} + +void OSystem_X11::draw_mouse() { + if (_mouse_drawn || !_mouse_visible) + return; + _mouse_drawn = true; + + int xdraw = cur_state.x - cur_state.hot_x; + int ydraw = cur_state.y - cur_state.hot_y; + int w = cur_state.w; + int h = cur_state.h; + int real_w; + int real_h; + int real_h_2; + + byte *dst; + byte *dst2; + const byte *buf = _ms_buf; + byte *bak = _ms_backup; + + assert(w <= BAK_WIDTH && h <= BAK_HEIGHT); + + if (ydraw < 0) { + real_h = h + ydraw; + buf += (-ydraw) * w; + ydraw = 0; + } else { + real_h = (ydraw + h) > 200 ? (200 - ydraw) : h; + } + if (xdraw < 0) { + real_w = w + xdraw; + buf += (-xdraw); + xdraw = 0; + } else { + real_w = (xdraw + w) > 320 ? (320 - xdraw) : w; + } + + dst = local_fb + (ydraw * 320) + xdraw; + dst2 = dst; + + if ((real_h == 0) || (real_w == 0)) { + _mouse_drawn = false; + return; + } - new_time = get_ms_from_start(); - waitForTimer(&scumm, delta * 15 + last_time - new_time); - last_time = get_ms_from_start(); + AddDirtyRec(xdraw, ydraw, real_w, real_h); + old_state.x = xdraw; + old_state.y = ydraw; + old_state.w = real_w; + old_state.h = real_h; - if (gui._active) { - gui.loop(); - delta = 5; - } else { - error("gui closed!"); + real_h_2 = real_h; + while (real_h_2 > 0) { + memcpy(bak, dst, real_w); + bak += BAK_WIDTH; + dst += 320; + real_h_2--; + } + while (real_h > 0) { + int width = real_w; + while (width > 0) { + byte color = *buf; + if (color != 0xFF) { + *dst2 = color; + } + buf++; + dst2++; + width--; } + buf += w - real_w; + dst2 += 320 - real_w; + real_h--; } } -/* This function waits for 'msec_delay' miliseconds and handles external events */ -void waitForTimer(Scumm *s, int msec_delay) -{ - int start_time = get_ms_from_start(); - int end_time; - fd_set rfds; - struct timeval tv; - XEvent event; +void OSystem_X11::undraw_mouse() { + if (!_mouse_drawn) + return; + _mouse_drawn = false; - if (s->_fastMode & 2) - msec_delay = 0; - else if (s->_fastMode & 1) - msec_delay = 10; - end_time = start_time + msec_delay; + int old_h = old_state.h; + AddDirtyRec(old_state.x, old_state.y, old_state.w, old_state.h); - while (1) { - FD_ZERO(&rfds); - FD_SET(x11_socket, &rfds); - - msec_delay = end_time - get_ms_from_start(); - tv.tv_sec = 0; - if (msec_delay <= 0) { - tv.tv_usec = 0; - } else { - tv.tv_usec = msec_delay * 1000; - } - if (select(x11_socket + 1, &rfds, NULL, NULL, &tv) == 0) - break; /* This is the timeout */ - while (XPending(display)) { - XNextEvent(display, &event); - switch (event.type) { - case Expose:{ - int real_w, real_h; - int real_x, real_y; - real_x = event.xexpose.x; - real_y = event.xexpose.y; - real_w = event.xexpose.width; - real_h = event.xexpose.height; - - if (real_x < scumm_x) { - real_w -= scumm_x - real_x; - real_x = 0; - } else { - real_x -= scumm_x; - } - if (real_y < scumm_y) { - real_h -= scumm_y - real_y; - real_y = 0; - } else { - real_y -= scumm_y; - } - if ((real_h <= 0) || (real_w <= 0)) - break; - if ((real_x >= 320) || (real_y >= 200)) - break; + byte *dst = local_fb + (old_state.y * 320) + old_state.x; + byte *bak = _ms_backup; - if ((real_x + real_w) >= 320) { - real_w = 320 - real_x; - } - if ((real_y + real_h) >= 200) { - real_h = 200 - real_y; - } + while (old_h > 0) { + memcpy(dst, bak, old_state.w); + bak += BAK_WIDTH; + dst += 320; + old_h--; + } +} - /* Compute the intersection of the expose event with the real ScummVM display zone */ - AddDirtyRec(real_x, real_y, real_w, real_h); - } +void OSystem_X11::set_mouse_pos(int x, int y) { + if ((x != cur_state.x) || (y != cur_state.y)) { + cur_state.x = x; + cur_state.y = y; + undraw_mouse(); + } +} + +void OSystem_X11::set_mouse_cursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y) { + cur_state.w = w; + cur_state.h = h; + cur_state.hot_x = hotspot_x; + cur_state.hot_y = hotspot_y; + _ms_buf = (byte*)buf; + + undraw_mouse(); +} + +void OSystem_X11::set_shake_pos(int shake_pos) { + warning("Shaking not implemented yet (%d) ", shake_pos); +} + +void *OSystem_X11::create_thread(ThreadProc *proc, void *param) { + error("Create_thread Should never be called "); +} + +uint32 OSystem_X11::property(int param, uint32 value) { + switch (param) + { + case PROP_GET_SAMPLE_RATE: + return 22050; + } + warning("Property not implemented yet (%d, 0x%08X) ", param, value); + return 0; +} + +bool OSystem_X11::poll_cdrom() { + return false; +} + +void OSystem_X11::play_cdrom(int track, int num_loops, int start_frame, int end_frame) { +} + +void OSystem_X11::stop_cdrom() { +} + +void OSystem_X11::update_cdrom() { +} + +void OSystem_X11::delay_msecs(uint msecs) { + usleep(msecs * 1000); +} + +bool OSystem_X11::poll_event(Event *scumm_event) { + while (XPending(display)) { + XEvent event; + + XNextEvent(display, &event); + switch (event.type) { + case Expose:{ + int real_w, real_h; + int real_x, real_y; + real_x = event.xexpose.x; + real_y = event.xexpose.y; + real_w = event.xexpose.width; + real_h = event.xexpose.height; + if (real_x < scumm_x) { + real_w -= scumm_x - real_x; + real_x = 0; + } else { + real_x -= scumm_x; + } + if (real_y < scumm_y) { + real_h -= scumm_y - real_y; + real_y = 0; + } else { + real_y -= scumm_y; + } + if ((real_h <= 0) || (real_w <= 0)) + break; + if ((real_x >= 320) || (real_y >= 200)) break; - case KeyPress: - switch (event.xkey.keycode) { + if ((real_x + real_w) >= 320) { + real_w = 320 - real_x; + } + if ((real_y + real_h) >= 200) { + real_h = 200 - real_y; + } + + /* Compute the intersection of the expose event with the real ScummVM display zone */ + AddDirtyRec(real_x, real_y, real_w, real_h); + } + break; + + case KeyPress: + switch (event.xkey.keycode) { case 132: report_presses = 0; break; @@ -717,26 +713,28 @@ void waitForTimer(Scumm *s, int msec_delay) fake_right_mouse = 1; break; } - break; - - case KeyRelease: - /* I am using keycodes here and NOT keysyms to be sure that even if the user - remaps his iPAQ's keyboard, it will still work. - */ - switch (event.xkey.keycode) { + break; + + case KeyRelease: { + /* I am using keycodes here and NOT keysyms to be sure that even if the user + remaps his iPAQ's keyboard, it will still work. + */ + int keycode = -1; + int ascii = -1; + switch (event.xkey.keycode) { case 9: /* Escape on my PC */ case 130: /* Calendar on the iPAQ */ - s->_keyPressed = 27; + keycode = 27; break; - case 71: /* F5 on my PC */ + case 71: /* F5 on my PC */ case 128: /* Record on the iPAQ */ - s->_keyPressed = 319; + keycode = 319; break; - case 65: /* Space on my PC */ + case 65: /* Space on my PC */ case 131: /* Schedule on the iPAQ */ - s->_keyPressed = 32; + keycode = 32; break; case 132: /* 'Q' on the iPAQ */ @@ -748,111 +746,78 @@ void waitForTimer(Scumm *s, int msec_delay) break; default:{ - KeySym xsym; - xsym = XKeycodeToKeysym(display, event.xkey.keycode, 0); - if ((xsym >= 'a') && (xsym <= 'z') && (event.xkey.state & 0x01)) - xsym &= ~0x20; /* Handle shifted keys */ - s->_keyPressed = xsym; - } + KeySym xsym; + xsym = XKeycodeToKeysym(display, event.xkey.keycode, 0); + keycode = xsym; + if ((xsym >= 'a') && (xsym <= 'z') && (event.xkey.state & 0x01)) + xsym &= ~0x20; /* Handle shifted keys */ + ascii = xsym; } - break; - - case ButtonPress: - if (report_presses != 0) { - if (event.xbutton.button == 1) { - if (fake_right_mouse == 0) { - s->_leftBtnPressed |= msClicked | msDown; - } else { - s->_rightBtnPressed |= msClicked | msDown; - } - } else if (event.xbutton.button == 3) - s->_rightBtnPressed |= msClicked | msDown; - } - break; - - case ButtonRelease: - if (report_presses != 0) { - if (event.xbutton.button == 1) { - if (fake_right_mouse == 0) { - s->_leftBtnPressed &= ~msDown; - } else { - s->_rightBtnPressed &= ~msDown; - } - } else if (event.xbutton.button == 3) - s->_rightBtnPressed &= ~msDown; - } - break; + } + if (keycode != -1) + { + scumm_event->event_code = EVENT_KEYDOWN; + scumm_event->kbd.keycode = keycode; + scumm_event->kbd.ascii = (ascii != -1 ? ascii : keycode); + return true; + } + } break; - case MotionNotify:{ - int newx, newy; - newx = event.xmotion.x - scumm_x; - newy = event.xmotion.y - scumm_y; - if ((newx != s->mouse.x) || (newy != s->mouse.y)) { - s->mouse.x = newx; - s->mouse.y = newy; - s->drawMouse(); - updateScreen(s); + case ButtonPress: + if (report_presses != 0) { + if (event.xbutton.button == 1) { + if (fake_right_mouse == 0) { + scumm_event->event_code = EVENT_LBUTTONDOWN; + } else { + scumm_event->event_code = EVENT_RBUTTONDOWN; } - } - break; + } else if (event.xbutton.button == 3) + scumm_event->event_code = EVENT_RBUTTONDOWN; + scumm_event->mouse.x = event.xbutton.x - scumm_x; + scumm_event->mouse.y = event.xbutton.y - scumm_y; + return true; + } + break; - case ConfigureNotify:{ - if ((window_width != event.xconfigure.width) || - (window_height != event.xconfigure.height)) { - window_width = event.xconfigure.width; - window_height = event.xconfigure.height; - scumm_x = (window_width - 320) / 2; - scumm_y = (window_height - 200) / 2; - XFillRectangle(display, window, black_gc, 0, 0, window_width, - window_height); + case ButtonRelease: + if (report_presses != 0) { + if (event.xbutton.button == 1) { + if (fake_right_mouse == 0) { + scumm_event->event_code = EVENT_LBUTTONUP; + } else { + scumm_event->event_code = EVENT_RBUTTONUP; } - } - break; - - default: - printf("%d\n", event.type); - break; + } else if (event.xbutton.button == 3) + scumm_event->event_code = EVENT_RBUTTONUP; + scumm_event->mouse.x = event.xbutton.x - scumm_x; + scumm_event->mouse.y = event.xbutton.y - scumm_y; + return true; + } + break; + + case MotionNotify: + scumm_event->event_code = EVENT_MOUSEMOVE; + scumm_event->mouse.x = event.xmotion.x - scumm_x; + scumm_event->mouse.y = event.xmotion.y - scumm_y; + return true; + + case ConfigureNotify:{ + if ((window_width != event.xconfigure.width) || + (window_height != event.xconfigure.height)) { + window_width = event.xconfigure.width; + window_height = event.xconfigure.height; + scumm_x = (window_width - 320) / 2; + scumm_y = (window_height - 200) / 2; + XFillRectangle(display, window, black_gc, 0, 0, window_width, window_height); } } - } -} - -/* Main function for the system-dependent part. Needs to handle : - - handle command line arguments - - initialize all the 'globals' (sound driver, Scumm object, ...) - - do the main loop of the game -*/ -int main(int argc, char *argv[]) -{ - int delta; - int last_time, new_time; - - scumm._gui = &gui; - gui.init(&scumm); - sound.initialize(&scumm, &snd_driv); - scumm.scummMain(argc, argv); - gui.init(&scumm); /* Reinit GUI after loading a game */ + break; - num_of_dirty_square = 0; - - /* Start the milisecond counter */ - init_timer(); - last_time = 0; - delta = 0; - while (1) { - updateScreen(&scumm); - - new_time = get_ms_from_start(); - waitForTimer(&scumm, delta * 15 + last_time - new_time); - last_time = get_ms_from_start(); - - if (gui._active) { - gui.loop(); - delta = 5; - } else { - delta = scumm.scummLoop(delta); + default: + printf("Unhandled event : %d\n", event.type); + break; } } - return 0; + return false; } |