if (tod_hack_enabled > 1) {
tod_hack_enabled--;
if (tod_hack_enabled == 1) {
- write_log (_T("TOD HACK enabled\n"));
+ //write_log (_T("TOD HACK enabled\n"));
tod_hack_reset ();
}
return;
return;
if (rate != oldrate || ciaatod != tod_hack_tod_last) {
if (ciaatod != 0)
- write_log (_T("TOD HACK reset %d,%d %d,%d\n"),
- rate, oldrate, ciaatod, tod_hack_tod_last);
+ //write_log (_T("TOD HACK reset %d,%d %d,%d\n"), rate, oldrate, ciaatod, tod_hack_tod_last);
tod_hack_reset ();
oldrate = rate;
docount = 1;
cnt++;
if (cnt == 500) {
int port_insert_custom (int inputmap_port, int devicetype, DWORD flags, const TCHAR *custom);
- port_insert_custom (0, 0, 0, L"Left=0xC8 Right=0xD0 Up=0xCB Down=0xCD Fire=0x39");
- port_insert_custom (1, 0, 0, L"Left=0x48 Right=0x50 Up=0x4B Down=0x4D Fire=0x4C");
+ port_insert_custom (0, 2, 0, L"Fire.autorepeat=0x38 Left=0x4B Right=0x4D Up=0x48 Down=0x50 Fire=0x4C Fire2=0x52'");
+ port_insert_custom (1, 2, 0, L"Left=0x48 Right=0x50 Up=0x4B Down=0x4D Fire=0x4C");
} else if (cnt == 1000) {
TCHAR out[256];
bool port_get_custom (int inputmap_port, TCHAR *out);
is_syncline = 1;
}
} else {
+ static int linecounter;
/* end of scanline, run cpu emulation as long as we still have time */
vsyncmintime += vsynctimeperline;
+ linecounter++;
is_syncline = 0;
if (!vblank_found_chipset) {
if ((int)vsyncmaxtime - (int)vsyncmintime > 0 && (int)vsyncwaittime - (int)vsyncmintime > 0) {
/* Extra time left? Do some extra CPU emulation */
if ((int)vsyncmintime - (int)rpt > 0) {
is_syncline = -1;
+ linecounter = 0;
}
}
+ // extra cpu emulation time if 10 lines without extra
+ if (!is_syncline && linecounter > 9) {
+ is_syncline = -1;
+ linecounter = 0;
+ }
}
}
} else {
extern frame_time_t vsync_busywait_end (void);
extern bool vsync_busywait_do (int*, bool, bool);
extern void vsync_busywait_start (void);
-extern bool vsync_busywait_check (void);
extern double vblank_calibrate (double, bool);
extern void doflashscreen (void);
extern int flashscreen;
{
if (!af)
return;
+#ifdef RETROPLATFORM
+ // don't override custom AF autofire mappings
+ if (rp_isactive ())
+ return;
+#endif
int *afp = af_ports[index];
for (int k = 0; afp[k] >= 0; k++) {
if (afp[k] == uid->eventid[num][sub]) {
static void setautofires (struct uae_prefs *prefs, int port, int af)
{
+#ifdef RETROPLATFORM
+ // don't override custom AF autofire mappings
+ if (rp_isactive ())
+ return;
+#endif
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
setautofire (&joysticks[l], port, af);
setautofire (&mice[l], port, af);
inputdevice_get_mapping (devnum, num, &xflags, &xport, xname, xcustom, 0);
if (xport == 0)
inputdevice_set_mapping (devnum, num, xname, xcustom, xflags, MAX_JPORTS + 1, SPARE_SUB_EVENT);
- inputdevice_set_mapping (devnum, num, name, NULL, IDEV_MAPPED_GAMEPORTSCUSTOM1, port + 1, 0);
+ inputdevice_set_mapping (devnum, num, name, NULL, IDEV_MAPPED_GAMEPORTSCUSTOM1 | flags, port + 1, 0);
}
return true;
}
PSTORAGE_ADAPTER_DESCRIPTOR adpDesc;
int gli_ok;
BOOL status;
- ULONG length = 0,
- returned = 0,
- returnedLength;
+ ULONG length = 0, returned = 0, returnedLength;
+ BOOL showonly = FALSE;
//
// Now we have the device path. Open the device interface
if (hDevice == INVALID_HANDLE_VALUE) {
- write_log (_T("CreateFile failed with error: %d\n"), GetLastError());
- ret = 1;
- goto end;
+ hDevice = CreateFile(
+ udi->device_path, // device interface name
+ 0, // dwDesiredAccess
+ FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode
+ NULL, // lpSecurityAttributes
+ OPEN_EXISTING, // dwCreationDistribution
+ 0, // dwFlagsAndAttributes
+ NULL // hTemplateFile
+ );
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ write_log (_T("CreateFile failed with error: %d\n"), GetLastError());
+ ret = 1;
+ goto end;
+ }
+ showonly = TRUE;
}
query.PropertyId = StorageAdapterProperty;
udi->readonly = 1;
}
+ if (showonly) {
+ udi->dangerous = -10;
+ udi->readonly = -1;
+ goto amipartfound;
+ }
+
gli_ok = 1;
if (!DeviceIoControl (hDevice, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, (void*)&gli, sizeof (gli), &returnedLength, NULL)) {
gli_ok = 0;
int nomedia = uae_drives[index].nomedia;
TCHAR *dang = _T("?");
TCHAR *rw = _T("RW");
+ bool noaccess = false;
if (dangerousdrive)
*dangerousdrive = 0;
switch (uae_drives[index].dangerous)
{
+ case -10:
+ dang = _T("[???]");
+ noaccess = true;
+ break;
case -5:
dang = _T("[PART]");
break;
*dangerousdrive |= 1;
break;
}
- if (nomedia) {
- dang = _T("[NO MEDIA]");
- if (dangerousdrive)
- *dangerousdrive &= ~1;
- }
- if (uae_drives[index].readonly) {
- rw = _T("RO");
- if (dangerousdrive && !nomedia)
- *dangerousdrive |= 2;
- }
- if (sectorsize)
- *sectorsize = uae_drives[index].bytespersector;
- if (flags & 1) {
+ if (noaccess) {
+ if (dangerousdrive)
+ *dangerousdrive = -1;
+ if (flags & 1) {
+ _stprintf (name, _T("[ACCESS DENIED] %s"), uae_drives[index].device_name + 1);
+ return name;
+ }
+ } else {
if (nomedia) {
- _tcscpy (tmp, _T("N/A"));
- } else {
- if (size >= 1024 * 1024 * 1024)
- _stprintf (tmp, _T("%.1fG"), ((double)(uae_u32)(size / (1024 * 1024))) / 1024.0);
- else if (size < 10 * 1024 * 1024)
- _stprintf (tmp, _T("%dK"), size / 1024);
- else
- _stprintf (tmp, _T("%.1fM"), ((double)(uae_u32)(size / (1024))) / 1024.0);
+ dang = _T("[NO MEDIA]");
+ if (dangerousdrive)
+ *dangerousdrive &= ~1;
+ }
+
+ if (uae_drives[index].readonly) {
+ rw = _T("RO");
+ if (dangerousdrive && !nomedia)
+ *dangerousdrive |= 2;
+ }
+
+ if (sectorsize)
+ *sectorsize = uae_drives[index].bytespersector;
+ if (flags & 1) {
+ if (nomedia) {
+ _tcscpy (tmp, _T("N/A"));
+ } else {
+ if (size >= 1024 * 1024 * 1024)
+ _stprintf (tmp, _T("%.1fG"), ((double)(uae_u32)(size / (1024 * 1024))) / 1024.0);
+ else if (size < 10 * 1024 * 1024)
+ _stprintf (tmp, _T("%dK"), size / 1024);
+ else
+ _stprintf (tmp, _T("%.1fM"), ((double)(uae_u32)(size / (1024))) / 1024.0);
+ }
+ _stprintf (name, _T("%10s [%s,%s] %s"), dang, tmp, rw, uae_drives[index].device_name + 1);
+ return name;
}
- _stprintf (name, _T("%10s [%s,%s] %s"), dang, tmp, rw, uae_drives[index].device_name + 1);
- return name;
}
if (flags & 2)
return uae_drives[index].device_path;
}
_stprintf (p, _T("=%02X"), kc);
p += _tcslen (p);
- break;
}
}
}
const TCHAR *p2 = _tcschr (p, '=');
if (!p2)
break;
- const TCHAR *p3 = _tcschr (p, '.');
- if (!p3 || p3 >= p2) {
- p3 = NULL;
- eventlen = p2 - p;
- } else {
- eventlen = p3 - p;
- if (!_tcsncmp (p3, L"autorepeat", p2 - p3))
+ const TCHAR *p4 = p;
+ eventlen = -1;
+ for (;;) {
+ const TCHAR *p3 = _tcschr (p4, '.');
+ if (!p3 || p3 >= p2) {
+ p3 = NULL;
+ if (eventlen < 0)
+ eventlen = p2 - p;
+ break;
+ }
+ if (eventlen < 0)
+ eventlen = p3 - p;
+ if (!_tcsnicmp (p3 + 1, L"autorepeat", 10))
flags |= IDEV_MAPPED_AUTOFIRE_SET;
+ p4 = p3 + 1;
}
for (int i = 0; eventorder[i]; i++) {
#define MAX_TIMEHANDLES 8
static int timehandlecounter;
static HANDLE timehandle[MAX_TIMEHANDLES];
+static bool timehandleinuse[MAX_TIMEHANDLES];
int sleep_resolution;
static CRITICAL_SECTION cs_time;
if (main)
start = read_processor_time ();
EnterCriticalSection (&cs_time);
- cnt = timehandlecounter++;
- if (timehandlecounter >= MAX_TIMEHANDLES)
- timehandlecounter = 0;
+ for (;;) {
+ timehandlecounter++;
+ if (timehandlecounter >= MAX_TIMEHANDLES)
+ timehandlecounter = 0;
+ if (timehandleinuse[timehandlecounter] == false) {
+ cnt = timehandlecounter;
+ timehandleinuse[cnt] = true;
+ break;
+ }
+ }
LeaveCriticalSection (&cs_time);
TimerEvent = timeSetEvent (ms, 0, (LPTIMECALLBACK)timehandle[cnt], 0, TIME_ONESHOT | TIME_CALLBACK_EVENT_SET);
WaitForSingleObject (timehandle[cnt], ms);
ResetEvent (timehandle[cnt]);
timeKillEvent (TimerEvent);
+ timehandleinuse[cnt] = false;
if (main)
idletime += read_processor_time () - start;
}
#define LANG_DLL 1
//#define WINUAEBETA _T("")
-#define WINUAEBETA _T("Beta 9")
-#define WINUAEDATE MAKEBD(2012, 4, 21)
+#define WINUAEBETA _T("Beta 10")
+#define WINUAEDATE MAKEBD(2012, 4, 23)
#define WINUAEEXTRA _T("")
//#define WINUAEEXTRA _T("AmiKit Preview")
#define WINUAEREV _T("")
#define VBLANKTH_ACTIVE_WAIT 3
#define VBLANKTH_ACTIVE 4
#define VBLANKTH_ACTIVE_START 5
+#define VBLANKTH_ACTIVE_SKIPFRAME 6
+#define VBLANKTH_ACTIVE_SKIPFRAME2 7
static volatile bool vblank_found;
static volatile int flipthread_mode;
}
}
-static bool vblank_getstate (bool *state)
+static bool vblank_getstate (bool *state, int *pvp)
{
int vp, opos;
opos = prevvblankpos;
if (!getvblankpos (&vp))
return false;
+ if (pvp)
+ *pvp = vp;
if (opos > maxscanline / 2 && vp < maxscanline / 3) {
*state = true;
return true;
*state = false;
return true;
}
+static bool vblank_getstate (bool *state)
+{
+ return vblank_getstate (state, NULL);
+}
void vblank_reset (double freq)
{
static int frame_usage, frame_usage_avg, frame_usage_total;
extern int log_vsync;
static bool dooddevenskip;
+static volatile bool vblank_skipeveryother;
+static volatile bool vblank_first_time;
static bool vblanklaceskip (void)
{
static unsigned int __stdcall vblankthread (void *dummy)
{
- static bool firstvblankbasewait2; // if >85Hz mode
+ static bool firstvblankbasewait2;
while (vblankthread_mode > VBLANKTH_KILL) {
struct apmode *ap = picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
vblankthread_counter++;
sleep_millis (ap->gfx_vflip && currprefs.m68k_speed >= 0 ? 2 : 1);
} else if (vblankthread_mode == VBLANKTH_ACTIVE_START) {
// do not start until vblank has been passed
- bool vb = false;
+ int vp;
firstvblankbasewait2 = false;
- vblank_getstate (&vb);
- bool ok = vblank_getstate (&vb);
- if (vb == false)
- vblankthread_mode = VBLANKTH_ACTIVE;
- else
+ getvblankpos (&vp);
+ if (vp <= 0) {
+ if (!vblank_first_time) {
+ // set prevtime now if we are still at vsync to improve timing
+ vblank_prev_time = read_processor_time ();
+ vblank_first_time = true;
+ }
+ sleep_millis (1);
+ continue;
+ }
+ if (vp > maxscanline / 2) {
sleep_millis (1);
+ continue;
+ }
+ prevvblankpos = 0;
+ if (vblank_skipeveryother) // wait for first vblank in skip frame mode (100Hz+)
+ vblankthread_mode = VBLANKTH_ACTIVE_SKIPFRAME;
+ else
+ vblankthread_mode = VBLANKTH_ACTIVE;
+ } else if (vblankthread_mode == VBLANKTH_ACTIVE_SKIPFRAME) {
+ int vp;
+ sleep_millis (1);
+ getvblankpos (&vp);
+ if (vp >= maxscanline / 2)
+ vblankthread_mode = VBLANKTH_ACTIVE_SKIPFRAME2;
+ } else if (vblankthread_mode == VBLANKTH_ACTIVE_SKIPFRAME2) {
+ int vp;
+ sleep_millis (1);
+ getvblankpos (&vp);
+ if (vp < maxscanline / 2)
+ vblankthread_mode = VBLANKTH_ACTIVE;
} else if (vblankthread_mode == VBLANKTH_ACTIVE) {
// busy wait mode
frame_time_t t = read_processor_time ();
bool donotwait = false;
- if (!vblank_found) {
- int vs = isvsync_chipset ();
- // immediate vblank if mismatched frame type
- if (vs < 0 && vblanklaceskip ()) {
- vblank_found = true;
- vblank_found_chipset = true;
- vblankthread_mode = VBLANKTH_ACTIVE_WAIT;
- donotwait = true;
- } else if (t - thread_vblank_time > vblankbasewait2) {
- bool vb = false;
- bool ok;
- if (firstvblankbasewait2 == false) {
- firstvblankbasewait2 = true;
- vblank_getstate (&vb);
- if (!dooddevenskip && ap->gfx_vflip > 0) {
- doflipevent ();
- }
+ bool end = false;
+ int vs = isvsync_chipset ();
+ // immediate vblank if mismatched frame type
+ if (vs < 0 && vblanklaceskip ()) {
+ vblank_found = true;
+ vblank_found_chipset = true;
+ end = true;
+ } else if (t - vblank_prev_time > vblankbasewait2) {
+ int vp = 0;
+ bool vb = false;
+ bool ok;
+ if (firstvblankbasewait2 == false) {
+ firstvblankbasewait2 = true;
+ vblank_getstate (&vb, &vp);
+ if (!dooddevenskip && ap->gfx_vflip > 0) {
+ doflipevent ();
}
- ok = vblank_getstate (&vb);
- if (!ok || vb) {
- vblank_found = true;
- if (vs < 0) {
- vblank_found_chipset = true;
- if (!ap->gfx_vflip) {
- show_screen ();
- }
+ }
+ ok = vblank_getstate (&vb, &vp);
+ if (!ok || vb) {
+ thread_vblank_time = t;
+ if (vs < 0) {
+ vblank_found_chipset = true;
+ if (!ap->gfx_vflip) {
+ show_screen ();
}
- vblank_found_rtg = true;
- //write_log (_T("%d\n"), t - thread_vblank_time);
- thread_vblank_time = t;
- vblankthread_mode = VBLANKTH_ACTIVE_WAIT;
}
- if (t - thread_vblank_time > vblankbasewait3)
- donotwait = true;
+ vblank_found_rtg = true;
+ vblank_found = true;
+ end = true;
}
+ if (t - vblank_prev_time > vblankbasewait3)
+ donotwait = true;
}
- if (t - vblank_prev_time > vblankbasefull * 3) {
+ if (t - vblank_prev_time > vblankbasefull * 2) {
+ thread_vblank_time = t;
vblank_found = true;
vblank_found_rtg = true;
vblank_found_chipset = true;
- vblankthread_mode = VBLANKTH_IDLE;
+ end = true;
}
- if (!donotwait || ap->gfx_vflip || picasso_on)
+ if (end) {
+ vblankthread_mode = VBLANKTH_ACTIVE_WAIT;
+ } else if (!donotwait || ap->gfx_vflip || picasso_on) {
sleep_millis (ap->gfx_vflip && currprefs.m68k_speed >= 0 ? 2 : 1);
+ }
} else {
break;
}
return 0;
}
-bool vsync_busywait_check (void)
-{
- return vblankthread_mode == VBLANKTH_ACTIVE || vblankthread_mode == VBLANKTH_ACTIVE_WAIT;
-}
#if 0
static void vsync_notvblank (void)
{
#endif
frame_time_t vsync_busywait_end (void)
{
+ while (vblankthread_mode == VBLANKTH_ACTIVE_START || vblankthread_mode == VBLANKTH_ACTIVE_SKIPFRAME || vblankthread_mode == VBLANKTH_ACTIVE_SKIPFRAME2) {
+ sleep_millis_main (1);
+ }
if (!dooddevenskip) {
while (!vblank_found && vblankthread_mode == VBLANKTH_ACTIVE) {
vsync_sleep (currprefs.m68k_speed < 0 && currprefs.m68k_speed_throttle == 0);
void vsync_busywait_start (void)
{
- int vp = 0;
- struct apmode *ap = picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
#if 0
struct apmode *ap = picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
if (!dooddevenskip) {
}
}
#endif
- changevblankthreadmode_fast (VBLANKTH_ACTIVE_START);
vblank_prev_time = thread_vblank_time;
+ vblank_first_time = false;
+ changevblankthreadmode_fast (VBLANKTH_ACTIVE_START);
}
static bool isthreadedvsync (void)
t = read_processor_time ();
ti = t - prevtime;
if (ti > 2 * vblankbasefull || ti < -2 * vblankbasefull) {
+ changevblankthreadmode_fast (VBLANKTH_ACTIVE_WAIT);
waitvblankstate (false, NULL);
- t = read_processor_time ();
vblank_prev_time = t;
thread_vblank_time = t;
frame_missed++;
if (waitonly)
tsum = approx_vblank;
+ vblank_skipeveryother = false;
getvsyncrate (tsum, &mult);
- if (mult < 0)
+ if (mult < 0) {
div = 2.0;
- else if (mult > 0)
+ vblank_skipeveryother = true;
+ } else if (mult > 0) {
div = 0.5;
- else
+ } else {
div = 1.0;
+ }
tsum2 = tsum / div;
vblankbasefull = (syncbase / tsum2);
vblankbasewait1 = (syncbase / tsum2) * 75 / 100;
vblankbasewait2 = (syncbase / tsum2) * 55 / 100;
- vblankbasewait3 = (syncbase / tsum2) * 90 / 100;
+ vblankbasewait3 = (syncbase / tsum2) * 99 / 100 - syncbase / 500; // at least 2ms before vblank
vblankbaselace = lace;
- write_log (_T("VSync %s: %.6fHz/%.1f=%.6fHz. MinV=%d MaxV=%d%s Units=%d\n"),
- waitonly ? _T("remembered") : _T("calibrated"), tsum, div, tsum2, minscanline, maxvpos, lace ? _T("i") : _T(""), vblankbasefull);
+ write_log (_T("VSync %s: %.6fHz/%.1f=%.6fHz. MinV=%d MaxV=%d%s Units=%d %.1f%%\n"),
+ waitonly ? _T("remembered") : _T("calibrated"), tsum, div, tsum2,
+ minscanline, maxvpos, lace ? _T("i") : _T(""), vblankbasefull,
+ vblankbasewait3 * 100 / (syncbase / tsum2));
remembered_vblank = tsum;
vblank_prev_time = read_processor_time ();
if (oposn != posn && posn != CB_ERR) {
oposn = posn;
if (posn >= 0) {
+ BOOL ena ;
int dang = 1;
hdf_getnameharddrive (posn, 1, NULL, &dang);
- ew (hDlg, IDC_HARDDRIVE_IMAGE, TRUE);
- ew (hDlg, IDOK, TRUE);
+ ena = dang >= 0;
+ ew (hDlg, IDC_HARDDRIVE_IMAGE, ena);
+ ew (hDlg, IDOK, ena);
ew (hDlg, IDC_HDF_RW, !dang);
if (dang)
current_hfdlg.rw = FALSE;
- ew (hDlg, IDC_HDF_CONTROLLER, TRUE);
+ ew (hDlg, IDC_HDF_CONTROLLER, ena);
hardfile_testrdb (hDlg, ¤t_hfdlg);
SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_SETCURSEL, current_hfdlg.controller, 0);
CheckDlgButton(hDlg, IDC_HDF_RW, current_hfdlg.rw);
- restore only single input target to default.
- hdd from command line
+Beta 10:
+
+- Partial rewrite of fastest possible CPU low latency vsync detection code. Should fix jitter caused by frame not always
+ getting shown on screen at correct time.
+- Low latency vsync and double frame mode (85Hz+): guarantee every other vblank is really skipped, previously it didn't
+ work correctly in some situations.
+- Calculate final vblank busywait time from selected rate instead of using hardcoded 50Hz/100Hz-only compatible value.
+ Fixes >50Hz no-buffer jitters.
+- Emulate extra CPU time if it has been more than 7 lines since last extra CPU time, matches older behavior without
+ losing 2.4.0+ performance increase.
+- Fixed low latency vsync + fastest possible CPU getting in state where FPS dropped greatly temporarily, usually at startup.
+- Show also drives that require admin privileges in harddrives panel, unselectable and marked with "Access denied"
+ label. Only name shown because accessing any other attribute may require admin privileges.
+
Beta 9:
- Fixed D3D texture reallocation ordering. Caused blank screen or other strange side-effects (b7)