From: DeaDDooMER Date: Sat, 5 Oct 2019 22:43:33 +0000 (+0300) Subject: implement SDL1.2 system driver X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=0e101bd452c40da601236aaa2dd4106be47ddce1;p=d2df-sdl.git implement SDL1.2 system driver --- diff --git a/src/engine/e_graphics.pas b/src/engine/e_graphics.pas index c46e8ec..6f1df29 100644 --- a/src/engine/e_graphics.pas +++ b/src/engine/e_graphics.pas @@ -19,7 +19,11 @@ interface uses {$INCLUDE ../nogl/noGLuses.inc} - SysUtils, Classes, Math, e_log, e_texture, SDL2, MAPDEF, ImagingTypes, Imaging, ImagingUtility; + {$IFDEF USE_SDL2} + SDL2, + {$ENDIF} + SysUtils, Classes, Math, e_log, e_texture, + MAPDEF, ImagingTypes, Imaging, ImagingUtility; type TMirrorType=(None, Horizontal, Vertical); @@ -128,8 +132,10 @@ procedure e_Clear(Mask: TGLbitfield; Red, Green, Blue: Single); overload; procedure e_Clear(); overload; procedure e_EndRender(); +{$IFDEF USE_SDL2} function e_GetGamma(win: PSDL_Window): Byte; procedure e_SetGamma(win: PSDL_Window;Gamma: Byte); +{$ENDIF} procedure e_MakeScreenshot(st: TStream; Width, Height: Word); @@ -1113,6 +1119,7 @@ begin glPopMatrix(); end; +{$IFDEF USE_SDL2} function e_GetGamma(win: PSDL_Window): Byte; var ramp: array [0..256*3-1] of Word; @@ -1175,6 +1182,7 @@ begin SDL_SetWindowGammaRamp(win, @ramp[0], @ramp[256], @ramp[512]); end; +{$ENDIF} function e_CharFont_Create(sp: ShortInt=0): DWORD; var diff --git a/src/engine/e_input.pas b/src/engine/e_input.pas index 1bfd7f3..e7fa6cb 100644 --- a/src/engine/e_input.pas +++ b/src/engine/e_input.pas @@ -15,450 +15,12 @@ {$INCLUDE ../shared/a_modes.inc} unit e_input; -interface - -uses SysUtils, SDL2; - -const - e_MaxKbdKeys = SDL_NUM_SCANCODES; - e_MaxJoys = 4; - e_MaxJoyBtns = 32; - e_MaxJoyAxes = 8; - e_MaxJoyHats = 8; - e_MaxVirtKeys = 48; - - e_MaxJoyKeys = e_MaxJoyBtns + e_MaxJoyAxes*2 + e_MaxJoyHats*4; - - e_MaxInputKeys = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys + e_MaxVirtKeys - 1; - // $$$..$$$ - 321 Keyboard buttons/keys - // $$$..$$$ - 4*32 Joystick buttons - // $$$..$$$ - 8*2 Joystick axes (- and +) - // $$$..$$$ - 4*4 Joystick hats (L U R D) - // $$$..$$$ - 48 Virtual buttons/keys - - KBRD_END = e_MaxKbdKeys; - JOYK_BEG = KBRD_END; - JOYK_END = JOYK_BEG + e_MaxJoyBtns*e_MaxJoys; - JOYA_BEG = JOYK_END; - JOYA_END = JOYA_BEG + e_MaxJoyAxes*2*e_MaxJoys; - JOYH_BEG = JOYA_END; - JOYH_END = JOYH_BEG + e_MaxJoyHats*4*e_MaxJoys; - VIRT_BEG = JOYH_END; - VIRT_END = VIRT_BEG + e_MaxVirtKeys; - - // these are apparently used in g_gui and g_game and elsewhere - IK_INVALID = 0; - IK_ESCAPE = SDL_SCANCODE_ESCAPE; - IK_RETURN = SDL_SCANCODE_RETURN; - IK_KPRETURN= SDL_SCANCODE_KP_ENTER; - IK_ENTER = SDL_SCANCODE_RETURN; - IK_KPINSERT = SDL_SCANCODE_KP_0; - IK_UP = SDL_SCANCODE_UP; - IK_KPUP = SDL_SCANCODE_KP_8; - IK_DOWN = SDL_SCANCODE_DOWN; - IK_KPDOWN = SDL_SCANCODE_KP_2; - IK_LEFT = SDL_SCANCODE_LEFT; - IK_KPLEFT = SDL_SCANCODE_KP_4; - IK_RIGHT = SDL_SCANCODE_RIGHT; - IK_KPRIGHT = SDL_SCANCODE_KP_6; - IK_DELETE = SDL_SCANCODE_DELETE; - IK_HOME = SDL_SCANCODE_HOME; - IK_KPHOME = SDL_SCANCODE_KP_7; - IK_INSERT = SDL_SCANCODE_INSERT; - IK_SPACE = SDL_SCANCODE_SPACE; - IK_CONTROL = SDL_SCANCODE_LCTRL; - IK_SHIFT = SDL_SCANCODE_LSHIFT; - IK_ALT = SDL_SCANCODE_LALT; - IK_TAB = SDL_SCANCODE_TAB; - IK_PAGEUP = SDL_SCANCODE_PAGEUP; - IK_KPPAGEUP= SDL_SCANCODE_KP_9; - IK_PAGEDN = SDL_SCANCODE_PAGEDOWN; - IK_KPPAGEDN= SDL_SCANCODE_KP_3; - IK_KP5 = SDL_SCANCODE_KP_5; - IK_NUMLOCK = SDL_SCANCODE_NUMLOCKCLEAR; - IK_KPDIVIDE= SDL_SCANCODE_KP_DIVIDE; - IK_KPMULTIPLE= SDL_SCANCODE_KP_MULTIPLY; - IK_KPMINUS = SDL_SCANCODE_KP_MINUS; - IK_KPPLUS = SDL_SCANCODE_KP_PLUS; - IK_KPENTER = SDL_SCANCODE_KP_ENTER; - IK_KPDOT = SDL_SCANCODE_KP_PERIOD; - IK_CAPSLOCK= SDL_SCANCODE_CAPSLOCK; - IK_RSHIFT = SDL_SCANCODE_RSHIFT; - IK_CTRL = SDL_SCANCODE_LCTRL; - IK_RCTRL = SDL_SCANCODE_RCTRL; - IK_RALT = SDL_SCANCODE_RALT; - IK_WIN = SDL_SCANCODE_LGUI; - IK_RWIN = SDL_SCANCODE_RGUI; - IK_MENU = SDL_SCANCODE_MENU; - IK_PRINTSCR= SDL_SCANCODE_PRINTSCREEN; - IK_SCROLLLOCK= SDL_SCANCODE_SCROLLLOCK; - IK_LBRACKET= SDL_SCANCODE_LEFTBRACKET; - IK_RBRACKET= SDL_SCANCODE_RIGHTBRACKET; - IK_SEMICOLON= SDL_SCANCODE_SEMICOLON; - IK_QUOTE = SDL_SCANCODE_APOSTROPHE; - IK_BACKSLASH= SDL_SCANCODE_BACKSLASH; - IK_SLASH = SDL_SCANCODE_SLASH; - IK_COMMA = SDL_SCANCODE_COMMA; - IK_DOT = SDL_SCANCODE_PERIOD; - IK_EQUALS = SDL_SCANCODE_EQUALS; - IK_0 = SDL_SCANCODE_0; - IK_1 = SDL_SCANCODE_1; - IK_2 = SDL_SCANCODE_2; - IK_3 = SDL_SCANCODE_3; - IK_4 = SDL_SCANCODE_4; - IK_5 = SDL_SCANCODE_5; - IK_6 = SDL_SCANCODE_6; - IK_7 = SDL_SCANCODE_7; - IK_8 = SDL_SCANCODE_8; - IK_9 = SDL_SCANCODE_9; - IK_F1 = SDL_SCANCODE_F1; - IK_F2 = SDL_SCANCODE_F2; - IK_F3 = SDL_SCANCODE_F3; - IK_F4 = SDL_SCANCODE_F4; - IK_F5 = SDL_SCANCODE_F5; - IK_F6 = SDL_SCANCODE_F6; - IK_F7 = SDL_SCANCODE_F7; - IK_F8 = SDL_SCANCODE_F8; - IK_F9 = SDL_SCANCODE_F9; - IK_F10 = SDL_SCANCODE_F10; - IK_F11 = SDL_SCANCODE_F11; - IK_F12 = SDL_SCANCODE_F12; - IK_END = SDL_SCANCODE_END; - IK_KPEND = SDL_SCANCODE_KP_1; - IK_BACKSPACE = SDL_SCANCODE_BACKSPACE; - IK_BACKQUOTE = SDL_SCANCODE_GRAVE; - IK_GRAVE = SDL_SCANCODE_GRAVE; - IK_PAUSE = SDL_SCANCODE_PAUSE; - IK_Y = SDL_SCANCODE_Y; - IK_N = SDL_SCANCODE_N; - IK_W = SDL_SCANCODE_W; - IK_A = SDL_SCANCODE_A; - IK_S = SDL_SCANCODE_S; - IK_D = SDL_SCANCODE_D; - IK_Q = SDL_SCANCODE_Q; - IK_E = SDL_SCANCODE_E; - IK_H = SDL_SCANCODE_H; - IK_J = SDL_SCANCODE_J; - IK_T = SDL_SCANCODE_T; - IK_Z = SDL_SCANCODE_Z; - IK_MINUS = SDL_SCANCODE_MINUS; - // TODO: think of something better than this shit - IK_LASTKEY = SDL_NUM_SCANCODES-1; - - VK_FIRSTKEY = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys; - VK_LEFT = VK_FIRSTKEY + 0; - VK_RIGHT = VK_FIRSTKEY + 1; - VK_UP = VK_FIRSTKEY + 2; - VK_DOWN = VK_FIRSTKEY + 3; - VK_FIRE = VK_FIRSTKEY + 4; - VK_OPEN = VK_FIRSTKEY + 5; - VK_JUMP = VK_FIRSTKEY + 6; - VK_CHAT = VK_FIRSTKEY + 7; - VK_ESCAPE = VK_FIRSTKEY + 8; - VK_0 = VK_FIRSTKEY + 9; - VK_1 = VK_FIRSTKEY + 10; - VK_2 = VK_FIRSTKEY + 11; - VK_3 = VK_FIRSTKEY + 12; - VK_4 = VK_FIRSTKEY + 13; - VK_5 = VK_FIRSTKEY + 14; - VK_6 = VK_FIRSTKEY + 15; - VK_7 = VK_FIRSTKEY + 16; - VK_8 = VK_FIRSTKEY + 17; - VK_9 = VK_FIRSTKEY + 18; - VK_A = VK_FIRSTKEY + 19; - VK_B = VK_FIRSTKEY + 20; - VK_C = VK_FIRSTKEY + 21; - VK_D = VK_FIRSTKEY + 22; - VK_E = VK_FIRSTKEY + 23; - VK_F = VK_FIRSTKEY + 24; - VK_CONSOLE = VK_FIRSTKEY + 25; - VK_STATUS = VK_FIRSTKEY + 26; - VK_TEAM = VK_FIRSTKEY + 27; - VK_PREV = VK_FIRSTKEY + 28; - VK_NEXT = VK_FIRSTKEY + 29; - VK_STRAFE = VK_FIRSTKEY + 30; - VK_LSTRAFE = VK_FIRSTKEY + 31; - VK_RSTRAFE = VK_FIRSTKEY + 32; - VK_PRINTSCR = VK_FIRSTKEY + 33; - VK_SHOWKBD = VK_FIRSTKEY + 34; - VK_HIDEKBD = VK_FIRSTKEY + 35; - VK_LASTKEY = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys + e_MaxVirtKeys - 1; - - AX_MINUS = 0; - AX_PLUS = 1; - HAT_LEFT = 0; - HAT_UP = 1; - HAT_RIGHT = 2; - HAT_DOWN = 3; - - JOY0_ATTACK = JOYK_BEG + 0*e_MaxJoyBtns + 0; - JOY1_ATTACK = JOYK_BEG + 1*e_MaxJoyBtns + 0; - JOY2_ATTACK = JOYK_BEG + 2*e_MaxJoyBtns + 0; - JOY3_ATTACK = JOYK_BEG + 3*e_MaxJoyBtns + 0; - JOY0_NEXT = JOYK_BEG + 0*e_MaxJoyBtns + 1; - JOY1_NEXT = JOYK_BEG + 1*e_MaxJoyBtns + 1; - JOY2_NEXT = JOYK_BEG + 2*e_MaxJoyBtns + 1; - JOY3_NEXT = JOYK_BEG + 3*e_MaxJoyBtns + 1; - JOY0_JUMP = JOYK_BEG + 0*e_MaxJoyBtns + 2; - JOY1_JUMP = JOYK_BEG + 1*e_MaxJoyBtns + 2; - JOY2_JUMP = JOYK_BEG + 2*e_MaxJoyBtns + 2; - JOY3_JUMP = JOYK_BEG + 3*e_MaxJoyBtns + 2; - JOY0_ACTIVATE = JOYK_BEG + 0*e_MaxJoyBtns + 3; - JOY1_ACTIVATE = JOYK_BEG + 1*e_MaxJoyBtns + 3; - JOY2_ACTIVATE = JOYK_BEG + 2*e_MaxJoyBtns + 3; - JOY3_ACTIVATE = JOYK_BEG + 3*e_MaxJoyBtns + 3; - JOY0_PREV = JOYK_BEG + 0*e_MaxJoyBtns + 4; - JOY1_PREV = JOYK_BEG + 1*e_MaxJoyBtns + 4; - JOY2_PREV = JOYK_BEG + 2*e_MaxJoyBtns + 4; - JOY3_PREV = JOYK_BEG + 3*e_MaxJoyBtns + 4; - - JOY0_LEFT = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; - JOY1_LEFT = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; - JOY2_LEFT = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; - JOY3_LEFT = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; - JOY0_RIGHT = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; - JOY1_RIGHT = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; - JOY2_RIGHT = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; - JOY3_RIGHT = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; - JOY0_UP = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_UP; - JOY1_UP = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_UP; - JOY2_UP = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_UP; - JOY3_UP = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_UP; - JOY0_DOWN = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; - JOY1_DOWN = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; - JOY2_DOWN = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; - JOY3_DOWN = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; - -function e_InitInput: Boolean; -procedure e_ReleaseInput; -procedure e_UnpressAllKeys; -procedure e_KeyUpDown (key: Integer; down: Boolean); - -function e_KeyPressed (key: Integer): Boolean; -function e_AnyKeyPressed: Boolean; -function e_GetFirstKeyPressed: Integer; -function e_HasJoysticks: Boolean; - -function e_JoyButtonToKey (id, btn: Integer): Integer; -function e_JoyAxisToKey (id, ax, dir: Integer): Integer; -function e_JoyHatToKey (id, hat, dir: Integer): Integer; - -var - e_JoystickAvailable: array [0..e_MaxJoys - 1] of Boolean; - e_JoystickDeadzones: array [0..e_MaxJoys - 1] of Integer = (8192, 8192, 8192, 8192); - e_KeyNames: array [0..e_MaxInputKeys] of String; - -implementation - -var - InputBuffer: array [0..e_MaxInputKeys - 1] of Boolean; - -procedure e_UnpressAllKeys; - var i: Integer; -begin - for i := 0 to High(InputBuffer) do - InputBuffer[i] := False -end; - -procedure e_KeyUpDown (key: Integer; down: Boolean); -begin - ASSERT(key >= 0); - ASSERT(key < e_MaxInputKeys); - if key > 0 then - InputBuffer[key] := down -end; - -procedure GenerateKeyNames; - var i, j, k: Integer; -begin - // keyboard key names - e_KeyNames[IK_0] := '0'; - e_KeyNames[IK_1] := '1'; - e_KeyNames[IK_2] := '2'; - e_KeyNames[IK_3] := '3'; - e_KeyNames[IK_4] := '4'; - e_KeyNames[IK_5] := '5'; - e_KeyNames[IK_6] := '6'; - e_KeyNames[IK_7] := '7'; - e_KeyNames[IK_8] := '8'; - e_KeyNames[IK_9] := '9'; - - for i := IK_A to IK_Z do - e_KeyNames[i] := '' + chr(ord('a') + (i - IK_a)); - - e_KeyNames[IK_ESCAPE] := 'ESCAPE'; - e_KeyNames[IK_ENTER] := 'ENTER'; - e_KeyNames[IK_TAB] := 'TAB'; - e_KeyNames[IK_BACKSPACE] := 'BACKSPACE'; - e_KeyNames[IK_SPACE] := 'SPACE'; - e_KeyNames[IK_UP] := 'UP'; - e_KeyNames[IK_LEFT] := 'LEFT'; - e_KeyNames[IK_RIGHT] := 'RIGHT'; - e_KeyNames[IK_DOWN] := 'DOWN'; - e_KeyNames[IK_INSERT] := 'INSERT'; - e_KeyNames[IK_DELETE] := 'DELETE'; - e_KeyNames[IK_HOME] := 'HOME'; - e_KeyNames[IK_END] := 'END'; - e_KeyNames[IK_PAGEUP] := 'PGUP'; - e_KeyNames[IK_PAGEDN] := 'PGDOWN'; - e_KeyNames[IK_KPINSERT] := 'PAD0'; - e_KeyNames[IK_KPEND] := 'PAD1'; - e_KeyNames[IK_KPDOWN] := 'PAD2'; - e_KeyNames[IK_KPPAGEDN] := 'PAD3'; - e_KeyNames[IK_KPLEFT] := 'PAD4'; - e_KeyNames[IK_KP5] := 'PAD5'; - e_KeyNames[IK_KPRIGHT] := 'PAD6'; - e_KeyNames[IK_KPHOME] := 'PAD7'; - e_KeyNames[IK_KPUP] := 'PAD8'; - e_KeyNames[IK_KPPAGEUP] := 'PAD9'; - e_KeyNames[IK_NUMLOCK] := 'NUM'; - e_KeyNames[IK_KPDIVIDE] := 'PAD/'; - e_KeyNames[IK_KPMULTIPLE] := 'PAD*'; - e_KeyNames[IK_KPMINUS] := 'PAD-'; - e_KeyNames[IK_KPPLUS] := 'PAD+'; - e_KeyNames[IK_KPENTER] := 'PADENTER'; - e_KeyNames[IK_KPDOT] := 'PAD.'; - e_KeyNames[IK_CAPSLOCK] := 'CAPS'; - e_KeyNames[IK_BACKQUOTE] := 'BACKQUOTE'; - e_KeyNames[IK_F1] := 'F1'; - e_KeyNames[IK_F2] := 'F2'; - e_KeyNames[IK_F3] := 'F3'; - e_KeyNames[IK_F4] := 'F4'; - e_KeyNames[IK_F5] := 'F5'; - e_KeyNames[IK_F6] := 'F6'; - e_KeyNames[IK_F7] := 'F7'; - e_KeyNames[IK_F8] := 'F8'; - e_KeyNames[IK_F9] := 'F9'; - e_KeyNames[IK_F10] := 'F10'; - e_KeyNames[IK_F11] := 'F11'; - e_KeyNames[IK_F12] := 'F12'; - e_KeyNames[IK_SHIFT] := 'LSHIFT'; - e_KeyNames[IK_RSHIFT] := 'RSHIFT'; - e_KeyNames[IK_CTRL] := 'LCTRL'; - e_KeyNames[IK_RCTRL] := 'RCTRL'; - e_KeyNames[IK_ALT] := 'LALT'; - e_KeyNames[IK_RALT] := 'RALT'; - e_KeyNames[IK_WIN] := 'LWIN'; - e_KeyNames[IK_RWIN] := 'RWIN'; - e_KeyNames[IK_MENU] := 'MENU'; - e_KeyNames[IK_PRINTSCR] := 'PSCRN'; - e_KeyNames[IK_SCROLLLOCK] := 'SCROLL'; - e_KeyNames[IK_PAUSE] := 'PAUSE'; - e_KeyNames[IK_LBRACKET] := '['; - e_KeyNames[IK_RBRACKET] := ']'; - e_KeyNames[IK_SEMICOLON] := ';'; - e_KeyNames[IK_QUOTE] := ''''; - e_KeyNames[IK_BACKSLASH] := '\'; - e_KeyNames[IK_SLASH] := '/'; - e_KeyNames[IK_COMMA] := ','; - e_KeyNames[IK_DOT] := '.'; - e_KeyNames[IK_MINUS] := '-'; - e_KeyNames[IK_EQUALS] := '='; - - // joysticks - for j := 0 to e_MaxJoys-1 do - begin - k := JOYK_BEG + j * e_MaxJoyBtns; - // buttons - for i := 0 to e_MaxJoyBtns-1 do - e_KeyNames[k + i] := Format('JOY%dB%d', [j, i]); - k := JOYA_BEG + j * e_MaxJoyAxes * 2; - // axes - for i := 0 to e_MaxJoyAxes-1 do - begin - e_KeyNames[k + i*2 ] := Format('JOY%dA%d+', [j, i]); - e_KeyNames[k + i*2 + 1] := Format('JOY%dA%d-', [j, i]); - end; - k := JOYH_BEG + j * e_MaxJoyHats * 4; - // hats - for i := 0 to e_MaxJoyHats-1 do - begin - e_KeyNames[k + i*4 ] := Format('JOY%dD%dL', [j, i]); - e_KeyNames[k + i*4 + 1] := Format('JOY%dD%dU', [j, i]); - e_KeyNames[k + i*4 + 2] := Format('JOY%dD%dR', [j, i]); - e_KeyNames[k + i*4 + 3] := Format('JOY%dD%dD', [j, i]); - end; - end; - - // vitrual keys - for i := 0 to e_MaxVirtKeys-1 do - e_KeyNames[VIRT_BEG + i] := 'VIRTUAL' + IntToStr(i); -end; - -function e_HasJoysticks: Boolean; - var i: Integer; -begin - i := 0; - while (i < e_MaxJoys) and (e_JoystickAvailable[i] = False) do inc(i); - result := i < e_MaxJoys -end; - -function e_InitInput: Boolean; - var i: Integer; -begin - for i := 0 to e_MaxJoys - 1 do - e_JoystickAvailable[i] := False; - GenerateKeyNames; - result := True -end; - -procedure e_ReleaseInput; - var i: Integer; -begin - for i := 0 to e_MaxJoys - 1 do - e_JoystickAvailable[i] := False -end; - -function e_KeyPressed (key: Integer): Boolean; -begin - ASSERT(key >= 0); - ASSERT(key < e_MaxInputKeys); - result := InputBuffer[key] -end; - -function e_AnyKeyPressed: Boolean; -begin - result := e_GetFirstKeyPressed <> IK_INVALID; -end; - -function e_GetFirstKeyPressed: Integer; - var i: Integer; -begin - i := 1; - while (i < e_MaxInputKeys) and (InputBuffer[i] = False) do inc(i); - if i < e_MaxInputKeys then - result := i - else - result := IK_INVALID -end; - -function e_JoyButtonToKey (id, btn: Integer): Integer; -begin - ASSERT(id >= 0); - ASSERT(id < e_MaxJoys); - ASSERT(btn >= 0); - ASSERT(btn < e_MaxJoyBtns); - result := JOYK_BEG + id*e_MaxJoyBtns + btn -end; - -function e_JoyAxisToKey (id, ax, dir: Integer): Integer; -begin - ASSERT(id >= 0); - ASSERT(id < e_MaxJoys); - ASSERT(ax >= 0); - ASSERT(ax < e_MaxJoyAxes); - ASSERT(dir in [AX_MINUS, AX_PLUS]); - result := JOYA_BEG + id*e_MaxJoyAxes*2 + ax*2 + dir -end; - -function e_JoyHatToKey (id, hat, dir: Integer): Integer; -begin - ASSERT(id >= 0); - ASSERT(id < e_MaxJoys); - ASSERT(hat >= 0); - ASSERT(hat < e_MaxJoyHats); - ASSERT(dir in [HAT_LEFT, HAT_UP, HAT_RIGHT, HAT_DOWN]); - result := JOYH_BEG + id*e_MaxJoyHats*4 + hat*4 + dir -end; +{$IF DEFINED(USE_SYSSTUB) OR DEFINED(USE_SDL)} + {$I e_input_stub.inc} +{$ELSEIF DEFINED(USE_SDL2)} + {$I e_input_sdl2.inc} +{$ELSE} + {$ERROR e_input driver not implemented?} +{$ENDIF} end. diff --git a/src/engine/e_input_sdl2.inc b/src/engine/e_input_sdl2.inc new file mode 100644 index 0000000..d619c51 --- /dev/null +++ b/src/engine/e_input_sdl2.inc @@ -0,0 +1,446 @@ +interface + +uses + SDL2, SysUtils; + +const + e_MaxKbdKeys = SDL_NUM_SCANCODES; + e_MaxJoys = 4; + e_MaxJoyBtns = 32; + e_MaxJoyAxes = 8; + e_MaxJoyHats = 8; + e_MaxVirtKeys = 48; + + e_MaxJoyKeys = e_MaxJoyBtns + e_MaxJoyAxes*2 + e_MaxJoyHats*4; + + e_MaxInputKeys = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys + e_MaxVirtKeys - 1; + // $$$..$$$ - 321 Keyboard buttons/keys + // $$$..$$$ - 4*32 Joystick buttons + // $$$..$$$ - 8*2 Joystick axes (- and +) + // $$$..$$$ - 4*4 Joystick hats (L U R D) + // $$$..$$$ - 48 Virtual buttons/keys + + KBRD_END = e_MaxKbdKeys; + JOYK_BEG = KBRD_END; + JOYK_END = JOYK_BEG + e_MaxJoyBtns*e_MaxJoys; + JOYA_BEG = JOYK_END; + JOYA_END = JOYA_BEG + e_MaxJoyAxes*2*e_MaxJoys; + JOYH_BEG = JOYA_END; + JOYH_END = JOYH_BEG + e_MaxJoyHats*4*e_MaxJoys; + VIRT_BEG = JOYH_END; + VIRT_END = VIRT_BEG + e_MaxVirtKeys; + + // these are apparently used in g_gui and g_game and elsewhere + IK_INVALID = 0; + IK_ESCAPE = SDL_SCANCODE_ESCAPE; + IK_RETURN = SDL_SCANCODE_RETURN; + IK_KPRETURN= SDL_SCANCODE_KP_ENTER; + IK_ENTER = SDL_SCANCODE_RETURN; + IK_KPINSERT = SDL_SCANCODE_KP_0; + IK_UP = SDL_SCANCODE_UP; + IK_KPUP = SDL_SCANCODE_KP_8; + IK_DOWN = SDL_SCANCODE_DOWN; + IK_KPDOWN = SDL_SCANCODE_KP_2; + IK_LEFT = SDL_SCANCODE_LEFT; + IK_KPLEFT = SDL_SCANCODE_KP_4; + IK_RIGHT = SDL_SCANCODE_RIGHT; + IK_KPRIGHT = SDL_SCANCODE_KP_6; + IK_DELETE = SDL_SCANCODE_DELETE; + IK_HOME = SDL_SCANCODE_HOME; + IK_KPHOME = SDL_SCANCODE_KP_7; + IK_INSERT = SDL_SCANCODE_INSERT; + IK_SPACE = SDL_SCANCODE_SPACE; + IK_CONTROL = SDL_SCANCODE_LCTRL; + IK_SHIFT = SDL_SCANCODE_LSHIFT; + IK_ALT = SDL_SCANCODE_LALT; + IK_TAB = SDL_SCANCODE_TAB; + IK_PAGEUP = SDL_SCANCODE_PAGEUP; + IK_KPPAGEUP= SDL_SCANCODE_KP_9; + IK_PAGEDN = SDL_SCANCODE_PAGEDOWN; + IK_KPPAGEDN= SDL_SCANCODE_KP_3; + IK_KP5 = SDL_SCANCODE_KP_5; + IK_NUMLOCK = SDL_SCANCODE_NUMLOCKCLEAR; + IK_KPDIVIDE= SDL_SCANCODE_KP_DIVIDE; + IK_KPMULTIPLE= SDL_SCANCODE_KP_MULTIPLY; + IK_KPMINUS = SDL_SCANCODE_KP_MINUS; + IK_KPPLUS = SDL_SCANCODE_KP_PLUS; + IK_KPENTER = SDL_SCANCODE_KP_ENTER; + IK_KPDOT = SDL_SCANCODE_KP_PERIOD; + IK_CAPSLOCK= SDL_SCANCODE_CAPSLOCK; + IK_RSHIFT = SDL_SCANCODE_RSHIFT; + IK_CTRL = SDL_SCANCODE_LCTRL; + IK_RCTRL = SDL_SCANCODE_RCTRL; + IK_RALT = SDL_SCANCODE_RALT; + IK_WIN = SDL_SCANCODE_LGUI; + IK_RWIN = SDL_SCANCODE_RGUI; + IK_MENU = SDL_SCANCODE_MENU; + IK_PRINTSCR= SDL_SCANCODE_PRINTSCREEN; + IK_SCROLLLOCK= SDL_SCANCODE_SCROLLLOCK; + IK_LBRACKET= SDL_SCANCODE_LEFTBRACKET; + IK_RBRACKET= SDL_SCANCODE_RIGHTBRACKET; + IK_SEMICOLON= SDL_SCANCODE_SEMICOLON; + IK_QUOTE = SDL_SCANCODE_APOSTROPHE; + IK_BACKSLASH= SDL_SCANCODE_BACKSLASH; + IK_SLASH = SDL_SCANCODE_SLASH; + IK_COMMA = SDL_SCANCODE_COMMA; + IK_DOT = SDL_SCANCODE_PERIOD; + IK_EQUALS = SDL_SCANCODE_EQUALS; + IK_0 = SDL_SCANCODE_0; + IK_1 = SDL_SCANCODE_1; + IK_2 = SDL_SCANCODE_2; + IK_3 = SDL_SCANCODE_3; + IK_4 = SDL_SCANCODE_4; + IK_5 = SDL_SCANCODE_5; + IK_6 = SDL_SCANCODE_6; + IK_7 = SDL_SCANCODE_7; + IK_8 = SDL_SCANCODE_8; + IK_9 = SDL_SCANCODE_9; + IK_F1 = SDL_SCANCODE_F1; + IK_F2 = SDL_SCANCODE_F2; + IK_F3 = SDL_SCANCODE_F3; + IK_F4 = SDL_SCANCODE_F4; + IK_F5 = SDL_SCANCODE_F5; + IK_F6 = SDL_SCANCODE_F6; + IK_F7 = SDL_SCANCODE_F7; + IK_F8 = SDL_SCANCODE_F8; + IK_F9 = SDL_SCANCODE_F9; + IK_F10 = SDL_SCANCODE_F10; + IK_F11 = SDL_SCANCODE_F11; + IK_F12 = SDL_SCANCODE_F12; + IK_END = SDL_SCANCODE_END; + IK_KPEND = SDL_SCANCODE_KP_1; + IK_BACKSPACE = SDL_SCANCODE_BACKSPACE; + IK_BACKQUOTE = SDL_SCANCODE_GRAVE; + IK_GRAVE = SDL_SCANCODE_GRAVE; + IK_PAUSE = SDL_SCANCODE_PAUSE; + IK_Y = SDL_SCANCODE_Y; + IK_N = SDL_SCANCODE_N; + IK_W = SDL_SCANCODE_W; + IK_A = SDL_SCANCODE_A; + IK_S = SDL_SCANCODE_S; + IK_D = SDL_SCANCODE_D; + IK_Q = SDL_SCANCODE_Q; + IK_E = SDL_SCANCODE_E; + IK_H = SDL_SCANCODE_H; + IK_J = SDL_SCANCODE_J; + IK_T = SDL_SCANCODE_T; + IK_Z = SDL_SCANCODE_Z; + IK_MINUS = SDL_SCANCODE_MINUS; + // TODO: think of something better than this shit + IK_LASTKEY = SDL_NUM_SCANCODES-1; + + VK_FIRSTKEY = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys; + VK_LEFT = VK_FIRSTKEY + 0; + VK_RIGHT = VK_FIRSTKEY + 1; + VK_UP = VK_FIRSTKEY + 2; + VK_DOWN = VK_FIRSTKEY + 3; + VK_FIRE = VK_FIRSTKEY + 4; + VK_OPEN = VK_FIRSTKEY + 5; + VK_JUMP = VK_FIRSTKEY + 6; + VK_CHAT = VK_FIRSTKEY + 7; + VK_ESCAPE = VK_FIRSTKEY + 8; + VK_0 = VK_FIRSTKEY + 9; + VK_1 = VK_FIRSTKEY + 10; + VK_2 = VK_FIRSTKEY + 11; + VK_3 = VK_FIRSTKEY + 12; + VK_4 = VK_FIRSTKEY + 13; + VK_5 = VK_FIRSTKEY + 14; + VK_6 = VK_FIRSTKEY + 15; + VK_7 = VK_FIRSTKEY + 16; + VK_8 = VK_FIRSTKEY + 17; + VK_9 = VK_FIRSTKEY + 18; + VK_A = VK_FIRSTKEY + 19; + VK_B = VK_FIRSTKEY + 20; + VK_C = VK_FIRSTKEY + 21; + VK_D = VK_FIRSTKEY + 22; + VK_E = VK_FIRSTKEY + 23; + VK_F = VK_FIRSTKEY + 24; + VK_CONSOLE = VK_FIRSTKEY + 25; + VK_STATUS = VK_FIRSTKEY + 26; + VK_TEAM = VK_FIRSTKEY + 27; + VK_PREV = VK_FIRSTKEY + 28; + VK_NEXT = VK_FIRSTKEY + 29; + VK_STRAFE = VK_FIRSTKEY + 30; + VK_LSTRAFE = VK_FIRSTKEY + 31; + VK_RSTRAFE = VK_FIRSTKEY + 32; + VK_PRINTSCR = VK_FIRSTKEY + 33; + VK_SHOWKBD = VK_FIRSTKEY + 34; + VK_HIDEKBD = VK_FIRSTKEY + 35; + VK_LASTKEY = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys + e_MaxVirtKeys - 1; + + AX_MINUS = 0; + AX_PLUS = 1; + HAT_LEFT = 0; + HAT_UP = 1; + HAT_RIGHT = 2; + HAT_DOWN = 3; + + JOY0_ATTACK = JOYK_BEG + 0*e_MaxJoyBtns + 0; + JOY1_ATTACK = JOYK_BEG + 1*e_MaxJoyBtns + 0; + JOY2_ATTACK = JOYK_BEG + 2*e_MaxJoyBtns + 0; + JOY3_ATTACK = JOYK_BEG + 3*e_MaxJoyBtns + 0; + JOY0_NEXT = JOYK_BEG + 0*e_MaxJoyBtns + 1; + JOY1_NEXT = JOYK_BEG + 1*e_MaxJoyBtns + 1; + JOY2_NEXT = JOYK_BEG + 2*e_MaxJoyBtns + 1; + JOY3_NEXT = JOYK_BEG + 3*e_MaxJoyBtns + 1; + JOY0_JUMP = JOYK_BEG + 0*e_MaxJoyBtns + 2; + JOY1_JUMP = JOYK_BEG + 1*e_MaxJoyBtns + 2; + JOY2_JUMP = JOYK_BEG + 2*e_MaxJoyBtns + 2; + JOY3_JUMP = JOYK_BEG + 3*e_MaxJoyBtns + 2; + JOY0_ACTIVATE = JOYK_BEG + 0*e_MaxJoyBtns + 3; + JOY1_ACTIVATE = JOYK_BEG + 1*e_MaxJoyBtns + 3; + JOY2_ACTIVATE = JOYK_BEG + 2*e_MaxJoyBtns + 3; + JOY3_ACTIVATE = JOYK_BEG + 3*e_MaxJoyBtns + 3; + JOY0_PREV = JOYK_BEG + 0*e_MaxJoyBtns + 4; + JOY1_PREV = JOYK_BEG + 1*e_MaxJoyBtns + 4; + JOY2_PREV = JOYK_BEG + 2*e_MaxJoyBtns + 4; + JOY3_PREV = JOYK_BEG + 3*e_MaxJoyBtns + 4; + + JOY0_LEFT = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; + JOY1_LEFT = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; + JOY2_LEFT = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; + JOY3_LEFT = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; + JOY0_RIGHT = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; + JOY1_RIGHT = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; + JOY2_RIGHT = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; + JOY3_RIGHT = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; + JOY0_UP = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_UP; + JOY1_UP = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_UP; + JOY2_UP = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_UP; + JOY3_UP = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_UP; + JOY0_DOWN = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; + JOY1_DOWN = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; + JOY2_DOWN = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; + JOY3_DOWN = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; + +function e_InitInput: Boolean; +procedure e_ReleaseInput; +procedure e_UnpressAllKeys; +procedure e_KeyUpDown (key: Integer; down: Boolean); + +function e_KeyPressed (key: Integer): Boolean; +function e_AnyKeyPressed: Boolean; +function e_GetFirstKeyPressed: Integer; +function e_HasJoysticks: Boolean; + +function e_JoyButtonToKey (id, btn: Integer): Integer; +function e_JoyAxisToKey (id, ax, dir: Integer): Integer; +function e_JoyHatToKey (id, hat, dir: Integer): Integer; + +var + e_JoystickAvailable: array [0..e_MaxJoys - 1] of Boolean; + e_JoystickDeadzones: array [0..e_MaxJoys - 1] of Integer = (8192, 8192, 8192, 8192); + e_KeyNames: array [0..e_MaxInputKeys] of String; + +implementation + +var + InputBuffer: array [0..e_MaxInputKeys - 1] of Boolean; + +procedure e_UnpressAllKeys; + var i: Integer; +begin + for i := 0 to High(InputBuffer) do + InputBuffer[i] := False +end; + +procedure e_KeyUpDown (key: Integer; down: Boolean); +begin + ASSERT(key >= 0); + ASSERT(key < e_MaxInputKeys); + if key > 0 then + InputBuffer[key] := down +end; + +procedure GenerateKeyNames; + var i, j, k: Integer; +begin + // keyboard key names + e_KeyNames[IK_0] := '0'; + e_KeyNames[IK_1] := '1'; + e_KeyNames[IK_2] := '2'; + e_KeyNames[IK_3] := '3'; + e_KeyNames[IK_4] := '4'; + e_KeyNames[IK_5] := '5'; + e_KeyNames[IK_6] := '6'; + e_KeyNames[IK_7] := '7'; + e_KeyNames[IK_8] := '8'; + e_KeyNames[IK_9] := '9'; + + for i := IK_A to IK_Z do + e_KeyNames[i] := '' + chr(ord('a') + (i - IK_a)); + + e_KeyNames[IK_ESCAPE] := 'ESCAPE'; + e_KeyNames[IK_ENTER] := 'ENTER'; + e_KeyNames[IK_TAB] := 'TAB'; + e_KeyNames[IK_BACKSPACE] := 'BACKSPACE'; + e_KeyNames[IK_SPACE] := 'SPACE'; + e_KeyNames[IK_UP] := 'UP'; + e_KeyNames[IK_LEFT] := 'LEFT'; + e_KeyNames[IK_RIGHT] := 'RIGHT'; + e_KeyNames[IK_DOWN] := 'DOWN'; + e_KeyNames[IK_INSERT] := 'INSERT'; + e_KeyNames[IK_DELETE] := 'DELETE'; + e_KeyNames[IK_HOME] := 'HOME'; + e_KeyNames[IK_END] := 'END'; + e_KeyNames[IK_PAGEUP] := 'PGUP'; + e_KeyNames[IK_PAGEDN] := 'PGDOWN'; + e_KeyNames[IK_KPINSERT] := 'PAD0'; + e_KeyNames[IK_KPEND] := 'PAD1'; + e_KeyNames[IK_KPDOWN] := 'PAD2'; + e_KeyNames[IK_KPPAGEDN] := 'PAD3'; + e_KeyNames[IK_KPLEFT] := 'PAD4'; + e_KeyNames[IK_KP5] := 'PAD5'; + e_KeyNames[IK_KPRIGHT] := 'PAD6'; + e_KeyNames[IK_KPHOME] := 'PAD7'; + e_KeyNames[IK_KPUP] := 'PAD8'; + e_KeyNames[IK_KPPAGEUP] := 'PAD9'; + e_KeyNames[IK_NUMLOCK] := 'NUM'; + e_KeyNames[IK_KPDIVIDE] := 'PAD/'; + e_KeyNames[IK_KPMULTIPLE] := 'PAD*'; + e_KeyNames[IK_KPMINUS] := 'PAD-'; + e_KeyNames[IK_KPPLUS] := 'PAD+'; + e_KeyNames[IK_KPENTER] := 'PADENTER'; + e_KeyNames[IK_KPDOT] := 'PAD.'; + e_KeyNames[IK_CAPSLOCK] := 'CAPS'; + e_KeyNames[IK_BACKQUOTE] := 'BACKQUOTE'; + e_KeyNames[IK_F1] := 'F1'; + e_KeyNames[IK_F2] := 'F2'; + e_KeyNames[IK_F3] := 'F3'; + e_KeyNames[IK_F4] := 'F4'; + e_KeyNames[IK_F5] := 'F5'; + e_KeyNames[IK_F6] := 'F6'; + e_KeyNames[IK_F7] := 'F7'; + e_KeyNames[IK_F8] := 'F8'; + e_KeyNames[IK_F9] := 'F9'; + e_KeyNames[IK_F10] := 'F10'; + e_KeyNames[IK_F11] := 'F11'; + e_KeyNames[IK_F12] := 'F12'; + e_KeyNames[IK_SHIFT] := 'LSHIFT'; + e_KeyNames[IK_RSHIFT] := 'RSHIFT'; + e_KeyNames[IK_CTRL] := 'LCTRL'; + e_KeyNames[IK_RCTRL] := 'RCTRL'; + e_KeyNames[IK_ALT] := 'LALT'; + e_KeyNames[IK_RALT] := 'RALT'; + e_KeyNames[IK_WIN] := 'LWIN'; + e_KeyNames[IK_RWIN] := 'RWIN'; + e_KeyNames[IK_MENU] := 'MENU'; + e_KeyNames[IK_PRINTSCR] := 'PSCRN'; + e_KeyNames[IK_SCROLLLOCK] := 'SCROLL'; + e_KeyNames[IK_PAUSE] := 'PAUSE'; + e_KeyNames[IK_LBRACKET] := '['; + e_KeyNames[IK_RBRACKET] := ']'; + e_KeyNames[IK_SEMICOLON] := ';'; + e_KeyNames[IK_QUOTE] := ''''; + e_KeyNames[IK_BACKSLASH] := '\'; + e_KeyNames[IK_SLASH] := '/'; + e_KeyNames[IK_COMMA] := ','; + e_KeyNames[IK_DOT] := '.'; + e_KeyNames[IK_MINUS] := '-'; + e_KeyNames[IK_EQUALS] := '='; + + // joysticks + for j := 0 to e_MaxJoys-1 do + begin + k := JOYK_BEG + j * e_MaxJoyBtns; + // buttons + for i := 0 to e_MaxJoyBtns-1 do + e_KeyNames[k + i] := Format('JOY%dB%d', [j, i]); + k := JOYA_BEG + j * e_MaxJoyAxes * 2; + // axes + for i := 0 to e_MaxJoyAxes-1 do + begin + e_KeyNames[k + i*2 ] := Format('JOY%dA%d+', [j, i]); + e_KeyNames[k + i*2 + 1] := Format('JOY%dA%d-', [j, i]); + end; + k := JOYH_BEG + j * e_MaxJoyHats * 4; + // hats + for i := 0 to e_MaxJoyHats-1 do + begin + e_KeyNames[k + i*4 ] := Format('JOY%dD%dL', [j, i]); + e_KeyNames[k + i*4 + 1] := Format('JOY%dD%dU', [j, i]); + e_KeyNames[k + i*4 + 2] := Format('JOY%dD%dR', [j, i]); + e_KeyNames[k + i*4 + 3] := Format('JOY%dD%dD', [j, i]); + end; + end; + + // vitrual keys + for i := 0 to e_MaxVirtKeys-1 do + e_KeyNames[VIRT_BEG + i] := 'VIRTUAL' + IntToStr(i); +end; + +function e_HasJoysticks: Boolean; + var i: Integer; +begin + i := 0; + while (i < e_MaxJoys) and (e_JoystickAvailable[i] = False) do inc(i); + result := i < e_MaxJoys +end; + +function e_InitInput: Boolean; + var i: Integer; +begin + for i := 0 to e_MaxJoys - 1 do + e_JoystickAvailable[i] := False; + GenerateKeyNames; + result := True +end; + +procedure e_ReleaseInput; + var i: Integer; +begin + for i := 0 to e_MaxJoys - 1 do + e_JoystickAvailable[i] := False +end; + +function e_KeyPressed (key: Integer): Boolean; +begin + ASSERT(key >= 0); + ASSERT(key < e_MaxInputKeys); + result := InputBuffer[key] +end; + +function e_AnyKeyPressed: Boolean; +begin + result := e_GetFirstKeyPressed <> IK_INVALID; +end; + +function e_GetFirstKeyPressed: Integer; + var i: Integer; +begin + i := 1; + while (i < e_MaxInputKeys) and (InputBuffer[i] = False) do inc(i); + if i < e_MaxInputKeys then + result := i + else + result := IK_INVALID +end; + +function e_JoyButtonToKey (id, btn: Integer): Integer; +begin + ASSERT(id >= 0); + ASSERT(id < e_MaxJoys); + ASSERT(btn >= 0); + ASSERT(btn < e_MaxJoyBtns); + result := JOYK_BEG + id*e_MaxJoyBtns + btn +end; + +function e_JoyAxisToKey (id, ax, dir: Integer): Integer; +begin + ASSERT(id >= 0); + ASSERT(id < e_MaxJoys); + ASSERT(ax >= 0); + ASSERT(ax < e_MaxJoyAxes); + ASSERT(dir in [AX_MINUS, AX_PLUS]); + result := JOYA_BEG + id*e_MaxJoyAxes*2 + ax*2 + dir +end; + +function e_JoyHatToKey (id, hat, dir: Integer): Integer; +begin + ASSERT(id >= 0); + ASSERT(id < e_MaxJoys); + ASSERT(hat >= 0); + ASSERT(hat < e_MaxJoyHats); + ASSERT(dir in [HAT_LEFT, HAT_UP, HAT_RIGHT, HAT_DOWN]); + result := JOYH_BEG + id*e_MaxJoyHats*4 + hat*4 + dir +end; diff --git a/src/engine/e_input_stub.inc b/src/engine/e_input_stub.inc new file mode 100644 index 0000000..b2ca332 --- /dev/null +++ b/src/engine/e_input_stub.inc @@ -0,0 +1,458 @@ +interface + + uses SysUtils; + + const + e_MaxKbdKeys = 256; + e_MaxJoys = 4; + e_MaxJoyBtns = 32; + e_MaxJoyAxes = 8; + e_MaxJoyHats = 8; + e_MaxVirtKeys = 48; + + e_MaxJoyKeys = e_MaxJoyBtns + e_MaxJoyAxes*2 + e_MaxJoyHats*4; + + e_MaxInputKeys = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys + e_MaxVirtKeys - 1; + // $$$..$$$ - 321 Keyboard buttons/keys + // $$$..$$$ - 4*32 Joystick buttons + // $$$..$$$ - 8*2 Joystick axes (- and +) + // $$$..$$$ - 4*4 Joystick hats (L U R D) + // $$$..$$$ - 48 Virtual buttons/keys + + KBRD_END = e_MaxKbdKeys; + JOYK_BEG = KBRD_END; + JOYK_END = JOYK_BEG + e_MaxJoyBtns*e_MaxJoys; + JOYA_BEG = JOYK_END; + JOYA_END = JOYA_BEG + e_MaxJoyAxes*2*e_MaxJoys; + JOYH_BEG = JOYA_END; + JOYH_END = JOYH_BEG + e_MaxJoyHats*4*e_MaxJoys; + VIRT_BEG = JOYH_END; + VIRT_END = VIRT_BEG + e_MaxVirtKeys; + + // these are apparently used in g_gui and g_game and elsewhere + IK_INVALID = 0; + IK_ESCAPE = 1; + IK_RETURN = 2; + IK_KPRETURN= 3; + IK_ENTER = IK_RETURN; + IK_KPINSERT = 5; + IK_UP = 6; + IK_KPUP = 7; + IK_DOWN = 8; + IK_KPDOWN = 9; + IK_LEFT = 10; + IK_KPLEFT = 11; + IK_RIGHT = 12; + IK_KPRIGHT = 13; + IK_DELETE = 14; + IK_HOME = 15; + IK_KPHOME = 16; + IK_INSERT = 17; + IK_SPACE = 18; + IK_SHIFT = 20; + IK_ALT = 21; + IK_TAB = 22; + IK_PAGEUP = 23; + IK_KPPAGEUP= 24; + IK_PAGEDN = 25; + IK_KPPAGEDN= 26; + IK_KP5 = 27; + IK_NUMLOCK = 28; + IK_KPDIVIDE= 29; + IK_KPMULTIPLE= 30; + IK_KPMINUS = 31; + IK_KPPLUS = 32; + IK_KPENTER = IK_KPRETURN; + IK_KPDOT = 34; + IK_CAPSLOCK= 35; + IK_RSHIFT = 36; + IK_CTRL = 37; + IK_RCTRL = 38; + IK_RALT = 39; + IK_WIN = 40; + IK_RWIN = 41; + IK_MENU = 42; + IK_PRINTSCR= 43; + IK_SCROLLLOCK= 44; + IK_LBRACKET= 45; + IK_RBRACKET= 46; + IK_SEMICOLON= 47; + IK_QUOTE = 48; + IK_BACKSLASH= 49; + IK_SLASH = 50; + IK_COMMA = 51; + IK_DOT = 52; + IK_EQUALS = 53; + IK_0 = 54; + IK_1 = 55; + IK_2 = 56; + IK_3 = 57; + IK_4 = 58; + IK_5 = 59; + IK_6 = 60; + IK_7 = 61; + IK_8 = 62; + IK_9 = 63; + IK_F1 = 64; + IK_F2 = 65; + IK_F3 = 66; + IK_F4 = 67; + IK_F5 = 68; + IK_F6 = 69; + IK_F7 = 70; + IK_F8 = 71; + IK_F9 = 72; + IK_F10 = 73; + IK_F11 = 74; + IK_F12 = 75; + IK_END = 76; + IK_KPEND = 77; + IK_BACKSPACE = 78; + IK_BACKQUOTE = 79; + IK_GRAVE = IK_BACKQUOTE; + IK_PAUSE = 81; + IK_A = 82; + IK_B = 83; + IK_C = 84; + IK_D = 85; + IK_E = 86; + IK_F = 87; + IK_G = 88; + IK_H = 89; + IK_I = 90; + IK_J = 91; + IK_K = 92; + IK_L = 93; + IK_M = 94; + IK_N = 95; + IK_O = 96; + IK_P = 97; + IK_Q = 98; + IK_R = 99; + IK_S = 100; + IK_T = 101; + IK_U = 102; + IK_V = 103; + IK_W = 104; + IK_X = 105; + IK_Y = 106; + IK_Z = 107; + IK_MINUS = 108; + // TODO: think of something better than this shit + IK_LASTKEY = e_MaxKbdKeys-1; + + VK_FIRSTKEY = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys; + VK_LEFT = VK_FIRSTKEY + 0; + VK_RIGHT = VK_FIRSTKEY + 1; + VK_UP = VK_FIRSTKEY + 2; + VK_DOWN = VK_FIRSTKEY + 3; + VK_FIRE = VK_FIRSTKEY + 4; + VK_OPEN = VK_FIRSTKEY + 5; + VK_JUMP = VK_FIRSTKEY + 6; + VK_CHAT = VK_FIRSTKEY + 7; + VK_ESCAPE = VK_FIRSTKEY + 8; + VK_0 = VK_FIRSTKEY + 9; + VK_1 = VK_FIRSTKEY + 10; + VK_2 = VK_FIRSTKEY + 11; + VK_3 = VK_FIRSTKEY + 12; + VK_4 = VK_FIRSTKEY + 13; + VK_5 = VK_FIRSTKEY + 14; + VK_6 = VK_FIRSTKEY + 15; + VK_7 = VK_FIRSTKEY + 16; + VK_8 = VK_FIRSTKEY + 17; + VK_9 = VK_FIRSTKEY + 18; + VK_A = VK_FIRSTKEY + 19; + VK_B = VK_FIRSTKEY + 20; + VK_C = VK_FIRSTKEY + 21; + VK_D = VK_FIRSTKEY + 22; + VK_E = VK_FIRSTKEY + 23; + VK_F = VK_FIRSTKEY + 24; + VK_CONSOLE = VK_FIRSTKEY + 25; + VK_STATUS = VK_FIRSTKEY + 26; + VK_TEAM = VK_FIRSTKEY + 27; + VK_PREV = VK_FIRSTKEY + 28; + VK_NEXT = VK_FIRSTKEY + 29; + VK_STRAFE = VK_FIRSTKEY + 30; + VK_LSTRAFE = VK_FIRSTKEY + 31; + VK_RSTRAFE = VK_FIRSTKEY + 32; + VK_PRINTSCR = VK_FIRSTKEY + 33; + VK_SHOWKBD = VK_FIRSTKEY + 34; + VK_HIDEKBD = VK_FIRSTKEY + 35; + VK_LASTKEY = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys + e_MaxVirtKeys - 1; + + AX_MINUS = 0; + AX_PLUS = 1; + HAT_LEFT = 0; + HAT_UP = 1; + HAT_RIGHT = 2; + HAT_DOWN = 3; + + JOY0_ATTACK = JOYK_BEG + 0*e_MaxJoyBtns + 0; + JOY1_ATTACK = JOYK_BEG + 1*e_MaxJoyBtns + 0; + JOY2_ATTACK = JOYK_BEG + 2*e_MaxJoyBtns + 0; + JOY3_ATTACK = JOYK_BEG + 3*e_MaxJoyBtns + 0; + JOY0_NEXT = JOYK_BEG + 0*e_MaxJoyBtns + 1; + JOY1_NEXT = JOYK_BEG + 1*e_MaxJoyBtns + 1; + JOY2_NEXT = JOYK_BEG + 2*e_MaxJoyBtns + 1; + JOY3_NEXT = JOYK_BEG + 3*e_MaxJoyBtns + 1; + JOY0_JUMP = JOYK_BEG + 0*e_MaxJoyBtns + 2; + JOY1_JUMP = JOYK_BEG + 1*e_MaxJoyBtns + 2; + JOY2_JUMP = JOYK_BEG + 2*e_MaxJoyBtns + 2; + JOY3_JUMP = JOYK_BEG + 3*e_MaxJoyBtns + 2; + JOY0_ACTIVATE = JOYK_BEG + 0*e_MaxJoyBtns + 3; + JOY1_ACTIVATE = JOYK_BEG + 1*e_MaxJoyBtns + 3; + JOY2_ACTIVATE = JOYK_BEG + 2*e_MaxJoyBtns + 3; + JOY3_ACTIVATE = JOYK_BEG + 3*e_MaxJoyBtns + 3; + JOY0_PREV = JOYK_BEG + 0*e_MaxJoyBtns + 4; + JOY1_PREV = JOYK_BEG + 1*e_MaxJoyBtns + 4; + JOY2_PREV = JOYK_BEG + 2*e_MaxJoyBtns + 4; + JOY3_PREV = JOYK_BEG + 3*e_MaxJoyBtns + 4; + + JOY0_LEFT = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; + JOY1_LEFT = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; + JOY2_LEFT = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; + JOY3_LEFT = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_LEFT; + JOY0_RIGHT = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; + JOY1_RIGHT = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; + JOY2_RIGHT = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; + JOY3_RIGHT = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_RIGHT; + JOY0_UP = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_UP; + JOY1_UP = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_UP; + JOY2_UP = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_UP; + JOY3_UP = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_UP; + JOY0_DOWN = JOYH_BEG + 0*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; + JOY1_DOWN = JOYH_BEG + 1*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; + JOY2_DOWN = JOYH_BEG + 2*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; + JOY3_DOWN = JOYH_BEG + 3*e_MaxJoyHats*4 + 0*4 + HAT_DOWN; + +function e_InitInput: Boolean; +procedure e_ReleaseInput; +procedure e_UnpressAllKeys; +procedure e_KeyUpDown (key: Integer; down: Boolean); + +function e_KeyPressed (key: Integer): Boolean; +function e_AnyKeyPressed: Boolean; +function e_GetFirstKeyPressed: Integer; +function e_HasJoysticks: Boolean; + +function e_JoyButtonToKey (id, btn: Integer): Integer; +function e_JoyAxisToKey (id, ax, dir: Integer): Integer; +function e_JoyHatToKey (id, hat, dir: Integer): Integer; + +var + e_JoystickAvailable: array [0..e_MaxJoys - 1] of Boolean; + e_JoystickDeadzones: array [0..e_MaxJoys - 1] of Integer = (8192, 8192, 8192, 8192); + e_KeyNames: array [0..e_MaxInputKeys] of String; + +implementation + +var + InputBuffer: array [0..e_MaxInputKeys - 1] of Boolean; + +procedure e_UnpressAllKeys; + var i: Integer; +begin + for i := 0 to High(InputBuffer) do + InputBuffer[i] := False +end; + +procedure e_KeyUpDown (key: Integer; down: Boolean); +begin + ASSERT(key >= 0); + ASSERT(key < e_MaxInputKeys); + if key > 0 then + InputBuffer[key] := down +end; + +procedure GenerateKeyNames; + var i, j, k: Integer; +begin + // keyboard key names + e_KeyNames[IK_0] := '0'; + e_KeyNames[IK_1] := '1'; + e_KeyNames[IK_2] := '2'; + e_KeyNames[IK_3] := '3'; + e_KeyNames[IK_4] := '4'; + e_KeyNames[IK_5] := '5'; + e_KeyNames[IK_6] := '6'; + e_KeyNames[IK_7] := '7'; + e_KeyNames[IK_8] := '8'; + e_KeyNames[IK_9] := '9'; + + for i := IK_A to IK_Z do + e_KeyNames[i] := '' + chr(ord('a') + (i - IK_a)); + + e_KeyNames[IK_ESCAPE] := 'ESCAPE'; + e_KeyNames[IK_ENTER] := 'ENTER'; + e_KeyNames[IK_TAB] := 'TAB'; + e_KeyNames[IK_BACKSPACE] := 'BACKSPACE'; + e_KeyNames[IK_SPACE] := 'SPACE'; + e_KeyNames[IK_UP] := 'UP'; + e_KeyNames[IK_LEFT] := 'LEFT'; + e_KeyNames[IK_RIGHT] := 'RIGHT'; + e_KeyNames[IK_DOWN] := 'DOWN'; + e_KeyNames[IK_INSERT] := 'INSERT'; + e_KeyNames[IK_DELETE] := 'DELETE'; + e_KeyNames[IK_HOME] := 'HOME'; + e_KeyNames[IK_END] := 'END'; + e_KeyNames[IK_PAGEUP] := 'PGUP'; + e_KeyNames[IK_PAGEDN] := 'PGDOWN'; + e_KeyNames[IK_KPINSERT] := 'PAD0'; + e_KeyNames[IK_KPEND] := 'PAD1'; + e_KeyNames[IK_KPDOWN] := 'PAD2'; + e_KeyNames[IK_KPPAGEDN] := 'PAD3'; + e_KeyNames[IK_KPLEFT] := 'PAD4'; + e_KeyNames[IK_KP5] := 'PAD5'; + e_KeyNames[IK_KPRIGHT] := 'PAD6'; + e_KeyNames[IK_KPHOME] := 'PAD7'; + e_KeyNames[IK_KPUP] := 'PAD8'; + e_KeyNames[IK_KPPAGEUP] := 'PAD9'; + e_KeyNames[IK_NUMLOCK] := 'NUM'; + e_KeyNames[IK_KPDIVIDE] := 'PAD/'; + e_KeyNames[IK_KPMULTIPLE] := 'PAD*'; + e_KeyNames[IK_KPMINUS] := 'PAD-'; + e_KeyNames[IK_KPPLUS] := 'PAD+'; + e_KeyNames[IK_KPENTER] := 'PADENTER'; + e_KeyNames[IK_KPDOT] := 'PAD.'; + e_KeyNames[IK_CAPSLOCK] := 'CAPS'; + e_KeyNames[IK_BACKQUOTE] := 'BACKQUOTE'; + e_KeyNames[IK_F1] := 'F1'; + e_KeyNames[IK_F2] := 'F2'; + e_KeyNames[IK_F3] := 'F3'; + e_KeyNames[IK_F4] := 'F4'; + e_KeyNames[IK_F5] := 'F5'; + e_KeyNames[IK_F6] := 'F6'; + e_KeyNames[IK_F7] := 'F7'; + e_KeyNames[IK_F8] := 'F8'; + e_KeyNames[IK_F9] := 'F9'; + e_KeyNames[IK_F10] := 'F10'; + e_KeyNames[IK_F11] := 'F11'; + e_KeyNames[IK_F12] := 'F12'; + e_KeyNames[IK_SHIFT] := 'LSHIFT'; + e_KeyNames[IK_RSHIFT] := 'RSHIFT'; + e_KeyNames[IK_CTRL] := 'LCTRL'; + e_KeyNames[IK_RCTRL] := 'RCTRL'; + e_KeyNames[IK_ALT] := 'LALT'; + e_KeyNames[IK_RALT] := 'RALT'; + e_KeyNames[IK_WIN] := 'LWIN'; + e_KeyNames[IK_RWIN] := 'RWIN'; + e_KeyNames[IK_MENU] := 'MENU'; + e_KeyNames[IK_PRINTSCR] := 'PSCRN'; + e_KeyNames[IK_SCROLLLOCK] := 'SCROLL'; + e_KeyNames[IK_PAUSE] := 'PAUSE'; + e_KeyNames[IK_LBRACKET] := '['; + e_KeyNames[IK_RBRACKET] := ']'; + e_KeyNames[IK_SEMICOLON] := ';'; + e_KeyNames[IK_QUOTE] := ''''; + e_KeyNames[IK_BACKSLASH] := '\'; + e_KeyNames[IK_SLASH] := '/'; + e_KeyNames[IK_COMMA] := ','; + e_KeyNames[IK_DOT] := '.'; + e_KeyNames[IK_MINUS] := '-'; + e_KeyNames[IK_EQUALS] := '='; + + // joysticks + for j := 0 to e_MaxJoys-1 do + begin + k := JOYK_BEG + j * e_MaxJoyBtns; + // buttons + for i := 0 to e_MaxJoyBtns-1 do + e_KeyNames[k + i] := Format('JOY%dB%d', [j, i]); + k := JOYA_BEG + j * e_MaxJoyAxes * 2; + // axes + for i := 0 to e_MaxJoyAxes-1 do + begin + e_KeyNames[k + i*2 ] := Format('JOY%dA%d+', [j, i]); + e_KeyNames[k + i*2 + 1] := Format('JOY%dA%d-', [j, i]); + end; + k := JOYH_BEG + j * e_MaxJoyHats * 4; + // hats + for i := 0 to e_MaxJoyHats-1 do + begin + e_KeyNames[k + i*4 ] := Format('JOY%dD%dL', [j, i]); + e_KeyNames[k + i*4 + 1] := Format('JOY%dD%dU', [j, i]); + e_KeyNames[k + i*4 + 2] := Format('JOY%dD%dR', [j, i]); + e_KeyNames[k + i*4 + 3] := Format('JOY%dD%dD', [j, i]); + end; + end; + + // vitrual keys + for i := 0 to e_MaxVirtKeys-1 do + e_KeyNames[VIRT_BEG + i] := 'VIRTUAL' + IntToStr(i); +end; + +function e_HasJoysticks: Boolean; + var i: Integer; +begin + i := 0; + while (i < e_MaxJoys) and (e_JoystickAvailable[i] = False) do inc(i); + result := i < e_MaxJoys +end; + +function e_InitInput: Boolean; + var i: Integer; +begin + for i := 0 to e_MaxJoys - 1 do + e_JoystickAvailable[i] := False; + GenerateKeyNames; + result := True +end; + +procedure e_ReleaseInput; + var i: Integer; +begin + for i := 0 to e_MaxJoys - 1 do + e_JoystickAvailable[i] := False +end; + +function e_KeyPressed (key: Integer): Boolean; +begin + ASSERT(key >= 0); + ASSERT(key < e_MaxInputKeys); + result := InputBuffer[key] +end; + +function e_AnyKeyPressed: Boolean; +begin + result := e_GetFirstKeyPressed <> IK_INVALID; +end; + +function e_GetFirstKeyPressed: Integer; + var i: Integer; +begin + i := 1; + while (i < e_MaxInputKeys) and (InputBuffer[i] = False) do inc(i); + if i < e_MaxInputKeys then + result := i + else + result := IK_INVALID +end; + +function e_JoyButtonToKey (id, btn: Integer): Integer; +begin + ASSERT(id >= 0); + ASSERT(id < e_MaxJoys); + ASSERT(btn >= 0); + ASSERT(btn < e_MaxJoyBtns); + result := JOYK_BEG + id*e_MaxJoyBtns + btn +end; + +function e_JoyAxisToKey (id, ax, dir: Integer): Integer; +begin + ASSERT(id >= 0); + ASSERT(id < e_MaxJoys); + ASSERT(ax >= 0); + ASSERT(ax < e_MaxJoyAxes); + ASSERT(dir in [AX_MINUS, AX_PLUS]); + result := JOYA_BEG + id*e_MaxJoyAxes*2 + ax*2 + dir +end; + +function e_JoyHatToKey (id, hat, dir: Integer): Integer; +begin + ASSERT(id >= 0); + ASSERT(id < e_MaxJoys); + ASSERT(hat >= 0); + ASSERT(hat < e_MaxJoyHats); + ASSERT(dir in [HAT_LEFT, HAT_UP, HAT_RIGHT, HAT_DOWN]); + result := JOYH_BEG + id*e_MaxJoyHats*4 + hat*4 + dir +end; diff --git a/src/engine/e_sound_al.inc b/src/engine/e_sound_al.inc index c57e2a3..53ee47e 100644 --- a/src/engine/e_sound_al.inc +++ b/src/engine/e_sound_al.inc @@ -98,7 +98,7 @@ var implementation uses - g_window, g_options, utils; + g_options, utils; const NUM_SOURCES = 255; // + 1 stereo diff --git a/src/engine/e_sound_sdl.inc b/src/engine/e_sound_sdl.inc index 35cd2c3..4d9eaba 100644 --- a/src/engine/e_sound_sdl.inc +++ b/src/engine/e_sound_sdl.inc @@ -15,11 +15,9 @@ interface uses - sdl2, - SDL2_mixer, {$IFDEF USE_MEMPOOL}mempool,{$ENDIF} - e_log, - SysUtils; + SDL2, SDL2_mixer, + e_log, SysUtils; type TSoundRec = record diff --git a/src/engine/e_soundfile_wav.pas b/src/engine/e_soundfile_wav.pas index 0ebe256..ba7bcdf 100644 --- a/src/engine/e_soundfile_wav.pas +++ b/src/engine/e_soundfile_wav.pas @@ -44,7 +44,13 @@ type implementation -uses sdl2, utils, e_log; +uses + {$IFDEF USE_SDL} + SDL, + {$ELSE} + SDL2, + {$ENDIF} + utils, e_log; (* TWAVLoaderFactory *) @@ -73,7 +79,6 @@ begin end; (* TWAVLoader *) - function TWAVLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; var Spec: TSDL_AudioSpec; @@ -85,14 +90,22 @@ begin RW := SDL_RWFromConstMem(Data, Len); +{$IFDEF USE_SDL2} if SDL_LoadWAV_RW(RW, 0, @Spec, @TmpBuf, @TmpLen) = nil then +{$ELSE} + if SDL_LoadWAV_RW(RW, 0, @Spec, PUInt8(@TmpBuf), @TmpLen) = nil then +{$ENDIF} begin e_LogWriteln('Could not load WAV: ' + SDL_GetError()); end else begin FFormat.SampleRate := Spec.freq; - FFormat.SampleBits := SDL_AUDIO_BITSIZE(Spec.format); + {$IFDEF USE_SDL2} + FFormat.SampleBits := SDL_AUDIO_BITSIZE(Spec.format); + {$ELSE} + FFormat.SampleBits := Spec.format and $FF; + {$ENDIF} FFormat.Channels := Spec.channels; FStreaming := False; // never stream wavs FDataLen := TmpLen; @@ -120,14 +133,22 @@ begin exit; end; +{$IFDEF USE_SDL2} if SDL_LoadWAV_RW(RW, 0, @Spec, @TmpBuf, @TmpLen) = nil then +{$ELSE} + if SDL_LoadWAV_RW(RW, 0, @Spec, PUInt8(@TmpBuf), @TmpLen) = nil then +{$ENDIF} begin e_LogWritefln('Could not load WAV file `%s`: %s', [FName, SDL_GetError()]); end else begin FFormat.SampleRate := Spec.freq; - FFormat.SampleBits := SDL_AUDIO_BITSIZE(Spec.format); + {$IFDEF USE_SDL2} + FFormat.SampleBits := SDL_AUDIO_BITSIZE(Spec.format); + {$ELSE} + FFormat.SampleBits := Spec.format and $FF; + {$ENDIF} FFormat.Channels := Spec.channels; FStreaming := False; // never stream wavs FDataLen := TmpLen; diff --git a/src/game/Doom2DF.lpr b/src/game/Doom2DF.lpr index 875879f..18f1f21 100644 --- a/src/game/Doom2DF.lpr +++ b/src/game/Doom2DF.lpr @@ -21,6 +21,22 @@ {$ENDIF} {$HINTS OFF} +{$IF DEFINED(USE_SYSSTUB)} + {$IF DEFINED(USE_SDL) OR DEFINED(USE_SDL2)} + {$ERROR Only one system driver must be selected!} + {$ENDIF} +{$ELSEIF DEFINED(USE_SDL)} + {$IF DEFINED(USE_SYSSTUB) OR DEFINED(USE_SDL2)} + {$ERROR Only one system driver must be selected!} + {$ENDIF} +{$ELSEIF DEFINED(USE_SDL2)} + {$IF DEFINED(USE_SYSSTUB) OR DEFINED(USE_SDL)} + {$ERROR Only one system driver must be selected!} + {$ENDIF} +{$ELSE} + {$ERROR System driver not selected. Use -dUSE_SYSSTUB or -dUSE_SDL or -dUSE_SDL2} +{$ENDIF} + {$IF DEFINED(USE_SDLMIXER)} {$IF DEFINED(USE_FMOD) OR DEFINED(USE_OPENAL)} {$ERROR Only one sound driver must be selected!} @@ -34,7 +50,7 @@ {$ERROR Only one sound driver must be selected!} {$ENDIF} {$ELSE} - {$ERROR Sound driver not selected. Use -DUSE_SDLMIXER or -DUSE_FMOD or -DUSE_OPENAL} + {$ERROR Sound driver not selected. Use -dUSE_SDLMIXER or -dUSE_FMOD or -dUSE_OPENAL} {$ENDIF} uses @@ -54,14 +70,23 @@ uses {$IFDEF USE_MINIUPNPC} miniupnpc in '../lib/miniupnpc/miniupnpc.pas', {$ENDIF} + +{$IFDEF USE_SDL} + SDL, +{$ENDIF} +{$IFDEF USE_SDL2} SDL2 in '../lib/sdl2/sdl2.pas', -{$IFDEF USE_SDLMIXER} - SDL2_mixer in '../lib/sdl2/SDL2_mixer.pas', + {$IFDEF USE_SDLMIXER} + SDL2_mixer in '../lib/sdl2/SDL2_mixer.pas', + {$ENDIF} {$ENDIF} + {$IFDEF USE_OPENAL} AL in '../lib/openal/al.pas', e_soundfile in '../engine/e_soundfile.pas', - e_soundfile_wav in '../engine/e_soundfile_wav.pas', + {$IF DEFINED(USE_SDL) OR DEFINED(USE_SDL2)} + e_soundfile_wav in '../engine/e_soundfile_wav.pas', + {$ENDIF} {$IFDEF USE_VORBIS} vorbis in '../lib/vorbis/vorbis.pas', e_soundfile_vorbis in '../engine/e_soundfile_vorbis.pas', @@ -90,6 +115,7 @@ uses ogg in '../lib/vorbis/ogg.pas', // this has to come last because link order {$ENDIF} {$ENDIF} + ENet in '../lib/enet/enet.pp', e_graphics in '../engine/e_graphics.pas', e_input in '../engine/e_input.pas', @@ -131,6 +157,19 @@ uses g_triggers in 'g_triggers.pas', g_weapons in 'g_weapons.pas', g_window in 'g_window.pas', +{$IFDEF USE_SYSSTUB} + g_system in 'stub/g_system.pas', + g_touch in 'stub/g_touch.pas', +{$ENDIF} +{$IFDEF USE_SDL} + g_system in 'sdl/g_system.pas', + g_touch in 'sdl/g_touch.pas', +{$ENDIF} +{$IFDEF USE_SDL2} + g_system in 'sdl2/g_system.pas', + g_touch in 'sdl2/g_touch.pas', +{$ENDIF} + SysUtils, {$IFDEF USE_FMOD} fmod in '../lib/FMOD/fmod.pas', diff --git a/src/game/g_basic.pas b/src/game/g_basic.pas index 01a27b0..22e318a 100644 --- a/src/game/g_basic.pas +++ b/src/game/g_basic.pas @@ -689,6 +689,7 @@ var b: array of string; str: string; begin +{ SetLength(Result, 0); SetLength(b, 0); @@ -715,7 +716,7 @@ begin if TextLen(str) > MaxWidth then begin // Òåêóùàÿ ñòðîêà ñëèøêîì äëèííàÿ => ðàçáèâàåì - while str <> '' do + while (str[0] <> #0) and (str <> '') do begin SetLength(Result, Length(Result)+1); @@ -741,6 +742,8 @@ begin Result[High(Result)] := str; end; end; +} + Result := nil end; procedure Sort(var a: SSArray); diff --git a/src/game/g_console.pas b/src/game/g_console.pas index b7c30de..7caa3ba 100644 --- a/src/game/g_console.pas +++ b/src/game/g_console.pas @@ -1416,7 +1416,7 @@ begin IK_END, IK_KPEND: CPos := Length(Line) + 1; IK_A..IK_Z, IK_SPACE, IK_SHIFT, IK_RSHIFT, IK_CAPSLOCK, IK_LBRACKET, IK_RBRACKET, - IK_SEMICOLON, IK_QUOTE, IK_BACKSLASH, IK_SLASH, IK_COMMA, IK_DOT, IK_EQUALS, + IK_SEMICOLON, IK_QUOTE, IK_BACKSLASH, IK_SLASH, IK_COMMA, IK_DOT, (*IK_EQUALS,*) IK_0, IK_1, IK_2, IK_3, IK_4, IK_5, IK_6, IK_7, IK_8, IK_9, IK_MINUS, IK_EQUALS: (* see TEXTINPUT event *) end diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 963496a..aa4c189 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -383,7 +383,7 @@ uses g_triggers, g_monsters, e_sound, CONFIG, g_language, g_net, ENet, e_msg, g_netmsg, g_netmaster, - sfs, wadreader; + sfs, wadreader, g_system; var @@ -894,7 +894,7 @@ begin gDelayedEvents[n].DENum := Num; gDelayedEvents[n].DEStr := Str; if DEType = DE_GLOBEVENT then - gDelayedEvents[n].Time := (GetTimer() {div 1000}) + Time + gDelayedEvents[n].Time := (sys_GetTicks() {div 1000}) + Time else gDelayedEvents[n].Time := gTime + Time; Result := n; @@ -2187,7 +2187,7 @@ begin KeyPress(IK_F10); end; - Time := GetTimer() {div 1000}; + Time := sys_GetTicks() {div 1000}; // Îáðàáîòêà îòëîæåííûõ ñîáûòèé: if gDelayedEvents <> nil then @@ -2543,7 +2543,7 @@ var begin e_TextureFontGetSize(gStdFont, ww2, hh2); - g_ProcessMessages(); + sys_HandleInput; if g_Console_Action(ACTION_SCORES) then begin @@ -3732,7 +3732,7 @@ var begin if gExit = EXIT_QUIT then Exit; - Time := GetTimer() {div 1000}; + Time := sys_GetTicks() {div 1000}; FPSCounter := FPSCounter+1; if Time - FPSTime >= 1000 then begin @@ -4098,7 +4098,7 @@ begin g_Game_DeleteTestMap(); gExit := EXIT_QUIT; - PushExitEvent(); + sys_RequestQuit; end; procedure g_FatalError(Text: String); @@ -4156,7 +4156,7 @@ end; procedure g_Game_ChangeResolution(newWidth, newHeight: Word; nowFull, nowMax: Boolean); begin - g_Window_SetSize(newWidth, newHeight, nowFull); + sys_SetDisplayMode(newWidth, newHeight, gBPP, nowFull); end; procedure g_Game_AddPlayer(Team: Byte = TEAM_NONE); diff --git a/src/game/g_main.pas b/src/game/g_main.pas index 3b84f30..d60f2dd 100644 --- a/src/game/g_main.pas +++ b/src/game/g_main.pas @@ -40,11 +40,14 @@ uses {$IFDEF ENABLE_HOLMES} g_holmes, fui_wadread, fui_style, fui_gfx_gl, {$ENDIF} - SDL2, wadreader, e_log, g_window, +{$IFDEF USE_SDL2} + SDL2, +{$ENDIF} + wadreader, e_log, g_window, e_graphics, e_input, g_game, g_console, g_gui, e_sound, g_options, g_sound, g_player, g_basic, g_weapons, SysUtils, g_triggers, MAPDEF, g_map, - g_menu, g_language, g_net, g_touch, g_res_downloader, + g_menu, g_language, g_net, g_touch, g_system, g_res_downloader, utils, conbuf, envvars, xparser; @@ -84,6 +87,7 @@ begin {$ENDIF} e_WriteToStdOut := False; //{$IFDEF HEADLESS}True;{$ELSE}False;{$ENDIF} +{$IFDEF USE_SDL2} {$IFDEF HEADLESS} {$IFDEF USE_SDLMIXER} sdlflags := SDL_INIT_TIMER or SDL_INIT_AUDIO or $00004000; @@ -105,6 +109,7 @@ begin if SDL_Init(sdlflags) < 0 then raise Exception.Create('SDL: Init failed: ' + SDL_GetError()); +{$ENDIF} e_WriteLog('Read config file', TMsgType.Notify); g_Options_Read(GameDir + '/' + CONFIG_FILENAME); @@ -116,6 +121,10 @@ begin e_WriteLog(gLanguage, TMsgType.Notify); g_Language_Set(gLanguage); +{$IFNDEF USE_SDL2} + sys_Init; +{$ENDIF} + {$IF not DEFINED(HEADLESS) and DEFINED(ENABLE_HOLMES)} flexloaded := true; if not fuiAddWad('flexui.wad') then @@ -169,8 +178,12 @@ begin SDLMain(); {$WARNINGS ON} +{$IFDEF USE_SDL2} e_WriteLog('Releasing SDL', TMsgType.Notify); SDL_Quit(); +{$ELSE} + sys_Final; +{$ENDIF} end; procedure Init(); diff --git a/src/game/g_menu.pas b/src/game/g_menu.pas index 4d2da49..3ffef26 100644 --- a/src/game/g_menu.pas +++ b/src/game/g_menu.pas @@ -45,11 +45,11 @@ uses {$INCLUDE ../nogl/noGLuses.inc} g_gui, g_textures, e_graphics, g_main, g_window, g_game, g_map, g_basic, g_console, g_sound, g_gfx, g_player, g_options, g_weapons, - e_log, SysUtils, CONFIG, g_playermodel, DateUtils, sdl2, + e_log, SysUtils, CONFIG, g_playermodel, DateUtils, MAPDEF, Math, g_saveload, e_texture, g_language, g_net, g_netmsg, g_netmaster, g_items, e_input, g_touch, - utils, wadreader; + utils, wadreader, g_system; type TYNCallback = procedure (yes:Boolean); @@ -118,7 +118,8 @@ begin ovs := gVSync; gVSync := TGUISwitch(menu.GetControl('swVSync')).ItemIndex = 0; - if (ovs <> gVSync) then g_SetVSync(gVSync); + if (ovs <> gVSync) then + sys_EnableVSync(gVSync); gTextureFilter := TGUISwitch(menu.GetControl('swTextureFilter')).ItemIndex = 0; glLegacyNPOT := not (TGUISwitch(menu.GetControl('swLegacyNPOT')).ItemIndex = 0); @@ -818,7 +819,7 @@ begin slWaitStr := _lc[I_NET_SLIST_WAIT]; g_Game_Draw; - ReDrawWindow; + sys_Repaint; slReturnPressed := True; if g_Net_Slist_Fetch(slCurrent) then @@ -1824,7 +1825,6 @@ procedure ProcVideoOptionsRes(); var menu: TGUIMenu; list: SSArray; - SR: DWORD; begin menu := TGUIMenu(g_GUI_GetWindow('OptionsVideoResMenu').GetControl('mOptionsVideoResMenu')); @@ -1835,15 +1835,16 @@ begin with TGUIListBox(menu.GetControl('lsResolution')) do begin - list := GetDisplayModes(gBPP, SR); - + list := sys_GetDispalyModes(gBPP); if list <> nil then - begin - Items := list; - ItemIndex := SR; - end + begin + Items := list; + ItemIndex := Length(list) + end else - Clear(); + begin + Clear + end end; with TGUISwitch(menu.GetControl('swFullScreen')) do diff --git a/src/game/g_net.pas b/src/game/g_net.pas index 63b1270..eaf35fa 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -250,7 +250,7 @@ implementation uses SysUtils, e_input, g_nethandler, g_netmsg, g_netmaster, g_player, g_window, g_console, - g_main, g_game, g_language, g_weapons, utils, ctypes, + g_main, g_game, g_language, g_weapons, utils, ctypes, g_system, g_map; const @@ -1899,7 +1899,7 @@ begin end; // предупредить что ждем слишком долго через N секунд - TimeoutTime := GetTimer() + NET_CONNECT_TIMEOUT; + TimeoutTime := sys_GetTicks() + NET_CONNECT_TIMEOUT; OuterLoop := True; while OuterLoop do @@ -1920,7 +1920,7 @@ begin end; end; - T := GetTimer(); + T := sys_GetTicks(); if T > TimeoutTime then begin TimeoutTime := T + NET_CONNECT_TIMEOUT * 100; // одного предупреждения хватит diff --git a/src/game/g_netmaster.pas b/src/game/g_netmaster.pas index 01d5d67..2ecad14 100644 --- a/src/game/g_netmaster.pas +++ b/src/game/g_netmaster.pas @@ -86,7 +86,7 @@ implementation uses SysUtils, e_msg, e_input, e_graphics, e_log, g_window, g_net, g_console, g_map, g_game, g_sound, g_gui, g_menu, g_options, g_language, g_basic, - wadreader; + wadreader, g_system; var NetMHost: pENetHost = nil; @@ -105,7 +105,7 @@ var function GetTimerMS (): Int64; begin - Result := GetTimer() {div 1000}; + Result := sys_GetTicks() {div 1000}; end; @@ -876,7 +876,7 @@ begin if gConsoleShow or gChatShow then Exit; - qm := g_ProcessMessages(); // this updates kbd + qm := sys_HandleInput(); // this updates kbd if qm or e_KeyPressed(IK_ESCAPE) or e_KeyPressed(VK_ESCAPE) or e_KeyPressed(JOY0_JUMP) or e_KeyPressed(JOY1_JUMP) or @@ -909,7 +909,7 @@ begin slWaitStr := _lc[I_NET_SLIST_WAIT]; g_Game_Draw; - g_window.ReDrawWindow; + sys_Repaint; if g_Net_Slist_Fetch(SL) then begin diff --git a/src/game/g_options.pas b/src/game/g_options.pas index 979fe45..ac80a1b 100644 --- a/src/game/g_options.pas +++ b/src/game/g_options.pas @@ -96,9 +96,12 @@ implementation uses {$INCLUDE ../nogl/noGLuses.inc} + {$IFDEF USE_SDL2} + SDL2, + {$ENDIF} e_log, e_input, g_console, g_window, g_sound, g_gfx, g_player, Math, g_map, g_net, g_netmaster, SysUtils, CONFIG, g_game, g_main, e_texture, - g_items, wadreader, e_graphics, g_touch, SDL2, envvars; + g_items, wadreader, e_graphics, g_touch, envvars; var machine: Integer; @@ -115,6 +118,7 @@ uses Result := Copy(Result, 1, 10) + ' ' + IntToStr(n) end; +{$IFDEF USE_SDL2} procedure g_Options_SetDefaultVideo; var target, closest, display: TSDL_DisplayMode; @@ -165,6 +169,24 @@ begin e_LogWriteLn('g_Options_SetDefaultVideo: w = ' + IntToStr(gScreenWidth) + ' h = ' + IntToStr(gScreenHeight)); g_Console_ResetBinds; end; +{$ELSE} +procedure g_Options_SetDefaultVideo; +begin + {$WARNING stub} + gScreenWidth := 640; + gScreenHeight := 480; + gBPP := 32; + gFullScreen := False; + gWinRealPosX := 0; + gWinRealPosY := 0; + gWinMaximized := False; + gVSync := True; + gTextureFilter := True; + glLegacyNPOT := False; + e_LogWriteLn('g_Options_SetDefaultVideo: w = ' + IntToStr(gScreenWidth) + ' h = ' + IntToStr(gScreenHeight)); + g_Console_ResetBinds; +end; +{$ENDIF} procedure g_Options_SetDefault(); var diff --git a/src/game/g_touch.pas b/src/game/g_touch.pas deleted file mode 100644 index a35a56e..0000000 --- a/src/game/g_touch.pas +++ /dev/null @@ -1,324 +0,0 @@ -(* Copyright (C) Doom 2D: Forever Developers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License ONLY. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *) -{$INCLUDE ../shared/a_modes.inc} -unit g_touch; - -interface - - uses - SDL2; - - var - g_touch_enabled: Boolean = False; - g_touch_size: Single = 1.0; - g_touch_offset: Single = 50.0; - g_touch_fire: Boolean = True; - g_touch_alt: Boolean = False; - - procedure g_Touch_Init; - procedure g_Touch_ShowKeyboard(yes: Boolean); - procedure g_Touch_HandleEvent(const ev: TSDL_TouchFingerEvent); - procedure g_Touch_Draw; - -implementation - - uses - SysUtils, - e_log, e_graphics, e_input, g_options, g_game, g_main, g_gui, g_weapons, g_console, g_window; - - var - angleFire: Boolean; - keyFinger: array [VK_FIRSTKEY..VK_LASTKEY] of Integer; - - procedure GetKeyRect(key: Integer; out x, y, w, h: Integer; out founded: Boolean); - var - sw, sh, sz: Integer; - dpi: Single; - - procedure S (xx, yy, ww, hh: Single); - begin - x := Trunc(xx); - y := Trunc(yy); - w := Trunc(ww); - h := Trunc(hh); - founded := true; - end; - - begin - founded := false; - if SDL_GetDisplayDPI(0, @dpi, nil, nil) <> 0 then - dpi := 96; - - sz := Trunc(g_touch_size * dpi); sw := gScreenWidth; sh := gScreenHeight; - x := 0; y := Round(sh * g_touch_offset / 100); - w := sz; h := sz; - - if SDL_IsTextInputActive() = SDL_True then - case key of - VK_HIDEKBD: S(sw - (sz/2), 0, sz / 2, sz / 2); - end - else if g_touch_alt then - case key of - (* top ------- x ------------------------------- y w ----- h -- *) - VK_CONSOLE: S(0, 0, sz / 2, sz / 2); - VK_ESCAPE: S(sw - 1*(sz/2) - 1, 0, sz / 2, sz / 2); - VK_SHOWKBD: S(sw - 2*(sz/2) - 1, 0, sz / 2, sz / 2); - VK_CHAT: S(sw / 2 - (sz/2) / 2 - (sz/2) - 1, 0, sz / 2, sz / 2); - VK_STATUS: S(sw / 2 - (sz/2) / 2 - 1, 0, sz / 2, sz / 2); - VK_TEAM: S(sw / 2 - (sz/2) / 2 + (sz/2) - 1, 0, sz / 2, sz / 2); - (* left --- x - y -------------- w - h --- *) - VK_PREV: S(0, sh - 3.0*sz - 1, sz, sz / 2); - VK_LEFT: S(0, sh - 2.0*sz - 1, sz, sz * 2); - VK_RIGHT: S(sz, sh - 2.0*sz - 1, sz, sz * 2); - (* right - x ------------ y -------------- w - h -- *) - VK_NEXT: S(sw - 1*sz - 1, sh - 3.0*sz - 1, sz, sz / 2); - VK_UP: S(sw - 2*sz - 1, sh - 2.0*sz - 1, sz, sz / 2); - VK_FIRE: S(sw - 2*sz - 1, sh - 1.5*sz - 1, sz, sz); - VK_DOWN: S(sw - 2*sz - 1, sh - 0.5*sz - 1, sz, sz / 2); - VK_JUMP: S(sw - 1*sz - 1, sh - 2.0*sz - 1, sz, sz); - VK_OPEN: S(sw - 1*sz - 1, sh - 1.0*sz - 1, sz, sz); - end - else - case key of - (* left ----- x ----- y -------------- w ----- h -- *) - VK_ESCAPE: S(0.0*sz, y - 1*sz - sz/2, sz, sz / 2); - VK_LSTRAFE: S(0.0*sz, y - 0*sz - sz/2, sz / 2, sz); - VK_LEFT: S(0.5*sz, y - 0*sz - sz/2, sz, sz); - VK_RIGHT: S(1.5*sz, y - 0*sz - sz/2, sz, sz); - VK_RSTRAFE: S(2.5*sz, y - 0*sz - sz/2, sz / 2, sz); - (* right - x ------------ y --------------- w - h *) - VK_UP: S(sw - 1*sz - 1, y - 1*sz - sz/2, sz, sz); - VK_FIRE: S(sw - 1*sz - 1, y - 0*sz - sz/2, sz, sz); - VK_DOWN: S(sw - 1*sz - 1, y - -1*sz - sz/2, sz, sz); - VK_NEXT: S(sw - 2*sz - 1, y - 1*sz - sz/2, sz, sz); - VK_JUMP: S(sw - 2*sz - 1, y - 0*sz - sz/2, sz, sz); - VK_PREV: S(sw - 3*sz - 1, y - 1*sz - sz/2, sz, sz); - VK_OPEN: S(sw - 3*sz - 1, y - 0*sz - sz/2, sz, sz); - (* bottom ---- x -------------------------- y ---------------- w ----- h -- *) - VK_CHAT: S(sw/2 - sz/4 - 2*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2); - VK_CONSOLE: S(sw/2 - sz/4 - 1*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2); - VK_STATUS: S(sw/2 - sz/4 - 0*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2); - VK_TEAM: S(sw/2 - sz/4 - -1*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2); - VK_SHOWKBD: S(sw/2 - sz/4 - -2*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2); - VK_0: S(sw/2 - sz/4 - 5*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_1: S(sw/2 - sz/4 - 4*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_2: S(sw/2 - sz/4 - 3*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_3: S(sw/2 - sz/4 - 2*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_4: S(sw/2 - sz/4 - 1*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_5: S(sw/2 - sz/4 - 0*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_6: S(sw/2 - sz/4 - -1*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_7: S(sw/2 - sz/4 - -2*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_8: S(sw/2 - sz/4 - -3*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_9: S(sw/2 - sz/4 - -4*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - VK_A: S(sw/2 - sz/4 - -5*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2); - end - end; - - function GetKeyName(key: Integer): String; - begin - case key of - VK_SHOWKBD: result := 'KBD'; - VK_HIDEKBD: result := 'KBD'; - VK_LEFT: result := 'LEFT'; - VK_RIGHT: result := 'RIGHT'; - VK_UP: result := 'UP'; - VK_DOWN: result := 'DOWN'; - VK_FIRE: result := 'FIRE'; - VK_OPEN: result := 'OPEN'; - VK_JUMP: result := 'JUMP'; - VK_CHAT: result := 'CHAT'; - VK_ESCAPE: result := 'ESC'; - VK_0: result := '0'; - VK_1: result := '1'; - VK_2: result := '2'; - VK_3: result := '3'; - VK_4: result := '4'; - VK_5: result := '5'; - VK_6: result := '6'; - VK_7: result := '7'; - VK_8: result := '8'; - VK_9: result := '9'; - VK_A: result := '10'; - VK_B: result := '11'; - VK_C: result := '12'; - VK_D: result := '13'; - VK_E: result := '14'; - VK_F: result := '15'; - VK_CONSOLE: result := 'CON'; - VK_STATUS: result := 'STAT'; - VK_TEAM: result := 'TEAM'; - VK_PREV: result := ' 0) and (key < e_MaxInputKeys) then - result := e_KeyNames[key] - else - result := '<' + IntToStr(key) + '>' - end - end; - - function IntersectControl(ctl, xx, yy: Integer): Boolean; - var - x, y, w, h: Integer; - founded: Boolean; - begin - GetKeyRect(ctl, x, y, w, h, founded); - result := founded and (xx >= x) and (yy >= y) and (xx <= x + w) and (yy <= y + h); - end; - - procedure g_Touch_Init; - begin -{$IFNDEF HEADLESS} - g_Touch_ShowKeyboard(FALSE); - g_touch_enabled := SDL_GetNumTouchDevices() > 0 -{$ENDIF} - end; - - procedure g_Touch_ShowKeyboard(yes: Boolean); - begin -{$IFNDEF HEADLESS} - if g_dbg_input then - e_LogWritefln('g_Touch_ShowKeyboard(%s)', [yes]); - (* on desktop we always receive text (needed for cheats) *) - if yes or (SDL_HasScreenKeyboardSupport() = SDL_FALSE) then - SDL_StartTextInput - else - SDL_StopTextInput -{$ENDIF} - end; - - procedure g_Touch_HandleEvent(const ev: TSDL_TouchFingerEvent); - var - x, y, i, finger: Integer; - - procedure KeyUp (finger, i: Integer); - begin - if g_dbg_input then - e_LogWritefln('Input Debug: g_touch.KeyUp, finger=%s, key=%s', [finger, i]); - - keyFinger[i] := 0; - e_KeyUpDown(i, False); - g_Console_ProcessBind(i, False); - - (* up/down + fire hack *) - if g_touch_fire and (gGameSettings.GameType <> GT_NONE) and (g_ActiveWindow = nil) and angleFire then - begin - if (i = VK_UP) or (i = VK_DOWN) then - begin - angleFire := False; - keyFinger[VK_FIRE] := 0; - e_KeyUpDown(VK_FIRE, False); - g_Console_ProcessBind(VK_FIRE, False) - end - end - end; - - procedure KeyDown (finger, i: Integer); - begin - if g_dbg_input then - e_LogWritefln('Input Debug: g_touch.KeyDown, finger=%s, key=%s', [finger, i]); - - keyFinger[i] := finger; - e_KeyUpDown(i, True); - g_Console_ProcessBind(i, True); - - (* up/down + fire hack *) - if g_touch_fire and (gGameSettings.GameType <> GT_NONE) and (g_ActiveWindow = nil) then - begin - if i = VK_UP then - begin - angleFire := True; - keyFinger[VK_FIRE] := -1; - e_KeyUpDown(VK_FIRE, True); - g_Console_ProcessBind(VK_FIRE, True) - end - else if i = VK_DOWN then - begin - angleFire := True; - keyFinger[VK_FIRE] := -1; - e_KeyUpDown(VK_FIRE, True); - g_Console_ProcessBind(VK_FIRE, True) - end - end - end; - - procedure KeyMotion (finger, i: Integer); - begin - if keyFinger[i] <> finger then - begin - KeyUp(finger, i); - KeyDown(finger, i) - end - end; - - begin - if not g_touch_enabled then - Exit; - - finger := ev.fingerId + 2; - x := Trunc(ev.x * gScreenWidth); - y := Trunc(ev.y * gScreenHeight); - - for i := VK_FIRSTKEY to VK_LASTKEY do - begin - if IntersectControl(i, x, y) then - begin - if ev.type_ = SDL_FINGERUP then - KeyUp(finger, i) - else if ev.type_ = SDL_FINGERMOTION then - KeyMotion(finger, i) - else if ev.type_ = SDL_FINGERDOWN then - keyDown(finger, i) - end - else if keyFinger[i] = finger then - begin - if ev.type_ = SDL_FINGERUP then - KeyUp(finger, i) - else if ev.type_ = SDL_FINGERMOTION then - KeyUp(finger, i) - end - end - end; - - procedure g_Touch_Draw; -{$IFNDEF HEADLESS} - var i, x, y, w, h: Integer; founded: Boolean; -{$ENDIF} - begin -{$IFNDEF HEADLESS} - if not g_touch_enabled then - Exit; - - for i := VK_FIRSTKEY to VK_LASTKEY do - begin - GetKeyRect(i, x, y, w, h, founded); - if founded then - begin - e_DrawQuad(x, y, x + w, y + h, 0, 255, 0, 31); - e_TextureFontPrintEx(x, y, GetKeyName(i), gStdFont, 255, 255, 255, 1, True) - end - end -{$ENDIF} - end; - -initialization - conRegVar('touch_enable', @g_touch_enabled, 'enable/disable virtual buttons', 'draw buttons'); - conRegVar('touch_fire', @g_touch_fire, 'enable/disable fire when press virtual up/down', 'fire when press up/down'); - conRegVar('touch_size', @g_touch_size, 0.1, 10, 'size of virtual buttons', 'button size'); - conRegVar('touch_offset', @g_touch_offset, 0, 100, '', ''); - conRegVar('touch_alt', @g_touch_alt, 'althernative virtual buttons layout', 'althernative layout'); -end. diff --git a/src/game/g_window.pas b/src/game/g_window.pas index 3adb2b6..f623e8a 100644 --- a/src/game/g_window.pas +++ b/src/game/g_window.pas @@ -21,24 +21,9 @@ uses utils; function SDLMain (): Integer; -function GetTimer (): Int64; procedure ResetTimer (); -procedure PushExitEvent (); -function ProcessMessage (): Boolean; -procedure ReDrawWindow (); -procedure SwapBuffers (); -procedure Sleep (ms: LongWord); -function GetDisplayModes (dbpp: LongWord; var selres: LongWord): SSArray; -function g_Window_SetDisplay (preserveGL: Boolean=false): Boolean; -function g_Window_SetSize (w, h: Word; fullscreen: Boolean): Boolean; -procedure g_SetVSync (vsync: Boolean); - procedure ProcessLoading (forceUpdate: Boolean=false); -// returns `true` if quit event was received -function g_ProcessMessages (): Boolean; - - var gwin_dump_extensions: Boolean = false; gwin_has_stencil: Boolean = false; @@ -46,742 +31,38 @@ var g_dbg_aimline_on: Boolean = false; g_dbg_input: Boolean = False; - implementation uses {$IFDEF WINDOWS}Windows,{$ENDIF} -{$INCLUDE ../nogl/noGLuses.inc} {$IFDEF ENABLE_HOLMES} g_holmes, sdlcarcass, fui_ctls, {$ENDIF} SysUtils, Classes, MAPDEF, Math, - SDL2, e_graphics, e_log, e_texture, g_main, + e_graphics, e_log, e_texture, g_main, g_console, e_input, g_options, g_game, g_basic, g_textures, e_sound, g_sound, g_menu, ENet, g_net, g_map, g_gfx, g_monsters, xprofiler, - g_touch, g_gui; + g_touch, g_gui, g_system; const ProgressUpdateMSecs = 35; //1;//100; var - h_Wnd: PSDL_Window = nil; - h_GL: TSDL_GLContext = nil; Time, Time_Delta, Time_Old: Int64; flag: Boolean; -{$IF not DEFINED(HEADLESS)} - wTitle: PChar = nil; - wasFullscreen: Boolean = true; // so we need to recreate the window -{$ENDIF} wNeedTimeReset: Boolean = false; wMinimized: Boolean = false; wMaximized: Boolean = false; wLoadingProgress: Boolean = false; wLoadingQuit: Boolean = false; -{$IFNDEF WINDOWS} - ticksOverflow: Int64 = -1; - lastTicks: Uint32 = 0; // to detect overflow -{$ENDIF} - JoystickHandle: array [0..e_MaxJoys - 1] of PSDL_Joystick; - JoystickHatState: array [0..e_MaxJoys - 1, 0..e_MaxJoyHats - 1, HAT_LEFT..HAT_DOWN] of Boolean; - JoystickZeroAxes: array [0..e_MaxJoys - 1, 0..e_MaxJoyAxes - 1] of Integer; - -procedure KillGLWindow (preserveGL: Boolean); -begin -{$IFDEF ENABLE_HOLMES} - if (h_GL <> nil) and (not preserveGL) then begin if (assigned(oglDeinitCB)) then oglDeinitCB(); end; -{$ENDIF} - if (h_Wnd <> nil) then SDL_DestroyWindow(h_Wnd); - if (h_GL <> nil) and (not preserveGL) then - begin - -{$IFDEF USE_NANOGL} - nanoGL_Destroy; -{$ENDIF} - -{$IFDEF USE_NOGL} - nogl_Quit; -{$ENDIF} - - SDL_GL_DeleteContext(h_GL); - end; - h_Wnd := nil; - if (not preserveGL) then h_GL := nil; -end; - - -function g_Window_SetDisplay (preserveGL: Boolean = false): Boolean; -{$IF not DEFINED(HEADLESS)} -var - mode, cmode: TSDL_DisplayMode; - wFlags: LongWord = 0; - nw, nh: Integer; -{$ENDIF} -begin -{$IF not DEFINED(HEADLESS)} - result := false; - - e_WriteLog('Setting display mode...', TMsgType.Notify); - - wFlags := SDL_WINDOW_OPENGL {or SDL_WINDOW_RESIZABLE}; - if gFullscreen then wFlags := wFlags {or SDL_WINDOW_FULLSCREEN} else wFlags := wFlags or SDL_WINDOW_RESIZABLE; - if (not gFullscreen) and (not preserveGL) and gWinMaximized then wFlags := wFlags or SDL_WINDOW_MAXIMIZED else gWinMaximized := false; - - if gFullscreen then - begin - mode.w := gScreenWidth; - mode.h := gScreenHeight; - mode.format := 0; - mode.refresh_rate := 0; - mode.driverdata := nil; - if (SDL_GetClosestDisplayMode(0, @mode, @cmode) = nil) then - begin - e_WriteLog('SDL: cannot find display mode for '+IntToStr(gScreenWidth), TMsgType.Notify); - gScreenWidth := 800; - gScreenHeight := 600; - end - else - begin - e_WriteLog('SDL: found display mode for '+IntToStr(gScreenWidth)+'x'+IntToStr(gScreenHeight)+': '+IntToStr(cmode.w)+'x'+IntToStr(cmode.h), TMsgType.Notify); - gScreenWidth := cmode.w; - gScreenHeight := cmode.h; - end; - end; - - if (preserveGL) and (h_Wnd <> nil) and (not gFullscreen) and (not wasFullscreen) then - begin - //SDL_SetWindowMaximumSize(h_Wnd, gScreenWidth, gScreenHeight); - //SDL_SetWindowDisplayMode(h_Wnd, @cmode); - if (wMaximized) then SDL_RestoreWindow(h_Wnd); - wMaximized := false; - gWinMaximized := false; - SDL_SetWindowSize(h_Wnd, gScreenWidth, gScreenHeight); - //SDL_SetWindowFullscreen(h_Wnd, SDL_WINDOW_FULLSCREEN); - //SDL_SetWindowFullscreen(h_Wnd, 0); - end - else - begin - KillGLWindow(preserveGL); - h_Wnd := SDL_CreateWindow(PChar(wTitle), gWinRealPosX, gWinRealPosY, gScreenWidth, gScreenHeight, wFlags); - if gFullscreen then - SDL_SetWindowFullscreen(h_Wnd, SDL_WINDOW_FULLSCREEN); - if (h_Wnd = nil) then exit; - end; - wasFullscreen := gFullscreen; - - SDL_GL_MakeCurrent(h_Wnd, h_GL); - SDL_ShowCursor(SDL_DISABLE); - if (h_GL <> nil) then g_SetVSync(gVSync); - if (gFullscreen) then - begin - nw := 0; - nh := 0; - SDL_GetWindowSize(h_Wnd, @nw, @nh); - if (nw > 128) and (nh > 128) then - begin - e_WriteLog('SDL: fullscreen window got size '+IntToStr(nw)+'x'+IntToStr(nh)+': '+IntToStr(gScreenWidth)+'x'+IntToStr(gScreenHeight), TMsgType.Notify); - gScreenWidth := nw; - gScreenHeight := nh; - end - else - begin - e_WriteLog('SDL: fullscreen window got invalid size: '+IntToStr(nw)+'x'+IntToStr(nh), TMsgType.Notify); - end; - end; - - {$IFDEF ENABLE_HOLMES} - fuiScrWdt := gScreenWidth; - fuiScrHgt := gScreenHeight; - if (h_GL <> nil) and (not preserveGL) then begin if (assigned(oglInitCB)) then oglInitCB(); end; - {$ENDIF} -{$ENDIF} - - result := true; -end; - - -function GetDisplayModes (dbpp: LongWord; var selres: LongWord): SSArray; -var - mode: TSDL_DisplayMode; - res, i, k, n, pw, ph: Integer; -begin - SetLength(result, 0); - {$IFDEF HEADLESS}exit;{$ENDIF} - k := 0; selres := 0; - n := SDL_GetNumDisplayModes(0); - pw := 0; ph := 0; - for i := 0 to n do - begin - res := SDL_GetDisplayMode(0, i, @mode); - if res < 0 then continue; - if SDL_BITSPERPIXEL(mode.format) = gBPP then continue; - if (mode.w = pw) and (mode.h = ph) then continue; - if (mode.w = gScreenWidth) and (mode.h = gScreenHeight) then - selres := k; - Inc(k); - SetLength(result, k); - result[k-1] := IntToStr(mode.w) + 'x' + IntToStr(mode.h); - pw := mode.w; ph := mode.h - end; - - e_WriteLog('SDL: Got ' + IntToStr(k) + ' resolutions.', TMsgType.Notify); -end; - - -procedure Sleep (ms: LongWord); -begin - SDL_Delay(ms); -end; - - -procedure ChangeWindowSize (requested: Boolean); -begin - e_LogWritefln(' ChangeWindowSize: (ws=%dx%d) (ss=%dx%d)', [gWinSizeX, gWinSizeY, gScreenWidth, gScreenHeight]); - gWinSizeX := gScreenWidth; - gWinSizeY := gScreenHeight; -{$IF not DEFINED(HEADLESS)} - {$IFDEF ENABLE_HOLMES} - fuiScrWdt := gScreenWidth; - fuiScrHgt := gScreenHeight; - {$ENDIF} - e_ResizeWindow(gScreenWidth, gScreenHeight); - g_Game_SetupScreenSize(); - {$IF DEFINED(ANDROID)} - (* This will fix menu reset on keyboard showing *) - if requested then - g_Menu_Reset; - {$ELSE} - g_Menu_Reset; - {$ENDIF} - g_Game_ClearLoading(); -{$ENDIF} -end; - - -function g_Window_SetSize (w, h: Word; fullscreen: Boolean): Boolean; -{$IF not DEFINED(HEADLESS)} -var - preserve: Boolean; -{$ENDIF} -begin - result := false; -{$IF not DEFINED(HEADLESS)} - preserve := false; - - if (gScreenWidth <> w) or (gScreenHeight <> h) then - begin - result := true; - preserve := true; - gScreenWidth := w; - gScreenHeight := h; - end; - - if (gFullscreen <> fullscreen) then - begin - result := true; - preserve := true; - gFullscreen := fullscreen; - preserve := true; - end; - - if result then - begin - g_Window_SetDisplay(preserve); - ChangeWindowSize(true); - end; -{$ENDIF} -end; - - -function WindowEventHandler (constref ev: TSDL_WindowEvent): Boolean; -var - wActivate, wDeactivate: Boolean; -begin - result := false; - wActivate := false; - wDeactivate := false; - - case ev.event of - SDL_WINDOWEVENT_MOVED: - begin - if not (gFullscreen or gWinMaximized) then - begin - gWinRealPosX := ev.data1; - gWinRealPosY := ev.data2; - end; - end; - - SDL_WINDOWEVENT_MINIMIZED: - begin - e_UnpressAllKeys(); - if not wMinimized then - begin - e_ResizeWindow(0, 0); - wMinimized := true; - if g_debug_WinMsgs then - begin - g_Console_Add('Now minimized'); - e_WriteLog('[DEBUG] WinMsgs: Now minimized', TMsgType.Notify); - end; - wDeactivate := true; - end; - end; - - SDL_WINDOWEVENT_RESIZED: - begin - e_LogWritefln('Resize: (os=%dx%d) (ns=%dx%d)', [gScreenWidth, gScreenHeight, Integer(ev.data1), Integer(ev.data2)]); - {if (gFullscreen) then - begin - e_LogWriteln(' fullscreen fix applied.'); - if (gScreenWidth <> ev.data1) or (gScreenHeight <> ev.data2) then - begin - SDL_SetWindowSize(h_Wnd, gScreenWidth, gScreenHeight); - end; - end - else} - begin - gScreenWidth := ev.data1; - gScreenHeight := ev.data2; - end; - ChangeWindowSize(false); - SwapBuffers(); - if g_debug_WinMsgs then - begin - g_Console_Add('Resized to ' + IntToStr(ev.data1) + 'x' + IntToStr(ev.data2)); - e_WriteLog('[DEBUG] WinMsgs: Resized to ' + IntToStr(ev.data1) + 'x' + IntToStr(ev.data2), TMsgType.Notify); - end; - end; - - SDL_WINDOWEVENT_EXPOSED: - SwapBuffers(); - - SDL_WINDOWEVENT_MAXIMIZED: - begin - wMaximized := true; - if wMinimized then - begin - e_ResizeWindow(gScreenWidth, gScreenHeight); - wMinimized := false; - wActivate := true; - end; - if (not gWinMaximized) and (not gFullscreen) then - begin - gWinMaximized := true; - if g_debug_WinMsgs then - begin - g_Console_Add('Now maximized'); - e_WriteLog('[DEBUG] WinMsgs: Now maximized', TMsgType.Notify); - end; - end; - end; - - SDL_WINDOWEVENT_RESTORED: - begin - wMaximized := false; - if wMinimized then - begin - e_ResizeWindow(gScreenWidth, gScreenHeight); - wMinimized := false; - wActivate := true; - end; - gWinMaximized := false; - if g_debug_WinMsgs then - begin - g_Console_Add('Now restored'); - e_WriteLog('[DEBUG] WinMsgs: Now restored', TMsgType.Notify); - end; - end; - - SDL_WINDOWEVENT_FOCUS_GAINED: - begin - wActivate := true; - //e_WriteLog('window gained focus!', MSG_NOTIFY); - end; - - SDL_WINDOWEVENT_FOCUS_LOST: - begin - wDeactivate := true; - e_UnpressAllKeys(); - //e_WriteLog('window lost focus!', MSG_NOTIFY); - end; - end; - - if wDeactivate then - begin - if gWinActive then - begin - e_WriteLog('deactivating window', TMsgType.Notify); - e_UnpressAllKeys; - - if gMuteWhenInactive then - begin - //e_WriteLog('deactivating sounds', MSG_NOTIFY); - e_MuteChannels(true); - end; - - if g_debug_WinMsgs then - begin - g_Console_Add('Now inactive'); - e_WriteLog('[DEBUG] WinMsgs: Now inactive', TMsgType.Notify); - end; - - gWinActive := false; - - {$IFDEF ENABLE_HOLMES} - if assigned(winBlurCB) then winBlurCB(); - {$ENDIF} - end; - end - else if wActivate then - begin - if not gWinActive then - begin - //e_WriteLog('activating window', MSG_NOTIFY); - - if gMuteWhenInactive then - begin - //e_WriteLog('activating sounds', MSG_NOTIFY); - e_MuteChannels(false); - end; - - if g_debug_WinMsgs then - begin - g_Console_Add('Now active'); - e_WriteLog('[DEBUG] WinMsgs: Now active', TMsgType.Notify); - end; - - gWinActive := true; - - {$IFDEF ENABLE_HOLMES} - if assigned(winFocusCB) then winFocusCB(); - {$ENDIF} - end; - end; -end; - - -function EventHandler (var ev: TSDL_Event): Boolean; -var - key, keychr, minuskey: Word; - uc: UnicodeChar; - down: Boolean; - i: Integer; - hat: array [HAT_LEFT..HAT_DOWN] of Boolean; -begin - result := false; - - case ev.type_ of - SDL_WINDOWEVENT: - result := WindowEventHandler(ev.window); - - SDL_QUITEV: - begin - if (gExit <> EXIT_QUIT) then - begin - if not wLoadingProgress then - begin - g_Game_Free(); - g_Game_Quit(); - end - else - begin - wLoadingQuit := true; - end; - end; - result := true; - end; - - SDL_KEYDOWN, SDL_KEYUP: - begin - key := ev.key.keysym.scancode; - if key = SDL_SCANCODE_AC_BACK then - key := SDL_SCANCODE_ESCAPE; - down := (ev.type_ = SDL_KEYDOWN); - {$IF not DEFINED(HEADLESS) and DEFINED(ENABLE_HOLMES)} - if fuiOnSDLEvent(ev) then - begin - // event eaten, but... - if not down then e_KeyUpDown(key, false); - exit; - end; - {$ENDIF} - if ev.key._repeat = 0 then - begin - if g_dbg_input then - e_LogWritefln('Input Debug: keysym, press=%s, scancode=%s', [down, key]); - e_KeyUpDown(key, down); - g_Console_ProcessBind(key, down); - end - else if gConsoleShow or gChatShow or (g_ActiveWindow <> nil) then - begin - // key repeat in menus and shit - KeyPress(key); - end; - end; - - SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP: - if (ev.jbutton.which < e_MaxJoys) and (ev.jbutton.button < e_MaxJoyBtns) then - begin - key := e_JoyButtonToKey(ev.jbutton.which, ev.jbutton.button); - down := ev.type_ = SDL_JOYBUTTONDOWN; - if g_dbg_input then - e_LogWritefln('Input Debug: jbutton, joy=%s, button=%s, keycode=%s, press=%s', [ev.jbutton.which, ev.jbutton.button, key, down]); - e_KeyUpDown(key, down); - g_Console_ProcessBind(key, down); - end - else - begin - if g_dbg_input then - begin - down := ev.type_ = SDL_JOYBUTTONDOWN; - e_LogWritefln('Input Debug: NOT IN RANGE! jbutton, joy=%s, button=%s, press=%s', [ev.jbutton.which, ev.jbutton.button, down]) - end - end; - - SDL_JOYAXISMOTION: - if (ev.jaxis.which < e_MaxJoys) and (ev.jaxis.axis < e_MaxJoyAxes) then - begin - key := e_JoyAxisToKey(ev.jaxis.which, ev.jaxis.axis, AX_PLUS); - minuskey := e_JoyAxisToKey(ev.jaxis.which, ev.jaxis.axis, AX_MINUS); - - if g_dbg_input then - e_LogWritefln('Input Debug: jaxis, joy=%s, axis=%s, value=%s, zeroaxes=%s, deadzone=%s', [ev.jaxis.which, ev.jaxis.axis, ev.jaxis.value, JoystickZeroAxes[ev.jaxis.which, ev.jaxis.axis], e_JoystickDeadzones[ev.jaxis.which]]); - - if ev.jaxis.value < JoystickZeroAxes[ev.jaxis.which, ev.jaxis.axis] - e_JoystickDeadzones[ev.jaxis.which] then - begin - if (e_KeyPressed(key)) then - begin - e_KeyUpDown(key, False); - g_Console_ProcessBind(key, False); - end; - e_KeyUpDown(minuskey, True); - g_Console_ProcessBind(minuskey, True); - end - else if ev.jaxis.value > JoystickZeroAxes[ev.jaxis.which, ev.jaxis.axis] + e_JoystickDeadzones[ev.jaxis.which] then - begin - if (e_KeyPressed(minuskey)) then - begin - e_KeyUpDown(minuskey, False); - g_Console_ProcessBind(minuskey, False); - end; - e_KeyUpDown(key, True); - g_Console_ProcessBind(key, True); - end - else - begin - if (e_KeyPressed(minuskey)) then - begin - e_KeyUpDown(minuskey, False); - g_Console_ProcessBind(minuskey, False); - end; - if (e_KeyPressed(key)) then - begin - e_KeyUpDown(key, False); - g_Console_ProcessBind(key, False); - end; - end; - end - else - begin - if g_dbg_input then - e_LogWritefln('Input Debug: NOT IN RANGE! jaxis, joy=%s, axis=%s, value=%s, zeroaxes=%s, deadzone=%s', [ev.jaxis.which, ev.jaxis.axis, ev.jaxis.value, JoystickZeroAxes[ev.jaxis.which, ev.jaxis.axis], e_JoystickDeadzones[ev.jaxis.which]]) - end; - - SDL_JOYHATMOTION: - if (ev.jhat.which < e_MaxJoys) and (ev.jhat.hat < e_MaxJoyHats) then - begin - if g_dbg_input then - e_LogWritefln('Input Debug: jhat, joy=%s, hat=%s, value=%s', [ev.jhat.which, ev.jhat.hat, ev.jhat.value]); - hat[HAT_UP] := LongBool(ev.jhat.value and SDL_HAT_UP); - hat[HAT_DOWN] := LongBool(ev.jhat.value and SDL_HAT_DOWN); - hat[HAT_LEFT] := LongBool(ev.jhat.value and SDL_HAT_LEFT); - hat[HAT_RIGHT] := LongBool(ev.jhat.value and SDL_HAT_RIGHT); - for i := HAT_LEFT to HAT_DOWN do - begin - if JoystickHatState[ev.jhat.which, ev.jhat.hat, i] <> hat[i] then - begin - down := hat[i]; - key := e_JoyHatToKey(ev.jhat.which, ev.jhat.hat, i); - e_KeyUpDown(key, down); - g_Console_ProcessBind(key, down); - end - end; - JoystickHatState[ev.jhat.which, ev.jhat.hat] := hat - end - else - begin - if g_dbg_input then - e_LogWritefln('Input Debug: NOT IN RANGE! jhat, joy=%s, hat=%s, value=%s', [ev.jhat.which, ev.jhat.hat, ev.jhat.value]) - end; - - SDL_JOYDEVICEADDED: - if (ev.jdevice.which < e_MaxJoys) then - begin - JoystickHandle[ev.jdevice.which] := SDL_JoystickOpen(ev.jdevice.which); - if JoystickHandle[ev.jdevice.which] <> nil then - begin - e_LogWritefln('Added Joystick %s', [ev.jdevice.which]); - e_JoystickAvailable[ev.jdevice.which] := True; - for i := 0 to Min(SDL_JoystickNumAxes(JoystickHandle[ev.jdevice.which]), e_MaxJoyAxes) - 1 do - JoystickZeroAxes[ev.jdevice.which, i] := SDL_JoystickGetAxis(JoystickHandle[ev.jdevice.which], i) - end - else - e_LogWritefln('Warning! Failed to open Joystick %s', [ev.jdevice.which]) - end - else - begin - e_LogWritefln('Warning! Added Joystick %s, but we support only <= %s', [ev.jdevice.which, e_MaxJoys]) - end; - - SDL_JOYDEVICEREMOVED: - begin - e_LogWritefln('Removed Joystick %s', [ev.jdevice.which]); - if (ev.jdevice.which < e_MaxJoys) then - begin - e_JoystickAvailable[ev.jdevice.which] := False; - if JoystickHandle[ev.jdevice.which] <> nil then - SDL_JoystickClose(JoystickHandle[ev.jdevice.which]); - JoystickHandle[ev.jdevice.which] := nil - end - end; - - {$IF not DEFINED(HEADLESS) and DEFINED(ENABLE_HOLMES)} - SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP, SDL_MOUSEWHEEL, SDL_MOUSEMOTION: - fuiOnSDLEvent(ev); - {$ENDIF} - - SDL_TEXTINPUT: - begin - if g_dbg_input then - e_LogWritefln('Input Debug: text, text=%s', [ev.text.text]); - Utf8ToUnicode(@uc, PChar(ev.text.text), 1); - keychr := Word(uc); - if (keychr > 127) then keychr := Word(wchar2win(WideChar(keychr))); - if (keychr > 0) and (keychr <= 255) then CharPress(AnsiChar(keychr)); - end; - - SDL_FINGERMOTION, SDL_FINGERDOWN, SDL_FINGERUP: - g_Touch_HandleEvent(ev.tfinger); - - // other key presses and joysticks are handled in e_input - end; -end; - - -procedure SwapBuffers (); -begin - {$IF not DEFINED(HEADLESS)} - SDL_GL_SwapWindow(h_Wnd); - {$ENDIF} -end; - - -function CreateGLWindow (Title: PChar): Boolean; -begin - result := false; - - gWinSizeX := gScreenWidth; - gWinSizeY := gScreenHeight; - -{$IF not DEFINED(HEADLESS)} - wTitle := Title; -{$ENDIF} - e_WriteLog('Creating window', TMsgType.Notify); - - if not g_Window_SetDisplay() then - begin - KillGLWindow(false); - e_WriteLog('Window creation error (resolution not supported?)', TMsgType.Fatal); - exit; - end; - -{$IF not DEFINED(HEADLESS)} - h_GL := SDL_GL_CreateContext(h_Wnd); - if (h_GL = nil) then exit; - {$IFDEF ENABLE_HOLMES} - fuiScrWdt := gScreenWidth; - fuiScrHgt := gScreenHeight; - {$ENDIF} - SDL_GL_MakeCurrent(h_Wnd, h_GL); -{$IFDEF USE_NANOGL} - if nanoGL_Init() = 0 then - begin - KillGLWindow(false); - e_WriteLog('nanoGL initialization error', TMsgType.Fatal); - exit; - end; -{$ENDIF} -{$IFDEF USE_NOGL} - nogl_Init; -{$ENDIF} - {$IFDEF ENABLE_HOLMES} - if (assigned(oglInitCB)) then oglInitCB(); - {$ENDIF} - if (h_GL <> nil) then g_SetVSync(gVSync); -{$ENDIF} - - e_ResizeWindow(gScreenWidth, gScreenHeight); - e_InitGL(); - - result := true; -end; - - -{$IFDEF WINDOWS} -// windoze sux; in headless mode `GetTickCount()` (and SDL) returns shit -function GetTimer (): Int64; -var - F, C: Int64; -begin - QueryPerformanceFrequency(F); - QueryPerformanceCounter(C); - result := Round(C/F*1000{000}); -end; -{$ELSE} -function GetTimer (): Int64; -var - t: Uint32; - tt: Int64; -begin - t := SDL_GetTicks(); - if (ticksOverflow = -1) then - begin - ticksOverflow := 0; - lastTicks := t; - end - else - begin - if (lastTicks > t) then - begin - // overflow, increment overflow ;-) - ticksOverflow := ticksOverflow+(Int64($ffffffff)+Int64(1)); - tt := (Int64($ffffffff)+Int64(1))+Int64(t); - t := Uint32(tt-lastTicks); - end; - end; - lastTicks := t; - result := ticksOverflow+Int64(t); -end; -{$ENDIF} - procedure ResetTimer (); begin wNeedTimeReset := true; end; - -procedure PushExitEvent (); -var - ev: TSDL_Event; -begin - ev.type_ := SDL_QUITEV; - SDL_PushEvent(@ev); -end; - - {$IFNDEF HEADLESS} var prevLoadingUpdateTime: UInt64 = 0; @@ -789,26 +70,26 @@ var procedure ProcessLoading (forceUpdate: Boolean=false); var - ev: TSDL_Event; {$IFNDEF HEADLESS} +// ev: TSDL_Event; stt: UInt64; {$ENDIF} begin - FillChar(ev, sizeof(ev), 0); +// FillChar(ev, sizeof(ev), 0); wLoadingProgress := true; - while (SDL_PollEvent(@ev) > 0) do - begin - EventHandler(ev); - if (ev.type_ = SDL_QUITEV) then break; - end; +// while (SDL_PollEvent(@ev) > 0) do +// begin +// EventHandler(ev); +// if (ev.type_ = SDL_QUITEV) then break; +// end; //e_PollJoysticks(); - if (ev.type_ = SDL_QUITEV) or (gExit = EXIT_QUIT) then - begin - wLoadingProgress := false; - exit; - end; +// if (ev.type_ = SDL_QUITEV) or (gExit = EXIT_QUIT) then +// begin +// wLoadingProgress := false; +// exit; +// end; {$IFNDEF HEADLESS} if not wMinimized then @@ -826,7 +107,7 @@ begin DrawLoadingStat(); g_Console_Draw(True); - SwapBuffers(); + sys_Repaint; prevLoadingUpdateTime := getTimeMilli(); end; end; @@ -847,28 +128,13 @@ begin end; -function g_ProcessMessages (): Boolean; -var - ev: TSDL_Event; -begin - result := false; - FillChar(ev, SizeOf(ev), 0); - while (SDL_PollEvent(@ev) > 0) do - begin - result := EventHandler(ev); - if (ev.type_ = SDL_QUITEV) then exit; - end; - //e_PollJoysticks(); -end; - - function ProcessMessage (): Boolean; var i, t: Integer; begin - result := g_ProcessMessages(); + result := sys_HandleInput(); - Time := GetTimer(); + Time := sys_GetTicks(); Time_Delta := Time-Time_Old; flag := false; @@ -919,111 +185,21 @@ begin // Âðåìÿ ïðåäûäóùåãî îáíîâëåíèÿ if flag then begin - Time_Old := Time-(Time_Delta mod 28); + Time_Old := Time - (Time_Delta mod 28); if (not wMinimized) then begin - Draw(); - SwapBuffers(); - end; + Draw; + sys_Repaint + end end else begin - Sleep(1); // release time slice, so we won't eat 100% CPU + sys_Delay(1) // release time slice, so we won't eat 100% CPU end; e_SoundUpdate(); end; - -procedure ReDrawWindow (); -begin - SwapBuffers(); -end; - - -procedure g_SetVSync (vsync: Boolean); -{$IF not DEFINED(HEADLESS)} -var - v: Byte; -{$ENDIF} -begin -{$IF not DEFINED(HEADLESS)} - if vsync then v := 1 else v := 0; - if (SDL_GL_SetSwapInterval(v) <> 0) then - begin - e_WriteLog('oops; can''t change vsync option, restart required', TMsgType.Warning); - end - else - begin - if vsync then e_WriteLog('VSync: ON', TMsgType.Notify) else e_WriteLog('VSync: OFF', TMsgType.Notify); - end; -{$ENDIF} -end; - - -procedure InitOpenGL (); -begin -{$IF not DEFINED(HEADLESS)} - {$IFDEF USE_GLES1} - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - {$ELSE} - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); // lights; it is enough to have 1-bit stencil buffer for lighting, but... - {$ENDIF} -{$ENDIF} -end; - - -function glHasExtension (const name: AnsiString): Boolean; -var - exts: PChar; - i: Integer; - found: Boolean; - extName: ShortString; -begin - result := false; - if (Length(name) = 0) then exit; - exts := glGetString(GL_EXTENSIONS); - if (exts = nil) then exit; - while (exts[0] <> #0) and (exts[0] = ' ') do Inc(exts); - while (exts[0] <> #0) do - begin - if gwin_dump_extensions then - begin - i := 0; - while (exts[i] <> #0) and (exts[i] <> ' ') do Inc(i); - if i > 255 then - begin - e_WriteLog('FUUUUUUUUUUUUU', TMsgType.Warning); - end - else - begin - Move(exts^, extName[1], i); - extName[0] := Char(i); - e_WriteLog(Format('EXT: %s', [extName]), TMsgType.Notify); - end; - end; - found := true; - for i := 0 to length(name)-1 do - begin - if (exts[i] = #0) then begin found := false; break; end; - if (exts[i] <> name[i+1]) then begin found := false; break; end; - end; - if found and ((exts[Length(name)] = #0) or (exts[Length(name)] = ' ')) then begin result := true; exit; end; - while (exts[0] <> #0) and (exts[0] <> ' ') do Inc(exts); - while (exts[0] <> #0) and (exts[0] = ' ') do Inc(exts); - end; -end; - - function SDLMain (): Integer; var idx: Integer; @@ -1132,45 +308,8 @@ begin end; end; - e_WriteLog('Initializing OpenGL', TMsgType.Notify); - InitOpenGL(); - - e_WriteLog('Creating GL window', TMsgType.Notify); - if not CreateGLWindow(PChar(Format('Doom 2D: Forever %s', [GAME_VERSION]))) then - begin - result := 0; - e_WriteLog('Unable to create GL window: ' + SDL_GetError(), TMsgType.Fatal); - exit; - end; - - {EnumDisplayModes();} - -{$IFDEF HEADLESS} - //gwin_k8_enable_light_experiments := false; - gwin_has_stencil := false; - glLegacyNPOT := false; - gwin_dump_extensions := false; -{$ELSE} - SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, @ltmp); - e_LogWritefln('stencil buffer size: %s', [ltmp]); - gwin_has_stencil := (ltmp > 0); - - if glHasExtension('GL_ARB_texture_non_power_of_two') or - glHasExtension('GL_OES_texture_npot') then - begin - e_WriteLog('NPOT textures: YES', TMsgType.Notify); - glLegacyNPOT := false; - end - else - begin - e_WriteLog('NPOT textures: NO', TMsgType.Warning); - glLegacyNPOT := true; - end; - gwin_dump_extensions := false; -{$ENDIF} - - Init(); - Time_Old := GetTimer(); + Init; + Time_Old := sys_GetTicks(); // Êîìàíäíàÿ ñòðîêà if (ParamCount > 0) then g_Game_Process_Params(); @@ -1186,8 +325,6 @@ begin while not ProcessMessage() do begin end; Release(); - KillGLWindow(false); - result := 0; end; diff --git a/src/game/sdl/g_system.pas b/src/game/sdl/g_system.pas new file mode 100644 index 0000000..a72f658 --- /dev/null +++ b/src/game/sdl/g_system.pas @@ -0,0 +1,301 @@ +(* Copyright (C) Doom 2D: Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License ONLY. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE ../shared/a_modes.inc} +unit g_system; + +interface + + (* To fix: + * - Text input + * - Joystick support + * - Window resizing using SDL_VIDEORESIZE + *) + + uses Utils; + + (* --- Utils --- *) + function sys_GetTicks (): Int64; + procedure sys_Delay (ms: Integer); + + (* --- Graphics --- *) + function sys_GetDispalyModes (bpp: Integer): SSArray; + function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen: Boolean): Boolean; + procedure sys_EnableVSync (yes: Boolean); + procedure sys_Repaint; + + (* --- Input --- *) + function sys_HandleInput (): Boolean; + procedure sys_RequestQuit; + + (* --- Init --- *) + procedure sys_Init; + procedure sys_Final; + +implementation + + uses + SysUtils, SDL, GL, + e_log, e_graphics, e_input, + g_options, g_window, g_console, g_game, g_menu; + + var + screen: PSDL_Surface; + + (* --------- Utils --------- *) + + function sys_GetTicks (): Int64; + begin + Result := SDL_GetTicks() + end; + + procedure sys_Delay (ms: Integer); + begin + SDL_Delay(ms) + end; + + (* --------- Graphics --------- *) + + procedure UpdateSize (w, h: Integer); + begin + gWinSizeX := w; + gWinSizeY := h; + gWinRealPosX := 0; + gWinRealPosY := 0; + gScreenWidth := w; + gScreenHeight := h; + {$IFDEF ENABLE_HOLMES} + fuiScrWdt := w; + fuiScrHgt := h; + {$ENDIF} + e_ResizeWindow(w, h); + e_InitGL; + g_Game_SetupScreenSize; + g_Menu_Reset; + g_Game_ClearLoading; + end; + + function InitWindow (w, h, bpp: Integer; fullScreen: Boolean): Boolean; + var flags: Uint32; + begin + e_LogWritefln('InitWindow %s %s %s %s', [w, h, bpp, fullscreen]); + Result := False; + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); // lights; it is enough to have 1-bit stencil buffer for lighting, but... + flags := SDL_OPENGL or SDL_VIDEORESIZE; + if fullScreen then + flags := flags or SDL_FULLSCREEN; + if (screen = nil) or (SDL_VideoModeOk(w, h, bpp, flags) <> 0) then + begin + SDL_FreeSurface(screen); + screen := SDL_SetVideoMode(w, h, bpp, flags); + if screen <> nil then + begin + SDL_WM_SetCaption('Doom 2D: Forever (SDL 1.2)', nil); + UpdateSize(w, h); + Result := True + end + end + else + begin + e_LogWritefln('SDL: video mode not supported', []) + end + end; + + procedure sys_Repaint; + begin + SDL_GL_SwapBuffers + end; + + procedure sys_EnableVSync (yes: Boolean); + begin + (* ??? *) + end; + + function sys_GetDispalyModes (bpp: Integer): SSArray; + var m: PPSDL_Rect; f: TSDL_PixelFormat; i, count: Integer; + begin + SetLength(result, 0); + FillChar(f, sizeof(f), 0); + f.palette := nil; + f.BitsPerPixel := bpp; + f.BytesPerPixel := (bpp + 7) div 8; + m := SDL_ListModes(@f, SDL_OPENGL or SDL_FULLSCREEN); + if (m <> NIL) and (IntPtr(m) <> -1) then + begin + count := 0; + while m[count] <> nil do inc(count); + SetLength(result, count); + for i := 0 to count - 1 do + result[i] := IntToStr(m[i].w) + 'x' + IntToStr(m[i].h); + end + end; + + function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen: Boolean): Boolean; + begin + result := InitWindow(w, h, bpp, fullscreen) + end; + + (* --------- Input --------- *) + + function Key2Stub (key: Integer): Integer; + var x: Integer; + begin + case key of + SDLK_ESCAPE: x := IK_ESCAPE; + SDLK_RETURN: x := IK_RETURN; + SDLK_KP_ENTER: x := IK_KPRETURN; + SDLK_KP0: x := IK_KPINSERT; + SDLK_UP: x := IK_UP; + SDLK_KP8: x := IK_KPUP; + SDLK_DOWN: x := IK_DOWN; + SDLK_KP2: x := IK_KPDOWN; + SDLK_LEFT: x := IK_LEFT; + SDLK_KP4: x := IK_KPLEFT; + SDLK_RIGHT: x := IK_RIGHT; + SDLK_KP6: x := IK_KPRIGHT; + SDLK_DELETE: x := IK_DELETE; + SDLK_HOME: x := IK_HOME; + SDLK_KP7: x := IK_KPHOME; + SDLK_INSERT: x := IK_INSERT; + SDLK_SPACE: x := IK_SPACE; + SDLK_LSHIFT: x := IK_SHIFT; + SDLK_LALT: x := IK_ALT; + SDLK_TAB: x := IK_TAB; + SDLK_PAGEUP: x := IK_PAGEUP; + SDLK_KP9: x := IK_KPPAGEUP; + SDLK_PAGEDOWN: x := IK_PAGEDN; + SDLK_KP3: x := IK_KPPAGEDN; + SDLK_KP5: x := IK_KP5; + SDLK_NUMLOCK: x := IK_NUMLOCK; + SDLK_KP_DIVIDE: x := IK_KPDIVIDE; + SDLK_KP_MULTIPLY: x := IK_KPMULTIPLE; + SDLK_KP_MINUS: x := IK_KPMINUS; + SDLK_KP_PLUS: x := IK_KPPLUS; + SDLK_KP_PERIOD: x := IK_KPDOT; + SDLK_CAPSLOCK: x := IK_CAPSLOCK; + SDLK_RSHIFT: x := IK_RSHIFT; + SDLK_LCTRL: x := IK_CTRL; + SDLK_RCTRL: x := IK_RCTRL; + SDLK_RALT: x := IK_RALT; + SDLK_LSUPER: x := IK_WIN; + SDLK_RSUPER: x := IK_RWIN; + SDLK_MENU: x := IK_MENU; + SDLK_PRINT: x := IK_PRINTSCR; + SDLK_SCROLLOCK: x := IK_SCROLLLOCK; + SDLK_LEFTBRACKET: x := IK_LBRACKET; + SDLK_RIGHTBRACKET: x := IK_RBRACKET; + SDLK_SEMICOLON: x := IK_SEMICOLON; + SDLK_QUOTE: x := IK_QUOTE; + SDLK_BACKSLASH: x := IK_BACKSLASH; + SDLK_SLASH: x := IK_SLASH; + SDLK_COMMA: x := IK_COMMA; + SDLK_PERIOD: x := IK_DOT; + SDLK_EQUALS: x := IK_EQUALS; + SDLK_0: x := IK_0; + SDLK_1: x := IK_1; + SDLK_2: x := IK_2; + SDLK_3: x := IK_3; + SDLK_4: x := IK_4; + SDLK_5: x := IK_5; + SDLK_6: x := IK_6; + SDLK_7: x := IK_7; + SDLK_8: x := IK_8; + SDLK_9: x := IK_9; + SDLK_F1: x := IK_F1; + SDLK_F2: x := IK_F2; + SDLK_F3: x := IK_F3; + SDLK_F4: x := IK_F4; + SDLK_F5: x := IK_F5; + SDLK_F6: x := IK_F6; + SDLK_F7: x := IK_F7; + SDLK_F8: x := IK_F8; + SDLK_F9: x := IK_F9; + SDLK_F10: x := IK_F10; + SDLK_F11: x := IK_F11; + SDLK_F12: x := IK_F12; + SDLK_END: x := IK_END; + SDLK_KP1: x := IK_KPEND; + SDLK_BACKSPACE: x := IK_BACKSPACE; + SDLK_BACKQUOTE: x := IK_BACKQUOTE; + SDLK_PAUSE: x := IK_PAUSE; + SDLK_A..SDLK_Z: x := IK_A + (key - SDLK_A); + SDLK_MINUS: x := IK_MINUS; + else + x := IK_INVALID + end; + result := x + end; + + procedure HandleKeyboard (var ev: TSDL_KeyboardEvent); + var down: Boolean; key, stb: Integer; + begin + down := (ev.type_ = SDL_KEYDOWN); + key := ev.keysym.sym; + stb := Key2Stub(key); + if g_dbg_input then + e_LogWritefln('Input Debug: keysym, press=%s, scancode=%s SDL.ev.key.state=%s', [down, key, ev.state]); + e_KeyUpDown(stb, down); + g_Console_ProcessBind(stb, down); + (* !!! need text input -- console, cheaats, fields *) + end; + + function sys_HandleInput (): Boolean; + var ev: TSDL_Event; + begin + result := false; + while SDL_PollEvent(@ev) <> 0 do + begin + case ev.type_ of + SDL_QUITEV: result := true; + SDL_VIDEORESIZE: InitWindow(ev.resize.w, ev.resize.h, gBPP, gFullscreen); + SDL_KEYUP, SDL_KEYDOWN: HandleKeyboard(ev.key); + end + end + end; + + procedure sys_RequestQuit; + var ev: TSDL_Event; + begin + ev.quit.type_ := SDL_QUITEV; + SDL_PushEvent(@ev) + end; + + (* --------- Init --------- *) + + procedure sys_Init; + var flags: Uint32; ok: Boolean; + begin + flags := SDL_INIT_VIDEO or SDL_INIT_AUDIO or + SDL_INIT_TIMER or SDL_INIT_JOYSTICK + (*or SDL_INIT_NOPARACHUTE*); + if SDL_Init(flags) <> 0 then + raise Exception.Create('SDL: Init failed: ' + SDL_GetError()); + ok := InitWindow(gScreenWidth, gScreenHeight, gBPP, gFullScreen); + if not ok then + raise Exception.Create('SDL: failed to set videomode: ' + SDL_GetError) + end; + + procedure sys_Final; + begin + e_WriteLog('Releasing SDL', TMsgType.Notify); + SDL_FreeSurface(screen); + SDL_Quit + end; + +end. diff --git a/src/game/sdl/g_touch.pas b/src/game/sdl/g_touch.pas new file mode 100644 index 0000000..d07de41 --- /dev/null +++ b/src/game/sdl/g_touch.pas @@ -0,0 +1,53 @@ +(* Copyright (C) Doom 2D: Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License ONLY. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE ../shared/a_modes.inc} +unit g_touch; + +interface + + var + g_touch_enabled: Boolean = False; + g_touch_size: Single = 1.0; + g_touch_offset: Single = 50.0; + g_touch_fire: Boolean = True; + g_touch_alt: Boolean = False; + + procedure g_Touch_Init; + procedure g_Touch_ShowKeyboard(yes: Boolean); + procedure g_Touch_Draw; + +implementation + + uses g_console; + + procedure g_Touch_Init; + begin + end; + + procedure g_Touch_ShowKeyboard(yes: Boolean); + begin + end; + + procedure g_Touch_Draw; + begin + end; + +initialization + conRegVar('touch_enable', @g_touch_enabled, 'enable/disable virtual buttons', 'draw buttons'); + conRegVar('touch_fire', @g_touch_fire, 'enable/disable fire when press virtual up/down', 'fire when press up/down'); + conRegVar('touch_size', @g_touch_size, 0.1, 10, 'size of virtual buttons', 'button size'); + conRegVar('touch_offset', @g_touch_offset, 0, 100, '', ''); + conRegVar('touch_alt', @g_touch_alt, 'althernative virtual buttons layout', 'althernative layout'); +end. diff --git a/src/game/stub/g_system.pas b/src/game/stub/g_system.pas new file mode 100644 index 0000000..84ae121 --- /dev/null +++ b/src/game/stub/g_system.pas @@ -0,0 +1,94 @@ +(* Copyright (C) Doom 2D: Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License ONLY. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE ../shared/a_modes.inc} +unit g_system; + +interface + + uses Utils; + + (* --- Utils --- *) + function sys_GetTicks (): Int64; + procedure sys_Delay (ms: Integer); + + (* --- Graphics --- *) + function sys_GetDispalyModes (bpp: Integer): SSArray; + function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen: Boolean): Boolean; + procedure sys_EnableVSync (yes: Boolean); + procedure sys_Repaint; + + (* --- Input --- *) + function sys_HandleInput (): Boolean; + procedure sys_RequestQuit; + + (* --- Init --- *) + procedure sys_Init; + procedure sys_Final; + +implementation + + (* --------- Utils --------- *) + + function sys_GetTicks (): Int64; + begin + Result := 0 + end; + + procedure sys_Delay (ms: Integer); + begin + end; + + (* --------- Graphics --------- *) + + procedure sys_Repaint; + begin + end; + + procedure sys_EnableVSync (yes: Boolean); + begin + end; + + function sys_GetDispalyModes (bpp: Integer): SSArray; + begin + SetLength(result, 0); + end; + + function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen: Boolean): Boolean; + begin + result := True + end; + + (* --------- Input --------- *) + + function sys_HandleInput (): Boolean; + begin + result := false + end; + + procedure sys_RequestQuit; + begin + end; + + (* --------- Init --------- *) + + procedure sys_Init; + begin + end; + + procedure sys_Final; + begin + end; + +end. diff --git a/src/game/stub/g_touch.pas b/src/game/stub/g_touch.pas new file mode 100644 index 0000000..d07de41 --- /dev/null +++ b/src/game/stub/g_touch.pas @@ -0,0 +1,53 @@ +(* Copyright (C) Doom 2D: Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License ONLY. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE ../shared/a_modes.inc} +unit g_touch; + +interface + + var + g_touch_enabled: Boolean = False; + g_touch_size: Single = 1.0; + g_touch_offset: Single = 50.0; + g_touch_fire: Boolean = True; + g_touch_alt: Boolean = False; + + procedure g_Touch_Init; + procedure g_Touch_ShowKeyboard(yes: Boolean); + procedure g_Touch_Draw; + +implementation + + uses g_console; + + procedure g_Touch_Init; + begin + end; + + procedure g_Touch_ShowKeyboard(yes: Boolean); + begin + end; + + procedure g_Touch_Draw; + begin + end; + +initialization + conRegVar('touch_enable', @g_touch_enabled, 'enable/disable virtual buttons', 'draw buttons'); + conRegVar('touch_fire', @g_touch_fire, 'enable/disable fire when press virtual up/down', 'fire when press up/down'); + conRegVar('touch_size', @g_touch_size, 0.1, 10, 'size of virtual buttons', 'button size'); + conRegVar('touch_offset', @g_touch_offset, 0, 100, '', ''); + conRegVar('touch_alt', @g_touch_alt, 'althernative virtual buttons layout', 'althernative layout'); +end. diff --git a/src/shared/xprofiler.pas b/src/shared/xprofiler.pas index be2a86a..5e6212b 100644 --- a/src/shared/xprofiler.pas +++ b/src/shared/xprofiler.pas @@ -21,6 +21,12 @@ interface {$IFNDEF IN_TOOLS} uses + {$IFDEF USE_SDL} + SDL, + {$ENDIF} + {$IFDEF USE_SDL2} + SDL2, + {$ENDIF} SysUtils; {$DEFINE STOPWATCH_IS_HERE} @@ -46,6 +52,11 @@ interface ; {$ENDIF} // IN_TOOLS +{$IFDEF USE_SDL} + type + UInt64 = QWord; (* !!! *) +{$ENDIF} + {$IF DEFINED(STOPWATCH_IS_HERE)} type TStopWatch = record @@ -160,9 +171,6 @@ function getTimeMilli (): UInt64; inline; implementation {$IFNDEF IN_TOOLS} -uses - SDL2; - type THPTimeType = Int64; {$ELSE} @@ -205,7 +213,7 @@ begin end; -{$IFDEF IN_TOOLS} +{$IF DEFINED(IN_TOOLS)} function getTimeMicro (): UInt64; inline; var r: THPTimeType; @@ -219,17 +227,30 @@ begin result := UInt64(r)*1000000 div mFrequency; {$ENDIF} end; -{$ELSE} +(* !!! +{$ELSEIF DEFINED(USE_SDL)} +function getTimeMicro: UInt64; inline; +begin + {$WARNING use inaccurate profiling timer} + result := SDL_GetTicks() * 1000 +end; +*) +{$ELSEIF DEFINED(USE_SDL2)} function getTimeMicro (): UInt64; inline; begin Result := SDL_GetPerformanceCounter() * 1000000 div SDL_GetPerformanceFrequency() end; +{$ELSE} +function getTimeMicro: UInt64; inline; +begin + {$WARNING use stub profiling timer} +end; {$ENDIF} function getTimeMilli (): UInt64; inline; begin - result := getTimeMicro div 1000; + result := getTimeMicro() div 1000; end;