2020
2121#include <stdarg.h>
2222#include <string.h>
23- #include <stdlib.h>
2423#include "windef.h"
2524#include "winbase.h"
2625#include "wingdi.h"
2928#include "wine/wingdi16.h"
3029#include "windows/dispdib.h"
3130#include "wine/debug.h"
31+ #include "../krnl386/dosexe.h"
3232
3333WINE_DEFAULT_DEBUG_CHANNEL (ddraw );
3434
35- static HTASK owner = 0 ;
35+ #define width 320
36+
37+ static HTASK16 owner = 0 ;
3638static HDC dddc ;
3739static int height ;
3840static HWND ddhwnd ;
41+ static INTPROC oldproc ;
42+ static OUTPROC oldout [0x20 ];
43+ static INPROC oldin [0x20 ];
44+ static HANDLE running = 0 ;
45+ static BOOL vsync ;
46+ static LPVOID vram ;
3947
40- LRESULT CALLBACK ddwndproc (HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
48+ static LRESULT CALLBACK ddwndproc (HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
4149{
42- HWND parhwnd = GetWindowLongA (hwnd , GWL_HWNDPARENT );
50+ HWND parhwnd = ( HWND ) GetWindowLongA (hwnd , GWL_HWNDPARENT );
4351 switch (uMsg )
4452 {
4553 case WM_KEYDOWN :
@@ -54,13 +62,150 @@ LRESULT CALLBACK ddwndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5462 case WM_TIMER :
5563 case WM_SETFOCUS :
5664 case WM_KILLFOCUS :
57- return CallWindowProcA (GetWindowLongA (parhwnd , GWL_WNDPROC ), parhwnd , uMsg , wParam , lParam );
65+ case WM_CLOSE :
66+ return CallWindowProcA ((WNDPROC )GetWindowLongA (parhwnd , GWL_WNDPROC ), parhwnd , uMsg , wParam , lParam );
5867 }
5968 if (uMsg >= MM_JOY1MOVE )
60- return CallWindowProcA (GetWindowLongA (parhwnd , GWL_WNDPROC ), parhwnd , uMsg , wParam , lParam );
69+ return CallWindowProcA (( WNDPROC ) GetWindowLongA (parhwnd , GWL_WNDPROC ), parhwnd , uMsg , wParam , lParam );
6170 return DefWindowProcA (hwnd , uMsg , wParam , lParam );
6271}
6372
73+ static void CALLBACK retrace_cb (LPVOID arg , DWORD low , DWORD high )
74+ {
75+ vsync = TRUE;
76+ if (WaitForSingleObject (running , 0 ))
77+ {
78+ SetEvent (running );
79+ ExitThread (0 );
80+ }
81+ RECT ddrect ;
82+ GetClientRect (ddhwnd , & ddrect );
83+ HDC dc = GetDC (ddhwnd );
84+ SetBitmapBits (GetCurrentObject (dddc , OBJ_BITMAP ), width * height , vram );
85+ StretchBlt (dc , 0 , 0 , ddrect .right , ddrect .bottom , dddc , 0 , 0 , width , height , SRCCOPY );
86+ ReleaseDC (ddhwnd , dc );
87+ }
88+
89+ static DWORD CALLBACK retrace_th (LPVOID arg )
90+ {
91+ LARGE_INTEGER when ;
92+ HANDLE timer ;
93+
94+ if (!(timer = CreateWaitableTimerA ( NULL , FALSE, NULL ))) return 0 ;
95+
96+ when .u .LowPart = when .u .HighPart = 0 ;
97+ SetWaitableTimer (timer , & when , 17 , retrace_cb , arg , FALSE);
98+ for (;;) SleepEx (INFINITE , TRUE);
99+ }
100+
101+ static void start_retrace_timer ()
102+ {
103+ if (running ) return ;
104+ if (height == 240 ) FIXME ("240 px height doesn't work properly with direct fb access\n" );
105+ running = CreateEventA (NULL , TRUE, TRUE, NULL );
106+ vram = MapSL ((DWORD )GetProcAddress16 (GetModuleHandle16 ("KERNEL" ), (LPCSTR )174 ) << 16 );
107+ CloseHandle (CreateThread (NULL , 0 , retrace_th , NULL , 0 , NULL ));
108+ }
109+
110+ static void WINAPI ddInt10Handler (CONTEXT * context )
111+ {
112+ if (GetCurrentTask () != owner )
113+ {
114+ oldproc (context );
115+ return ;
116+ }
117+
118+ switch (AH_reg (context ))
119+ {
120+ case 0x00 :
121+ start_retrace_timer ();
122+ switch (AL_reg (context ))
123+ {
124+ case 0x13 :
125+ height = 200 ;
126+ break ;
127+ default :
128+ FIXME ("Vid mode %#x not supported\n" , AL_reg (context ));
129+ break ;
130+ }
131+ break ;
132+ default :
133+ FIXME ("Int 10 func: %#x unimplemented\n" , AH_reg (context ));
134+ break ;
135+ }
136+ }
137+
138+ static DWORD WINAPI ddVGAinHandler (int port , int size )
139+ {
140+ if (GetCurrentTask () != owner )
141+ return oldin [port - 0x3c0 ] ? oldin [port - 0x3c0 ](port , size ) : 0 ;
142+
143+ DWORD ret = -1 ;
144+
145+ switch (port )
146+ {
147+ case 0x3da :
148+ {
149+ start_retrace_timer ();
150+ ret = vsync ? 9 : 0 ;
151+ vsync = FALSE;
152+ break ;
153+ }
154+ default :
155+ FIXME ("vga port %#x unimplemented\n" , port );
156+ break ;
157+ }
158+ return ret ;
159+ }
160+
161+ static void WINAPI ddVGAoutHandler (int port , int size , DWORD value )
162+ {
163+ if (GetCurrentTask () != owner )
164+ {
165+ if (oldout [port - 0x3c0 ])
166+ oldout [port - 0x3c0 ](port , size , value );
167+ return ;
168+ }
169+
170+ if ((port & ~3 ) != 0x3c8 ) start_retrace_timer ();
171+
172+ static BYTE dacidx ;
173+ static BYTE dacclr = 0 ;
174+
175+ switch (port )
176+ {
177+ case 0x3c8 :
178+ dacidx = value & 0xff ;
179+ dacclr = 0 ;
180+ if (size == 1 ) break ;
181+ value >>= 8 ;
182+ case 0x3c9 :
183+ {
184+ RGBQUAD color ;
185+ GetDIBColorTable (dddc , dacidx , 1 , & color );
186+ switch (dacclr ++ )
187+ {
188+ case 0 :
189+ color .rgbRed = (BYTE )value << 2 ;
190+ break ;
191+ case 1 :
192+ color .rgbGreen = (BYTE )value << 2 ;
193+ break ;
194+ case 2 :
195+ color .rgbBlue = (BYTE )value << 2 ;
196+ dacclr = 0 ;
197+ break ;
198+ }
199+ SetDIBColorTable (dddc , dacidx , 1 , & color );
200+ if (!dacclr ) dacidx ++ ;
201+ break ;
202+ }
203+ default :
204+ FIXME ("vga port %#x unimplemented\n" , port );
205+ break ;
206+ }
207+ }
208+
64209/*********************************************************************
65210 * DisplayDib (DISPDIB.1)
66211 *
@@ -95,7 +240,7 @@ WORD WINAPI DisplayDib(
95240 WORD wFlags /* [in] */
96241 )
97242{
98- HTASK task = GetCurrentTask ();
243+ HTASK16 task = GetCurrentTask ();
99244 if ((wFlags & DISPLAYDIB_BEGIN ) && !owner )
100245 {
101246 switch (wFlags & DISPLAYDIB_MODE )
@@ -114,34 +259,41 @@ WORD WINAPI DisplayDib(
114259 if (!GetClassInfoA (GetModuleHandleA (NULL ), "DispDibClass" , & wc ))
115260 {
116261 WNDCLASSA ddwc = {0 };
117- ddwc .style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE ;
262+ ddwc .style = CS_HREDRAW | CS_VREDRAW ;
118263 ddwc .lpfnWndProc = ddwndproc ;
119264 ddwc .hInstance = GetModuleHandleA (NULL );
120265 ddwc .lpszClassName = "DispDibClass" ;
121266 if (!RegisterClassA (& ddwc ))
122267 return DISPLAYDIB_NOTSUPPORTED ;
123268 }
124269
270+ owner = task ;
125271 dddc = CreateCompatibleDC (0 );
126272 BITMAPINFO * bmap = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY , 256 * 4 + sizeof (BITMAPINFOHEADER ));
127273 VOID * section ;
128274 bmap -> bmiHeader .biSize = sizeof (BITMAPINFOHEADER );
129- bmap -> bmiHeader .biWidth = 320 ;
275+ bmap -> bmiHeader .biWidth = width ;
130276 bmap -> bmiHeader .biHeight = height ;
131277 bmap -> bmiHeader .biPlanes = 1 ;
132278 bmap -> bmiHeader .biBitCount = 8 ;
133279 HBITMAP ddbmap = CreateDIBSection (dddc , bmap , DIB_RGB_COLORS , & section , NULL , 0 );
134280 HeapFree (GetProcessHeap (), 0 , bmap );
135281 SelectObject (dddc , ddbmap );
136282
137- char title [32 ] = "DispDib " ;
283+ char title [32 ] = "\0 " ;
138284 HWND parhwnd = GetActiveWindow ();
139285 GetWindowTextA (parhwnd , title , 32 );
286+ if (title [0 ] == '\0' ) GetModuleName16 (GetCurrentTask (), title , 32 );
140287 ddhwnd = CreateWindowExA (0 , "DispDibClass" , title , WS_OVERLAPPEDWINDOW | WS_VISIBLE , CW_USEDEFAULT ,
141288 CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , parhwnd , NULL , GetModuleHandleA (NULL ), NULL );
142289 if (!ddhwnd )
290+ {
291+ owner = 0 ;
143292 return DISPLAYDIB_NOTSUPPORTED ;
144- owner = task ;
293+ }
294+ oldproc = DOSVM_SetBuiltinVector (0x10 , ddInt10Handler );
295+ for (int i = 0 ; i < 0x20 ; i ++ )
296+ DOSVM_setportcb (ddVGAoutHandler , ddVGAinHandler , i + 0x3c0 , & oldout [i ], & oldin [i ]);
145297 return DISPLAYDIB_NOERROR ;
146298 }
147299 else if ((owner != task ) || !owner )
@@ -150,14 +302,24 @@ WORD WINAPI DisplayDib(
150302 {
151303 DestroyWindow (ddhwnd );
152304 DeleteDC (dddc );
305+ DOSVM_SetBuiltinVector (0x10 , oldproc );
306+ for (int i = 0 ; i < 0x20 ; i ++ )
307+ DOSVM_setportcb (oldout [i ], oldin [i ], i + 0x3c0 , & oldout [i ], & oldin [i ]);
308+ if (running )
309+ {
310+ ResetEvent (running );
311+ WaitForSingleObject (running , INFINITE );
312+ CloseHandle (running );
313+ running = 0 ;
314+ }
153315 owner = 0 ;
154316 return DISPLAYDIB_NOERROR ;
155317 }
156318 if (!(wFlags & DISPLAYDIB_NOPALETTE ))
157319 {
158320 if (!lpbi )
159321 return DISPLAYDIB_INVALIDDIB ;
160- SetDIBColorTable (dddc , 0 , lpbi -> bmiHeader .biClrUsed , & lpbi -> bmiColors );
322+ SetDIBColorTable (dddc , 0 , lpbi -> bmiHeader .biClrUsed , ( RGBQUAD * ) & lpbi -> bmiColors );
161323 }
162324 if (!(wFlags & /*DISPLAYDIB_NOIMAGE*/ 0x80 ))
163325 {
@@ -166,8 +328,8 @@ WORD WINAPI DisplayDib(
166328 RECT ddrect ;
167329 GetClientRect (ddhwnd , & ddrect );
168330 HDC dc = GetDC (ddhwnd );
169- SetDIBitsToDevice (dddc , 0 , 0 , 320 , height , 0 , 0 , 0 , 320 , lpBits , lpbi , DIB_RGB_COLORS );
170- StretchBlt (dc , 0 , 0 , ddrect .right , ddrect .bottom , dddc , 0 , 0 , 320 , height , SRCCOPY );
331+ SetDIBitsToDevice (dddc , 0 , 0 , width , height , 0 , 0 , 0 , height , lpBits , lpbi , DIB_RGB_COLORS );
332+ StretchBlt (dc , 0 , 0 , ddrect .right , ddrect .bottom , dddc , 0 , 0 , width , height , SRCCOPY );
171333 ReleaseDC (ddhwnd , dc );
172334 }
173335 return DISPLAYDIB_NOERROR ;
0 commit comments