1 /*
2  * UAE - The Un*x Amiga Emulator
3  *
4  * Win32 interface
5  *
6  * Copyright 1997-1998 Mathias Ortmann
7  * Copyright 1997-1999 Brian King
8  */
9 
10 /* Uncomment this line if you want the logs time-stamped */
11 /* #define TIMESTAMP_LOGS */
12 
13 #include "sysconfig.h"
14 
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <signal.h>
18 
19 #include <windows.h>
20 #include <commctrl.h>
21 #include <commdlg.h>
22 #include <shellapi.h>
23 #include <zmouse.h>
24 #include <ddraw.h>
25 #include <dbt.h>
26 #include <math.h>
27 
28 #include "sysdeps.h"
29 #include "options.h"
30 #include "gensound.h"
31 #include "sounddep/sound.h"
32 #include "uae.h"
33 #include "memory.h"
34 #include "custom.h"
35 #include "events.h"
36 #include "xwin.h"
37 #include "keyboard.h"
38 #include "keybuf.h"
39 #include "drawing.h"
40 #include "picasso96.h"
41 #include "bsdsocket.h"
42 #include "osdep/win32.h"
43 #include "osdep/win32gfx.h"
44 #include "osdep/win32gui.h"
45 #include "osdep/dxwrap.h"
46 #include "autoconf.h"
47 #include "gui.h"
48 #include "newcpu.h"
49 extern void WIN32GFX_WindowMove ( void );
50 extern void WIN32GFX_WindowSize ( void );
51 unsigned long *win32_stackbase;
52 unsigned long *win32_freestack[42]; //EXTRA_STACK_SIZE
53 
54 /* Comment out the following line if you don't want ZLIB.DLL support */
55 #undef USE_ZLIB_DLL
56 
57 #ifdef USE_ZLIB_DLL
58 #include "zlib.h"
59 #endif
60 
61 int useqpc = 0; /* Set to TRUE to use the QueryPerformanceCounter() function instead of rdtsc() */
62 
63 static FILE *debugfile = NULL;
64 
65 HINSTANCE hInst = NULL;
66 HMODULE hUIDLL = NULL;
67 
68 HWND (WINAPI *pHtmlHelp)(HWND, LPCSTR, UINT, LPDWORD ) = NULL;
69 
70 HWND hAmigaWnd, hMainWnd;
71 /*DWORD Keys; */
72 RECT amigawin_rect;
73 
74 char VersionStr[256];
75 
76 int in_sizemove = 0;
77 int manual_painting_needed = 0;
78 int customsize = 0;
79 
80 int bActive;
81 int toggle_sound;
82 
83 BOOL viewing_child = FALSE;
84 
85 HKEY hWinUAEKey    = NULL;
86 COLORREF g_dwBackgroundColor  = RGB(10, 0, 10);
87 
88 /* Keyboard emulation, Win32 helper routines. */
89 static LPARAM keysdown[256];
90 static short numkeysdown;
checkkey(int vkey,LPARAM lParam)91 int checkkey (int vkey, LPARAM lParam)
92 {
93     switch (vkey) {
94     case VK_LWIN:
95     case VK_RWIN:
96      case VK_SHIFT:
97      case VK_LSHIFT:
98      case VK_RSHIFT:
99      case VK_CONTROL:
100      case VK_LCONTROL:
101      case VK_RCONTROL:
102      case VK_MENU:
103      case VK_LMENU:
104      case VK_RMENU:
105 	return GetKeyState (vkey) & 0x8000;
106     }
107     return GetAsyncKeyState (vkey) & 0x8000;
108 }
109 
110 /* Mouse emulation, Win32 interface */
111 static int mousecx = 160, mousecy = 100, mousedx = 160, mousedy = 100;
112 static int mousecl = MAKELONG (160, 100);
113 int mouseactive;
114 
WIN32_MouseDefaults(void)115 void WIN32_MouseDefaults( void )
116 {
117     mousecx = 160, mousecy = 100, mousedx = 160, mousedy = 100, mousecl = MAKELONG (160, 100);
118 }
119 
setmouseactive(int active)120 void setmouseactive (int active)
121 {
122     mousedx = (amigawin_rect.right - amigawin_rect.left) / 2;
123     mousedy = (amigawin_rect.bottom - amigawin_rect.top) / 2;
124     mousecl = MAKELONG (mousedx, mousedy);
125     mousecx = amigawin_rect.left + mousedx;
126     mousecy = amigawin_rect.top + mousedy;
127 
128     if (active == mouseactive)
129 	return;
130     mouseactive = active;
131 
132     if (active)
133     {
134 #ifdef HARDWARE_SPRITE_EMULATION
135 	if( !WIN32GFX_IsPicassoScreen() )
136 #endif
137 	{
138 	    ShowCursor (FALSE);
139 	    SetCursorPos (mousecx, mousecy);
140 	}
141 	SetWindowText (hMainWnd ? hMainWnd : hAmigaWnd, "UAE/Win32 - [Mouse active - press Alt-Tab to cancel]");
142 	ClipCursor (&amigawin_rect);
143     }
144     else
145     {
146 	ShowCursor (TRUE);
147 	SetWindowText (hMainWnd ? hMainWnd : hAmigaWnd, "UAE/Win32" );
148 	ClipCursor (NULL);
149     }
150 }
151 
152 static int hascapture = 0;
153 
setcapture(void)154 static void setcapture (void)
155 {
156     if (hascapture)
157 	return;
158     hascapture++;
159     SetCapture (hAmigaWnd);
160 }
161 
releasecapture(void)162 void releasecapture (void)
163 {
164     if (!hascapture)
165 	return;
166     hascapture--;
167     ReleaseCapture ();
168 }
169 
read_processor_time_cyrix(void)170 frame_time_t read_processor_time_cyrix (void)
171 {
172     LARGE_INTEGER counter;
173     QueryPerformanceCounter( &counter );
174     return (frame_time_t)(counter.LowPart);
175 }
176 
177 #include <setjmp.h>
178 jmp_buf catch_test;
179 
illhandler(int foo)180 static RETSIGTYPE illhandler(int foo)
181 {
182     rpt_available = 0;
183     longjmp(catch_test,1);
184 }
185 
have_rdtsc(void)186 int have_rdtsc (void)
187 {
188     rpt_available = 1;
189     write_log ("Testing the RDTSC instruction ... ");
190     signal (SIGILL, illhandler);
191     if (setjmp (catch_test) == 0)
192 	read_processor_time ();
193     signal (SIGILL, SIG_DFL);
194     write_log ("done.\n");
195     if (! rpt_available) {
196 	write_log ("Your processor does not support the RDTSC instruction.\n");
197 	return 0;
198     }
199     return 1;
200 }
201 
figure_processor_speed(void)202 static void figure_processor_speed (void)
203 {
204     extern volatile frame_time_t vsynctime;
205     extern unsigned long syncbase;
206     frame_time_t clockrate;
207 
208 #if defined __GNUC__
209     if (! have_rdtsc ())
210 	useqpc = 1;
211 #else
212     LARGE_INTEGER freq;
213 
214     __try
215     {
216 	__asm{rdtsc};
217     }
218     __except( GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION )
219     {
220 	useqpc = 1;
221     }
222     if( QueryPerformanceFrequency( &freq ) )
223     {
224 	if (freq.LowPart > 90000000) /* looks like CPU freq. */
225 	    write_log ( "CLOCKFREQ: QueryPerformanceFrequency() reports %d-MHz\n", freq.LowPart / 1000000 );
226 	else
227 	    write_log ( "CLOCKFREQ: QueryPerformanceFrequency() reports %.2f-MHz\n", (float)freq.LowPart / 1000000.0f );
228 
229 	if( freq.LowPart < 1000000 )
230 	{
231 	    write_log ( "CLOCKFREQ: Weird value.  Using QueryPerformanceCounter() instead of RDTSC.\n" );
232 	    useqpc = 1;
233 	}
234 	rpt_available = 1;
235     }
236     else
237     {
238 	write_log ( "CLOCKFREQ: No support for clock-rate stuff!\n" );
239 	rpt_available = 0;
240     }
241 #endif
242     SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS );
243     clockrate = read_processor_time();
244     Sleep( 1000 );
245     clockrate = read_processor_time() - clockrate;
246     SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS );
247 
248     write_log ( "CLOCKFREQ: Measured as %d-MHz\n", clockrate / 1000000 );
249     syncbase = clockrate;
250     vsynctime = syncbase / VBLANK_HZ_PAL; /* default to 50Hz */
251 }
252 
253 static BOOL bDiskChanged = FALSE;
254 
AmigaWindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)255 static long FAR PASCAL AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
256 {
257     PAINTSTRUCT ps;
258     HDC hDC;
259     short wheeldelta;
260     static int store_xy = 0;
261     BOOL minimized;
262     LPMINMAXINFO lpmmi;
263     RECT rect;
264 
265     switch( message )
266     {
267 	case WM_PALETTECHANGED:
268 	    if( (HWND)wParam != hWnd )
269 	    {
270 		write_log ( "WM_PALETTECHANGED Request\n" );
271 		WIN32GFX_PaletteChange();
272 	    }
273 	break;
274 	case WM_ACTIVATEAPP:
275 	    if (bActive = wParam)
276 	    {
277 		if( WIN32GFX_IsFullScreen() )
278 		{
279 		    SetCursor (NULL);
280 #ifndef HARDWARE_SPRITE_EMULATION
281 		    SetCursorPos (mousecx, mousecy);
282 #else
283 		    if( !WIN32GFX_IsPicassoScreen() )
284 			SetCursorPos (mousecx, mousecy);
285 #endif
286 		}
287 		my_kbd_handler (VK_CAPITAL, 0x3a, TRUE);
288 	    }
289 	    else
290 	    {
291 		if( !WIN32GFX_IsFullScreen() )
292 		    setmouseactive (0);
293 		else
294 		{
295 		    if( WIN32GFX_IsPicassoScreen() )
296 		    {
297 			WIN32GFX_DisablePicasso();
298 		    }
299 		}
300 		}
301 	    break;
302 	case WM_ACTIVATE:
303 	    minimized = HIWORD( wParam );
304 	    if (LOWORD (wParam) != WA_INACTIVE)
305 	    {
306 		write_log ( "WinUAE now active via WM_ACTIVATE\n" );
307 		if( !minimized )
308 		{
309 		    if( currprefs.win32_iconified_nospeed )
310 		    {
311 			SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS );
312 		    }
313 		    if( currprefs.win32_iconified_nosound )
314 		    {
315 			resume_sound();
316 		    }
317 
318 		    clear_inhibit_frame( IHF_WINDOWHIDDEN );
319 		}
320 		ShowWindow (hWnd, SW_RESTORE);
321 		if( WIN32GFX_IsPicassoScreen() )
322 		{
323 		    WIN32GFX_EnablePicasso();
324 		}
325 	    }
326 	    else
327 	    {
328 		write_log ( "WinUAE now inactive via WM_ACTIVATE\n" );
329 		if( minimized && !quit_program )
330 		{
331 		    if( currprefs.win32_iconified_nospeed )
332 		    {
333 			SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
334 		    }
335 		    if( currprefs.win32_iconified_nosound )
336 		    {
337 			pause_sound ();
338 		    }
339 		    set_inhibit_frame( IHF_WINDOWHIDDEN );
340 		}
341 	    }
342 	    break;
343 
344 	case WM_SETCURSOR:
345 		if( WIN32GFX_IsFullScreen() )
346 	    {
347 #ifdef HARDWARE_SPRITE_EMULATION
348 		    if( !WIN32GFX_IsPicassoScreen() )
349 #endif
350 		    SetCursor (NULL);
351 		    return TRUE;
352 		}
353 	    break;
354 
355 	case WM_SYSCOMMAND:
356 	    switch( wParam & 0xFFF0 )
357 	    {
358 		case SC_MAXIMIZE:
359 		    WIN32GFX_ToggleFullScreen();
360 			return 0;
361 		break;
362 		case SC_MINIMIZE:
363 		    WIN32GFX_DisablePicasso();
364 		break;
365 	    }
366 	    break;
367 
368 	case WM_KEYUP:
369 	case WM_SYSKEYUP:
370 		numkeysdown--;
371 		keysdown[wParam] = 0;
372 		my_kbd_handler (wParam, (lParam >> 16) & 0x1ff, FALSE);
373 	    return 0;
374 	break;
375 
376      case WM_KEYDOWN:
377      case WM_SYSKEYDOWN:
378 	if (LOWORD (lParam) == 1)
379     {
380 	    if (numkeysdown)
381 	{
382 		    int key;
383 		    numkeysdown = 0;
384 
385 		    for (key = 256; key--;)
386 	    {
387 			if (keysdown[key])
388 		{
389 				if (checkkey (key, lParam))
390 				    numkeysdown++;
391 				else
392 		    {
393 				    my_kbd_handler (key, (keysdown[key] >> 16) & 0x1ff, FALSE);
394 				    keysdown[key] = 0;
395 				}
396 			}
397 		    }
398 	    }
399 	    if (!keysdown[wParam])
400 	{
401 		    keysdown[wParam] = lParam;
402 		    numkeysdown++;
403 	    }
404 	    numkeysdown++;
405 	    my_kbd_handler (wParam, (lParam >> 16) & 0x1ff, TRUE);
406 	}
407 	break;
408 
409      case WM_LBUTTONDBLCLK: // According to MSDN, having CS_DBLCLKS in your window-class
410 			    // means that the sequence is WM_LBUTTONDOWN, WM_LBUTTONUP,
411 			    // WM_LBUTTONDBLCLK, and WM_LBUTTONUP.
412 			    // So we need to make WM_LBUTTONDBLCLK act like WM_LBUTTONDOWN.
413      case WM_LBUTTONDOWN:
414 	if (ievent_alive) {
415 	    setcapture ();
416 	    buttonstate[0] = 1;
417 	} else if (!WIN32GFX_IsFullScreen() && !mouseactive)
418 	    setmouseactive (1);
419 	else
420 	    buttonstate[0] = 1;
421 	break;
422 
423      case WM_LBUTTONUP:
424 	releasecapture ();
425 	buttonstate[0] = 0;
426 	break;
427 
428 
429      case WM_MBUTTONDOWN:
430 	if (ievent_alive)
431 	    setcapture ();
432 	buttonstate[1] = 1;
433 	break;
434 
435      case WM_MBUTTONUP:
436 	releasecapture ();
437 	buttonstate[1] = 0;
438 	break;
439 
440      case WM_RBUTTONDOWN:
441 	if (ievent_alive)
442 	    setcapture ();
443 	buttonstate[2] = 1;
444 	break;
445 
446      case WM_RBUTTONUP:
447 	releasecapture ();
448 	buttonstate[2] = 0;
449 	break;
450 
451      case WM_VSCROLL:
452 	 write_log ( "WM_VSCROLL\n" );
453 	 if( LOWORD( wParam ) == SB_LINEDOWN )
454 	     record_key(0x7A<<1);
455 	 else if( LOWORD( wParam ) == SB_LINEUP )
456 	     record_key(0x7B<<1);
457 	 break;
458 
459      case WM_MOUSEWHEEL:
460 	 wheeldelta = HIWORD(wParam);
461 	 write_log ( "WM_MOUSEWHEEL with delta %d\n", wheeldelta );
462 	 if( wheeldelta > 0 )
463 	     record_key(0x7A<<1);
464 	 else if( wheeldelta < 0 )
465 	     record_key(0x7B<<1);
466 	 break;
467 
468      case WM_MOUSEMOVE:
469 #ifndef HARDWARE_SPRITE_EMULATION
470 	 if( ( mouseactive && !ievent_alive ) ||
471 	     WIN32GFX_IsFullScreen() )
472 #else
473 	 if( ( ( mouseactive && !ievent_alive ) || WIN32GFX_IsFullScreen() ) &&
474 	     !WIN32GFX_IsPicassoScreen() )
475 #endif
476 	 {
477 	     /*
478 	      * In this mode, the mouse pointer is always centered in the window,
479 	      * this is ensured by the SetCursorPos call below.
480 	      * We don't want to handle messages that result from such a SetCursorPos
481 	      * call (recursion!), so exit early if we see one.
482 	      */
483 	     if (lParam == mousecl)
484 		 break;
485 	     lastmx += (signed short) LOWORD (lParam) - mousedx;
486 	     lastmy += (signed short) HIWORD (lParam) - mousedy;
487 	     if (ievent_alive)
488 	     {
489 		 if (lastmx < 0)
490 		     lastmx = 0;
491 		 if (lastmx > WIN32GFX_GetWidth() )
492 		     lastmx = WIN32GFX_GetWidth();
493 		 if (lastmy < 0)
494 		     lastmy = 0;
495 		 if (lastmy > WIN32GFX_GetHeight() )
496 		     lastmy = WIN32GFX_GetHeight();
497 	     }
498 	     SetCursorPos (mousecx, mousecy);
499 	     break;
500 	}
501 	lastmx = (signed short) LOWORD (lParam);
502 	lastmy = (signed short) HIWORD (lParam);
503     break;
504 
505      case WM_PAINT:
506 	notice_screen_contents_lost ();
507 
508 	hDC = BeginPaint (hWnd, &ps);
509 	/* Check to see if this WM_PAINT is coming while we've got the GUI visible */
510 	if( manual_painting_needed )
511 	{
512 	    /* Update the display area */
513 	    if( !WIN32GFX_IsFullScreen() )
514 	    {
515 		if( DirectDraw_GetLockableType() != overlay_surface )
516 		    DX_Blit( 0, 0, 0, 0, WIN32GFX_GetWidth(), WIN32GFX_GetHeight(), BLIT_SRC );
517 	    }
518 	    else
519 	    {
520 		DirectDraw_Blt( primary_surface, NULL, secondary_surface, NULL, DDBLT_WAIT, NULL );
521 	    }
522 	}
523 	EndPaint (hWnd, &ps);
524 
525 	break;
526 
527      case WM_DROPFILES:
528 	if (DragQueryFile ((HDROP) wParam, (UINT) - 1, NULL, 0)) {
529 	    if (DragQueryFile ((HDROP) wParam, 0, NULL, 0) < 255)
530 		DragQueryFile ((HDROP) wParam, 0, changed_prefs.df[0], sizeof (changed_prefs.df[0]));
531 	}
532 	DragFinish ((HDROP) wParam);
533 	break;
534 
535      case WM_CAPTURECHANGED:
536 	if ((HWND)lParam != hAmigaWnd)
537 	    buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
538 	break;
539 
540      case WM_TIMER:
541 	finishjob ();
542 	break;
543 
544      case WM_CREATE:
545 	DragAcceptFiles (hWnd, TRUE);
546 	break;
547 
548      case WM_CLOSE:
549 	uae_quit ();
550 	return 0;
551 
552      case WM_WINDOWPOSCHANGED:
553 	if( GetWindowRect( hWnd, &amigawin_rect) )
554 	{
555 	    if( hMainWnd )
556 	    {
557 		if( hWinUAEKey && store_xy++)
558 		{
559 		    RegSetValueEx( hWinUAEKey, "xPos", 0, REG_DWORD, (LPBYTE)&amigawin_rect.left, sizeof( LONG ) );
560 		    RegSetValueEx( hWinUAEKey, "yPos", 0, REG_DWORD, (LPBYTE)&amigawin_rect.top, sizeof( LONG ) );
561 		}
562 	    }
563 	}
564 	break;
565 
566     case WM_MOVING:
567     case WM_MOVE:
568     WIN32GFX_WindowMove();
569     return TRUE;
570 
571     case WM_SIZING:
572     WIN32GFX_WindowSize();
573     return TRUE;
574     case WM_SIZE:
575     WIN32GFX_WindowSize();
576     return 0;
577 
578     case WM_GETMINMAXINFO:
579     rect.left=0;
580     rect.top=0;
581     lpmmi=(LPMINMAXINFO)lParam;
582     rect.right=320;
583     rect.bottom=256;
584     //AdjustWindowRectEx(&rect,WSTYLE,0,0);
585     lpmmi->ptMinTrackSize.x=rect.right-rect.left;
586     lpmmi->ptMinTrackSize.y=rect.bottom-rect.top;
587     return 0;
588 
589     default:
590 #if 0
591 #ifdef BSDSOCKET_SUPPORTED
592     if( message >= 0xB000 && message < 0xB000+MAXPENDINGASYNC*2 )
593     {
594 #if DEBUG_SOCKETS
595 	write_log ( "sockmsg(0x%x, 0x%x, 0x%x)\n", message, wParam, lParam );
596 #endif
597 	sockmsg( message, wParam, lParam );
598 	return 0;
599     }
600 #endif
601 #endif
602     break;
603     }
604 
605     return DefWindowProc (hWnd, message, wParam, lParam);
606 }
607 
MainWindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)608 static long FAR PASCAL MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
609 {
610     PAINTSTRUCT ps;
611     RECT rc;
612     HDC hDC;
613 
614     switch (message) {
615      case WM_LBUTTONDOWN:
616      case WM_MOUSEWHEEL:
617      case WM_MOUSEMOVE:
618      case WM_ACTIVATEAPP:
619      case WM_DROPFILES:
620      case WM_ACTIVATE:
621      case WM_SETCURSOR:
622      case WM_SYSCOMMAND:
623      case WM_KEYUP:
624      case WM_SYSKEYUP:
625      case WM_KEYDOWN:
626      case WM_SYSKEYDOWN:
627      case WM_LBUTTONUP:
628      case WM_MBUTTONDOWN:
629      case WM_MBUTTONUP:
630      case WM_RBUTTONDOWN:
631      case WM_RBUTTONUP:
632      case WM_MOVING:
633      case WM_MOVE:
634      case WM_SIZING:
635      case WM_SIZE:
636      case WM_GETMINMAXINFO:
637      case WM_CREATE:
638      case WM_DESTROY:
639      case WM_USER + 0x200:
640      case WM_CLOSE:
641      case WM_HELP:
642      case WM_DEVICECHANGE:
643 	return AmigaWindowProc (hWnd, message, wParam, lParam);
644 
645      case WM_DISPLAYCHANGE:
646 	if (!WIN32GFX_IsFullScreen && (wParam + 7) / 8 != DirectDraw_GetBytesPerPixel() )
647 	    WIN32GFX_DisplayChangeRequested();
648 	break;
649 
650      case WM_ENTERSIZEMOVE:
651 	in_sizemove++;
652 	break;
653 
654      case WM_EXITSIZEMOVE:
655 	in_sizemove--;
656 	/* fall through */
657 
658      case WM_WINDOWPOSCHANGED:
659 	WIN32GFX_WindowMove();
660 	if( hAmigaWnd && GetWindowRect (hAmigaWnd, &amigawin_rect) )
661 	{
662 	    if (in_sizemove > 0)
663 		break;
664 
665 	    if( !WIN32GFX_IsFullScreen() && hAmigaWnd )
666 	    {
667 		if( amigawin_rect.left & 3 )
668 		{
669 		    RECT rc2;
670 		    if( GetWindowRect( hMainWnd, &rc2 ) )
671 		    {
672 			MoveWindow (hMainWnd, rc2.left + 4 - amigawin_rect.left % 4, rc2.top,
673 				    rc2.right - rc2.left, rc2.bottom - rc2.top, TRUE);
674 		    }
675 		}
676 		//setmouseactive (0);
677 		return 0;
678 	    }
679 	}
680 	break;
681 
682      case WM_PAINT:
683 	hDC = BeginPaint (hWnd, &ps);
684 	GetClientRect (hWnd, &rc);
685 	DrawEdge (hDC, &rc, EDGE_SUNKEN, BF_RECT);
686 	EndPaint (hWnd, &ps);
687 	break;
688      case WM_NCLBUTTONDBLCLK:
689 	if (wParam == HTCAPTION) {
690 	    WIN32GFX_ToggleFullScreen();
691 	    return 0;
692 	}
693 	break;
694     default:
695     break;
696 
697     }
698 
699     return DefWindowProc (hWnd, message, wParam, lParam);
700 }
701 
handle_events(void)702 void handle_events (void)
703 {
704     MSG msg;
705 
706     while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
707 	TranslateMessage (&msg);
708 	DispatchMessage (&msg);
709     }
710 }
711 
712 /* Console Win32 helper routines */
713 void activate_debugger ();
714 
715 /* We're not a console-app anymore! */
setup_brkhandler(void)716 void setup_brkhandler (void)
717 {
718 }
719 
remove_brkhandler(void)720 void remove_brkhandler (void)
721 {
722 }
723 
WIN32_RegisterClasses(void)724 int WIN32_RegisterClasses( void )
725 {
726     WNDCLASS wc;
727     HDC hDC = GetDC( NULL );
728 
729     if( GetDeviceCaps( hDC, NUMCOLORS ) != -1 )
730 	g_dwBackgroundColor = RGB( 255, 0, 255 );
731     ReleaseDC( NULL, hDC );
732 
733     wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS;
734     wc.lpfnWndProc = AmigaWindowProc;
735     wc.cbClsExtra = 0;
736     wc.cbWndExtra = 0;
737     wc.hInstance = 0;
738     wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE( IDI_APPICON ) );
739     wc.hCursor = LoadCursor (NULL, IDC_ARROW);
740     wc.lpszMenuName = 0;
741     wc.lpszClassName = "AmigaPowah";
742     wc.hbrBackground = CreateSolidBrush( g_dwBackgroundColor );
743     if (!RegisterClass (&wc))
744 	return 0;
745 
746     wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
747     wc.lpfnWndProc = MainWindowProc;
748     wc.cbClsExtra = 0;
749     wc.cbWndExtra = 0;
750     wc.hInstance = 0;
751     wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE( IDI_APPICON ) );
752     wc.hCursor = LoadCursor (NULL, IDC_ARROW);
753     wc.hbrBackground = CreateSolidBrush( g_dwBackgroundColor );
754     wc.lpszMenuName = 0;
755     wc.lpszClassName = "PCsuxRox";
756     if (!RegisterClass (&wc))
757 	return 0;
758     return 1;
759 }
760 
761 #ifdef __GNUC__
762 #undef WINAPI
763 #define WINAPI
764 #endif
765 
766 static HINSTANCE hRichEdit = NULL, hHtmlHelp = NULL;
767 
768 #ifdef USE_ZLIB_DLL
769 static HINSTANCE hZlib = NULL;
770 FARPROC	pgzread = NULL, pgzopen = NULL, pgzclose = NULL, pgzwrite = NULL, pgzerror = NULL;
771 #endif
772 
WIN32_CleanupLibraries(void)773 int WIN32_CleanupLibraries( void )
774 {
775     if (hRichEdit)
776 	FreeLibrary (hRichEdit);
777 
778     if( hHtmlHelp )
779 	FreeLibrary( hHtmlHelp );
780 
781     if( hUIDLL )
782 	FreeLibrary( hUIDLL );
783 
784 #ifdef USE_ZLIB_DLL
785     if( hZlib )
786 	FreeLibrary( hZlib );
787 #endif
788 
789     return 1;
790 }
791 
792 /* HtmlHelp Initialization - optional component */
WIN32_InitHtmlHelp(void)793 int WIN32_InitHtmlHelp( void )
794 {
795     int result = 0;
796     if( hHtmlHelp = LoadLibrary( "HHCTRL.OCX" ) )
797     {
798 	pHtmlHelp = ( HWND(WINAPI *)(HWND, LPCSTR, UINT, LPDWORD ) )GetProcAddress( hHtmlHelp, "HtmlHelpA" );
799 	result = 1;
800     }
801 
802 
803     return result;
804 }
805 
806 #if 0
807 #define TESTING_LANGUAGES
808 #define TEST_LANGID LANG_GERMAN
809 //#define TEST_LANGID LANG_FRENCH
810 //#define TEST_LANGID LANG_TURKISH
811 #endif
812 
LoadGUI(void)813 static HMODULE LoadGUI( void )
814 {
815     HMODULE result = NULL;
816     LPCTSTR dllname = NULL;
817     LANGID language = GetUserDefaultLangID() & 0x3FF; // low 9-bits form the primary-language ID
818 #ifdef TESTING_LANGUAGES
819     language = TEST_LANGID;
820 #endif
821 
822     switch( language )
823     {
824     case LANG_AFRIKAANS:
825 	dllname = "WinUAE_Afrikaans.dll";
826 	break;
827     case LANG_ARABIC:
828 	dllname = "WinUAE_Arabic.dll";
829 	break;
830     case LANG_ARMENIAN:
831 	dllname = "WinUAE_Armenian.dll";
832 	break;
833     case LANG_ASSAMESE:
834 	dllname = "WinUAE_Assamese.dll";
835 	break;
836     case LANG_AZERI:
837 	dllname = "WinUAE_Azeri.dll";
838 	break;
839     case LANG_BASQUE:
840 	dllname = "WinUAE_Basque.dll";
841 	break;
842     case LANG_BELARUSIAN:
843 	dllname = "WinUAE_Belarusian.dll";
844 	break;
845     case LANG_BENGALI:
846 	dllname = "WinUAE_Bengali.dll";
847 	break;
848     case LANG_BULGARIAN:
849 	dllname = "WinUAE_Bulgarian.dll";
850 	break;
851     case LANG_CATALAN:
852 	dllname = "WinUAE_Catalan.dll";
853 	break;
854     case LANG_CHINESE:
855 	dllname = "WinUAE_Chinese.dll";
856 	break;
857     case LANG_CROATIAN:
858 	dllname = "WinUAE_CroatianSerbian.dll";
859 	break;
860     case LANG_CZECH:
861 	dllname = "WinUAE_Czech.dll";
862 	break;
863     case LANG_DANISH:
864 	dllname = "WinUAE_Danish.dll";
865 	break;
866     case LANG_DUTCH:
867 	dllname = "WinUAE_Dutch.dll";
868 	break;
869     case LANG_ESTONIAN:
870 	dllname = "WinUAE_Estonian.dll";
871 	break;
872     case LANG_FAEROESE:
873 	dllname = "WinUAE_Faeroese.dll";
874 	break;
875     case LANG_FARSI:
876 	dllname = "WinUAE_Farsi.dll";
877 	break;
878     case LANG_FINNISH:
879 	dllname = "WinUAE_Finnish.dll";
880 	break;
881     case LANG_FRENCH:
882 	dllname = "WinUAE_French.dll";
883 	break;
884     case LANG_GEORGIAN:
885 	dllname = "WinUAE_Georgian.dll";
886 	break;
887     case LANG_GERMAN:
888 	dllname = "WinUAE_German.dll";
889 	break;
890     case LANG_GREEK:
891 	dllname = "WinUAE_Greek.dll";
892 	break;
893     case LANG_GUJARATI:
894 	dllname = "WinUAE_Gujarati.dll";
895 	break;
896     case LANG_HEBREW:
897 	dllname = "WinUAE_Hebrew.dll";
898 	break;
899     case LANG_HINDI:
900 	dllname = "WinUAE_Hindi.dll";
901 	break;
902     case LANG_HUNGARIAN:
903 	dllname = "WinUAE_Hungarian.dll";
904 	break;
905     case LANG_ICELANDIC:
906 	dllname = "WinUAE_Icelandic.dll";
907 	break;
908     case LANG_INDONESIAN:
909 	dllname = "WinUAE_Indonesian.dll";
910 	break;
911     case LANG_ITALIAN:
912 	dllname = "WinUAE_Italian.dll";
913 	break;
914     case LANG_JAPANESE:
915 	dllname = "WinUAE_Japanese.dll";
916 	break;
917     case LANG_KANNADA:
918 	dllname = "WinUAE_Kannada.dll";
919 	break;
920     case LANG_KASHMIRI:
921 	dllname = "WinUAE_Kashmiri.dll";
922 	break;
923     case LANG_KAZAK:
924 	dllname = "WinUAE_Kazak.dll";
925 	break;
926     case LANG_KONKANI:
927 	dllname = "WinUAE_Konkani.dll";
928 	break;
929     case LANG_KOREAN:
930 	dllname = "WinUAE_Korean.dll";
931 	break;
932     case LANG_LATVIAN:
933 	dllname = "WinUAE_Latvian.dll";
934 	break;
935     case LANG_LITHUANIAN:
936 	dllname = "WinUAE_Lithuanian.dll";
937 	break;
938     case LANG_MACEDONIAN:
939 	dllname = "WinUAE_Macedonian.dll";
940 	break;
941     case LANG_MALAY:
942 	dllname = "WinUAE_Malay.dll";
943 	break;
944     case LANG_MALAYALAM:
945 	dllname = "WinUAE_Malayalam.dll";
946 	break;
947     case LANG_MANIPURI:
948 	dllname = "WinUAE_Manipuri.dll";
949 	break;
950     case LANG_MARATHI:
951 	dllname = "WinUAE_Marathi.dll";
952 	break;
953     case LANG_NEPALI:
954 	dllname = "WinUAE_Nepali.dll";
955 	break;
956     case LANG_NORWEGIAN:
957 	dllname = "WinUAE_Norwegian.dll";
958 	break;
959     case LANG_ORIYA:
960 	dllname = "WinUAE_Oriya.dll";
961 	break;
962     case LANG_POLISH:
963 	dllname = "WinUAE_Polish.dll";
964 	break;
965     case LANG_PORTUGUESE:
966 	dllname = "WinUAE_Portuguese.dll";
967 	break;
968     case LANG_PUNJABI:
969 	dllname = "WinUAE_Punjabi.dll";
970 	break;
971     case LANG_ROMANIAN:
972 	dllname = "WinUAE_Romanian.dll";
973 	break;
974     case LANG_RUSSIAN:
975 	dllname = "WinUAE_Russian.dll";
976 	break;
977     case LANG_SANSKRIT:
978 	dllname = "WinUAE_Sanskrit.dll";
979 	break;
980     case LANG_SINDHI:
981 	dllname = "WinUAE_Sindhi.dll";
982 	break;
983     case LANG_SLOVAK:
984 	dllname = "WinUAE_Slovak.dll";
985 	break;
986     case LANG_SLOVENIAN:
987 	dllname = "WinUAE_Slovenian.dll";
988 	break;
989     case LANG_SPANISH:
990 	dllname = "WinUAE_Spanish.dll";
991 	break;
992     case LANG_SWAHILI:
993 	dllname = "WinUAE_Swahili.dll";
994 	break;
995     case LANG_SWEDISH:
996 	dllname = "WinUAE_Swedish.dll";
997 	break;
998     case LANG_TAMIL:
999 	dllname = "WinUAE_Tamil.dll";
1000 	break;
1001     case LANG_TATAR:
1002 	dllname = "WinUAE_Tatar.dll";
1003 	break;
1004     case LANG_TELUGU:
1005 	dllname = "WinUAE_Telugu.dll";
1006 	break;
1007     case LANG_THAI:
1008 	dllname = "WinUAE_Thai.dll";
1009 	break;
1010     case LANG_TURKISH:
1011 	dllname = "WinUAE_Turkish.dll";
1012 	break;
1013     case LANG_UKRAINIAN:
1014 	dllname = "WinUAE_Ukrainian.dll";
1015 	break;
1016     case LANG_URDU:
1017 	dllname = "WinUAE_Urdu.dll";
1018 	break;
1019     case LANG_UZBEK:
1020 	dllname = "WinUAE_Uzbek.dll";
1021 	break;
1022     case LANG_VIETNAMESE:
1023 	dllname = "WinUAE_Vietnamese.dll";
1024 	break;
1025     case 0x400:
1026 	dllname = "guidll.dll";
1027 	break;
1028     }
1029 
1030     if( dllname )
1031     {
1032 	TCHAR  szFilename[ MAX_PATH ];
1033 	DWORD  dwVersionHandle, dwFileVersionInfoSize;
1034 	LPVOID lpFileVersionData = NULL;
1035 	BOOL   success = FALSE;
1036 	result = LoadLibrary( dllname );
1037 	if( result && GetModuleFileName( result, (LPTSTR)&szFilename, MAX_PATH ) )
1038 	{
1039 	    dwFileVersionInfoSize = GetFileVersionInfoSize( szFilename, &dwVersionHandle );
1040 	    if( dwFileVersionInfoSize )
1041 	    {
1042 		if( lpFileVersionData = calloc( 1, dwFileVersionInfoSize ) )
1043 		{
1044 		    if( GetFileVersionInfo( szFilename, dwVersionHandle, dwFileVersionInfoSize, lpFileVersionData ) )
1045 		    {
1046 			VS_FIXEDFILEINFO *vsFileInfo = NULL;
1047 			UINT uLen;
1048 			if( VerQueryValue( lpFileVersionData, TEXT("\\"), (void **)&vsFileInfo, &uLen ) )
1049 			{
1050 			    if( vsFileInfo &&
1051 				( HIWORD(vsFileInfo->dwProductVersionMS) == UAEMAJOR )
1052 				&& ( LOWORD(vsFileInfo->dwProductVersionMS) == UAEMINOR )
1053 				&& ( HIWORD(vsFileInfo->dwProductVersionLS) == UAESUBREV )
1054 // Change this to an #if 1 when the WinUAE Release version (as opposed to UAE-core version)
1055 // requires a GUI-DLL change...
1056 #if 0
1057 				&& ( LOWORD(vsFileInfo->dwProductVersionLS) == WINUAERELEASE)
1058 #endif
1059 				)
1060 			    {
1061 				success = TRUE;
1062 			    }
1063 			}
1064 		    }
1065 		    free( lpFileVersionData );
1066 		}
1067 	    }
1068 	}
1069 	if( result && !success )
1070 	{
1071 	    FreeLibrary( result );
1072 	    result = NULL;
1073 	}
1074     }
1075 
1076     return result;
1077 }
1078 
1079 #ifndef _WIN32_WCE
1080 /* try to load COMDLG32 and DDRAW, initialize csDraw */
WIN32_InitLibraries(void)1081 int WIN32_InitLibraries( void )
1082 {
1083     int result = 1;
1084     /* Determine our processor speed and capabilities */
1085     figure_processor_speed();
1086 
1087     /* Make sure we do an InitCommonControls() to get some advanced controls */
1088     InitCommonControls();
1089 
1090     hRichEdit = LoadLibrary( "RICHED32.DLL" );
1091 
1092     hUIDLL = LoadGUI();
1093 
1094 #ifdef USE_ZLIB_DLL
1095     hZlib = LoadLibrary( "ZLIB.DLL" );
1096     if( hZlib )
1097     {
1098 	pgzread = GetProcAddress( hZlib, "gzread" );
1099 	pgzopen = GetProcAddress( hZlib, "gzopen" );
1100 	pgzclose = GetProcAddress( hZlib, "gzclose" );
1101 	pgzwrite = GetProcAddress( hZlib, "gzwrite" );
1102 	pgzerror = GetProcAddress( hZlib, "gzerror" );
1103 	if( !pgzread || !pgzopen || !pgzclose || !pgzwrite || !pgzerror)
1104 	{
1105 	    FreeLibrary( hZlib );
1106 	    hZlib = NULL;
1107 	}
1108     }
1109 #endif
1110     return result;
1111 }
1112 #endif
1113 
1114 /* Mathias says: "this truly sucks, I'll include a native gunzip() routine soon" */
1115 
1116 #ifdef USE_ZLIB_DLL
1117 extern FARPROC	pgzread, pgzopen, pgzclose, pgzwrite, pgzerror;
1118 #define GZOPEN( X, Y ) (gzFile)pgzopen( X, Y )
1119 #define GZCLOSE( X ) (int)pgzclose( X )
1120 #define GZREAD( X, Y, Z ) (int)pgzread( X, Y, Z )
1121 
1122 #define ZLIB_BUFFER_SIZE 32767
1123 
1124 /* gzip decompression via zlib */
zlib_gunzip(const char * src,char * dst)1125 static int zlib_gunzip( const char *src, char *dst )
1126 {
1127     int result = 0, gzResult = 0;
1128     gzFile zSrc = NULL;
1129     FILE *fDst = NULL;
1130     size_t filesize = 0;
1131     uae_u8 *buffer = NULL;
1132 
1133     if( hZlib )
1134     {
1135 	zSrc = GZOPEN( src, "rb" );
1136 	fDst = fopen( dst, "wb" );
1137 	buffer = xmalloc( ZLIB_BUFFER_SIZE + 1 );
1138 
1139 	if( zSrc && fDst && buffer )
1140 	{
1141 	    DWORD dwWritten = 0;
1142 	    result = 1;
1143 	    do
1144 	    {
1145 		gzResult = GZREAD( zSrc, buffer, ZLIB_BUFFER_SIZE );
1146 		if( gzResult > 0 )
1147 		{
1148 		    if( fwrite( buffer, gzResult, 1, fDst ) != 1 )
1149 		    {
1150 			result = 0;
1151 			break;
1152 		    }
1153 		}
1154 	    } while( gzResult == ZLIB_BUFFER_SIZE );
1155 	}
1156 
1157 	if( zSrc )
1158 	{
1159 	    GZCLOSE( zSrc );
1160 	}
1161 
1162 	if( fDst )
1163 	{
1164 	    fclose( fDst );
1165 	}
1166     }
1167     return result;
1168 }
1169 #endif
1170 
1171 static char *uncompress_error[2] = { "Error: You need zlib.dll to use .adz/.roz files!\n",
1172 				    "Error: You need xdms.exe (32 bit) to use .dms files!\n" };
1173 
uncompress_hack(int type,const char * src,const char * dst)1174 int uncompress_hack( int type, const char *src, const char *dst)
1175 {
1176     int result = 0;
1177     char fullname[1024];
1178     char buf[1024];
1179     char cmd[256];
1180     char *posn = NULL;
1181     STARTUPINFO si = {sizeof si};
1182     PROCESS_INFORMATION pi;
1183 
1184     strcpy( fullname, dst );
1185 
1186     if( type == 1 )
1187     {
1188 #ifdef USE_ZLIB_DLL
1189 	result = zlib_gunzip( src, fullname );
1190 	if( !result )
1191 	{
1192 	    gui_message( uncompress_error[type-1] );
1193 	}
1194 	return result;
1195 #else
1196 	strcpy( cmd, "gzip.exe -f -d" );
1197 	strcat( fullname, ".gz" );
1198 #endif
1199     }
1200     else if( type == 2 )
1201     {
1202 	strcpy( cmd, "xdms.exe u" );
1203 	posn = strrchr( fullname, '.' );
1204 	if( posn )
1205 	{
1206 	    *posn = 0;
1207 	    strcat( fullname, ".dms" );
1208 	}
1209     }
1210 
1211     if( CopyFile( src, fullname, FALSE ) )
1212     {
1213 	sprintf (buf, "%s %s +%s", cmd, fullname, dst );
1214 	si.dwFlags = STARTF_USESTDHANDLES;
1215 	if( CreateProcess( NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ) )
1216 	{
1217 	    WaitForSingleObject( pi.hProcess, INFINITE );
1218 	    result = -1;
1219 	}
1220 	else
1221 	{
1222 	    gui_message( uncompress_error[type-1] );
1223 	}
1224     }
1225 
1226     /* Special handling for broken xdms.exe */
1227     if( type == 2 )
1228     {
1229 	DeleteFile( fullname );     /* Delete the uaeXX.dms file */
1230     }
1231 
1232     return result;
1233 }
1234 
1235 /* console window for debugging messages */
1236 /* Brian: disable for release version if you want (TW) */
1237 
1238 #define WRITE_LOG_BUF_SIZE 4096
1239 
1240 static int consoleopen = 0;
1241 HANDLE stdinput,stdoutput;
1242 
openconsole(void)1243 static void openconsole(void)
1244 {
1245     if(consoleopen) return;
1246     AllocConsole();
1247     stdinput=GetStdHandle(STD_INPUT_HANDLE);
1248     stdoutput=GetStdHandle(STD_OUTPUT_HANDLE);
1249     SetConsoleMode(stdinput,ENABLE_PROCESSED_INPUT|ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_OUTPUT);
1250     consoleopen = 1;
1251 }
1252 
1253 /* console functions for debugger */
1254 
console_out(const char * format,...)1255 void console_out (const char *format,...)
1256 {
1257     va_list parms;
1258     char buffer[WRITE_LOG_BUF_SIZE];
1259     DWORD temp;
1260 
1261     va_start (parms, format);
1262     _vsnprintf( buffer, WRITE_LOG_BUF_SIZE-1, format, parms );
1263     va_end (parms);
1264     openconsole();
1265     WriteConsole(stdoutput,buffer,strlen(buffer),&temp,0);
1266 }
1267 
console_get(char * out,int maxlen)1268 int console_get (char *out, int maxlen)
1269 {
1270     DWORD len,totallen;
1271 
1272     totallen=0;
1273     while(maxlen>0)
1274     {
1275 	    ReadConsole(stdinput,out,1,&len,0);
1276 	    if(*out == 13) break;
1277 	    out++;
1278 	    maxlen--;
1279 	    totallen++;
1280     }
1281     *out=0;
1282     return totallen;
1283 }
1284 
console_flush(void)1285 void console_flush (void)
1286 {
1287 }
1288 
1289 /* GCC/EGCS wants this write_log in order to work from socket-land and to do traces */
1290 #ifdef __GNUC__
write_log(const char * format,...)1291 void write_log (const char *format, ...)
1292 {
1293     int result = 0;
1294     DWORD numwritten;
1295     char buffer[12];
1296     va_list parms;
1297     int count = 0;
1298     int *blah = NULL;
1299 
1300     if( debugfile )
1301     {
1302 #if defined HAVE_GETTICKCOUNT && defined TIMESTAMP_LOGS
1303 	{
1304 	    sprintf( buffer, "%7d - ", GetTickCount() );
1305 	    fprintf( debugfile, buffer );
1306 	}
1307 #endif
1308 	va_start (parms, format);
1309 	count = vfprintf( debugfile, format, parms );
1310 	fflush( debugfile );
1311 	if( count >= WRITE_LOG_BUF_SIZE-1 )
1312 	{
1313 	    fprintf( debugfile, "SHIT in write_log ()\n" );
1314 	    fflush( debugfile );
1315 	    *blah = 0; /* Access Violation here! */
1316 	    abort();
1317 	}
1318 	else
1319 	    result = count;
1320 	va_end (parms);
1321     }
1322 }
1323 #else /* MSVC likes this one, and so do I */
write_log(const char * format,...)1324 int write_log ( const char *format, ... )
1325 {
1326     int result = 0;
1327 #ifdef _DEBUG
1328     DWORD numwritten;
1329 #endif
1330     char buffer[ WRITE_LOG_BUF_SIZE ];
1331     va_list parms;
1332     int count = 0;
1333     int *blah = (int *)0xdeadbeef;
1334 
1335     va_start (parms, format);
1336     count = _vsnprintf( buffer, WRITE_LOG_BUF_SIZE-1, format, parms );
1337 #if defined HAVE_GETTICKCOUNT && defined TIMESTAMP_LOGS
1338     {
1339 	char buffme[WRITE_LOG_BUF_SIZE];
1340 	sprintf( buffme, "%7d - %s", GetTickCount(), buffer );
1341 	OutputDebugString( buffme );
1342 	if( debugfile )
1343 	    fprintf( debugfile, buffme );
1344 	result = strlen( buffme );
1345     }
1346 #else
1347     OutputDebugString( buffer );
1348     if( debugfile )
1349     {
1350 	fprintf( debugfile, buffer );
1351 	fflush( debugfile );
1352     }
1353     result = strlen( buffer );
1354 #endif
1355 #ifdef _DEBUG
1356     openconsole();
1357     WriteConsole(stdoutput,buffer,strlen(buffer),&numwritten,0);
1358 #endif
1359     va_end (parms);
1360     return result;
1361 }
1362 #endif
1363 
debuggable(void)1364 int debuggable (void)
1365 {
1366     return 0;
1367 }
1368 
needmousehack(void)1369 int needmousehack (void)
1370 {
1371     if( WIN32GFX_IsFullScreen() || WIN32GFX_IsPicassoScreen() )
1372 	return 0;
1373     else
1374 	return 1;
1375 }
1376 
LED(int a)1377 void LED (int a)
1378 {
1379 }
1380 
logging_init(void)1381 void logging_init( void )
1382 {
1383     char debugfilename[MAX_PATH];
1384     if (1) {
1385 	sprintf( debugfilename, "%s\\winuaelog.txt", start_path );
1386 	if( !debugfile )
1387 	    debugfile = fopen( debugfilename, "wt" );
1388     }
1389     write_log ( "%s\n", VersionStr );
1390     write_log ("\n(c) 1995-2001 Bernd Schmidt   - Core UAE concept and implementation."
1391 	       "\n(c) 1996-1999 Mathias Ortmann - Win32 port and bsdsocket support."
1392 	       "\n(c) 1996-2001 Brian King      - Win32 port, Picasso96 RTG, and GUI."
1393 	       "\n(c) 1998-2001 Toni Wilen      - AGA chipset, NTSC/PAL modes.\n"
1394 	       "\n(c) 2000-2001 Bernd Meyer     - JIT engine.\n"
1395 	       "\n(c) 2000-2001 Bernd Roesch    - MIDI input, many fixes.\n"
1396 	       "\nPress F12 to show the Settings Dialog (GUI), Alt-F4 to quit."
1397 	       "\nEnd+F1 changes floppy 0, End+F2 changes floppy 1, etc.\n"
1398 	       "\nhttp://www.codepoet.com/UAE/\n\n");
1399 }
1400 
logging_cleanup(void)1401 void logging_cleanup( void )
1402 {
1403     if( debugfile )
1404 	fclose( debugfile );
1405 }
1406 
1407 static const char *sound_styles[] = { "waveout_looping", "waveout_dblbuff", "dsound_looping", "dsound_dblbuff", 0 };
1408 
target_save_options(FILE * f,struct uae_prefs * p)1409 void target_save_options (FILE *f, struct uae_prefs *p)
1410 {
1411     fprintf (f, "win32.middle_mouse=%s\n", p->win32_middle_mouse ? "true" : "false");
1412     fprintf (f, "win32.logfile=%s\n", p->win32_logfile ? "true" : "false");
1413     fprintf (f, "win32.map_drives=%s\n", p->win32_automount_drives ? "true" : "false" );
1414     fprintf (f, "win32.serial_port=%s\n", p->use_serial ? p->sername : "none" );
1415     fprintf (f, "win32.parallel_port=%s\n", p->prtname[0] ? p->prtname : "none" );
1416     fprintf (f, "win32.iconified_nospeed=%s\n", p->win32_iconified_nospeed ? "true" : "false");
1417     fprintf (f, "win32.iconified_nosound=%s\n", p->win32_iconified_nosound ? "true" : "false");
1418     fprintf (f, "win32.no_overlay=%s\n", p->win32_no_overlay ? "true" : "false" );
1419 }
1420 
target_parse_option(struct uae_prefs * p,char * option,char * value)1421 int target_parse_option (struct uae_prefs *p, char *option, char *value)
1422 {
1423     int result = (cfgfile_yesno (option, value, "middle_mouse", &p->win32_middle_mouse)
1424 		  || cfgfile_yesno (option, value, "logfile", &p->win32_logfile)
1425 		  || cfgfile_yesno (option, value, "no_overlay", &p->win32_no_overlay)
1426 		  || cfgfile_yesno (option, value, "map_drives", &p->automount_drives)
1427 		  || cfgfile_yesno (option, value, "iconified_nospeed", &p->win32_iconified_nospeed)
1428 		  || cfgfile_yesno (option, value, "iconified_nosound", &p->win32_iconified_nosound)
1429 		  || cfgfile_string (option, value, "serial_port", &p->sername[0], 256)
1430 		  || cfgfile_string (option, value, "parallel_port", &p->prtname[0], 256));
1431 
1432     if (p->sername[0] == 'n')
1433 	p->use_serial = 0;
1434     else
1435 	p->use_serial = 1;
1436 
1437     return 0;
1438 }
1439 
WIN32_HandleRegistryStuff(void)1440 void WIN32_HandleRegistryStuff( void )
1441 {
1442     RGBFTYPE colortype      = RGBFB_NONE;
1443     DWORD dwType            = REG_DWORD;
1444     DWORD dwDisplayInfoSize = sizeof( colortype );
1445     DWORD disposition;
1446     char path[MAX_PATH] = "";
1447     HKEY hWinUAEKeyLocal = NULL;
1448 
1449     /* Create/Open the hWinUAEKey which points to our config-info */
1450     if( RegCreateKeyEx( HKEY_CLASSES_ROOT, ".uae", 0, "", REG_OPTION_NON_VOLATILE,
1451 			  KEY_ALL_ACCESS, NULL, &hWinUAEKey, &disposition ) == ERROR_SUCCESS )
1452     {
1453 	// Regardless of opening the existing key, or creating a new key, we will write the .uae filename-extension
1454 	// commands in.  This way, we're always up to date.
1455 
1456 	/* Set our (default) sub-key to point to the "WinUAE" key, which we then create */
1457 	RegSetValueEx( hWinUAEKey, "", 0, REG_SZ, (CONST BYTE *)"WinUAE", strlen( "WinUAE" ) + 1 );
1458 
1459 	if( ( RegCreateKeyEx( HKEY_CLASSES_ROOT, "WinUAE\\shell\\Edit\\command", 0, "", REG_OPTION_NON_VOLATILE,
1460 			      KEY_ALL_ACCESS, NULL, &hWinUAEKeyLocal, &disposition ) == ERROR_SUCCESS ) )
1461 	{
1462 	    /* Set our (default) sub-key to BE the "WinUAE" command for editing a configuration */
1463 	    sprintf( path, "%s\\WinUAE.exe -f \"%%1\" -s use_gui=yes", start_path );
1464 	    RegSetValueEx( hWinUAEKeyLocal, "", 0, REG_SZ, (CONST BYTE *)path, strlen( path ) + 1 );
1465 	}
1466 	RegCloseKey( hWinUAEKeyLocal );
1467 
1468 	if( ( RegCreateKeyEx( HKEY_CLASSES_ROOT, "WinUAE\\shell\\Open\\command", 0, "", REG_OPTION_NON_VOLATILE,
1469 			      KEY_ALL_ACCESS, NULL, &hWinUAEKeyLocal, &disposition ) == ERROR_SUCCESS ) )
1470 	{
1471 	    /* Set our (default) sub-key to BE the "WinUAE" command for launching a configuration */
1472 	    sprintf( path, "%s\\WinUAE.exe -f \"%%1\"", start_path );
1473 	    RegSetValueEx( hWinUAEKeyLocal, "", 0, REG_SZ, (CONST BYTE *)path, strlen( path ) + 1 );
1474 	}
1475 	RegCloseKey( hWinUAEKeyLocal );
1476     }
1477     else
1478     {
1479 	char szMessage[ MAX_PATH ];
1480 	WIN32GUI_LoadUIString( IDS_REGKEYCREATEFAILED, szMessage, MAX_PATH );
1481 	gui_message( szMessage );
1482 	hWinUAEKey = NULL;
1483     }
1484     RegCloseKey( hWinUAEKey );
1485 
1486     /* Create/Open the hWinUAEKey which points our config-info */
1487     if( RegCreateKeyEx( HKEY_CURRENT_USER, "Software\\CodePoet Computing\\WinUAE", 0, "", REG_OPTION_NON_VOLATILE,
1488 			  KEY_ALL_ACCESS, NULL, &hWinUAEKey, &disposition ) == ERROR_SUCCESS )
1489     {
1490 	if( disposition == REG_CREATED_NEW_KEY )
1491 	{
1492 	    /* Create and initialize all our sub-keys to the default values */
1493 	    colortype = 0;
1494 	    RegSetValueEx( hWinUAEKey, "DisplayInfo", 0, REG_DWORD, (CONST BYTE *)&colortype, sizeof( colortype ) );
1495 	    RegSetValueEx( hWinUAEKey, "xPos", 0, REG_DWORD, (CONST BYTE *)&colortype, sizeof( colortype ) );
1496 	    RegSetValueEx( hWinUAEKey, "yPos", 0, REG_DWORD, (CONST BYTE *)&colortype, sizeof( colortype ) );
1497 	    RegSetValueEx( hWinUAEKey, "FloppyPath", 0, REG_SZ, (CONST BYTE *)start_path, strlen( start_path ) + 1 );
1498 	    RegSetValueEx( hWinUAEKey, "KickstartPath", 0, REG_SZ, (CONST BYTE *)start_path, strlen( start_path ) + 1 );
1499 	    RegSetValueEx( hWinUAEKey, "hdfPath", 0, REG_SZ, (CONST BYTE *)start_path, strlen( start_path ) + 1 );
1500 	}
1501 	// Set this even when we're opening an existing key, so that the version info is always up to date.
1502 	RegSetValueEx( hWinUAEKey, "Version", 0, REG_SZ, (CONST BYTE *)VersionStr, strlen( VersionStr ) + 1 );
1503 
1504 	RegQueryValueEx( hWinUAEKey, "DisplayInfo", 0, &dwType, (LPBYTE)&colortype, &dwDisplayInfoSize );
1505 	if( colortype == 0 ) /* No color information stored in the registry yet */
1506 	{
1507 	    char szMessage[ 4096 ];
1508 	    char szTitle[ MAX_PATH ];
1509 	    WIN32GUI_LoadUIString( IDS_GFXCARDCHECK, szMessage, 4096 );
1510 	    WIN32GUI_LoadUIString( IDS_GFXCARDTITLE, szTitle, MAX_PATH );
1511 
1512 	    if( MessageBox( NULL, szMessage, szTitle,
1513 		MB_YESNO | MB_ICONWARNING | MB_TASKMODAL | MB_SETFOREGROUND ) == IDYES )
1514 	    {
1515 		colortype = WIN32GFX_FigurePixelFormats(0);
1516 		RegSetValueEx( hWinUAEKey, "DisplayInfo", 0, REG_DWORD, (CONST BYTE *)&colortype, sizeof( colortype ) );
1517 	    }
1518 	}
1519 	if( colortype )
1520 	{
1521 	    /* Set the 16-bit pixel format for the appropriate modes */
1522 	    WIN32GFX_FigurePixelFormats( colortype );
1523 	}
1524     }
1525     else
1526     {
1527 	char szMessage[ MAX_PATH ];
1528 	WIN32GUI_LoadUIString( IDS_REGKEYCREATEFAILED, szMessage, MAX_PATH );
1529 	gui_message( szMessage );
1530 	hWinUAEKey = NULL;
1531     }
1532 }
1533 
machdep_init(void)1534 void machdep_init (void)
1535 {
1536 }
1537 
1538 char *start_path = NULL;
1539 char help_file[ MAX_PATH ];
1540 
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)1541 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
1542 		    int nCmdShow)
1543 {
1544     char *posn;
1545     HANDLE hMutex;
1546     OSVERSIONINFO osVersion;
1547 
1548 #ifdef __GNUC__
1549     __asm__ ("leal -2300*1024(%%esp),%0" : "=r" (win32_stackbase) :);
1550 #else
1551 __asm{
1552     mov eax,esp
1553     sub eax,2300*1024
1554     mov win32_stackbase,eax
1555  }
1556 #endif
1557 
1558     hInst = hInstance;
1559     hMutex = CreateMutex( NULL, FALSE, "WinUAE Instantiated" ); // To tell the installer we're running
1560 
1561     osVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
1562     if( GetVersionEx( &osVersion ) )
1563     {
1564 	if( ( osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT ) &&
1565 	    ( osVersion.dwMajorVersion <= 4 ) )
1566 	{
1567 	    /* WinUAE not supported on this version of Windows... */
1568 	    char szWrongOSVersion[ MAX_PATH ];
1569 	    WIN32GUI_LoadUIString( IDS_WRONGOSVERSION, szWrongOSVersion, MAX_PATH );
1570 	    gui_message( szWrongOSVersion );
1571 	    return FALSE;
1572 	}
1573     }
1574 
1575     /* Get our executable's root-path */
1576     if( ( start_path = xmalloc( MAX_PATH ) ) )
1577     {
1578 	GetModuleFileName( NULL, start_path, MAX_PATH );
1579 	if( ( posn = strrchr( start_path, '\\' ) ) )
1580 	    *posn = 0;
1581 	sprintf( help_file, "%s\\WinUAE.chm", start_path );
1582 
1583 	sprintf( VersionStr, "WinUAE %d.%d.%d, Release %d%s", UAEMAJOR, UAEMINOR, UAESUBREV, WINUAERELEASE, WINUAEBETA ? WINUAEBETASTR : "" );
1584 
1585 	logging_init ();
1586 	printf ("Hello, world\n");
1587 
1588 	if( WIN32_RegisterClasses() && WIN32_InitLibraries() && DirectDraw_Start() )
1589 	{
1590 	    struct foo {
1591 		DEVMODE actual_devmode;
1592 		char overrun[8];
1593 	    } devmode;
1594 
1595 	    DWORD i = 0;
1596 
1597 	    DirectDraw_EnumDisplayModes( 0, modesCallback );
1598 
1599 	    memset( &devmode, 0, sizeof(DEVMODE) + 8 );
1600 	    devmode.actual_devmode.dmSize = sizeof(DEVMODE);
1601 	    devmode.actual_devmode.dmDriverExtra = 8;
1602 #define ENUM_CURRENT_SETTINGS ((DWORD)-1)
1603 	    if( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, (LPDEVMODE)&devmode ) )
1604 	    {
1605 		default_freq = devmode.actual_devmode.dmDisplayFrequency;
1606 		write_log ( "Your Windows desktop refresh frequency is %d Hz\n", default_freq );
1607 		if( default_freq >= 70 )
1608 		    default_freq = 70;
1609 		else
1610 		    default_freq = 60;
1611 	    }
1612 
1613 	    WIN32_HandleRegistryStuff();
1614 	    if( WIN32_InitHtmlHelp() == 0 )
1615 	    {
1616 		char szMessage[ MAX_PATH ];
1617 		WIN32GUI_LoadUIString( IDS_NOHELP, szMessage, MAX_PATH );
1618 		write_log ( szMessage );
1619 	    }
1620 
1621 	    DirectDraw_Release();
1622 #ifdef __MINGW32__
1623 	    real_main (_argc, _argv);
1624 #else
1625 	    real_main (__argc, __argv);
1626 #endif
1627 	}
1628 	free( start_path );
1629     }
1630 
1631     WIN32_CleanupLibraries();
1632     _fcloseall();
1633     if( hWinUAEKey )
1634 	RegCloseKey( hWinUAEKey );
1635     CloseHandle( hMutex );
1636     return FALSE;
1637 }
1638 
1639