DEADSOFTWARE

sdl: fix
[d2df-sdl.git] / src / game / sdl / g_system.pas
index 4cb69f90349c26ac449f029ded27ff3e30303747..74672ef36145819e3344a507a8f4873b802519c7 100644 (file)
@@ -25,7 +25,7 @@ interface
 
   (* --- Graphics --- *)
   function sys_GetDisplayModes (bpp: Integer): SSArray;
-  function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen: Boolean): Boolean;
+  function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen, maximized: Boolean): Boolean;
   procedure sys_EnableVSync (yes: Boolean);
   procedure sys_Repaint;
 
@@ -40,13 +40,16 @@ interface
 implementation
 
   uses
+    {$IFDEF DARWIN}
+      Keyboards, Events,
+    {$ENDIF}
     SysUtils, SDL, Math,
     {$INCLUDE ../nogl/noGLuses.inc}
     e_log, e_graphics, e_input, e_sound,
-    g_options, g_window, g_console, g_game, g_menu, g_gui, g_main;
+    g_options, g_window, g_console, g_game, g_menu, g_gui, g_main, g_basic;
 
   const
-    GameTitle = 'Doom 2D: Forever (SDL 1.2)';
+    GameTitle = 'Doom 2D: Forever (SDL 1.2, %s)';
 
   var
     userResize: Boolean;
@@ -70,12 +73,47 @@ implementation
 
   (* --------- Graphics --------- *)
 
+  function LoadGL: Boolean;
+  begin
+    result := true;
+    {$IFDEF NOGL_INIT}
+    nogl_Init;
+    if glRenderToFBO and (not nogl_ExtensionSupported('GL_OES_framebuffer_object')) then
+    {$ELSE}
+    if glRenderToFBO and (not Load_GL_ARB_framebuffer_object) then
+    {$ENDIF}
+    begin
+      e_LogWriteln('GL: framebuffer objects not supported; disabling FBO rendering');
+      glRenderToFBO := false;
+    end;
+  end;
+
+  procedure FreeGL;
+  begin
+    {$IFDEF NOGL_INIT}
+    nogl_Quit();
+    {$ENDIF}
+  end;
+
   procedure UpdateSize (w, h: Integer);
   begin
     gWinSizeX := w;
     gWinSizeY := h;
-    gWinRealPosX := 0;
-    gWinRealPosY := 0;
+    gRC_Width := w;
+    gRC_Height := h;
+    if glRenderToFBO then
+    begin
+      // store real window size in gWinSize, downscale resolution now
+      w := round(w / r_pixel_scale);
+      h := round(h / r_pixel_scale);
+      if not e_ResizeFramebuffer(w, h) then
+      begin
+        e_LogWriteln('GL: could not create framebuffer, falling back to --no-fbo');
+        glRenderToFBO := False;
+        w := gWinSizeX;
+        h := gWinSizeY;
+      end;
+    end;
     gScreenWidth := w;
     gScreenHeight := h;
     {$IFDEF ENABLE_HOLMES}
@@ -89,11 +127,20 @@ implementation
     g_Game_ClearLoading;
   end;
 
+  function GetTitle (): AnsiString;
+    var info: AnsiString;
+  begin
+    info := g_GetBuildHash(false);
+    if info = 'custom build' then
+      info := info + ' by ' + g_GetBuilderName() + ' ' + GAME_BUILDDATE + ' ' + GAME_BUILDTIME;
+    result := Format(GameTitle, [info]);
+  end;
+
   function InitWindow (w, h, bpp: Integer; fullScreen: Boolean): Boolean;
-    var flags: Uint32;
+    var flags: Uint32; title: AnsiString;
   begin
     e_LogWritefln('InitWindow %s %s %s %s', [w, h, bpp, fullScreen]);
-    result := False;
+    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);
@@ -109,10 +156,15 @@ implementation
       screen := SDL_SetVideoMode(w, h, bpp, flags);
       if screen <> nil then
       begin
-        {$IFDEF NOGL_INIT}
-          nogl_Init;
-        {$ENDIF}
-        SDL_WM_SetCaption(GameTitle, nil);
+        if not LoadGL then
+        begin
+          e_LogWriteln('GL: unable to load OpenGL functions', TMsgType.Fatal);
+          exit;
+        end;
+        title := GetTitle();
+        SDL_WM_SetCaption(PChar(title), nil);
+        gFullScreen := fullscreen;
+        gRC_FullScreen := fullscreen;
         UpdateSize(w, h);
         result := True
       end
@@ -136,7 +188,7 @@ implementation
   function sys_GetDisplayModes (bpp: Integer): SSArray;
     var m: PPSDL_Rect; f: TSDL_PixelFormat; i, count: Integer;
   begin
-    SetLength(result, 0);
+    result := nil;
     FillChar(f, sizeof(f), 0);
     f.palette := nil;
     f.BitsPerPixel := bpp;
@@ -152,7 +204,7 @@ implementation
     end
   end;
 
-  function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen: Boolean): Boolean;
+  function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen, maximized: Boolean): Boolean;
   begin
     result := InitWindow(w, h, bpp, fullscreen)
   end;
@@ -296,6 +348,146 @@ implementation
 
   (* --------- Input --------- *)
 
+{$IFDEF DARWIN}
+  function Mac2Stub (scancode: Integer): Integer;
+  begin
+    (* SDL 2 swap tilda/grave and paragraph/plus-minus buttons on ISO keyboards *)
+    if ((scancode = 10) or (scancode = 50)) and (KBGetLayoutType(LMGetKbdType()) = kKeyboardISO) then
+      scancode := 60 - scancode;
+    case scancode of
+      0: result := IK_A;
+      1: result := IK_S;
+      2: result := IK_D;
+      3: result := IK_F;
+      4: result := IK_H;
+      5: result := IK_G;
+      6: result := IK_Z;
+      7: result := IK_X;
+      8: result := IK_C;
+      9: result := IK_V;
+      10: result := IK_NONUSBACKSLASH;
+      11: result := IK_B;
+      12: result := IK_Q;
+      13: result := IK_W;
+      14: result := IK_E;
+      15: result := IK_R;
+      16: result := IK_Y;
+      17: result := IK_T;
+      18: result := IK_1;
+      19: result := IK_2;
+      20: result := IK_3;
+      21: result := IK_4;
+      22: result := IK_6;
+      23: result := IK_5;
+      24: result := IK_EQUALS;
+      25: result := IK_9;
+      26: result := IK_7;
+      27: result := IK_MINUS;
+      28: result := IK_8;
+      29: result := IK_0;
+      30: result := {IK_RIGHTBRACKET} IK_RBRACKET;
+      31: result := IK_O;
+      32: result := IK_U;
+      33: result := {IK_LEFTBRACKET} IK_LBRACKET;
+      34: result := IK_I;
+      35: result := IK_P;
+      36: result := IK_RETURN;
+      37: result := IK_L;
+      38: result := IK_J;
+      39: result := {IK_APOSTROPHE} IK_QUOTE;
+      40: result := IK_K;
+      41: result := IK_SEMICOLON;
+      42: result := IK_BACKSLASH;
+      43: result := IK_COMMA;
+      44: result := IK_SLASH;
+      45: result := IK_N;
+      46: result := IK_M;
+      47: result := {IK_PERIOD} IK_DOT;
+      48: result := IK_TAB;
+      49: result := IK_SPACE;
+      50: result := IK_GRAVE;
+      51: result := IK_BACKSPACE;
+      52: result := {IK_KP_ENTER} IK_KPRETURN;
+      53: result := IK_ESCAPE;
+      54: result := {IK_RGUI} IK_RWIN;
+      55: result := {IK_LGUI} IK_WIN;
+      56: result := {IK_LSHIFT} IK_SHIFT;
+      57: result := IK_CAPSLOCK;
+      58: result := {IK_LALT} IK_ALT;
+      59: result := {IK_LCTRL} IK_CTRL;
+      60: result := IK_RSHIFT;
+      61: result := IK_RALT;
+      62: result := IK_RCTRL;
+      63: result := {IK_RGUI} IK_RWIN;
+      {64: result := IK_F17;}
+      65: result := {IK_KP_PERIOD} IK_KPDOT;
+      66: result := IK_INVALID; (* unused? *)
+      67: result := {IK_KP_MULTIPLY} IK_KPMULTIPLE;
+      68: result := IK_INVALID; (* unused? *)
+      69: result := {IK_KP_PLUS} IK_KPPLUS;
+      70: result := IK_INVALID; (* unused? *)
+      71: result := {IK_NUMLOCKCLEAR} IK_NUMLOCK;
+      {72: result := IK_VOLUMEUP;}
+      {73: result := IK_VOLUMEDOWN;}
+      {74: result := IK_MUTE;}
+      75: result := {IK_KP_DIVIDE} IK_KPDIVIDE;
+      76: result := {IK_KP_ENTER} IK_KPRETURN;
+      77: result := IK_INVALID; (* unused? *)
+      78: result := {IK_KP_MINUS} IK_KPMINUS;
+      {79: result := IK_F18;}
+      {80: result := IK_F19;}
+      {81: result := IK_KP_EQUALS;}
+      82: result := {IK_KP_0} IK_KPINSERT;
+      83: result := {IK_KP_1} IK_KPEND;
+      84: result := {IK_KP_2} IK_KPDOWN;
+      85: result := {IK_KP_3} IK_KPPAGEDN;
+      86: result := {IK_KP_4} IK_KPLEFT;
+      87: result := {IK_KP_5} IK_KP5;
+      88: result := {IK_KP_6} IK_KPRIGHT;
+      89: result := {IK_KP_7} IK_KPHOME;
+      90: result := IK_INVALID; (* unused? *)
+      91: result := {IK_KP_8} IK_KPUP;
+      92: result := {IK_KP_9} IK_KPPAGEUP;
+      {93: result := IK_INTERNATIONAL3;}
+      {94: result := IK_INTERNATIONAL1;}
+      {95: result := IK_KP_COMMA;}
+      96: result := IK_F5;
+      97: result := IK_F6;
+      98: result := IK_F7;
+      99: result := IK_F3;
+      100: result := IK_F8;
+      101: result := IK_F9;
+      {102: result := IK_LANG2;}
+      103: result := IK_F11;
+      {104: result := IK_LANG1;}
+      105: result := {IK_PRINTSCREEN} IK_PRINTSCR;
+      {106: result := IK_F16;}
+      107: result := IK_SCROLLLOCK;
+      108: result := IK_INVALID; (* unused? *)
+      109: result := IK_F10;
+      {110: result := IK_APPLICATION;}
+      111: result := IK_F12;
+      112: result := IK_INVALID; (* unused? *)
+      113: result := IK_PAUSE;
+      114: result := IK_INSERT;
+      115: result := IK_HOME;
+      116: result := IK_PAGEUP;
+      117: result := IK_DELETE;
+      118: result := IK_F4;
+      119: result := IK_END;
+      120: result := IK_F2;
+      121: result := {IK_PAGEDOWN} IK_PAGEDN;
+      122: result := IK_F1;
+      123: result := IK_LEFT;
+      124: result := IK_RIGHT;
+      125: result := IK_DOWN;
+      126: result := IK_UP;
+      {127: result := IK_POWER;}
+    otherwise result := IK_INVALID
+    end
+  end;
+{$ENDIF}
+
   function Key2Stub (key: Integer): Integer;
     var x: Integer;
   begin
@@ -379,8 +571,6 @@ implementation
       SDLK_PAUSE: x := IK_PAUSE;
       SDLK_A..SDLK_Z: x := IK_A + (key - SDLK_A);
       SDLK_MINUS: x := IK_MINUS;
-      SDLK_RMETA: x := IK_RMETA;
-      SDLK_LMETA: x := IK_LMETA;
     else
       x := IK_INVALID
     end;
@@ -390,20 +580,25 @@ implementation
   procedure HandleKeyboard (var ev: TSDL_KeyboardEvent);
     var down, repeated: Boolean; key: Integer; ch: Char;
   begin
-    key := Key2Stub(ev.keysym.sym);
+    key := IK_INVALID;
+    {$IFDEF DARWIN}
+      key := Mac2Stub(ev.keysym.scancode);
+    {$ENDIF}
+    if key = IK_INVALID then
+      key := Key2Stub(ev.keysym.sym);
     down := (ev.type_ = SDL_KEYDOWN);
     repeated := down and e_KeyPressed(key);
     ch := wchar2win(WideChar(ev.keysym.unicode));
     if g_dbg_input then
-      e_LogWritefln('Input Debug: keysym, down=%s, sym=%s, state=%s, unicode=%s, stubsym=%s, cp1251=%s', [down, ev.keysym.sym, ev.state, ev.keysym.unicode, key, Ord(ch)]);
+      e_LogWritefln('Input Debug: keysym, scancode=%s, down=%s, sym=%s, state=%s, unicode=%s, stubsym=%s, cp1251=%s', [ev.keysym.scancode, down, ev.keysym.sym, ev.state, ev.keysym.unicode, key, Ord(ch)]);
     if not repeated then
     begin
       e_KeyUpDown(key, down);
       g_Console_ProcessBind(key, down);
     end
-    else if gConsoleShow or gChatShow or (g_ActiveWindow <> nil) then
+    else
     begin
-      KeyPress(key) // key repeat in menus and shit
+      g_Console_ProcessBindRepeat(key)
     end;
     if down and IsValid1251(ev.keysym.unicode) and IsPrintable1251(ch) then
       CharPress(ch)
@@ -470,9 +665,7 @@ implementation
       RemoveJoystick(i);
     if screen <> nil then
     begin
-      {$IFDEF NOGL_INIT}
-        nogl_Quit;
-      {$ENDIF}
+      FreeGL;
       SDL_FreeSurface(screen)
     end;
     SDL_Quit