diff --git a/src/include/cursor.h b/src/include/cursor.h
index 21bfa72b6..664000b73 100644
--- a/src/include/cursor.h
+++ b/src/include/cursor.h
@@ -106,7 +106,7 @@
 --  Includes
 ----------------------------------------------------------------------------*/
 
-
+#include <SDL.h>
 #include <vec2i.h>
 
 /*----------------------------------------------------------------------------
@@ -127,6 +127,8 @@ public:
 	CCursor() : HotPos(0, 0),
 		SpriteFrame(0), FrameRate(0), G(NULL) {}
 
+	~CCursor();
+
 	std::string Ident;  /// Identifier to reference it
 	std::string Race;   /// Race name
 
@@ -138,6 +140,12 @@ public:
 	// --- FILLED UP ---
 
 	CGraphic *G; /// Cursor sprite image
+
+	SDL_Cursor *GetSDLCursor();
+
+private:
+	std::vector<SDL_Cursor*> SdlCursors;
+	std::vector<SDL_Surface*> SdlCursorSurfaces;
 };
 
 /// Cursor config reference
diff --git a/src/video/cursor.cpp b/src/video/cursor.cpp
index d0cd1b2b9..9dd6bba57 100644
--- a/src/video/cursor.cpp
+++ b/src/video/cursor.cpp
@@ -81,11 +81,46 @@ CUnitType *CursorBuilding;           /// building cursor
 /*--- DRAW SPRITE CURSOR ---------------------------------------------------*/
 CCursor *GameCursor;                 /// current shown cursor-type
 
+static CCursor *ActuallyVisibleGameCursor;
+static int VisibleGameCursorFrame;
+
+
 static SDL_Surface *HiddenSurface;
+
 /*----------------------------------------------------------------------------
 --  Functions
 ----------------------------------------------------------------------------*/
 
+SDL_Cursor *CCursor::GetSDLCursor()
+{
+	if (SdlCursors.size() <= SpriteFrame) {
+		// slow path
+		for (int i = SdlCursors.size(); i <= SpriteFrame; i++) {
+			G->Load();
+			SDL_Surface *cursorFrame = SDL_CreateRGBSurfaceWithFormat(0, G->getWidth(), G->getHeight(), TheScreen->format->BitsPerPixel, TheScreen->format->format);
+			G->DrawFrame(i, 0, 0, cursorFrame);
+			printf("%s\n", SDL_GetError());
+			SdlCursorSurfaces.push_back(cursorFrame);
+			SDL_Cursor *cur = SDL_CreateColorCursor(cursorFrame, HotPos.x, HotPos.y);
+			if (!cur) {
+				printf("%s\n", SDL_GetError());
+			}
+			SdlCursors.push_back(cur);
+		}
+	}
+	return SdlCursors[SpriteFrame];
+}
+
+CCursor::~CCursor()
+{
+	for (auto sdlCur : SdlCursors) {
+		SDL_FreeCursor(sdlCur);
+	}
+	for (auto sdlSurface : SdlCursorSurfaces) {
+		SDL_FreeSurface(sdlSurface);
+	}
+}
+
 /**
 **  Load all cursor sprites.
 **
@@ -256,38 +291,21 @@ void DrawCursor()
 	//  Cursor may not exist if we are loading a game or something.
 	//  Only draw it if it exists
 	if (GameCursor == NULL || IsDemoMode()) {
+		SDL_ShowCursor(SDL_DISABLE);
+		ActuallyVisibleGameCursor = NULL;
 		return;
 	}
-	const PixelPos pos = CursorScreenPos - GameCursor->HotPos;
 
-	if (!GameRunning && !Editor.Running) {
-		if (!HiddenSurface
-			|| HiddenSurface->w != GameCursor->G->getWidth()
-			|| HiddenSurface->h != GameCursor->G->getHeight()) {
-			if (HiddenSurface) {
-				VideoPaletteListRemove(HiddenSurface);
-				SDL_FreeSurface(HiddenSurface);
-			}
-
-			HiddenSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
-												 GameCursor->G->getWidth(),
-												 GameCursor->G->getHeight(),
-												 TheScreen->format->BitsPerPixel,
-												 TheScreen->format->Rmask,
-												 TheScreen->format->Gmask,
-												 TheScreen->format->Bmask,
-												 TheScreen->format->Amask);
+	//  Last, Normal cursor. This is a (hardware) cursor drawn by SDL, so only needs to be set if something changed
+	if (ActuallyVisibleGameCursor != GameCursor || GameCursor->SpriteFrame != VisibleGameCursorFrame) {
+		if (!GameCursor->G->IsLoaded()) {
+			GameCursor->G->Load();
 		}
-
-		SDL_Rect srcRect = { Sint16(pos.x), Sint16(pos.y), Uint16(GameCursor->G->getWidth()), Uint16(GameCursor->G->getHeight())};
-		SDL_BlitSurface(TheScreen, &srcRect, HiddenSurface, NULL);
+		SDL_SetCursor(GameCursor->GetSDLCursor());
+		SDL_ShowCursor(SDL_ENABLE);
+		ActuallyVisibleGameCursor = GameCursor;
+		VisibleGameCursorFrame = GameCursor->SpriteFrame;
 	}
-
-	//  Last, Normal cursor.
-	if (!GameCursor->G->IsLoaded()) {
-		GameCursor->G->Load();
-	}
-	GameCursor->G->DrawFrameClip(GameCursor->SpriteFrame, pos.x, pos.y);
 }
 
 /**
@@ -295,11 +313,8 @@ void DrawCursor()
 */
 void HideCursor()
 {
-	if (!GameRunning && !Editor.Running && GameCursor) {
-		const PixelPos pos = CursorScreenPos - GameCursor->HotPos;
-		SDL_Rect dstRect = {Sint16(pos.x), Sint16(pos.y), 0, 0 };
-		SDL_BlitSurface(HiddenSurface, NULL, TheScreen, &dstRect);
-	}
+	SDL_ShowCursor(SDL_DISABLE);
+	ActuallyVisibleGameCursor = NULL;
 }
 
 /**
diff --git a/src/video/sdl.cpp b/src/video/sdl.cpp
index 552ceca83..04c739023 100644
--- a/src/video/sdl.cpp
+++ b/src/video/sdl.cpp
@@ -820,7 +820,6 @@ void RealizeVideoMemory()
 		}
 		NumRects = 0;
 	}
-	HideCursor();
 }
 
 /**