Repository: isledecomp/isle-portable
Pull request #96: Split miniwin headers and implementation
Author: login: madebr
Created: 2025-05-16T16:21:03Z | Merged: 2025-05-16T19:37:16Z

This removes issues about forward declarations etc.
No new features have been added.


Diff:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 303e7619e..b0a952a4b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -87,11 +87,14 @@ endif()
 #if (NOT WIN32)
 add_library(miniwin STATIC EXCLUDE_FROM_ALL
   miniwin/miniwin/src/miniwin.cpp
+  miniwin/miniwin/src/miniwin_ddclipper.cpp
+  miniwin/miniwin/src/miniwin_ddpalette.cpp
+  miniwin/miniwin/src/miniwin_ddsurface.cpp
   miniwin/miniwin/src/miniwin_ddraw.cpp
-  miniwin/miniwin/src/miniwin_d3d.cpp
   miniwin/miniwin/src/miniwin_d3drm.cpp
 )
 target_include_directories(miniwin PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/miniwin/miniwin/include>")
+target_include_directories(miniwin PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/miniwin/miniwin/src/include")
 target_compile_definitions(miniwin PUBLIC "MINIWIN")
 target_link_libraries(miniwin PRIVATE SDL3::SDL3)
 
diff --git a/miniwin/miniwin/src/include/miniwin_ddclipper_p.h b/miniwin/miniwin/src/include/miniwin_ddclipper_p.h
new file mode 100644
index 000000000..0c0948248
--- /dev/null
+++ b/miniwin/miniwin/src/include/miniwin_ddclipper_p.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <SDL3/SDL.h>
+#include <miniwin_ddraw.h>
+
+class DirectDrawImpl;
+
+struct DirectDrawClipperImpl : public IDirectDrawClipper {
+	DirectDrawClipperImpl(DirectDrawImpl* lpDD);
+	~DirectDrawClipperImpl() override;
+
+	// IDirectDrawClipper interface
+	HRESULT SetHWnd(DWORD unnamedParam1, HWND hWnd) override;
+};
diff --git a/miniwin/miniwin/src/include/miniwin_ddpalette_p.h b/miniwin/miniwin/src/include/miniwin_ddpalette_p.h
new file mode 100644
index 000000000..048044312
--- /dev/null
+++ b/miniwin/miniwin/src/include/miniwin_ddpalette_p.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "miniwin_ddraw.h"
+
+struct DirectDrawPaletteImpl : public IDirectDrawPalette {
+	DirectDrawPaletteImpl(LPPALETTEENTRY lpColorTable);
+	HRESULT GetCaps(LPDWORD lpdwCaps) override;
+	HRESULT GetEntries(DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries) override;
+	HRESULT SetEntries(DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries) override;
+};
diff --git a/miniwin/miniwin/src/include/miniwin_ddraw_p.h b/miniwin/miniwin/src/include/miniwin_ddraw_p.h
new file mode 100644
index 000000000..1dba2d71c
--- /dev/null
+++ b/miniwin/miniwin/src/include/miniwin_ddraw_p.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "miniwin_d3d.h"
+#include "miniwin_ddraw.h"
+
+extern struct SDL_Renderer* renderer;
+
+struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 {
+	// IUnknown interface
+	HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
+	// IDirectDraw interface
+	HRESULT CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter) override;
+	HRESULT
+	CreatePalette(
+		DDPixelCaps dwFlags,
+		LPPALETTEENTRY lpColorTable,
+		LPDIRECTDRAWPALETTE* lplpDDPalette,
+		IUnknown* pUnkOuter
+	) override;
+	HRESULT CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE* lplpDDSurface, IUnknown* pUnkOuter)
+		override;
+	HRESULT EnumDisplayModes(
+		DWORD dwFlags,
+		LPDDSURFACEDESC lpDDSurfaceDesc,
+		LPVOID lpContext,
+		LPDDENUMMODESCALLBACK lpEnumModesCallback
+	) override;
+	HRESULT FlipToGDISurface() override;
+	HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) override;
+	HRESULT GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) override;
+	HRESULT RestoreDisplayMode() override;
+	HRESULT SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) override;
+	HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) override;
+	// IDirect3D2 interface
+	HRESULT CreateDevice(const GUID& guid, void* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice) override;
+	HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override;
+};
diff --git a/miniwin/miniwin/src/include/miniwin_ddsurface_p.h b/miniwin/miniwin/src/include/miniwin_ddsurface_p.h
new file mode 100644
index 000000000..df8ec4a83
--- /dev/null
+++ b/miniwin/miniwin/src/include/miniwin_ddsurface_p.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <SDL3/SDL.h>
+#include <miniwin_ddraw.h>
+
+struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 {
+	DirectDrawSurfaceImpl();
+	DirectDrawSurfaceImpl(int width, int height);
+	~DirectDrawSurfaceImpl() override;
+
+	// IUnknown interface
+	HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
+	// IDirectDrawSurface interface
+	HRESULT AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) override;
+	HRESULT Blt(
+		LPRECT lpDestRect,
+		LPDIRECTDRAWSURFACE lpDDSrcSurface,
+		LPRECT lpSrcRect,
+		DDBltFlags dwFlags,
+		LPDDBLTFX lpDDBltFx
+	) override;
+	HRESULT BltFast(DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans)
+		override;
+	HRESULT Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override;
+	HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) override;
+	HRESULT GetCaps(LPDDSCAPS lpDDSCaps) override;
+	HRESULT GetDC(HDC* lphDC) override;
+	HRESULT GetOverlayPosition(LPLONG lplX, LPLONG lplY) override;
+	HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override;
+	HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override;
+	HRESULT GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) override;
+	HRESULT IsLost() override;
+	HRESULT Lock(LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override;
+	HRESULT ReleaseDC(HDC hDC) override;
+	HRESULT Restore() override;
+	HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) override;
+	HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override;
+	HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
+	HRESULT Unlock(LPVOID lpSurfaceData) override;
+
+private:
+	SDL_Texture* texture = nullptr;
+};
diff --git a/miniwin/miniwin/src/include/miniwin_p.h b/miniwin/miniwin/src/include/miniwin_p.h
new file mode 100644
index 000000000..c5fcc2019
--- /dev/null
+++ b/miniwin/miniwin/src/include/miniwin_p.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <SDL3/SDL.h>
+
+#define LOG_CATEGORY_MINIWIN (SDL_LOG_CATEGORY_CUSTOM)
+
+#define MINIWIN_TRACE(FUNCTION, MSG, ...)                                                                              \
+	do {                                                                                                               \
+		SDL_LogTrace(LOG_CATEGORY_MINIWIN, FUNCTION);                                                                  \
+	}
+
+#define MINIWIN_ERROR(MSG)                                                                                             \
+	do {                                                                                                               \
+		SDL_LogError(LOG_CATEGORY_MINIWIN, "%s:%s", __func__, MSG);                                                    \
+	} while (0)
+
+static SDL_FRect ConvertRect(const RECT* r)
+{
+	SDL_FRect sdlRect;
+	sdlRect.x = r->left;
+	sdlRect.y = r->top;
+	sdlRect.w = r->right - r->left;
+	sdlRect.h = r->bottom - r->top;
+	return sdlRect;
+}
diff --git a/miniwin/miniwin/src/miniwin.cpp b/miniwin/miniwin/src/miniwin.cpp
index 92da13ceb..7eaad90e0 100644
--- a/miniwin/miniwin/src/miniwin.cpp
+++ b/miniwin/miniwin/src/miniwin.cpp
@@ -1,7 +1,6 @@
 #include "miniwin.h"
 
 #include <SDL3/SDL.h>
-#include <utility>
 #include <vector>
 
 ULONG IUnknown::AddRef()
diff --git a/miniwin/miniwin/src/miniwin_d3d.cpp b/miniwin/miniwin/src/miniwin_d3d.cpp
deleted file mode 100644
index f91143af4..000000000
--- a/miniwin/miniwin/src/miniwin_d3d.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "miniwin_d3d.h"
diff --git a/miniwin/miniwin/src/miniwin_d3drm.cpp b/miniwin/miniwin/src/miniwin_d3drm.cpp
index 867240ad5..a7fc9fd2b 100644
--- a/miniwin/miniwin/src/miniwin_d3drm.cpp
+++ b/miniwin/miniwin/src/miniwin_d3drm.cpp
@@ -1,5 +1,7 @@
 #include "miniwin_d3drm.h"
 
+#include "miniwin_ddsurface_p.h"
+
 #include <SDL3/SDL.h>
 #include <assert.h>
 
diff --git a/miniwin/miniwin/src/miniwin_ddclipper.cpp b/miniwin/miniwin/src/miniwin_ddclipper.cpp
new file mode 100644
index 000000000..79dfa882e
--- /dev/null
+++ b/miniwin/miniwin/src/miniwin_ddclipper.cpp
@@ -0,0 +1,15 @@
+#include "miniwin_ddclipper_p.h"
+#include "miniwin_ddraw_p.h"
+
+DirectDrawClipperImpl::DirectDrawClipperImpl(DirectDrawImpl* lpDD)
+{
+}
+
+DirectDrawClipperImpl::~DirectDrawClipperImpl()
+{
+}
+
+HRESULT DirectDrawClipperImpl::SetHWnd(DWORD unnamedParam1, HWND hWnd)
+{
+	return DD_OK;
+}
diff --git a/miniwin/miniwin/src/miniwin_ddpalette.cpp b/miniwin/miniwin/src/miniwin_ddpalette.cpp
new file mode 100644
index 000000000..0615f06cd
--- /dev/null
+++ b/miniwin/miniwin/src/miniwin_ddpalette.cpp
@@ -0,0 +1,21 @@
+#include "miniwin_ddpalette_p.h"
+#include "miniwin_ddraw.h"
+
+DirectDrawPaletteImpl::DirectDrawPaletteImpl(LPPALETTEENTRY lpColorTable)
+{
+}
+
+HRESULT DirectDrawPaletteImpl::GetCaps(LPDWORD lpdwCaps)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawPaletteImpl::GetEntries(DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawPaletteImpl::SetEntries(DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries)
+{
+	return DD_OK;
+}
diff --git a/miniwin/miniwin/src/miniwin_ddraw.cpp b/miniwin/miniwin/src/miniwin_ddraw.cpp
index 85036003f..7d4a7c43f 100644
--- a/miniwin/miniwin/src/miniwin_ddraw.cpp
+++ b/miniwin/miniwin/src/miniwin_ddraw.cpp
@@ -1,6 +1,10 @@
-#include "miniwin_ddraw.h"
 
 #include "miniwin_d3d.h"
+#include "miniwin_ddclipper_p.h"
+#include "miniwin_ddpalette_p.h"
+#include "miniwin_ddraw_p.h"
+#include "miniwin_ddsurface_p.h"
+#include "miniwin_p.h"
 
 #include <SDL3/SDL.h>
 #include <assert.h>
@@ -10,321 +14,170 @@
 
 SDL_Renderer* renderer;
 
-static SDL_FRect ConvertRect(const RECT* r)
+HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject)
 {
-	SDL_FRect sdlRect;
-	sdlRect.x = r->left;
-	sdlRect.y = r->top;
-	sdlRect.w = r->right - r->left;
-	sdlRect.h = r->bottom - r->top;
-	return sdlRect;
+	if (SDL_memcmp(&riid, &IID_IDirectDraw2, sizeof(GUID)) == 0) {
+		this->IUnknown::AddRef();
+		*ppvObject = static_cast<IDirectDraw2*>(this);
+		return S_OK;
+	}
+	if (SDL_memcmp(&riid, &IID_IDirect3D2, sizeof(GUID)) == 0) {
+		this->IUnknown::AddRef();
+		*ppvObject = static_cast<IDirect3D2*>(this);
+		return S_OK;
+	}
+	SDL_LogError(LOG_CATEGORY_MINIWIN, "DirectDrawImpl does not implement guid");
+	return E_NOINTERFACE;
 }
 
-struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 {
-	DirectDrawSurfaceImpl() {}
-	DirectDrawSurfaceImpl(int width, int height)
-	{
-		texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
-		if (!texture) {
-			SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create texture: %s", SDL_GetError());
-		}
-	}
+// IDirectDraw interface
+HRESULT DirectDrawImpl::CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter)
+{
+	*lplpDDClipper = static_cast<IDirectDrawClipper*>(new DirectDrawClipperImpl(this));
+
+	return DD_OK;
+}
 
-	~DirectDrawSurfaceImpl() override
-	{
-		if (texture) {
-			SDL_DestroyTexture(texture);
+HRESULT DirectDrawImpl::CreatePalette(
+	DDPixelCaps dwFlags,
+	LPPALETTEENTRY lpColorTable,
+	LPDIRECTDRAWPALETTE* lplpDDPalette,
+	IUnknown* pUnkOuter
+)
+{
+	*lplpDDPalette = static_cast<LPDIRECTDRAWPALETTE>(new DirectDrawPaletteImpl(lpColorTable));
+	return DD_OK;
+}
+
+HRESULT DirectDrawImpl::CreateSurface(
+	LPDDSURFACEDESC lpDDSurfaceDesc,
+	LPDIRECTDRAWSURFACE* lplpDDSurface,
+	IUnknown* pUnkOuter
+)
+{
+	if ((lpDDSurfaceDesc->dwFlags & DDSD_CAPS) == DDSD_CAPS) {
+		if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER) {
+			if ((lpDDSurfaceDesc->dwFlags & DDSD_ZBUFFERBITDEPTH) != DDSD_ZBUFFERBITDEPTH) {
+				return DDERR_INVALIDPARAMS;
+			}
+			SDL_Log("Todo: Set %dbit Z-Buffer", lpDDSurfaceDesc->dwZBufferBitDepth);
+			*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl);
+			return DD_OK;
 		}
-	}
-	// IUnknown interface
-	HRESULT QueryInterface(const GUID& riid, void** ppvObject) override
-	{
-		if (SDL_memcmp(&riid, &IID_IDirectDrawSurface3, sizeof(GUID)) == 0) {
-			this->IUnknown::AddRef();
-			*ppvObject = static_cast<IDirectDrawSurface3*>(this);
-			return S_OK;
+		if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) {
+			if ((lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT) == DDSD_BACKBUFFERCOUNT) {
+				SDL_Log("Todo: Switch to %d buffering", lpDDSurfaceDesc->dwBackBufferCount);
+			}
+			int width, height;
+			SDL_GetRenderOutputSize(renderer, &width, &height);
+			*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height));
+			return DD_OK;
 		}
-		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
-		return E_NOINTERFACE;
-	}
-	// IDirectDrawSurface interface
-	HRESULT AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) override { return DD_OK; }
-	HRESULT Blt(
-		LPRECT lpDestRect,
-		LPDIRECTDRAWSURFACE lpDDSrcSurface,
-		LPRECT lpSrcRect,
-		DDBltFlags dwFlags,
-		LPDDBLTFX lpDDBltFx
-	) override
-	{
-		if (!renderer) {
-			return DDERR_GENERIC;
+		if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) == DDSCAPS_OFFSCREENPLAIN) {
+			SDL_Log("DDSCAPS_OFFSCREENPLAIN"); // 2D surfaces?
 		}
-		SDL_FRect srcRect = ConvertRect(lpSrcRect);
-		SDL_FRect dstRect = ConvertRect(lpDestRect);
-		SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
-		SDL_RenderPresent(renderer);
-		return DD_OK;
-	}
-	HRESULT BltFast(DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans)
-		override
-	{
-		if (!renderer) {
-			return DDERR_GENERIC;
+		if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == DDSCAPS_SYSTEMMEMORY) {
+			SDL_Log("DDSCAPS_SYSTEMMEMORY"); // Software rendering?
 		}
-		SDL_FRect dstRect = {
-			(float) dwX,
-			(float) dwY,
-			(float) (lpSrcRect->right - lpSrcRect->left),
-			(float) (lpSrcRect->bottom - lpSrcRect->top)
-		};
-		SDL_FRect srcRect = ConvertRect(lpSrcRect);
-		SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
-		SDL_RenderPresent(renderer);
-		return DD_OK;
-	}
-	HRESULT Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override
-	{
-		if (!renderer || !texture) {
-			return DDERR_GENERIC;
+		if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) {
+			SDL_Log("DDSCAPS_TEXTURE"); // Texture for use in 3D
 		}
-		float width, height;
-		SDL_GetTextureSize(texture, &width, &height);
-		SDL_FRect rect{0, 0, width, height};
-		SDL_RenderTexture(renderer, texture, &rect, &rect);
-		SDL_RenderPresent(renderer);
-		return DD_OK;
-	}
-	HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) override
-	{
-		if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) {
-			return DDERR_INVALIDPARAMS;
+		if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) {
+			SDL_Log("DDSCAPS_3DDEVICE"); // back buffer
 		}
-		*lplpDDAttachedSurface = static_cast<IDirectDrawSurface*>(this);
-		return DD_OK;
-	}
-	HRESULT GetCaps(LPDDSCAPS lpDDSCaps) override { return DD_OK; }
-	HRESULT GetDC(HDC* lphDC) override { return DD_OK; }
-	HRESULT GetOverlayPosition(LPLONG lplX, LPLONG lplY) override { return DD_OK; }
-	HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override { return DDERR_GENERIC; }
-	HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override
-	{
-		memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat));
-		lpDDPixelFormat->dwFlags = DDPF_RGB;
-		return DD_OK;
-	}
-	HRESULT GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) override
-	{
-		if (!texture) {
-			return DDERR_GENERIC;
+		if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) == DDSCAPS_VIDEOMEMORY) {
+			SDL_Log("DDSCAPS_VIDEOMEMORY"); // front / back buffer
 		}
-		const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
-		lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
-		return DD_OK;
 	}
-	HRESULT IsLost() override { return DD_OK; }
-	HRESULT Lock(LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override
-	{
-		if (!lpDDSurfaceDesc) {
-			return DDERR_INVALIDPARAMS;
-		}
-		if (!texture) {
-			return DDERR_GENERIC;
-		}
 
-		int pitch = 0;
-		void* pixels = nullptr;
-		if (SDL_LockTexture(texture, (SDL_Rect*) lpDestRect, &pixels, &pitch) < 0) {
-			return DDERR_GENERIC;
+	if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) {
+		if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) {
+			SDL_Log("DDPF_RGB"); // Use dwRGBBitCount to choose the texture format
 		}
-
-		lpDDSurfaceDesc->lpSurface = pixels;
-		lpDDSurfaceDesc->lPitch = pitch;
-		const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
-		lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
-
-		return DD_OK;
-	}
-	HRESULT ReleaseDC(HDC hDC) override { return DD_OK; }
-	HRESULT Restore() override { return DD_OK; }
-	HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) override { return DD_OK; }
-	HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override { return DD_OK; }
-	HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override { return DD_OK; }
-	HRESULT Unlock(LPVOID lpSurfaceData) override
-	{
-		if (texture) {
-			SDL_UnlockTexture(texture);
-			return DD_OK;
-		}
-		return DDERR_GENERIC;
 	}
 
-private:
-	SDL_Texture* texture = nullptr;
-};
+	if ((lpDDSurfaceDesc->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT)) != (DDSD_WIDTH | DDSD_HEIGHT)) {
+		return DDERR_INVALIDPARAMS;
+	}
 
-struct DirectDrawClipperImpl : public IDirectDrawClipper {
-	// IDirectDrawClipper interface
-	HRESULT SetHWnd(DWORD unnamedParam1, HWND hWnd) override { return DD_OK; }
-};
+	int width = lpDDSurfaceDesc->dwWidth;
+	int height = lpDDSurfaceDesc->dwHeight;
+	*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height));
+	return DD_OK;
+}
 
-struct DirectDrawPaletteImpl : public IDirectDrawPalette {
-	HRESULT GetCaps(LPDWORD lpdwCaps) override { return DD_OK; }
-	HRESULT GetEntries(DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries) override
-	{
-		return DD_OK;
-	}
-	HRESULT SetEntries(DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries) override
-	{
-		return DD_OK;
-	}
-};
-
-struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 {
-	// IUnknown interface
-	HRESULT QueryInterface(const GUID& riid, void** ppvObject) override
-	{
-		if (SDL_memcmp(&riid, &IID_IDirectDraw2, sizeof(GUID)) == 0) {
-			this->IUnknown::AddRef();
-			*ppvObject = static_cast<IDirectDraw2*>(this);
-			return S_OK;
-		}
-		if (SDL_memcmp(&riid, &IID_IDirect3D2, sizeof(GUID)) == 0) {
-			this->IUnknown::AddRef();
-			*ppvObject = static_cast<IDirect3D2*>(this);
-			return S_OK;
-		}
-		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
-		return E_NOINTERFACE;
+HRESULT DirectDrawImpl::EnumDisplayModes(
+	DWORD dwFlags,
+	LPDDSURFACEDESC lpDDSurfaceDesc,
+	LPVOID lpContext,
+	LPDDENUMMODESCALLBACK lpEnumModesCallback
+)
+{
+	if (!lpEnumModesCallback) {
+		return DDERR_INVALIDPARAMS;
 	}
-	// IDirecdtDraw interface
-	HRESULT CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter) override
-	{
-		*lplpDDClipper = static_cast<IDirectDrawClipper*>(new DirectDrawClipperImpl);
 
-		return DD_OK;
-	}
-	HRESULT CreatePalette(
-		DDPixelCaps dwFlags,
-		LPPALETTEENTRY lpColorTable,
-		LPDIRECTDRAWPALETTE* lplpDDPalette,
-		IUnknown* pUnkOuter
-	) override
-	{
-		*lplpDDPalette = static_cast<LPDIRECTDRAWPALETTE>(new DirectDrawPaletteImpl);
-		return DD_OK;
+	SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
+	if (!displayID) {
+		return DDERR_GENERIC;
 	}
-	HRESULT CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE* lplpDDSurface, IUnknown* pUnkOuter)
-		override
-	{
-		if ((lpDDSurfaceDesc->dwFlags & DDSD_CAPS) == DDSD_CAPS) {
-			if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER) {
-				if ((lpDDSurfaceDesc->dwFlags & DDSD_ZBUFFERBITDEPTH) != DDSD_ZBUFFERBITDEPTH) {
-					return DDERR_INVALIDPARAMS;
-				}
-				SDL_Log("Todo: Set %dbit Z-Buffer", lpDDSurfaceDesc->dwZBufferBitDepth);
-				*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl);
-				return DD_OK;
-			}
-			if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) {
-				if ((lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT) == DDSD_BACKBUFFERCOUNT) {
-					SDL_Log("Todo: Switch to %d buffering", lpDDSurfaceDesc->dwBackBufferCount);
-				}
-				int width, height;
-				SDL_GetRenderOutputSize(renderer, &width, &height);
-				*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height));
-				return DD_OK;
-			}
-			if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) == DDSCAPS_OFFSCREENPLAIN) {
-				SDL_Log("DDSCAPS_OFFSCREENPLAIN"); // 2D surfaces?
-			}
-			if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == DDSCAPS_SYSTEMMEMORY) {
-				SDL_Log("DDSCAPS_SYSTEMMEMORY"); // Software rendering?
-			}
-			if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) {
-				SDL_Log("DDSCAPS_TEXTURE"); // Texture for use in 3D
-			}
-			if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) {
-				SDL_Log("DDSCAPS_3DDEVICE"); // back buffer
-			}
-			if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) == DDSCAPS_VIDEOMEMORY) {
-				SDL_Log("DDSCAPS_VIDEOMEMORY"); // front / back buffer
-			}
-		}
 
-		if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) {
-			if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) {
-				SDL_Log("DDPF_RGB"); // Use dwRGBBitCount to choose the texture format
-			}
-		}
+	int count_modes;
+	SDL_DisplayMode** modes = SDL_GetFullscreenDisplayModes(displayID, &count_modes);
+	if (!modes) {
+		return DDERR_GENERIC;
+	}
 
-		if ((lpDDSurfaceDesc->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT)) != (DDSD_WIDTH | DDSD_HEIGHT)) {
-			return DDERR_INVALIDPARAMS;
-		}
+	HRESULT status = S_OK;
 
-		int width = lpDDSurfaceDesc->dwWidth;
-		int height = lpDDSurfaceDesc->dwHeight;
-		*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height));
-		return DD_OK;
-	}
-	HRESULT EnumDisplayModes(
-		DWORD dwFlags,
-		LPDDSURFACEDESC lpDDSurfaceDesc,
-		LPVOID lpContext,
-		LPDDENUMMODESCALLBACK lpEnumModesCallback
-	) override;
-	HRESULT FlipToGDISurface() override { return DD_OK; }
-	HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) override;
-	HRESULT GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) override
-	{
-		SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
-		if (!displayID) {
-			return DDERR_GENERIC;
+	for (int i = 0; i < count_modes; i++) {
+		const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(modes[i]->format);
+		if (!format) {
+			continue;
 		}
+		DDSURFACEDESC ddsd = {};
+		ddsd.dwSize = sizeof(DDSURFACEDESC);
+		ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
+		ddsd.dwWidth = modes[i]->w;
+		ddsd.dwHeight = modes[i]->h;
+		ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+		ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
+		ddsd.ddpfPixelFormat.dwRGBBitCount =
+			(format->bits_per_pixel == 8) ? 8 : 16; // Game only accepts 8 or 16 bit mode
+		ddsd.ddpfPixelFormat.dwRBitMask = format->Rmask;
+		ddsd.ddpfPixelFormat.dwGBitMask = format->Gmask;
+		ddsd.ddpfPixelFormat.dwBBitMask = format->Bmask;
 
-		const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
-		if (!mode) {
-			return DDERR_GENERIC;
+		if (!lpEnumModesCallback(&ddsd, lpContext)) {
+			status = DDERR_GENERIC;
 		}
+	}
+	SDL_free(modes);
 
-		const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(mode->format);
+	return status;
+}
 
-		lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
-		lpDDSurfaceDesc->dwWidth = mode->w;
-		lpDDSurfaceDesc->dwHeight = mode->h;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
-		lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
+HRESULT DirectDrawImpl::FlipToGDISurface()
+{
+	return DD_OK;
+}
 
-		return DD_OK;
-	}
-	HRESULT RestoreDisplayMode() override { return DD_OK; }
-	HRESULT SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) override
-	{
-		if (hWnd) {
-			renderer = SDL_CreateRenderer(hWnd, NULL);
+HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
+{
+	if (lpDDDriverCaps) {
+		if (lpDDDriverCaps->dwSize >= sizeof(DDCAPS)) {
+			lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
 		}
-		return DD_OK;
 	}
-	HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) override { return DD_OK; }
-	// IDirect3D2 interface
-	HRESULT CreateDevice(const GUID& guid, void* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice) override
-	{
-		*ppDirect3DDevice = new IDirect3DDevice2;
-		return DD_OK;
+
+	if (lpDDHELCaps) {
+		if (lpDDDriverCaps->dwSize >= sizeof(DDCAPS)) {
+			lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
+		}
 	}
-	HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override;
-};
+
+	return S_OK;
+}
 
 HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
 {
@@ -337,8 +190,7 @@ HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
 		return DDERR_GENERIC;
 	}
 
-	const char* deviceDesc = "SDL3-backed renderer";
-	char* deviceDescDup = SDL_strdup(deviceDesc);
+	const char* deviceDesc = "SDL3 SDL_Renderer";
 
 	for (int i = 0; i < numDrivers; ++i) {
 		const char* deviceName = SDL_GetRenderDriver(i);
@@ -358,84 +210,84 @@ HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
 		halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
 
 		char* deviceNameDup = SDL_strdup(deviceName);
+		char* deviceDescDup = SDL_strdup(deviceDesc);
 		cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &halDesc, ctx);
+		SDL_free(deviceDescDup);
 		SDL_free(deviceNameDup);
 	}
-	SDL_free(deviceDescDup);
 
 	return S_OK;
 }
 
-HRESULT DirectDrawImpl::EnumDisplayModes(
-	DWORD dwFlags,
-	LPDDSURFACEDESC lpDDSurfaceDesc,
-	LPVOID lpContext,
-	LPDDENUMMODESCALLBACK lpEnumModesCallback
-)
+HRESULT DirectDrawImpl::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
 {
-	if (!lpEnumModesCallback) {
-		return DDERR_INVALIDPARAMS;
-	}
-
 	SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
 	if (!displayID) {
 		return DDERR_GENERIC;
 	}
 
-	int count_modes;
-	SDL_DisplayMode** modes = SDL_GetFullscreenDisplayModes(displayID, &count_modes);
-	if (!modes) {
+	const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
+	if (!mode) {
 		return DDERR_GENERIC;
 	}
 
-	HRESULT status = S_OK;
+	const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(mode->format);
 
-	for (int i = 0; i < count_modes; i++) {
-		const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(modes[i]->format);
-		if (!format) {
-			continue;
-		}
-		DDSURFACEDESC ddsd = {};
-		ddsd.dwSize = sizeof(DDSURFACEDESC);
-		ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
-		ddsd.dwWidth = modes[i]->w;
-		ddsd.dwHeight = modes[i]->h;
-		ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-		ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
-		ddsd.ddpfPixelFormat.dwRGBBitCount =
-			(format->bits_per_pixel == 8) ? 8 : 16; // Game only accepts 8 or 16 bit mode
-		ddsd.ddpfPixelFormat.dwRBitMask = format->Rmask;
-		ddsd.ddpfPixelFormat.dwGBitMask = format->Gmask;
-		ddsd.ddpfPixelFormat.dwBBitMask = format->Bmask;
+	lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
+	lpDDSurfaceDesc->dwWidth = mode->w;
+	lpDDSurfaceDesc->dwHeight = mode->h;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
 
-		if (!lpEnumModesCallback(&ddsd, lpContext)) {
-			status = DDERR_GENERIC;
-		}
-	}
-	SDL_free(modes);
+	return DD_OK;
+}
 
-	return status;
+HRESULT DirectDrawImpl::RestoreDisplayMode()
+{
+	return DD_OK;
 }
 
-HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
+HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
 {
-	if (lpDDDriverCaps) {
-		memset(lpDDDriverCaps, 0, sizeof(DDCAPS));
-		lpDDDriverCaps->dwSize = sizeof(DDCAPS);
-		lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
-	}
+	if (hWnd) {
+		bool fullscreen;
+		if ((dwFlags & DDSCL_NORMAL) == DDSCL_NORMAL) {
+			fullscreen = false;
+		}
+		else if ((dwFlags & DDSCL_FULLSCREEN) == DDSCL_FULLSCREEN) {
+			fullscreen = true;
+		}
+		else {
+			return DDERR_INVALIDPARAMS;
+		}
 
-	if (lpDDHELCaps) {
-		memset(lpDDHELCaps, 0, sizeof(DDCAPS));
-		lpDDHELCaps->dwSize = sizeof(DDCAPS);
-		lpDDHELCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
+		if (!SDL_SetWindowFullscreen(hWnd, fullscreen)) {
+			return DDERR_GENERIC;
+		}
+		renderer = SDL_CreateRenderer(hWnd, NULL);
 	}
+	return DD_OK;
+}
 
-	return S_OK;
+HRESULT DirectDrawImpl::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
+{
+	return DD_OK;
+}
+// IDirect3D2 interface
+HRESULT DirectDrawImpl::CreateDevice(const GUID& guid, void* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice)
+{
+	*ppDirect3DDevice = new IDirect3DDevice2;
+	return DD_OK;
 }
 
 HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter)
 {
+	if (lpGuid) {
+		MINIWIN_ERROR("Specifying a DirectDraw driver is not implemented");
+	}
 	if (!lplpDD) {
 		return DDERR_INVALIDPARAMS;
 	}
@@ -451,8 +303,10 @@ HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context)
 
 	for (int i = 0; i < numDrivers; ++i) {
 		const char* driverName = SDL_GetVideoDriver(i);
-
-		if (!cb(NULL, (LPSTR) driverName, NULL, context)) {
+		char* driverNameDup = SDL_strdup(driverName);
+		BOOL callback_result = cb(NULL, driverNameDup, NULL, context);
+		SDL_free(driverNameDup);
+		if (!callback_result) {
 			return DDERR_GENERIC;
 		}
 	}
diff --git a/miniwin/miniwin/src/miniwin_ddsurface.cpp b/miniwin/miniwin/src/miniwin_ddsurface.cpp
new file mode 100644
index 000000000..e4461d2a8
--- /dev/null
+++ b/miniwin/miniwin/src/miniwin_ddsurface.cpp
@@ -0,0 +1,216 @@
+#include "miniwin_ddraw_p.h"
+#include "miniwin_ddsurface_p.h"
+#include "miniwin_p.h"
+
+#include <assert.h>
+
+DirectDrawSurfaceImpl::DirectDrawSurfaceImpl()
+{
+}
+
+DirectDrawSurfaceImpl::DirectDrawSurfaceImpl(int width, int height)
+{
+	texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
+	if (!texture) {
+		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create texture: %s", SDL_GetError());
+	}
+}
+
+DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl()
+{
+	if (texture) {
+		SDL_DestroyTexture(texture);
+	}
+}
+
+// IUnknown interface
+HRESULT DirectDrawSurfaceImpl::QueryInterface(const GUID& riid, void** ppvObject)
+{
+	if (SDL_memcmp(&riid, &IID_IDirectDrawSurface3, sizeof(GUID)) == 0) {
+		this->IUnknown::AddRef();
+		*ppvObject = static_cast<IDirectDrawSurface3*>(this);
+		return S_OK;
+	}
+	SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
+	return E_NOINTERFACE;
+}
+
+// IDirectDrawSurface interface
+HRESULT DirectDrawSurfaceImpl::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
+{
+	return DD_OK;
+}
+HRESULT DirectDrawSurfaceImpl::Blt(
+	LPRECT lpDestRect,
+	LPDIRECTDRAWSURFACE lpDDSrcSurface,
+	LPRECT lpSrcRect,
+	DDBltFlags dwFlags,
+	LPDDBLTFX lpDDBltFx
+)
+{
+	if (!renderer) {
+		return DDERR_GENERIC;
+	}
+	SDL_FRect srcRect = ConvertRect(lpSrcRect);
+	SDL_FRect dstRect = ConvertRect(lpDestRect);
+	SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::BltFast(
+	DWORD dwX,
+	DWORD dwY,
+	LPDIRECTDRAWSURFACE lpDDSrcSurface,
+	LPRECT lpSrcRect,
+	DDBltFastFlags dwTrans
+)
+{
+	if (!renderer) {
+		return DDERR_GENERIC;
+	}
+	SDL_FRect dstRect = {
+		(float) dwX,
+		(float) dwY,
+		(float) (lpSrcRect->right - lpSrcRect->left),
+		(float) (lpSrcRect->bottom - lpSrcRect->top)
+	};
+	SDL_FRect srcRect = ConvertRect(lpSrcRect);
+	SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags)
+{
+	if (!renderer || !texture) {
+		return DDERR_GENERIC;
+	}
+	float width, height;
+	SDL_GetTextureSize(texture, &width, &height);
+	SDL_FRect rect{0, 0, width, height};
+	SDL_RenderTexture(renderer, texture, &rect, &rect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface)
+{
+	if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) {
+		return DDERR_INVALIDPARAMS;
+	}
+	*lplpDDAttachedSurface = static_cast<IDirectDrawSurface*>(this);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetCaps(LPDDSCAPS lpDDSCaps)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetDC(HDC* lphDC)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetOverlayPosition(LPLONG lplX, LPLONG lplY)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette)
+{
+	assert(false && "unimplemented");
+	return DDERR_GENERIC;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
+{
+	memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat));
+	lpDDPixelFormat->dwFlags = DDPF_RGB;
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc)
+{
+	if (!texture) {
+		return DDERR_GENERIC;
+	}
+	const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
+	lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::IsLost()
+{
+	return DD_OK;
+}
+HRESULT DirectDrawSurfaceImpl::Lock(
+	LPRECT lpDestRect,
+	LPDDSURFACEDESC lpDDSurfaceDesc,
+	DDLockFlags dwFlags,
+	HANDLE hEvent
+)
+{
+	if (!lpDDSurfaceDesc) {
+		return DDERR_INVALIDPARAMS;
+	}
+	if (!texture) {
+		return DDERR_GENERIC;
+	}
+
+	int pitch = 0;
+	void* pixels = nullptr;
+	if (SDL_LockTexture(texture, (SDL_Rect*) lpDestRect, &pixels, &pitch) < 0) {
+		return DDERR_GENERIC;
+	}
+
+	lpDDSurfaceDesc->lpSurface = pixels;
+	lpDDSurfaceDesc->lPitch = pitch;
+	const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
+	lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
+
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::ReleaseDC(HDC hDC)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::Restore()
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData)
+{
+	if (!texture) {
+		return DDERR_GENERIC;
+	}
+	SDL_UnlockTexture(texture);
+	return DD_OK;
+}


Reviews:
user: login: AJenbo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T17:28:27Z
user: login: AJenbo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T17:30:26Z
user: login: AJenbo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T17:35:59Z
user: login: madebr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T17:48:09Z
user: login: AJenbo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T18:18:35Z
user: login: AJenbo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T19:13:15Z
user: login: AJenbo
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-16T19:13:28Z

Review comments:
diff_hunk: @@ -0,0 +1,213 @@
+#include "miniwin_ddraw_p.h"
+#include "miniwin_ddsurface_p.h"
+#include "miniwin_p.h"
+
+DirectDrawSurfaceImpl::DirectDrawSurfaceImpl()
+{
+}
+
+DirectDrawSurfaceImpl::DirectDrawSurfaceImpl(int width, int height)
+{
+	texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
+	if (!texture) {
+		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create texture: %s", SDL_GetError());
+	}
+}
+
+DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl()
+{
+	if (texture) {
+		SDL_DestroyTexture(texture);
+	}
+}
+
+// IUnknown interface
+HRESULT DirectDrawSurfaceImpl::QueryInterface(const GUID& riid, void** ppvObject)
+{
+	if (SDL_memcmp(&riid, &IID_IDirectDrawSurface3, sizeof(GUID)) == 0) {
+		this->IUnknown::AddRef();
+		*ppvObject = static_cast<IDirectDrawSurface3*>(this);
+		return S_OK;
+	}
+	SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
+	return E_NOINTERFACE;
+}
+
+// IDirectDrawSurface interface
+HRESULT DirectDrawSurfaceImpl::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
+{
+	return DD_OK;
+}
+HRESULT DirectDrawSurfaceImpl::Blt(
+	LPRECT lpDestRect,
+	LPDIRECTDRAWSURFACE lpDDSrcSurface,
+	LPRECT lpSrcRect,
+	DDBltFlags dwFlags,
+	LPDDBLTFX lpDDBltFx
+)
+{
+	if (!renderer) {
+		return DDERR_GENERIC;
+	}
+	SDL_FRect srcRect = ConvertRect(lpSrcRect);
+	SDL_FRect dstRect = ConvertRect(lpDestRect);
+	SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::BltFast(
+	DWORD dwX,
+	DWORD dwY,
+	LPDIRECTDRAWSURFACE lpDDSrcSurface,
+	LPRECT lpSrcRect,
+	DDBltFastFlags dwTrans
+)
+{
+	if (!renderer) {
+		return DDERR_GENERIC;
+	}
+	SDL_FRect dstRect = {
+		(float) dwX,
+		(float) dwY,
+		(float) (lpSrcRect->right - lpSrcRect->left),
+		(float) (lpSrcRect->bottom - lpSrcRect->top)
+	};
+	SDL_FRect srcRect = ConvertRect(lpSrcRect);
+	SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags)
+{
+	if (!renderer || !texture) {
+		return DDERR_GENERIC;
+	}
+	float width, height;
+	SDL_GetTextureSize(texture, &width, &height);
+	SDL_FRect rect{0, 0, width, height};
+	SDL_RenderTexture(renderer, texture, &rect, &rect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface)
+{
+	if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) {
+		return DDERR_INVALIDPARAMS;
+	}
+	*lplpDDAttachedSurface = static_cast<IDirectDrawSurface*>(this);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetCaps(LPDDSCAPS lpDDSCaps)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetDC(HDC* lphDC)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetOverlayPosition(LPLONG lplX, LPLONG lplY)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette)
+{
+	return DDERR_GENERIC;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
+{
+	memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat));
+	lpDDPixelFormat->dwFlags = DDPF_RGB;
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc)
+{
+	if (!texture) {
+		return DDERR_GENERIC;
+	}
+	const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
+	lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::IsLost()
+{
+	return DD_OK;
+}
+HRESULT DirectDrawSurfaceImpl::Lock(
+	LPRECT lpDestRect,
+	LPDDSURFACEDESC lpDDSurfaceDesc,
+	DDLockFlags dwFlags,
+	HANDLE hEvent
+)
+{
+	if (!lpDDSurfaceDesc) {
+		return DDERR_INVALIDPARAMS;
+	}
+	if (!texture) {
+		return DDERR_GENERIC;
+	}
+
+	int pitch = 0;
+	void* pixels = nullptr;
+	if (SDL_LockTexture(texture, (SDL_Rect*) lpDestRect, &pixels, &pitch) < 0) {
+		return DDERR_GENERIC;
+	}
+
+	lpDDSurfaceDesc->lpSurface = pixels;
+	lpDDSurfaceDesc->lPitch = pitch;
+	const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
+	lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
+
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::ReleaseDC(HDC hDC)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::Restore()
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData)
+{
+	if (texture) {
+		SDL_UnlockTexture(texture);
+		return DD_OK;
+	}
+	return DDERR_GENERIC;
path: miniwin/miniwin/src/miniwin_ddsurface.cpp
user: login: AJenbo
body: ```suggestion
	if (!texture) {
		return DDERR_GENERIC;
	}
	SDL_UnlockTexture(texture);
	return DD_OK;
```
created_at: 2025-05-16T17:28:27Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,213 @@
+#include "miniwin_ddraw_p.h"
+#include "miniwin_ddsurface_p.h"
+#include "miniwin_p.h"
+
+DirectDrawSurfaceImpl::DirectDrawSurfaceImpl()
+{
+}
+
+DirectDrawSurfaceImpl::DirectDrawSurfaceImpl(int width, int height)
+{
+	texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
+	if (!texture) {
+		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create texture: %s", SDL_GetError());
+	}
+}
+
+DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl()
+{
+	if (texture) {
+		SDL_DestroyTexture(texture);
+	}
+}
+
+// IUnknown interface
+HRESULT DirectDrawSurfaceImpl::QueryInterface(const GUID& riid, void** ppvObject)
+{
+	if (SDL_memcmp(&riid, &IID_IDirectDrawSurface3, sizeof(GUID)) == 0) {
+		this->IUnknown::AddRef();
+		*ppvObject = static_cast<IDirectDrawSurface3*>(this);
+		return S_OK;
+	}
+	SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
+	return E_NOINTERFACE;
+}
+
+// IDirectDrawSurface interface
+HRESULT DirectDrawSurfaceImpl::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
+{
+	return DD_OK;
+}
+HRESULT DirectDrawSurfaceImpl::Blt(
+	LPRECT lpDestRect,
+	LPDIRECTDRAWSURFACE lpDDSrcSurface,
+	LPRECT lpSrcRect,
+	DDBltFlags dwFlags,
+	LPDDBLTFX lpDDBltFx
+)
+{
+	if (!renderer) {
+		return DDERR_GENERIC;
+	}
+	SDL_FRect srcRect = ConvertRect(lpSrcRect);
+	SDL_FRect dstRect = ConvertRect(lpDestRect);
+	SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::BltFast(
+	DWORD dwX,
+	DWORD dwY,
+	LPDIRECTDRAWSURFACE lpDDSrcSurface,
+	LPRECT lpSrcRect,
+	DDBltFastFlags dwTrans
+)
+{
+	if (!renderer) {
+		return DDERR_GENERIC;
+	}
+	SDL_FRect dstRect = {
+		(float) dwX,
+		(float) dwY,
+		(float) (lpSrcRect->right - lpSrcRect->left),
+		(float) (lpSrcRect->bottom - lpSrcRect->top)
+	};
+	SDL_FRect srcRect = ConvertRect(lpSrcRect);
+	SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags)
+{
+	if (!renderer || !texture) {
+		return DDERR_GENERIC;
+	}
+	float width, height;
+	SDL_GetTextureSize(texture, &width, &height);
+	SDL_FRect rect{0, 0, width, height};
+	SDL_RenderTexture(renderer, texture, &rect, &rect);
+	SDL_RenderPresent(renderer);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface)
+{
+	if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) {
+		return DDERR_INVALIDPARAMS;
+	}
+	*lplpDDAttachedSurface = static_cast<IDirectDrawSurface*>(this);
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetCaps(LPDDSCAPS lpDDSCaps)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetDC(HDC* lphDC)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetOverlayPosition(LPLONG lplX, LPLONG lplY)
+{
+	return DD_OK;
+}
+
+HRESULT DirectDrawSurfaceImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette)
+{
+	return DDERR_GENERIC;
path: miniwin/miniwin/src/miniwin_ddsurface.cpp
user: login: AJenbo
body: ```suggestion
	assert(false && "unimplemented");
	return DDERR_GENERIC;
```
created_at: 2025-05-16T17:30:26Z
author_association: COLLABORATOR
diff_hunk: @@ -358,87 +210,73 @@ HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
 		halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
 
 		char* deviceNameDup = SDL_strdup(deviceName);
+		char* deviceDescDup = SDL_strdup(deviceDesc);
 		cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &halDesc, ctx);
+		SDL_free(deviceDescDup);
 		SDL_free(deviceNameDup);
 	}
-	SDL_free(deviceDescDup);
 
 	return S_OK;
 }
 
-HRESULT DirectDrawImpl::EnumDisplayModes(
-	DWORD dwFlags,
-	LPDDSURFACEDESC lpDDSurfaceDesc,
-	LPVOID lpContext,
-	LPDDENUMMODESCALLBACK lpEnumModesCallback
-)
+HRESULT DirectDrawImpl::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
 {
-	if (!lpEnumModesCallback) {
-		return DDERR_INVALIDPARAMS;
-	}
-
 	SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
 	if (!displayID) {
 		return DDERR_GENERIC;
 	}
 
-	int count_modes;
-	SDL_DisplayMode** modes = SDL_GetFullscreenDisplayModes(displayID, &count_modes);
-	if (!modes) {
+	const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
+	if (!mode) {
 		return DDERR_GENERIC;
 	}
 
-	HRESULT status = S_OK;
+	const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(mode->format);
 
-	for (int i = 0; i < count_modes; i++) {
-		const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(modes[i]->format);
-		if (!format) {
-			continue;
-		}
-		DDSURFACEDESC ddsd = {};
-		ddsd.dwSize = sizeof(DDSURFACEDESC);
-		ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
-		ddsd.dwWidth = modes[i]->w;
-		ddsd.dwHeight = modes[i]->h;
-		ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-		ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
-		ddsd.ddpfPixelFormat.dwRGBBitCount =
-			(format->bits_per_pixel == 8) ? 8 : 16; // Game only accepts 8 or 16 bit mode
-		ddsd.ddpfPixelFormat.dwRBitMask = format->Rmask;
-		ddsd.ddpfPixelFormat.dwGBitMask = format->Gmask;
-		ddsd.ddpfPixelFormat.dwBBitMask = format->Bmask;
+	lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
+	lpDDSurfaceDesc->dwWidth = mode->w;
+	lpDDSurfaceDesc->dwHeight = mode->h;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
 
-		if (!lpEnumModesCallback(&ddsd, lpContext)) {
-			status = DDERR_GENERIC;
-		}
-	}
-	SDL_free(modes);
-
-	return status;
+	return DD_OK;
 }
 
-HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
+HRESULT DirectDrawImpl::RestoreDisplayMode()
 {
-	if (lpDDDriverCaps) {
-		memset(lpDDDriverCaps, 0, sizeof(DDCAPS));
-		lpDDDriverCaps->dwSize = sizeof(DDCAPS);
-		lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
-	}
+	return DD_OK;
+}
 
-	if (lpDDHELCaps) {
-		memset(lpDDHELCaps, 0, sizeof(DDCAPS));
-		lpDDHELCaps->dwSize = sizeof(DDCAPS);
-		lpDDHELCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
+HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
+{
+	if (hWnd) {
+		renderer = SDL_CreateRenderer(hWnd, NULL);
 	}
+	return DD_OK;
+}
 
-	return S_OK;
+HRESULT DirectDrawImpl::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
+{
+	return DD_OK;
+}
+// IDirect3D2 interface
+HRESULT DirectDrawImpl::CreateDevice(const GUID& guid, void* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice)
+{
+	*ppDirect3DDevice = new IDirect3DDevice2;
+	return DD_OK;
 }
 
 HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter)
 {
 	if (!lplpDD) {
 		return DDERR_INVALIDPARAMS;
 	}
+	if (lpGuid) {
+		MINIWIN_ERROR("Specifying a DirectDraw driver is not implemented");
+	}
path: miniwin/miniwin/src/miniwin_ddraw.cpp
user: login: AJenbo
body: ```suggestion
	if (lpGuid) {
		MINIWIN_ERROR("Specifying a DirectDraw driver is not implemented");
	}
	if (!lplpDD) {
		return DDERR_INVALIDPARAMS;
	}
```
created_at: 2025-05-16T17:35:59Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,214 @@
+#include "miniwin_ddraw_p.h"
+#include "miniwin_ddsurface_p.h"
+#include "miniwin_p.h"
path: miniwin/miniwin/src/miniwin_ddsurface.cpp
user: login: madebr
body: ```suggestion
#include "miniwin_p.h"

#include <assert.h>
```
created_at: 2025-05-16T17:48:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -358,87 +210,73 @@ HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
 		halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
 
 		char* deviceNameDup = SDL_strdup(deviceName);
+		char* deviceDescDup = SDL_strdup(deviceDesc);
 		cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &halDesc, ctx);
+		SDL_free(deviceDescDup);
 		SDL_free(deviceNameDup);
 	}
-	SDL_free(deviceDescDup);
 
 	return S_OK;
 }
 
-HRESULT DirectDrawImpl::EnumDisplayModes(
-	DWORD dwFlags,
-	LPDDSURFACEDESC lpDDSurfaceDesc,
-	LPVOID lpContext,
-	LPDDENUMMODESCALLBACK lpEnumModesCallback
-)
+HRESULT DirectDrawImpl::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
 {
-	if (!lpEnumModesCallback) {
-		return DDERR_INVALIDPARAMS;
-	}
-
 	SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
 	if (!displayID) {
 		return DDERR_GENERIC;
 	}
 
-	int count_modes;
-	SDL_DisplayMode** modes = SDL_GetFullscreenDisplayModes(displayID, &count_modes);
-	if (!modes) {
+	const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
+	if (!mode) {
 		return DDERR_GENERIC;
 	}
 
-	HRESULT status = S_OK;
+	const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(mode->format);
 
-	for (int i = 0; i < count_modes; i++) {
-		const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(modes[i]->format);
-		if (!format) {
-			continue;
-		}
-		DDSURFACEDESC ddsd = {};
-		ddsd.dwSize = sizeof(DDSURFACEDESC);
-		ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
-		ddsd.dwWidth = modes[i]->w;
-		ddsd.dwHeight = modes[i]->h;
-		ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-		ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
-		ddsd.ddpfPixelFormat.dwRGBBitCount =
-			(format->bits_per_pixel == 8) ? 8 : 16; // Game only accepts 8 or 16 bit mode
-		ddsd.ddpfPixelFormat.dwRBitMask = format->Rmask;
-		ddsd.ddpfPixelFormat.dwGBitMask = format->Gmask;
-		ddsd.ddpfPixelFormat.dwBBitMask = format->Bmask;
+	lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
+	lpDDSurfaceDesc->dwWidth = mode->w;
+	lpDDSurfaceDesc->dwHeight = mode->h;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
 
-		if (!lpEnumModesCallback(&ddsd, lpContext)) {
-			status = DDERR_GENERIC;
-		}
-	}
-	SDL_free(modes);
-
-	return status;
+	return DD_OK;
 }
 
-HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
+HRESULT DirectDrawImpl::RestoreDisplayMode()
 {
-	if (lpDDDriverCaps) {
-		memset(lpDDDriverCaps, 0, sizeof(DDCAPS));
-		lpDDDriverCaps->dwSize = sizeof(DDCAPS);
-		lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
-	}
+	return DD_OK;
+}
 
-	if (lpDDHELCaps) {
-		memset(lpDDHELCaps, 0, sizeof(DDCAPS));
-		lpDDHELCaps->dwSize = sizeof(DDCAPS);
-		lpDDHELCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
+HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
+{
+	if (hWnd) {
path: miniwin/miniwin/src/miniwin_ddraw.cpp
user: login: AJenbo
body: ```suggestion
	if (hWnd) {
		bool fullscreen;
		if ((dwFlags & DDSCL_NORMAL) == DDSCL_NORMAL) {
			fullscreen = false;
		} else if ((dwFlags & DDSCL_FULLSCREEN) == DDSCL_FULLSCREEN) {
			fullscreen = true;
		} else {
			return DDERR_INVALIDPARAMS; 
		}

		if (!SDL_SetWindowFullscreen(hWnd, fullscreen)) {
			return DDERR_GENERIC;
		}
```
created_at: 2025-05-16T18:18:35Z
author_association: COLLABORATOR
diff_hunk: @@ -358,84 +210,82 @@ HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
 		halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
 
 		char* deviceNameDup = SDL_strdup(deviceName);
+		char* deviceDescDup = SDL_strdup(deviceDesc);
 		cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &halDesc, ctx);
+		SDL_free(deviceDescDup);
 		SDL_free(deviceNameDup);
 	}
-	SDL_free(deviceDescDup);
 
 	return S_OK;
 }
 
-HRESULT DirectDrawImpl::EnumDisplayModes(
-	DWORD dwFlags,
-	LPDDSURFACEDESC lpDDSurfaceDesc,
-	LPVOID lpContext,
-	LPDDENUMMODESCALLBACK lpEnumModesCallback
-)
+HRESULT DirectDrawImpl::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
 {
-	if (!lpEnumModesCallback) {
-		return DDERR_INVALIDPARAMS;
-	}
-
 	SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
 	if (!displayID) {
 		return DDERR_GENERIC;
 	}
 
-	int count_modes;
-	SDL_DisplayMode** modes = SDL_GetFullscreenDisplayModes(displayID, &count_modes);
-	if (!modes) {
+	const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
+	if (!mode) {
 		return DDERR_GENERIC;
 	}
 
-	HRESULT status = S_OK;
+	const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(mode->format);
 
-	for (int i = 0; i < count_modes; i++) {
-		const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(modes[i]->format);
-		if (!format) {
-			continue;
-		}
-		DDSURFACEDESC ddsd = {};
-		ddsd.dwSize = sizeof(DDSURFACEDESC);
-		ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
-		ddsd.dwWidth = modes[i]->w;
-		ddsd.dwHeight = modes[i]->h;
-		ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-		ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
-		ddsd.ddpfPixelFormat.dwRGBBitCount =
-			(format->bits_per_pixel == 8) ? 8 : 16; // Game only accepts 8 or 16 bit mode
-		ddsd.ddpfPixelFormat.dwRBitMask = format->Rmask;
-		ddsd.ddpfPixelFormat.dwGBitMask = format->Gmask;
-		ddsd.ddpfPixelFormat.dwBBitMask = format->Bmask;
+	lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
+	lpDDSurfaceDesc->dwWidth = mode->w;
+	lpDDSurfaceDesc->dwHeight = mode->h;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
+	lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
 
-		if (!lpEnumModesCallback(&ddsd, lpContext)) {
-			status = DDERR_GENERIC;
-		}
-	}
-	SDL_free(modes);
+	return DD_OK;
+}
 
-	return status;
+HRESULT DirectDrawImpl::RestoreDisplayMode()
+{
+	return DD_OK;
 }
 
-HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
+HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
 {
-	if (lpDDDriverCaps) {
-		memset(lpDDDriverCaps, 0, sizeof(DDCAPS));
-		lpDDDriverCaps->dwSize = sizeof(DDCAPS);
-		lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
-	}
+	if (hWnd) {
+		bool fullscreen;
+		if ((dwFlags & DDSCL_NORMAL) == DDSCL_NORMAL) {
+			fullscreen = false;
+		} else if ((dwFlags & DDSCL_FULLSCREEN) == DDSCL_FULLSCREEN) {
+			fullscreen = true;
+		} else {
+			return DDERR_INVALIDPARAMS; 
path: miniwin/miniwin/src/miniwin_ddraw.cpp
user: login: AJenbo
body: ```suggestion
		}
		else if ((dwFlags & DDSCL_FULLSCREEN) == DDSCL_FULLSCREEN) {
			fullscreen = true;
		}
		else {
			return DDERR_INVALIDPARAMS;
```
created_at: 2025-05-16T19:13:15Z
author_association: COLLABORATOR

PR comments:
user: login: foxtacles
created_at: 2025-05-16T16:52:34Z
body: CC @AJenbo 
author_association: MEMBER
user: login: AJenbo
created_at: 2025-05-16T20:05:53Z
body: Nice cleanup
author_association: COLLABORATOR