1 /*
2  * UAE - The Un*x Amiga Emulator
3  *
4  * Win32 Drawing and DirectX interface
5  *
6  * Copyright 1997-1998 Mathias Ortmann
7  * Copyright 1997-2000 Brian King
8  */
9 
10 #include "sysconfig.h"
11 
12 #include <stdlib.h>
13 #include <stdarg.h>
14 
15 #include <signal.h>
16 #include <io.h>
17 
18 #include <windows.h>
19 #include <commctrl.h>
20 #include <stdio.h>
21 
22 #include "sysdeps.h"
23 #include "options.h"
24 #include "gensound.h"
25 #include "uae.h"
26 #include "memory.h"
27 #include "custom.h"
28 #include "events.h"
29 #include "xwin.h"
30 #include "keyboard.h"
31 #include "drawing.h"
32 #include "picasso96.h"
33 #include "osdep/win32.h"
34 #include "osdep/win32gui.h"
35 #include "osdep/win32gfx.h"
36 #include "sounddep/sound.h"
37 
38 /* Local globals */
39 static uae_u32 current_width, current_height, current_depth;
40 static int fullscreen = 0; /* fullscreen mode */
41 static int window_width = 900, window_height = 720, window_depth; /* target resolution */
42 static int usedirect = 0; /* direct to dx surface (fullscreen or overlay) */
43 static int overlay = 1; /* use overlay surface */
44 static int needs_direct; /* is overlay or fullscreen mode required */
45 static int display_change_requested = 0;
46 static int mapping_is_mainscreen = 0;
47 static BOOL bInitDone = FALSE; //?????JGI
48 
49 int screen_is_picasso = 0;
50 
51 static BOOL bJustClosedWithActiveMouse = FALSE;
52 
WIN32GFX_IsPicassoScreen(void)53 int WIN32GFX_IsPicassoScreen( void )
54 {
55     return screen_is_picasso;
56 }
57 
WIN32GFX_DisablePicasso(void)58 void WIN32GFX_DisablePicasso( void )
59 {
60     picasso_requested_on = 0;
61     picasso_on = 0;
62 }
63 
WIN32GFX_EnablePicasso(void)64 void WIN32GFX_EnablePicasso( void )
65 {
66     picasso_requested_on = 1;
67 }
68 
WIN32GFX_DisplayChangeRequested(void)69 void WIN32GFX_DisplayChangeRequested( void )
70 {
71     display_change_requested = 1;
72 }
73 
WIN32GFX_IsFullScreen(void)74 int WIN32GFX_IsFullScreen( void )
75 {
76     return fullscreen;
77 }
78 
WIN32GFX_GetWidth(void)79 int WIN32GFX_GetWidth( void )
80 {
81     return current_width;
82 }
83 
WIN32GFX_GetHeight(void)84 int WIN32GFX_GetHeight( void )
85 {
86     return current_height;
87 }
88 
89 #ifdef _WIN32_WCE
90 int nr_joysticks = 1;
91 
init_joystick(void)92 void init_joystick( void )
93 {
94 }
95 
read_joystick(int nr,unsigned int * dir,int * button)96 void read_joystick (int nr, unsigned int *dir, int *button)
97 {
98     *dir = *button = 0;
99 
100     if( nr < nr_joysticks )
101     {
102 
103     }
104 }
105 
close_joystick(void)106 void close_joystick( void )
107 {
108 }
109 
check_prefs_changed_gfx(void)110 int check_prefs_changed_gfx (void)
111 {
112     return 0;
113 }
114 
graphics_init(void)115 int graphics_init( void )
116 {
117     return 1;
118 }
119 
graphics_setup(void)120 int graphics_setup( void )
121 {
122     return 1;
123 }
124 
graphics_leave(void)125 void graphics_leave( void )
126 {
127 }
128 
unlockscr(void)129 void unlockscr( void )
130 {
131 }
132 
lockscr(void)133 int lockscr( void )
134 {
135     return 0;
136 }
137 
flush_screen(int a,int b)138 void flush_screen( int a, int b )
139 {
140 }
141 
flush_block(int a,int b)142 void flush_block( int a, int b )
143 {
144 }
145 
flush_line(int a)146 void flush_line( int a )
147 {
148 }
149 
WIN32GFX_PaletteChange(void)150 void WIN32GFX_PaletteChange( void )
151 {
152 }
153 
154 #else
155 #include "osdep/dxwrap.h"
156 
157 #ifdef __GNUC__
158 int __cdecl _fcloseall( void );
159 #endif
160 
161 /* Local Globals */
162 static UINT current_pixbytes;
163 static LPPALETTEENTRY current_palette = NULL;
164 
165 static BOOL doInit (void);
166 static void close_windows (void);
167 
168 uae_u32 default_freq = 0;
169 
170 HWND hStatusWnd = NULL;
171 HINSTANCE hDDraw = NULL;
172 
173 /* For the DX_Invalidate() and gfx_unlock_picasso() functions */
174 static int p96_double_buffer_first, p96_double_buffer_last, p96_double_buffer_needs_flushing = 0;
175 
176 static char scrlinebuf[4096];	/* this is too large, but let's rather play on the safe side here */
177 
rgbformat_bits(RGBFTYPE t)178 static int rgbformat_bits (RGBFTYPE t)
179 {
180     unsigned long f = 1 << t;
181     return ((f & RGBMASK_8BIT) != 0 ? 8
182 	    : (f & RGBMASK_15BIT) != 0 ? 15
183 	    : (f & RGBMASK_16BIT) != 0 ? 16
184 	    : (f & RGBMASK_24BIT) != 0 ? 24
185 	    : (f & RGBMASK_32BIT) != 0 ? 32
186 	    : 0);
187 }
188 
set_ddraw(int width,int height,int wantfull,int wantoverlay,int bits,LPPALETTEENTRY pal)189 static int set_ddraw (int width, int height, int wantfull, int wantoverlay, int bits, LPPALETTEENTRY pal)
190 {
191     HRESULT ddrval;
192 
193     bits = (bits + 7) & ~7;
194 
195     ddrval = DirectDraw_SetCooperativeLevel( hAmigaWnd, wantfull );
196     if (ddrval != DD_OK)
197 	goto oops;
198 
199     if (wantfull)
200     {
201 	write_log ( "set_ddraw: Trying %dx%d, %d bits\n", width, height, bits );
202 	ddrval = DirectDraw_SetDisplayMode( width, height, bits, 0 );
203 	if (ddrval != DD_OK)
204 	{
205 	    write_log ( "set_ddraw: Couldn't SetDisplayMode()\n" );
206 	    goto oops;
207 	}
208 
209 	ddrval = DirectDraw_GetDisplayMode();
210 	if (ddrval != DD_OK)
211 	{
212 	    write_log ( "set_ddraw: Couldn't GetDisplayMode()\n" );
213 	    goto oops;
214 	}
215     }
216 
217     ddrval = DirectDraw_CreateClipper();
218     if (ddrval != DD_OK)
219     {
220 	write_log ( "set_ddraw: No clipping support\n" );
221 	goto oops;
222     }
223 
224     ddrval = DirectDraw_CreateSurface( width, height );
225     if( ddrval != DD_OK )
226     {
227 	write_log ( "set_ddraw: Couldn't CreateSurface() for primary because %s.\n", DirectDraw_ErrorString( ddrval ) );
228 	goto oops;
229     }
230 
231     if( wantoverlay )
232     {
233 	if( !currprefs.win32_no_overlay && ( DirectDraw_GetPrimaryBitCount() != bits ) )
234 	{
235 	    ddrval = DirectDraw_CreateOverlaySurface( width, height, bits );
236 	    if( ddrval != DD_OK )
237 	    {
238 		write_log ( "set_ddraw: Couldn't CreateOverlaySurface(%d,%d,%d) because %s.\n", width, height, bits, DirectDraw_ErrorString( ddrval ) );
239 		overlay = 0;
240 	    }
241 	}
242 	else
243 	{
244 	    overlay = 0;
245 	}
246     }
247 
248     DirectDraw_ClearSurfaces();
249 
250     if( !DirectDraw_DetermineLocking( wantfull ) )
251     {
252 	write_log ( "set_ddraw: Couldn't determine locking.\n" );
253 	goto oops;
254     }
255 
256     ddrval = DirectDraw_SetClipper( hAmigaWnd );
257 
258     if (ddrval != DD_OK)
259     {
260 	write_log ( "set_ddraw: Couldn't SetHWnd()\n" );
261 	    goto oops;
262     }
263 
264     current_pixbytes = DirectDraw_GetBytesPerPixel();
265 
266     write_log ( "set_ddraw() called, and is %dx%d@%d-bytes\n", width, height, current_pixbytes );
267 
268     if (current_pixbytes == 1) {
269 	current_palette = pal;
270 	ddrval = DirectDraw_CreatePalette( pal );
271 	if (ddrval != DD_OK)
272 	{
273 	    write_log ( "set_ddraw: Couldn't CreatePalette()\n" );
274 		goto oops;
275 	}
276     }
277 
278     return 1;
279 
280   oops:
281     if( wantfull )
282 	DirectDraw_SetCooperativeLevel( hAmigaWnd, 0 ); /* No full-screen, so that people can see our gui_message() */
283     gui_message("set_ddraw(): DirectDraw initialization failed with %s/%d\n", DirectDraw_ErrorString( ddrval ), ddrval);
284     return 0;
285 }
286 
287 struct win32_displaymode *win32_displaymode_list;
288 
modesCallback(LPDDSURFACEDESC2 modeDesc,LPVOID context)289 HRESULT CALLBACK modesCallback( LPDDSURFACEDESC2 modeDesc, LPVOID context )
290 {
291     struct win32_displaymode **dmpp;
292     RGBFTYPE colortype;
293 
294     colortype = DirectDraw_GetSurfacePixelFormat( modeDesc );
295     if (colortype == RGBFB_NONE || colortype == RGBFB_R8G8B8 || colortype == RGBFB_B8G8R8 )
296 	return DDENUMRET_OK;
297 
298     dmpp = &win32_displaymode_list;
299     while (*dmpp != 0) {
300 	if ((*dmpp)->width == modeDesc->dwWidth
301 	    && (*dmpp)->height == modeDesc->dwHeight
302 	    && (*dmpp)->refreshrate == modeDesc->dwRefreshRate)
303 	    break;
304 	dmpp = &(*dmpp)->next;
305     }
306 
307     if (*dmpp == 0) {
308 	*dmpp = (struct win32_displaymode *)xmalloc (sizeof **dmpp);
309 	(*dmpp)->next = 0;
310 	(*dmpp)->width = modeDesc->dwWidth;
311 	(*dmpp)->height = modeDesc->dwHeight;
312 	(*dmpp)->refreshrate = modeDesc->dwRefreshRate;
313 	(*dmpp)->colormodes = 0;
314     }
315     (*dmpp)->colormodes |= 1 << colortype;
316     return DDENUMRET_OK;
317 }
318 
cleanup_modes(void)319 static void cleanup_modes( void )
320 {
321     struct win32_displaymode *temp = NULL, *dmpp = win32_displaymode_list;
322 
323     while( dmpp )
324     {
325 	temp = dmpp;
326 	dmpp = dmpp->next;
327 	free( temp );
328     }
329 }
330 
331 static int our_possible_depths[] = { 8, 15, 16, 24, 32 };
332 
WIN32GFX_FigurePixelFormats(RGBFTYPE colortype)333 RGBFTYPE WIN32GFX_FigurePixelFormats( RGBFTYPE colortype )
334 {
335     HRESULT ddrval;
336     struct win32_displaymode *dm;
337     int got_16bit_mode = 0;
338     int window_created = 0;
339 
340     if( colortype == 0 ) /* Need to query a 16-bit display mode for its pixel-format.  Do this by opening such a screen */
341     {
342 	hAmigaWnd = CreateWindowEx (WS_EX_TOPMOST,
343 			       "AmigaPowah", VersionStr,
344 			       WS_VISIBLE | WS_POPUP,
345 			       CW_USEDEFAULT, CW_USEDEFAULT,
346 			       1,//GetSystemMetrics (SM_CXSCREEN),
347 			       1,//GetSystemMetrics (SM_CYSCREEN),
348 			       0, NULL, 0, NULL);
349 	if( hAmigaWnd )
350 	{
351 	    window_created = 1;
352 	    ddrval = DirectDraw_SetCooperativeLevel( hAmigaWnd, TRUE ); /* TRUE indicates full-screen */
353 	    if( ddrval != DD_OK )
354 	    {
355 		write_log ( "WIN32GFX_FigurePixelFormats: ERROR -  %s\n", DirectDraw_ErrorString(ddrval) );
356 		gui_message( "WIN32GFX_FigurePixelFormats: ERROR - %s\n", DirectDraw_ErrorString(ddrval) );
357 		goto out;
358 	    }
359 	}
360 	else
361 	{
362 	    write_log ( "WIN32GFX_FigurePixelFormats: ERROR - test-window could not be created.\n" );
363 	    gui_message( "WIN32GFX_FigurePixelFormats: ERROR - test-window could not be created.\n" );
364 	}
365     }
366     else
367     {
368 	got_16bit_mode = 1;
369     }
370 
371     for (dm = win32_displaymode_list; dm != 0; dm = dm->next)
372     {
373 	if (!got_16bit_mode)
374 	{
375 	    write_log ("figure_pixel_formats: Attempting %dx%d: ", dm->width, dm->height);
376 
377 	    ddrval = DirectDraw_SetDisplayMode( dm->width, dm->height, 16, 0 ); /* 0 for default freq */
378 	    if (ddrval != DD_OK)
379 		continue;
380 
381 	    ddrval = DirectDraw_GetDisplayMode();
382 	    if (ddrval != DD_OK)
383 		continue;
384 
385 	    colortype = DirectDraw_GetPixelFormat();
386 	    if (colortype != RGBFB_NONE)
387 	    {
388 		write_log ("%d ", our_possible_depths[2]);
389 
390 		/* Clear the 16-bit information, and get the real stuff! */
391 		dm->colormodes &= ~(RGBFF_R5G6B5PC|RGBFF_R5G5B5PC|RGBFF_R5G6B5|RGBFF_R5G5B5|RGBFF_B5G6R5PC|RGBFF_B5G5R5PC);
392 		dm->colormodes |= 1 << colortype;
393 		got_16bit_mode = 1;
394 		write_log ( "Got real 16-bit colour-depth information: 0x%x\n", colortype );
395 	    }
396 	}
397 	else if (dm->colormodes & (RGBFF_R5G6B5PC|RGBFF_R5G5B5PC|RGBFF_R5G6B5|RGBFF_R5G5B5|RGBFF_B5G6R5PC|RGBFF_B5G5R5PC) )
398 	{
399 	    /* Clear the 16-bit information, and set the real stuff! */
400 	    dm->colormodes &= ~(RGBFF_R5G6B5PC|RGBFF_R5G5B5PC|RGBFF_R5G6B5|RGBFF_R5G5B5|RGBFF_B5G6R5PC|RGBFF_B5G5R5PC);
401 	    dm->colormodes |= 1 << colortype;
402 	}
403     }
404     out:
405     if( window_created )
406     {
407 	Sleep( 2000 );
408 	DestroyWindow( hAmigaWnd );
409 	hAmigaWnd = NULL;
410     }
411     return colortype;
412 }
413 
414 /* DirectX will fail with "Mode not supported" if we try to switch to a full
415  * screen mode that doesn't match one of the dimensions we got during enumeration.
416  * So try to find a best match for the given resolution in our list.  */
WIN32GFX_AdjustScreenmode(uae_u32 * pwidth,uae_u32 * pheight,uae_u32 * ppixbits)417 int WIN32GFX_AdjustScreenmode( uae_u32 *pwidth, uae_u32 *pheight, uae_u32 *ppixbits )
418 {
419     struct win32_displaymode *best;
420     uae_u32 selected_mask = (*ppixbits == 8 ? RGBMASK_8BIT
421 			     : *ppixbits == 15 ? RGBMASK_15BIT
422 			     : *ppixbits == 16 ? RGBMASK_16BIT
423 			     : *ppixbits == 24 ? RGBMASK_24BIT
424 			     : RGBMASK_32BIT);
425     int pass, i = 0, index = 0;
426 
427     for (pass = 0; pass < 2; pass++)
428     {
429 	struct win32_displaymode *dm;
430 	uae_u32 mask = (pass == 0
431 			? selected_mask
432 			: RGBMASK_8BIT | RGBMASK_15BIT | RGBMASK_16BIT | RGBMASK_24BIT | RGBMASK_32BIT); /* %%% - BERND, were you missing 15-bit here??? */
433 	i = 0;
434 	index = 0;
435 
436 	best = win32_displaymode_list;
437 	dm = best->next;
438 
439 	while (dm != 0)
440 	{
441 	    if ((dm->colormodes & mask) != 0)
442 	    {
443 		if (dm->width <= best->width && dm->height <= best->height
444 		    && dm->width >= *pwidth && dm->height >= *pheight)
445 		{
446 		    best = dm;
447 		    index = i;
448 		}
449 		if (dm->width >= best->width && dm->height >= best->height
450 		    && dm->width <= *pwidth && dm->height <= *pheight)
451 		{
452 		    best = dm;
453 		    index = i;
454 		}
455 	    }
456 	    dm = dm->next;
457 	    i++;
458 	}
459 	if (best->width == *pwidth && best->height == *pheight)
460 	{
461 	    selected_mask = mask; /* %%% - BERND, I added this - does it make sense?  Otherwise, I'd specify a 16-bit display-mode for my
462 				     Workbench (using -H 2, but SHOULD have been -H 1), and end up with an 8-bit mode instead*/
463 	    break;
464 	}
465     }
466     *pwidth = best->width;
467     *pheight = best->height;
468     if( best->colormodes & selected_mask )
469 	return index;
470 
471     /* Ordering here is done such that 16-bit is preferred, followed by 15-bit, 8-bit, 32-bit and 24-bit */
472     if (best->colormodes & RGBMASK_16BIT)
473 	*ppixbits = 16;
474     else if (best->colormodes & RGBMASK_15BIT) /* %%% - BERND, this possibility was missing? */
475 	*ppixbits = 15;
476     else if (best->colormodes & RGBMASK_8BIT)
477 	*ppixbits = 8;
478     else if (best->colormodes & RGBMASK_32BIT)
479 	*ppixbits = 32;
480     else if (best->colormodes & RGBMASK_24BIT)
481 	*ppixbits = 24;
482     else
483 	index = -1;
484 
485     return index;
486 }
487 
flush_line(int lineno)488 void flush_line( int lineno )
489 {
490 
491 }
492 
flush_block(int a,int b)493 void flush_block (int a, int b)
494 {
495 
496 }
497 
flush_screen(int a,int b)498 void flush_screen (int a, int b)
499 {
500     if( DirectDraw_GetLockableType() == secondary_surface )
501     {
502 	if( fullscreen )
503 	{
504 	    if( DX_Flip() == 0 )
505 	    {
506 		DX_Blit( 0, a, 0, a, current_width, b - a + 1, BLIT_SRC );
507 	    }
508 	}
509 	else
510 	{
511 	    DX_Blit( 0, a, 0, a, current_width, b - a + 1, BLIT_SRC );
512 	}
513     }
514 }
515 
dolock(void)516 static uae_u8 *dolock (void)
517 {
518     char *surface = NULL, *oldsurface;
519 
520     if( !DirectDraw_SurfaceLock( lockable_surface ) )
521 	return 0;
522 
523     surface = DirectDraw_GetSurfacePointer();
524     oldsurface = gfxvidinfo.bufmem;
525     gfxvidinfo.bufmem = surface;
526     if (surface != oldsurface && ! screen_is_picasso)
527     {
528 	write_log ("Need to init_row_map\n");
529 	init_row_map ();
530     }
531 
532     clear_inhibit_frame (IHF_WINDOWHIDDEN);
533     return surface;
534 }
535 
lockscr(void)536 int lockscr( void )
537 {
538     return dolock() != 0;
539 }
540 
gfx_lock_picasso(void)541 uae_u8 *gfx_lock_picasso (void)
542 {
543     return dolock ();
544 }
545 
gfx_unlock_picasso(void)546 void gfx_unlock_picasso (void)
547 {
548     DirectDraw_SurfaceUnlock();
549     if( p96_double_buffer_needs_flushing )
550     {
551 	/* Here, our flush_block() will deal with a offscreen-plain (back-buffer) to visible-surface (front-buffer) */
552 	if( DirectDraw_GetLockableType() == secondary_surface )
553 	{
554 	    BOOL relock = FALSE;
555 	    if( DirectDraw_IsLocked() )
556 	    {
557 		relock = TRUE;
558 		unlockscr();
559 	    }
560 	    DX_Blit( 0, p96_double_buffer_first,
561 		     0, p96_double_buffer_first,
562 		     current_width, p96_double_buffer_last - p96_double_buffer_first + 1,
563 		     BLIT_SRC );
564 	    if( relock )
565 	    {
566 		lockscr();
567 	    }
568 	}
569 	p96_double_buffer_needs_flushing = 0;
570     }
571 }
572 
close_hwnds(void)573 static void close_hwnds( void )
574 {
575     if (hStatusWnd)
576     {
577 	ShowWindow( hStatusWnd, SW_HIDE );
578 	DestroyWindow (hStatusWnd);
579     }
580     if (hAmigaWnd)
581     {
582 	ShowWindow( hAmigaWnd, SW_HIDE );
583 	DestroyWindow (hAmigaWnd);
584     }
585     if (hMainWnd)
586     {
587 	ShowWindow( hMainWnd, SW_HIDE );
588 	DestroyWindow (hMainWnd);
589     }
590 
591     hMainWnd = 0;
592     hStatusWnd = 0;
593     hAmigaWnd = 0;
594 }
595 
open_windows(void)596 static int open_windows (void)
597 {
598     static BOOL bFirstTime = TRUE;
599     char tmpstr[300];
600 
601     char *fs_warning = 0;
602     RGBFTYPE colortype;
603 
604     current_pixbytes = 0;
605 
606     in_sizemove = 0;
607     fixup_prefs_dimensions (&currprefs);
608 
609     if( !DirectDraw_Start() )
610 	return 0;
611     if( DirectDraw_GetDisplayMode() != DD_OK )
612 	return 0;
613     colortype = DirectDraw_GetPixelFormat();
614     write_log ("Ct: %08lx, picasso_vidinfo.selected_rgbformat %08lx\n", (unsigned long)colortype,
615 	    picasso_vidinfo.selected_rgbformat);
616 
617     if (screen_is_picasso) {
618 	fullscreen = currprefs.gfx_pfullscreen;
619 	window_width = current_width = picasso_vidinfo.width;
620 	window_height = current_height = picasso_vidinfo.height;
621 	window_depth = current_depth = rgbformat_bits (picasso_vidinfo.selected_rgbformat);
622     } else {
623 	fullscreen = currprefs.gfx_afullscreen;
624 	window_width = current_width = currprefs.gfx_width;
625 	window_height = current_height = currprefs.gfx_height;
626 	window_depth = current_depth = (currprefs.color_mode == 0 ? 8
627 			 : currprefs.color_mode == 1 ? 15
628 			 : currprefs.color_mode == 2 ? 16
629 			 : currprefs.color_mode == 3 ? 8
630 			 : currprefs.color_mode == 4 ? 8 : 32);
631     }
632 
633     //If screen depth is equal to the desired window_depth then no overlay is needed.
634     if( DirectDraw_GetSurfaceBitCount() == window_depth )
635 	overlay = 0;
636 
637     if (overlay) {
638 	needs_direct = 1;
639     } else {
640 	needs_direct = 0;
641     }
642 
643     if (colortype == RGBFB_NONE && !overlay) {
644 	needs_direct = 1;
645 	fs_warning = "the desktop is running in an unknown color mode.";
646     } else if (colortype == RGBFB_CLUT && !overlay) {
647 	needs_direct = 1;
648 	fs_warning = "the desktop is running in 8 bit color depth, which UAE can't use in windowed mode.";
649     } else if ( !fullscreen && ( current_width >= DirectDraw_CurrentWidth() || current_height >= DirectDraw_CurrentHeight() ) ) {
650 	needs_direct = 1;
651 	fs_warning = "the desktop is too small for the specified window size.";
652 	overlay = 0; // we're going to go full-screen
653     } else if (screen_is_picasso && !fullscreen &&
654 	      ( picasso_vidinfo.selected_rgbformat != RGBFB_CHUNKY ) &&
655 	      ( picasso_vidinfo.selected_rgbformat != colortype ) &&
656 		overlay )
657     {
658 	needs_direct = 1;
659 	fs_warning = "you selected a Picasso display with a color depth different from that of the desktop and an overlay was unavailable.";
660 	if( !doInit() )
661 	{
662 	    overlay = 0; // we're going to go full-screen
663 	    // doInit in windowed-mode modifies the width/height params, so
664 	    // restore our mucked-up width and height values for full-screen.
665 	    window_width = current_width = picasso_vidinfo.width;
666 	    window_height = current_height = picasso_vidinfo.height;
667 	}
668 	DirectDraw_Release();
669 	close_hwnds();
670 	if( !DirectDraw_Start() )
671 	    return 0;
672     }
673 
674     if( needs_direct && ! usedirect )
675 	usedirect = needs_direct;
676 
677     if( fs_warning && !overlay )
678     {
679 	// Temporarily drop the DirectDraw stuff
680 	DirectDraw_Release();
681 	sprintf (tmpstr, "The selected screen mode can't be displayed in a window, because %s\n"
682 		 "Switching to full-screen display.", fs_warning);
683 	MessageBox (0, tmpstr, "WinUAE", MB_ICONEXCLAMATION | MB_OK);
684 	DirectDraw_Start();
685 	fullscreen = 1;
686     }
687 
688     if (! usedirect)
689 	window_depth = rgbformat_bits (colortype);
690 
691     if( current_depth == 24 )
692     {
693 	if( screen_is_picasso )
694 	    fs_warning = "you've selected a Picasso display with a 24-bit depth, which WinUAE no longer supports.";
695 	else
696 	    fs_warning = "the desktop is running in 24-bit color depth, which WinUAE no longer supports.";
697 	/* Temporarily drop the DirectDraw stuff.  This is necessary, otherwise
698 	 * WinNT will just return 1 for the message box without ever displaying
699 	 * it on the screen.  */
700 	DirectDraw_Release();
701 	sprintf (tmpstr, "WinUAE cannot run because %s", fs_warning);
702 	MessageBox (0, tmpstr, "WinUAE", MB_ICONEXCLAMATION | MB_OK);
703 	return 0;
704     }
705 
706     if (! doInit ())
707 	return 0;
708 
709     if(!WIN32GFX_IsFullScreen() && ( bFirstTime || bJustClosedWithActiveMouse ) )
710     {
711 	bFirstTime = FALSE;
712 	bJustClosedWithActiveMouse = FALSE;
713 	setmouseactive (1);
714     }
715 
716     return 1;
717 }
718 
check_prefs_changed_gfx(void)719 int check_prefs_changed_gfx (void)
720 {
721     if (display_change_requested ||
722 	( currprefs.gfx_afullscreen != changed_prefs.gfx_afullscreen ) ||
723 	( currprefs.gfx_pfullscreen != changed_prefs.gfx_pfullscreen ) )
724     {
725 	display_change_requested = 0;
726 	currprefs.gfx_afullscreen = changed_prefs.gfx_afullscreen;
727 	currprefs.gfx_pfullscreen = changed_prefs.gfx_pfullscreen;
728 	close_windows ();
729 	open_windows ();
730 	return 1;
731     }
732     return 0;
733 }
734 
735 /* Color management */
736 
737 static xcolnr xcol8[4096];
738 static PALETTEENTRY colors256[256];
739 static int ncols256 = 0;
740 
741 static int red_bits, green_bits, blue_bits;
742 static int red_shift, green_shift, blue_shift;
743 
get_color(int r,int g,int b,xcolnr * cnp)744 static int get_color (int r, int g, int b, xcolnr * cnp)
745 {
746     if (ncols256 == 256)
747 	return 0;
748     colors256[ncols256].peRed = r * 0x11;
749     colors256[ncols256].peGreen = g * 0x11;
750     colors256[ncols256].peBlue = b * 0x11;
751     colors256[ncols256].peFlags = 0;
752     *cnp = ncols256;
753     ncols256++;
754     return 1;
755 }
756 
init_colors(void)757 static void init_colors (void)
758 {
759     int i;
760     HRESULT ddrval;
761 
762     if (ncols256 == 0) {
763 	alloc_colors256 (get_color);
764 	memcpy (xcol8, xcolors, sizeof xcol8);
765     }
766 
767     /* init colors */
768 
769     switch( current_pixbytes )
770     {
771 	case 1:
772 	    memcpy (xcolors, xcol8, sizeof xcolors);
773 	    ddrval = DirectDraw_SetPaletteEntries( 0, 256, colors256 );
774 	    if (ddrval != DD_OK)
775 		gui_message ("DX_SetPalette() failed with %s/%d\n", DirectDraw_ErrorString (ddrval), ddrval);
776 	break;
777 
778 	case 2:
779 	case 3:
780 	case 4:
781 	    red_bits = bits_in_mask( DirectDraw_GetPixelFormatBitMask( red_mask ) );
782 	    green_bits = bits_in_mask( DirectDraw_GetPixelFormatBitMask( green_mask ) );
783 	    blue_bits = bits_in_mask( DirectDraw_GetPixelFormatBitMask( blue_mask ) );
784 	    red_shift = mask_shift( DirectDraw_GetPixelFormatBitMask( red_mask ) );
785 	    green_shift = mask_shift( DirectDraw_GetPixelFormatBitMask( green_mask ) );
786 	    blue_shift = mask_shift( DirectDraw_GetPixelFormatBitMask( blue_mask ) );
787 
788 	    alloc_colors64k (red_bits, green_bits, blue_bits, red_shift,
789 			     green_shift, blue_shift);
790 	break;
791     }
792     switch (gfxvidinfo.pixbytes)
793     {
794      case 2:
795 	for (i = 0; i < 4096; i++)
796 	    xcolors[i] = xcolors[i] * 0x00010001;
797 	gfxvidinfo.can_double = 1;
798 	break;
799      case 1:
800 	for (i = 0; i < 4096; i++)
801 	    xcolors[i] = xcolors[i] * 0x01010101;
802 	gfxvidinfo.can_double = 1;
803 	break;
804      default:
805 	gfxvidinfo.can_double = 0;
806 	break;
807     }
808 }
809 
DX_FillResolutions(uae_u16 * ppixel_format)810 int DX_FillResolutions (uae_u16 * ppixel_format)
811 {
812     struct win32_displaymode *dm;
813     int count = 0;
814 
815     *ppixel_format = 0;
816     for (dm = win32_displaymode_list; dm != 0; dm = dm->next) {
817 	*ppixel_format |= dm->colormodes;
818 	if (dm->colormodes & RGBMASK_8BIT) {
819 	    DisplayModes[count].res.width = dm->width;
820 	    DisplayModes[count].res.height = dm->height;
821 	    DisplayModes[count].refresh = default_freq;
822 	    DisplayModes[count].depth = 1;
823 	    count++;
824 	}
825 	if (count >= MAX_PICASSO_MODES)
826 	    break;
827 	if (dm->colormodes & (RGBMASK_16BIT | RGBMASK_15BIT)) {
828 	    DisplayModes[count].res.width = dm->width;
829 	    DisplayModes[count].res.height = dm->height;
830 	    DisplayModes[count].refresh = default_freq;
831 	    DisplayModes[count].depth = 2;
832 	    count++;
833 	}
834 	if (count >= MAX_PICASSO_MODES)
835 	    break;
836 	if (dm->colormodes & RGBMASK_24BIT) {
837 	    DisplayModes[count].res.width = dm->width;
838 	    DisplayModes[count].res.height = dm->height;
839 	    DisplayModes[count].refresh = default_freq;
840 	    DisplayModes[count].depth = 3;
841 	    count++;
842 	}
843 	if (count >= MAX_PICASSO_MODES)
844 	    break;
845 	if (dm->colormodes & RGBMASK_32BIT) {
846 	    DisplayModes[count].res.width = dm->width;
847 	    DisplayModes[count].res.height = dm->height;
848 	    DisplayModes[count].refresh = default_freq;
849 	    DisplayModes[count].depth = 4;
850 	    count++;
851 	}
852 	if (count >= MAX_PICASSO_MODES)
853 	    break;
854     }
855     return count;
856 }
857 
DX_SetPalette(int start,int count)858 void DX_SetPalette (int start, int count)
859 {
860     HRESULT ddrval;
861 
862     if( !screen_is_picasso )
863 	return;
864 
865     if( picasso96_state.RGBFormat != RGBFB_CHUNKY )
866     {
867 	/* notice_screen_contents_lost(); */
868 	return;
869     }
870 
871     if (picasso_vidinfo.pixbytes != 1)
872     {
873 	/* write_log ("DX Setpalette emulation\n"); */
874 	/* This is the case when we're emulating a 256 color display.  */
875 	while (count-- > 0)
876 	{
877 	    int r = picasso96_state.CLUT[start].Red;
878 	    int g = picasso96_state.CLUT[start].Green;
879 	    int b = picasso96_state.CLUT[start].Blue;
880 	    picasso_vidinfo.clut[start++] = (doMask256 (r, red_bits, red_shift)
881 		| doMask256 (g, green_bits, green_shift)
882 		| doMask256 (b, blue_bits, blue_shift));
883 	}
884 	notice_screen_contents_lost();
885 	return;
886     }
887 
888     /* Set our DirectX palette here */
889     if( current_pixbytes == 1 )
890     {
891 	    ddrval = DirectDraw_SetPaletteEntries( start, count, (LPPALETTEENTRY)&(picasso96_state.CLUT[start] ) );
892 	    if (ddrval != DD_OK)
893 		gui_message("DX_SetPalette() failed with %s/%d\n", DirectDraw_ErrorString (ddrval), ddrval);
894     }
895     else
896     {
897 	    write_log ("ERROR - DX_SetPalette() pixbytes %d\n", current_pixbytes );
898     }
899 }
900 
DX_Invalidate(int first,int last)901 void DX_Invalidate (int first, int last)
902 {
903     p96_double_buffer_first = first;
904     if( (unsigned)last >= picasso_vidinfo.height )
905 	last = picasso_vidinfo.height - 1;
906     p96_double_buffer_last  = last;
907     p96_double_buffer_needs_flushing = 1;
908 }
909 
DX_BitsPerCannon(void)910 int DX_BitsPerCannon (void)
911 {
912     return 8;
913 }
914 
BuildColorRef(int color,RGBFTYPE pixelformat)915 static COLORREF BuildColorRef( int color, RGBFTYPE pixelformat )
916 {
917     COLORREF result;
918 
919     /* Do special case first */
920     if( pixelformat == RGBFB_CHUNKY )
921 	result = color;
922     else
923 	result = do_get_mem_long( &color );
924     return result;
925 #if 0
926     int r,g,b;
927     write_log ( "DX_Blit() called to fill with color of 0x%x, rgbtype of 0x%x\n", color, pixelformat );
928 
929     switch( pixelformat )
930     {
931 	case RGBFB_R5G6B5PC:
932 	    r = color & 0xF800 >> 11;
933 	    g = color & 0x07E0 >> 5;
934 	    b = color & 0x001F;
935 	break;
936 	case RGBFB_R5G5B5PC:
937 	    r = color & 0x7C00 >> 10;
938 	    g = color & 0x03E0 >> 5;
939 	    b = color & 0x001F;
940 	break;
941 	case RGBFB_B5G6R5PC:
942 	    r = color & 0x001F;
943 	    g = color & 0x07E0 >> 5;
944 	    b = color & 0xF800 >> 11;
945 	break;
946 	case RGBFB_B5G5R5PC:
947 	    r = color & 0x001F;
948 	    g = color & 0x03E0 >> 5;
949 	    b = color & 0x7C00 >> 10;
950 	break;
951 	case RGBFB_B8G8R8:
952 	    r = color & 0x00FF0000 >> 16;
953 	    g = color & 0x0000FF00 >> 8;
954 	    b = color & 0x000000FF;
955 	break;
956 	case RGBFB_A8B8G8R8:
957 	    r = color & 0xFF000000 >> 24;
958 	    g = color & 0x00FF0000 >> 16;
959 	    b = color & 0x0000FF00 >> 8;
960 	break;
961 	case RGBFB_R8G8B8:
962 	    r = color & 0x000000FF;
963 	    g = color & 0x0000FF00 >> 8;
964 	    b = color & 0x00FF0000 >> 16;
965 	break;
966 	case RGBFB_A8R8G8B8:
967 	    r = color & 0x0000FF00 >> 8;
968 	    g = color & 0x00FF0000 >> 16;
969 	    b = color & 0xFF000000 >> 24;
970 	break;
971 	default:
972 	    write_log ( "Uknown 0x%x pixel-format\n", pixelformat );
973 	break;
974     }
975     result = RGB(r,g,b);
976     write_log ( "R = 0x%02x, G = 0x%02x, B = 0x%02x - result = 0x%08x\n", r, g, b, result );
977     return result;
978 #endif
979 }
980 
981 /* This is a general purpose DirectDrawSurface filling routine.  It can fill within primary surface.
982  * Definitions:
983  * - primary is the displayed (visible) surface in VRAM, which may have an associated offscreen surface (or back-buffer)
984  */
DX_Fill(int dstx,int dsty,int width,int height,uae_u32 color,RGBFTYPE rgbtype)985 int DX_Fill( int dstx, int dsty, int width, int height, uae_u32 color, RGBFTYPE rgbtype )
986 {
987     int result = 0;
988     RECT dstrect;
989     RECT srcrect;
990     DDBLTFX ddbltfx;
991     memset( &ddbltfx, 0, sizeof( ddbltfx ) );
992     ddbltfx.dwFillColor = BuildColorRef( color, rgbtype );
993     ddbltfx.dwSize = sizeof( ddbltfx );
994 
995     /* Set up our source rectangle.  This NEVER needs to be adjusted for windowed display, since the
996      * source is ALWAYS in an offscreen buffer, or we're in full-screen mode. */
997     SetRect( &srcrect, dstx, dsty, dstx+width, dsty+height );
998 
999     /* Set up our destination rectangle, and adjust for blit to windowed display (if necessary ) */
1000     SetRect( &dstrect, dstx, dsty, dstx+width, dsty+height );
1001     if( !fullscreen && !overlay )
1002 	OffsetRect( &dstrect, amigawin_rect.left, amigawin_rect.top );
1003 
1004     /* Render our fill to the visible (primary) surface */
1005     if( ( result = DirectDraw_Blt( primary_surface, &dstrect, invalid_surface, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx ) ) )
1006     {
1007 	if( DirectDraw_GetLockableType() == secondary_surface )
1008 	{
1009 	    /* We've colour-filled the visible, but still need to colour-fill the offscreen */
1010 	    result = DirectDraw_Blt( secondary_surface, &srcrect, invalid_surface, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx );
1011 	}
1012     }
1013     return result;
1014 }
1015 
1016 /* This is a general purpose DirectDrawSurface blitting routine.  It can blit within primary surface
1017  * Definitions:
1018  * - primary is the displayed (visible) surface in VRAM, which may have an associated offscreen surface (or back-buffer)
1019  */
1020 
1021 DDBLTFX fx = { sizeof( DDBLTFX ) };
1022 
1023 DWORD BLIT_OPCODE_TRANSLATION[ BLIT_LAST ] =
1024 {
1025     BLACKNESS,  /* BLIT_FALSE */
1026     NOTSRCERASE,/* BLIT_NOR */
1027     -1,         /* BLIT_ONLYDST NOT SUPPORTED */
1028     NOTSRCCOPY, /* BLIT_NOTSRC */
1029     SRCERASE,   /* BLIT_ONLYSRC */
1030     DSTINVERT,  /* BLIT_NOTDST */
1031     SRCINVERT,  /* BLIT_EOR */
1032     -1,         /* BLIT_NAND NOT SUPPORTED */
1033     SRCAND,     /* BLIT_AND */
1034     -1,         /* BLIT_NEOR NOT SUPPORTED */
1035     -1,         /* NO-OP */
1036     MERGEPAINT, /* BLIT_NOTONLYSRC */
1037     SRCCOPY,    /* BLIT_SRC */
1038     -1,         /* BLIT_NOTONLYDST NOT SUPPORTED */
1039     SRCPAINT,   /* BLIT_OR */
1040     WHITENESS   /* BLIT_TRUE */
1041 };
1042 
1043 // This function is only called for full-screen Amiga screen-modes, and simply flips
1044 // the front and back buffers.  Additionally, because the emulation is not always drawing
1045 // complete frames, we also need to update the back-buffer with the new contents we just
1046 // flipped to.  Thus, after our flip, we blit.
DX_Flip(void)1047 int DX_Flip( void )
1048 {
1049     int result = 0;
1050 
1051     result = DirectDraw_Flip();
1052     if( result )
1053     {
1054 	result = DirectDraw_BltFast( secondary_surface, 0, 0, primary_surface, NULL );
1055     }
1056     return result;
1057 }
1058 
DX_Blit(int srcx,int srcy,int dstx,int dsty,int width,int height,BLIT_OPCODE opcode)1059 int DX_Blit( int srcx, int srcy, int dstx, int dsty, int width, int height, BLIT_OPCODE opcode )
1060 {
1061     int result = 0;
1062     RECT dstrect;
1063     RECT srcrect;
1064     DWORD dwROP = BLIT_OPCODE_TRANSLATION[ opcode ];
1065 
1066     /* Set up our source rectangle.  This NEVER needs to be adjusted for windowed display, since the
1067      * source is ALWAYS in an offscreen buffer, or we're in full-screen mode. */
1068     SetRect( &srcrect, srcx, srcy, srcx+width, srcy+height );
1069 
1070     /* Set up our destination rectangle, and adjust for blit to windowed display (if necessary ) */
1071     SetRect( &dstrect, dstx, dsty, dstx+width, dsty+height );
1072 
1073     if( !fullscreen && !overlay )
1074 	OffsetRect( &dstrect, amigawin_rect.left, amigawin_rect.top );
1075 
1076     if( dwROP == -1 )
1077     {
1078 	/* Unsupported blit opcode! */
1079 	return 0;
1080     }
1081     else
1082     {
1083 	fx.dwROP = dwROP;
1084     }
1085 
1086     /* Render our blit within the primary surface */
1087     result = DirectDraw_Blt( primary_surface, &dstrect, DirectDraw_GetLockableType(), &srcrect, DDBLT_WAIT | DDBLT_ROP, &fx );
1088 
1089     if( !result )
1090     {
1091 	BLIT_OPCODE_TRANSLATION[ opcode ] = -1;
1092     }
1093     else if( DirectDraw_GetLockableType() == secondary_surface )
1094     {
1095 	/* We've just blitted from the offscreen to the visible, but still need to blit from offscreen to offscreen
1096 	 * NOTE: reset our destination rectangle again if its been modified above... */
1097 	if( ( srcx != dstx ) || ( srcy != dsty ) )
1098 	{
1099 	    if( !fullscreen )
1100 		SetRect( &dstrect, dstx, dsty, dstx+width, dsty+height );
1101 	    result = DirectDraw_Blt( secondary_surface, &dstrect, secondary_surface, &srcrect, DDBLT_WAIT | DDBLT_ROP, &fx );
1102 	}
1103     }
1104 
1105     return result;
1106 }
1107 
DX_WaitVerticalSync(void)1108 void DX_WaitVerticalSync( void )
1109 {
1110     DirectDraw_WaitForVerticalBlank( DDWAITVB_BLOCKBEGIN );
1111 }
1112 
DX_ShowCursor(uae_u32 activate)1113 uae_u32 DX_ShowCursor( uae_u32 activate )
1114 {
1115     uae_u32 result = 0;
1116     if( ShowCursor( activate ) > 0 )
1117 	result = 1;
1118     return result;
1119 }
1120 
DX_MoveCursor(uae_u32 x,uae_u32 y)1121 uae_u32 DX_MoveCursor( uae_u32 x, uae_u32 y )
1122 {
1123     uae_u32 result = 0;
1124 
1125     // We may need to adjust the x,y values for our window-offset
1126     if( !fullscreen )
1127     {
1128 	RECT rect;
1129 	if( GetWindowRect( hAmigaWnd, &rect ) )
1130 	{
1131 	    x = rect.left + x;
1132 	    y = rect.top + y;
1133 	}
1134     }
1135     if( SetCursorPos( x, y ) )
1136 	result = 1;
1137     return result;
1138 }
1139 
open_screen(void)1140 static void open_screen( void )
1141 {
1142     close_windows ();
1143     if( open_windows() )
1144 	DX_SetPalette (0, 256);
1145     else
1146 	abort();
1147 }
1148 
gfx_set_picasso_state(int on)1149 void gfx_set_picasso_state( int on )
1150 {
1151     if (screen_is_picasso == on)
1152 	return;
1153 
1154     screen_is_picasso = on;
1155     open_screen();
1156 }
1157 
gfx_set_picasso_modeinfo(int w,int h,int depth,int rgbfmt)1158 void gfx_set_picasso_modeinfo( int w, int h, int depth, int rgbfmt )
1159 {
1160     depth >>= 3;
1161     if( ( picasso_vidinfo.width == w ) &&
1162 	    ( picasso_vidinfo.height == h ) &&
1163 	    ( picasso_vidinfo.depth == depth ) &&
1164 	    ( picasso_vidinfo.selected_rgbformat == rgbfmt) )
1165 	return;
1166 
1167     picasso_vidinfo.selected_rgbformat = rgbfmt;
1168     picasso_vidinfo.width = w;
1169     picasso_vidinfo.height = h;
1170     picasso_vidinfo.depth = depth;
1171     picasso_vidinfo.extra_mem = 1;
1172 
1173     if( screen_is_picasso )
1174     {
1175 	open_screen();
1176     }
1177 }
1178 
graphics_init(void)1179 int graphics_init (void)
1180 {
1181     return open_windows ();
1182 }
1183 
graphics_setup(void)1184 int graphics_setup (void)
1185 {
1186     if( !DirectDraw_Start() )
1187 	return 0;
1188 
1189     DirectDraw_Release();
1190 
1191     InitPicasso96();
1192 
1193     return 1;
1194 }
1195 
graphics_leave(void)1196 void graphics_leave (void)
1197 {
1198     close_windows ();
1199     dumpcustom ();
1200     cleanup_modes ();
1201 }
1202 
OSDEP_minimize_uae(void)1203 uae_u32 OSDEP_minimize_uae( void )
1204 {
1205     return ShowWindow( hAmigaWnd, SW_MINIMIZE );
1206 }
1207 
close_windows(void)1208 static void close_windows (void)
1209 {
1210     gfxvidinfo.bufmem = 0;
1211 
1212     releasecapture ();
1213     setmouseactive (0);
1214     ClipCursor (NULL);
1215     DirectDraw_Release();
1216     close_hwnds();
1217     if( mouseactive )
1218 	bJustClosedWithActiveMouse = TRUE;
1219     {
1220 	int i;
1221 	for( i=0;i<AK_CTRL+1;i++)my_kbd_handler (0,i,0);
1222 	for( i=0;i<AK_CTRL+1;i++)my_kbd_handler (i,0,0);
1223 	buttonstate[0] = 0;
1224 	buttonstate[1] = 0;
1225 	buttonstate[2] = 0;
1226     }
1227     bInitDone = FALSE; //?????JGI
1228     overlay = 1; // Go back to desiring overlay support
1229 }
1230 
WIN32GFX_ToggleFullScreen(void)1231 void WIN32GFX_ToggleFullScreen( void )
1232 {
1233     if (needs_direct && !overlay)
1234 	return;
1235 
1236     display_change_requested = 1;
1237     if (screen_is_picasso)
1238 	currprefs.gfx_pfullscreen ^= 1;
1239     else
1240 	currprefs.gfx_afullscreen ^= 1;
1241 }
1242 
create_windows(void)1243 static int create_windows (void)
1244 {
1245     if (!fullscreen)
1246     {
1247 	RECT rc;
1248 	LONG stored_x = 1, stored_y = GetSystemMetrics( SM_CYMENU ) + GetSystemMetrics( SM_CYBORDER );
1249 	DWORD regkeytype;
1250 	DWORD regkeysize = sizeof(LONG);
1251 	HLOCAL hloc;
1252 	    LPINT lpParts;
1253 
1254 	RegQueryValueEx( hWinUAEKey, "xPos", 0, &regkeytype, (LPBYTE)&stored_x, &regkeysize );
1255 	RegQueryValueEx( hWinUAEKey, "yPos", 0, &regkeytype, (LPBYTE)&stored_y, &regkeysize );
1256 	if( stored_x < 1 )
1257 	    stored_x = 1;
1258 	if( stored_y < ( GetSystemMetrics( SM_CYMENU ) + GetSystemMetrics( SM_CYBORDER ) ) )
1259 	    stored_y = GetSystemMetrics( SM_CYMENU ) + GetSystemMetrics( SM_CYBORDER );
1260 
1261 	if( stored_x > GetSystemMetrics( SM_CXFULLSCREEN ) )
1262 	    rc.left = 1;
1263 	else
1264 	    rc.left = stored_x;
1265 
1266 	if( stored_y > GetSystemMetrics( SM_CYFULLSCREEN ) )
1267 	    rc.top = 1;
1268 	else
1269 	    rc.top = stored_y;
1270 
1271 	rc.right = rc.left + current_width;
1272 	rc.bottom = rc.top + current_height + GetSystemMetrics( SM_CYMENU ) + GetSystemMetrics( SM_CYBORDER )*3;
1273 
1274 	AdjustWindowRect (&rc, NORMAL_WINDOW_STYLE, FALSE);
1275 
1276 	hMainWnd = CreateWindowEx( picasso_on ? WS_EX_ACCEPTFILES : WS_EX_ACCEPTFILES | WS_EX_APPWINDOW, "PCsuxRox", "WinUAE",
1277 				       NORMAL_WINDOW_STYLE, rc.left, rc.top,
1278 				       rc.right - rc.left, rc.bottom - rc.top,
1279 				       NULL, NULL, 0, NULL);
1280 
1281 	if (! hMainWnd)
1282 	    return 0;
1283 	hStatusWnd = CreateStatusWindow (WS_CHILD | WS_VISIBLE, "", hMainWnd, 1);
1284 	if (hStatusWnd)
1285 	{
1286 	    GetClientRect (hMainWnd, &rc);
1287 	    /* Allocate an array for holding the right edge coordinates. */
1288 	    hloc = LocalAlloc (LHND, sizeof (int) * NUM_PARTS);
1289 	    if (hloc)
1290 	    {
1291 		lpParts = LocalLock (hloc);
1292 
1293 		/* Calculate the right edge coordinate for each part, and copy the coords
1294 		 * to the array.  */
1295 		lpParts[0] = rc.right - (DRIVE_WIDTH * 4) - LED_WIDTH - FPS_WIDTH - 2;
1296 		lpParts[1] = lpParts[0] + FPS_WIDTH;
1297 		lpParts[2] = lpParts[1] + LED_WIDTH;
1298 		lpParts[3] = lpParts[2] + DRIVE_WIDTH;
1299 		lpParts[4] = lpParts[3] + DRIVE_WIDTH;
1300 		lpParts[5] = lpParts[4] + DRIVE_WIDTH;
1301 		lpParts[6] = lpParts[5] + DRIVE_WIDTH;
1302 
1303 		/* Create the seven parts */
1304 		SendMessage (hStatusWnd, SB_SETPARTS, (WPARAM) NUM_PARTS, (LPARAM) lpParts);
1305 
1306 		LocalUnlock (hloc);
1307 		LocalFree (hloc);
1308 	    }
1309 	}
1310     }
1311     else
1312 	hMainWnd = NULL;
1313 
1314     hAmigaWnd = CreateWindowEx (fullscreen ? WS_EX_TOPMOST : WS_EX_ACCEPTFILES | WS_EX_APPWINDOW,
1315 				"AmigaPowah", "WinUAE",
1316 				hMainWnd ? WS_VISIBLE | WS_CHILD : WS_VISIBLE | WS_POPUP,
1317 				hMainWnd ? 0 : CW_USEDEFAULT, hMainWnd ? 0 : CW_USEDEFAULT,
1318 				fullscreen ? GetSystemMetrics (SM_CXSCREEN) : current_width,
1319 				fullscreen ? GetSystemMetrics (SM_CYSCREEN) : current_height,
1320 				hMainWnd, NULL, 0, NULL);
1321 
1322     if (! hAmigaWnd)
1323     {
1324 	close_hwnds();
1325 	return 0;
1326     }
1327 
1328 
1329     if (hMainWnd)
1330 	UpdateWindow( hMainWnd );
1331     if (hAmigaWnd)
1332 	UpdateWindow (hAmigaWnd);
1333 
1334     return 1;
1335 }
1336 
setoverlay(void)1337 static void setoverlay(void)
1338 {
1339     RECT sr, dr, statusr;
1340     POINT p = {0,0};
1341     int maxwidth, maxheight;
1342 
1343     GetClientRect(hMainWnd, &dr);
1344     // adjust the dest-rect to avoid the status-bar
1345     if( hStatusWnd )
1346     {
1347 	if( GetWindowRect( hStatusWnd, &statusr ) )
1348 	    dr.bottom = dr.bottom - ( statusr.bottom - statusr.top );
1349     }
1350 
1351     ClientToScreen( hMainWnd, &p );
1352     dr.left = p.x;
1353     dr.top = p.y;
1354     dr.right += p.x;
1355     dr.bottom += p.y;
1356 
1357     sr.left = 0; sr.top = 0;
1358     sr.right = current_width; sr.bottom = current_height;
1359 
1360     // Adjust our dst-rect to match the dimensions of our src-rect
1361     if( dr.right - dr.left > sr.right - sr.left )
1362     {
1363 	dr.right = dr.left + sr.right - sr.left;
1364     }
1365     if( dr.bottom - dr.top > sr.bottom - sr.top )
1366     {
1367 	dr.bottom = dr.top + sr.bottom - sr.top;
1368     }
1369 
1370     maxwidth = GetSystemMetrics(SM_CXSCREEN);
1371     if (dr.right > maxwidth) {
1372 	sr.right = current_width - (dr.right - maxwidth);
1373 	dr.right = maxwidth;
1374     }
1375     maxheight = GetSystemMetrics(SM_CYSCREEN);
1376     if (dr.bottom > maxheight) {
1377 	sr.bottom = current_height - (dr.bottom - maxheight);
1378 	dr.bottom = maxheight;
1379     }
1380     if (dr.left < 0) {
1381 	sr.left = -dr.left;
1382 	dr.left = 0;
1383     }
1384     if (dr.top < 0) {
1385 	sr.top = -dr.top;
1386 	dr.top = 0;
1387     }
1388     DirectDraw_UpdateOverlay(sr, dr);
1389 }
1390 
doInit(void)1391 static BOOL doInit (void)
1392 {
1393     if (! create_windows ())
1394 	goto oops;
1395 
1396     if( screen_is_picasso )
1397     {
1398 	if (! set_ddraw (current_width, current_height, fullscreen, overlay, window_depth,
1399 			(LPPALETTEENTRY) & picasso96_state.CLUT))
1400 	    goto oops;
1401 	picasso_vidinfo.rowbytes = DirectDraw_GetSurfacePitch();
1402 	picasso_vidinfo.pixbytes = DirectDraw_GetBytesPerPixel();
1403 	picasso_vidinfo.rgbformat = DirectDraw_GetPixelFormat();
1404     }
1405     else
1406     {
1407 	if (fullscreen)
1408 	{
1409 #if 0
1410 	    write_log ( "Calling adjust_screenmode with %d,%d,%d\n", window_width, window_height, window_depth );
1411 	    if( WIN32GFX_AdjustScreenmode( &window_width, &window_height, &window_depth ) < 0 )
1412 		abort ();
1413 	    write_log ( "Finished adjust_screenmode with %d,%d,%d\n", window_width, window_height, window_depth );
1414 #endif
1415 	}
1416 	if (! set_ddraw (current_width, current_height, fullscreen, overlay, window_depth, colors256))
1417 	    goto oops;
1418 	gfxvidinfo.bufmem = 0;
1419 	gfxvidinfo.linemem = 0;
1420 	gfxvidinfo.emergmem = scrlinebuf; // memcpy from system-memory to video-memory
1421 	gfxvidinfo.pixbytes = current_pixbytes;
1422 	gfxvidinfo.width = current_width;
1423 	gfxvidinfo.height = current_height;
1424 	gfxvidinfo.maxblocklines = 0; // flush_screen actually does everything
1425 	gfxvidinfo.rowbytes = DirectDraw_GetSurfacePitch();
1426     }
1427 
1428     if( fullscreen )
1429     {
1430 	WIN32_MouseDefaults();
1431     }
1432     if( !DirectDraw_SurfaceLock( lockable_surface ) )
1433 	goto oops;
1434     DirectDraw_SurfaceUnlock();
1435 
1436     if( ( DirectDraw_GetPixelFormatFlags() & (DDPF_RGB | DDPF_PALETTEINDEXED8 | DDPF_RGBTOYUV ) ) )
1437     {
1438 	write_log ( "%s mode (bits: %d, pixbytes: %d)\n", fullscreen ? "Full screen" : "Window",
1439 		   DirectDraw_GetSurfaceBitCount(), current_pixbytes );
1440     }
1441     else
1442     {
1443 	char szMessage[ MAX_PATH ];
1444 	WIN32GUI_LoadUIString( IDS_UNSUPPORTEDPIXELFORMAT, szMessage, MAX_PATH );
1445 	gui_message( szMessage);
1446 	goto oops;
1447     }
1448 
1449     init_colors ();
1450 
1451     if (overlay)
1452 	setoverlay ();
1453 
1454 #if 0 // This crashes WinXP, because that last param should be an LPWINDOWPOS...
1455     if (! fullscreen)
1456 	SendMessage( hMainWnd, WM_WINDOWPOSCHANGED, 0, 0);
1457 #endif
1458 
1459     bInitDone = TRUE;
1460     return 1;
1461 
1462 oops:
1463     DirectDraw_Release();
1464     close_hwnds();
1465     return 0;
1466 }
1467 
1468 
WIN32GFX_PaletteChange(void)1469 void WIN32GFX_PaletteChange( void )
1470 {
1471     DirectDraw_SetPalette( 1 ); /* Remove current palette */
1472     DirectDraw_SetPalette( 0 ); /* Set our real palette */
1473 }
1474 
WIN32GFX_ClearPalette(void)1475 void WIN32GFX_ClearPalette( void )
1476 {
1477     DirectDraw_SetPalette( 1 ); /* Remove palette */
1478 }
1479 
WIN32GFX_SetPalette(void)1480 void WIN32GFX_SetPalette( void )
1481 {
1482     DirectDraw_SetPalette( 0 ); /* Set palette */
1483 }
1484 #endif
WIN32GFX_WindowMove(void)1485 void WIN32GFX_WindowMove ( void )
1486 {
1487     if (overlay && hMainWnd && bInitDone) setoverlay();
1488 }
1489 
WIN32GFX_WindowSize(void)1490 void WIN32GFX_WindowSize ( void )
1491 {
1492     RECT r;
1493 
1494     //?????JGI (to delete): if (!overlay) return;
1495     if (!hMainWnd) return;
1496     if(!GetClientRect (hMainWnd, &r)) return;
1497     window_width = r.right - r.left;
1498     window_height = r.bottom - r.top;
1499     if (overlay && bInitDone) setoverlay();//????? JGI
1500 }
1501