|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Win32 interface
5: *
6: * Copyright 1997 Mathias Ortmann
7: */
8:
9: #ifdef __GNUC__
10: #define __int64 long long
11: #include "machdep/winstuff.h"
12: #else
13: #include <windows.h>
14: #include <ddraw.h>
15: #include <stdlib.h>
16: #include <stdarg.h>
17: #include <commctrl.h>
18: #include <commdlg.h>
19: #include <stdio.h>
20: #include <fcntl.h>
21: #include <sys/stat.h>
22: #include <io.h>
23: #endif
24:
25: #include "config.h"
26: #include "sysconfig.h"
27: #include "sysdeps.h"
28:
29: #include "options.h"
30: #include "gensound.h"
31: #include "sounddep/sound.h"
32: #include "uae.h"
33: #include "threaddep/penguin.h"
34: #include "memory.h"
35: #include "custom.h"
36: #include "events.h"
37: #include "xwin.h"
38: #include "keyboard.h"
39: #include "picasso96.h"
40:
41: #include "osdep/win32gui.h"
42: #include "resource.h"
43: #include "osdep/win32.h"
44:
45: extern struct picasso_vidbuf_description picasso_vidinfo;
46: #define IHF_WINDOWHIDDEN 6
47:
48: static BOOL (WINAPI *pGetOpenFileNameA) (LPOPENFILENAME);
49: static HRESULT (WINAPI *pDirectDrawCreate) (GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *);
50: static HRESULT CALLBACK modesCallback (LPDDSURFACEDESC modeDesc, LPVOID context);
51:
52: HWND hAmigaWnd, hMainWnd;
53: HINSTANCE hInst;
54: /*DWORD Keys;*/
55: static RECT amigawin_rect;
56:
57: drive_specs drives[NUM_DRIVES];
58: char *start_path = NULL;
59:
60: static LPDIRECTDRAW lpDD;
61: static LPDIRECTDRAWSURFACE lpDDS;
62: static LPDIRECTDRAWCLIPPER lpDDC;
63: static LPDIRECTDRAWPALETTE lpDDP;
64: static DDSURFACEDESC ddsd;
65: HANDLE hEmuThread;
66:
67: static HDC hBackDC;
68: static HBITMAP hBackBM;
69:
70: static CRITICAL_SECTION csDraw;
71:
72: #define TITLETEXT PROGNAME " -- Amiga Display"
73: char VersionStr[256];
74: extern int current_width, current_height;
75:
76: static uae_sem_t picasso_switch_sem;
77:
78: static int fullscreen = 0;
79: int current_width, current_height;
80: static int current_pixbytes;
81:
82: static int changemode;
83:
84: static int screen_is_picasso = 0;
85: static int picasso_fullscreen = 1;
86: int amiga_fullscreen = 1, customsize = 0;
87:
88: int bActive;
89: int capslock;
90: int toggle_sound;
91:
92: int process_desired_pri;
93:
94: int cycles_per_instruction = 4;
95: int good_cpu = 0;
96:
97: BOOL allow_quit_from_property_sheet = TRUE;
98: BOOL viewing_child = FALSE;
99:
100: static char scrlinebuf[8192]; /* this is too large, but let's rather play on the safe side here */
101: static int scrindirect;
102:
103: static void set_linemem (void)
104: {
105: if (scrindirect)
106: gfxvidinfo.linemem = scrlinebuf;
107: else
108: gfxvidinfo.linemem = 0;
109: }
110:
111: /* Keyboard emulation, Win32 helper routines. */
112: static LPARAM keysdown[256];
113: static short numkeysdown;
114:
115: int getcapslock (void)
116: {
117: BYTE keyState[256];
118:
119: GetKeyboardState (keyState);
120: return keyState[VK_CAPITAL] & 1;
121: }
122:
123: int helppressed (void)
124: {
125: return GetAsyncKeyState (VK_END) & 0x8000;
126: }
127:
128: int shiftpressed (void)
129: {
130: return GetAsyncKeyState (VK_SHIFT) & 0x8000 ? 1 : 0;
131: }
132:
133: int checkkey (int vkey, LPARAM lParam)
134: {
135: switch (vkey) {
136: case VK_SHIFT:
137: case VK_LSHIFT:
138: case VK_RSHIFT:
139: case VK_CONTROL:
140: case VK_LCONTROL:
141: case VK_RCONTROL:
142: case VK_MENU:
143: case VK_LMENU:
144: case VK_RMENU:
145: return GetKeyState (vkey) & 0x8000;
146: }
147: return GetAsyncKeyState (vkey) & 0x8000;
148: }
149:
150: /* Mouse emulation, Win32 interface */
151: static int mousecx = 160, mousecy = 100, mousedx = 160, mousedy = 100;
152: static int mousecl = MAKELONG (160, 100);
153: int mouseactive;
154:
155: void setmouseactive (int active)
156: {
157: mousedx = (amigawin_rect.right - amigawin_rect.left) / 2;
158: mousedy = (amigawin_rect.bottom - amigawin_rect.top) / 2;
159: mousecl = MAKELONG (mousedx, mousedy);
160: mousecx = amigawin_rect.left + mousedx;
161: mousecy = amigawin_rect.top + mousedy;
162:
163: if (active == mouseactive)
164: return;
165: mouseactive = active;
166:
167: if (active) {
168: ShowCursor (FALSE);
169: SetCursorPos (mousecx, mousecy);
170: SetWindowText (hMainWnd ? hMainWnd : hAmigaWnd, TITLETEXT " [Mouse active - press Alt-Tab to cancel]");
171: ClipCursor (&amigawin_rect);
172: } else {
173: ShowCursor (TRUE);
174: SetWindowText (hMainWnd ? hMainWnd : hAmigaWnd, TITLETEXT);
175: ClipCursor (NULL);
176: }
177: }
178:
179: static int hascapture = 0;
180:
181: void setcapture (void)
182: {
183: if (hascapture)
184: return;
185: hascapture++;
186: SetCapture (hAmigaWnd);
187: }
188:
189: static __inline__ void releasecapture (void)
190: {
191: if (!hascapture)
192: return;
193: hascapture--;
194: ReleaseCapture ();
195: }
196:
197: static void figure_processor_speed (void)
198: {
199: SYSTEM_INFO sysinfo;
200: OSVERSIONINFO osinfo;
201: HKEY hKey;
202: DWORD value;
203: DWORD type, size;
204: unsigned long mhz = 0;
205: char cpuid[40];
206: char *envptr;
207:
208: vsynctime = -1;
209: if ((envptr = getenv ("PROCESSOR_LEVEL")) && atoi (envptr) < 5)
210: goto bad_cpu;
211:
212: if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0L, KEY_READ, &hKey) == ERROR_SUCCESS) {
213: size = sizeof (value);
214: if (RegQueryValueEx (hKey, "~MHz", NULL, &type, (LPBYTE) & value, &size) == ERROR_SUCCESS)
215: mhz = value;
216: size = sizeof cpuid;
217: if (RegQueryValueEx (hKey, "VendorIdentifier", NULL, &type, (LPBYTE) cpuid, &size) == ERROR_SUCCESS) {
218: good_cpu = (strncmp (cpuid, "AuthenticAMD", 12) == 0
219: || strncmp (cpuid, "GenuineIntel", 12) == 0);
220: }
221: RegCloseKey (hKey);
222: }
223: if (!good_cpu)
224: goto bad_cpu;
225:
226: #ifdef FRAME_RATE_HACK
227: if (mhz == 0) {
228: frame_time_t t;
229: DWORD oldpri = GetPriorityClass (GetCurrentProcess ());
230:
231: write_log ("Calibrating delay loop.. ");
232:
233: SetPriorityClass (GetCurrentProcess (), REALTIME_PRIORITY_CLASS);
234: vsynctime = 1;
235: t = read_processor_time ();
236: Sleep (1001);
237: t = 2*read_processor_time () - t;
238: Sleep (1);
239: t -= read_processor_time ();
240: SetPriorityClass (GetCurrentProcess (), oldpri);
241:
242: MyOutputDebugString ("ok - %.2f BogoMIPS\n", (double)t / 1000000.0);
243: vsynctime = t / 50;
244: return;
245: }
246: #endif
247: if (mhz != 0) {
248: vsynctime = mhz * 1000000 / 50;
249: return;
250: }
251: write_log ("Could not determine clock speed of your CPU.\n");
252: return;
253: bad_cpu:
254: write_log ("Processor level too low - disabling frame rate hack\n");
255: }
256:
257: /* DirectDraw stuff*/
258: char *getddrname (HRESULT ddrval)
259: {
260: switch (ddrval) {
261: case DDERR_ALREADYINITIALIZED:
262: return "This object is already initialized.";
263: case DDERR_BLTFASTCANTCLIP:
264: return "Cannot use BLTFAST with Clipper attached to surface.";
265: case DDERR_CANNOTATTACHSURFACE:
266: return "Cannot attach surface.";
267: case DDERR_CANNOTDETACHSURFACE:
268: return "Cannot detach surface.";
269: case DDERR_CANTCREATEDC:
270: return "Cannot create DC Device Context.";
271: case DDERR_CANTDUPLICATE:
272: return "Cannot duplicate.";
273: case DDERR_CANTLOCKSURFACE:
274: return "Access to surface refused (no DCI provider).";
275: case DDERR_CANTPAGELOCK:
276: return "PageLock failure.";
277: case DDERR_CANTPAGEUNLOCK:
278: return "PageUnlock failure.";
279: case DDERR_CLIPPERISUSINGHWND:
280: return "Can't set a clip-list for a Clipper which is attached to an HWND.";
281: case DDERR_COLORKEYNOTSET:
282: return "No source colour-key provided.";
283: case DDERR_CURRENTLYNOTAVAIL:
284: return "Support unavailable.";
285: case DDERR_DCALREADYCREATED:
286: return "Surface already has a Device Context.";
287: case DDERR_DIRECTDRAWALREADYCREATED:
288: return "DirectDraw already bound to this process.";
289: case DDERR_EXCEPTION:
290: return "Unexpected exception.";
291: case DDERR_EXCLUSIVEMODEALREADYSET:
292: return "Already in exclusive mode.";
293: case DDERR_GENERIC:
294: return "Undefined"; /* THIS MAKES SENSE! FUCKING M$ */
295:
296: case DDERR_HEIGHTALIGN:
297: return "Height needs to be aligned.";
298: case DDERR_HWNDALREADYSET:
299: return "HWND already set for cooperative level.";
300: case DDERR_HWNDSUBCLASSED:
301: return "HWND has been subclassed.";
302: case DDERR_IMPLICITLYCREATED:
303: return "Can't restore an implicitly created surface.";
304: case DDERR_INCOMPATIBLEPRIMARY:
305: return "New params doesn't match existing primary surface.";
306: case DDERR_INVALIDCAPS:
307: return "Device doesn't have requested capabilities.";
308: case DDERR_INVALIDCLIPLIST:
309: return "Provided clip-list not supported.";
310: case DDERR_INVALIDDIRECTDRAWGUID:
311: return "Invalid GUID.";
312: case DDERR_INVALIDMODE:
313: return "Mode not supported.";
314: case DDERR_INVALIDOBJECT:
315: return "Invalid object.";
316: case DDERR_INVALIDPARAMS:
317: return "Invalid params.";
318: case DDERR_INVALIDPIXELFORMAT:
319: return "Device doesn't support requested pixel format.";
320: case DDERR_INVALIDPOSITION:
321: return "Overlay position illegal.";
322: case DDERR_INVALIDRECT:
323: return "Invalid RECT.";
324: case DDERR_INVALIDSURFACETYPE:
325: return "Wrong type of surface.";
326: case DDERR_LOCKEDSURFACES:
327: return "Surface locked.";
328: case DDERR_NO3D:
329: return "No 3d capabilities.";
330: case DDERR_NOALPHAHW:
331: return "No alpha h/w.";
332: case DDERR_NOBLTHW:
333: return "No blit h/w.";
334: case DDERR_NOCLIPLIST:
335: return "No clip-list.";
336: case DDERR_NOCLIPPERATTACHED:
337: return "No Clipper attached.";
338: case DDERR_NOCOLORCONVHW:
339: return "No colour-conversion h/w.";
340: case DDERR_NOCOLORKEY:
341: return "No colour-key.";
342:
343: case DDERR_NOTLOCKED:
344: return "Not locked.";
345: case DDERR_NOTPAGELOCKED:
346: return "Not page-locked.";
347: case DDERR_NOTPALETTIZED:
348: return "Not palette-based.";
349:
350: case DDERR_OUTOFCAPS:
351: return "out of caps";
352: case DDERR_OUTOFMEMORY:
353: return "Out of memory.";
354: case DDERR_OUTOFVIDEOMEMORY:
355: return "out of video memory.";
356: case DDERR_PALETTEBUSY:
357: return "Palette busy.";
358: case DDERR_PRIMARYSURFACEALREADYEXISTS:
359: return "Already a primary surface.";
360:
361: case DDERR_SURFACEBUSY:
362: return "Surface busy.";
363: /*case DDERR_SURFACEOBSCURED: return "Surface is obscured.";*/
364: case DDERR_SURFACELOST:
365: return "Surface lost.";
366:
367: case DDERR_UNSUPPORTED:
368: return "Unsupported.";
369: case DDERR_UNSUPPORTEDFORMAT:
370: return "Unsupported format.";
371:
372: case DDERR_WASSTILLDRAWING:
373: return "Was still drawing.";
374: }
375: return "";
376: }
377:
378: static int lockcnt = 0;
379:
380: static int do_surfacelock (void)
381: {
382: HRESULT ddrval = IDirectDrawSurface_Lock (lpDDS, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
383: if (ddrval != DD_OK) {
384: if (ddrval == DDERR_SURFACELOST)
385: ddrval = IDirectDrawSurface_Restore (lpDDS);
386: else if (ddrval != DDERR_SURFACEBUSY)
387: MyOutputDebugString ("lpDDS->Lock() failed - %s (%d)\n", getddrname (ddrval), (unsigned short) ddrval);
388: return 0;
389: }
390: lockcnt++;
391: return 1;
392: }
393:
394: void unlockscr (void)
395: {
396: lockcnt--;
397: IDirectDrawSurface_Unlock (lpDDS, ddsd.lpSurface);
398: }
399:
400: static void release_ddraw_stuff (void)
401: {
402: if (lpDD) {
403: IDirectDraw_RestoreDisplayMode (lpDD);
404: IDirectDraw_SetCooperativeLevel (lpDD, hAmigaWnd, DDSCL_NORMAL);
405: }
406: if (lpDDC)
407: IDirectDrawClipper_Release (lpDDC);
408: if (lpDDS)
409: IDirectDrawSurface_Release (lpDDS);
410: if (lpDDP)
411: IDirectDrawPalette_Release (lpDDP);
412: if (lpDD)
413: IDirectDraw_Release (lpDD);
414: lpDDC = 0;
415: lpDDS = 0;
416: lpDDP = 0;
417: lpDD = 0;
418: }
419:
420: static int set_ddraw (int width, int height, int wantfull, int *pbytes,
421: LPPALETTEENTRY pal)
422: {
423: int bits = 8 * *pbytes;
424: HRESULT ddrval;
425:
426: #ifdef __GNUC__
427: ddrval = (*pDirectDrawCreate) (NULL, &lpDD, NULL);
428: #else
429: ddrval = DirectDrawCreate (NULL, &lpDD, NULL);
430: #endif
431: if (ddrval != DD_OK)
432: goto oops;
433:
434: ddrval = IDirectDraw_SetCooperativeLevel (lpDD, hAmigaWnd,
435: (wantfull
436: ? DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN
437: : DDSCL_NORMAL));
438: if (ddrval != DD_OK)
439: goto oops;
440:
441: ddrval = IDirectDraw_CreateClipper (lpDD, 0, &lpDDC, NULL);
442: if (ddrval != DD_OK) {
443: MyOutputDebugString ("DirectDraw error: Clipper unavailable! (%d)\n", ddrval);
444: } else {
445: if (IDirectDrawClipper_SetHWnd (lpDDC, 0, hAmigaWnd) != DD_OK)
446: MyOutputDebugString ("DirectDraw error: Can't attach HWnd!\n");
447: }
448:
449: if (wantfull) {
450: ddrval = IDirectDraw_SetDisplayMode (lpDD, width, height, bits);
451: if (ddrval != DD_OK)
452: goto oops;
453: }
454: ddsd.dwSize = sizeof (ddsd);
455: ddsd.dwFlags = DDSD_CAPS;
456: ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
457:
458: ddrval = IDirectDraw_CreateSurface (lpDD, &ddsd, &lpDDS, NULL);
459: if (ddrval != DD_OK)
460: goto oops;
461:
462: if (! do_surfacelock ())
463: return 0;
464: unlockscr ();
465:
466: bits = (ddsd.ddpfPixelFormat.dwRGBBitCount + 7) & ~7;
467: current_pixbytes = *pbytes = bits >> 3;
468:
469: if (bits == 8) {
470: ddrval = IDirectDraw_CreatePalette (lpDD, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
471: pal,
472: &lpDDP, NULL);
473: if (ddrval != DD_OK)
474: goto oops;
475:
476: ddrval = IDirectDrawSurface2_SetPalette (lpDDS, lpDDP);
477: if (ddrval != DD_OK)
478: goto oops;
479: }
480: /* Set global values for current width,height */
481: current_width = width;
482: current_height = height;
483:
484: return 1;
485:
486: oops:
487: MyOutputDebugString ("DirectDraw initialization failed with %s/%d\n", getddrname (ddrval), ddrval);
488: return 0;
489: }
490:
491: /* Color management */
492: static int bits_in_mask (unsigned long mask)
493: {
494: int n = 0;
495: while (mask) {
496: n += mask & 1;
497: mask >>= 1;
498: }
499: return n;
500: }
501:
502: static int mask_shift (unsigned long mask)
503: {
504: int n = 0;
505: while (!(mask & 1)) {
506: n++;
507: mask >>= 1;
508: }
509: return n;
510: }
511:
512: static xcolnr xcol8[4096];
513: static PALETTEENTRY colors256[256];
514: static int ncols256 = 0;
515:
516: static int get_color (int r, int g, int b, xcolnr *cnp)
517: {
518: if (ncols256 == 256)
519: return 0;
520: colors256[ncols256].peRed = r * 0x11;
521: colors256[ncols256].peGreen = g * 0x11;
522: colors256[ncols256].peBlue = b * 0x11;
523: colors256[ncols256].peFlags = 0;
524: *cnp = ncols256;
525: ncols256++;
526: return 1;
527: }
528:
529: static void init_colors (void)
530: {
531: if (ncols256 == 0)
532: alloc_colors256 (get_color);
533: memcpy (xcol8, xcolors, sizeof xcol8);
534:
535: /* init colors */
536:
537: switch (current_pixbytes) {
538: case 1:
539: memcpy (xcolors, xcol8, sizeof xcolors);
540: if (lpDDP != 0) {
541: HRESULT ddrval = IDirectDrawPalette_SetEntries (lpDDP, 0, 0, 256, colors256);
542: if (ddrval != DD_OK)
543: MyOutputDebugString ("DX_SetPalette() failed with %s/%d\n", getddrname (ddrval), ddrval);
544: }
545: break;
546:
547: case 2:
548: case 3:
549: case 4:
550: {
551: int red_bits = bits_in_mask (ddsd.ddpfPixelFormat.dwRBitMask);
552: int green_bits = bits_in_mask (ddsd.ddpfPixelFormat.dwGBitMask);
553: int blue_bits = bits_in_mask (ddsd.ddpfPixelFormat.dwBBitMask);
554: int red_shift = mask_shift (ddsd.ddpfPixelFormat.dwRBitMask);
555: int green_shift = mask_shift (ddsd.ddpfPixelFormat.dwGBitMask);
556: int blue_shift = mask_shift (ddsd.ddpfPixelFormat.dwBBitMask);
557:
558: alloc_colors64k (red_bits, green_bits, blue_bits, red_shift,
559: green_shift, blue_shift);
560: }
561: break;
562: }
563: }
564:
565: static void close_windows (void)
566: {
567: int i;
568:
569: gfxvidinfo.bufmem = 0;
570: gfxvidinfo.linemem = 0;
571:
572: releasecapture ();
573: setmouseactive (0);
574: ClipCursor (NULL);
575: release_ddraw_stuff ();
576:
577: if (!hMainWnd && hAmigaWnd) {
578: /*ShowWindow (hAmigaWnd, SW_MINIMIZE);*/
579: }
580: if (hAmigaWnd)
581: DestroyWindow (hAmigaWnd);
582: if (hMainWnd)
583: DestroyWindow (hMainWnd);
584: PostQuitMessage (0);
585: hMainWnd = 0;
586: hAmigaWnd = 0;
587: }
588:
589: static void destroy_window (int nowait)
590: {
591: if (currprefs.produce_sound > 1)
592: stopsound ();
593:
594: if (!nowait) {
595: frame_do_semup = 1;
596: set_inhibit_frame (5);
597: uae_sem_wait (&frame_sem);
598: }
599:
600: /*SuspendThread (hEmuThread);*/
601: close_windows ();
602: }
603:
604: void displaychange (void)
605: {
606: changemode = 1;
607: destroy_window (0);
608: }
609:
610: void toggle_fullscreen (void)
611: {
612: changemode = 1;
613: if (screen_is_picasso)
614: picasso_fullscreen ^= 1;
615: else
616: amiga_fullscreen ^= 1;
617: destroy_window (0);
618: }
619:
620: int can_draw (void)
621: {
622: return gfxvidinfo.pixbytes != 0;
623: }
624:
625: long FAR PASCAL AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
626: {
627: PAINTSTRUCT ps;
628: HDC hDC;
629:
630: if (changemode != 0)
631: return DefWindowProc (hWnd, message, wParam, lParam);
632:
633: switch (message) {
634: case WM_ACTIVATEAPP:
635: if (bActive = wParam) {
636: if (fullscreen) {
637: SetCursor (NULL);
638: SetCursorPos (mousecx, mousecy);
639: #ifdef PICASSO96
640: if( !picasso96_state.RefreshPending )
641: picasso96_state.RefreshPending = 1;
642: #endif
643: }
644: my_kbd_handler (VK_CAPITAL, 0x3a, TRUE);
645: } else {
646: if (!fullscreen)
647: setmouseactive (0);
648: }
649: break;
650:
651: case WM_ACTIVATE:
652: if (LOWORD (wParam) != WA_INACTIVE) {
653: ShowWindow (hWnd, SW_RESTORE);
654: }
655: break;
656:
657: case WM_SETCURSOR:
658: if (fullscreen) {
659: SetCursor (NULL);
660: return TRUE;
661: }
662: break;
663:
664: case WM_SYSCOMMAND:
665: if (wParam == SC_ZOOM) {
666: toggle_fullscreen ();
667: return 0;
668: }
669: break;
670:
671: case WM_KEYUP:
672: case WM_SYSKEYUP:
673: numkeysdown--;
674: keysdown[wParam] = 0;
675: my_kbd_handler (wParam, (lParam >> 16) & 0x1ff, FALSE);
676: break;
677:
678: case WM_KEYDOWN:
679: case WM_SYSKEYDOWN:
680: if (LOWORD (lParam) == 1) {
681: if (numkeysdown) {
682: int key;
683: numkeysdown = 0;
684:
685: for (key = 256; key--;) {
686: if (keysdown[key]) {
687: if (checkkey (key, lParam))
688: numkeysdown++;
689: else {
690: my_kbd_handler (key, (keysdown[key] >> 16) & 0x1ff, FALSE);
691: keysdown[key] = 0;
692: }
693: }
694: }
695: }
696: if (!keysdown[wParam]) {
697: keysdown[wParam] = lParam;
698: numkeysdown++;
699: }
700: numkeysdown++;
701: my_kbd_handler (wParam, (lParam >> 16) & 0x1ff, TRUE);
702: }
703: break;
704:
705: case WM_LBUTTONDOWN:
706: if (ievent_alive) {
707: setcapture ();
708: buttonstate[0] = 1;
709: } else if (!fullscreen && !mouseactive)
710: setmouseactive (1);
711: else
712: buttonstate[0] = 1;
713: break;
714:
715: case WM_LBUTTONUP:
716: releasecapture ();
717: buttonstate[0] = 0;
718: break;
719:
720: case WM_MBUTTONDOWN:
721: if (ievent_alive)
722: setcapture ();
723: buttonstate[1] = 1;
724: break;
725:
726: case WM_MBUTTONUP:
727: releasecapture ();
728: buttonstate[1] = 0;
729: break;
730:
731: case WM_RBUTTONDOWN:
732: if (ievent_alive)
733: setcapture ();
734: buttonstate[2] = 1;
735: break;
736:
737: case WM_RBUTTONUP:
738: releasecapture ();
739: buttonstate[2] = 0;
740: break;
741:
742: case WM_MOUSEMOVE:
743: if ((mouseactive && !ievent_alive) || fullscreen) {
744: /*
745: * In this mode, the mouse pointer is always centered in the window,
746: * this is ensured by the SetCursorPos call below.
747: * We don't want to handle messages that result from such a SetCursorPos
748: * call (recursion!), so exit early if we see one.
749: */
750: if (lParam == mousecl)
751: break;
752: lastmx += (signed short) LOWORD (lParam) - mousedx;
753: lastmy += (signed short) HIWORD (lParam) - mousedy;
754: if (ievent_alive) {
755: if (lastmx < 0)
756: lastmx = 0;
757: if (lastmx > current_width)
758: lastmx = current_width;
759: if (lastmy < 0)
760: lastmy = 0;
761: if (lastmy > current_height)
762: lastmy = current_height;
763:
764: }
765: SetCursorPos (mousecx, mousecy);
766: break;
767: }
768: lastmx = (signed short) LOWORD (lParam);
769: lastmy = (signed short) HIWORD (lParam);
770: break;
771:
772: case WM_PAINT:
773: hDC = BeginPaint (hWnd, &ps);
774: clear_inhibit_frame (IHF_WINDOWHIDDEN);
775: if (hBackDC)
776: BitBlt (hDC, ps.rcPaint.left, ps.rcPaint.top,
777: ps.rcPaint.right - ps.rcPaint.left,
778: ps.rcPaint.bottom - ps.rcPaint.top, hBackDC,
779: ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
780: else
781: notice_screen_contents_lost ();
782:
783: EndPaint (hWnd, &ps);
784: break;
785:
786: case WM_DROPFILES:
787: if (DragQueryFile ((HDROP) wParam, (UINT) - 1, NULL, 0)) {
788: if (DragQueryFile ((HDROP) wParam, 0, NULL, 0) < 255)
789: DragQueryFile ((HDROP) wParam, 0, changed_prefs.df[0], sizeof (changed_prefs.df[0]));
790: }
791: DragFinish ((HDROP) wParam);
792: break;
793:
794: case WM_CAPTURECHANGED:
795: if (lParam != hWnd)
796: buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
797: break;
798:
799: case WM_TIMER:
800: #if 0
801: if (wParam == 2) {
802: KillTimer (hwnd, timer_id);
803: timer_id = 0;
804: ClearVisibleAreaAndRefresh ();
805: } else
806: #endif
807: {
808: finishjob ();
809: }
810: break;
811:
812: case WM_USER + 0x200:
813: DoSomeWeirdPrintingStuff(wParam);
814: break;
815:
816: case WM_USER + 0x201:
817: changemode = 2;
818: destroy_window (1);
819: break;
820:
821: case WM_CREATE:
822: DragAcceptFiles (hWnd, TRUE);
823: break;
824:
825: case WM_DESTROY:
826: changemode = 3;
827: destroy_window (0);
828: break;
829: }
830:
831: return DefWindowProc (hWnd, message, wParam, lParam);
832: }
833:
834: long FAR PASCAL MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
835: {
836: PAINTSTRUCT ps;
837: RECT rc, rc2;
838: HDC hDC;
839:
840: if (changemode != 0)
841: return DefWindowProc (hWnd, message, wParam, lParam);
842:
843: switch (message) {
844: case WM_LBUTTONDOWN:
845: case WM_MOUSEMOVE:
846: case WM_ACTIVATEAPP:
847: case WM_ACTIVATE:
848: case WM_SETCURSOR:
849: case WM_SYSCOMMAND:
850: case WM_KEYUP:
851: case WM_SYSKEYUP:
852: case WM_KEYDOWN:
853: case WM_SYSKEYDOWN:
854: case WM_LBUTTONUP:
855: case WM_MBUTTONDOWN:
856: case WM_MBUTTONUP:
857: case WM_RBUTTONDOWN:
858: case WM_RBUTTONUP:
859: case WM_DROPFILES:
860: case WM_CREATE:
861: case WM_DESTROY:
862: case WM_USER + 0x200:
863: case WM_USER + 0x201:
864: return AmigaWindowProc (hWnd, message, wParam, lParam);
865:
866: case WM_DISPLAYCHANGE:
867: if (!fullscreen && !changemode && (wParam + 7) / 8 != current_pixbytes)
868: displaychange ();
869: break;
870:
871: case WM_ENTERSIZEMOVE:
872: if (!fullscreen) {
873: frame_do_semup = 1;
874: set_inhibit_frame (5);
875: uae_sem_wait (&frame_sem);
876: }
877: break;
878:
879: case WM_EXITSIZEMOVE:
880: clear_inhibit_frame (5);
881: /* fall through */
882:
883: case WM_WINDOWPOSCHANGED:
884: GetWindowRect (hAmigaWnd, &amigawin_rect);
885:
886: if (!fullscreen && hAmigaWnd) {
887: if (current_pixbytes == 2) {
888: if (amigawin_rect.left & 1) {
889: GetWindowRect (hMainWnd, &rc2);
890: if (1 /*!mon || rc2.left + 4 < GetSystemMetrics (SM_CXSCREEN)*/)
891: MoveWindow (hMainWnd, rc2.left + 1, rc2.top,
892: rc2.right - rc2.left, rc2.bottom - rc2.top, TRUE);
893: }
894: } else if (current_pixbytes == 3) {
895: if (amigawin_rect.left >= 0) {
896: if (amigawin_rect.left & 3) {
897: GetWindowRect (hMainWnd, &rc2);
898: if (1 /*!mon || rc2.left + 4 < GetSystemMetrics (SM_CXSCREEN)*/)
899: MoveWindow (hMainWnd, rc2.left - amigawin_rect.left % 4, rc2.top,
900: rc2.right - rc2.left, rc2.bottom - rc2.top, TRUE);
901: }
902: }
903: }
904: setmouseactive (0);
905: return 0;
906: }
907: break;
908:
909: case WM_PAINT:
910: hDC = BeginPaint (hWnd, &ps);
911: GetClientRect (hWnd, &rc);
912: DrawEdge (hDC, &rc, EDGE_SUNKEN, BF_RECT);
913:
914: EndPaint (hWnd, &ps);
915: break;
916:
917: case WM_NCLBUTTONDBLCLK:
918: if (wParam == HTCAPTION) {
919: toggle_fullscreen ();
920: return 0;
921: }
922: }
923:
924: return DefWindowProc (hWnd, message, wParam, lParam);
925: }
926:
927: static int HasConsole;
928: static HANDLE stdouthandle;
929: static HANDLE debugfile;
930:
931: /* Console Win32 helper routines */
932: void activate_debugger ();
933:
934: static BOOL __stdcall ctrlchandler (DWORD type)
935: {
936: SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrlchandler, FALSE);
937:
938: if (type == CTRL_C_EVENT) {
939: activate_debugger ();
940: return TRUE;
941: }
942: return FALSE;
943: }
944:
945: void setup_brkhandler (void)
946: {
947: SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrlchandler, TRUE);
948: }
949:
950: void remove_brkhandler (void)
951: {
952: SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrlchandler, FALSE);
953: }
954:
955: int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
956: int nCmdShow)
957: {
958: char *posn;
959: int i;
960:
961: hInst = hInstance;
962:
963: debugfile = CreateFile ("outfile", GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
964: 0, NULL);
965:
966: for (i = 0; i < NUM_DRIVES; i++) {
967: drives[i].path[0] = 0;
968: drives[i].name[0] = 0;
969: drives[i].rw = TRUE;
970: }
971:
972: /* Get our executable's root-path */
973: start_path = xmalloc(MAX_PATH);
974: GetModuleFileName (hInst, start_path, MAX_PATH);
975: if (posn = strrchr (start_path, '\\'))
976: *posn = 0;
977:
978:
979: HasConsole = 0;/*AllocConsole ();*/
980: if (HasConsole)
981: stdouthandle = GetStdHandle (STD_OUTPUT_HANDLE);
982:
983: write_log ("UAE " UAEWINVERSION " Win32/DirectX, release " UAEWINRELEASE "\n");
984: strcpy (VersionStr, PROGNAME);
985: write_log ("\n(c) 1995-1997 Bernd Schmidt - Core UAE concept and implementation."
986: "\n(c) 1996-1997 Mathias Ortmann - Win32 port and enhancements."
987: "\n(c) 1996-1997 Brian King - Picasso96 and AHI support, GUI.\n"
988: "\nPress F12 to show the Settings Dialog (GUI), Alt-F4 to quit.\n"
989: "\nhttp://www.informatik.tu-muenchen.de/~ortmann/uae/\n\n");
990:
991: currprefs.copper_pos = -1;
992: /*initgfxspecs();*/
993: if (initlibs ())
994: real_main (__argc, __argv);
995: cleanuplibs();
996:
997: if (HasConsole)
998: FreeConsole ();
999:
1000: return FALSE;
1001: }
1002:
1003: static int register_classes (void)
1004: {
1005: WNDCLASS wc;
1006:
1007: wc.style = 0;
1008: wc.lpfnWndProc = AmigaWindowProc;
1009: wc.cbClsExtra = 0;
1010: wc.cbWndExtra = 0;
1011: wc.hInstance = 0;
1012: wc.hIcon = LoadIcon (GetModuleHandle (NULL), IDI_APPICON);
1013: wc.hCursor = LoadCursor (NULL, IDC_ARROW);
1014: wc.hbrBackground = GetStockObject (BLACK_BRUSH);
1015: wc.lpszMenuName = NULL;
1016: wc.lpszClassName = "AmigaPowah";
1017: if (!RegisterClass (&wc))
1018: return 0;
1019:
1020: wc.style = 0;
1021: wc.lpfnWndProc = MainWindowProc;
1022: wc.cbClsExtra = 0;
1023: wc.cbWndExtra = 0;
1024: wc.hInstance = 0;
1025: wc.hIcon = LoadIcon (GetModuleHandle (NULL), IDI_APPICON);
1026: wc.hCursor = LoadCursor (NULL, IDC_ARROW);
1027: wc.hbrBackground = GetStockObject (BLACK_BRUSH);
1028: wc.lpszMenuName = NULL;
1029: wc.lpszClassName = "PCsuxRox";
1030: if (!RegisterClass (&wc))
1031: return 0;
1032: return 1;
1033: }
1034:
1035: int graphics_setup (void)
1036: {
1037: DWORD ddrval;
1038:
1039: if (!register_classes ())
1040: return 0;
1041:
1042: uae_sem_init (&picasso_switch_sem, 0, 0);
1043: return 1;
1044: }
1045:
1046: #define NORMAL_WINDOW_STYLE (WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
1047:
1048: static int create_windows (void)
1049: {
1050: POINT pt;
1051:
1052: if (!fullscreen) {
1053: RECT rc;
1054:
1055: rc.left = 0;
1056: rc.top = 0;
1057: rc.right = current_width;
1058: rc.bottom = current_height;
1059: rc.right += 4;
1060: rc.bottom += 4;
1061: AdjustWindowRect (&rc, NORMAL_WINDOW_STYLE, FALSE);
1062:
1063: hMainWnd = CreateWindowEx (WS_EX_ACCEPTFILES,
1064: "PCsuxRox",
1065: TITLETEXT,
1066: NORMAL_WINDOW_STYLE,
1067: CW_USEDEFAULT, CW_USEDEFAULT,
1068: rc.right - rc.left, rc.bottom - rc.top,
1069: NULL,
1070: NULL,
1071: 0,
1072: NULL);
1073:
1074: if (! hMainWnd)
1075: return 0;
1076: } else
1077: hMainWnd = NULL;
1078:
1079: hAmigaWnd = CreateWindowEx (fullscreen ? WS_EX_TOPMOST : WS_EX_ACCEPTFILES,
1080: "AmigaPowah",
1081: PROGNAME,
1082: hMainWnd ? WS_VISIBLE | WS_CHILD : WS_VISIBLE | WS_POPUP,
1083: hMainWnd ? 2 : CW_USEDEFAULT, hMainWnd ? 2 : CW_USEDEFAULT,
1084: fullscreen ? GetSystemMetrics (SM_CXSCREEN) : current_width,
1085: fullscreen ? GetSystemMetrics (SM_CYSCREEN) : current_height,
1086: hMainWnd,
1087: NULL,
1088: 0,
1089: NULL);
1090:
1091: if (!hAmigaWnd) {
1092: if (hMainWnd)
1093: DestroyWindow (hMainWnd);
1094: return 0;
1095: }
1096:
1097: if (hMainWnd)
1098: UpdateWindow (hMainWnd);
1099: if (hAmigaWnd)
1100: UpdateWindow (hAmigaWnd);
1101:
1102: return 1;
1103: }
1104:
1105: void doPreInit( void )
1106: {
1107: void *blah;
1108: DWORD ddrval;
1109: #ifdef __GNUC__
1110: ddrval = (*pDirectDrawCreate)(NULL,&lpDD,NULL);
1111: #else
1112: ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
1113: #endif
1114: if (ddrval == DD_OK)
1115: {
1116: //IDirectDraw2_QueryInterface( lpDD, &IID_IDirectDraw2, &blah );
1117:
1118: mode_count = DX_FillResolutions( &picasso96_pixel_format );
1119:
1120: // If we've got no command-line arguments, then we use the integrated-GUI
1121: if( ( __argc == 1 ) &&
1122: ( GetSettings() == FALSE ) )
1123: {
1124: MyOutputDebugString("GetSettings() trying to quit...\n");
1125: shutdownmain();
1126: }
1127: }
1128: }
1129:
1130: BOOL doInit (void)
1131: {
1132: if (! create_windows ())
1133: return 0;
1134: #ifdef PICASSO96
1135: if (screen_is_picasso) {
1136: if (!set_ddraw (current_width, current_height, fullscreen, &picasso_vidinfo.depth,
1137: (LPPALETTEENTRY)&picasso96_state.CLUT))
1138: goto oops;
1139: picasso_vidinfo.rowbytes = ddsd.lPitch;
1140: } else
1141: #endif
1142: {
1143: gfxvidinfo.pixbytes = 2;
1144: if (!set_ddraw (current_width, current_height, fullscreen, &gfxvidinfo.pixbytes, colors256))
1145: goto oops;
1146: gfxvidinfo.bufmem = 0;
1147: gfxvidinfo.linemem = 0;
1148: gfxvidinfo.maxblocklines = 0;
1149: gfxvidinfo.width = current_width;
1150: gfxvidinfo.height = current_height;
1151: gfxvidinfo.rowbytes = ddsd.lPitch;
1152: gfxvidinfo.can_double = 1;
1153: }
1154:
1155: if (fullscreen) {
1156: scrindirect = 0;
1157: gfxvidinfo.linemem = 0;
1158: mousecx = 160, mousecy = 100, mousedx = 160, mousedy = 100, mousecl = MAKELONG (160, 100);
1159: }
1160:
1161: if (! do_surfacelock ())
1162: goto oops;
1163: unlockscr ();
1164:
1165: if ((ddsd.ddpfPixelFormat.dwFlags & (DDPF_RGB | DDPF_PALETTEINDEXED8 | DDPF_RGBTOYUV)) != 0)
1166: {
1167: MyOutputDebugString ("%s mode (bits: %d, pixbytes: %d)\n", fullscreen ? "Full screen" : "Window",
1168: ddsd.ddpfPixelFormat.dwRGBBitCount, current_pixbytes);
1169: #ifdef PICASSO96
1170: if( ddsd.ddpfPixelFormat.dwRBitMask == 0x0000F800 )
1171: picasso96_pixel_format |= RGBFF_R5G6B5PC;
1172: else if( ddsd.ddpfPixelFormat.dwRBitMask == 0x00007C00 )
1173: picasso96_pixel_format |= RGBFF_R5G5B5PC;
1174: else if( ddsd.ddpfPixelFormat.dwBBitMask == 0x0000F800 )
1175: picasso96_pixel_format |= RGBFF_B5G6R5PC;
1176: else
1177: picasso96_pixel_format |= RGBFF_B5G5R5PC;
1178: #endif
1179: } else {
1180: MyOutputDebugString ("Error: Unsupported pixel format - use a different screen mode\n");
1181: goto oops;
1182: }
1183: #ifdef PICASSO96
1184: if (screen_is_picasso)
1185: DX_SetPalette (0, 256);
1186: else
1187: #endif
1188: init_colors ();
1189:
1190: if (!fullscreen)
1191: MainWindowProc (0, WM_WINDOWPOSCHANGED, 0, 0);
1192: return 1;
1193:
1194: oops:
1195: if (hMainWnd)
1196: DestroyWindow (hMainWnd);
1197: if (hAmigaWnd)
1198: DestroyWindow (hAmigaWnd);
1199: return 0;
1200: }
1201:
1202: struct myRGNDATA {
1203: RGNDATAHEADER rdh;
1204: RECT rects[640]; /* fixed buffers suck, but this is _very_ unlikely to overflow */
1205: } ClipList = { {
1206: sizeof (ClipList), RDH_RECTANGLES, 0, 640 * sizeof (RECT)
1207: } };
1208:
1209:
1210: /* this is the way the display line is put to screen
1211: * if the display is not 16 bits deep or the window is not fully visible */
1212: static void clipped_linetoscr (char *dst, char *src, int y)
1213: {
1214: LPRECT lpRect = ClipList.rects;
1215: int i;
1216:
1217: switch (current_pixbytes) {
1218: case 1:
1219: for (i = ClipList.rdh.nCount; i--; lpRect++) {
1220: if (y >= lpRect->top && y < lpRect->bottom) {
1221: memcpy (dst + lpRect->left, src + lpRect->left, lpRect->right);
1222: }
1223: }
1224: break;
1225:
1226: case 2:
1227: for (i = ClipList.rdh.nCount; i--; lpRect++) {
1228: if (y >= lpRect->top && y < lpRect->bottom) {
1229: memcpy (dst + lpRect->left*2, src + lpRect->left*2, lpRect->right*2);
1230: }
1231: }
1232: break;
1233:
1234: case 3:
1235: for (i = ClipList.rdh.nCount; i--; lpRect++) {
1236: if (y >= lpRect->top && y < lpRect->bottom) {
1237: memcpy (dst + lpRect->left*3, src + lpRect->left*3, lpRect->right*3);
1238: }
1239: }
1240: break;
1241:
1242: case 4:
1243: for (i = ClipList.rdh.nCount; i--; lpRect++) {
1244: if (y >= lpRect->top && y < lpRect->bottom) {
1245: memcpy (dst + lpRect->left*4, src + lpRect->left*4, lpRect->right*4);
1246: }
1247: }
1248: break;
1249: }
1250: }
1251:
1252: void flush_line(int lineno)
1253: {
1254: if (scrindirect)
1255: clipped_linetoscr(gfxvidinfo.bufmem + lineno * gfxvidinfo.rowbytes,
1256: scrlinebuf, lineno);
1257: }
1258:
1259: void flush_block(int a, int b)
1260: {
1261: }
1262:
1263: void flush_screen(int a, int b)
1264: {
1265: }
1266:
1267: char *lockscr (void)
1268: {
1269: char *surface, *oldsurface;
1270: DWORD tmp;
1271: LPRECT lpRect;
1272:
1273: if (!do_surfacelock ())
1274: return NULL;
1275:
1276: surface = ddsd.lpSurface;
1277: oldsurface = gfxvidinfo.bufmem;
1278: if (!fullscreen) {
1279: surface += amigawin_rect.top * ddsd.lPitch + current_pixbytes * amigawin_rect.left;
1280: }
1281: gfxvidinfo.bufmem = surface;
1282: if (surface != oldsurface && ! screen_is_picasso) {
1283: write_log ("Need to init_row_map\n");
1284: init_row_map ();
1285: }
1286:
1287: scrindirect = 0;
1288:
1289: if (fullscreen) {
1290: set_linemem ();
1291: clear_inhibit_frame (IHF_WINDOWHIDDEN);
1292: return surface;
1293: }
1294:
1295: tmp = sizeof (ClipList.rects);
1296:
1297: /* This is the VERY instruction that drags other threads (input/file system) down when in windowed
1298: * mode - WHY can't Microsoft implement the IsClipListChanged() method as documented? ARGH! */
1299: if (IDirectDrawClipper_GetClipList (lpDDC, NULL, (LPRGNDATA) & ClipList, &tmp) == DD_OK) {
1300: lpRect = ClipList.rects;
1301:
1302: if (!ClipList.rdh.nCount) {
1303: write_log("ClipList empty\n");
1304: set_inhibit_frame (IHF_WINDOWHIDDEN);
1305: unlockscr ();
1306: return 0;
1307: }
1308:
1309: if (ClipList.rdh.nCount != 1
1310: || lpRect->right - lpRect->left != current_width
1311: || lpRect->bottom - lpRect->top != current_height)
1312: {
1313: scrindirect = 1;
1314: for (tmp = ClipList.rdh.nCount; tmp--; lpRect++) {
1315: lpRect->left -= amigawin_rect.left;
1316: lpRect->right -= amigawin_rect.left;
1317: lpRect->top -= amigawin_rect.top;
1318: lpRect->bottom -= amigawin_rect.top;
1319:
1320: lpRect->right -= lpRect->left;
1321: }
1322: }
1323: }
1324:
1325: set_linemem ();
1326: clear_inhibit_frame (IHF_WINDOWHIDDEN);
1327: return surface;
1328: }
1329:
1330: int graphics_init (void)
1331: {
1332: static int first_time = 1;
1333: if (first_time)
1334: figure_processor_speed ();
1335: first_time = 0;
1336: #ifdef PICASSO96
1337: if (screen_is_picasso) {
1338: fullscreen = picasso_fullscreen;
1339: current_width = picasso_vidinfo.width;
1340: current_height = picasso_vidinfo.height;
1341: } else
1342: #endif
1343: {
1344: fullscreen = amiga_fullscreen;
1345: current_width = currprefs.gfx_width;
1346: current_height = currprefs.gfx_height;
1347:
1348: if (!fullscreen) {
1349: if (current_height > 290 << currprefs.gfx_linedbl)
1350: current_height = 290 << currprefs.gfx_linedbl;
1351: if (current_width > 800 >> currprefs.gfx_lores)
1352: current_width = 800 >> currprefs.gfx_lores;
1353: }
1354: current_width = (current_width + 7) & ~7;
1355: }
1356:
1357: if (!doInit ())
1358: return 0;
1359:
1360: *xcolors = 0;
1361:
1362: return 1;
1363: }
1364:
1365: void graphics_leave (void)
1366: {
1367: dumpcustom ();
1368: }
1369:
1370: void shutdownmain (void)
1371: {
1372: changemode = 3;
1373: PostMessage (hAmigaWnd, WM_QUIT, 0, 0);
1374: }
1375:
1376: void workthread(void)
1377: {
1378: if (use_debugger && debuggable ())
1379: activate_debugger ();
1380:
1381: do_start_program();
1382: shutdownmain();
1383: }
1384:
1385: void start_program (void)
1386: {
1387: DWORD id;
1388: MSG msg;
1389:
1390: SetPriorityClass (GetCurrentProcess (), process_desired_pri);
1391:
1392: hEmuThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) workthread, 0, CREATE_SUSPENDED, &id);
1393: SetThreadPriority (hEmuThread, THREAD_PRIORITY_BELOW_NORMAL);
1394: ResumeThread (hEmuThread);
1395:
1396: for (;;) {
1397: int cm;
1398: while (GetMessage (&msg, NULL, 0, 0)) {
1399: TranslateMessage (&msg);
1400: DispatchMessage (&msg);
1401: }
1402: cm = changemode;
1403: if (cm == 3)
1404: break;
1405:
1406: changemode = 0;
1407: current_pixbytes = 0;
1408: if (!graphics_init ())
1409: break;
1410:
1411: if (cm == 2) {
1412: uae_sem_post (&picasso_switch_sem);
1413: }
1414: clear_inhibit_frame (5);
1415: notice_screen_contents_lost ();
1416: notice_new_xcolors ();
1417:
1418: notice_new_xcolors ();
1419:
1420: /*ResumeThread (hEmuThread);*/
1421:
1422: if (currprefs.produce_sound > 1)
1423: startsound ();
1424: }
1425: }
1426:
1427: void handle_events (void)
1428: {
1429: }
1430:
1431: #ifdef CONFIG_FOR_SMP
1432: int uae_sem_initcs (LPCRITICAL_SECTION * cs)
1433: {
1434: *cs = (LPCRITICAL_SECTION) GlobalAlloc (GPTR, sizeof csDraw);
1435: InitializeCriticalSection (*cs);
1436: }
1437:
1438: void uae_sem_enter (LPCRITICAL_SECTION cs)
1439: {
1440: EnterCriticalSection (cs);
1441: }
1442:
1443: void uae_sem_leave (LPCRITICAL_SECTION cs)
1444: {
1445: LeaveCriticalSection (cs);
1446: }
1447:
1448: void uae_sleep (int ms)
1449: {
1450: Sleep (ms);
1451: }
1452:
1453: #endif
1454:
1455: /* this is the semaphore for protecting the actual drawing against intermittent window movements */
1456: void begindrawing (void)
1457: {
1458: EnterCriticalSection (&csDraw);
1459: }
1460:
1461: void enddrawing (void)
1462: {
1463: LeaveCriticalSection (&csDraw);
1464: }
1465:
1466: /* this truly sucks, I'll include a native gunzip() routine soon */
1467: int gunzip_hack (const char *src, const char *dst)
1468: {
1469: char buf[1024];
1470: STARTUPINFO si =
1471: {sizeof si};
1472: PROCESS_INFORMATION pi;
1473:
1474: strcpy (buf, dst);
1475: strcat (buf, ".gz");
1476:
1477: if (CopyFile (src, buf, FALSE)) {
1478: sprintf (buf, "gzip -f -d \"%s.gz\"", dst);
1479: si.dwFlags = STARTF_USESTDHANDLES;
1480: if (CreateProcess (NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
1481: WaitForSingleObject (pi.hProcess, INFINITE);
1482: return -1;
1483: } else {
1484: MyOutputDebugString ("Error: You need gzip.exe (32 bit) to use .adz/.roz files!\n");
1485: }
1486: }
1487: return 0;
1488: }
1489:
1490: /* file name requester. hBackBM will hopefully be dropped in the near future. */
1491: static OPENFILENAME ofn = {
1492: sizeof (OPENFILENAME),
1493: NULL, NULL, "Amiga Disk Files\000*.adf;*.adz\000",
1494: NULL, 0, 0, 0, 256, NULL, 0, "",
1495: 0,
1496: OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
1497: 0,
1498: 0,
1499: "adf",
1500: 0,
1501: NULL,
1502: NULL
1503: };
1504:
1505: int requestfname (char *title, char *name)
1506: {
1507: HDC hDC;
1508: char *result;
1509: RECT rc;
1510: #ifdef PICASSO96
1511: uae_u8 old_switch_state = picasso96_state.SwitchState;
1512: #endif
1513:
1514: ofn.hwndOwner = hAmigaWnd;
1515: ofn.lpstrTitle = title;
1516: ofn.lpstrFile = name;
1517:
1518: if (pGetOpenFileNameA == 0)
1519: return 0;
1520:
1521: if (IDirectDrawSurface_GetDC (lpDDS, &hDC) == DD_OK) {
1522: if ((hBackBM = CreateCompatibleBitmap (hDC, currprefs.gfx_width, currprefs.gfx_height))
1523: && (hBackDC = CreateCompatibleDC (hDC))) {
1524: SelectObject (hBackDC, hBackBM);
1525:
1526: if (fullscreen)
1527: BitBlt (hBackDC, 0, 0, currprefs.gfx_width, currprefs.gfx_height, hDC, 0, 0, SRCCOPY);
1528: else {
1529: BitBlt (hBackDC, 0, 0, currprefs.gfx_width, currprefs.gfx_height, hDC,
1530: amigawin_rect.left, amigawin_rect.top, SRCCOPY);
1531: }
1532: }
1533: IDirectDrawSurface_ReleaseDC (lpDDS, hDC);
1534: }
1535: if (!fullscreen)
1536: setmouseactive (0);
1537:
1538: if (title)
1539: result = (char *)((*pGetOpenFileNameA) (&ofn));
1540: else {
1541: GetSettings ();
1542: }
1543:
1544: if (!fullscreen || !mouseactive)
1545: SetCursor (NULL);
1546:
1547: if (hBackBM) {
1548: if (hBackDC) {
1549: if (fullscreen && IDirectDrawSurface_GetDC (lpDDS, &hDC) == DD_OK) {
1550: BitBlt (hDC, 0, 0, currprefs.gfx_width, currprefs.gfx_height, hBackDC, 0, 0, SRCCOPY);
1551: IDirectDrawSurface_ReleaseDC (lpDDS, hDC);
1552: }
1553: DeleteObject (hBackDC);
1554: hBackDC = NULL;
1555: }
1556: DeleteObject (hBackBM);
1557: hBackBM = NULL;
1558: }
1559: notice_screen_contents_lost ();
1560:
1561: if (result)
1562: return 1;
1563:
1564: return 0;
1565: }
1566:
1567: int DisplayGUI( void )
1568: {
1569: HBITMAP hBackBM2 = NULL;
1570: #ifdef PICASSO96
1571: BITMAPINFO bminfo = { sizeof( BITMAPINFOHEADER ), current_width, -current_height, 1, 8, BI_RGB, 0, 0, 0, 0, 0, &picasso96_state.CLUT };
1572: #endif
1573: HDC hDC;
1574: void *blah;
1575: RECT rc;
1576: uae_u8 p96_8bit = 0;
1577:
1578: if (pGetOpenFileNameA)
1579: {
1580: if (IDirectDrawSurface_GetDC(lpDDS,&hDC) == DD_OK)
1581: {
1582: #ifdef PICASSO96
1583: if( picasso96_state.SwitchState && ( picasso96_state.BytesPerPixel == 1 ) )
1584: {
1585: p96_8bit = 1;
1586: hBackBM2 = CreateDIBSection( hDC, &bminfo, DIB_PAL_COLORS, &blah, NULL, 0 );
1587: }
1588: else
1589: #endif
1590: hBackBM = CreateCompatibleBitmap( hDC, current_width, current_height );
1591:
1592: if( (hBackBM2 || hBackBM ) && ( hBackDC = CreateCompatibleDC( hDC ) ) )
1593: {
1594: #ifdef PICASSO96
1595: if( hBackBM2 )
1596: {
1597: SelectObject( hBackDC, hBackBM2 );
1598: hBackBM = CreateCompatibleBitmap( hDC, current_width, current_height );
1599: }
1600: else
1601: #endif
1602: SelectObject( hBackDC, hBackBM );
1603:
1604: if( fullscreen )
1605: BitBlt( hBackDC, 0, 0, current_width, current_height, hDC, 0, 0, SRCCOPY );
1606: else
1607: {
1608: GetWindowRect(hAmigaWnd,&rc);
1609: BitBlt(hBackDC,0,0,current_width,current_height,hDC,rc.left,rc.top,SRCCOPY);
1610: }
1611:
1612: IDirectDrawSurface2_SetPalette( lpDDS, NULL );
1613: if( hBackBM2 )
1614: BitBlt( hDC, 0, 0, current_width, current_height, hBackDC, 0, 0, SRCCOPY );
1615: }
1616: IDirectDrawSurface_ReleaseDC( lpDDS, hDC );
1617: }
1618:
1619: if (!fullscreen) setmouseactive(FALSE);
1620:
1621: GetSettings();
1622: if( lpDDP )
1623: IDirectDrawSurface2_SetPalette( lpDDS, lpDDP );
1624:
1625: if (!fullscreen || !mouseactive) SetCursor(NULL);
1626:
1627: if( hBackBM || hBackBM2 )
1628: {
1629: if( hBackDC )
1630: {
1631: #ifdef PICASSO96
1632: if( p96_8bit )
1633: {
1634: picasso96_state.RefreshPending = 1;
1635: }
1636: else
1637: #endif
1638: if( fullscreen && IDirectDrawSurface_GetDC( lpDDS, &hDC ) == DD_OK )
1639: {
1640: BitBlt( hDC, 0, 0, current_width, current_height, hBackDC, 0, 0, SRCCOPY );
1641: IDirectDrawSurface_ReleaseDC( lpDDS, hDC );
1642: }
1643: DeleteObject( hBackDC );
1644: hBackDC = NULL;
1645: }
1646: if( hBackBM2 )
1647: DeleteObject( hBackBM2 );
1648: if( hBackBM )
1649: {
1650: DeleteObject( hBackBM );
1651: hBackBM = NULL;
1652: }
1653: }
1654: }
1655: return 0;
1656: }
1657:
1658: #ifdef __GNUC__
1659: #undef WINAPI
1660: #define WINAPI
1661: #endif
1662:
1663: static HINSTANCE hDDraw = NULL, hComDlg32 = NULL, hRichEdit = NULL;
1664:
1665: int cleanuplibs(void)
1666: {
1667: if (hRichEdit)
1668: FreeLibrary(hRichEdit);
1669: if (hDDraw)
1670: FreeLibrary(hDDraw);
1671: if (hComDlg32)
1672: FreeLibrary(hComDlg32);
1673: return 1;
1674: }
1675:
1676: /* try to load COMDLG32 and DDRAW, initialize csDraw, try to obtain the system clock frequency
1677: * from the registry, try to find out if we are running on a Pentium */
1678: int initlibs (void)
1679: {
1680: /* Make sure we do an InitCommonControls() to get some advanced controls */
1681: InitCommonControls ();
1682:
1683: if (hComDlg32 = LoadLibrary ("COMDLG32.DLL")) {
1684: pGetOpenFileNameA = (BOOL (WINAPI *) (LPOPENFILENAME)) GetProcAddress (hComDlg32, "GetOpenFileNameA");
1685: } else
1686: /* System administrator? ROFL! -- Bernd */
1687: MyOutputDebugString ("COMDLG32.DLL not available. Please contact your system administrator.\n");
1688:
1689: /* LoadLibrary the richedit control stuff */
1690: if ((hRichEdit = LoadLibrary ("RICHED32.DLL")) == NULL) {
1691: MyOutputDebugString ("RICHED32.DLL not available. Please contact your system administrator.\n");
1692: }
1693: if (hDDraw = LoadLibrary ("DDRAW.DLL")) {
1694: #ifdef __GNUC__
1695: pDirectDrawCreate = (HRESULT (WINAPI *) (GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *)) GetProcAddress (hDDraw, "DirectDrawCreate");
1696: #endif
1697: InitializeCriticalSection (&csDraw);
1698:
1699: process_desired_pri = IDLE_PRIORITY_CLASS;
1700:
1701: return 1;
1702: } else
1703: MyOutputDebugString ("You have to install DirectX on your system before you can use UAE.\nRefer to the documentation for further details.\n");
1704:
1705: return 0;
1706: }
1707:
1708: void MyOutputDebugString (char *format,...)
1709: {
1710: char buffer[512];
1711: va_list parms;
1712:
1713: va_start (parms, format);
1714: vsprintf (buffer, format, parms);
1715: va_end (parms);
1716: write_log (buffer);
1717: }
1718:
1719: void write_log (const char *txt)
1720: {
1721: DWORD numwritten;
1722: #ifdef _DEBUG
1723: OutputDebugString( txt );
1724: #endif
1725: fprintf (stderr, "%s", txt);
1726: /* if (HasConsole)
1727: WriteConsole (stdouthandle, txt, strlen (txt), &numwritten, NULL);*/
1728: WriteFile (debugfile, txt, strlen (txt), &numwritten, NULL);
1729: }
1730:
1731: int debuggable (void)
1732: {
1733: return 1;
1734: }
1735:
1736: int needmousehack (void)
1737: {
1738: return 1;
1739: }
1740:
1741: void LED (int on)
1742: {
1743: }
1744:
1745:
1746: static uae_u16 *ppicasso_format;
1747: static int picasso_modecount;
1748:
1749: static HRESULT CALLBACK modesCallback (LPDDSURFACEDESC modeDesc, LPVOID context)
1750: {
1751: int bpp;
1752:
1753: if (picasso_modecount >= MAX_PICASSO_MODES)
1754: return DDENUMRET_CANCEL;
1755:
1756: if (modeDesc->dwFlags & (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_REFRESHRATE)) {
1757: bpp = modeDesc->ddpfPixelFormat.dwRGBBitCount;
1758: #ifdef PICASSO96
1759: switch (bpp) {
1760: case 8:
1761: *ppicasso_format |= RGBFF_CHUNKY;
1762: break;
1763: case 16:
1764: /* figure out which actual format it is using based on the RGB masks */
1765:
1766: /* Bernd - this doesn't work for some reason. Instead, I figure out the modes in doInit(),
1767: * where I have the surface's description and pixel formats. Damned DirectDraw stuff!
1768: */
1769: break;
1770: case 24:
1771: /* figure out which actual format it is using based on the RGB masks */
1772: if (modeDesc->ddpfPixelFormat.dwRBitMask == 0x00FF0000)
1773: *ppicasso_format |= RGBFF_B8G8R8;
1774: else
1775: *ppicasso_format |= RGBFF_R8G8B8;
1776: break;
1777: case 32:
1778: /* figure out which actual format it is using based on the RGB masks */
1779: if (modeDesc->ddpfPixelFormat.dwRBitMask == 0x00FF0000)
1780: *ppicasso_format |= RGBFF_B8G8R8A8;
1781: else if (modeDesc->ddpfPixelFormat.dwRBitMask == 0x000000FF)
1782: *ppicasso_format |= RGBFF_R8G8B8A8;
1783: else if (modeDesc->ddpfPixelFormat.dwBBitMask == 0xFF000000)
1784: *ppicasso_format |= RGBFF_A8R8G8B8;
1785: else
1786: *ppicasso_format |= RGBFF_A8B8G8R8;
1787: break;
1788: }
1789: #endif
1790: DisplayModes[picasso_modecount].res.width = modeDesc->dwWidth;
1791: DisplayModes[picasso_modecount].res.height = modeDesc->dwHeight;
1792: DisplayModes[picasso_modecount].depth = bpp/8;
1793: if (modeDesc->dwRefreshRate)
1794: {
1795: sprintf(DisplayModes[picasso_modecount].name,"%dx%d, %d-bit, %d Hz",modeDesc->dwWidth,
1796: modeDesc->dwHeight, bpp, modeDesc->dwRefreshRate );
1797: DisplayModes[picasso_modecount].refresh = modeDesc->dwRefreshRate;
1798: }
1799: else
1800: {
1801: sprintf(DisplayModes[picasso_modecount].name,"%dx%d, %d-bit",modeDesc->dwWidth,
1802: modeDesc->dwHeight, bpp );
1803: DisplayModes[picasso_modecount].refresh = 75; /* fake a 75-Hz refresh rate... BLAH! */
1804: }
1805: picasso_modecount++;
1806: }
1807: return DDENUMRET_OK;
1808: }
1809:
1810: int DX_FillResolutions (uae_u16 *ppixel_format)
1811: {
1812: static int from_preInit = 1;
1813: if( from_preInit )
1814: {
1815: picasso_modecount = 0;
1816: *ppixel_format = 0;
1817: ppicasso_format = ppixel_format;
1818:
1819: IDirectDraw_EnumDisplayModes (lpDD, 0, NULL, NULL, modesCallback);
1820: from_preInit = 0;
1821: }
1822: return picasso_modecount;
1823: }
1824:
1825: #ifdef PICASSO96
1826:
1827: void DX_SetPalette (int start, int count)
1828: {
1829: HRESULT ddrval;
1830:
1831: if (!screen_is_picasso)
1832: return;
1833:
1834: /* Set our DirectX palette here */
1835: if (lpDDP && (picasso96_state.BytesPerPixel == 1)) {
1836: /* For now, until I figure this out, just set the entire range of CLUT values */
1837: ddrval = IDirectDrawPalette_SetEntries (lpDDP, 0, 0, 256, (LPPALETTEENTRY) &picasso96_state.CLUT);
1838: if (ddrval != DD_OK)
1839: MyOutputDebugString ("DX_SetPalette() failed with %s/%d\n", getddrname (ddrval), ddrval);
1840: } else
1841: MyOutputDebugString ("ERROR - DX_SetPalette() doesn't have palette, or isn't Chunky mode.\n");
1842: }
1843:
1844: void DX_Invalidate (int first, int last)
1845: {
1846: }
1847:
1848: int DX_BitsPerCannon (void)
1849: {
1850: return 8;
1851: }
1852:
1853: int DX_FillRect (uaecptr addr, uae_u16 X, uae_u16 Y, uae_u16 Width, uae_u16 Height, uae_u32 Pen, uae_u8 Bpp)
1854: {
1855: return 0;
1856: }
1857:
1858: void gfx_set_picasso_state (int on)
1859: {
1860: if (screen_is_picasso == on)
1861: return;
1862: screen_is_picasso = on;
1863: PostMessage (hAmigaWnd, WM_USER + 0x201, 0, 0);
1864: uae_sem_wait (&picasso_switch_sem);
1865: }
1866:
1867: void gfx_set_picasso_modeinfo (int w, int h, int depth)
1868: {
1869: depth >>= 3;
1870: if (picasso_vidinfo.width == w
1871: && picasso_vidinfo.height == h
1872: && picasso_vidinfo.depth == depth)
1873: return;
1874:
1875: picasso_vidinfo.width = w;
1876: picasso_vidinfo.height = h;
1877: picasso_vidinfo.depth = depth;
1878: picasso_vidinfo.extra_mem = 1;
1879:
1880: if (screen_is_picasso) {
1881: PostMessage (hAmigaWnd, WM_USER + 0x201, 0, 0);
1882: uae_sem_wait (&picasso_switch_sem);
1883: }
1884: }
1885:
1886: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.