diff options
author | rubidium <rubidium@openttd.org> | 2007-01-02 19:19:48 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2007-01-02 19:19:48 +0000 |
commit | 66bbf336c6af7353ef0aeed58002c46543b30635 (patch) | |
tree | ad4a63860df2626b22f77e7dac712e958bea54cb /video | |
parent | ccc0a3f4dbf58c005b22341ac8874252924690cd (diff) | |
download | openttd-66bbf336c6af7353ef0aeed58002c46543b30635.tar.xz |
(svn r7759) -Merge: makefile rewrite. This merge features:
- A proper ./configure, so everything needs to be configured only once, not for every make.
- Usage of makedepend when available. This greatly reduces the time needed for generating the dependencies.
- A generator for all project files. There is a single file with sources, which is used to generate Makefiles and the project files for MSVC.
- Proper support for OSX universal binaries.
- Object files for non-MSVC compiles are also placed in separate directories, making is faster to switch between debug and release compiles and it does not touch the directory with the source files.
- Functionality to make a bundle of all needed files for for example a nightly or distribution of a binary with all needed GRFs and language files.
Note: as this merge moves almost all files, it is recommended to make a backup of your working copy before updating your working copy.
Diffstat (limited to 'video')
-rw-r--r-- | video/cocoa_keys.h | 127 | ||||
-rw-r--r-- | video/cocoa_v.h | 10 | ||||
-rw-r--r-- | video/cocoa_v.m | 2064 | ||||
-rw-r--r-- | video/dedicated_v.c | 298 | ||||
-rw-r--r-- | video/dedicated_v.h | 10 | ||||
-rw-r--r-- | video/null_v.c | 45 | ||||
-rw-r--r-- | video/null_v.h | 10 | ||||
-rw-r--r-- | video/sdl_v.c | 515 | ||||
-rw-r--r-- | video/sdl_v.h | 10 | ||||
-rw-r--r-- | video/win32_v.c | 876 | ||||
-rw-r--r-- | video/win32_v.h | 10 |
11 files changed, 0 insertions, 3975 deletions
diff --git a/video/cocoa_keys.h b/video/cocoa_keys.h deleted file mode 100644 index 1e69c1425..000000000 --- a/video/cocoa_keys.h +++ /dev/null @@ -1,127 +0,0 @@ -/* $Id$ */ - -#ifndef COCOA_KEYS_H -#define COCOA_KEYS_H - -/* From SDL_QuartzKeys.h */ -/* These are the Macintosh key scancode constants -- from Inside Macintosh */ - -#define QZ_ESCAPE 0x35 -#define QZ_F1 0x7A -#define QZ_F2 0x78 -#define QZ_F3 0x63 -#define QZ_F4 0x76 -#define QZ_F5 0x60 -#define QZ_F6 0x61 -#define QZ_F7 0x62 -#define QZ_F8 0x64 -#define QZ_F9 0x65 -#define QZ_F10 0x6D -#define QZ_F11 0x67 -#define QZ_F12 0x6F -#define QZ_PRINT 0x69 -#define QZ_SCROLLOCK 0x6B -#define QZ_PAUSE 0x71 -#define QZ_POWER 0x7F -#define QZ_BACKQUOTE 0x0A -#define QZ_BACKQUOTE2 0x32 -#define QZ_1 0x12 -#define QZ_2 0x13 -#define QZ_3 0x14 -#define QZ_4 0x15 -#define QZ_5 0x17 -#define QZ_6 0x16 -#define QZ_7 0x1A -#define QZ_8 0x1C -#define QZ_9 0x19 -#define QZ_0 0x1D -#define QZ_MINUS 0x1B -#define QZ_EQUALS 0x18 -#define QZ_BACKSPACE 0x33 -#define QZ_INSERT 0x72 -#define QZ_HOME 0x73 -#define QZ_PAGEUP 0x74 -#define QZ_NUMLOCK 0x47 -#define QZ_KP_EQUALS 0x51 -#define QZ_KP_DIVIDE 0x4B -#define QZ_KP_MULTIPLY 0x43 -#define QZ_TAB 0x30 -#define QZ_q 0x0C -#define QZ_w 0x0D -#define QZ_e 0x0E -#define QZ_r 0x0F -#define QZ_t 0x11 -#define QZ_y 0x10 -#define QZ_u 0x20 -#define QZ_i 0x22 -#define QZ_o 0x1F -#define QZ_p 0x23 -#define QZ_LEFTBRACKET 0x21 -#define QZ_RIGHTBRACKET 0x1E -#define QZ_BACKSLASH 0x2A -#define QZ_DELETE 0x75 -#define QZ_END 0x77 -#define QZ_PAGEDOWN 0x79 -#define QZ_KP7 0x59 -#define QZ_KP8 0x5B -#define QZ_KP9 0x5C -#define QZ_KP_MINUS 0x4E -#define QZ_CAPSLOCK 0x39 -#define QZ_a 0x00 -#define QZ_s 0x01 -#define QZ_d 0x02 -#define QZ_f 0x03 -#define QZ_g 0x05 -#define QZ_h 0x04 -#define QZ_j 0x26 -#define QZ_k 0x28 -#define QZ_l 0x25 -#define QZ_SEMICOLON 0x29 -#define QZ_QUOTE 0x27 -#define QZ_RETURN 0x24 -#define QZ_KP4 0x56 -#define QZ_KP5 0x57 -#define QZ_KP6 0x58 -#define QZ_KP_PLUS 0x45 -#define QZ_LSHIFT 0x38 -#define QZ_z 0x06 -#define QZ_x 0x07 -#define QZ_c 0x08 -#define QZ_v 0x09 -#define QZ_b 0x0B -#define QZ_n 0x2D -#define QZ_m 0x2E -#define QZ_COMMA 0x2B -#define QZ_PERIOD 0x2F -#define QZ_SLASH 0x2C -#if 1 /* Panther now defines right side keys */ -#define QZ_RSHIFT 0x3C -#endif -#define QZ_UP 0x7E -#define QZ_KP1 0x53 -#define QZ_KP2 0x54 -#define QZ_KP3 0x55 -#define QZ_KP_ENTER 0x4C -#define QZ_LCTRL 0x3B -#define QZ_LALT 0x3A -#define QZ_LMETA 0x37 -#define QZ_SPACE 0x31 -#if 1 /* Panther now defines right side keys */ -#define QZ_RMETA 0x36 -#define QZ_RALT 0x3D -#define QZ_RCTRL 0x3E -#endif -#define QZ_LEFT 0x7B -#define QZ_DOWN 0x7D -#define QZ_RIGHT 0x7C -#define QZ_KP0 0x52 -#define QZ_KP_PERIOD 0x41 - -/* Wierd, these keys are on my iBook under MacOS X */ -#define QZ_IBOOK_ENTER 0x34 -#define QZ_IBOOK_LEFT 0x3B -#define QZ_IBOOK_RIGHT 0x3C -#define QZ_IBOOK_DOWN 0x3D -#define QZ_IBOOK_UP 0x3E - -#endif diff --git a/video/cocoa_v.h b/video/cocoa_v.h deleted file mode 100644 index 93d7b2639..000000000 --- a/video/cocoa_v.h +++ /dev/null @@ -1,10 +0,0 @@ -/* $Id$ */ - -#ifndef VIDEO_COCOA_H -#define VIDEO_COCOA_H - -#include "../hal.h" - -extern const HalVideoDriver _cocoa_video_driver; - -#endif diff --git a/video/cocoa_v.m b/video/cocoa_v.m deleted file mode 100644 index f93f86ca4..000000000 --- a/video/cocoa_v.m +++ /dev/null @@ -1,2064 +0,0 @@ -/* $Id$ */ - -/****************************************************************************** - * Cocoa video driver * - * Known things left to do: * - * Nothing at the moment. * - ******************************************************************************/ - -#ifdef WITH_COCOA - -#import <Cocoa/Cocoa.h> -#import <sys/time.h> /* gettimeofday */ -#import <sys/param.h> /* for MAXPATHLEN */ -#import <unistd.h> - -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum { - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess(CPSProcessSerNum* psn); -extern OSErr CPSEnableForegroundOperation(CPSProcessSerNum* psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess(CPSProcessSerNum* psn); - -/* From Menus.h (according to Xcode Developer Documentation) */ -extern void ShowMenuBar(void); -extern void HideMenuBar(void); - -/* Disables a warning. This is needed since the method exists but has been dropped from the header, supposedly as of 10.4. */ -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) -@interface NSApplication(NSAppleMenu) -- (void)setAppleMenu:(NSMenu *)menu; -@end -#endif - - -/* Defined in ppc/param.h or i386/param.h included from sys/param.h */ -#undef ALIGN -/* Defined in stdbool.h */ -#ifndef __cplusplus -# ifndef __BEOS__ -# undef bool -# undef false -# undef true -# endif -#endif - -#include "../stdafx.h" -#include "../openttd.h" -#include "../debug.h" -#include "../functions.h" -#include "../gfx.h" -#include "../macros.h" -#include "../sdl.h" -#include "../window.h" -#include "../network/network.h" -#include "../variables.h" -#include "../os/macosx/splash.h" - -#include "cocoa_v.h" -#include "cocoa_keys.h" - -#undef Point -#undef Rect - - -/* Subclass of NSWindow to fix genie effect and support resize events */ -@interface OTTD_QuartzWindow : NSWindow -- (void)miniaturize:(id)sender; -- (void)display; -- (void)setFrame:(NSRect)frameRect display:(BOOL)flag; -- (void)appDidHide:(NSNotification*)note; -- (void)appWillUnhide:(NSNotification*)note; -- (void)appDidUnhide:(NSNotification*)note; -- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag; -@end - -/* Delegate for our NSWindow to send ask for quit on close */ -@interface OTTD_QuartzWindowDelegate : NSObject -- (BOOL)windowShouldClose:(id)sender; -@end - -@interface OTTDMain : NSObject -@end - - -/* Structure for rez switch gamma fades - * We can hide the monitor flicker by setting the gamma tables to 0 - */ -#define QZ_GAMMA_TABLE_SIZE 256 - -typedef struct { - CGGammaValue red[QZ_GAMMA_TABLE_SIZE]; - CGGammaValue green[QZ_GAMMA_TABLE_SIZE]; - CGGammaValue blue[QZ_GAMMA_TABLE_SIZE]; -} OTTD_QuartzGammaTable; - -/* Add methods to get at private members of NSScreen. - * Since there is a bug in Apple's screen switching code that does not update - * this variable when switching to fullscreen, we'll set it manually (but only - * for the main screen). - */ -@interface NSScreen (NSScreenAccess) - - (void) setFrame:(NSRect)frame; -@end - -@implementation NSScreen (NSScreenAccess) -- (void) setFrame:(NSRect)frame; -{ - _frame = frame; -} -@end - - -static void QZ_Draw(void); -static void QZ_UnsetVideoMode(void); -static void QZ_UpdatePalette(uint start, uint count); -static void QZ_WarpCursor(int x, int y); -static void QZ_ShowMouse(void); -static void QZ_HideMouse(void); -static void CocoaVideoFullScreen(bool full_screen); - - -static NSAutoreleasePool *_ottd_autorelease_pool; -static OTTDMain *_ottd_main; - - -static struct CocoaVideoData { - bool isset; - bool issetting; - - CGDirectDisplayID display_id; /* 0 == main display (only support single display) */ - CFDictionaryRef mode; /* current mode of the display */ - CFDictionaryRef save_mode; /* original mode of the display */ - CFArrayRef mode_list; /* list of available fullscreen modes */ - CGDirectPaletteRef palette; /* palette of an 8-bit display */ - - uint32 device_width; - uint32 device_height; - uint32 device_bpp; - - void *realpixels; - uint8 *pixels; - uint32 width; - uint32 height; - uint32 pitch; - bool fullscreen; - - unsigned int current_mods; - bool tab_is_down; - bool emulating_right_button; - - bool cursor_visible; - bool active; - -#ifdef _DEBUG - uint32 tEvent; -#endif - - OTTD_QuartzWindow *window; - NSQuickDrawView *qdview; - -#define MAX_DIRTY_RECTS 100 - OTTDRect dirty_rects[MAX_DIRTY_RECTS]; - int num_dirty_rects; - - uint16 palette16[256]; - uint32 palette32[256]; -} _cocoa_video_data; - -static bool _cocoa_video_started = false; -static bool _cocoa_video_dialog = false; - - - - -/****************************************************************************** - * Game loop and accessories * - ******************************************************************************/ - -static uint32 GetTick(void) -{ - struct timeval tim; - - gettimeofday(&tim, NULL); - return tim.tv_usec / 1000 + tim.tv_sec * 1000; -} - -static void QZ_CheckPaletteAnim(void) -{ - if (_pal_last_dirty != -1) { - QZ_UpdatePalette(_pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1); - _pal_last_dirty = -1; - } -} - - - -typedef struct VkMapping { - unsigned short vk_from; - byte map_to; -} VkMapping; - -#define AS(x, z) {x, z} - -static const VkMapping _vk_mapping[] = { - AS(QZ_BACKQUOTE, WKC_BACKQUOTE), // key left of '1' - AS(QZ_BACKQUOTE2, WKC_BACKQUOTE), // some keyboards have it on another scancode - - // Pageup stuff + up/down - //AM(SDLK_PAGEUP, SDLK_PAGEDOWN, WKC_PAGEUP, WKC_PAGEDOWN), <==== Does this include HOME/END? - AS(QZ_PAGEUP, WKC_PAGEUP), - AS(QZ_PAGEDOWN, WKC_PAGEDOWN), - - AS(QZ_UP, WKC_UP), - AS(QZ_DOWN, WKC_DOWN), - AS(QZ_LEFT, WKC_LEFT), - AS(QZ_RIGHT, WKC_RIGHT), - - AS(QZ_HOME, WKC_HOME), - AS(QZ_END, WKC_END), - - AS(QZ_INSERT, WKC_INSERT), - AS(QZ_DELETE, WKC_DELETE), - - // Letters. QZ_[a-z] is not in numerical order so we can't use AM(...) - AS(QZ_a, 'A'), - AS(QZ_b, 'B'), - AS(QZ_c, 'C'), - AS(QZ_d, 'D'), - AS(QZ_e, 'E'), - AS(QZ_f, 'F'), - AS(QZ_g, 'G'), - AS(QZ_h, 'H'), - AS(QZ_i, 'I'), - AS(QZ_j, 'J'), - AS(QZ_k, 'K'), - AS(QZ_l, 'L'), - AS(QZ_m, 'M'), - AS(QZ_n, 'N'), - AS(QZ_o, 'O'), - AS(QZ_p, 'P'), - AS(QZ_q, 'Q'), - AS(QZ_r, 'R'), - AS(QZ_s, 'S'), - AS(QZ_t, 'T'), - AS(QZ_u, 'U'), - AS(QZ_v, 'V'), - AS(QZ_w, 'W'), - AS(QZ_x, 'X'), - AS(QZ_y, 'Y'), - AS(QZ_z, 'Z'), - // Same thing for digits - AS(QZ_0, '0'), - AS(QZ_1, '1'), - AS(QZ_2, '2'), - AS(QZ_3, '3'), - AS(QZ_4, '4'), - AS(QZ_5, '5'), - AS(QZ_6, '6'), - AS(QZ_7, '7'), - AS(QZ_8, '8'), - AS(QZ_9, '9'), - - AS(QZ_ESCAPE, WKC_ESC), - AS(QZ_PAUSE, WKC_PAUSE), - AS(QZ_BACKSPACE, WKC_BACKSPACE), - - AS(QZ_SPACE, WKC_SPACE), - AS(QZ_RETURN, WKC_RETURN), - AS(QZ_TAB, WKC_TAB), - - // Function keys - AS(QZ_F1, WKC_F1), - AS(QZ_F2, WKC_F2), - AS(QZ_F3, WKC_F3), - AS(QZ_F4, WKC_F4), - AS(QZ_F5, WKC_F5), - AS(QZ_F6, WKC_F6), - AS(QZ_F7, WKC_F7), - AS(QZ_F8, WKC_F8), - AS(QZ_F9, WKC_F9), - AS(QZ_F10, WKC_F10), - AS(QZ_F11, WKC_F11), - AS(QZ_F12, WKC_F12), - - // Numeric part. - AS(QZ_KP0, WKC_NUM_0), - AS(QZ_KP1, WKC_NUM_1), - AS(QZ_KP2, WKC_NUM_2), - AS(QZ_KP3, WKC_NUM_3), - AS(QZ_KP4, WKC_NUM_4), - AS(QZ_KP5, WKC_NUM_5), - AS(QZ_KP6, WKC_NUM_6), - AS(QZ_KP7, WKC_NUM_7), - AS(QZ_KP8, WKC_NUM_8), - AS(QZ_KP9, WKC_NUM_9), - AS(QZ_KP_DIVIDE, WKC_NUM_DIV), - AS(QZ_KP_MULTIPLY, WKC_NUM_MUL), - AS(QZ_KP_MINUS, WKC_NUM_MINUS), - AS(QZ_KP_PLUS, WKC_NUM_PLUS), - AS(QZ_KP_ENTER, WKC_NUM_ENTER), - AS(QZ_KP_PERIOD, WKC_NUM_DECIMAL) -}; - - -static uint32 QZ_MapKey(unsigned short sym) -{ - const VkMapping *map; - uint32 key = 0; - - for (map = _vk_mapping; map != endof(_vk_mapping); ++map) { - if (sym == map->vk_from) { - key = map->map_to; - break; - } - } - - if (_cocoa_video_data.current_mods & NSShiftKeyMask) key |= WKC_SHIFT; - if (_cocoa_video_data.current_mods & NSControlKeyMask) key |= WKC_CTRL; - if (_cocoa_video_data.current_mods & NSAlternateKeyMask) key |= WKC_ALT; - if (_cocoa_video_data.current_mods & NSCommandKeyMask) key |= WKC_META; - - return key << 16; -} - -static void QZ_KeyEvent(unsigned short keycode, unsigned short unicode, BOOL down) -{ - switch (keycode) { - case QZ_UP: SB(_dirkeys, 1, 1, down); break; - case QZ_DOWN: SB(_dirkeys, 3, 1, down); break; - case QZ_LEFT: SB(_dirkeys, 0, 1, down); break; - case QZ_RIGHT: SB(_dirkeys, 2, 1, down); break; - - case QZ_TAB: _cocoa_video_data.tab_is_down = down; break; - - case QZ_RETURN: - case QZ_f: - if (down && ( - (_cocoa_video_data.current_mods & NSControlKeyMask) || - (_cocoa_video_data.current_mods & NSCommandKeyMask) - )) { - CocoaVideoFullScreen(!_fullscreen); - } - break; - } - - if (down) { - uint32 pressed_key = QZ_MapKey(keycode) | unicode; - HandleKeypress(pressed_key); - DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), down, mapping: %x", keycode, unicode, pressed_key); - } else { - DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), up", keycode, unicode); - } -} - -static void QZ_DoUnsidedModifiers(unsigned int newMods) -{ - const int mapping[] = { QZ_CAPSLOCK, QZ_LSHIFT, QZ_LCTRL, QZ_LALT, QZ_LMETA }; - - int i; - int bit; - - if (_cocoa_video_data.current_mods == newMods) return; - - /* Iterate through the bits, testing each against the current modifiers */ - for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { - unsigned int currentMask, newMask; - - currentMask = _cocoa_video_data.current_mods & bit; - newMask = newMods & bit; - - if (currentMask && currentMask != newMask) { /* modifier up event */ - /* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */ - if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, YES); - QZ_KeyEvent(mapping[i], 0, NO); - } else if (newMask && currentMask != newMask) { /* modifier down event */ - QZ_KeyEvent(mapping[i], 0, YES); - /* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */ - if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, NO); - } - } - - _cocoa_video_data.current_mods = newMods; -} - -static void QZ_MouseMovedEvent(int x, int y) -{ - if (_cursor.fix_at) { - int dx = x - _cursor.pos.x; - int dy = y - _cursor.pos.y; - - if (dx != 0 || dy != 0) { - _cursor.delta.x += dx; - _cursor.delta.y += dy; - - QZ_WarpCursor(_cursor.pos.x, _cursor.pos.y); - } - } else { - _cursor.delta.x = x - _cursor.pos.x; - _cursor.delta.y = y - _cursor.pos.y; - _cursor.pos.x = x; - _cursor.pos.y = y; - _cursor.dirty = true; - } - HandleMouseEvents(); -} - - -static void QZ_MouseButtonEvent(int button, BOOL down) -{ - switch (button) { - case 0: - if (down) { - _left_button_down = true; - } else { - _left_button_down = false; - _left_button_clicked = false; - } - HandleMouseEvents(); - break; - - case 1: - if (down) { - _right_button_down = true; - _right_button_clicked = true; - } else { - _right_button_down = false; - } - HandleMouseEvents(); - break; - } -} - - -static inline NSPoint QZ_GetMouseLocation(NSEvent *event) -{ - NSPoint pt; - - if (_cocoa_video_data.fullscreen) { - pt = [ NSEvent mouseLocation ]; - pt.y = _cocoa_video_data.height - pt.y; - } else { - pt = [event locationInWindow]; - pt = [_cocoa_video_data.qdview convertPoint:pt fromView:nil]; - } - - return pt; -} - -static bool QZ_MouseIsInsideView(NSPoint *pt) -{ - if (_cocoa_video_data.fullscreen) { - return pt->x >= 0 && pt->y >= 0 && pt->x < _cocoa_video_data.width && pt->y < _cocoa_video_data.height; - } else { - return [ _cocoa_video_data.qdview mouse:*pt inRect:[ _cocoa_video_data.qdview bounds ] ]; - } -} - - -static bool QZ_PollEvent(void) -{ - NSEvent *event; - NSPoint pt; - NSString *chars; -#ifdef _DEBUG - uint32 et0, et; -#endif - -#ifdef _DEBUG - et0 = GetTick(); -#endif - event = [ NSApp nextEventMatchingMask:NSAnyEventMask - untilDate: [ NSDate distantPast ] - inMode: NSDefaultRunLoopMode dequeue:YES ]; -#ifdef _DEBUG - et = GetTick(); - _cocoa_video_data.tEvent+= et - et0; -#endif - - if (event == nil) return false; - if (!_cocoa_video_data.active) { - QZ_ShowMouse(); - [NSApp sendEvent:event]; - return true; - } - - QZ_DoUnsidedModifiers( [ event modifierFlags ] ); - - switch ([event type]) { - case NSMouseMoved: - case NSOtherMouseDragged: - case NSRightMouseDragged: - case NSLeftMouseDragged: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt) && - !_cocoa_video_data.emulating_right_button) { - QZ_ShowMouse(); - [NSApp sendEvent:event]; - break; - } - - QZ_HideMouse(); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); - break; - - case NSLeftMouseDown: - if (!([ event modifierFlags ] & NSCommandKeyMask) || - !QZ_MouseIsInsideView(&pt)) { - [NSApp sendEvent:event]; - } - - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { - QZ_ShowMouse(); - break; - } - - QZ_HideMouse(); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); - - /* Right mouse button emulation */ - if ([ event modifierFlags ] & NSCommandKeyMask) { - _cocoa_video_data.emulating_right_button = true; - QZ_MouseButtonEvent(1, YES); - } else { - QZ_MouseButtonEvent(0, YES); - } - break; - - case NSLeftMouseUp: - [NSApp sendEvent:event]; - - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { - QZ_ShowMouse(); - break; - } - - QZ_HideMouse(); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); - - /* Right mouse button emulation */ - if (_cocoa_video_data.emulating_right_button) { - _cocoa_video_data.emulating_right_button = false; - QZ_MouseButtonEvent(1, NO); - } else { - QZ_MouseButtonEvent(0, NO); - } - break; - - case NSRightMouseDown: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { - QZ_ShowMouse(); - [NSApp sendEvent:event]; - break; - } - - QZ_HideMouse(); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); - QZ_MouseButtonEvent(1, YES); - break; - - case NSRightMouseUp: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { - QZ_ShowMouse(); - [NSApp sendEvent:event]; - break; - } - - QZ_HideMouse(); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); - QZ_MouseButtonEvent(1, NO); - break; - -#if 0 - /* This is not needed since openttd currently only use two buttons */ - case NSOtherMouseDown: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { - QZ_ShowMouse(); - [NSApp sendEvent:event]; - break; - } - - QZ_HideMouse(); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); - QZ_MouseButtonEvent([ event buttonNumber ], YES); - break; - - case NSOtherMouseUp: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { - QZ_ShowMouse(); - [NSApp sendEvent:event]; - break; - } - - QZ_HideMouse(); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); - QZ_MouseButtonEvent([ event buttonNumber ], NO); - break; -#endif - - case NSKeyDown: - /* Quit, hide and minimize */ - switch ([event keyCode]) { - case QZ_q: - case QZ_h: - case QZ_m: - if ([ event modifierFlags ] & NSCommandKeyMask) { - [NSApp sendEvent:event]; - } - break; - } - - chars = [ event characters ]; - QZ_KeyEvent([event keyCode], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, YES); - break; - - case NSKeyUp: - /* Quit, hide and minimize */ - switch ([event keyCode]) { - case QZ_q: - case QZ_h: - case QZ_m: - if ([ event modifierFlags ] & NSCommandKeyMask) { - [NSApp sendEvent:event]; - } - break; - } - - chars = [ event characters ]; - QZ_KeyEvent([event keyCode], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, NO); - break; - - case NSScrollWheel: - if ([ event deltaY ] > 0.0) { /* Scroll up */ - _cursor.wheel--; - } else if ([ event deltaY ] < 0.0) { /* Scroll down */ - _cursor.wheel++; - } /* else: deltaY was 0.0 and we don't want to do anything */ - break; - - default: - [NSApp sendEvent:event]; - } - - return true; -} - - -static void QZ_GameLoop(void) -{ - uint32 next_tick = GetTick() + 30; - uint32 cur_ticks; - uint32 pal_tick = 0; -#ifdef _DEBUG - uint32 et0, et, st0, st; -#endif - int i; - -#ifdef _DEBUG - et0 = GetTick(); - st = 0; -#endif - - _screen.dst_ptr = _cocoa_video_data.pixels; - DisplaySplashImage(); - QZ_CheckPaletteAnim(); - QZ_Draw(); - CSleep(1); - - for (i = 0; i < 2; i++) GameLoop(); - - _screen.dst_ptr = _cocoa_video_data.pixels; - UpdateWindows(); - QZ_CheckPaletteAnim(); - QZ_Draw(); - CSleep(1); - - for (;;) { - InteractiveRandom(); // randomness - - while (QZ_PollEvent()) {} - - if (_exit_game) break; - -#if defined(_DEBUG) - if (_cocoa_video_data.current_mods & NSShiftKeyMask) -#else - if (_cocoa_video_data.tab_is_down) -#endif - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } - - cur_ticks = GetTick(); - if ((_fast_forward && !_pause) || cur_ticks > next_tick) - next_tick = cur_ticks; - - if (cur_ticks == next_tick) { - next_tick += 30; - - _ctrl_pressed = !!(_cocoa_video_data.current_mods & NSControlKeyMask); - _shift_pressed = !!(_cocoa_video_data.current_mods & NSShiftKeyMask); -#ifdef _DEBUG - _dbg_screen_rect = !!(_cocoa_video_data.current_mods & NSAlphaShiftKeyMask); -#endif - - GameLoop(); - - _screen.dst_ptr = _cocoa_video_data.pixels; - UpdateWindows(); - if (++pal_tick > 4) { - QZ_CheckPaletteAnim(); - pal_tick = 1; - } - QZ_Draw(); - } else { -#ifdef _DEBUG - st0 = GetTick(); -#endif - CSleep(1); -#ifdef _DEBUG - st += GetTick() - st0; -#endif - _screen.dst_ptr = _cocoa_video_data.pixels; - DrawTextMessage(); - DrawMouseCursor(); - QZ_Draw(); - } - } - -#ifdef _DEBUG - et = GetTick(); - - DEBUG(driver, 1, "cocoa_v: nextEventMatchingMask took %i ms total", _cocoa_video_data.tEvent); - DEBUG(driver, 1, "cocoa_v: game loop took %i ms total (%i ms without sleep)", et - et0, et - et0 - st); - DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop total) is %f%%", (double)_cocoa_video_data.tEvent / (double)(et - et0) * 100); - DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop without sleep total) is %f%%", (double)_cocoa_video_data.tEvent / (double)(et - et0 - st) * 100); -#endif -} - - -/****************************************************************************** - * Windowed mode * - ******************************************************************************/ - -/* This function makes the *game region* of the window 100% opaque. - * The genie effect uses the alpha component. Otherwise, - * it doesn't seem to matter what value it has. - */ -static void QZ_SetPortAlphaOpaque(void) -{ - if (_cocoa_video_data.device_bpp == 32) { - uint32* pixels = (uint32*)_cocoa_video_data.realpixels; - uint32 rowPixels = _cocoa_video_data.pitch / 4; - uint32 i; - uint32 j; - - for (i = 0; i < _cocoa_video_data.height; i++) - for (j = 0; j < _cocoa_video_data.width; j++) { - pixels[i * rowPixels + j] |= 0xFF000000; - } - } -} - - -@implementation OTTD_QuartzWindow - -/* we override these methods to fix the miniaturize animation/dock icon bug */ -- (void)miniaturize:(id)sender -{ - /* make the alpha channel opaque so anim won't have holes in it */ - QZ_SetPortAlphaOpaque (); - - /* window is hidden now */ - _cocoa_video_data.active = false; - - QZ_ShowMouse(); - - [ super miniaturize:sender ]; -} - -- (void)display -{ - /* This method fires just before the window deminaturizes from the Dock. - * We'll save the current visible surface, let the window manager redraw any - * UI elements, and restore the surface. This way, no expose event - * is required, and the deminiaturize works perfectly. - */ - - QZ_SetPortAlphaOpaque(); - - /* save current visible surface */ - [ self cacheImageInRect:[ _cocoa_video_data.qdview frame ] ]; - - /* let the window manager redraw controls, border, etc */ - [ super display ]; - - /* restore visible surface */ - [ self restoreCachedImage ]; - - /* window is visible again */ - _cocoa_video_data.active = true; -} - -- (void)setFrame:(NSRect)frameRect display:(BOOL)flag -{ - NSRect newViewFrame; - CGrafPtr thePort; - - [ super setFrame:frameRect display:flag ]; - - /* Don't do anything if the window is currently beign created */ - if (_cocoa_video_data.issetting) return; - - if (_cocoa_video_data.window == nil) return; - - newViewFrame = [ _cocoa_video_data.qdview frame ]; - - /* Update the pixels and pitch */ - thePort = [ _cocoa_video_data.qdview qdPort ]; - LockPortBits(thePort); - - _cocoa_video_data.realpixels = GetPixBaseAddr(GetPortPixMap(thePort)); - _cocoa_video_data.pitch = GetPixRowBytes(GetPortPixMap(thePort)); - - /* _cocoa_video_data.realpixels now points to the window's pixels - * We want it to point to the *view's* pixels - */ - { - int vOffset = [ _cocoa_video_data.window frame ].size.height - newViewFrame.size.height - newViewFrame.origin.y; - int hOffset = newViewFrame.origin.x; - - _cocoa_video_data.realpixels = (uint8*)_cocoa_video_data.realpixels + (vOffset * _cocoa_video_data.pitch) + hOffset * (_cocoa_video_data.device_bpp / 8); - } - - UnlockPortBits(thePort); - - /* Allocate new buffer */ - free(_cocoa_video_data.pixels); - _cocoa_video_data.pixels = (uint8*)malloc(newViewFrame.size.width * newViewFrame.size.height); - assert(_cocoa_video_data.pixels != NULL); - - - /* Tell the game that the resolution changed */ - _cocoa_video_data.width = newViewFrame.size.width; - _cocoa_video_data.height = newViewFrame.size.height; - - _screen.width = _cocoa_video_data.width; - _screen.height = _cocoa_video_data.height; - _screen.pitch = _cocoa_video_data.width; - - GameSizeChanged(); - - /* Redraw screen */ - _cocoa_video_data.num_dirty_rects = MAX_DIRTY_RECTS; -} - -- (void)appDidHide:(NSNotification*)note -{ - _cocoa_video_data.active = false; -} - - -- (void)appWillUnhide:(NSNotification*)note -{ - QZ_SetPortAlphaOpaque (); - - /* save current visible surface */ - [ self cacheImageInRect:[ _cocoa_video_data.qdview frame ] ]; -} - -- (void)appDidUnhide:(NSNotification*)note -{ - /* restore cached image, since it may not be current, post expose event too */ - [ self restoreCachedImage ]; - - _cocoa_video_data.active = true; -} - - -- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag -{ - /* Make our window subclass receive these application notifications */ - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; - - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; - - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ]; - - return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]; -} - -@end - -@implementation OTTD_QuartzWindowDelegate -- (BOOL)windowShouldClose:(id)sender -{ - HandleExitGameRequest(); - - return NO; -} - -- (void)windowDidBecomeKey:(NSNotification*)aNotification -{ - _cocoa_video_data.active = true; -} - -- (void)windowDidResignKey:(NSNotification*)aNotification -{ - _cocoa_video_data.active = false; -} - -- (void)windowDidBecomeMain:(NSNotification*)aNotification -{ - _cocoa_video_data.active = true; -} - -- (void)windowDidResignMain:(NSNotification*)aNotification -{ - _cocoa_video_data.active = false; -} - -@end - - -static void QZ_UpdateWindowPalette(uint start, uint count) -{ - uint i; - - switch (_cocoa_video_data.device_bpp) { - case 32: - for (i = start; i < start + count; i++) { - uint32 clr32 = 0xff000000; - clr32 |= (uint32)_cur_palette[i].r << 16; - clr32 |= (uint32)_cur_palette[i].g << 8; - clr32 |= (uint32)_cur_palette[i].b; - _cocoa_video_data.palette32[i] = clr32; - } - break; - case 16: - for (i = start; i < start + count; i++) { - uint16 clr16 = 0x0000; - clr16 |= (uint16)((_cur_palette[i].r >> 3) & 0x1f) << 10; - clr16 |= (uint16)((_cur_palette[i].g >> 3) & 0x1f) << 5; - clr16 |= (uint16)((_cur_palette[i].b >> 3) & 0x1f); - _cocoa_video_data.palette16[i] = clr16; - } - break; - } - - _cocoa_video_data.num_dirty_rects = MAX_DIRTY_RECTS; -} - -static inline void QZ_WindowBlitIndexedPixelsToView32(uint left, uint top, uint right, uint bottom) -{ - const uint32* pal = _cocoa_video_data.palette32; - const uint8* src = _cocoa_video_data.pixels; - uint32* dst = (uint32*)_cocoa_video_data.realpixels; - uint width = _cocoa_video_data.width; - uint pitch = _cocoa_video_data.pitch / 4; - uint x; - uint y; - - for (y = top; y < bottom; y++) { - for (x = left; x < right; x++) { - dst[y * pitch + x] = pal[src[y * width + x]]; - } - } -} - -static inline void QZ_WindowBlitIndexedPixelsToView16(uint left, uint top, uint right, uint bottom) -{ - const uint16* pal = _cocoa_video_data.palette16; - const uint8* src = _cocoa_video_data.pixels; - uint16* dst = (uint16*)_cocoa_video_data.realpixels; - uint width = _cocoa_video_data.width; - uint pitch = _cocoa_video_data.pitch / 2; - uint x; - uint y; - - for (y = top; y < bottom; y++) { - for (x = left; x < right; x++) { - dst[y * pitch + x] = pal[src[y * width + x]]; - } - } -} - -static inline void QZ_WindowBlitIndexedPixelsToView(int left, int top, int right, int bottom) -{ - switch (_cocoa_video_data.device_bpp) { - case 32: QZ_WindowBlitIndexedPixelsToView32(left, top, right, bottom); break; - case 16: QZ_WindowBlitIndexedPixelsToView16(left, top, right, bottom); break; - } -} - -static bool _resize_icon[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, - 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, - 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, - 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, - 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, - 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0 -}; - -static void QZ_DrawResizeIcon(void) -{ - int xoff = _cocoa_video_data.width - 16; - int yoff = _cocoa_video_data.height - 16; - int x; - int y; - - for (y = 0; y < 16; y++) { - uint16* trg16 = (uint16*)_cocoa_video_data.realpixels + (yoff + y) * _cocoa_video_data.pitch / 2 + xoff; - uint32* trg32 = (uint32*)_cocoa_video_data.realpixels + (yoff + y) * _cocoa_video_data.pitch / 4 + xoff; - - for (x = 0; x < 16; x++, trg16++, trg32++) { - if (!_resize_icon[y * 16 + x]) continue; - - switch (_cocoa_video_data.device_bpp) { - case 32: *trg32 = 0xff000000; break; - case 16: *trg16 = 0x0000; break; - } - } - } -} - -static void QZ_DrawWindow(void) -{ - int i; - RgnHandle dirty, temp; - - /* Check if we need to do anything */ - if (_cocoa_video_data.num_dirty_rects == 0 || - [ _cocoa_video_data.window isMiniaturized ]) { - return; - } - - if (_cocoa_video_data.num_dirty_rects >= MAX_DIRTY_RECTS) { - _cocoa_video_data.num_dirty_rects = 1; - _cocoa_video_data.dirty_rects[0].left = 0; - _cocoa_video_data.dirty_rects[0].top = 0; - _cocoa_video_data.dirty_rects[0].right = _cocoa_video_data.width; - _cocoa_video_data.dirty_rects[0].bottom = _cocoa_video_data.height; - } - - dirty = NewRgn(); - temp = NewRgn(); - - SetEmptyRgn(dirty); - - /* Build the region of dirty rectangles */ - for (i = 0; i < _cocoa_video_data.num_dirty_rects; i++) { - QZ_WindowBlitIndexedPixelsToView( - _cocoa_video_data.dirty_rects[i].left, - _cocoa_video_data.dirty_rects[i].top, - _cocoa_video_data.dirty_rects[i].right, - _cocoa_video_data.dirty_rects[i].bottom - ); - - MacSetRectRgn( - temp, - _cocoa_video_data.dirty_rects[i].left, - _cocoa_video_data.dirty_rects[i].top, - _cocoa_video_data.dirty_rects[i].right, - _cocoa_video_data.dirty_rects[i].bottom - ); - MacUnionRgn(dirty, temp, dirty); - } - - QZ_DrawResizeIcon(); - - /* Flush the dirty region */ - QDFlushPortBuffer([ _cocoa_video_data.qdview qdPort ], dirty); - DisposeRgn(dirty); - DisposeRgn(temp); - - _cocoa_video_data.num_dirty_rects = 0; -} - - -extern const char _openttd_revision[]; - -static const char* QZ_SetVideoWindowed(uint width, uint height) -{ - char caption[50]; - NSString *nsscaption; - unsigned int style; - NSRect contentRect; - BOOL isCustom = NO; - - if (width > _cocoa_video_data.device_width) - width = _cocoa_video_data.device_width; - if (height > _cocoa_video_data.device_height) - height = _cocoa_video_data.device_height; - - _cocoa_video_data.width = width; - _cocoa_video_data.height = height; - - contentRect = NSMakeRect(0, 0, width, height); - - /* Check if we should completely destroy the previous mode - * - If it is fullscreen - */ - if (_cocoa_video_data.isset && _cocoa_video_data.fullscreen) - QZ_UnsetVideoMode(); - - /* Check if we should recreate the window */ - if (_cocoa_video_data.window == nil) { - /* Set the window style */ - style = NSTitledWindowMask; - style |= (NSMiniaturizableWindowMask | NSClosableWindowMask); - style |= NSResizableWindowMask; - - /* Manually create a window, avoids having a nib file resource */ - _cocoa_video_data.window = [ [ OTTD_QuartzWindow alloc ] - initWithContentRect:contentRect - styleMask:style - backing:NSBackingStoreBuffered - defer:NO ]; - - if (_cocoa_video_data.window == nil) - return "Could not create the Cocoa window"; - - snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision); - nsscaption = [ [ NSString alloc ] initWithCString:caption ]; - [ _cocoa_video_data.window setTitle:nsscaption ]; - [ _cocoa_video_data.window setMiniwindowTitle:nsscaption ]; - [ nsscaption release ]; - - [ _cocoa_video_data.window setAcceptsMouseMovedEvents:YES ]; - [ _cocoa_video_data.window setViewsNeedDisplay:NO ]; - - [ _cocoa_video_data.window setDelegate: [ [ [ OTTD_QuartzWindowDelegate alloc ] init ] autorelease ] ]; - } else { - /* We already have a window, just change its size */ - if (!isCustom) { - [ _cocoa_video_data.window setContentSize:contentRect.size ]; - [ _cocoa_video_data.qdview setFrameSize:contentRect.size ]; - } - } - - [ _cocoa_video_data.window center ]; - - /* Only recreate the view if it doesn't already exist */ - if (_cocoa_video_data.qdview == nil) { - _cocoa_video_data.qdview = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; - [ _cocoa_video_data.qdview setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; - [ [ _cocoa_video_data.window contentView ] addSubview:_cocoa_video_data.qdview ]; - [ _cocoa_video_data.qdview release ]; - [ _cocoa_video_data.window makeKeyAndOrderFront:nil ]; - } - - LockPortBits([ _cocoa_video_data.qdview qdPort ]); - _cocoa_video_data.realpixels = GetPixBaseAddr(GetPortPixMap([ _cocoa_video_data.qdview qdPort ])); - _cocoa_video_data.pitch = GetPixRowBytes(GetPortPixMap([ _cocoa_video_data.qdview qdPort ])); - UnlockPortBits([ _cocoa_video_data.qdview qdPort ]); - - /* _cocoa_video_data.realpixels now points to the window's pixels - * We want it to point to the *view's* pixels - */ - { - int vOffset = [ _cocoa_video_data.window frame ].size.height - [ _cocoa_video_data.qdview frame ].size.height - [ _cocoa_video_data.qdview frame ].origin.y; - int hOffset = [ _cocoa_video_data.qdview frame ].origin.x; - - _cocoa_video_data.realpixels = (uint8*)_cocoa_video_data.realpixels + (vOffset * _cocoa_video_data.pitch) + hOffset * (_cocoa_video_data.device_bpp / 8); - } - - free(_cocoa_video_data.pixels); - _cocoa_video_data.pixels = (uint8*)malloc(width * height); - if (_cocoa_video_data.pixels == NULL) return "Failed to allocate 8-bit buffer"; - - _cocoa_video_data.fullscreen = false; - - return NULL; -} - - -/****************************************************************************** - * Fullscreen mode * - ******************************************************************************/ - -/* Gamma functions to try to hide the flash from a rez switch - * Fade the display from normal to black - * Save gamma tables for fade back to normal - */ -static uint32 QZ_FadeGammaOut(OTTD_QuartzGammaTable* table) -{ - CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE]; - CGGammaValue greenTable[QZ_GAMMA_TABLE_SIZE]; - CGGammaValue blueTable[QZ_GAMMA_TABLE_SIZE]; - float percent; - int j; - unsigned int actual; - - if (CGGetDisplayTransferByTable( - _cocoa_video_data.display_id, QZ_GAMMA_TABLE_SIZE, - table->red, table->green, table->blue, &actual - ) != CGDisplayNoErr || - actual != QZ_GAMMA_TABLE_SIZE) { - return 1; - } - - memcpy(redTable, table->red, sizeof(redTable)); - memcpy(greenTable, table->green, sizeof(greenTable)); - memcpy(blueTable, table->blue, sizeof(greenTable)); - - for (percent = 1.0; percent >= 0.0; percent -= 0.01) { - for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) { - redTable[j] = redTable[j] * percent; - greenTable[j] = greenTable[j] * percent; - blueTable[j] = blueTable[j] * percent; - } - - if (CGSetDisplayTransferByTable( - _cocoa_video_data.display_id, QZ_GAMMA_TABLE_SIZE, - redTable, greenTable, blueTable - ) != CGDisplayNoErr) { - CGDisplayRestoreColorSyncSettings(); - return 1; - } - - CSleep(10); - } - - return 0; -} - -/* Fade the display from black to normal - * Restore previously saved gamma values - */ -static uint32 QZ_FadeGammaIn(const OTTD_QuartzGammaTable* table) -{ - CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE]; - CGGammaValue greenTable[QZ_GAMMA_TABLE_SIZE]; - CGGammaValue blueTable[QZ_GAMMA_TABLE_SIZE]; - float percent; - int j; - - memset(redTable, 0, sizeof(redTable)); - memset(greenTable, 0, sizeof(greenTable)); - memset(blueTable, 0, sizeof(greenTable)); - - for (percent = 0.0; percent <= 1.0; percent += 0.01) { - for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) { - redTable[j] = table->red[j] * percent; - greenTable[j] = table->green[j] * percent; - blueTable[j] = table->blue[j] * percent; - } - - if (CGSetDisplayTransferByTable( - _cocoa_video_data.display_id, QZ_GAMMA_TABLE_SIZE, - redTable, greenTable, blueTable - ) != CGDisplayNoErr) { - CGDisplayRestoreColorSyncSettings(); - return 1; - } - - CSleep(10); - } - - return 0; -} - -static const char* QZ_SetVideoFullScreen(int width, int height) -{ - const char* errstr = "QZ_SetVideoFullScreen error"; - int exact_match; - CFNumberRef number; - int bpp; - int gamma_error; - OTTD_QuartzGammaTable gamma_table; - NSRect screen_rect; - CGError error; - NSPoint pt; - - /* Destroy any previous mode */ - if (_cocoa_video_data.isset) QZ_UnsetVideoMode(); - - /* See if requested mode exists */ - _cocoa_video_data.mode = CGDisplayBestModeForParameters(_cocoa_video_data.display_id, 8, width, height, &exact_match); - - /* If the mode wasn't an exact match, check if it has the right bpp, and update width and height */ - if (!exact_match) { - number = CFDictionaryGetValue (_cocoa_video_data.mode, kCGDisplayBitsPerPixel); - CFNumberGetValue(number, kCFNumberSInt32Type, &bpp); - if (bpp != 8) { - errstr = "Failed to find display resolution"; - goto ERR_NO_MATCH; - } - - number = CFDictionaryGetValue(_cocoa_video_data.mode, kCGDisplayWidth); - CFNumberGetValue(number, kCFNumberSInt32Type, &width); - - number = CFDictionaryGetValue(_cocoa_video_data.mode, kCGDisplayHeight); - CFNumberGetValue(number, kCFNumberSInt32Type, &height); - } - - /* Fade display to zero gamma */ - gamma_error = QZ_FadeGammaOut(&gamma_table); - - /* Put up the blanking window (a window above all other windows) */ - error = CGDisplayCapture(_cocoa_video_data.display_id); - - if (CGDisplayNoErr != error) { - errstr = "Failed capturing display"; - goto ERR_NO_CAPTURE; - } - - /* Do the physical switch */ - if (CGDisplaySwitchToMode(_cocoa_video_data.display_id, _cocoa_video_data.mode) != CGDisplayNoErr) { - errstr = "Failed switching display resolution"; - goto ERR_NO_SWITCH; - } - - _cocoa_video_data.realpixels = (uint8*)CGDisplayBaseAddress(_cocoa_video_data.display_id); - _cocoa_video_data.pitch = CGDisplayBytesPerRow(_cocoa_video_data.display_id); - - _cocoa_video_data.width = CGDisplayPixelsWide(_cocoa_video_data.display_id); - _cocoa_video_data.height = CGDisplayPixelsHigh(_cocoa_video_data.display_id); - _cocoa_video_data.fullscreen = true; - - /* Setup double-buffer emulation */ - _cocoa_video_data.pixels = (uint8*)malloc(width * height); - if (_cocoa_video_data.pixels == NULL) { - errstr = "Failed to allocate memory for double buffering"; - goto ERR_DOUBLEBUF; - } - - if (!CGDisplayCanSetPalette(_cocoa_video_data.display_id)) { - errstr = "Not an indexed display mode."; - goto ERR_NOT_INDEXED; - } - - /* If we don't hide menu bar, it will get events and interrupt the program */ - HideMenuBar(); - - /* Fade the display to original gamma */ - if (!gamma_error) QZ_FadeGammaIn(&gamma_table); - - /* There is a bug in Cocoa where NSScreen doesn't synchronize - * with CGDirectDisplay, so the main screen's frame is wrong. - * As a result, coordinate translation produces incorrect results. - * We can hack around this bug by setting the screen rect ourselves. - * This hack should be removed if/when the bug is fixed. - */ - screen_rect = NSMakeRect(0, 0, width, height); - [ [ NSScreen mainScreen ] setFrame:screen_rect ]; - - /* we're fullscreen, so flag all input states... */ - _cocoa_video_data.active = true; - - - pt = [ NSEvent mouseLocation ]; - pt.y = CGDisplayPixelsHigh(_cocoa_video_data.display_id) - pt.y; - if (QZ_MouseIsInsideView(&pt)) QZ_HideMouse(); - - return NULL; - -/* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ -ERR_NOT_INDEXED: - free(_cocoa_video_data.pixels); - _cocoa_video_data.pixels = NULL; -ERR_DOUBLEBUF: - CGDisplaySwitchToMode(_cocoa_video_data.display_id, _cocoa_video_data.save_mode); -ERR_NO_SWITCH: - CGReleaseAllDisplays(); -ERR_NO_CAPTURE: - if (!gamma_error) QZ_FadeGammaIn(&gamma_table); -ERR_NO_MATCH: - return errstr; -} - - -static void QZ_UpdateFullscreenPalette(uint first_color, uint num_colors) -{ - CGTableCount index; - CGDeviceColor color; - - for (index = first_color; index < first_color+num_colors; index++) { - /* Clamp colors between 0.0 and 1.0 */ - color.red = _cur_palette[index].r / 255.0; - color.blue = _cur_palette[index].b / 255.0; - color.green = _cur_palette[index].g / 255.0; - - CGPaletteSetColorAtIndex(_cocoa_video_data.palette, color, index); - } - - CGDisplaySetPalette(_cocoa_video_data.display_id, _cocoa_video_data.palette); -} - -/* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */ -static void QZ_WaitForVerticalBlank(void) -{ - /* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */ - double refreshRate; - double linesPerSecond; - double target; - double position; - double adjustment; - CFNumberRef refreshRateCFNumber; - - refreshRateCFNumber = CFDictionaryGetValue(_cocoa_video_data.mode, kCGDisplayRefreshRate); - if (refreshRateCFNumber == NULL) return; - - if (CFNumberGetValue(refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) == 0) - return; - - if (refreshRate == 0) return; - - linesPerSecond = refreshRate * _cocoa_video_data.height; - target = _cocoa_video_data.height; - - /* Figure out the first delay so we start off about right */ - position = CGDisplayBeamPosition(_cocoa_video_data.display_id); - if (position > target) position = 0; - - adjustment = (target - position) / linesPerSecond; - - CSleep((uint32)(adjustment * 1000)); -} - - -static void QZ_DrawScreen(void) -{ - const uint8* src = _cocoa_video_data.pixels; - uint8* dst = (uint8*)_cocoa_video_data.realpixels; - uint pitch = _cocoa_video_data.pitch; - uint width = _cocoa_video_data.width; - uint num_dirty = _cocoa_video_data.num_dirty_rects; - uint i; - - /* Check if we need to do anything */ - if (num_dirty == 0) return; - - if (num_dirty >= MAX_DIRTY_RECTS) { - num_dirty = 1; - _cocoa_video_data.dirty_rects[0].left = 0; - _cocoa_video_data.dirty_rects[0].top = 0; - _cocoa_video_data.dirty_rects[0].right = _cocoa_video_data.width; - _cocoa_video_data.dirty_rects[0].bottom = _cocoa_video_data.height; - } - - QZ_WaitForVerticalBlank(); - /* Build the region of dirty rectangles */ - for (i = 0; i < num_dirty; i++) { - uint y = _cocoa_video_data.dirty_rects[i].top; - uint left = _cocoa_video_data.dirty_rects[i].left; - uint length = _cocoa_video_data.dirty_rects[i].right - left; - uint bottom = _cocoa_video_data.dirty_rects[i].bottom; - - for (; y < bottom; y++) { - memcpy(dst + y * pitch + left, src + y * width + left, length); - } - } - - _cocoa_video_data.num_dirty_rects = 0; -} - - -static int QZ_ListFullscreenModes(OTTDPoint* mode_list, int max_modes) -{ - CFIndex num_modes; - CFIndex i; - int list_size = 0; - - num_modes = CFArrayGetCount(_cocoa_video_data.mode_list); - - /* Build list of modes with the requested bpp */ - for (i = 0; i < num_modes && list_size < max_modes; i++) { - CFDictionaryRef onemode; - CFNumberRef number; - int bpp; - int intvalue; - bool hasMode; - uint16 width, height; - - onemode = CFArrayGetValueAtIndex(_cocoa_video_data.mode_list, i); - number = CFDictionaryGetValue(onemode, kCGDisplayBitsPerPixel); - CFNumberGetValue (number, kCFNumberSInt32Type, &bpp); - - if (bpp != 8) continue; - - number = CFDictionaryGetValue(onemode, kCGDisplayWidth); - CFNumberGetValue(number, kCFNumberSInt32Type, &intvalue); - width = (uint16)intvalue; - - number = CFDictionaryGetValue(onemode, kCGDisplayHeight); - CFNumberGetValue(number, kCFNumberSInt32Type, &intvalue); - height = (uint16)intvalue; - - /* Check if mode is already in the list */ - { - int i; - hasMode = false; - for (i = 0; i < list_size; i++) { - if (mode_list[i].x == width && mode_list[i].y == height) { - hasMode = true; - break; - } - } - } - - if (hasMode) continue; - - /* Add mode to the list */ - mode_list[list_size].x = width; - mode_list[list_size].y = height; - list_size++; - } - - /* Sort list smallest to largest */ - { - int i, j; - for (i = 0; i < list_size; i++) { - for (j = 0; j < list_size-1; j++) { - if (mode_list[j].x > mode_list[j + 1].x || ( - mode_list[j].x == mode_list[j + 1].x && - mode_list[j].y > mode_list[j + 1].y - )) { - uint tmpw = mode_list[j].x; - uint tmph = mode_list[j].y; - - mode_list[j].x = mode_list[j + 1].x; - mode_list[j].y = mode_list[j + 1].y; - - mode_list[j + 1].x = tmpw; - mode_list[j + 1].y = tmph; - } - } - } - } - - return list_size; -} - - -/****************************************************************************** - * Windowed and fullscreen common code * - ******************************************************************************/ - -static void QZ_UpdatePalette(uint start, uint count) -{ - if (_cocoa_video_data.fullscreen) { - QZ_UpdateFullscreenPalette(start, count); - } else { - QZ_UpdateWindowPalette(start, count); - } -} - -static void QZ_InitPalette(void) -{ - QZ_UpdatePalette(0, 256); -} - -static void QZ_Draw(void) -{ - if (_cocoa_video_data.fullscreen) { - QZ_DrawScreen(); - } else { - QZ_DrawWindow(); - } -} - - -static const OTTDPoint _default_resolutions[] = { - { 640, 480}, - { 800, 600}, - {1024, 768}, - {1152, 864}, - {1280, 800}, - {1280, 960}, - {1280, 1024}, - {1400, 1050}, - {1600, 1200}, - {1680, 1050}, - {1920, 1200} -}; - -static void QZ_UpdateVideoModes(void) -{ - uint i, j, count; - OTTDPoint modes[32]; - const OTTDPoint *current_modes; - - if (_cocoa_video_data.fullscreen) { - count = QZ_ListFullscreenModes(modes, 32); - current_modes = modes; - } else { - count = lengthof(_default_resolutions); - current_modes = _default_resolutions; - } - - for (i = 0, j = 0; j < lengthof(_resolutions) && i < count; i++) { - if (_cocoa_video_data.fullscreen || ( - (uint)current_modes[i].x < _cocoa_video_data.device_width && - (uint)current_modes[i].y < _cocoa_video_data.device_height) - ) { - _resolutions[j][0] = current_modes[i].x; - _resolutions[j][1] = current_modes[i].y; - j++; - } - } - - _num_resolutions = j; -} - -static void QZ_UnsetVideoMode(void) -{ - if (_cocoa_video_data.fullscreen) { - /* Release fullscreen resources */ - OTTD_QuartzGammaTable gamma_table; - int gamma_error; - NSRect screen_rect; - - gamma_error = QZ_FadeGammaOut(&gamma_table); - - /* Restore original screen resolution/bpp */ - CGDisplaySwitchToMode(_cocoa_video_data.display_id, _cocoa_video_data.save_mode); - CGReleaseAllDisplays(); - ShowMenuBar(); - /* Reset the main screen's rectangle - * See comment in QZ_SetVideoFullscreen for why we do this - */ - screen_rect = NSMakeRect(0,0,_cocoa_video_data.device_width,_cocoa_video_data.device_height); - [ [ NSScreen mainScreen ] setFrame:screen_rect ]; - - if (!gamma_error) QZ_FadeGammaIn(&gamma_table); - } else { - /* Release window mode resources */ - [ _cocoa_video_data.window close ]; - _cocoa_video_data.window = nil; - _cocoa_video_data.qdview = nil; - } - - free(_cocoa_video_data.pixels); - _cocoa_video_data.pixels = NULL; - - /* Signal successful teardown */ - _cocoa_video_data.isset = false; - - QZ_ShowMouse(); -} - - -static const char* QZ_SetVideoMode(uint width, uint height, bool fullscreen) -{ - const char *ret; - - _cocoa_video_data.issetting = true; - if (fullscreen) { - /* Setup full screen video */ - ret = QZ_SetVideoFullScreen(width, height); - } else { - /* Setup windowed video */ - ret = QZ_SetVideoWindowed(width, height); - } - _cocoa_video_data.issetting = false; - if (ret != NULL) return ret; - - /* Signal successful completion (used internally) */ - _cocoa_video_data.isset = true; - - /* Tell the game that the resolution has changed */ - _screen.width = _cocoa_video_data.width; - _screen.height = _cocoa_video_data.height; - _screen.pitch = _cocoa_video_data.width; - - QZ_UpdateVideoModes(); - GameSizeChanged(); - - QZ_InitPalette(); - - return NULL; -} - -static const char* QZ_SetVideoModeAndRestoreOnFailure(uint width, uint height, bool fullscreen) -{ - bool wasset = _cocoa_video_data.isset; - uint32 oldwidth = _cocoa_video_data.width; - uint32 oldheight = _cocoa_video_data.height; - bool oldfullscreen = _cocoa_video_data.fullscreen; - const char *ret; - - ret = QZ_SetVideoMode(width, height, fullscreen); - if (ret != NULL && wasset) QZ_SetVideoMode(oldwidth, oldheight, oldfullscreen); - - return ret; -} - -static void QZ_VideoInit(void) -{ - memset(&_cocoa_video_data, 0, sizeof(_cocoa_video_data)); - - /* Initialize the video settings; this data persists between mode switches */ - _cocoa_video_data.display_id = kCGDirectMainDisplay; - _cocoa_video_data.save_mode = CGDisplayCurrentMode(_cocoa_video_data.display_id); - _cocoa_video_data.mode_list = CGDisplayAvailableModes(_cocoa_video_data.display_id); - _cocoa_video_data.palette = CGPaletteCreateDefaultColorPalette(); - - /* Gather some information that is useful to know about the display */ - /* Maybe this should be moved to QZ_SetVideoMode, in case this is changed after startup */ - CFNumberGetValue( - CFDictionaryGetValue(_cocoa_video_data.save_mode, kCGDisplayBitsPerPixel), - kCFNumberSInt32Type, &_cocoa_video_data.device_bpp - ); - - CFNumberGetValue( - CFDictionaryGetValue(_cocoa_video_data.save_mode, kCGDisplayWidth), - kCFNumberSInt32Type, &_cocoa_video_data.device_width - ); - - CFNumberGetValue( - CFDictionaryGetValue(_cocoa_video_data.save_mode, kCGDisplayHeight), - kCFNumberSInt32Type, &_cocoa_video_data.device_height - ); - - _cocoa_video_data.cursor_visible = true; - - /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */ -// QZ_RegisterForSleepNotifications(); -} - - -/* Convert local coordinate to window server (CoreGraphics) coordinate */ -static CGPoint QZ_PrivateLocalToCG(NSPoint* p) -{ - CGPoint cgp; - - if (!_cocoa_video_data.fullscreen) { - *p = [ _cocoa_video_data.qdview convertPoint:*p toView: nil ]; - *p = [ _cocoa_video_data.window convertBaseToScreen:*p ]; - p->y = _cocoa_video_data.device_height - p->y; - } - - cgp.x = p->x; - cgp.y = p->y; - - return cgp; -} - -static void QZ_WarpCursor(int x, int y) -{ - NSPoint p; - CGPoint cgp; - - /* Only allow warping when in foreground */ - if (![ NSApp isActive ]) return; - - p = NSMakePoint(x, y); - cgp = QZ_PrivateLocalToCG(&p); - - /* this is the magic call that fixes cursor "freezing" after warp */ - CGSetLocalEventsSuppressionInterval(0.0); - /* Do the actual warp */ - CGWarpMouseCursorPosition(cgp); - - /* Generate the mouse moved event */ -} - -static void QZ_ShowMouse(void) -{ - if (!_cocoa_video_data.cursor_visible) { - [ NSCursor unhide ]; - _cocoa_video_data.cursor_visible = true; - - // Hide the openttd cursor when leaving the window - if (_cocoa_video_data.isset) - UndrawMouseCursor(); - _cursor.in_window = false; - } -} - -static void QZ_HideMouse(void) -{ - if (_cocoa_video_data.cursor_visible) { -#ifndef _DEBUG - [ NSCursor hide ]; -#endif - _cocoa_video_data.cursor_visible = false; - - // Show the openttd cursor again - _cursor.in_window = true; - } -} - - -/****************************************************************************** - * OS X application creation * - ******************************************************************************/ - -/* The main class of the application, the application's delegate */ -@implementation OTTDMain -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification*) note -{ - /* Hand off to main application code */ - QZ_GameLoop(); - - /* We're done, thank you for playing */ - [ NSApp stop:_ottd_main ]; -} - -/* Display the in game quit confirmation dialog */ -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*) sender -{ - - HandleExitGameRequest(); - - return NSTerminateCancel; // NSTerminateLater ? -} -@end - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = @"OTTD"; - appleMenu = [[NSMenu alloc] initWithTitle:appName]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem*)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu* windowMenu; - NSMenuItem* windowMenuItem; - NSMenuItem* menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -static void setupApplication(void) -{ - CPSProcessSerNum PSN; - - /* Ensure the application object is initialised */ - [NSApplication sharedApplication]; - - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN) && - !CPSEnableForegroundOperation(&PSN, 0x03, 0x3C, 0x2C, 0x1103) && - !CPSSetFrontProcess(&PSN)) { - [NSApplication sharedApplication]; - } - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create OTTDMain and make it the app delegate */ - _ottd_main = [[OTTDMain alloc] init]; - [NSApp setDelegate:_ottd_main]; -} - - -/****************************************************************************** - * Video driver interface * - ******************************************************************************/ - -static void CocoaVideoStop(void) -{ - if (!_cocoa_video_started) return; - - if (_cocoa_video_data.isset) QZ_UnsetVideoMode(); - - [_ottd_main release]; - - _cocoa_video_started = false; -} - -static const char *CocoaVideoStart(const char * const *parm) -{ - const char *ret; - - if (_cocoa_video_started) return "Already started"; - _cocoa_video_started = true; - - memset(&_cocoa_video_data, 0, sizeof(_cocoa_video_data)); - - setupApplication(); - - /* Don't create a window or enter fullscreen if we're just going to show a dialog. */ - if (_cocoa_video_dialog) return NULL; - - QZ_VideoInit(); - - ret = QZ_SetVideoMode(_cur_resolution[0], _cur_resolution[1], _fullscreen); - if (ret != NULL) CocoaVideoStop(); - - return ret; -} - -static void CocoaVideoMakeDirty(int left, int top, int width, int height) -{ - if (_cocoa_video_data.num_dirty_rects < MAX_DIRTY_RECTS) { - _cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].left = left; - _cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].top = top; - _cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].right = left + width; - _cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].bottom = top + height; - } - _cocoa_video_data.num_dirty_rects++; -} - -static void CocoaVideoMainLoop(void) -{ - /* Start the main event loop */ - [NSApp run]; -} - -static bool CocoaVideoChangeRes(int w, int h) -{ - const char *ret = QZ_SetVideoModeAndRestoreOnFailure((uint)w, (uint)h, _cocoa_video_data.fullscreen); - if (ret != NULL) { - DEBUG(driver, 0, "cocoa_v: CocoaVideoChangeRes failed with message: %s", ret); - } - - return ret == NULL; -} - -static void CocoaVideoFullScreen(bool full_screen) -{ - const char *ret = QZ_SetVideoModeAndRestoreOnFailure(_cocoa_video_data.width, _cocoa_video_data.height, full_screen); - if (ret != NULL) { - DEBUG(driver, 0, "cocoa_v: CocoaVideoFullScreen failed with message: %s", ret); - } - - _fullscreen = _cocoa_video_data.fullscreen; -} - -const HalVideoDriver _cocoa_video_driver = { - CocoaVideoStart, - CocoaVideoStop, - CocoaVideoMakeDirty, - CocoaVideoMainLoop, - CocoaVideoChangeRes, - CocoaVideoFullScreen, -}; - - -/* This is needed since sometimes assert is called before the videodriver is initialized */ -void CocoaDialog(const char* title, const char* message, const char* buttonLabel) -{ - bool wasstarted; - - _cocoa_video_dialog = true; - - wasstarted = _cocoa_video_started; - if (!_cocoa_video_started && CocoaVideoStart(NULL) != NULL) { - fprintf(stderr, "%s: %s\n", title, message); - return; - } - - NSRunAlertPanel([NSString stringWithCString: title], [NSString stringWithCString: message], [NSString stringWithCString: buttonLabel], nil, nil); - - if (!wasstarted) CocoaVideoStop(); - - _cocoa_video_dialog = false; -} - - -/* This is needed since OS X applications are started with the working dir set to / when double-clicked */ -void cocoaSetWorkingDirectory(void) -{ - char parentdir[MAXPATHLEN]; - int chdir_ret; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (unsigned char*)parentdir, MAXPATHLEN)) { - chdir_ret = chdir(parentdir); /* chdir to the binary app's parent */ - assert(chdir_ret == 0); - } - CFRelease(url); - CFRelease(url2); -} - -/* These are called from main() to prevent a _NSAutoreleaseNoPool error when - * exiting before the cocoa video driver has been loaded - */ -void cocoaSetupAutoreleasePool(void) -{ - _ottd_autorelease_pool = [[NSAutoreleasePool alloc] init]; -} - -void cocoaReleaseAutoreleasePool(void) -{ - [_ottd_autorelease_pool release]; -} - -#endif /* WITH_COCOA */ diff --git a/video/dedicated_v.c b/video/dedicated_v.c deleted file mode 100644 index caa1c8963..000000000 --- a/video/dedicated_v.c +++ /dev/null @@ -1,298 +0,0 @@ -/* $Id$ */ - -#include "../stdafx.h" - -#ifdef ENABLE_NETWORK - -#include "../openttd.h" -#include "../debug.h" -#include "../functions.h" -#include "../gfx.h" -#include "../network/network.h" -#include "../window.h" -#include "../console.h" -#include "../variables.h" -#include "../genworld.h" -#include "dedicated_v.h" - -#ifdef BEOS_NET_SERVER -#include <net/socket.h> -#endif - -#ifdef __OS2__ -# include <sys/time.h> /* gettimeofday */ -# include <sys/types.h> -# include <unistd.h> -# include <conio.h> - -# define INCL_DOS -# include <os2.h> - -# define STDIN 0 /* file descriptor for standard input */ - -/** - * Switches OpenTTD to a console app at run-time, instead of a PM app - * Necessary to see stdout, etc. */ -static void OS2_SwitchToConsoleMode(void) -{ - PPIB pib; - PTIB tib; - - DosGetInfoBlocks(&tib, &pib); - - // Change flag from PM to VIO - pib->pib_ultype = 3; -} -#endif - -#ifdef UNIX -# include <sys/time.h> /* gettimeofday */ -# include <sys/types.h> -# include <unistd.h> -# include <signal.h> -# define STDIN 0 /* file descriptor for standard input */ - -/* Signal handlers */ -static void DedicatedSignalHandler(int sig) -{ - _exit_game = true; - signal(sig, DedicatedSignalHandler); -} -#endif - -#ifdef WIN32 -#include <windows.h> /* GetTickCount */ -#include <conio.h> -#include <time.h> -#include <tchar.h> -static HANDLE _hInputReady, _hWaitForInputHandling; -static HANDLE _hThread; // Thread to close -static char _win_console_thread_buffer[200]; - -/* Windows Console thread. Just loop and signal when input has been received */ -static void WINAPI CheckForConsoleInput(void) -{ - while (true) { - fgets(_win_console_thread_buffer, lengthof(_win_console_thread_buffer), stdin); - /* Signal input waiting that input is read and wait for it being handled - * SignalObjectAndWait() should be used here, but it's unsupported in Win98< */ - SetEvent(_hInputReady); - WaitForSingleObject(_hWaitForInputHandling, INFINITE); - } -} - -static void CreateWindowsConsoleThread(void) -{ - DWORD dwThreadId; - /* Create event to signal when console input is ready */ - _hInputReady = CreateEvent(NULL, false, false, NULL); - _hWaitForInputHandling = CreateEvent(NULL, false, false, NULL); - if (_hInputReady == NULL || _hWaitForInputHandling == NULL) error("Cannot create console event!"); - - _hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, NULL, 0, &dwThreadId); - if (_hThread == NULL) error("Cannot create console thread!"); - - DEBUG(driver, 2, "Windows console thread started"); -} - -static void CloseWindowsConsoleThread(void) -{ - CloseHandle(_hThread); - CloseHandle(_hInputReady); - CloseHandle(_hWaitForInputHandling); - DEBUG(driver, 2, "Windows console thread shut down"); -} - -#endif - - -static void *_dedicated_video_mem; - -extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm); -extern void SwitchMode(int new_mode); - - -static const char *DedicatedVideoStart(const char * const *parm) -{ - _screen.width = _screen.pitch = _cur_resolution[0]; - _screen.height = _cur_resolution[1]; - _dedicated_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]); - - SetDebugString("net=6"); - -#ifdef WIN32 - // For win32 we need to allocate a console (debug mode does the same) - CreateConsole(); - CreateWindowsConsoleThread(); - SetConsoleTitle(_T("OpenTTD Dedicated Server")); -#endif - -#ifdef __OS2__ - // For OS/2 we also need to switch to console mode instead of PM mode - OS2_SwitchToConsoleMode(); -#endif - - DEBUG(driver, 1, "Loading dedicated server"); - return NULL; -} - -static void DedicatedVideoStop(void) -{ -#ifdef WIN32 - CloseWindowsConsoleThread(); -#endif - free(_dedicated_video_mem); -} - -static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {} -static bool DedicatedVideoChangeRes(int w, int h) { return false; } -static void DedicatedVideoFullScreen(bool fs) {} - -#if defined(UNIX) || defined(__OS2__) -static bool InputWaiting(void) -{ - struct timeval tv; - fd_set readfds; - - tv.tv_sec = 0; - tv.tv_usec = 1; - - FD_ZERO(&readfds); - FD_SET(STDIN, &readfds); - - /* don't care about writefds and exceptfds: */ - return select(STDIN + 1, &readfds, NULL, NULL, &tv) > 0; -} - -static uint32 GetTime(void) -{ - struct timeval tim; - - gettimeofday(&tim, NULL); - return tim.tv_usec / 1000 + tim.tv_sec * 1000; -} - -#else - -static bool InputWaiting(void) -{ - return WaitForSingleObject(_hInputReady, 1) == WAIT_OBJECT_0; -} - -static uint32 GetTime(void) -{ - return GetTickCount(); -} - -#endif - -static void DedicatedHandleKeyInput(void) -{ - static char input_line[200] = ""; - - if (!InputWaiting()) return; - - if (_exit_game) return; - -#if defined(UNIX) || defined(__OS2__) - if (fgets(input_line, lengthof(input_line), stdin) == NULL) return; -#else - /* Handle console input, and singal console thread, it can accept input again */ - strncpy(input_line, _win_console_thread_buffer, lengthof(input_line)); - SetEvent(_hWaitForInputHandling); -#endif - - /* XXX - strtok() does not 'forget' \n\r if it is the first character! */ - strtok(input_line, "\r\n"); // Forget about the final \n (or \r) - { /* Remove any special control characters */ - uint i; - for (i = 0; i < lengthof(input_line); i++) { - if (input_line[i] == '\n' || input_line[i] == '\r') // cut missed beginning '\0' - input_line[i] = '\0'; - - if (input_line[i] == '\0') - break; - - if (!IS_INT_INSIDE(input_line[i], ' ', 256)) - input_line[i] = ' '; - } - } - - IConsoleCmdExec(input_line); // execute command -} - -static void DedicatedVideoMainLoop(void) -{ - uint32 next_tick; - uint32 cur_ticks; - - next_tick = GetTime() + 30; - - /* Signal handlers */ -#ifdef UNIX - signal(SIGTERM, DedicatedSignalHandler); - signal(SIGINT, DedicatedSignalHandler); - signal(SIGQUIT, DedicatedSignalHandler); -#endif - - // Load the dedicated server stuff - _is_network_server = true; - _network_dedicated = true; - _network_playas = PLAYER_SPECTATOR; - _local_player = PLAYER_SPECTATOR; - - /* If SwitchMode is SM_LOAD, it means that the user used the '-g' options */ - if (_switch_mode != SM_LOAD) { - StartNewGameWithoutGUI(GENERATE_NEW_SEED); - SwitchMode(_switch_mode); - _switch_mode = SM_NONE; - } else { - _switch_mode = SM_NONE; - /* First we need to test if the savegame can be loaded, else we will end up playing the - * intro game... */ - if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) { - /* Loading failed, pop out.. */ - DEBUG(net, 0, "Loading requested map failed, aborting"); - _networking = false; - } else { - /* We can load this game, so go ahead */ - SwitchMode(SM_LOAD); - } - } - - // Done loading, start game! - - if (!_networking) { - DEBUG(net, 0, "Dedicated server could not be started, aborting"); - return; - } - - while (!_exit_game) { - InteractiveRandom(); // randomness - - if (!_dedicated_forks) - DedicatedHandleKeyInput(); - - cur_ticks = GetTime(); - - if (cur_ticks >= next_tick) { - next_tick += 30; - - GameLoop(); - _screen.dst_ptr = _dedicated_video_mem; - UpdateWindows(); - } - CSleep(1); - } -} - -const HalVideoDriver _dedicated_video_driver = { - DedicatedVideoStart, - DedicatedVideoStop, - DedicatedVideoMakeDirty, - DedicatedVideoMainLoop, - DedicatedVideoChangeRes, - DedicatedVideoFullScreen, -}; - -#endif /* ENABLE_NETWORK */ diff --git a/video/dedicated_v.h b/video/dedicated_v.h deleted file mode 100644 index 9ba1223d3..000000000 --- a/video/dedicated_v.h +++ /dev/null @@ -1,10 +0,0 @@ -/* $Id$ */ - -#ifndef VIDEO_DEDICATED_H -#define VIDEO_DEDICATED_H - -#include "../hal.h" - -extern const HalVideoDriver _dedicated_video_driver; - -#endif diff --git a/video/null_v.c b/video/null_v.c deleted file mode 100644 index ecdd3486c..000000000 --- a/video/null_v.c +++ /dev/null @@ -1,45 +0,0 @@ -/* $Id$ */ - -#include "../stdafx.h" -#include "../openttd.h" -#include "../gfx.h" -#include "../variables.h" -#include "../window.h" -#include "null_v.h" - -static void* _null_video_mem = NULL; - -static const char* NullVideoStart(const char* const* parm) -{ - _screen.width = _screen.pitch = _cur_resolution[0]; - _screen.height = _cur_resolution[1]; - _null_video_mem = malloc(_cur_resolution[0] * _cur_resolution[1]); - return NULL; -} - -static void NullVideoStop(void) { free(_null_video_mem); } - -static void NullVideoMakeDirty(int left, int top, int width, int height) {} - -static void NullVideoMainLoop(void) -{ - uint i; - - for (i = 0; i < 1000; i++) { - GameLoop(); - _screen.dst_ptr = _null_video_mem; - UpdateWindows(); - } -} - -static bool NullVideoChangeRes(int w, int h) { return false; } -static void NullVideoFullScreen(bool fs) {} - -const HalVideoDriver _null_video_driver = { - NullVideoStart, - NullVideoStop, - NullVideoMakeDirty, - NullVideoMainLoop, - NullVideoChangeRes, - NullVideoFullScreen, -}; diff --git a/video/null_v.h b/video/null_v.h deleted file mode 100644 index 56922d9b3..000000000 --- a/video/null_v.h +++ /dev/null @@ -1,10 +0,0 @@ -/* $Id$ */ - -#ifndef VIDEO_NULL_H -#define VIDEO_NULL_H - -#include "../hal.h" - -extern const HalVideoDriver _null_video_driver; - -#endif diff --git a/video/sdl_v.c b/video/sdl_v.c deleted file mode 100644 index e88de85a5..000000000 --- a/video/sdl_v.c +++ /dev/null @@ -1,515 +0,0 @@ -/* $Id$ */ - -#include "../stdafx.h" - -#ifdef WITH_SDL - -#include "../openttd.h" -#include "../debug.h" -#include "../functions.h" -#include "../gfx.h" -#include "../macros.h" -#include "../sdl.h" -#include "../window.h" -#include "../network/network.h" -#include "../variables.h" -#include "sdl_v.h" -#include <SDL.h> - -static SDL_Surface *_sdl_screen; -static bool _all_modes; - -#define MAX_DIRTY_RECTS 100 -static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS]; -static int _num_dirty_rects; - -static void SdlVideoMakeDirty(int left, int top, int width, int height) -{ - if (_num_dirty_rects < MAX_DIRTY_RECTS) { - _dirty_rects[_num_dirty_rects].x = left; - _dirty_rects[_num_dirty_rects].y = top; - _dirty_rects[_num_dirty_rects].w = width; - _dirty_rects[_num_dirty_rects].h = height; - } - _num_dirty_rects++; -} - -static void UpdatePalette(uint start, uint count) -{ - SDL_Color pal[256]; - uint i; - - for (i = 0; i != count; i++) { - pal[i].r = _cur_palette[start + i].r; - pal[i].g = _cur_palette[start + i].g; - pal[i].b = _cur_palette[start + i].b; - pal[i].unused = 0; - } - - SDL_CALL SDL_SetColors(_sdl_screen, pal, start, count); -} - -static void InitPalette(void) -{ - UpdatePalette(0, 256); -} - -static void CheckPaletteAnim(void) -{ - if (_pal_last_dirty != -1) { - UpdatePalette(_pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1); - _pal_last_dirty = -1; - } -} - -static void DrawSurfaceToScreen(void) -{ - int n = _num_dirty_rects; - if (n != 0) { - _num_dirty_rects = 0; - if (n > MAX_DIRTY_RECTS) - SDL_CALL SDL_UpdateRect(_sdl_screen, 0, 0, 0, 0); - else - SDL_CALL SDL_UpdateRects(_sdl_screen, n, _dirty_rects); - } -} - -static const uint16 default_resolutions[][2] = { - { 640, 480}, - { 800, 600}, - {1024, 768}, - {1152, 864}, - {1280, 800}, - {1280, 960}, - {1280, 1024}, - {1400, 1050}, - {1600, 1200}, - {1680, 1050}, - {1920, 1200} -}; - -static void GetVideoModes(void) -{ - int i; - SDL_Rect **modes; - - modes = SDL_CALL SDL_ListModes(NULL, SDL_SWSURFACE + (_fullscreen ? SDL_FULLSCREEN : 0)); - - if (modes == NULL) - error("sdl: no modes available"); - - _all_modes = (modes == (void*)-1); - - if (_all_modes) { - // all modes available, put some default ones here - memcpy(_resolutions, default_resolutions, sizeof(default_resolutions)); - _num_resolutions = lengthof(default_resolutions); - } else { - int n = 0; - for (i = 0; modes[i]; i++) { - int w = modes[i]->w; - int h = modes[i]->h; - if (IS_INT_INSIDE(w, 640, MAX_SCREEN_WIDTH + 1) && - IS_INT_INSIDE(h, 480, MAX_SCREEN_HEIGHT + 1)) { - int j; - for (j = 0; j < n; j++) { - if (_resolutions[j][0] == w && _resolutions[j][1] == h) break; - } - - if (j == n) { - _resolutions[j][0] = w; - _resolutions[j][1] = h; - if (++n == lengthof(_resolutions)) break; - } - } - } - _num_resolutions = n; - SortResolutions(_num_resolutions); - } -} - -static void GetAvailableVideoMode(int *w, int *h) -{ - int i; - int best; - uint delta; - - // all modes available? - if (_all_modes) return; - - // is the wanted mode among the available modes? - for (i = 0; i != _num_resolutions; i++) { - if (*w == _resolutions[i][0] && *h == _resolutions[i][1]) return; - } - - // use the closest possible resolution - best = 0; - delta = abs((_resolutions[0][0] - *w) * (_resolutions[0][1] - *h)); - for (i = 1; i != _num_resolutions; ++i) { - uint newdelta = abs((_resolutions[i][0] - *w) * (_resolutions[i][1] - *h)); - if (newdelta < delta) { - best = i; - delta = newdelta; - } - } - *w = _resolutions[best][0]; - *h = _resolutions[best][1]; -} - -#ifndef ICON_DIR -#define ICON_DIR "media" -#endif - -#ifdef WIN32 -/* Let's redefine the LoadBMP macro with because we are dynamically - * loading SDL and need to 'SDL_CALL' all functions */ -#undef SDL_LoadBMP -#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_CALL SDL_RWFromFile(file, "rb"), 1) -#endif - -static bool CreateMainSurface(int w, int h) -{ - extern const char _openttd_revision[]; - SDL_Surface *newscreen, *icon; - char caption[50]; - - GetAvailableVideoMode(&w, &h); - - DEBUG(driver, 1, "SDL: using mode %dx%d", w, h); - - /* Give the application an icon */ - icon = SDL_CALL SDL_LoadBMP(ICON_DIR PATHSEP "openttd.32.bmp"); - if (icon != NULL) { - /* Get the colourkey, which will be magenta */ - uint32 rgbmap = SDL_CALL SDL_MapRGB(icon->format, 255, 0, 255); - - SDL_CALL SDL_SetColorKey(icon, SDL_SRCCOLORKEY, rgbmap); - SDL_CALL SDL_WM_SetIcon(icon, NULL); - SDL_CALL SDL_FreeSurface(icon); - } - - // DO NOT CHANGE TO HWSURFACE, IT DOES NOT WORK - newscreen = SDL_CALL SDL_SetVideoMode(w, h, 8, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE)); - if (newscreen == NULL) - return false; - - _screen.width = newscreen->w; - _screen.height = newscreen->h; - _screen.pitch = newscreen->pitch; - - _sdl_screen = newscreen; - InitPalette(); - - snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision); - SDL_CALL SDL_WM_SetCaption(caption, caption); - SDL_CALL SDL_ShowCursor(0); - - GameSizeChanged(); - - return true; -} - -typedef struct VkMapping { - uint16 vk_from; - byte vk_count; - byte map_to; -} VkMapping; - -#define AS(x, z) {x, 0, z} -#define AM(x, y, z, w) {x, y - x, z} - -static const VkMapping _vk_mapping[] = { - // Pageup stuff + up/down - AM(SDLK_PAGEUP, SDLK_PAGEDOWN, WKC_PAGEUP, WKC_PAGEDOWN), - AS(SDLK_UP, WKC_UP), - AS(SDLK_DOWN, WKC_DOWN), - AS(SDLK_LEFT, WKC_LEFT), - AS(SDLK_RIGHT, WKC_RIGHT), - - AS(SDLK_HOME, WKC_HOME), - AS(SDLK_END, WKC_END), - - AS(SDLK_INSERT, WKC_INSERT), - AS(SDLK_DELETE, WKC_DELETE), - - // Map letters & digits - AM(SDLK_a, SDLK_z, 'A', 'Z'), - AM(SDLK_0, SDLK_9, '0', '9'), - - AS(SDLK_ESCAPE, WKC_ESC), - AS(SDLK_PAUSE, WKC_PAUSE), - AS(SDLK_BACKSPACE, WKC_BACKSPACE), - - AS(SDLK_SPACE, WKC_SPACE), - AS(SDLK_RETURN, WKC_RETURN), - AS(SDLK_TAB, WKC_TAB), - - // Function keys - AM(SDLK_F1, SDLK_F12, WKC_F1, WKC_F12), - - // Numeric part. - // What is the virtual keycode for numeric enter?? - AM(SDLK_KP0, SDLK_KP9, WKC_NUM_0, WKC_NUM_9), - AS(SDLK_KP_DIVIDE, WKC_NUM_DIV), - AS(SDLK_KP_MULTIPLY, WKC_NUM_MUL), - AS(SDLK_KP_MINUS, WKC_NUM_MINUS), - AS(SDLK_KP_PLUS, WKC_NUM_PLUS), - AS(SDLK_KP_ENTER, WKC_NUM_ENTER), - AS(SDLK_KP_PERIOD, WKC_NUM_DECIMAL) -}; - -static uint32 ConvertSdlKeyIntoMy(SDL_keysym *sym) -{ - const VkMapping *map; - uint key = 0; - - for (map = _vk_mapping; map != endof(_vk_mapping); ++map) { - if ((uint)(sym->sym - map->vk_from) <= map->vk_count) { - key = sym->sym - map->vk_from + map->map_to; - break; - } - } - - // check scancode for BACKQUOTE key, because we want the key left of "1", not anything else (on non-US keyboards) -#if defined(WIN32) || defined(__OS2__) - if (sym->scancode == 41) key = WKC_BACKQUOTE; -#elif defined(__APPLE__) - if (sym->scancode == 10) key = WKC_BACKQUOTE; -#elif defined(__MORPHOS__) - if (sym->scancode == 0) key = WKC_BACKQUOTE; // yes, that key is code '0' under MorphOS :) -#elif defined(__BEOS__) - if (sym->scancode == 17) key = WKC_BACKQUOTE; -#elif defined(__SVR4) && defined(__sun) - if (sym->scancode == 60) key = WKC_BACKQUOTE; - if (sym->scancode == 49) key = WKC_BACKSPACE; -#elif defined(__sgi__) - if (sym->scancode == 22) key = WKC_BACKQUOTE; -#else - if (sym->scancode == 49) key = WKC_BACKQUOTE; -#endif - - // META are the command keys on mac - if (sym->mod & KMOD_META) key |= WKC_META; - if (sym->mod & KMOD_SHIFT) key |= WKC_SHIFT; - if (sym->mod & KMOD_CTRL) key |= WKC_CTRL; - if (sym->mod & KMOD_ALT) key |= WKC_ALT; - // these two lines really help porting hotkey combos. Uncomment to use -- Bjarni -#if 0 - DEBUG(driver, 0, "Scancode character pressed %u", sym->scancode); - DEBUG(driver, 0, "Unicode character pressed %u", sym->unicode); -#endif - return (key << 16) + sym->unicode; -} - -static int PollEvent(void) -{ - SDL_Event ev; - - if (!SDL_CALL SDL_PollEvent(&ev)) return -2; - - switch (ev.type) { - case SDL_MOUSEMOTION: - if (_cursor.fix_at) { - int dx = ev.motion.x - _cursor.pos.x; - int dy = ev.motion.y - _cursor.pos.y; - if (dx != 0 || dy != 0) { - _cursor.delta.x += dx; - _cursor.delta.y += dy; - SDL_CALL SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y); - } - } else { - _cursor.delta.x = ev.motion.x - _cursor.pos.x; - _cursor.delta.y = ev.motion.y - _cursor.pos.y; - _cursor.pos.x = ev.motion.x; - _cursor.pos.y = ev.motion.y; - _cursor.dirty = true; - } - HandleMouseEvents(); - break; - - case SDL_MOUSEBUTTONDOWN: - if (_rightclick_emulate && SDL_CALL SDL_GetModState() & KMOD_CTRL) { - ev.button.button = SDL_BUTTON_RIGHT; - } - - switch (ev.button.button) { - case SDL_BUTTON_LEFT: - _left_button_down = true; - break; - - case SDL_BUTTON_RIGHT: - _right_button_down = true; - _right_button_clicked = true; - break; - - case SDL_BUTTON_WHEELUP: _cursor.wheel--; break; - case SDL_BUTTON_WHEELDOWN: _cursor.wheel++; break; - - default: break; - } - HandleMouseEvents(); - break; - - case SDL_MOUSEBUTTONUP: - if (_rightclick_emulate) { - _right_button_down = false; - _left_button_down = false; - _left_button_clicked = false; - } else if (ev.button.button == SDL_BUTTON_LEFT) { - _left_button_down = false; - _left_button_clicked = false; - } else if (ev.button.button == SDL_BUTTON_RIGHT) { - _right_button_down = false; - } - HandleMouseEvents(); - break; - - case SDL_ACTIVEEVENT: - if (!(ev.active.state & SDL_APPMOUSEFOCUS)) break; - - if (ev.active.gain) { // mouse entered the window, enable cursor - _cursor.in_window = true; - } else { - UndrawMouseCursor(); // mouse left the window, undraw cursor - _cursor.in_window = false; - } - break; - - case SDL_QUIT: HandleExitGameRequest(); break; - - case SDL_KEYDOWN: /* Toggle full-screen on ALT + ENTER/F */ - if ((ev.key.keysym.mod & (KMOD_ALT | KMOD_META)) && - (ev.key.keysym.sym == SDLK_RETURN || ev.key.keysym.sym == SDLK_f)) { - ToggleFullScreen(!_fullscreen); - } else { - HandleKeypress(ConvertSdlKeyIntoMy(&ev.key.keysym)); - } - break; - - case SDL_VIDEORESIZE: { - int w = clamp(ev.resize.w, 64, MAX_SCREEN_WIDTH); - int h = clamp(ev.resize.h, 64, MAX_SCREEN_HEIGHT); - ChangeResInGame(w, h); - break; - } - } - return -1; -} - -static const char *SdlVideoStart(const char * const *parm) -{ - char buf[30]; - - const char *s = SdlOpen(SDL_INIT_VIDEO); - if (s != NULL) return s; - - SDL_CALL SDL_VideoDriverName(buf, 30); - DEBUG(driver, 1, "SDL: using driver '%s'", buf); - - GetVideoModes(); - CreateMainSurface(_cur_resolution[0], _cur_resolution[1]); - MarkWholeScreenDirty(); - - SDL_CALL SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); - SDL_CALL SDL_EnableUNICODE(1); - return NULL; -} - -static void SdlVideoStop(void) -{ - SdlClose(SDL_INIT_VIDEO); -} - -static void SdlVideoMainLoop(void) -{ - uint32 next_tick = SDL_CALL SDL_GetTicks() + 30; - uint32 cur_ticks; - uint32 pal_tick = 0; - uint32 mod; - int numkeys; - Uint8 *keys; - - for (;;) { - InteractiveRandom(); // randomness - - while (PollEvent() == -1) {} - if (_exit_game) return; - - mod = SDL_CALL SDL_GetModState(); - keys = SDL_CALL SDL_GetKeyState(&numkeys); -#if defined(_DEBUG) - if (_shift_pressed) -#else - /* Speedup when pressing tab, except when using ALT+TAB - * to switch to another application */ - if (keys[SDLK_TAB] && (mod & KMOD_ALT) == 0) -#endif - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } - - cur_ticks = SDL_CALL SDL_GetTicks(); - if ((_fast_forward && !_pause) || cur_ticks > next_tick) - next_tick = cur_ticks; - - if (cur_ticks == next_tick) { - next_tick += 30; - - _ctrl_pressed = !!(mod & KMOD_CTRL); - _shift_pressed = !!(mod & KMOD_SHIFT); -#ifdef _DEBUG - _dbg_screen_rect = !!(mod & KMOD_CAPS); -#endif - - // determine which directional keys are down - _dirkeys = - (keys[SDLK_LEFT] ? 1 : 0) | - (keys[SDLK_UP] ? 2 : 0) | - (keys[SDLK_RIGHT] ? 4 : 0) | - (keys[SDLK_DOWN] ? 8 : 0); - GameLoop(); - - _screen.dst_ptr = _sdl_screen->pixels; - UpdateWindows(); - if (++pal_tick > 4) { - CheckPaletteAnim(); - pal_tick = 1; - } - DrawSurfaceToScreen(); - } else { - SDL_CALL SDL_Delay(1); - _screen.dst_ptr = _sdl_screen->pixels; - DrawTextMessage(); - DrawMouseCursor(); - DrawSurfaceToScreen(); - } - } -} - -static bool SdlVideoChangeRes(int w, int h) -{ - return CreateMainSurface(w, h); -} - -static void SdlVideoFullScreen(bool full_screen) -{ - _fullscreen = full_screen; - GetVideoModes(); // get the list of available video modes - if (_num_resolutions == 0 || !_video_driver->change_resolution(_cur_resolution[0], _cur_resolution[1])) { - // switching resolution failed, put back full_screen to original status - _fullscreen ^= true; - } -} - -const HalVideoDriver _sdl_video_driver = { - SdlVideoStart, - SdlVideoStop, - SdlVideoMakeDirty, - SdlVideoMainLoop, - SdlVideoChangeRes, - SdlVideoFullScreen, -}; - -#endif diff --git a/video/sdl_v.h b/video/sdl_v.h deleted file mode 100644 index 07ba50f3c..000000000 --- a/video/sdl_v.h +++ /dev/null @@ -1,10 +0,0 @@ -/* $Id$ */ - -#ifndef VIDEO_SDL_H -#define VIDEO_SDL_H - -#include "../hal.h" - -extern const HalVideoDriver _sdl_video_driver; - -#endif diff --git a/video/win32_v.c b/video/win32_v.c deleted file mode 100644 index 7588653f0..000000000 --- a/video/win32_v.c +++ /dev/null @@ -1,876 +0,0 @@ -/* $Id$ */ - -#include "../stdafx.h" -#include "../openttd.h" -#include "../functions.h" -#include "../gfx.h" -#include "../macros.h" -#include "../network/network.h" -#include "../variables.h" -#include "../win32.h" -#include "../window.h" -#include "win32_v.h" -#include <windows.h> -#include <tchar.h> - -static struct { - HWND main_wnd; - HBITMAP dib_sect; - Pixel *bitmap_bits; - Pixel *buffer_bits; - Pixel *alloced_bits; - HPALETTE gdi_palette; - int width; - int height; - int width_org; - int height_org; - bool fullscreen; - bool double_size; - bool has_focus; - bool running; -} _wnd; - -bool _force_full_redraw; -bool _double_size; -bool _window_maximize; -uint _display_hz; -uint _fullscreen_bpp; -static uint16 _bck_resolution[2]; - -static void MakePalette(void) -{ - LOGPALETTE *pal; - uint i; - - pal = alloca(sizeof(LOGPALETTE) + (256-1) * sizeof(PALETTEENTRY)); - - pal->palVersion = 0x300; - pal->palNumEntries = 256; - - for (i = 0; i != 256; i++) { - pal->palPalEntry[i].peRed = _cur_palette[i].r; - pal->palPalEntry[i].peGreen = _cur_palette[i].g; - pal->palPalEntry[i].peBlue = _cur_palette[i].b; - pal->palPalEntry[i].peFlags = 0; - - } - _wnd.gdi_palette = CreatePalette(pal); - if (_wnd.gdi_palette == NULL) error("CreatePalette failed!\n"); -} - -static void UpdatePalette(HDC dc, uint start, uint count) -{ - RGBQUAD rgb[256]; - uint i; - - for (i = 0; i != count; i++) { - rgb[i].rgbRed = _cur_palette[start + i].r; - rgb[i].rgbGreen = _cur_palette[start + i].g; - rgb[i].rgbBlue = _cur_palette[start + i].b; - rgb[i].rgbReserved = 0; - } - - SetDIBColorTable(dc, start, count, rgb); -} - -typedef struct { - byte vk_from; - byte vk_count; - byte map_to; -} VkMapping; - -#define AS(x, z) {x, 0, z} -#define AM(x, y, z, w) {x, y - x, z} - -static const VkMapping _vk_mapping[] = { - // Pageup stuff + up/down - AM(VK_PRIOR,VK_DOWN, WKC_PAGEUP, WKC_DOWN), - // Map letters & digits - AM('A','Z','A','Z'), - AM('0','9','0','9'), - - AS(VK_ESCAPE, WKC_ESC), - AS(VK_PAUSE, WKC_PAUSE), - AS(VK_BACK, WKC_BACKSPACE), - AM(VK_INSERT, VK_DELETE, WKC_INSERT, WKC_DELETE), - - AS(VK_SPACE, WKC_SPACE), - AS(VK_RETURN, WKC_RETURN), - AS(VK_TAB, WKC_TAB), - - // Function keys - AM(VK_F1, VK_F12, WKC_F1, WKC_F12), - - // Numeric part. - // What is the virtual keycode for numeric enter?? - AM(VK_NUMPAD0, VK_NUMPAD9, WKC_NUM_0, WKC_NUM_9), - AS(VK_DIVIDE, WKC_NUM_DIV), - AS(VK_MULTIPLY, WKC_NUM_MUL), - AS(VK_SUBTRACT, WKC_NUM_MINUS), - AS(VK_ADD, WKC_NUM_PLUS), - AS(VK_DECIMAL, WKC_NUM_DECIMAL) -}; - -static uint MapWindowsKey(uint sym) -{ - const VkMapping *map; - uint key = 0; - - for (map = _vk_mapping; map != endof(_vk_mapping); ++map) { - if ((uint)(sym - map->vk_from) <= map->vk_count) { - key = sym - map->vk_from + map->map_to; - break; - } - } - - if (GetAsyncKeyState(VK_SHIFT) < 0) key |= WKC_SHIFT; - if (GetAsyncKeyState(VK_CONTROL) < 0) key |= WKC_CTRL; - if (GetAsyncKeyState(VK_MENU) < 0) key |= WKC_ALT; - return key; -} - -static bool AllocateDibSection(int w, int h); - -static void ClientSizeChanged(int w, int h) -{ - if (_wnd.double_size) { - w /= 2; - h /= 2; - } - - // allocate new dib section of the new size - if (AllocateDibSection(w, h)) { - // mark all palette colors dirty - _pal_first_dirty = 0; - _pal_last_dirty = 255; - GameSizeChanged(); - - // redraw screen - if (_wnd.running) { - _screen.dst_ptr = _wnd.buffer_bits; - UpdateWindows(); - } - } -} - -#ifdef _DEBUG -// Keep this function here.. -// It allows you to redraw the screen from within the MSVC debugger -int RedrawScreenDebug(void) -{ - HDC dc,dc2; - static int _fooctr; - HBITMAP old_bmp; - HPALETTE old_palette; - - _screen.dst_ptr = _wnd.buffer_bits; - UpdateWindows(); - - dc = GetDC(_wnd.main_wnd); - dc2 = CreateCompatibleDC(dc); - - old_bmp = SelectObject(dc2, _wnd.dib_sect); - old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); - BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); - SelectPalette(dc, old_palette, TRUE); - SelectObject(dc2, old_bmp); - DeleteDC(dc2); - ReleaseDC(_wnd.main_wnd, dc); - - return _fooctr++; -} -#endif - -/* Windows 95 will not have a WM_MOUSELEAVE message, so define it if needed */ -#if !defined(WM_MOUSELEAVE) -#define WM_MOUSELEAVE 0x02A3 -#endif -#define TID_POLLMOUSE 1 -#define MOUSE_POLL_DELAY 75 - -static void CALLBACK TrackMouseTimerProc(HWND hwnd, UINT msg, UINT event, DWORD time) -{ - RECT rc; - POINT pt; - - /* Get the rectangle of our window and translate it to screen coordinates. - * Compare this with the current screen coordinates of the mouse and if it - * falls outside of the area or our window we have left the window. */ - GetClientRect(hwnd, &rc); - MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT)(LPRECT)&rc, 2); - GetCursorPos(&pt); - - if (!PtInRect(&rc, pt) || (WindowFromPoint(pt) != hwnd)) { - KillTimer(hwnd, event); - PostMessage(hwnd, WM_MOUSELEAVE, 0, 0L); - } -} - -static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_CREATE: - SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc); - break; - - case WM_PAINT: { - PAINTSTRUCT ps; - HDC dc,dc2; - HBITMAP old_bmp; - HPALETTE old_palette; - - BeginPaint(hwnd, &ps); - dc = ps.hdc; - dc2 = CreateCompatibleDC(dc); - old_bmp = SelectObject(dc2, _wnd.dib_sect); - old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); - - if (_pal_last_dirty != -1) { - UpdatePalette(dc2, _pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1); - _pal_last_dirty = -1; - } - - BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); - SelectPalette(dc, old_palette, TRUE); - SelectObject(dc2, old_bmp); - DeleteDC(dc2); - EndPaint(hwnd, &ps); - return 0; - } - - case WM_PALETTECHANGED: - if ((HWND)wParam == hwnd) return 0; - /* FALLTHROUGH */ - - case WM_QUERYNEWPALETTE: { - HDC hDC = GetWindowDC(hwnd); - HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE); - UINT nChanged = RealizePalette(hDC); - - SelectPalette(hDC, hOldPalette, TRUE); - ReleaseDC(hwnd, hDC); - if (nChanged) InvalidateRect(hwnd, NULL, FALSE); - return 0; - } - - case WM_CLOSE: - HandleExitGameRequest(); - return 0; - - case WM_DESTROY: - if (_window_maximize) { - _cur_resolution[0] = _bck_resolution[0]; - _cur_resolution[1] = _bck_resolution[1]; - } - return 0; - - case WM_LBUTTONDOWN: - SetCapture(hwnd); - _left_button_down = true; - HandleMouseEvents(); - return 0; - - case WM_LBUTTONUP: - ReleaseCapture(); - _left_button_down = false; - _left_button_clicked = false; - HandleMouseEvents(); - return 0; - - case WM_RBUTTONDOWN: - SetCapture(hwnd); - _right_button_down = true; - _right_button_clicked = true; - HandleMouseEvents(); - return 0; - - case WM_RBUTTONUP: - ReleaseCapture(); - _right_button_down = false; - HandleMouseEvents(); - return 0; - - case WM_MOUSELEAVE: - UndrawMouseCursor(); - _cursor.in_window = false; - - if (!_left_button_down && !_right_button_down) MyShowCursor(true); - HandleMouseEvents(); - return 0; - - case WM_MOUSEMOVE: { - int x = (int16)LOWORD(lParam); - int y = (int16)HIWORD(lParam); - POINT pt; - - /* If the mouse was not in the window and it has moved it means it has - * come into the window, so start drawing the mouse. Also start - * tracking the mouse for exiting the window */ - if (!_cursor.in_window) { - _cursor.in_window = true; - SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc); - - DrawMouseCursor(); - } - - if (_wnd.double_size) { - x /= 2; - y /= 2; - } - - if (_cursor.fix_at) { - int dx = x - _cursor.pos.x; - int dy = y - _cursor.pos.y; - if (dx != 0 || dy != 0) { - _cursor.delta.x += dx; - _cursor.delta.y += dy; - - pt.x = _cursor.pos.x; - pt.y = _cursor.pos.y; - - if (_wnd.double_size) { - pt.x *= 2; - pt.y *= 2; - } - ClientToScreen(hwnd, &pt); - SetCursorPos(pt.x, pt.y); - } - } else { - _cursor.delta.x += x - _cursor.pos.x; - _cursor.delta.y += y - _cursor.pos.y; - _cursor.pos.x = x; - _cursor.pos.y = y; - _cursor.dirty = true; - } - MyShowCursor(false); - HandleMouseEvents(); - return 0; - } - - case WM_KEYDOWN: { - // this is the rewritten ascii input function - // it disables windows deadkey handling --> more linux like :D - wchar_t w = 0; - byte ks[256]; - uint scancode; - uint32 pressed_key; - - GetKeyboardState(ks); - if (ToUnicode(wParam, 0, ks, &w, 1, 0) != 1) { - /* On win9x ToUnicode always fails, so fall back to ToAscii */ - if (ToAscii(wParam, 0, ks, &w, 0) != 1) w = 0; // no translation was possible - } - - pressed_key = w | MapWindowsKey(wParam) << 16; - - scancode = GB(lParam, 16, 8); - if (scancode == 41) pressed_key = w | WKC_BACKQUOTE << 16; - - if (GB(pressed_key, 16, 16) == ('D' | WKC_CTRL) && !_wnd.fullscreen) { - _double_size ^= 1; - _wnd.double_size = _double_size; - ClientSizeChanged(_wnd.width, _wnd.height); - MarkWholeScreenDirty(); - } - HandleKeypress(pressed_key); - break; - } - - case WM_SYSKEYDOWN: /* user presses F10 or Alt, both activating the title-menu */ - switch (wParam) { - case VK_RETURN: - case 'F': /* Full Screen on ALT + ENTER/F */ - ToggleFullScreen(!_wnd.fullscreen); - return 0; - - case VK_MENU: /* Just ALT */ - return 0; // do nothing - - case VK_F10: /* F10, ignore activation of menu */ - HandleKeypress(MapWindowsKey(wParam) << 16); - return 0; - - default: /* ALT in combination with something else */ - HandleKeypress(MapWindowsKey(wParam) << 16); - break; - } - break; - - case WM_SIZE: - if (wParam != SIZE_MINIMIZED) { - /* Set maximized flag when we maximize (obviously), but also when we - * switched to fullscreen from a maximized state */ - _window_maximize = (wParam == SIZE_MAXIMIZED || (_window_maximize && _fullscreen)); - if (_window_maximize) { - _bck_resolution[0] = _cur_resolution[0]; - _bck_resolution[1] = _cur_resolution[1]; - } - ClientSizeChanged(LOWORD(lParam), HIWORD(lParam)); - } - return 0; - - case WM_SIZING: { - RECT* r = (RECT*)lParam; - RECT r2; - int w, h; - - SetRect(&r2, 0, 0, 0, 0); - AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); - - w = r->right - r->left - (r2.right - r2.left); - h = r->bottom - r->top - (r2.bottom - r2.top); - if (_wnd.double_size) { - w /= 2; - h /= 2; - } - w = clamp(w, 64, MAX_SCREEN_WIDTH); - h = clamp(h, 64, MAX_SCREEN_HEIGHT); - if (_wnd.double_size) { - w *= 2; - h *= 2; - } - SetRect(&r2, 0, 0, w, h); - - AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); - w = r2.right - r2.left; - h = r2.bottom - r2.top; - - switch (wParam) { - case WMSZ_BOTTOM: - r->bottom = r->top + h; - break; - - case WMSZ_BOTTOMLEFT: - r->bottom = r->top + h; - r->left = r->right - w; - break; - - case WMSZ_BOTTOMRIGHT: - r->bottom = r->top + h; - r->right = r->left + w; - break; - - case WMSZ_LEFT: - r->left = r->right - w; - break; - - case WMSZ_RIGHT: - r->right = r->left + w; - break; - - case WMSZ_TOP: - r->top = r->bottom - h; - break; - - case WMSZ_TOPLEFT: - r->top = r->bottom - h; - r->left = r->right - w; - break; - - case WMSZ_TOPRIGHT: - r->top = r->bottom - h; - r->right = r->left + w; - break; - } - return TRUE; - } - -// needed for wheel -#if !defined(WM_MOUSEWHEEL) -# define WM_MOUSEWHEEL 0x020A -#endif //WM_MOUSEWHEEL -#if !defined(GET_WHEEL_DELTA_WPARAM) -# define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam)) -#endif //GET_WHEEL_DELTA_WPARAM - - case WM_MOUSEWHEEL: { - int delta = GET_WHEEL_DELTA_WPARAM(wParam); - - if (delta < 0) { - _cursor.wheel++; - } else if (delta > 0) { - _cursor.wheel--; - } - HandleMouseEvents(); - return 0; - } - - case WM_ACTIVATEAPP: - _wnd.has_focus = (bool)wParam; - break; - } - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -static void RegisterWndClass(void) -{ - static bool registered = false; - - if (!registered) { - HINSTANCE hinst = GetModuleHandle(NULL); - WNDCLASS wnd = { - 0, - WndProcGdi, - 0, - 0, - hinst, - LoadIcon(hinst, MAKEINTRESOURCE(100)), - LoadCursor(NULL, IDC_ARROW), - 0, - 0, - _T("OTTD") - }; - - registered = true; - if (!RegisterClass(&wnd)) error("RegisterClass failed"); - } -} - -static void MakeWindow(bool full_screen) -{ - _fullscreen = full_screen; - - _wnd.double_size = _double_size && !full_screen; - - // recreate window? - if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) { - DestroyWindow(_wnd.main_wnd); - _wnd.main_wnd = 0; - } - - if (full_screen) { - DEVMODE settings; - - memset(&settings, 0, sizeof(settings)); - settings.dmSize = sizeof(settings); - settings.dmFields = - (_fullscreen_bpp != 0 ? DM_BITSPERPEL : 0) | - DM_PELSWIDTH | - DM_PELSHEIGHT | - (_display_hz != 0 ? DM_DISPLAYFREQUENCY : 0); - settings.dmBitsPerPel = _fullscreen_bpp; - settings.dmPelsWidth = _wnd.width_org; - settings.dmPelsHeight = _wnd.height_org; - settings.dmDisplayFrequency = _display_hz; - - if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { - MakeWindow(false); - return; - } - } else if (_wnd.fullscreen) { - // restore display? - ChangeDisplaySettings(NULL, 0); - } - - { - RECT r; - DWORD style, showstyle; - int x, y, w, h; - - showstyle = SW_SHOWNORMAL; - _wnd.fullscreen = full_screen; - if (_wnd.fullscreen) { - style = WS_POPUP; - SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org); - } else { - style = WS_OVERLAPPEDWINDOW; - /* On window creation, check if we were in maximize mode before */ - if (_window_maximize) showstyle = SW_SHOWMAXIMIZED; - SetRect(&r, 0, 0, _wnd.width, _wnd.height); - } - - AdjustWindowRect(&r, style, FALSE); - w = r.right - r.left; - h = r.bottom - r.top; - x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2; - y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2; - - if (_wnd.main_wnd) { - ShowWindow(_wnd.main_wnd, SW_SHOWNORMAL); // remove maximize-flag - SetWindowPos(_wnd.main_wnd, 0, x, y, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); - } else { - extern const char _openttd_revision[]; - TCHAR Windowtitle[50]; - - _sntprintf(Windowtitle, sizeof(Windowtitle), _T("OpenTTD %s"), MB_TO_WIDE(_openttd_revision)); - - _wnd.main_wnd = CreateWindow(_T("OTTD"), Windowtitle, style, x, y, w, h, 0, 0, GetModuleHandle(NULL), 0); - if (_wnd.main_wnd == NULL) error("CreateWindow failed"); - ShowWindow(_wnd.main_wnd, showstyle); - } - } - GameSizeChanged(); // invalidate all windows, force redraw -} - -static bool AllocateDibSection(int w, int h) -{ - BITMAPINFO *bi; - HDC dc; - - w = clamp(w, 64, MAX_SCREEN_WIDTH); - h = clamp(h, 64, MAX_SCREEN_HEIGHT); - - if (w == _screen.width && h == _screen.height) - return false; - - _screen.width = w; - _screen.pitch = ALIGN(w, 4); - _screen.height = h; - - if (_wnd.alloced_bits) { - free(_wnd.alloced_bits); - _wnd.alloced_bits = NULL; - } - - bi = alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); - memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); - bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - - if (_wnd.double_size) { - w = ALIGN(w, 4); - _wnd.alloced_bits = _wnd.buffer_bits = malloc(w * h); - w *= 2; - h *= 2; - } - - bi->bmiHeader.biWidth = _wnd.width = w; - bi->bmiHeader.biHeight = -(_wnd.height = h); - - bi->bmiHeader.biPlanes = 1; - bi->bmiHeader.biBitCount = 8; - bi->bmiHeader.biCompression = BI_RGB; - - if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect); - - dc = GetDC(0); - _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.bitmap_bits, NULL, 0); - if (_wnd.dib_sect == NULL) error("CreateDIBSection failed"); - ReleaseDC(0, dc); - - if (!_wnd.double_size) _wnd.buffer_bits = _wnd.bitmap_bits; - - return true; -} - -static const uint16 default_resolutions[][2] = { - { 640, 480 }, - { 800, 600 }, - { 1024, 768 }, - { 1152, 864 }, - { 1280, 800 }, - { 1280, 960 }, - { 1280, 1024 }, - { 1400, 1050 }, - { 1600, 1200 }, - { 1680, 1050 }, - { 1920, 1200 } -}; - -static void FindResolutions(void) -{ - uint n = 0; - uint i; - DEVMODEA dm; - - /* XXX - EnumDisplaySettingsW crashes with unicows.dll on Windows95 - * Doesn't really matter since we don't pass a string anyways, but still - * a letdown */ - for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) { - if (dm.dmBitsPerPel == 8 && IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) && - IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT + 1)) { - uint j; - - for (j = 0; j < n; j++) { - if (_resolutions[j][0] == dm.dmPelsWidth && _resolutions[j][1] == dm.dmPelsHeight) break; - } - - /* In the previous loop we have checked already existing/added resolutions if - * they are the same as the new ones. If this is not the case (j == n); we have - * looped all and found none, add the new one to the list. If we have reached the - * maximum amount of resolutions, then quit querying the display */ - if (j == n) { - _resolutions[j][0] = dm.dmPelsWidth; - _resolutions[j][1] = dm.dmPelsHeight; - if (++n == lengthof(_resolutions)) break; - } - } - } - - /* We have found no resolutions, show the default list */ - if (n == 0) { - memcpy(_resolutions, default_resolutions, sizeof(default_resolutions)); - n = lengthof(default_resolutions); - } - - _num_resolutions = n; - SortResolutions(_num_resolutions); -} - - -static const char *Win32GdiStart(const char * const *parm) -{ - memset(&_wnd, 0, sizeof(_wnd)); - - RegisterWndClass(); - - MakePalette(); - - FindResolutions(); - - // fullscreen uses those - _wnd.width_org = _cur_resolution[0]; - _wnd.height_org = _cur_resolution[1]; - - AllocateDibSection(_cur_resolution[0], _cur_resolution[1]); - MarkWholeScreenDirty(); - - MakeWindow(_fullscreen); - - return NULL; -} - -static void Win32GdiStop(void) -{ - DeleteObject(_wnd.gdi_palette); - DeleteObject(_wnd.dib_sect); - DestroyWindow(_wnd.main_wnd); - - if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0); - if (_double_size) { - _cur_resolution[0] *= 2; - _cur_resolution[1] *= 2; - } - - MyShowCursor(true); -} - -// simple upscaler by 2 -static void filter(int left, int top, int width, int height) -{ - uint p = _screen.pitch; - const Pixel *s = _wnd.buffer_bits + top * p + left; - Pixel *d = _wnd.bitmap_bits + top * p * 4 + left * 2; - - for (; height > 0; height--) { - int i; - - for (i = 0; i != width; i++) { - d[i * 2] = d[i * 2 + 1] = d[i * 2 + p * 2] = d[i * 2 + 1 + p * 2] = s[i]; - } - s += p; - d += p * 4; - } -} - -static void Win32GdiMakeDirty(int left, int top, int width, int height) -{ - RECT r = { left, top, left + width, top + height }; - - if (_wnd.double_size) { - filter(left, top, width, height); - r.left *= 2; - r.top *= 2; - r.right *= 2; - r.bottom *= 2; - } - InvalidateRect(_wnd.main_wnd, &r, FALSE); -} - -static void CheckPaletteAnim(void) -{ - if (_pal_last_dirty == -1) - return; - InvalidateRect(_wnd.main_wnd, NULL, FALSE); -} - -static void Win32GdiMainLoop(void) -{ - MSG mesg; - uint32 next_tick = GetTickCount() + 30, cur_ticks; - - _wnd.running = true; - - for (;;) { - while (PeekMessage(&mesg, NULL, 0, 0, PM_REMOVE)) { - InteractiveRandom(); // randomness - DispatchMessage(&mesg); - } - if (_exit_game) return; - -#if defined(_DEBUG) - if (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0 && -#else - /* Speed up using TAB, but disable for ALT+TAB of course */ - if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0 && GetAsyncKeyState(VK_MENU) >= 0 && -#endif - !_networking && _game_mode != GM_MENU) { - _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } - - cur_ticks = GetTickCount(); - if ((_fast_forward && !_pause) || cur_ticks > next_tick) - next_tick = cur_ticks; - - if (cur_ticks == next_tick) { - next_tick += 30; - _ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0; - _shift_pressed = _wnd.has_focus && GetAsyncKeyState(VK_SHIFT)<0; -#ifdef _DEBUG - _dbg_screen_rect = _wnd.has_focus && GetAsyncKeyState(VK_CAPITAL)<0; -#endif - - // determine which directional keys are down - if (_wnd.has_focus) { - _dirkeys = - (GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) + - (GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) + - (GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) + - (GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0); - } else { - _dirkeys = 0; - } - - GameLoop(); - _cursor.delta.x = _cursor.delta.y = 0; - - if (_force_full_redraw) MarkWholeScreenDirty(); - - GdiFlush(); - _screen.dst_ptr = _wnd.buffer_bits; - UpdateWindows(); - CheckPaletteAnim(); - } else { - Sleep(1); - GdiFlush(); - _screen.dst_ptr = _wnd.buffer_bits; - DrawTextMessage(); - DrawMouseCursor(); - } - } -} - -static bool Win32GdiChangeRes(int w, int h) -{ - _wnd.width = _wnd.width_org = w; - _wnd.height = _wnd.height_org = h; - - MakeWindow(_fullscreen); // _wnd.fullscreen screws up ingame resolution switching - - return true; -} - -static void Win32GdiFullScreen(bool full_screen) -{ - MakeWindow(full_screen); -} - -const HalVideoDriver _win32_video_driver = { - Win32GdiStart, - Win32GdiStop, - Win32GdiMakeDirty, - Win32GdiMainLoop, - Win32GdiChangeRes, - Win32GdiFullScreen, -}; diff --git a/video/win32_v.h b/video/win32_v.h deleted file mode 100644 index c3b23a61a..000000000 --- a/video/win32_v.h +++ /dev/null @@ -1,10 +0,0 @@ -/* $Id$ */ - -#ifndef VIDEO_WIN32_H -#define VIDEO_WIN32_H - -#include "../hal.h" - -extern const HalVideoDriver _win32_video_driver; - -#endif |