WinUAE/od-win32/win32_nogui.cpp
2010-02-22 22:17:29 +02:00

500 lines
9.5 KiB
C++

#include "config.h"
#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 <mmsystem.h>
#include "sysdeps.h"
#include "options.h"
#include "sound.h"
#include "uae.h"
#include "memory.h"
#include "custom.h"
#include "events.h"
#include "xwin.h"
#include "keyboard.h"
#include "inputdevice.h"
#include "keybuf.h"
#include "drawing.h"
HWND hMainWnd;
HINSTANCE hInst;
int mouseactive, focus;
int os_winnt, os_winnt_admin, useqpc, cpu_mmx, pause_emulation;
char *start_path;
static int mm_timerres;
static int timermode, timeon;
static HANDLE timehandle;
static int timeend (void)
{
if (!timeon)
return 1;
timeon = 0;
if (timeEndPeriod (mm_timerres) == TIMERR_NOERROR)
return 1;
write_log ("TimeEndPeriod() failed\n");
return 0;
}
static int timebegin (void)
{
if (timeon) {
timeend();
return timebegin();
}
timeon = 0;
if (timeBeginPeriod (mm_timerres) == TIMERR_NOERROR) {
timeon = 1;
return 1;
}
write_log ("TimeBeginPeriod() failed\n");
return 0;
}
static void init_mmtimer (void)
{
TIMECAPS tc;
mm_timerres = 0;
if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR)
return;
mm_timerres = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);
timehandle = CreateEvent (NULL, TRUE, FALSE, NULL);
}
void sleep_millis (int ms)
{
UINT TimerEvent;
if (mm_timerres <= 0 || timermode) {
Sleep (ms);
return;
}
TimerEvent = timeSetEvent (ms, 0, timehandle, 0, TIME_ONESHOT | TIME_CALLBACK_EVENT_SET);
if (!TimerEvent) {
Sleep (ms);
} else {
WaitForSingleObject (timehandle, ms);
ResetEvent (timehandle);
timeKillEvent (TimerEvent);
}
}
void sleep_millis_busy (int ms)
{
if (timermode < 0)
return;
sleep_millis (ms);
}
#include <process.h>
static volatile int dummythread_die;
static void dummythread (void *dummy)
{
SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_LOWEST);
while (!dummythread_die);
}
static uae_u64 win32_read_processor_time (void)
{
uae_u32 foo, bar;
__asm
{
rdtsc
mov foo, eax
mov bar, edx
}
return ((uae_u64)bar << 32) | foo;
}
static int figure_processor_speed (void)
{
extern volatile frame_time_t vsynctime;
extern unsigned long syncbase;
uae_u64 clockrate, clockrateidle, qpfrate, ratea1, ratea2;
uae_u32 rate1, rate2;
double limit, clkdiv = 1, clockrate1000 = 0;
int i, ratecnt = 6;
LARGE_INTEGER freq;
int qpc_avail = 0;
int mmx = 0;
rpt_available = 1;
__try
{
__asm
{
rdtsc
}
} __except( GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION ) {
rpt_available = 0;
write_log ("CLOCKFREQ: RDTSC not supported\n");
}
__try
{
__asm
{
mov eax,1
cpuid
and edx,0x800000
mov mmx,edx
}
if (mmx)
cpu_mmx = 1;
} __except( GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION ) {
}
if (QueryPerformanceFrequency(&freq)) {
qpc_avail = 1;
write_log ("CLOCKFREQ: QPF %.2fMHz\n", freq.QuadPart / 1000000.0);
qpfrate = freq.QuadPart;
/* we don't want 32-bit overflow */
if (qpfrate > 100000000) {
qpfrate >>= 6;
qpc_avail = -1;
}
} else {
write_log ("CLOCKREQ: QPF not supported\n");
}
if (!rpt_available && !qpc_avail)
return 0;
init_mmtimer();
SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
sleep_millis (100);
dummythread_die = -1;
if (qpc_avail || rpt_available) {
if (rpt_available) {
clockrateidle = win32_read_processor_time();
sleep_millis (500);
clockrateidle = (win32_read_processor_time() - clockrateidle) * 2;
dummythread_die = 0;
_beginthread(&dummythread, 0, 0);
sleep_millis (100);
clockrate = win32_read_processor_time();
sleep_millis (500);
clockrate = (win32_read_processor_time() - clockrate) * 2;
write_log ("CLOCKFREQ: RDTSC %.2fMHz (busy) / %.2fMHz (idle)\n",
clockrate / 1000000.0, clockrateidle / 1000000.0);
clkdiv = (double)clockrate / (double)clockrateidle;
clockrate >>= 6;
clockrate1000 = clockrate / 1000.0;
}
if (clkdiv <= 0.95 || clkdiv >= 1.05 || !rpt_available) {
if (rpt_available)
write_log ("CLOCKFREQ: CPU throttling detected, using QPF instead of RDTSC\n");
useqpc = qpc_avail;
rpt_available = 1;
clkdiv = 1.0;
clockrate = qpfrate;
clockrate1000 = clockrate / 1000.0;
if (dummythread_die < 0) {
dummythread_die = 0;
_beginthread(&dummythread, 0, 0);
}
if (!qpc_avail)
write_log ("No working timing reference detected\n");
}
timermode = 0;
if (mm_timerres) {
sleep_millis (50);
timebegin ();
sleep_millis (50);
ratea1 = 0;
write_log ("Testing MM-timer resolution:\n");
for (i = 0; i < ratecnt; i++) {
rate1 = read_processor_time();
sleep_millis (1);
rate1 = read_processor_time() - rate1;
write_log ("%1.2fms ", rate1 / clockrate1000);
ratea1 += rate1;
}
write_log ("\n");
timeend ();
sleep_millis (50);
}
timermode = 1;
ratea2 = 0;
write_log ("Testing Sleep() resolution:\n");
for (i = 0; i < ratecnt; i++) {
rate2 = read_processor_time();
sleep_millis (1);
rate2 = read_processor_time() - rate2;
write_log ("%1.2fms ", rate2 / clockrate1000);
ratea2 += rate2;
}
write_log ("\n");
}
SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_NORMAL);
dummythread_die = 1;
if (clkdiv >= 0.90 && clkdiv <= 1.10 && rpt_available) {
limit = 2.5;
if ((ratea2 / ratecnt) < limit * clockrate1000) { /* regular Sleep() is ok */
timermode = 1;
write_log ("Using Sleep() (resolution < %.1fms)\n", limit);
} else if (mm_timerres && (ratea1 / ratecnt) < limit * clockrate1000) { /* MM-timer is ok */
timermode = 0;
timebegin ();
write_log ("Using MultiMedia timers (resolution < %.1fms)\n", limit);
} else {
timermode = -1; /* both timers are bad, fall back to busy-wait */
write_log ("falling back to busy-loop waiting (timer resolution > %.1fms)\n", limit);
}
} else {
timermode = -1;
write_log ("forcing busy-loop wait mode\n");
}
syncbase = (unsigned long)clockrate;
return 1;
}
int needmousehack (void)
{
return 0;
}
void gui_message (const char *format,...)
{
}
void gui_led (int led, int on)
{
}
void gui_fps (int fps)
{
}
void gui_hd_led (int led)
{
}
void gui_cd_led (int led)
{
}
void gui_unlock (void)
{
}
void gui_lock (void)
{
}
int gui_update (void)
{
return 0;
}
char *DXError (HRESULT ddrval)
{
return "";
}
void setmouseactive (int active)
{
}
void minimizewindow (void)
{
}
int isfullscreen (void)
{
return 0;
}
void fullscreentoggle (void)
{
}
void disablecapture (void)
{
}
void WIN32GUI_DisplayGUI (int shortcut)
{
}
void flush_block (int a, int b)
{
}
void flush_screen (int a, int b)
{
}
void flush_line (int lineno)
{
}
void flush_clear_screen (void)
{
}
int lockscr (void)
{
return 1;
}
void unlockscr (void)
{
}
void machdep_init (void)
{
}
void handle_events (void)
{
}
int debuggable (void)
{
return 0;
}
int graphics_init (void)
{
return 1;
}
int graphics_setup (void)
{
return 1;
}
void graphics_leave (void)
{
}
extern FILE *debugfile;
char VersionStr[256];
static OSVERSIONINFO osVersion;
void logging_init( void )
{
static int started;
static int first;
char debugfilename[MAX_DPATH];
if (first > 1) {
write_log ("** RESTART **\n");
return;
}
if (first == 1) {
if (debugfile)
fclose (debugfile);
debugfile = 0;
}
if( currprefs.win32_logfile ) {
sprintf( debugfilename, "%s\\winuaelog.txt", start_path );
if( !debugfile )
debugfile = fopen( debugfilename, "wt" );
} else if (!first) {
sprintf( debugfilename, "%s\\winuaebootlog.txt", start_path );
if( !debugfile )
debugfile = fopen( debugfilename, "wt" );
}
first++;
write_log ( "%s", VersionStr );
write_log (" (OS: %s %d.%d%s)", os_winnt ? "NT" : "W9X/ME", osVersion.dwMajorVersion, osVersion.dwMinorVersion, os_winnt_admin ? " Administrator privileges" : "");
write_log ("\n(c) 1995-2001 Bernd Schmidt - Core UAE concept and implementation."
"\n(c) 1998-2003 Toni Wilen - Win32 port, core code updates."
"\n(c) 1996-2001 Brian King - Win32 port, Picasso96 RTG, and GUI."
"\n(c) 1996-1999 Mathias Ortmann - Win32 port and bsdsocket support."
"\n(c) 2000-2001 Bernd Meyer - JIT engine."
"\n(c) 2000-2001 Bernd Roesch - MIDI input, many fixes."
"\nPress F12 to show the Settings Dialog (GUI), Alt-F4 to quit."
"\nEnd+F1 changes floppy 0, End+F2 changes floppy 1, etc."
"\n");
}
void target_save_options (FILE *f, struct uae_prefs *p)
{
}
int target_parse_option (struct uae_prefs *p, char *option, char *value)
{
return 0;
}
int gui_init (void)
{
return 1;
}
void gui_exit (void)
{
}
void gui_filename (int num, const char *name)
{
}
void setup_brkhandler (void)
{
}
int check_prefs_changed_gfx (void)
{
return 0;
}
void screenshot (int mode)
{
}
int _stdcall WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmd, int show)
{
char **argv, *posn;
int argc;
hInst = hInstance;
argc = __argc; argv = __argv;
start_path = xmalloc( MAX_DPATH );
GetModuleFileName( NULL, start_path, MAX_DPATH );
if( ( posn = strrchr( start_path, '\\' ) ) )
*posn = 0;
real_main (argc, argv);
if (mm_timerres && timermode == 0)
timeend ();
free (start_path);
return 0;
}