Source to src/od-win32/win32.c
/*
* UAE - The Un*x Amiga Emulator
*
* Win32 interface
*
* Copyright 1997-1998 Mathias Ortmann
* Copyright 1997-1999 Brian King
*/
/* Uncomment this line if you want the logs time-stamped */
/* #define TIMESTAMP_LOGS */
#include "sysconfig.h"
#include <stdlib.h>
#include <stdarg.h>
#include <signal.h>
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <shellapi.h>
#include <zmouse.h>
#include <ddraw.h>
#include <dbt.h>
#include <math.h>
#include "sysdeps.h"
#include "options.h"
#include "gensound.h"
#include "sounddep/sound.h"
#include "uae.h"
#include "memory.h"
#include "custom.h"
#include "events.h"
#include "xwin.h"
#include "keyboard.h"
#include "keybuf.h"
#include "drawing.h"
#include "picasso96.h"
#include "bsdsocket.h"
#include "osdep/win32.h"
#include "osdep/win32gfx.h"
#include "osdep/win32gui.h"
#include "osdep/dxwrap.h"
#include "autoconf.h"
#include "gui.h"
#include "newcpu.h"
extern void WIN32GFX_WindowMove ( void );
extern void WIN32GFX_WindowSize ( void );
unsigned long *win32_stackbase;
unsigned long *win32_freestack[42]; //EXTRA_STACK_SIZE
/* Comment out the following line if you don't want ZLIB.DLL support */
#undef USE_ZLIB_DLL
#ifdef USE_ZLIB_DLL
#include "zlib.h"
#endif
int useqpc = 0; /* Set to TRUE to use the QueryPerformanceCounter() function instead of rdtsc() */
static FILE *debugfile = NULL;
HINSTANCE hInst = NULL;
HMODULE hUIDLL = NULL;
HWND (WINAPI *pHtmlHelp)(HWND, LPCSTR, UINT, LPDWORD ) = NULL;
HWND hAmigaWnd, hMainWnd;
/*DWORD Keys; */
RECT amigawin_rect;
char VersionStr[256];
int in_sizemove = 0;
int manual_painting_needed = 0;
int customsize = 0;
int bActive;
int toggle_sound;
BOOL viewing_child = FALSE;
HKEY hWinUAEKey = NULL;
COLORREF g_dwBackgroundColor = RGB(10, 0, 10);
/* Keyboard emulation, Win32 helper routines. */
static LPARAM keysdown[256];
static short numkeysdown;
int checkkey (int vkey, LPARAM lParam)
{
switch (vkey) {
case VK_LWIN:
case VK_RWIN:
case VK_SHIFT:
case VK_LSHIFT:
case VK_RSHIFT:
case VK_CONTROL:
case VK_LCONTROL:
case VK_RCONTROL:
case VK_MENU:
case VK_LMENU:
case VK_RMENU:
return GetKeyState (vkey) & 0x8000;
}
return GetAsyncKeyState (vkey) & 0x8000;
}
/* Mouse emulation, Win32 interface */
static int mousecx = 160, mousecy = 100, mousedx = 160, mousedy = 100;
static int mousecl = MAKELONG (160, 100);
int mouseactive;
void WIN32_MouseDefaults( void )
{
mousecx = 160, mousecy = 100, mousedx = 160, mousedy = 100, mousecl = MAKELONG (160, 100);
}
void setmouseactive (int active)
{
mousedx = (amigawin_rect.right - amigawin_rect.left) / 2;
mousedy = (amigawin_rect.bottom - amigawin_rect.top) / 2;
mousecl = MAKELONG (mousedx, mousedy);
mousecx = amigawin_rect.left + mousedx;
mousecy = amigawin_rect.top + mousedy;
if (active == mouseactive)
return;
mouseactive = active;
if (active)
{
#ifdef HARDWARE_SPRITE_EMULATION
if( !WIN32GFX_IsPicassoScreen() )
#endif
{
ShowCursor (FALSE);
SetCursorPos (mousecx, mousecy);
}
SetWindowText (hMainWnd ? hMainWnd : hAmigaWnd, "UAE/Win32 - [Mouse active - press Alt-Tab to cancel]");
ClipCursor (&amigawin_rect);
}
else
{
ShowCursor (TRUE);
SetWindowText (hMainWnd ? hMainWnd : hAmigaWnd, "UAE/Win32" );
ClipCursor (NULL);
}
}
static int hascapture = 0;
static void setcapture (void)
{
if (hascapture)
return;
hascapture++;
SetCapture (hAmigaWnd);
}
void releasecapture (void)
{
if (!hascapture)
return;
hascapture--;
ReleaseCapture ();
}
frame_time_t read_processor_time_cyrix (void)
{
LARGE_INTEGER counter;
QueryPerformanceCounter( &counter );
return (frame_time_t)(counter.LowPart);
}
#include <setjmp.h>
jmp_buf catch_test;
static RETSIGTYPE illhandler(int foo)
{
rpt_available = 0;
longjmp(catch_test,1);
}
int have_rdtsc (void)
{
rpt_available = 1;
write_log ("Testing the RDTSC instruction ... ");
signal (SIGILL, illhandler);
if (setjmp (catch_test) == 0)
read_processor_time ();
signal (SIGILL, SIG_DFL);
write_log ("done.\n");
if (! rpt_available) {
write_log ("Your processor does not support the RDTSC instruction.\n");
return 0;
}
return 1;
}
static void figure_processor_speed (void)
{
extern volatile frame_time_t vsynctime;
extern unsigned long syncbase;
frame_time_t clockrate;
#if defined __GNUC__
if (! have_rdtsc ())
useqpc = 1;
#else
LARGE_INTEGER freq;
__try
{
__asm{rdtsc};
}
__except( GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION )
{
useqpc = 1;
}
if( QueryPerformanceFrequency( &freq ) )
{
if (freq.LowPart > 90000000) /* looks like CPU freq. */
write_log ( "CLOCKFREQ: QueryPerformanceFrequency() reports %d-MHz\n", freq.LowPart / 1000000 );
else
write_log ( "CLOCKFREQ: QueryPerformanceFrequency() reports %.2f-MHz\n", (float)freq.LowPart / 1000000.0f );
if( freq.LowPart < 1000000 )
{
write_log ( "CLOCKFREQ: Weird value. Using QueryPerformanceCounter() instead of RDTSC.\n" );
useqpc = 1;
}
rpt_available = 1;
}
else
{
write_log ( "CLOCKFREQ: No support for clock-rate stuff!\n" );
rpt_available = 0;
}
#endif
SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS );
clockrate = read_processor_time();
Sleep( 1000 );
clockrate = read_processor_time() - clockrate;
SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS );
write_log ( "CLOCKFREQ: Measured as %d-MHz\n", clockrate / 1000000 );
syncbase = clockrate;
vsynctime = syncbase / VBLANK_HZ_PAL; /* default to 50Hz */
}
static BOOL bDiskChanged = FALSE;
static long FAR PASCAL AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hDC;
short wheeldelta;
static int store_xy = 0;
BOOL minimized;
LPMINMAXINFO lpmmi;
RECT rect;
switch( message )
{
case WM_PALETTECHANGED:
if( (HWND)wParam != hWnd )
{
write_log ( "WM_PALETTECHANGED Request\n" );
WIN32GFX_PaletteChange();
}
break;
case WM_ACTIVATEAPP:
if (bActive = wParam)
{
if( WIN32GFX_IsFullScreen() )
{
SetCursor (NULL);
#ifndef HARDWARE_SPRITE_EMULATION
SetCursorPos (mousecx, mousecy);
#else
if( !WIN32GFX_IsPicassoScreen() )
SetCursorPos (mousecx, mousecy);
#endif
}
my_kbd_handler (VK_CAPITAL, 0x3a, TRUE);
}
else
{
if( !WIN32GFX_IsFullScreen() )
setmouseactive (0);
else
{
if( WIN32GFX_IsPicassoScreen() )
{
WIN32GFX_DisablePicasso();
}
}
}
break;
case WM_ACTIVATE:
minimized = HIWORD( wParam );
if (LOWORD (wParam) != WA_INACTIVE)
{
write_log ( "WinUAE now active via WM_ACTIVATE\n" );
if( !minimized )
{
if( currprefs.win32_iconified_nospeed )
{
SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS );
}
if( currprefs.win32_iconified_nosound )
{
resume_sound();
}
clear_inhibit_frame( IHF_WINDOWHIDDEN );
}
ShowWindow (hWnd, SW_RESTORE);
if( WIN32GFX_IsPicassoScreen() )
{
WIN32GFX_EnablePicasso();
}
}
else
{
write_log ( "WinUAE now inactive via WM_ACTIVATE\n" );
if( minimized && !quit_program )
{
if( currprefs.win32_iconified_nospeed )
{
SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
}
if( currprefs.win32_iconified_nosound )
{
pause_sound ();
}
set_inhibit_frame( IHF_WINDOWHIDDEN );
}
}
break;
case WM_SETCURSOR:
if( WIN32GFX_IsFullScreen() )
{
#ifdef HARDWARE_SPRITE_EMULATION
if( !WIN32GFX_IsPicassoScreen() )
#endif
SetCursor (NULL);
return TRUE;
}
break;
case WM_SYSCOMMAND:
switch( wParam & 0xFFF0 )
{
case SC_MAXIMIZE:
WIN32GFX_ToggleFullScreen();
return 0;
break;
case SC_MINIMIZE:
WIN32GFX_DisablePicasso();
break;
}
break;
case WM_KEYUP:
case WM_SYSKEYUP:
numkeysdown--;
keysdown[wParam] = 0;
my_kbd_handler (wParam, (lParam >> 16) & 0x1ff, FALSE);
return 0;
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (LOWORD (lParam) == 1)
{
if (numkeysdown)
{
int key;
numkeysdown = 0;
for (key = 256; key--;)
{
if (keysdown[key])
{
if (checkkey (key, lParam))
numkeysdown++;
else
{
my_kbd_handler (key, (keysdown[key] >> 16) & 0x1ff, FALSE);
keysdown[key] = 0;
}
}
}
}
if (!keysdown[wParam])
{
keysdown[wParam] = lParam;
numkeysdown++;
}
numkeysdown++;
my_kbd_handler (wParam, (lParam >> 16) & 0x1ff, TRUE);
}
break;
case WM_LBUTTONDBLCLK: // According to MSDN, having CS_DBLCLKS in your window-class
// means that the sequence is WM_LBUTTONDOWN, WM_LBUTTONUP,
// WM_LBUTTONDBLCLK, and WM_LBUTTONUP.
// So we need to make WM_LBUTTONDBLCLK act like WM_LBUTTONDOWN.
case WM_LBUTTONDOWN:
if (ievent_alive) {
setcapture ();
buttonstate[0] = 1;
} else if (!WIN32GFX_IsFullScreen() && !mouseactive)
setmouseactive (1);
else
buttonstate[0] = 1;
break;
case WM_LBUTTONUP:
releasecapture ();
buttonstate[0] = 0;
break;
case WM_MBUTTONDOWN:
if (ievent_alive)
setcapture ();
buttonstate[1] = 1;
break;
case WM_MBUTTONUP:
releasecapture ();
buttonstate[1] = 0;
break;
case WM_RBUTTONDOWN:
if (ievent_alive)
setcapture ();
buttonstate[2] = 1;
break;
case WM_RBUTTONUP:
releasecapture ();
buttonstate[2] = 0;
break;
case WM_VSCROLL:
write_log ( "WM_VSCROLL\n" );
if( LOWORD( wParam ) == SB_LINEDOWN )
record_key(0x7A<<1);
else if( LOWORD( wParam ) == SB_LINEUP )
record_key(0x7B<<1);
break;
case WM_MOUSEWHEEL:
wheeldelta = HIWORD(wParam);
write_log ( "WM_MOUSEWHEEL with delta %d\n", wheeldelta );
if( wheeldelta > 0 )
record_key(0x7A<<1);
else if( wheeldelta < 0 )
record_key(0x7B<<1);
break;
case WM_MOUSEMOVE:
#ifndef HARDWARE_SPRITE_EMULATION
if( ( mouseactive && !ievent_alive ) ||
WIN32GFX_IsFullScreen() )
#else
if( ( ( mouseactive && !ievent_alive ) || WIN32GFX_IsFullScreen() ) &&
!WIN32GFX_IsPicassoScreen() )
#endif
{
/*
* In this mode, the mouse pointer is always centered in the window,
* this is ensured by the SetCursorPos call below.
* We don't want to handle messages that result from such a SetCursorPos
* call (recursion!), so exit early if we see one.
*/
if (lParam == mousecl)
break;
lastmx += (signed short) LOWORD (lParam) - mousedx;
lastmy += (signed short) HIWORD (lParam) - mousedy;
if (ievent_alive)
{
if (lastmx < 0)
lastmx = 0;
if (lastmx > WIN32GFX_GetWidth() )
lastmx = WIN32GFX_GetWidth();
if (lastmy < 0)
lastmy = 0;
if (lastmy > WIN32GFX_GetHeight() )
lastmy = WIN32GFX_GetHeight();
}
SetCursorPos (mousecx, mousecy);
break;
}
lastmx = (signed short) LOWORD (lParam);
lastmy = (signed short) HIWORD (lParam);
break;
case WM_PAINT:
notice_screen_contents_lost ();
hDC = BeginPaint (hWnd, &ps);
/* Check to see if this WM_PAINT is coming while we've got the GUI visible */
if( manual_painting_needed )
{
/* Update the display area */
if( !WIN32GFX_IsFullScreen() )
{
if( DirectDraw_GetLockableType() != overlay_surface )
DX_Blit( 0, 0, 0, 0, WIN32GFX_GetWidth(), WIN32GFX_GetHeight(), BLIT_SRC );
}
else
{
DirectDraw_Blt( primary_surface, NULL, secondary_surface, NULL, DDBLT_WAIT, NULL );
}
}
EndPaint (hWnd, &ps);
break;
case WM_DROPFILES:
if (DragQueryFile ((HDROP) wParam, (UINT) - 1, NULL, 0)) {
if (DragQueryFile ((HDROP) wParam, 0, NULL, 0) < 255)
DragQueryFile ((HDROP) wParam, 0, changed_prefs.df[0], sizeof (changed_prefs.df[0]));
}
DragFinish ((HDROP) wParam);
break;
case WM_CAPTURECHANGED:
if ((HWND)lParam != hAmigaWnd)
buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
break;
case WM_TIMER:
finishjob ();
break;
case WM_CREATE:
DragAcceptFiles (hWnd, TRUE);
break;
case WM_CLOSE:
uae_quit ();
return 0;
case WM_WINDOWPOSCHANGED:
if( GetWindowRect( hWnd, &amigawin_rect) )
{
if( hMainWnd )
{
if( hWinUAEKey && store_xy++)
{
RegSetValueEx( hWinUAEKey, "xPos", 0, REG_DWORD, (LPBYTE)&amigawin_rect.left, sizeof( LONG ) );
RegSetValueEx( hWinUAEKey, "yPos", 0, REG_DWORD, (LPBYTE)&amigawin_rect.top, sizeof( LONG ) );
}
}
}
break;
case WM_MOVING:
case WM_MOVE:
WIN32GFX_WindowMove();
return TRUE;
case WM_SIZING:
WIN32GFX_WindowSize();
return TRUE;
case WM_SIZE:
WIN32GFX_WindowSize();
return 0;
case WM_GETMINMAXINFO:
rect.left=0;
rect.top=0;
lpmmi=(LPMINMAXINFO)lParam;
rect.right=320;
rect.bottom=256;
//AdjustWindowRectEx(&rect,WSTYLE,0,0);
lpmmi->ptMinTrackSize.x=rect.right-rect.left;
lpmmi->ptMinTrackSize.y=rect.bottom-rect.top;
return 0;
default:
#if 0
#ifdef BSDSOCKET_SUPPORTED
if( message >= 0xB000 && message < 0xB000+MAXPENDINGASYNC*2 )
{
#if DEBUG_SOCKETS
write_log ( "sockmsg(0x%x, 0x%x, 0x%x)\n", message, wParam, lParam );
#endif
sockmsg( message, wParam, lParam );
return 0;
}
#endif
#endif
break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
static long FAR PASCAL MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
RECT rc;
HDC hDC;
switch (message) {
case WM_LBUTTONDOWN:
case WM_MOUSEWHEEL:
case WM_MOUSEMOVE:
case WM_ACTIVATEAPP:
case WM_DROPFILES:
case WM_ACTIVATE:
case WM_SETCURSOR:
case WM_SYSCOMMAND:
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MOVING:
case WM_MOVE:
case WM_SIZING:
case WM_SIZE:
case WM_GETMINMAXINFO:
case WM_CREATE:
case WM_DESTROY:
case WM_USER + 0x200:
case WM_CLOSE:
case WM_HELP:
case WM_DEVICECHANGE:
return AmigaWindowProc (hWnd, message, wParam, lParam);
case WM_DISPLAYCHANGE:
if (!WIN32GFX_IsFullScreen && (wParam + 7) / 8 != DirectDraw_GetBytesPerPixel() )
WIN32GFX_DisplayChangeRequested();
break;
case WM_ENTERSIZEMOVE:
in_sizemove++;
break;
case WM_EXITSIZEMOVE:
in_sizemove--;
/* fall through */
case WM_WINDOWPOSCHANGED:
WIN32GFX_WindowMove();
if( hAmigaWnd && GetWindowRect (hAmigaWnd, &amigawin_rect) )
{
if (in_sizemove > 0)
break;
if( !WIN32GFX_IsFullScreen() && hAmigaWnd )
{
if( amigawin_rect.left & 3 )
{
RECT rc2;
if( GetWindowRect( hMainWnd, &rc2 ) )
{
MoveWindow (hMainWnd, rc2.left + 4 - amigawin_rect.left % 4, rc2.top,
rc2.right - rc2.left, rc2.bottom - rc2.top, TRUE);
}
}
//setmouseactive (0);
return 0;
}
}
break;
case WM_PAINT:
hDC = BeginPaint (hWnd, &ps);
GetClientRect (hWnd, &rc);
DrawEdge (hDC, &rc, EDGE_SUNKEN, BF_RECT);
EndPaint (hWnd, &ps);
break;
case WM_NCLBUTTONDBLCLK:
if (wParam == HTCAPTION) {
WIN32GFX_ToggleFullScreen();
return 0;
}
break;
default:
break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
void handle_events (void)
{
MSG msg;
while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
/* Console Win32 helper routines */
void activate_debugger ();
/* We're not a console-app anymore! */
void setup_brkhandler (void)
{
}
void remove_brkhandler (void)
{
}
int WIN32_RegisterClasses( void )
{
WNDCLASS wc;
HDC hDC = GetDC( NULL );
if( GetDeviceCaps( hDC, NUMCOLORS ) != -1 )
g_dwBackgroundColor = RGB( 255, 0, 255 );
ReleaseDC( NULL, hDC );
wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS;
wc.lpfnWndProc = AmigaWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = 0;
wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE( IDI_APPICON ) );
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.lpszMenuName = 0;
wc.lpszClassName = "AmigaPowah";
wc.hbrBackground = CreateSolidBrush( g_dwBackgroundColor );
if (!RegisterClass (&wc))
return 0;
wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = 0;
wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE( IDI_APPICON ) );
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush( g_dwBackgroundColor );
wc.lpszMenuName = 0;
wc.lpszClassName = "PCsuxRox";
if (!RegisterClass (&wc))
return 0;
return 1;
}
#ifdef __GNUC__
#undef WINAPI
#define WINAPI
#endif
static HINSTANCE hRichEdit = NULL, hHtmlHelp = NULL;
#ifdef USE_ZLIB_DLL
static HINSTANCE hZlib = NULL;
FARPROC pgzread = NULL, pgzopen = NULL, pgzclose = NULL, pgzwrite = NULL, pgzerror = NULL;
#endif
int WIN32_CleanupLibraries( void )
{
if (hRichEdit)
FreeLibrary (hRichEdit);
if( hHtmlHelp )
FreeLibrary( hHtmlHelp );
if( hUIDLL )
FreeLibrary( hUIDLL );
#ifdef USE_ZLIB_DLL
if( hZlib )
FreeLibrary( hZlib );
#endif
return 1;
}
/* HtmlHelp Initialization - optional component */
int WIN32_InitHtmlHelp( void )
{
int result = 0;
if( hHtmlHelp = LoadLibrary( "HHCTRL.OCX" ) )
{
pHtmlHelp = ( HWND(WINAPI *)(HWND, LPCSTR, UINT, LPDWORD ) )GetProcAddress( hHtmlHelp, "HtmlHelpA" );
result = 1;
}
return result;
}
#if 0
#define TESTING_LANGUAGES
#define TEST_LANGID LANG_GERMAN
//#define TEST_LANGID LANG_FRENCH
//#define TEST_LANGID LANG_TURKISH
#endif
static HMODULE LoadGUI( void )
{
HMODULE result = NULL;
LPCTSTR dllname = NULL;
LANGID language = GetUserDefaultLangID() & 0x3FF; // low 9-bits form the primary-language ID
#ifdef TESTING_LANGUAGES
language = TEST_LANGID;
#endif
switch( language )
{
case LANG_AFRIKAANS:
dllname = "WinUAE_Afrikaans.dll";
break;
case LANG_ARABIC:
dllname = "WinUAE_Arabic.dll";
break;
case LANG_ARMENIAN:
dllname = "WinUAE_Armenian.dll";
break;
case LANG_ASSAMESE:
dllname = "WinUAE_Assamese.dll";
break;
case LANG_AZERI:
dllname = "WinUAE_Azeri.dll";
break;
case LANG_BASQUE:
dllname = "WinUAE_Basque.dll";
break;
case LANG_BELARUSIAN:
dllname = "WinUAE_Belarusian.dll";
break;
case LANG_BENGALI:
dllname = "WinUAE_Bengali.dll";
break;
case LANG_BULGARIAN:
dllname = "WinUAE_Bulgarian.dll";
break;
case LANG_CATALAN:
dllname = "WinUAE_Catalan.dll";
break;
case LANG_CHINESE:
dllname = "WinUAE_Chinese.dll";
break;
case LANG_CROATIAN:
dllname = "WinUAE_CroatianSerbian.dll";
break;
case LANG_CZECH:
dllname = "WinUAE_Czech.dll";
break;
case LANG_DANISH:
dllname = "WinUAE_Danish.dll";
break;
case LANG_DUTCH:
dllname = "WinUAE_Dutch.dll";
break;
case LANG_ESTONIAN:
dllname = "WinUAE_Estonian.dll";
break;
case LANG_FAEROESE:
dllname = "WinUAE_Faeroese.dll";
break;
case LANG_FARSI:
dllname = "WinUAE_Farsi.dll";
break;
case LANG_FINNISH:
dllname = "WinUAE_Finnish.dll";
break;
case LANG_FRENCH:
dllname = "WinUAE_French.dll";
break;
case LANG_GEORGIAN:
dllname = "WinUAE_Georgian.dll";
break;
case LANG_GERMAN:
dllname = "WinUAE_German.dll";
break;
case LANG_GREEK:
dllname = "WinUAE_Greek.dll";
break;
case LANG_GUJARATI:
dllname = "WinUAE_Gujarati.dll";
break;
case LANG_HEBREW:
dllname = "WinUAE_Hebrew.dll";
break;
case LANG_HINDI:
dllname = "WinUAE_Hindi.dll";
break;
case LANG_HUNGARIAN:
dllname = "WinUAE_Hungarian.dll";
break;
case LANG_ICELANDIC:
dllname = "WinUAE_Icelandic.dll";
break;
case LANG_INDONESIAN:
dllname = "WinUAE_Indonesian.dll";
break;
case LANG_ITALIAN:
dllname = "WinUAE_Italian.dll";
break;
case LANG_JAPANESE:
dllname = "WinUAE_Japanese.dll";
break;
case LANG_KANNADA:
dllname = "WinUAE_Kannada.dll";
break;
case LANG_KASHMIRI:
dllname = "WinUAE_Kashmiri.dll";
break;
case LANG_KAZAK:
dllname = "WinUAE_Kazak.dll";
break;
case LANG_KONKANI:
dllname = "WinUAE_Konkani.dll";
break;
case LANG_KOREAN:
dllname = "WinUAE_Korean.dll";
break;
case LANG_LATVIAN:
dllname = "WinUAE_Latvian.dll";
break;
case LANG_LITHUANIAN:
dllname = "WinUAE_Lithuanian.dll";
break;
case LANG_MACEDONIAN:
dllname = "WinUAE_Macedonian.dll";
break;
case LANG_MALAY:
dllname = "WinUAE_Malay.dll";
break;
case LANG_MALAYALAM:
dllname = "WinUAE_Malayalam.dll";
break;
case LANG_MANIPURI:
dllname = "WinUAE_Manipuri.dll";
break;
case LANG_MARATHI:
dllname = "WinUAE_Marathi.dll";
break;
case LANG_NEPALI:
dllname = "WinUAE_Nepali.dll";
break;
case LANG_NORWEGIAN:
dllname = "WinUAE_Norwegian.dll";
break;
case LANG_ORIYA:
dllname = "WinUAE_Oriya.dll";
break;
case LANG_POLISH:
dllname = "WinUAE_Polish.dll";
break;
case LANG_PORTUGUESE:
dllname = "WinUAE_Portuguese.dll";
break;
case LANG_PUNJABI:
dllname = "WinUAE_Punjabi.dll";
break;
case LANG_ROMANIAN:
dllname = "WinUAE_Romanian.dll";
break;
case LANG_RUSSIAN:
dllname = "WinUAE_Russian.dll";
break;
case LANG_SANSKRIT:
dllname = "WinUAE_Sanskrit.dll";
break;
case LANG_SINDHI:
dllname = "WinUAE_Sindhi.dll";
break;
case LANG_SLOVAK:
dllname = "WinUAE_Slovak.dll";
break;
case LANG_SLOVENIAN:
dllname = "WinUAE_Slovenian.dll";
break;
case LANG_SPANISH:
dllname = "WinUAE_Spanish.dll";
break;
case LANG_SWAHILI:
dllname = "WinUAE_Swahili.dll";
break;
case LANG_SWEDISH:
dllname = "WinUAE_Swedish.dll";
break;
case LANG_TAMIL:
dllname = "WinUAE_Tamil.dll";
break;
case LANG_TATAR:
dllname = "WinUAE_Tatar.dll";
break;
case LANG_TELUGU:
dllname = "WinUAE_Telugu.dll";
break;
case LANG_THAI:
dllname = "WinUAE_Thai.dll";
break;
case LANG_TURKISH:
dllname = "WinUAE_Turkish.dll";
break;
case LANG_UKRAINIAN:
dllname = "WinUAE_Ukrainian.dll";
break;
case LANG_URDU:
dllname = "WinUAE_Urdu.dll";
break;
case LANG_UZBEK:
dllname = "WinUAE_Uzbek.dll";
break;
case LANG_VIETNAMESE:
dllname = "WinUAE_Vietnamese.dll";
break;
case 0x400:
dllname = "guidll.dll";
break;
}
if( dllname )
{
TCHAR szFilename[ MAX_PATH ];
DWORD dwVersionHandle, dwFileVersionInfoSize;
LPVOID lpFileVersionData = NULL;
BOOL success = FALSE;
result = LoadLibrary( dllname );
if( result && GetModuleFileName( result, (LPTSTR)&szFilename, MAX_PATH ) )
{
dwFileVersionInfoSize = GetFileVersionInfoSize( szFilename, &dwVersionHandle );
if( dwFileVersionInfoSize )
{
if( lpFileVersionData = calloc( 1, dwFileVersionInfoSize ) )
{
if( GetFileVersionInfo( szFilename, dwVersionHandle, dwFileVersionInfoSize, lpFileVersionData ) )
{
VS_FIXEDFILEINFO *vsFileInfo = NULL;
UINT uLen;
if( VerQueryValue( lpFileVersionData, TEXT("\\"), (void **)&vsFileInfo, &uLen ) )
{
if( vsFileInfo &&
( HIWORD(vsFileInfo->dwProductVersionMS) == UAEMAJOR )
&& ( LOWORD(vsFileInfo->dwProductVersionMS) == UAEMINOR )
&& ( HIWORD(vsFileInfo->dwProductVersionLS) == UAESUBREV )
// Change this to an #if 1 when the WinUAE Release version (as opposed to UAE-core version)
// requires a GUI-DLL change...
#if 0
&& ( LOWORD(vsFileInfo->dwProductVersionLS) == WINUAERELEASE)
#endif
)
{
success = TRUE;
}
}
}
free( lpFileVersionData );
}
}
}
if( result && !success )
{
FreeLibrary( result );
result = NULL;
}
}
return result;
}
#ifndef _WIN32_WCE
/* try to load COMDLG32 and DDRAW, initialize csDraw */
int WIN32_InitLibraries( void )
{
int result = 1;
/* Determine our processor speed and capabilities */
figure_processor_speed();
/* Make sure we do an InitCommonControls() to get some advanced controls */
InitCommonControls();
hRichEdit = LoadLibrary( "RICHED32.DLL" );
hUIDLL = LoadGUI();
#ifdef USE_ZLIB_DLL
hZlib = LoadLibrary( "ZLIB.DLL" );
if( hZlib )
{
pgzread = GetProcAddress( hZlib, "gzread" );
pgzopen = GetProcAddress( hZlib, "gzopen" );
pgzclose = GetProcAddress( hZlib, "gzclose" );
pgzwrite = GetProcAddress( hZlib, "gzwrite" );
pgzerror = GetProcAddress( hZlib, "gzerror" );
if( !pgzread || !pgzopen || !pgzclose || !pgzwrite || !pgzerror)
{
FreeLibrary( hZlib );
hZlib = NULL;
}
}
#endif
return result;
}
#endif
/* Mathias says: "this truly sucks, I'll include a native gunzip() routine soon" */
#ifdef USE_ZLIB_DLL
extern FARPROC pgzread, pgzopen, pgzclose, pgzwrite, pgzerror;
#define GZOPEN( X, Y ) (gzFile)pgzopen( X, Y )
#define GZCLOSE( X ) (int)pgzclose( X )
#define GZREAD( X, Y, Z ) (int)pgzread( X, Y, Z )
#define ZLIB_BUFFER_SIZE 32767
/* gzip decompression via zlib */
static int zlib_gunzip( const char *src, char *dst )
{
int result = 0, gzResult = 0;
gzFile zSrc = NULL;
FILE *fDst = NULL;
size_t filesize = 0;
uae_u8 *buffer = NULL;
if( hZlib )
{
zSrc = GZOPEN( src, "rb" );
fDst = fopen( dst, "wb" );
buffer = xmalloc( ZLIB_BUFFER_SIZE + 1 );
if( zSrc && fDst && buffer )
{
DWORD dwWritten = 0;
result = 1;
do
{
gzResult = GZREAD( zSrc, buffer, ZLIB_BUFFER_SIZE );
if( gzResult > 0 )
{
if( fwrite( buffer, gzResult, 1, fDst ) != 1 )
{
result = 0;
break;
}
}
} while( gzResult == ZLIB_BUFFER_SIZE );
}
if( zSrc )
{
GZCLOSE( zSrc );
}
if( fDst )
{
fclose( fDst );
}
}
return result;
}
#endif
static char *uncompress_error[2] = { "Error: You need zlib.dll to use .adz/.roz files!\n",
"Error: You need xdms.exe (32 bit) to use .dms files!\n" };
int uncompress_hack( int type, const char *src, const char *dst)
{
int result = 0;
char fullname[1024];
char buf[1024];
char cmd[256];
char *posn = NULL;
STARTUPINFO si = {sizeof si};
PROCESS_INFORMATION pi;
strcpy( fullname, dst );
if( type == 1 )
{
#ifdef USE_ZLIB_DLL
result = zlib_gunzip( src, fullname );
if( !result )
{
gui_message( uncompress_error[type-1] );
}
return result;
#else
strcpy( cmd, "gzip.exe -f -d" );
strcat( fullname, ".gz" );
#endif
}
else if( type == 2 )
{
strcpy( cmd, "xdms.exe u" );
posn = strrchr( fullname, '.' );
if( posn )
{
*posn = 0;
strcat( fullname, ".dms" );
}
}
if( CopyFile( src, fullname, FALSE ) )
{
sprintf (buf, "%s %s +%s", cmd, fullname, dst );
si.dwFlags = STARTF_USESTDHANDLES;
if( CreateProcess( NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ) )
{
WaitForSingleObject( pi.hProcess, INFINITE );
result = -1;
}
else
{
gui_message( uncompress_error[type-1] );
}
}
/* Special handling for broken xdms.exe */
if( type == 2 )
{
DeleteFile( fullname ); /* Delete the uaeXX.dms file */
}
return result;
}
/* console window for debugging messages */
/* Brian: disable for release version if you want (TW) */
#define WRITE_LOG_BUF_SIZE 4096
static int consoleopen = 0;
HANDLE stdinput,stdoutput;
static void openconsole(void)
{
if(consoleopen) return;
AllocConsole();
stdinput=GetStdHandle(STD_INPUT_HANDLE);
stdoutput=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(stdinput,ENABLE_PROCESSED_INPUT|ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_OUTPUT);
consoleopen = 1;
}
/* console functions for debugger */
void console_out (const char *format,...)
{
va_list parms;
char buffer[WRITE_LOG_BUF_SIZE];
DWORD temp;
va_start (parms, format);
_vsnprintf( buffer, WRITE_LOG_BUF_SIZE-1, format, parms );
va_end (parms);
openconsole();
WriteConsole(stdoutput,buffer,strlen(buffer),&temp,0);
}
int console_get (char *out, int maxlen)
{
DWORD len,totallen;
totallen=0;
while(maxlen>0)
{
ReadConsole(stdinput,out,1,&len,0);
if(*out == 13) break;
out++;
maxlen--;
totallen++;
}
*out=0;
return totallen;
}
void console_flush (void)
{
}
/* GCC/EGCS wants this write_log in order to work from socket-land and to do traces */
#ifdef __GNUC__
void write_log (const char *format, ...)
{
int result = 0;
DWORD numwritten;
char buffer[12];
va_list parms;
int count = 0;
int *blah = NULL;
if( debugfile )
{
#if defined HAVE_GETTICKCOUNT && defined TIMESTAMP_LOGS
{
sprintf( buffer, "%7d - ", GetTickCount() );
fprintf( debugfile, buffer );
}
#endif
va_start (parms, format);
count = vfprintf( debugfile, format, parms );
fflush( debugfile );
if( count >= WRITE_LOG_BUF_SIZE-1 )
{
fprintf( debugfile, "SHIT in write_log ()\n" );
fflush( debugfile );
*blah = 0; /* Access Violation here! */
abort();
}
else
result = count;
va_end (parms);
}
}
#else /* MSVC likes this one, and so do I */
int write_log ( const char *format, ... )
{
int result = 0;
#ifdef _DEBUG
DWORD numwritten;
#endif
char buffer[ WRITE_LOG_BUF_SIZE ];
va_list parms;
int count = 0;
int *blah = (int *)0xdeadbeef;
va_start (parms, format);
count = _vsnprintf( buffer, WRITE_LOG_BUF_SIZE-1, format, parms );
#if defined HAVE_GETTICKCOUNT && defined TIMESTAMP_LOGS
{
char buffme[WRITE_LOG_BUF_SIZE];
sprintf( buffme, "%7d - %s", GetTickCount(), buffer );
OutputDebugString( buffme );
if( debugfile )
fprintf( debugfile, buffme );
result = strlen( buffme );
}
#else
OutputDebugString( buffer );
if( debugfile )
{
fprintf( debugfile, buffer );
fflush( debugfile );
}
result = strlen( buffer );
#endif
#ifdef _DEBUG
openconsole();
WriteConsole(stdoutput,buffer,strlen(buffer),&numwritten,0);
#endif
va_end (parms);
return result;
}
#endif
int debuggable (void)
{
return 0;
}
int needmousehack (void)
{
if( WIN32GFX_IsFullScreen() || WIN32GFX_IsPicassoScreen() )
return 0;
else
return 1;
}
void LED (int a)
{
}
void logging_init( void )
{
char debugfilename[MAX_PATH];
if (1) {
sprintf( debugfilename, "%s\\winuaelog.txt", start_path );
if( !debugfile )
debugfile = fopen( debugfilename, "wt" );
}
write_log ( "%s\n", VersionStr );
write_log ("\n(c) 1995-2001 Bernd Schmidt - Core UAE concept and implementation."
"\n(c) 1996-1999 Mathias Ortmann - Win32 port and bsdsocket support."
"\n(c) 1996-2001 Brian King - Win32 port, Picasso96 RTG, and GUI."
"\n(c) 1998-2001 Toni Wilen - AGA chipset, NTSC/PAL modes.\n"
"\n(c) 2000-2001 Bernd Meyer - JIT engine.\n"
"\n(c) 2000-2001 Bernd Roesch - MIDI input, many fixes.\n"
"\nPress F12 to show the Settings Dialog (GUI), Alt-F4 to quit."
"\nEnd+F1 changes floppy 0, End+F2 changes floppy 1, etc.\n"
"\nhttp://www.codepoet.com/UAE/\n\n");
}
void logging_cleanup( void )
{
if( debugfile )
fclose( debugfile );
}
static const char *sound_styles[] = { "waveout_looping", "waveout_dblbuff", "dsound_looping", "dsound_dblbuff", 0 };
void target_save_options (FILE *f, struct uae_prefs *p)
{
fprintf (f, "win32.middle_mouse=%s\n", p->win32_middle_mouse ? "true" : "false");
fprintf (f, "win32.logfile=%s\n", p->win32_logfile ? "true" : "false");
fprintf (f, "win32.map_drives=%s\n", p->win32_automount_drives ? "true" : "false" );
fprintf (f, "win32.serial_port=%s\n", p->use_serial ? p->sername : "none" );
fprintf (f, "win32.parallel_port=%s\n", p->prtname[0] ? p->prtname : "none" );
fprintf (f, "win32.iconified_nospeed=%s\n", p->win32_iconified_nospeed ? "true" : "false");
fprintf (f, "win32.iconified_nosound=%s\n", p->win32_iconified_nosound ? "true" : "false");
fprintf (f, "win32.no_overlay=%s\n", p->win32_no_overlay ? "true" : "false" );
}
int target_parse_option (struct uae_prefs *p, char *option, char *value)
{
int result = (cfgfile_yesno (option, value, "middle_mouse", &p->win32_middle_mouse)
|| cfgfile_yesno (option, value, "logfile", &p->win32_logfile)
|| cfgfile_yesno (option, value, "no_overlay", &p->win32_no_overlay)
|| cfgfile_yesno (option, value, "map_drives", &p->automount_drives)
|| cfgfile_yesno (option, value, "iconified_nospeed", &p->win32_iconified_nospeed)
|| cfgfile_yesno (option, value, "iconified_nosound", &p->win32_iconified_nosound)
|| cfgfile_string (option, value, "serial_port", &p->sername[0], 256)
|| cfgfile_string (option, value, "parallel_port", &p->prtname[0], 256));
if (p->sername[0] == 'n')
p->use_serial = 0;
else
p->use_serial = 1;
return 0;
}
void WIN32_HandleRegistryStuff( void )
{
RGBFTYPE colortype = RGBFB_NONE;
DWORD dwType = REG_DWORD;
DWORD dwDisplayInfoSize = sizeof( colortype );
DWORD disposition;
char path[MAX_PATH] = "";
HKEY hWinUAEKeyLocal = NULL;
/* Create/Open the hWinUAEKey which points to our config-info */
if( RegCreateKeyEx( HKEY_CLASSES_ROOT, ".uae", 0, "", REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hWinUAEKey, &disposition ) == ERROR_SUCCESS )
{
// Regardless of opening the existing key, or creating a new key, we will write the .uae filename-extension
// commands in. This way, we're always up to date.
/* Set our (default) sub-key to point to the "WinUAE" key, which we then create */
RegSetValueEx( hWinUAEKey, "", 0, REG_SZ, (CONST BYTE *)"WinUAE", strlen( "WinUAE" ) + 1 );
if( ( RegCreateKeyEx( HKEY_CLASSES_ROOT, "WinUAE\\shell\\Edit\\command", 0, "", REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hWinUAEKeyLocal, &disposition ) == ERROR_SUCCESS ) )
{
/* Set our (default) sub-key to BE the "WinUAE" command for editing a configuration */
sprintf( path, "%s\\WinUAE.exe -f \"%%1\" -s use_gui=yes", start_path );
RegSetValueEx( hWinUAEKeyLocal, "", 0, REG_SZ, (CONST BYTE *)path, strlen( path ) + 1 );
}
RegCloseKey( hWinUAEKeyLocal );
if( ( RegCreateKeyEx( HKEY_CLASSES_ROOT, "WinUAE\\shell\\Open\\command", 0, "", REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hWinUAEKeyLocal, &disposition ) == ERROR_SUCCESS ) )
{
/* Set our (default) sub-key to BE the "WinUAE" command for launching a configuration */
sprintf( path, "%s\\WinUAE.exe -f \"%%1\"", start_path );
RegSetValueEx( hWinUAEKeyLocal, "", 0, REG_SZ, (CONST BYTE *)path, strlen( path ) + 1 );
}
RegCloseKey( hWinUAEKeyLocal );
}
else
{
char szMessage[ MAX_PATH ];
WIN32GUI_LoadUIString( IDS_REGKEYCREATEFAILED, szMessage, MAX_PATH );
gui_message( szMessage );
hWinUAEKey = NULL;
}
RegCloseKey( hWinUAEKey );
/* Create/Open the hWinUAEKey which points our config-info */
if( RegCreateKeyEx( HKEY_CURRENT_USER, "Software\\CodePoet Computing\\WinUAE", 0, "", REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hWinUAEKey, &disposition ) == ERROR_SUCCESS )
{
if( disposition == REG_CREATED_NEW_KEY )
{
/* Create and initialize all our sub-keys to the default values */
colortype = 0;
RegSetValueEx( hWinUAEKey, "DisplayInfo", 0, REG_DWORD, (CONST BYTE *)&colortype, sizeof( colortype ) );
RegSetValueEx( hWinUAEKey, "xPos", 0, REG_DWORD, (CONST BYTE *)&colortype, sizeof( colortype ) );
RegSetValueEx( hWinUAEKey, "yPos", 0, REG_DWORD, (CONST BYTE *)&colortype, sizeof( colortype ) );
RegSetValueEx( hWinUAEKey, "FloppyPath", 0, REG_SZ, (CONST BYTE *)start_path, strlen( start_path ) + 1 );
RegSetValueEx( hWinUAEKey, "KickstartPath", 0, REG_SZ, (CONST BYTE *)start_path, strlen( start_path ) + 1 );
RegSetValueEx( hWinUAEKey, "hdfPath", 0, REG_SZ, (CONST BYTE *)start_path, strlen( start_path ) + 1 );
}
// Set this even when we're opening an existing key, so that the version info is always up to date.
RegSetValueEx( hWinUAEKey, "Version", 0, REG_SZ, (CONST BYTE *)VersionStr, strlen( VersionStr ) + 1 );
RegQueryValueEx( hWinUAEKey, "DisplayInfo", 0, &dwType, (LPBYTE)&colortype, &dwDisplayInfoSize );
if( colortype == 0 ) /* No color information stored in the registry yet */
{
char szMessage[ 4096 ];
char szTitle[ MAX_PATH ];
WIN32GUI_LoadUIString( IDS_GFXCARDCHECK, szMessage, 4096 );
WIN32GUI_LoadUIString( IDS_GFXCARDTITLE, szTitle, MAX_PATH );
if( MessageBox( NULL, szMessage, szTitle,
MB_YESNO | MB_ICONWARNING | MB_TASKMODAL | MB_SETFOREGROUND ) == IDYES )
{
colortype = WIN32GFX_FigurePixelFormats(0);
RegSetValueEx( hWinUAEKey, "DisplayInfo", 0, REG_DWORD, (CONST BYTE *)&colortype, sizeof( colortype ) );
}
}
if( colortype )
{
/* Set the 16-bit pixel format for the appropriate modes */
WIN32GFX_FigurePixelFormats( colortype );
}
}
else
{
char szMessage[ MAX_PATH ];
WIN32GUI_LoadUIString( IDS_REGKEYCREATEFAILED, szMessage, MAX_PATH );
gui_message( szMessage );
hWinUAEKey = NULL;
}
}
void machdep_init (void)
{
}
char *start_path = NULL;
char help_file[ MAX_PATH ];
int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
char *posn;
HANDLE hMutex;
OSVERSIONINFO osVersion;
#ifdef __GNUC__
__asm__ ("leal -2300*1024(%%esp),%0" : "=r" (win32_stackbase) :);
#else
__asm{
mov eax,esp
sub eax,2300*1024
mov win32_stackbase,eax
}
#endif
hInst = hInstance;
hMutex = CreateMutex( NULL, FALSE, "WinUAE Instantiated" ); // To tell the installer we're running
osVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
if( GetVersionEx( &osVersion ) )
{
if( ( osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT ) &&
( osVersion.dwMajorVersion <= 4 ) )
{
/* WinUAE not supported on this version of Windows... */
char szWrongOSVersion[ MAX_PATH ];
WIN32GUI_LoadUIString( IDS_WRONGOSVERSION, szWrongOSVersion, MAX_PATH );
gui_message( szWrongOSVersion );
return FALSE;
}
}
/* Get our executable's root-path */
if( ( start_path = xmalloc( MAX_PATH ) ) )
{
GetModuleFileName( NULL, start_path, MAX_PATH );
if( ( posn = strrchr( start_path, '\\' ) ) )
*posn = 0;
sprintf( help_file, "%s\\WinUAE.chm", start_path );
sprintf( VersionStr, "WinUAE %d.%d.%d, Release %d%s", UAEMAJOR, UAEMINOR, UAESUBREV, WINUAERELEASE, WINUAEBETA ? WINUAEBETASTR : "" );
logging_init ();
printf ("Hello, world\n");
if( WIN32_RegisterClasses() && WIN32_InitLibraries() && DirectDraw_Start() )
{
struct foo {
DEVMODE actual_devmode;
char overrun[8];
} devmode;
DWORD i = 0;
DirectDraw_EnumDisplayModes( 0, modesCallback );
memset( &devmode, 0, sizeof(DEVMODE) + 8 );
devmode.actual_devmode.dmSize = sizeof(DEVMODE);
devmode.actual_devmode.dmDriverExtra = 8;
#define ENUM_CURRENT_SETTINGS ((DWORD)-1)
if( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, (LPDEVMODE)&devmode ) )
{
default_freq = devmode.actual_devmode.dmDisplayFrequency;
write_log ( "Your Windows desktop refresh frequency is %d Hz\n", default_freq );
if( default_freq >= 70 )
default_freq = 70;
else
default_freq = 60;
}
WIN32_HandleRegistryStuff();
if( WIN32_InitHtmlHelp() == 0 )
{
char szMessage[ MAX_PATH ];
WIN32GUI_LoadUIString( IDS_NOHELP, szMessage, MAX_PATH );
write_log ( szMessage );
}
DirectDraw_Release();
#ifdef __MINGW32__
real_main (_argc, _argv);
#else
real_main (__argc, __argv);
#endif
}
free( start_path );
}
WIN32_CleanupLibraries();
_fcloseall();
if( hWinUAEKey )
RegCloseKey( hWinUAEKey );
CloseHandle( hMutex );
return FALSE;
}