truelight@0: #include "stdafx.h" truelight@0: truelight@0: #if defined(WITH_SDL) truelight@0: #include "ttd.h" tron@1299: #include "debug.h" truelight@0: #include "gfx.h" truelight@0: #include "sound.h" truelight@0: #include "window.h" truelight@0: #include truelight@0: #include "player.h" truelight@0: #include "hal.h" truelight@543: #include "network.h" truelight@0: truelight@0: #ifdef UNIX truelight@0: #include tron@443: tron@443: #ifdef __MORPHOS__ tron@454: // The system supplied definition of SIG_DFL is wrong on MorphOS tron@454: #undef SIG_DFL tron@443: #define SIG_DFL (void (*)(int))0 tron@443: #endif truelight@0: #endif truelight@0: truelight@0: #define DYNAMICALLY_LOADED_SDL truelight@0: truelight@0: static SDL_Surface *_sdl_screen; truelight@0: static int _sdl_usage; truelight@0: static bool _all_modes; truelight@0: truelight@0: #define MAX_DIRTY_RECTS 100 truelight@0: static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS]; truelight@0: static int _num_dirty_rects; truelight@0: truelight@193: #define SDL_CALL truelight@0: truelight@0: #if defined(DYNAMICALLY_LOADED_SDL) && defined(WIN32) truelight@0: truelight@0: bool LoadLibraryList(void **proc, const char *dll); truelight@0: truelight@0: typedef struct { truelight@0: int (SDLCALL *SDL_Init)(Uint32); truelight@0: int (SDLCALL *SDL_InitSubSystem)(Uint32); truelight@0: char *(SDLCALL *SDL_GetError)(); truelight@0: void (SDLCALL *SDL_QuitSubSystem)(Uint32); truelight@0: void (SDLCALL *SDL_UpdateRect)(SDL_Surface *, Sint32, Sint32, Uint32, Uint32); truelight@0: void (SDLCALL *SDL_UpdateRects)(SDL_Surface *, int, SDL_Rect *); truelight@0: int (SDLCALL *SDL_SetColors)(SDL_Surface *, SDL_Color *, int, int); truelight@0: void (SDLCALL *SDL_WM_SetCaption)(const char *, const char *); truelight@0: int (SDLCALL *SDL_ShowCursor)(int); truelight@0: void (SDLCALL *SDL_FreeSurface)(SDL_Surface *); truelight@0: int (SDLCALL *SDL_PollEvent)(SDL_Event *); truelight@0: void (SDLCALL *SDL_WarpMouse)(Uint16, Uint16); truelight@0: uint32 (SDLCALL *SDL_GetTicks)(); truelight@0: int (SDLCALL *SDL_OpenAudio)(SDL_AudioSpec *, SDL_AudioSpec*); truelight@0: void (SDLCALL *SDL_PauseAudio)(int); truelight@0: void (SDLCALL *SDL_CloseAudio)(); truelight@0: int (SDLCALL *SDL_LockSurface)(SDL_Surface*); truelight@0: void (SDLCALL *SDL_UnlockSurface)(SDL_Surface*); truelight@0: SDLMod (SDLCALL *SDL_GetModState)(); truelight@0: void (SDLCALL *SDL_Delay)(Uint32); truelight@0: void (SDLCALL *SDL_Quit)(); tron@423: SDL_Surface *(SDLCALL *SDL_SetVideoMode)(int, int, int, Uint32); tron@423: int (SDLCALL *SDL_EnableKeyRepeat)(int, int); truelight@0: void (SDLCALL *SDL_EnableUNICODE)(int); truelight@0: void (SDLCALL *SDL_VideoDriverName)(char *, int); truelight@0: SDL_Rect **(SDLCALL *SDL_ListModes)(void *, int); truelight@0: Uint8 *(SDLCALL *SDL_GetKeyState)(int *); truelight@0: } SDLProcs; truelight@0: truelight@0: #define M(x) x "\0" truelight@193: static const char sdl_files[] = truelight@0: M("sdl.dll") truelight@0: M("SDL_Init") truelight@0: M("SDL_InitSubSystem") truelight@0: M("SDL_GetError") truelight@0: M("SDL_QuitSubSystem") truelight@0: M("SDL_UpdateRect") truelight@0: M("SDL_UpdateRects") truelight@0: M("SDL_SetColors") truelight@0: M("SDL_WM_SetCaption") truelight@0: M("SDL_ShowCursor") truelight@0: M("SDL_FreeSurface") truelight@0: M("SDL_PollEvent") truelight@0: M("SDL_WarpMouse") truelight@0: M("SDL_GetTicks") truelight@0: M("SDL_OpenAudio") truelight@0: M("SDL_PauseAudio") truelight@0: M("SDL_CloseAudio") truelight@0: M("SDL_LockSurface") truelight@0: M("SDL_UnlockSurface") truelight@0: M("SDL_GetModState") truelight@0: M("SDL_Delay") truelight@0: M("SDL_Quit") truelight@0: M("SDL_SetVideoMode") truelight@0: M("SDL_EnableKeyRepeat") truelight@0: M("SDL_EnableUNICODE") truelight@0: M("SDL_VideoDriverName") truelight@0: M("SDL_ListModes") truelight@0: M("SDL_GetKeyState") truelight@0: M("") truelight@0: ; truelight@0: #undef M truelight@0: truelight@0: static SDLProcs _proc; truelight@0: tron@1301: static const char *LoadSdlDLL(void) truelight@0: { truelight@193: if (_proc.SDL_Init != NULL) truelight@0: return NULL; truelight@0: if (!LoadLibraryList((void**)&_proc, sdl_files)) truelight@0: return "Unable to load sdl.dll"; truelight@0: return NULL; truelight@0: } truelight@0: truelight@0: #undef SDL_CALL truelight@0: #define SDL_CALL _proc. truelight@0: truelight@0: #endif truelight@0: truelight@0: truelight@0: #ifdef UNIX truelight@0: static void SdlAbort(int sig) truelight@0: { truelight@0: /* Own hand-made parachute for the cases of failed assertions. */ truelight@0: SDL_CALL SDL_Quit(); tron@444: tron@444: switch (sig) { tron@444: case SIGSEGV: tron@444: case SIGFPE: tron@444: signal(sig, SIG_DFL); tron@444: raise(sig); tron@444: break; tron@444: tron@444: default: tron@444: break; tron@444: } truelight@0: } truelight@0: #endif truelight@0: truelight@0: tron@1301: static const char *SdlOpen(uint32 x) truelight@0: { truelight@0: #if defined(DYNAMICALLY_LOADED_SDL) && defined(WIN32) tron@423: { tron@1301: const char *s = LoadSdlDLL(); tron@423: if (s != NULL) return s; tron@423: } truelight@0: #endif truelight@0: if (_sdl_usage++ == 0) { truelight@0: if (SDL_CALL SDL_Init(x) == -1) truelight@0: return SDL_CALL SDL_GetError(); tron@423: } else if (x != 0) { truelight@0: if (SDL_CALL SDL_InitSubSystem(x) == -1) truelight@0: return SDL_CALL SDL_GetError(); truelight@0: } truelight@0: truelight@0: #ifdef UNIX truelight@0: signal(SIGABRT, SdlAbort); tron@444: signal(SIGSEGV, SdlAbort); tron@444: signal(SIGFPE, SdlAbort); tron@1369: tron@1369: signal(SIGPIPE, SIG_IGN); truelight@0: #endif truelight@0: truelight@0: return NULL; truelight@0: } truelight@0: truelight@0: static void SdlClose(uint32 x) truelight@0: { tron@423: if (x != 0) truelight@0: SDL_CALL SDL_QuitSubSystem(x); truelight@0: if (--_sdl_usage == 0) { truelight@0: SDL_CALL SDL_Quit(); tron@423: #ifdef UNIX tron@443: signal(SIGABRT, SIG_DFL); tron@444: signal(SIGSEGV, SIG_DFL); tron@444: signal(SIGFPE, SIG_DFL); tron@423: #endif truelight@0: } truelight@0: } truelight@0: truelight@0: static void SdlVideoMakeDirty(int left, int top, int width, int height) truelight@0: { truelight@0: // printf("(%d,%d)-(%d,%d)\n", left, top, width, height); truelight@0: // _pixels_redrawn += width*height; truelight@0: if (_num_dirty_rects < MAX_DIRTY_RECTS) { truelight@0: _dirty_rects[_num_dirty_rects].x = left; truelight@0: _dirty_rects[_num_dirty_rects].y = top; truelight@0: _dirty_rects[_num_dirty_rects].w = width; truelight@0: _dirty_rects[_num_dirty_rects].h = height; truelight@0: } truelight@0: _num_dirty_rects++; truelight@0: } truelight@0: truelight@0: static SDL_Color pal[256]; truelight@0: tron@423: static void UpdatePalette(uint start, uint end) tron@423: { truelight@0: uint i; truelight@0: byte *b; truelight@0: tron@423: for (i = start, b = _cur_palette + start * 3; i != end; i++, b += 3) { truelight@0: pal[i].r = b[0]; truelight@0: pal[i].g = b[1]; truelight@0: pal[i].b = b[2]; truelight@0: pal[i].unused = b[3]; truelight@0: } truelight@0: truelight@0: SDL_CALL SDL_SetColors(_sdl_screen, pal, start, end); truelight@0: } truelight@0: tron@423: static void InitPalette(void) tron@423: { truelight@0: UpdatePalette(0, 256); truelight@0: } truelight@0: tron@423: static void CheckPaletteAnim(void) truelight@0: { truelight@0: if(_pal_last_dirty != -1) { truelight@0: UpdatePalette(_pal_first_dirty, _pal_last_dirty + 1); truelight@0: _pal_last_dirty = -1; truelight@0: } dominik@18: } dominik@18: tron@423: static void DrawSurfaceToScreen(void) dominik@18: { tron@423: int n = _num_dirty_rects; tron@423: if (n != 0) { truelight@0: _num_dirty_rects = 0; truelight@0: if (n > MAX_DIRTY_RECTS) truelight@0: SDL_CALL SDL_UpdateRect(_sdl_screen, 0, 0, 0, 0); tron@423: else truelight@0: SDL_CALL SDL_UpdateRects(_sdl_screen, n, _dirty_rects); truelight@0: } truelight@0: } truelight@0: truelight@0: static int CDECL compare_res(const void *pa, const void *pb) truelight@0: { darkvater@222: int x = ((const uint16*)pa)[0] - ((const uint16*)pb)[0]; tron@423: if (x != 0) return x; darkvater@222: return ((const uint16*)pa)[1] - ((const uint16*)pb)[1]; truelight@0: } truelight@0: truelight@0: static const uint16 default_resolutions[][2] = { tron@423: { 640, 480}, tron@423: { 800, 600}, tron@423: {1024, 768}, tron@423: {1152, 864}, darkvater@1028: {1280, 800}, tron@423: {1280, 960}, tron@423: {1280, 1024}, tron@423: {1400, 1050}, darkvater@1028: {1600, 1200}, darkvater@1028: {1680, 1050}, darkvater@1028: {1920, 1200} truelight@0: }; truelight@0: tron@423: static void GetVideoModes(void) tron@423: { truelight@0: int i; truelight@0: SDL_Rect **modes; truelight@0: truelight@0: modes = SDL_CALL SDL_ListModes(NULL, SDL_SWSURFACE + (_fullscreen ? SDL_FULLSCREEN : 0)); truelight@0: tron@423: if (modes == NULL) darkvater@245: error("sdl: no modes available"); dominik@119: darkvater@245: _all_modes = (modes == (void*)-1); darkvater@245: darkvater@245: if (_all_modes) { truelight@0: // all modes available, put some default ones here truelight@0: memcpy(_resolutions, default_resolutions, sizeof(default_resolutions)); darkvater@245: _num_resolutions = lengthof(default_resolutions); truelight@0: } else { dominik@128: int n = 0; tron@423: for (i = 0; modes[i]; i++) { dominik@128: int w = modes[i]->w; dominik@128: int h = modes[i]->h; darkvater@306: if (IS_INT_INSIDE(w, 640, MAX_SCREEN_WIDTH + 1) && darkvater@306: IS_INT_INSIDE(h, 480, MAX_SCREEN_HEIGHT + 1)) { dominik@128: int j; dominik@128: for (j = 0; j < n; ++j) dominik@128: if (_resolutions[j][0] == w && _resolutions[j][1] == h) dominik@128: break; dominik@128: if (j == n) { dominik@128: _resolutions[n][0] = w; dominik@128: _resolutions[n][1] = h; darkvater@245: if (++n == lengthof(_resolutions)) break; dominik@128: } truelight@0: } truelight@0: } truelight@0: _num_resolutions = n; darkvater@245: qsort(_resolutions, n, sizeof(_resolutions[0]), compare_res); truelight@0: } truelight@0: } truelight@0: truelight@0: static int GetAvailableVideoMode(int *w, int *h) truelight@0: { truelight@0: int i; darkvater@306: int best; darkvater@306: uint delta; truelight@0: truelight@0: // all modes available? truelight@0: if (_all_modes) truelight@0: return 1; truelight@0: truelight@0: // is the wanted mode among the available modes? darkvater@306: for (i = 0; i != _num_resolutions; i++) { truelight@0: if(*w == _resolutions[i][0] && *h == _resolutions[i][1]) truelight@0: return 1; truelight@0: } truelight@0: darkvater@306: // use the closest possible resolution darkvater@306: best = 0; darkvater@306: delta = abs((_resolutions[0][0] - *w) * (_resolutions[0][1] - *h)); darkvater@306: for (i = 1; i != _num_resolutions; ++i) { darkvater@306: uint newdelta = abs((_resolutions[i][0] - *w) * (_resolutions[i][1] - *h)); darkvater@306: if (newdelta < delta) { darkvater@306: best = i; darkvater@306: delta = newdelta; darkvater@306: } darkvater@306: } darkvater@306: *w = _resolutions[best][0]; darkvater@306: *h = _resolutions[best][1]; truelight@0: return 2; truelight@0: } truelight@0: dominik@902: extern const char _openttd_revision[]; dominik@902: truelight@0: static bool CreateMainSurface(int w, int h) truelight@0: { truelight@0: SDL_Surface *newscreen; Darkvater@1474: char caption[50]; truelight@0: truelight@0: GetAvailableVideoMode(&w, &h); truelight@0: darkvater@798: DEBUG(misc, 1) ("sdl: using mode %dx%d", w, h); truelight@0: darkvater@36: // DO NOT CHANGE TO HWSURFACE, IT DOES NOT WORK tron@423: newscreen = SDL_CALL SDL_SetVideoMode(w, h, 8, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE)); tron@423: if (newscreen == NULL) truelight@0: return false; truelight@0: darkvater@306: _screen.width = newscreen->w; darkvater@306: _screen.height = newscreen->h; darkvater@306: _screen.pitch = newscreen->pitch; darkvater@306: truelight@0: _sdl_screen = newscreen; truelight@0: InitPalette(); truelight@0: Darkvater@1474: snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision); dominik@902: SDL_CALL SDL_WM_SetCaption(caption, caption); truelight@0: SDL_CALL SDL_ShowCursor(0); truelight@0: darkvater@306: GameSizeChanged(); truelight@0: truelight@0: return true; truelight@0: } truelight@0: tron@423: typedef struct VkMapping { truelight@0: uint16 vk_from; truelight@0: byte vk_count; truelight@0: byte map_to; truelight@0: } VkMapping; truelight@0: tron@423: #define AS(x, z) {x, 0, z} tron@423: #define AM(x, y, z, w) {x, y - x, z} truelight@0: truelight@0: static const VkMapping _vk_mapping[] = { truelight@0: // Pageup stuff + up/down tron@423: AM(SDLK_PAGEUP, SDLK_PAGEDOWN, WKC_PAGEUP, WKC_PAGEDOWN), truelight@0: AS(SDLK_UP, WKC_UP), truelight@0: AS(SDLK_DOWN, WKC_DOWN), truelight@0: AS(SDLK_LEFT, WKC_LEFT), truelight@0: AS(SDLK_RIGHT, WKC_RIGHT), truelight@0: truelight@0: AS(SDLK_HOME, WKC_HOME), truelight@0: AS(SDLK_END, WKC_END), truelight@0: truelight@0: AS(SDLK_INSERT, WKC_INSERT), truelight@0: AS(SDLK_DELETE, WKC_DELETE), truelight@0: truelight@0: // Map letters & digits tron@423: AM(SDLK_a, SDLK_z, 'A', 'Z'), tron@423: AM(SDLK_0, SDLK_9, '0', '9'), truelight@0: truelight@0: AS(SDLK_ESCAPE, WKC_ESC), tron@424: AS(SDLK_PAUSE, WKC_PAUSE), truelight@0: AS(SDLK_BACKSPACE, WKC_BACKSPACE), truelight@0: truelight@0: AS(SDLK_SPACE, WKC_SPACE), truelight@0: AS(SDLK_RETURN, WKC_RETURN), truelight@0: AS(SDLK_TAB, WKC_TAB), truelight@0: truelight@0: // Function keys tron@423: AM(SDLK_F1, SDLK_F12, WKC_F1, WKC_F12), truelight@0: truelight@0: // Numeric part. truelight@0: // What is the virtual keycode for numeric enter?? tron@423: AM(SDLK_KP0, SDLK_KP9, WKC_NUM_0, WKC_NUM_9), truelight@0: AS(SDLK_KP_DIVIDE, WKC_NUM_DIV), truelight@0: AS(SDLK_KP_MULTIPLY, WKC_NUM_MUL), truelight@0: AS(SDLK_KP_MINUS, WKC_NUM_MINUS), truelight@0: AS(SDLK_KP_PLUS, WKC_NUM_PLUS), truelight@0: AS(SDLK_KP_ENTER, WKC_NUM_ENTER), tron@423: AS(SDLK_KP_PERIOD, WKC_NUM_DECIMAL) truelight@0: }; truelight@0: truelight@0: static uint32 ConvertSdlKeyIntoMy(SDL_keysym *sym) truelight@0: { tron@423: const VkMapping *map; tron@423: uint key = 0; tron@423: for (map = _vk_mapping; map != endof(_vk_mapping); ++map) { tron@423: if ((uint)(sym->sym - map->vk_from) <= map->vk_count) { tron@423: key = sym->sym - map->vk_from + map->map_to; truelight@0: break; truelight@0: } truelight@0: } dominik@129: dominik@129: // check scancode for BACKQUOTE key, because we want the key left of "1", not anything else (on non-US keyboards) truelight@810: #if defined(WIN32) || defined(__OS2__) darkvater@135: if (sym->scancode == 41) key |= WKC_BACKQUOTE; tron@423: #elif defined(__APPLE__) tron@423: if (sym->scancode == 10) key |= WKC_BACKQUOTE; tron@423: #elif defined(__MORPHOS__) tron@423: if (sym->scancode == 0) key |= WKC_BACKQUOTE; // yes, that key is code '0' under MorphOS :) tron@435: #elif defined(__BEOS__) tron@435: if (sym->scancode == 17) key |= WKC_BACKQUOTE; bjarni@570: #elif defined(__SVR4) && defined(__sun) bjarni@570: if (sym->scancode == 60) key |= WKC_BACKQUOTE; bjarni@572: if (sym->scancode == 49) key |= WKC_BACKSPACE; darkvater@135: #else pasky@1428: if (sym->scancode == 41) key |= WKC_BACKQUOTE; // Linux console tron@423: if (sym->scancode == 49) key |= WKC_BACKQUOTE; darkvater@135: #endif bjarni@572: truelight@0: // META are the command keys on mac truelight@0: if (sym->mod & KMOD_META) key |= WKC_META; truelight@0: if (sym->mod & KMOD_SHIFT) key |= WKC_SHIFT; truelight@0: if (sym->mod & KMOD_CTRL) key |= WKC_CTRL; truelight@0: if (sym->mod & KMOD_ALT) key |= WKC_ALT; tron@423: // these two lines really help porting hotkey combos. Uncomment to use -- Bjarni bjarni@167: //printf("scancode character pressed %d\n", sym->scancode); bjarni@167: //printf("unicode character pressed %d\n", sym->unicode); truelight@0: return (key << 16) + sym->unicode; truelight@0: } truelight@0: tron@1093: void DoExitSave(void); dominik@643: tron@423: static int PollEvent(void) tron@423: { truelight@0: SDL_Event ev; truelight@0: truelight@0: if (!SDL_CALL SDL_PollEvent(&ev)) truelight@0: return -2; truelight@0: tron@423: switch (ev.type) { truelight@0: case SDL_MOUSEMOTION: truelight@0: if (_cursor.fix_at) { truelight@0: int dx = ev.motion.x - _cursor.pos.x; truelight@0: int dy = ev.motion.y - _cursor.pos.y; truelight@0: if (dx != 0 || dy != 0) { truelight@0: _cursor.delta.x += dx; truelight@0: _cursor.delta.y += dy; truelight@0: SDL_CALL SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y); truelight@0: } truelight@0: } else { truelight@0: _cursor.delta.x = ev.motion.x - _cursor.pos.x; truelight@0: _cursor.delta.y = ev.motion.y - _cursor.pos.y; truelight@0: _cursor.pos.x = ev.motion.x; truelight@0: _cursor.pos.y = ev.motion.y; truelight@0: _cursor.dirty = true; truelight@0: } truelight@0: break; truelight@0: truelight@0: case SDL_MOUSEBUTTONDOWN: truelight@0: if (_rightclick_emulate && (SDL_CALL SDL_GetModState() & (KMOD_LCTRL | KMOD_RCTRL))) truelight@0: ev.button.button = SDL_BUTTON_RIGHT; truelight@0: tron@423: switch (ev.button.button) { tron@423: case SDL_BUTTON_LEFT: tron@423: _left_button_down = true; tron@423: break; tron@423: case SDL_BUTTON_RIGHT: tron@423: _right_button_down = true; tron@423: _right_button_clicked = true; tron@423: break; tron@423: case SDL_BUTTON_WHEELUP: tron@423: _cursor.wheel--; tron@423: break; tron@423: case SDL_BUTTON_WHEELDOWN: tron@423: _cursor.wheel++; tron@423: break; tron@423: default: tron@423: break; truelight@0: } truelight@0: break; truelight@0: truelight@0: case SDL_MOUSEBUTTONUP: truelight@0: if (_rightclick_emulate) { truelight@0: _right_button_down = false; truelight@0: _left_button_down = false; truelight@0: _left_button_clicked = false; truelight@0: } else if (ev.button.button == SDL_BUTTON_LEFT) { truelight@0: _left_button_down = false; truelight@0: _left_button_clicked = false; truelight@0: } else if (ev.button.button == SDL_BUTTON_RIGHT) { truelight@0: _right_button_down = false; truelight@0: } truelight@0: break; truelight@0: truelight@0: case SDL_QUIT: dominik@291: // do not ask to quit on the main screen dominik@643: if (_game_mode != GM_MENU) { dominik@643: if(_patches.autosave_on_exit) { dominik@643: DoExitSave(); dominik@643: return ML_QUIT; dominik@643: } else dominik@643: AskExitGame(); dominik@643: } else dominik@291: return ML_QUIT; dominik@291: break; truelight@0: truelight@0: case SDL_KEYDOWN: tron@423: if ((ev.key.keysym.mod & (KMOD_ALT | KMOD_META)) && tron@423: (ev.key.keysym.sym == SDLK_RETURN || ev.key.keysym.sym == SDLK_f)) { truelight@0: _fullscreen ^= true; truelight@0: GetVideoModes(); truelight@0: CreateMainSurface(_screen.width, _screen.height); truelight@0: MarkWholeScreenDirty(); truelight@0: } else { truelight@0: _pressed_key = ConvertSdlKeyIntoMy(&ev.key.keysym); truelight@0: } truelight@0: break; truelight@193: truelight@0: case SDL_VIDEORESIZE: { tron@423: int w = clamp(ev.resize.w, 64, MAX_SCREEN_WIDTH); tron@423: int h = clamp(ev.resize.h, 64, MAX_SCREEN_HEIGHT); tron@423: ChangeResInGame(w, h); tron@423: break; tron@423: } truelight@0: } truelight@0: return -1; truelight@0: } truelight@0: tron@1301: static const char *SdlVideoStart(const char * const *parm) truelight@0: { tron@423: char buf[30]; truelight@0: tron@423: const char *s = SdlOpen(SDL_INIT_VIDEO); tron@423: if (s != NULL) return s; truelight@0: truelight@0: SDL_CALL SDL_VideoDriverName(buf, 30); darkvater@798: DEBUG(misc, 1) ("sdl: using driver '%s'", buf); truelight@0: truelight@0: GetVideoModes(); truelight@0: CreateMainSurface(_cur_resolution[0], _cur_resolution[1]); truelight@0: MarkWholeScreenDirty(); truelight@0: truelight@0: SDL_CALL SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); truelight@0: SDL_CALL SDL_EnableUNICODE(1); truelight@0: return NULL; truelight@0: } truelight@0: tron@423: static void SdlVideoStop(void) truelight@0: { truelight@0: SdlClose(SDL_INIT_VIDEO); truelight@0: } truelight@0: tron@423: static int SdlVideoMainLoop(void) truelight@0: { tron@423: uint32 next_tick = SDL_CALL SDL_GetTicks() + 30; tron@423: uint32 cur_ticks; tron@423: uint32 pal_tick = 0; truelight@0: int i; truelight@0: uint32 mod; truelight@0: int numkeys; truelight@0: Uint8 *keys; truelight@0: tron@423: for (;;) { truelight@0: InteractiveRandom(); // randomness truelight@193: tron@423: while ((i = PollEvent()) == -1) {} tron@423: if (i >= 0) return i; truelight@0: dominik@18: if (_exit_game) return ML_QUIT; truelight@0: dominik@18: mod = SDL_CALL SDL_GetModState(); truelight@193: keys = SDL_CALL SDL_GetKeyState(&numkeys); truelight@0: #if defined(_DEBUG) tron@423: if (_shift_pressed) truelight@0: #else tron@423: if (keys[SDLK_TAB]) truelight@0: #endif tron@423: { dominik@1040: if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; tron@423: } else if (_fast_forward & 2) { truelight@0: _fast_forward = 0; truelight@0: } truelight@0: tron@423: cur_ticks = SDL_CALL SDL_GetTicks(); dominik@18: if ((_fast_forward && !_pause) || cur_ticks > next_tick) dominik@18: next_tick = cur_ticks; dominik@18: dominik@18: if (cur_ticks == next_tick) { dominik@18: next_tick += 30; dominik@18: dominik@18: _ctrl_pressed = !!(mod & (KMOD_LCTRL | KMOD_RCTRL)); dominik@18: _shift_pressed = !!(mod & (KMOD_LSHIFT | KMOD_RSHIFT)); dominik@302: _dbg_screen_rect = !!(mod & KMOD_CAPS); truelight@193: dominik@18: // determine which directional keys are down truelight@193: _dirkeys = tron@423: (keys[SDLK_LEFT] ? 1 : 0) | tron@423: (keys[SDLK_UP] ? 2 : 0) | tron@423: (keys[SDLK_RIGHT] ? 4 : 0) | tron@423: (keys[SDLK_DOWN] ? 8 : 0); dominik@18: GameLoop(); dominik@18: dominik@18: _screen.dst_ptr = _sdl_screen->pixels; dominik@18: UpdateWindows(); tron@423: if (++pal_tick > 4) { tron@423: CheckPaletteAnim(); tron@423: pal_tick = 1; truelight@0: } dominik@18: DrawSurfaceToScreen(); truelight@0: } else { dominik@18: SDL_CALL SDL_Delay(1); dominik@18: _screen.dst_ptr = _sdl_screen->pixels; truelight@543: DrawTextMessage(); dominik@18: DrawMouseCursor(); dominik@18: DrawSurfaceToScreen(); truelight@0: } truelight@0: } truelight@0: } truelight@0: truelight@0: static bool SdlVideoChangeRes(int w, int h) truelight@0: { truelight@0: // see if the mode is available truelight@0: if (GetAvailableVideoMode(&w, &h) != 1) truelight@0: return false; dominik@18: truelight@0: CreateMainSurface(w, h); truelight@0: return true; truelight@0: } truelight@0: truelight@0: const HalVideoDriver _sdl_video_driver = { truelight@0: SdlVideoStart, truelight@0: SdlVideoStop, truelight@0: SdlVideoMakeDirty, truelight@0: SdlVideoMainLoop, truelight@0: SdlVideoChangeRes, truelight@0: }; truelight@0: truelight@0: static void CDECL fill_sound_buffer(void *userdata, Uint8 *stream, int len) truelight@0: { tron@423: MxMixSamples(_mixer, stream, len / 4); truelight@0: } truelight@0: tron@1301: static const char *SdlSoundStart(const char * const *parm) truelight@0: { truelight@0: SDL_AudioSpec spec; truelight@193: tron@1301: const char *s = SdlOpen(SDL_INIT_AUDIO); tron@423: if (s != NULL) return s; tron@423: truelight@0: spec.freq = GetDriverParamInt(parm, "hz", 11025); truelight@0: spec.format = AUDIO_S16SYS; truelight@0: spec.channels = 2; truelight@0: spec.samples = 512; tron@423: spec.callback = fill_sound_buffer; truelight@0: SDL_CALL SDL_OpenAudio(&spec, &spec); truelight@0: SDL_CALL SDL_PauseAudio(0); truelight@0: return NULL; truelight@0: } truelight@0: tron@423: static void SdlSoundStop(void) truelight@0: { truelight@0: SDL_CALL SDL_CloseAudio(); truelight@0: SdlClose(SDL_INIT_AUDIO); truelight@0: } truelight@0: truelight@0: const HalSoundDriver _sdl_sound_driver = { truelight@0: SdlSoundStart, truelight@0: SdlSoundStop, truelight@0: }; truelight@0: truelight@0: tron@423: #if 0 /* XXX what the heck is that? */ truelight@0: #include "viewport.h" truelight@0: void redsq_debug(int tile) truelight@0: { truelight@0: _thd.redsq = tile; truelight@0: MarkWholeScreenDirty(); truelight@0: _screen.dst_ptr = _sdl_screen->pixels; truelight@0: UpdateWindows(); truelight@0: truelight@0: SdlVideoMakeDirty(0,0,_screen.width,_screen.height); truelight@0: DrawSurfaceToScreen(); truelight@0: } truelight@0: tron@410: static void DbgRedraw() truelight@0: { truelight@0: SdlVideoMakeDirty(0,0,_screen.width,_screen.height); truelight@0: DrawSurfaceToScreen(); truelight@0: } tron@423: #endif tron@423: truelight@0: #endif // WITH_SDL