return 0;
if (changed_prefs.produce_sound != currprefs.produce_sound
|| changed_prefs.win32_soundcard != currprefs.win32_soundcard
- || changed_prefs.win32_soundexclusive != currprefs.win32_soundexclusive
|| changed_prefs.sound_stereo != currprefs.sound_stereo
|| changed_prefs.sound_maxbsiz != currprefs.sound_maxbsiz
|| changed_prefs.sound_freq != currprefs.sound_freq
currprefs.produce_sound = changed_prefs.produce_sound;
currprefs.win32_soundcard = changed_prefs.win32_soundcard;
- currprefs.win32_soundexclusive = changed_prefs.win32_soundexclusive;
currprefs.sound_stereo = changed_prefs.sound_stereo;
currprefs.sound_auto = changed_prefs.sound_auto;
currprefs.sound_freq = changed_prefs.sound_freq;
cfgfile_dwrite_bool (f, L"clipboard_sharing", p->clipboard_sharing);
cfgfile_write (f, L"gfx_display", L"%d", p->gfx_display);
- cfgfile_write_str (f, L"gfx_display_name", p->gfx_display_name);
+ cfgfile_dwrite_str (f, L"gfx_display_name", p->gfx_display_name);
cfgfile_write (f, L"gfx_framerate", L"%d", p->gfx_framerate);
cfgfile_write (f, L"gfx_width", L"%d", p->gfx_size_win.width); /* compatibility with old versions */
cfgfile_write (f, L"gfx_height", L"%d", p->gfx_size_win.height); /* compatibility with old versions */
cfgfile_dwrite (f, L"gfx_autoresolution_min_horizontal", horizmode[p->gfx_autoresolution_minh + 1]);
cfgfile_write (f, L"gfx_backbuffers", L"%d", p->gfx_backbuffers);
+ cfgfile_write (f, L"gfx_backbuffers_rtg", L"%d", p->gfx_rtg_backbuffers);
cfgfile_write_str (f, L"gfx_vsync", vsyncmodes[p->gfx_avsync]);
cfgfile_write_str (f, L"gfx_vsyncmode", vsyncmodes2[p->gfx_avsyncmode]);
cfgfile_write_str (f, L"gfx_vsync_picasso", vsyncmodes[p->gfx_pvsync]);
|| cfgfile_intval (option, value, L"gfx_refreshrate", &p->gfx_refreshrate, 1)
|| cfgfile_yesno (option, value, L"gfx_autoresolution", &p->gfx_autoresolution)
|| cfgfile_intval (option, value, L"gfx_backbuffers", &p->gfx_backbuffers, 1)
+ || cfgfile_intval (option, value, L"gfx_backbuffers_rtg", &p->gfx_rtg_backbuffers, 1)
|| cfgfile_intval (option, value, L"gfx_center_horizontal_position", &p->gfx_xcenter_pos, 1)
|| cfgfile_intval (option, value, L"gfx_center_vertical_position", &p->gfx_ycenter_pos, 1)
p->color_mode = 2;
p->gfx_blackerthanblack = 0;
p->gfx_backbuffers = 1;
+ p->gfx_rtg_backbuffers = 2;
target_default_options (p, type);
unsigned long int vsync_cycles;
static int extra_cycle;
unsigned long start_cycles;
+bool vsync_check;
static int rpt_did_reset;
struct ev eventtab[ev_max];
fake_vblank_hz = 0;
if (abs (currprefs.chipset_refreshrate) > 0.1) {
vblank_hz = currprefs.chipset_refreshrate;
- if (isvsync ()) {
+ if (isvsync_chipset ()) {
vblank_skip = 1;
if (!fake_vblank_hz && getvsyncrate (vblank_hz) != vblank_hz) {
vblank_hz = getvsyncrate (vblank_hz);
(cr->lace < 0 || (cr->lace > 0 && islace) || (cr->lace == 0 && !islace)) &&
(cr->framelength < 0 || (cr->framelength > 0 && lof_store) || (cr->framelength == 0 && !lof_store) || (cr->framelength >= 0 && islace)) &&
((cr->rtg && picasso_on) || (!cr->rtg && !picasso_on)) &&
- (cr->vsync < 0 || (cr->vsync > 0 && isvsync ()) || (cr->vsync == 0 && !isvsync ()))) {
+ (cr->vsync < 0 || (cr->vsync > 0 && isvsync_chipset ()) || (cr->vsync == 0 && !isvsync_chipset ()))) {
double v = -1;
if (!picasso_on) {
- if (isvsync ()) {
+ if (isvsync_chipset ()) {
if (i == CHIPSET_REFRESH_PAL || i == CHIPSET_REFRESH_NTSC) {
if ((abs (vblank_hz - 50) < 1 || abs (vblank_hz - 60) < 1) && currprefs.gfx_avsync == 2 && currprefs.gfx_afullscreen > 0) {
vsync_switchmode (vblank_hz > 55 ? 60 : 50);
}
}
- if (isvsync () < 0) {
+ if (isvsync_chipset () < 0) {
double v2;
v2 = vblank_calibrate (cr->locked ? vblank_hz : cr->rate, cr->locked);
if (!cr->locked)
{
frame_time_t curr_time;
frame_time_t start;
- int vs = isvsync ();
+ int vs = isvsync_chipset ();
if (vs > 0) {
vsyncmintime = vsynctime;
if (vs == -2) {
curr_time = vsync_busywait_end ();
- vsync_busywait_do (&freetime);
+ vsync_busywait_do (NULL);
curr_time = read_processor_time ();
vsyncmintime = curr_time + vsynctime;
vsync_busywait_start ();
handle_events ();
#ifdef PICASSO96
- picasso_handle_vsync ();
+ if (isvsync_rtg () >= 0)
+ picasso_handle_vsync ();
#endif
audio_vsync ();
blkdev_vsync ();
fpscounter ();
- if (!isvsync ()
+ if (!isvsync_chipset ()
#ifdef AVIOUTPUT
&& ((avioutput_framelimiter && avioutput_enabled) || !avioutput_enabled)
#endif
/* Allow this to be one frame's worth of cycles out */
while (diff32 (curr_time, vsyncmintime + vsynctime) > 0) {
vsyncmintime += vsynctime * N_LINES / maxvpos_nom;
- if (currprefs.turbo_emulation || thread_vblank_found)
+ if (currprefs.turbo_emulation || vblank_found_chipset || vblank_found_rtg)
break;
}
}
diw_change--;
- if (is_lastline && isvsync () == -2 && !vsync_rendered) {
+ if (is_lastline && isvsync_chipset () == -2 && !vsync_rendered) {
/* last line, render the frame as early as possible */
vsync_rendered = true;
vsync_handle_redraw (lof_store, lof_changed);
render_screen ();
+ show_screen_maybe ();
+ vsync_check = true;
+ }
+ if (isvsync_rtg () < 0) {
+ if (vblank_found_rtg || vsync_busywait_check () == false)
+ picasso_handle_vsync ();
}
#if 0
unlockscr (vb);
if (start <= stop)
flush_screen (vb, start, stop);
- else if (isvsync ())
+ else if (isvsync_chipset ())
flush_screen (vb, 0, 0); /* vsync mode */
}
else if (currprefs.cpu_cycle_exact)
init_hardware_for_drawing_frame ();
} else {
- if (isvsync ())
+ if (isvsync_chipset ())
flush_screen (gfxvidinfo.inbuffer, 0, 0); /* vsync mode */
}
gui_flicker_led (-1, 0, 0);
reset_drawing ();
}
-int isvsync (void)
+int isvsync_chipset (void)
{
if (picasso_on || !currprefs.gfx_avsync || (currprefs.gfx_avsync == 0 && !currprefs.gfx_afullscreen))
return 0;
return 1;
return currprefs.m68k_speed < 0 ? -2 : -1;
}
+
+int isvsync_rtg (void)
+{
+ if (!picasso_on || !currprefs.gfx_pvsync || (currprefs.gfx_pvsync == 0 && !currprefs.gfx_pfullscreen))
+ return 0;
+ if (currprefs.gfx_pvsyncmode == 0)
+ return 1;
+ return currprefs.m68k_speed < 0 ? -2 : -1;
+}
+
+int isvsync (void)
+{
+ if (picasso_on)
+ return isvsync_rtg ();
+ else
+ return isvsync_chipset ();
+}
int mask_shift (unsigned long mask)
{
int n = 0;
+ if (!mask)
+ return 0;
while (!(mask & 1)) {
n++;
mask >>= 1;
#endif
}
-extern volatile bool thread_vblank_found;
+extern volatile bool vblank_found_chipset, vblank_found_rtg;
STATIC_INLINE void do_cycles_slow (unsigned long cycles_to_add)
{
- if (thread_vblank_found && pissoff > 0)
+ if (vblank_found_chipset && pissoff > 0)
cycles_do_special ();
if ((pissoff -= cycles_to_add) >= 0)
int v = rpt - vsyncmintime;
if (v > (int)syncbase || v < -((int)syncbase))
vsyncmintime = rpt;
- if (v < 0 && !thread_vblank_found && !currprefs.turbo_emulation) {
+ if (v < 0 && !vblank_found_chipset && !currprefs.turbo_emulation) {
pissoff = pissoff_value * CYCLE_UNIT;
return;
}
int gfx_saturation, gfx_luminance, gfx_contrast, gfx_gamma;
bool gfx_blackerthanblack;
int gfx_backbuffers;
+ int gfx_rtg_backbuffers;
int gfx_api;
int color_mode;
int win32_uaescsimode;
int win32_soundcard;
int win32_samplersoundcard;
- bool win32_soundexclusive;
bool win32_norecyclebin;
int win32_specialkey;
int win32_guikey;
extern frame_time_t vsync_busywait_end (void);
extern bool vsync_busywait_do (int*);
extern void vsync_busywait_start (void);
+bool vsync_busywait_check (void);
extern double vblank_calibrate (double, bool);
extern void doflashscreen (void);
extern int flashscreen;
extern void updatedisplayarea (void);
+extern int isvsync_chipset (void);
+extern int isvsync_rtg (void);
extern int isvsync (void);
extern void flush_line (struct vidbuffer*, int);
extern void flush_clear_screen (struct vidbuffer*);
extern bool render_screen (void);
extern void show_screen (void);
+extern bool show_screen_maybe (void);
extern int lockscr (struct vidbuffer*, bool);
extern void unlockscr (struct vidbuffer*);
fixup_prefs_dim2 (&prefs->gfx_size_win);
if (prefs->gfx_filter == 0 && prefs->gfx_filter_autoscale && !prefs->gfx_api)
prefs->gfx_filter = 1;
+ if (prefs->gfx_avsync)
+ prefs->gfx_avsyncmode = 1;
+ if (prefs->gfx_pvsync)
+ prefs->gfx_pvsyncmode = 1;
}
void fixup_cpu (struct uae_prefs *p)
static HWND d3dhwnd;
static int devicelost;
static int locked, fulllocked;
-static int cursor_offset_x, cursor_offset_y;
+static int cursor_offset_x, cursor_offset_y, cursor_offset2_x, cursor_offset2_y;
static float maskmult_x, maskmult_y;
static RECT mask2rect;
static int required_sl_texture_w, required_sl_texture_h;
static int vsync2, guimode, maxscanline;
static int resetcount;
-static int cursor_x, cursor_y, cursor_v;
+static double cursor_x, cursor_y;
+static bool cursor_v;
#define NUMVERTICES 8
#define D3DFVF_TLVERTEX D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1
int curw = CURSORMAXWIDTH, curh = CURSORMAXHEIGHT;
cursorsurfaced3d = createtext (curw, curh, D3DFMT_A8R8G8B8);
- cursor_v = 0;
+ cursor_v = false;
vbsize = sizeof (struct TLVERTEX) * NUMVERTICES;
if (FAILED (hr = d3ddev->CreateVertexBuffer (vbsize, D3DUSAGE_WRITEONLY,
ddraw_fs_hack_free ();
}
-static int prevvblankpos;
-
bool D3D_getvblankpos (int *vpos)
{
HRESULT hr;
if (rt.ScanLine > maxscanline)
maxscanline = rt.ScanLine;
*vpos = rt.ScanLine;
- prevvblankpos = rt.ScanLine;
if (rt.InVBlank != 0)
*vpos = -1;
return true;
}
-bool D3D_waitvblankstate (bool state, int *maxvpos)
-{
- int vpos;
- for (;;) {
- int omax = maxscanline;
- if (!D3D_getvblankpos (&vpos))
- return false;
- while (omax != maxscanline) {
- omax = maxscanline;
- if (!D3D_getvblankpos (&vpos))
- return false;
- }
- if (maxvpos)
- *maxvpos = maxscanline;
- if (vpos < 0) {
- if (state)
- return true;
- } else {
- if (!state)
- return true;
- }
- }
-}
-
-bool D3D_vblank_busywait (void)
-{
- int vpos;
-
- for (;;) {
- int opos = prevvblankpos;
- if (!D3D_getvblankpos (&vpos))
- return false;
- if (opos > maxscanline / 2 && vpos < maxscanline / 5)
- return true;
- if (vpos <= 0)
- return true;
- }
-}
-
-bool D3D_vblank_getstate (bool *state)
-{
- int vpos, opos;
-
- opos = prevvblankpos;
- if (!D3D_getvblankpos (&vpos))
- return false;
- if (opos > maxscanline / 2 && vpos < maxscanline / 5) {
- *state = true;
- return true;
- }
- if (vpos <= 0) {
- *state = true;
- return true;
- }
- *state = false;
- return true;
-}
-
const TCHAR *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth, int mmult)
{
typedef HRESULT (WINAPI *LPDIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**);
LPDIRECT3DCREATE9EX d3dexp = NULL;
int vsync = isvsync ();
-
+ int bb = picasso_on ? currprefs.gfx_rtg_backbuffers : currprefs.gfx_backbuffers;
D3D_free2 ();
if (!currprefs.gfx_api) {
memset (&dpp, 0, sizeof (dpp));
dpp.Windowed = isfullscreen () <= 0;
dpp.BackBufferFormat = mode.Format;
- dpp.BackBufferCount = currprefs.gfx_backbuffers;
+ dpp.BackBufferCount = bb;
dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
dpp.BackBufferWidth = w_w;
dpp.BackBufferHeight = w_h;
- dpp.PresentationInterval = dpp.BackBufferCount <= 1 || dpp.Windowed ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;
+ dpp.PresentationInterval = dpp.BackBufferCount == 0 || dpp.Windowed ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;
modeex.Width = w_w;
modeex.Height = w_h;
d3dhwnd = ahwnd;
t_depth = depth;
- flags = D3DCREATE_FPU_PRESERVE;
+ flags = D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED;
// Check if hardware vertex processing is available
if(d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
dpp.Windowed ? L"" : L" FS",
vsync, dpp.BackBufferCount,
dpp.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE ? L"I" : L"F",
- currprefs.gfx_backbuffers == 0 ? L"E" : L"",
+ bb == 0 ? L"E" : L"",
t_depth, adapter
);
maxscanline = 0;
d3d_enabled = 1;
- if (vsync < 0) {
- if (currprefs.gfx_backbuffers == 0) {
- hr = d3ddev->CreateQuery(D3DQUERYTYPE_EVENT, &query);
- if (FAILED (hr))
- write_log (L"%s: CreateQuery(D3DQUERYTYPE_EVENT) failed: %s\n", D3DHEAD, D3D_ErrorString (hr));
- }
+ if (vsync < 0 && bb == 0) {
+ hr = d3ddev->CreateQuery(D3DQUERYTYPE_EVENT, &query);
+ if (FAILED (hr))
+ write_log (L"%s: CreateQuery(D3DQUERYTYPE_EVENT) failed: %s\n", D3DHEAD, D3D_ErrorString (hr));
}
if (d3ddevex) {
- hr = d3ddevex->SetMaximumFrameLatency (vsync < 0 ? 1 : 0);
+ hr = d3ddevex->SetMaximumFrameLatency (vsync < 0 && bb == 0 ? 1 : 0);
if (FAILED (hr))
write_log (L"%s: SetMaximumFrameLatency() failed: %s\n", D3DHEAD, D3D_ErrorString (hr));
}
if (cursorsurfaced3d && cursor_v) {
D3DXMATRIXA16 t;
- MatrixScaling (&t, ((float)(window_w) / (tout_w + 2 * cursor_offset_x)), ((float)(window_h) / (tout_h + 2 * cursor_offset_y)), 0);
- v.x = cursor_x + cursor_offset_x;
- v.y = cursor_y + cursor_offset_y;
+ MatrixScaling (&t, ((float)(window_w) / (tout_w + 2 * cursor_offset2_x)), ((float)(window_h) / (tout_h + 2 * cursor_offset2_y)), 0);
+ v.x = cursor_x + cursor_offset2_x;
+ v.y = cursor_y + cursor_offset2_y;
v.z = 0;
sprite->SetTransform (&t);
sprite->Draw (cursorsurfaced3d, NULL, NULL, &v, 0xffffffff);
write_log (L"%s: EndScene() %s\n", D3DHEAD, D3D_ErrorString (hr));
}
-void D3D_setcursor (int x, int y, int visible)
+void D3D_setcursor (int x, int y, int width, int height, bool visible)
{
- cursor_x = x;
- cursor_y = y;
+ cursor_offset2_x = cursor_offset_x * window_w / width;
+ cursor_offset2_y = cursor_offset_y * window_h / height;
+
+ cursor_x = x * window_w / width;
+ cursor_y = y * window_h / height;
cursor_v = visible;
}
extern void D3D_clear (void);
extern int D3D_canshaders (void);
extern int D3D_goodenough (void);
-extern void D3D_setcursor (int x, int y, int visible);
-extern bool D3D_vblank_busywait (void);
-extern bool D3D_waitvblankstate (bool, int*);
-extern bool D3D_vblank_getstate (bool *state);
+extern void D3D_setcursor (int x, int y, int width, int height, bool visible);
extern bool D3D_getvblankpos (int *vpos);
extern double D3D_getrefreshrate (void);
extern LPDIRECT3DTEXTURE9 cursorsurfaced3d;
HRESULT ddrval;
DDSURFACEDESC2 desc = { 0 };
LPDIRECTDRAWSURFACE7 surf;
+ int bb = WIN32GFX_IsPicassoScreen () ? currprefs.gfx_rtg_backbuffers : currprefs.gfx_backbuffers;
width = (width + 7) & ~7;
desc.dwSize = sizeof (desc);
DWORD oldflags = desc.dwFlags;
desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP;
- desc.dwBackBufferCount = currprefs.gfx_backbuffers == 0 ? 1 : currprefs.gfx_backbuffers;
+ desc.dwBackBufferCount = bb == 0 ? 1 : bb;
if (desc.dwBackBufferCount > 0) {
ddrval = IDirectDraw7_CreateSurface (dxdata.maindd, &desc, &dxdata.primary, NULL);
if (SUCCEEDED (ddrval)) {
{
int result = 0;
HRESULT ddrval = DD_OK;
- DWORD flags = DDFLIP_WAIT;
+ DWORD flags = DDFLIP_DONOTWAIT;
int vsync = isvsync ();
+ int bb = WIN32GFX_IsPicassoScreen () ? currprefs.gfx_rtg_backbuffers : currprefs.gfx_backbuffers;
- if (currprefs.turbo_emulation || (vsync && currprefs.gfx_backbuffers <= 1))
+ if (currprefs.turbo_emulation || (vsync && bb == 0))
flags |= DDFLIP_NOVSYNC;
if (dxdata.backbuffers == 2) {
DirectDraw_Blit (dxdata.flipping[1], dxdata.flipping[0]);
ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags| DDFLIP_NOVSYNC);
}
} else if(dxdata.backbuffers == 1) {
- ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags | DDFLIP_NOVSYNC);
+ if (!vsync)
+ flags |= DDFLIP_NOVSYNC;
+ ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags);
DirectDraw_Blit (dxdata.flipping[0], dxdata.primary);
}
if (ddrval == DDERR_SURFACELOST) {
dxdata.islost = 1;
}
-bool DirectDraw_waitvblankstate (bool state, int *maxvpos)
+bool DD_getvblankpos (int *vpos)
{
- BOOL vb;
HRESULT hr;
+ DWORD sl;
+ BOOL vbs;
- if (maxvpos)
- *maxvpos = -1;
+ *vpos = -2;
if ((dxdata.primary == NULL && dxdata.fsmodeset > 0) || dxdata.islost || !dxdata.maindd)
return false;
- for (;;) {
- hr = IDirectDraw7_GetVerticalBlankStatus (dxdata.maindd, &vb);
- if (FAILED (hr)) {
- write_log (L"IDirectDraw7_GetVerticalBlankStatus %s\n", DXError (hr));
- return false;
- }
- if ((vb && state) || (!vb && !state))
- return true;
- }
-}
-
-bool DirectDraw_vblank_busywait (void)
-{
- if (!DirectDraw_waitvblankstate (true, NULL))
- return false;
- return true;
-}
-
-bool DirectDraw_getvblankstate (bool *state)
-{
- BOOL vb;
- HRESULT hr;
-
- if ((dxdata.primary == NULL && dxdata.fsmodeset > 0) || dxdata.islost || !dxdata.maindd)
- return false;
- hr = IDirectDraw7_GetVerticalBlankStatus (dxdata.maindd, &vb);
+ hr = IDirectDraw7_GetVerticalBlankStatus (dxdata.maindd, &vbs);
if (FAILED (hr)) {
- write_log (L"IDirectDraw7_GetVerticalBlankStatus %s\n", DXError (hr));
+ write_log (L"IDirectDraw7_GetVerticalBlankStatus() failed, %s\n", DXError (hr));
return false;
}
- *state = vb != 0;
+ sl = -2;
+ if (!vbs) {
+ hr = IDirectDraw7_GetScanLine (dxdata.maindd, &sl);
+ if (hr == 0x88760219) { // "vertical blank is in progress"
+ vbs = TRUE;
+ } else if (FAILED (hr) ) {
+ write_log (L"IDirectDraw7_GetScanLine() failed, %s\n", DXError (hr));
+ return false;
+ }
+ }
+ *vpos = sl;
+ if (vbs)
+ *vpos = -1;
return true;
}
extern GUID *displayGUID;
struct MultiDisplay {
- int primary, disabled, gdi;
+ bool primary;
GUID guid;
- TCHAR *name, *name2, *name3;
+ TCHAR *adaptername, *adapterid, *adapterkey;
+ TCHAR *monitorname, *monitorid;
+ TCHAR *fullname;
struct PicassoResolution *DisplayModes;
RECT rect;
};
void DirectDraw_FillSurface (LPDIRECTDRAWSURFACE7 dst, RECT *rect, uae_u32 color);
void DirectDraw_Fill (RECT *rect, uae_u32 color);
void DirectDraw_FillPrimary (void);
-bool DirectDraw_vblank_busywait (void);
-bool DirectDraw_waitvblankstate (bool, int*);
-bool DirectDraw_getvblankstate (bool*);
+bool DD_getvblankpos (int *vpos);
void dx_check (void);
int dx_islost (void);
static int wincursor_shown;
static uaecptr boardinfo, ABI_interrupt;
static int interrupt_enabled;
-int p96vblank;
+double p96vblank;
static int uaegfx_old, uaegfx_active;
static uae_u32 reserved_gfxmem;
D3DLOCKED_RECT locked;
HRESULT hr;
+ gfx_lock ();
setupcursor_needed = 1;
if (cursorsurfaced3d) {
if (SUCCEEDED (hr = cursorsurfaced3d->LockRect (0, &locked, NULL, 0))) {
cursorsurfaced3d->UnlockRect (0);
setupcursor_needed = 0;
P96TRACE_SPR((L"cursorsurface3d updated\n"));
- return;
} else {
P96TRACE_SPR((L"cursorsurfaced3d LockRect() failed %08x\n", hr));
}
}
+ gfx_unlock ();
}
static void disablemouse (void)
return;
if (!currprefs.gfx_api)
return;
- D3D_setcursor (0, 0, 0);
+ D3D_setcursor (0, 0, 0, 0, false);
}
static int newcursor_x, newcursor_y;
if (!currprefs.gfx_api)
return;
- D3D_setcursor (x, y, cursorvisible);
+ D3D_setcursor (x, y, picasso96_state.Width, picasso96_state.Height, cursorvisible);
}
static int framecnt;
return framecnt > 0;
}
-static void picasso_trigger_vblank (void)
+void picasso_trigger_vblank (void)
{
if (!ABI_interrupt || !uaegfx_base || !interrupt_enabled || currprefs.win32_rtgvblankrate < -1)
return;
INTREQ (0x8000 | 0x0008);
}
-static int isvsync (void)
+static bool rtg_render (void)
{
- if (currprefs.gfx_pfullscreen && currprefs.gfx_pvsync)
- return 1;
- if (currprefs.gfx_pvsync && currprefs.gfx_pvsyncmode)
- return -1;
- return 0;
+ int flushed = 0;
+ if (doskip () && p96skipmode == 0) {
+ ;
+ } else {
+ flushed = flushpixels ();
+ }
+ return flushed == 0;
+}
+static void rtg_show (void)
+{
+ gfx_unlock_picasso ();
}
-void picasso_handle_vsync (void)
+static void picasso_handle_vsync2 (void)
{
static int vsynccnt;
int thisisvsync = 1;
+ int vsync = isvsync_rtg ();
#ifdef RETROPLATFORM
rp_vsync ();
if (!picasso_on)
createwindowscursor (0, 0, 0, 0, 0, 1);
- if (currprefs.chipset_refreshrate >= 100.0) {
+ if (vsync >= 0 && currprefs.chipset_refreshrate >= 85) {
vsynccnt++;
if (vsynccnt < 2)
thisisvsync = 0;
vsynccnt = 0;
}
- if (thisisvsync && currprefs.win32_rtgvblankrate == 0 && !isvsync ())
+ if (thisisvsync && currprefs.win32_rtgvblankrate == 0 && !vsync)
picasso_trigger_vblank ();
if (!picasso_on)
return;
- if (dx_islost ())
- return;
framecnt++;
mouseupdate ();
if (thisisvsync) {
- int flushed = 0;
- if (doskip () && p96skipmode == 0) {
- ;
- } else {
- flushed = flushpixels ();
- }
- if (!flushed)
- gfx_unlock_picasso ();
+ if (rtg_render ())
+ rtg_show ();
}
if (setupcursor_needed)
setupcursor ();
}
+void picasso_handle_vsync (void)
+{
+ int vsync = isvsync_rtg ();
+
+ if (vsync == -2) {
+ vsync_busywait_end ();
+ vsync_busywait_do (NULL);
+ framecnt++;
+ bool rendered = rtg_render ();
+ picasso_trigger_vblank ();
+ clipboard_vsync ();
+ vsync_busywait_start ();
+ mouseupdate ();
+ if (rendered)
+ rtg_show ();
+ } else {
+ picasso_handle_vsync2 ();
+ }
+}
+
static int set_panning_called = 0;
if (GetCursor () != NULL)
SetCursor (NULL);
} else {
- if (wincursor == oldwincursor)
+ if (wincursor == oldwincursor && normalcursor != NULL)
SetCursor (normalcursor);
}
if (oldwincursor)
void picasso_handle_hsync (void)
{
static int p96hsync;
+ int vsync = isvsync_rtg ();
if (currprefs.gfxmem_size == 0)
return;
- if (currprefs.win32_rtgvblankrate == 0 && !isvsync ())
+ if (currprefs.win32_rtgvblankrate == 0 && !vsync)
return;
- if (WIN32GFX_IsPicassoScreen () && isvsync ()) {
- int vbs = DirectDraw_GetVerticalBlankStatus ();
- if (vbs <= 0) {
- if (p96hsync > 0)
- p96hsync = -1;
- return;
- } else {
- if (p96hsync >= 0)
- return;
- p96hsync = 0;
- }
- } else {
- p96hsync--;
- }
+ if (vsync == -2)
+ return;
+ p96hsync--;
if (p96hsync <= 0) {
picasso_trigger_vblank ();
p96hsync = p96syncrate;
void init_hz_p96 (void)
{
- if (currprefs.win32_rtgvblankrate < 0 || isvsync ()) {
+ if (currprefs.win32_rtgvblankrate < 0 || isvsync_rtg ()) {
double rate = getcurrentvblankrate ();
if (rate < 0)
- p96vblank = (int)(vblank_hz + 0.5);
+ p96vblank = vblank_hz;
else
- p96vblank = (int)(getcurrentvblankrate () + 0.5);
+ p96vblank = getcurrentvblankrate ();
} else if (currprefs.win32_rtgvblankrate == 0) {
- p96vblank = (int)(vblank_hz + 0.5);
+ p96vblank = vblank_hz;
} else {
p96vblank = currprefs.win32_rtgvblankrate;
}
if (p96vblank >= 300)
p96vblank = 300;
p96syncrate = maxvpos_nom * vblank_hz / p96vblank;
- write_log (L"P96FREQ: %d*%.4f = %.4f / %d = %d\n", maxvpos_nom, vblank_hz, maxvpos_nom * vblank_hz, p96vblank, p96syncrate);
+ write_log (L"P96FREQ: %d*%.4f = %.4f / %.1f = %d\n", maxvpos_nom, vblank_hz, maxvpos_nom * vblank_hz, p96vblank, p96syncrate);
}
/* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
if (!currprefs.gfx_api && (currprefs.leds_on_screen & STATUSLINE_RTG)) {
if (dst == NULL) {
dst = gfx_lock_picasso (false);
- lock = 1;
+ if (dst)
+ lock = 1;
}
if (dst) {
statusline (dst);
extern void picasso_handle_vsync (void);
extern void init_hz_p96 (void);
extern void picasso_handle_hsync (void);
+extern void picasso_handle_vsync (void);
+extern void picasso_trigger_vblank (void);
extern void picasso_reset (void);
extern int picasso_setwincursor (void);
extern int picasso_palette (void);
#define IDC_SOUND_AUTO 1709
#define IDC_FILTERKEEPASPECT 1709
#define IDC_CS_RTC 1710
-#define IDC_SOUND_EXCLUSIVE 1710
#define IDC_CS_CIAA_TOD1 1711
#define IDC_CS_CIAA_TOD2 1712
#define IDC_CS_EXT 1712
FONT 8, "MS Sans Serif", 0, 0, 0x1\r
BEGIN\r
GROUPBOX "Screen",IDC_SCREENRESTEXT,4,0,292,67,BS_LEFT\r
- COMBOBOX IDC_DISPLAYSELECT,59,10,225,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
+ COMBOBOX IDC_DISPLAYSELECT,10,10,279,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
COMBOBOX IDC_RESOLUTION,59,27,68,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
- COMBOBOX IDC_REFRESHRATE,187,27,97,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
+ COMBOBOX IDC_REFRESHRATE,187,27,102,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
EDITTEXT IDC_XSIZE,59,48,48,12,ES_NUMBER\r
EDITTEXT IDC_YSIZE,114,48,47,12,ES_NUMBER\r
GROUPBOX "Settings",IDC_SETTINGSTEXT,4,73,209,137\r
COMBOBOX IDC_LORES,103,152,102,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
CONTROL "Remove interlace artifacts",IDC_FLICKERFIXER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,139,99,10\r
RTEXT "Windowed:",IDC_STATIC,13,46,40,15,SS_CENTERIMAGE\r
- RTEXT "Fullscreen:",IDC_STATIC,13,19,40,15,SS_CENTERIMAGE\r
- COMBOBOX IDC_DISPLAY_BUFFERCNT,187,47,97,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
+ RTEXT "Fullscreen:",IDC_STATIC,11,27,40,15,SS_CENTERIMAGE\r
+ COMBOBOX IDC_DISPLAY_BUFFERCNT,187,47,102,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
CONTROL "Resolution autoswitch",IDC_AUTORESOLUTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,139,89,10\r
EDITTEXT IDC_DA_TEXT,167,218,46,12,ES_AUTOHSCROLL | ES_READONLY\r
COMBOBOX IDC_SCREENMODE_NATIVE2,112,85,95,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP\r
CONTROL "Disabled",IDC_SOUND0,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,35,101,10\r
CONTROL "Disabled, but emulated",IDC_SOUND1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,53,102,10\r
CONTROL "Enabled",IDC_SOUND2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,71,102,10\r
- GROUPBOX "Volume",IDC_STATIC,132,36,164,31\r
- CONTROL "",IDC_SOUNDVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,44,105,20\r
- EDITTEXT IDC_SOUNDVOLUME2,247,47,40,12,ES_CENTER | ES_READONLY\r
- GROUPBOX "Sound Buffer Size",IDC_STATIC,132,73,164,31\r
- CONTROL "Slider1",IDC_SOUNDBUFFERRAM,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,81,105,19\r
- EDITTEXT IDC_SOUNDBUFFERMEM,247,84,40,12,ES_CENTER | ES_READONLY\r
+ GROUPBOX "Volume",IDC_STATIC,132,20,164,31\r
+ CONTROL "",IDC_SOUNDVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,29,105,20\r
+ EDITTEXT IDC_SOUNDVOLUME2,247,32,40,12,ES_CENTER | ES_READONLY\r
+ GROUPBOX "Sound Buffer Size",IDC_STATIC,132,59,164,31\r
+ CONTROL "Slider1",IDC_SOUNDBUFFERRAM,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,67,105,19\r
+ EDITTEXT IDC_SOUNDBUFFERMEM,247,70,40,12,ES_CENTER | ES_READONLY\r
GROUPBOX "Settings",IDC_SOUNDINTERPOLATION2,6,106,290,60\r
LTEXT "Frequency:",IDC_SOUNDFREQTXT,11,140,53,8,SS_CENTERIMAGE\r
COMBOBOX IDC_SOUNDFREQ,13,149,51,75,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP\r
COMBOBOX IDC_SOUNDSWAP,73,149,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
LTEXT "Swap channels:",IDC_SOUNDSWAPTXT,74,140,61,8,SS_CENTERIMAGE\r
CONTROL "Automatic switching",IDC_SOUND_AUTO,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,14,89,103,10\r
- CONTROL "Exclusive mode",IDC_SOUND_EXCLUSIVE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,137,25,154,10\r
CONTROL "DirectSound",IDC_SOUND_DS,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,181,55,10\r
CONTROL "WASAPI",IDC_SOUND_WASAPI,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,193,53,10\r
CONTROL "OpenAL",IDC_SOUND_OPENAL,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,205,53,10\r
minimized = 0;
if (display) {
p->gfx_display = display;
+ p->gfx_display_name[0] = 0;
if (sm->dwScreenMode & RP_SCREENMODE_FULLWINDOW)
fs = 2;
else
hr = IDirectSoundBuffer_SetVolume (s->lpDSBsecondary, vol);
if (FAILED (hr))
write_log (L"DSSOUND: SetVolume(%d) failed: %s\n", vol, DXError (hr));
- } else if (sd->devicetype == SOUND_DEVICE_WASAPI) {
+ } else if (sd->devicetype == SOUND_DEVICE_WASAPI || sd->devicetype == SOUND_DEVICE_WASAPI_EXCLUSIVE) {
if (s->pAudioVolume) {
float vol = 0.0;
if (volume < 100 && !mute)
v /= 2;
if (sd->sndbufsize > v)
sd->sndbufsize = v;
- s->wasapigoodsize =s->bufferFrameCount / 2;
+ s->wasapigoodsize = s->bufferFrameCount / 2;
s->sndbufframes = sd->sndbufsize / sd->samplesize;
write_log(L"WASAPI: '%s'\nWASAPI: EX=%d CH=%d FREQ=%d BUF=%d (%d)\n",
return 0;
}
-int open_sound_device (struct sound_data *sd, int index, int exclusive, int bufsize, int freq, int channels)
+int open_sound_device (struct sound_data *sd, int index, int bufsize, int freq, int channels)
{
int ret = 0;
struct sound_dp *sdp = xcalloc (struct sound_dp, 1);
+ int type = sound_devices[index]->type;
+
sd->data = sdp;
sd->sndbufsize = bufsize;
sd->freq = freq;
sd->channels = channels;
sd->paused = 1;
- if (sound_devices[index]->type == SOUND_DEVICE_AL)
+ if (type == SOUND_DEVICE_AL)
ret = open_audio_al (sd, index);
- else if (sound_devices[index]->type == SOUND_DEVICE_DS)
+ else if (type == SOUND_DEVICE_DS)
ret = open_audio_ds (sd, index);
- else if (sound_devices[index]->type == SOUND_DEVICE_PA)
+ else if (type == SOUND_DEVICE_PA)
ret = open_audio_pa (sd, index);
- else if (sound_devices[index]->type == SOUND_DEVICE_WASAPI)
- ret = open_audio_wasapi (sd, index, exclusive);
+ else if (type == SOUND_DEVICE_WASAPI || type == SOUND_DEVICE_WASAPI_EXCLUSIVE)
+ ret = open_audio_wasapi (sd, index, type == SOUND_DEVICE_WASAPI_EXCLUSIVE);
sd->samplesize = sd->channels * 2;
return ret;
}
close_audio_ds (sd);
else if (sd->devicetype == SOUND_DEVICE_PA)
close_audio_pa (sd);
- else if (sd->devicetype == SOUND_DEVICE_WASAPI)
+ else if (sd->devicetype == SOUND_DEVICE_WASAPI || sd->devicetype == SOUND_DEVICE_WASAPI_EXCLUSIVE)
close_audio_wasapi (sd);
xfree (sd->data);
sd->data = NULL;
pause_audio_ds (sd);
else if (sd->devicetype == SOUND_DEVICE_PA)
pause_audio_pa (sd);
- else if (sd->devicetype == SOUND_DEVICE_WASAPI)
+ else if (sd->devicetype == SOUND_DEVICE_WASAPI || sd->devicetype == SOUND_DEVICE_WASAPI_EXCLUSIVE)
pause_audio_wasapi (sd);
}
void resume_sound_device (struct sound_data *sd)
resume_audio_ds (sd);
else if (sd->devicetype == SOUND_DEVICE_PA)
resume_audio_pa (sd);
- else if (sd->devicetype == SOUND_DEVICE_WASAPI)
+ else if (sd->devicetype == SOUND_DEVICE_WASAPI || sd->devicetype == SOUND_DEVICE_WASAPI_EXCLUSIVE)
resume_audio_wasapi (sd);
sd->paused = 0;
}
if (currprefs.win32_soundcard >= num)
currprefs.win32_soundcard = changed_prefs.win32_soundcard = 0;
ch = get_audio_nativechannels (currprefs.sound_stereo);
- ret = open_sound_device (sdp, currprefs.win32_soundcard, currprefs.win32_soundexclusive, size, currprefs.sound_freq, ch);
+ ret = open_sound_device (sdp, currprefs.win32_soundcard, size, currprefs.sound_freq, ch);
if (!ret)
return 0;
currprefs.sound_freq = changed_prefs.sound_freq = sdp->freq;
return 0;
return 1;
- } else if (sd->devicetype == SOUND_DEVICE_WASAPI) {
+ } else if (sd->devicetype == SOUND_DEVICE_WASAPI || sd->devicetype == SOUND_DEVICE_WASAPI_EXCLUSIVE) {
// if (WaitForSingleObject (s->wasapihandle, 0) == WAIT_TIMEOUT)
// return 0;
finish_sound_buffer_ds (sd, sndbuffer);
else if (sd->devicetype == SOUND_DEVICE_PA)
finish_sound_buffer_pa (sd, sndbuffer);
- else if (sd->devicetype == SOUND_DEVICE_WASAPI)
+ else if (sd->devicetype == SOUND_DEVICE_WASAPI || sd->devicetype == SOUND_DEVICE_WASAPI_EXCLUSIVE)
finish_sound_buffer_wasapi (sd, sndbuffer);
}
HRESULT hr;
IMMDeviceEnumerator *enumerator;
IMMDeviceCollection *col;
- int i, cnt;
+ int i, cnt, cnt2, start;
write_log (L"Enumerating WASAPI devices...\n");
for (cnt = 0; cnt < MAX_SOUND_DEVICES; cnt++) {
}
if (cnt >= MAX_SOUND_DEVICES)
return;
+ start = cnt;
hr = CoCreateInstance (__uuidof(MMDeviceEnumerator), NULL,
CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&enumerator);
dev->Release ();
}
if (devid && devname) {
- TCHAR tmp[MAX_DPATH];
if (i == 0) {
sdp[cnt] = xcalloc (struct sound_device, 1);
- sdp[cnt]->cfgname = my_strdup (L"WASAPI:Default Audio Device");
+ sdp[cnt]->cfgname = my_strdup (L"Default Audio Device");
sdp[cnt]->type = SOUND_DEVICE_WASAPI;
sdp[cnt]->name = my_strdup (L"Default Audio Device");
sdp[cnt]->alname = NULL;
cnt++;
}
if (cnt < MAX_SOUND_DEVICES) {
- _stprintf (tmp, L"WASAPI:%s", devname);
sdp[cnt] = xcalloc (struct sound_device, 1);
- sdp[cnt]->cfgname = my_strdup (tmp);
+ sdp[cnt]->cfgname = my_strdup (devname);
sdp[cnt]->type = SOUND_DEVICE_WASAPI;
sdp[cnt]->name = my_strdup (devname);
sdp[cnt]->alname = my_strdup (devid);
}
enumerator->Release ();
}
+ cnt2 = cnt;
+ for (i = start; i < cnt2; i++) {
+ TCHAR buf[1000];
+ _stprintf (buf, L"WASAPIX:%s", sdp[i]->cfgname);
+ sdp[cnt] = xcalloc (struct sound_device, 1);
+ sdp[cnt]->cfgname = my_strdup (buf);
+ sdp[cnt]->name = my_strdup (sdp[i]->name);
+ sdp[cnt]->alname = sdp[i]->alname ? my_strdup (sdp[i]->alname) : NULL;
+ _stprintf (buf, L"WASAPI:%s", sdp[i]->cfgname);
+ sdp[cnt]->type = SOUND_DEVICE_WASAPI_EXCLUSIVE;
+ xfree (sdp[i]->cfgname);
+ sdp[i]->cfgname = my_strdup (buf);
+ cnt++;
+ }
+
}
static void OpenALEnumerate (struct sound_device **sds, const char *pDeviceNames, const char *ppDefaultDevice, int skipdetect)
p->win32_ctrl_F11_is_quit = 0;
p->win32_soundcard = 0;
p->win32_samplersoundcard = -1;
- p->win32_soundexclusive = 0;
p->win32_minimize_inactive = 0;
p->win32_active_priority = 1;
p->win32_inactive_priority = 2;
cfgfile_target_dwrite_bool (f, L"borderless", p->win32_borderless);
cfgfile_target_dwrite_str (f, L"uaescsimode", scsimode[p->win32_uaescsimode]);
cfgfile_target_dwrite_str (f, L"statusbar", statusbarmode[p->win32_statusbar]);
- cfgfile_target_dwrite (f, L"soundcard", L"%d", p->win32_soundcard);
+ cfgfile_target_write (f, L"soundcard", L"%d", p->win32_soundcard);
if (p->win32_soundcard >= 0 && p->win32_soundcard < MAX_SOUND_DEVICES && sound_devices[p->win32_soundcard])
- cfgfile_target_dwrite_str (f, L"soundcardname", sound_devices[p->win32_soundcard]->cfgname);
- cfgfile_target_dwrite_bool (f, L"soundcard_exclusive", p->win32_soundexclusive);
+ cfgfile_target_write_str (f, L"soundcardname", sound_devices[p->win32_soundcard]->cfgname);
if (p->win32_samplersoundcard >= 0 && p->win32_samplersoundcard < MAX_SOUND_DEVICES) {
- cfgfile_target_dwrite (f, L"samplersoundcard", L"%d", p->win32_samplersoundcard);
+ cfgfile_target_write (f, L"samplersoundcard", L"%d", p->win32_samplersoundcard);
if (record_devices[p->win32_samplersoundcard])
- cfgfile_target_dwrite_str (f, L"samplersoundcardname", record_devices[p->win32_samplersoundcard]->cfgname);
+ cfgfile_target_write_str (f, L"samplersoundcardname", record_devices[p->win32_samplersoundcard]->cfgname);
}
cfgfile_target_dwrite (f, L"cpu_idle", L"%d", p->cpu_idle);
L"killwinkeys", L"sound_force_primary", L"iconified_highpriority",
L"sound_sync", L"sound_tweak", L"directx6", L"sound_style",
L"file_path", L"iconified_nospeed", L"activepriority", L"magic_mouse",
- L"filesystem_codepage", L"aspi", L"no_overlay",
+ L"filesystem_codepage", L"aspi", L"no_overlay", L"soundcard_exclusive",
0
};
|| cfgfile_intval (option, value, L"midiout_device", &p->win32_midioutdev, 1)
|| cfgfile_intval (option, value, L"midiin_device", &p->win32_midiindev, 1)
|| cfgfile_intval (option, value, L"samplersoundcard", &p->win32_samplersoundcard, 1)
- || cfgfile_yesno (option, value, L"soundcard_exclusive", &p->win32_soundexclusive)
|| cfgfile_yesno (option, value, L"notaskbarbutton", &p->win32_notaskbarbutton)
|| cfgfile_yesno (option, value, L"always_on_top", &p->win32_alwaysontop)
|| cfgfile_yesno (option, value, L"powersavedisabled", &p->win32_powersavedisabled)
const TCHAR *defprogid;
UAEREG *fkey;
+ if (!icon)
+ icon = IDI_APPICON;
+
_tcscpy (progid2, progid);
_tcscat (progid2, ext2 ? ext2 : extension);
if (os_winnt_admin > 1)
}
cc = NULL;
struct contextcommand ccs[2];
+ memset (ccs, 0, sizeof ccs);
if ((command || shellcommand)) {
ccs[0].command = command;
ccs[0].shellcommand = shellcommand;
- ccs[1].command = NULL;
+ ccs[0].icon = IDI_APPICON;
cc = &ccs[0];
}
if (cc) {
TCHAR rpath[MAX_DPATH];
HKEY rkey = HKEY_LOCAL_MACHINE;
HKEY key1;
- int setit = 1;
+ bool setit = true;
_tcscpy (rpath, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\winuae.exe");
if (RegOpenKeyEx (rkey, rpath, 0, KEY_READ, &key1) == ERROR_SUCCESS) {
TCHAR tmp[MAX_DPATH];
DWORD size = sizeof tmp / sizeof (TCHAR);
if (RegQueryValueEx (key1, NULL, NULL, NULL, (LPBYTE)tmp, &size) == ERROR_SUCCESS) {
- if (!_tcscmp (tmp, _wpgmptr))
- setit = 0;
+ if (!_tcsicmp (tmp, _wpgmptr))
+ setit = false;
}
RegCloseKey (key1);
}
DWORD val = 1;
RegSetValueEx (key1, L"", 0, REG_SZ, (CONST BYTE *)_wpgmptr, (_tcslen (_wpgmptr) + 1) * sizeof (TCHAR));
RegSetValueEx (key1, L"UseUrl", 0, REG_DWORD, (LPBYTE)&val, sizeof val);
+ _tcscpy (rpath, start_path_exe);
+ rpath[_tcslen (rpath) - 1] = 0;
+ RegSetValueEx (key1, L"Path", 0, REG_SZ, (CONST BYTE *)rpath, (_tcslen (rpath) + 1) * sizeof (TCHAR));
RegCloseKey (key1);
SHChangeNotify (SHCNE_ASSOCCHANGED, 0, 0, 0);
}
enumerate_sound_devices ();
for (i = 0; i < MAX_SOUND_DEVICES && sound_devices[i]; i++) {
int type = sound_devices[i]->type;
- write_log (L"%d:%s: %s\n", i, type == SOUND_DEVICE_DS ? L"DS" : (type == SOUND_DEVICE_AL ? L"AL" : (type == SOUND_DEVICE_WASAPI ? L"WA" : L"PA")), sound_devices[i]->name);
+ write_log (L"%d:%s: %s\n", i, type == SOUND_DEVICE_DS ? L"DS" : (type == SOUND_DEVICE_AL ? L"AL" : (type == SOUND_DEVICE_WASAPI ? L"WA" : (type == SOUND_DEVICE_WASAPI_EXCLUSIVE ? L"WX" : L"PA"))), sound_devices[i]->name);
}
write_log (L"Enumerating recording devices:\n");
for (i = 0; i < MAX_SOUND_DEVICES && record_devices[i]; i++) {
int type = record_devices[i]->type;
- write_log (L"%d:%s: %s\n", i, type == SOUND_DEVICE_DS ? L"DS" : (type == SOUND_DEVICE_AL ? L"AL" : (type == SOUND_DEVICE_WASAPI ? L"WA" : L"PA")), record_devices[i]->name);
+ write_log (L"%d:%s: %s\n", i, type == SOUND_DEVICE_DS ? L"DS" : (type == SOUND_DEVICE_AL ? L"AL" : (type == SOUND_DEVICE_WASAPI ? L"WA" : (type == SOUND_DEVICE_WASAPI_EXCLUSIVE ? L"WX" : L"PA"))), record_devices[i]->name);
}
write_log (L"done\n");
memset (&devmode, 0, sizeof (devmode));
#define LANG_DLL 1
//#define WINUAEBETA L""
-#define WINUAEBETA L"Beta 5"
-#define WINUAEDATE MAKEBD(2011, 12, 18)
+#define WINUAEBETA L"Beta 6"
+#define WINUAEDATE MAKEBD(2011, 12, 22)
#define WINUAEEXTRA L""
#define WINUAEREV L""
#define SOUND_DEVICE_AL 2
#define SOUND_DEVICE_PA 3
#define SOUND_DEVICE_WASAPI 4
+#define SOUND_DEVICE_WASAPI_EXCLUSIVE 5
struct sound_device
{
static int scalepicasso;
static double remembered_vblank;
static volatile int vblankthread_mode, vblankthread_counter;
-static CRITICAL_SECTION cs_render;
struct winuae_currentmode {
unsigned int flags;
#define VBLANKTH_ACTIVE 4
#define VBLANKTH_ACTIVE_START 5
+static volatile bool vblank_found;
+static volatile int flipthread_mode;
+volatile bool vblank_found_chipset, vblank_found_rtg;
+static HANDLE flipevent;
+static CRITICAL_SECTION screen_cs;
+
+void gfx_lock (void)
+{
+ EnterCriticalSection (&screen_cs);
+}
+void gfx_unlock (void)
+{
+ LeaveCriticalSection (&screen_cs);
+}
+
static void changevblankthreadmode (int newmode)
{
int t = vblankthread_counter;
- thread_vblank_found = false;
+ vblank_found = false;
+ vblank_found_chipset = vblank_found_rtg = false;
if (vblankthread_mode <= 0 || vblankthread_mode == newmode)
return;
vblankthread_mode = newmode;
+ if (newmode == VBLANKTH_KILL) {
+ flipthread_mode = 0;
+ SetEvent(flipevent);
+ while (flipthread_mode == 0)
+ sleep_millis (1);
+ CloseHandle(flipevent);
+ }
while (t == vblankthread_counter && vblankthread_mode > 0)
sleep_millis (1);
- thread_vblank_found = false;
}
int WIN32GFX_IsPicassoScreen (void)
int display = p->gfx_display - 1;
i = 0;
- while (Displays[i].name) {
+ while (Displays[i].monitorname) {
struct MultiDisplay *md = &Displays[i];
- if (p->gfx_display_name[0] && !_tcscmp (md->name, p->gfx_display_name))
+ if (p->gfx_display_name[0] && !_tcscmp (md->adaptername, p->gfx_display_name))
return md;
- if (p->gfx_display_name[0] && !_tcscmp (md->name2, p->gfx_display_name))
+ if (p->gfx_display_name[0] && !_tcscmp (md->adaptername, p->gfx_display_name))
return md;
i++;
}
}
static int set_ddraw_2 (void)
-{HRESULT ddrval;
+{
+ HRESULT ddrval;
int bits = (currentmode->current_depth + 7) & ~7;
int width = currentmode->native_width;
int height = currentmode->native_height;
MONITORINFOEX lpmi;
lpmi.cbSize = sizeof lpmi;
GetMonitorInfo(h, (LPMONITORINFO)&lpmi);
- while (md - Displays < MAX_DISPLAYS) {
- if (!_tcscmp (md->name3, lpmi.szDevice)) {
+ while (md - Displays < MAX_DISPLAYS && md->monitorid[0]) {
+ if (!_tcscmp (md->adapterid, lpmi.szDevice)) {
TCHAR tmp[1000];
md->rect = lpmi.rcMonitor;
if (md->rect.left == 0 && md->rect.top == 0)
- _stprintf (tmp, L"%s (%d*%d)", md->name, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top);
+ _stprintf (tmp, L"%s (%d*%d)", md->monitorname, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top);
else
- _stprintf (tmp, L"%s (%d*%d) [%d*%d]", md->name, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top, md->rect.left, md->rect.top);
- xfree (md->name);
- md->name = my_strdup (tmp);
+ _stprintf (tmp, L"%s (%d*%d) [%d*%d]", md->monitorname, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top, md->rect.left, md->rect.top);
+ xfree (md->fullname);
+ md->fullname = my_strdup (tmp);
return TRUE;
}
md++;
while (EnumDisplayDevices (NULL, adapterindex, &add, 0)) {
int monitorindex = 0;
adapterindex++;
+ if (!(add.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
if (add.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
continue;
+ if (md - Displays >= MAX_DISPLAYS)
+ return;
DISPLAY_DEVICE mdd;
mdd.cb = sizeof mdd;
while (EnumDisplayDevices (add.DeviceName, monitorindex, &mdd, 0)) {
monitorindex++;
if (md - Displays >= MAX_DISPLAYS)
return;
- md->name3 = my_strdup (add.DeviceName);
- md->name2 = my_strdup (mdd.DeviceKey);
- md->name = my_strdup (mdd.DeviceString);
+ if (!(mdd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+ if (mdd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
+ continue;
+ md->adaptername = my_strdup (add.DeviceString);
+ md->adapterid = my_strdup (add.DeviceName);
+ md->adapterkey = my_strdup (add.DeviceID);
+ md->monitorname = my_strdup (mdd.DeviceString);
+ md->monitorid = my_strdup (mdd.DeviceKey);
if (add.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
- md->primary = 1;
+ md->primary = true;
md++;
}
+ if (md - Displays >= MAX_DISPLAYS)
+ return;
+ if (monitorindex == 0) {
+ md->adaptername = my_strdup (add.DeviceString);
+ md->adapterid = my_strdup (add.DeviceName);
+ md->adapterkey = my_strdup (add.DeviceID);
+ md->monitorname = my_strdup (add.DeviceString);
+ md->monitorid = my_strdup (add.DeviceKey);
+ md->primary = true;
+ }
}
EnumDisplayMonitors (NULL, NULL, monitorEnumProc, NULL);
}
-static int makesort (struct MultiDisplay *md)
-{
- int v;
-
- v = md->rect.top * 65536 + md->rect.left;
- if (md->primary)
- v = 0x80000001;
- if (md->rect.top == 0 && md->rect.left == 0)
- v = 0x80000000;
- return v;
-}
-
void sortdisplays (void)
{
- struct MultiDisplay *md1, *md2, tmp;
+ struct MultiDisplay *md1;
int i, idx;
- md1 = Displays;
- while (md1->name) {
- int sort1 = makesort (md1);
- md2 = md1 + 1;
- while (md2->name) {
- int sort2 = makesort (md2);
- if (sort1 > sort2) {
- memcpy (&tmp, md1, sizeof (tmp));
- memcpy (md1, md2, sizeof (tmp));
- memcpy (md2, &tmp, sizeof (tmp));
- }
- md2++;
- }
- md1++;
+ int w = GetSystemMetrics (SM_CXSCREEN);
+ int h = GetSystemMetrics (SM_CYSCREEN);
+ int b = 0;
+ HDC hdc = GetDC (NULL);
+ if (hdc) {
+ b = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
+ ReleaseDC (NULL, hdc);
}
+ write_log (L"Desktop: W=%d H=%d B=%d. CXVS=%d CYVS=%d\n", w, h, b,
+ GetSystemMetrics (SM_CXVIRTUALSCREEN), GetSystemMetrics (SM_CYVIRTUALSCREEN));
md1 = Displays;
- while (md1->name) {
+ while (md1->monitorname) {
md1->DisplayModes = xmalloc (struct PicassoResolution, MAX_PICASSO_MODES);
md1->DisplayModes[0].depth = -1;
- md1->disabled = 1;
- int w = GetSystemMetrics (SM_CXSCREEN);
- int h = GetSystemMetrics (SM_CYSCREEN);
- HDC hdc = GetDC (NULL);
- int b = 0;
-
- if (hdc) {
- b = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
- ReleaseDC (NULL, hdc);
- }
-
- write_log (L"Desktop: W=%d H=%d B=%d. CXVS=%d CYVS=%d\n", w, h, b,
- GetSystemMetrics (SM_CXVIRTUALSCREEN), GetSystemMetrics (SM_CYVIRTUALSCREEN));
+
+ write_log (L"%s [%s]\n", md1->adaptername, md1->monitorname);
for (int mode = 0; mode < 2; mode++) {
DEVMODE dm;
dm.dmSize = sizeof dm;
dm.dmDriverExtra = 0;
idx = 0;
- while (EnumDisplaySettingsEx (md1->name3, idx, &dm, mode ? EDS_RAWMODE : 0)) {
+ while (EnumDisplaySettingsEx (md1->adapterid, idx, &dm, mode ? EDS_RAWMODE : 0)) {
int found = 0;
int idx2 = 0;
while (md1->DisplayModes[idx2].depth >= 0 && !found) {
//dhack();
sortmodes (md1);
modesList (md1);
- if (md1->DisplayModes[0].depth >= 0)
- md1->disabled = 0;
i = 0;
while (md1->DisplayModes[i].depth > 0)
i++;
- write_log (L"'%s', %d display modes (%s)\n", md1->name, i, md1->disabled ? L"disabled" : L"enabled");
+ write_log (L"%d display modes.\n", i);
md1++;
}
}
return render_ok;
flushymin = 0;
flushymax = currentmode->amiga_height;
- EnterCriticalSection (&cs_render);
+ EnterCriticalSection (&screen_cs);
if (currentmode->flags & DM_D3D) {
v = D3D_renderframe ();
#ifdef GFXFILTER
} else if (currentmode->flags & DM_DDRAW) {
v = true;
}
- LeaveCriticalSection (&cs_render);
render_ok = v;
+ LeaveCriticalSection (&screen_cs);
return render_ok;
}
+bool show_screen_maybe (void)
+{
+ int bb = picasso_on ? currprefs.gfx_rtg_backbuffers : currprefs.gfx_backbuffers;
+ if (!bb)
+ return false;
+ SetEvent (flipevent);
+ return true;
+}
+
void show_screen (void)
{
- if (picasso_on || dx_islost ())
- return;
if (!render_ok)
return;
- EnterCriticalSection (&cs_render);
+ EnterCriticalSection (&screen_cs);
if (currentmode->flags & DM_D3D) {
D3D_showframe ();
#ifdef GFXFILTER
} else if (currentmode->flags & DM_SWSCALE) {
- DirectDraw_Flip (1);
+ if (!dx_islost () && !picasso_on)
+ DirectDraw_Flip (1);
#endif
} else if (currentmode->flags & DM_DDRAW) {
- DirectDraw_Flip (1);
+ if (!dx_islost () && !picasso_on)
+ DirectDraw_Flip (1);
}
- LeaveCriticalSection (&cs_render);
+ LeaveCriticalSection (&screen_cs);
+ render_ok = false;
}
static uae_u8 *ddraw_dolock (void)
int srcratio, dstratio;
int srcwidth, srcheight;
- srcwidth = picasso96_state.Width;
- srcheight = picasso96_state.Height;
+ srcwidth = picasso96_state.Width;
+ srcheight = picasso96_state.Height;
+
if (currprefs.win32_rtgscaleaspectratio < 0) {
// automatic
srcratio = picasso96_state.Width * 256 / picasso96_state.Height;
dstratio = (currprefs.win32_rtgscaleaspectratio >> 8) * 256 / (currprefs.win32_rtgscaleaspectratio & 0xff);
srcratio = srcwidth * 256 / srcheight;
}
+
if (srcratio == dstratio) {
SetRect (dr, 0, 0, srcwidth, srcheight);
} else if (srcratio > dstratio) {
SetRect (dr, 0, 0, xx, picasso96_state.Height);
picasso_offset_x = (picasso96_state.Width - xx) / 2;
}
+
OffsetRect (zr, picasso_offset_x, picasso_offset_y);
picasso_offset_mx = picasso96_state.Width * 1000 / (dr->right - dr->left);
picasso_offset_my = picasso96_state.Height * 1000 / (dr->bottom - dr->top);
}
-uae_u8 *gfx_lock_picasso (int fullupdate)
+static bool rtg_locked;
+
+static uae_u8 *gfx_lock_picasso2 (int fullupdate)
{
if (currprefs.gfx_api) {
int pitch;
return DirectDraw_GetSurfacePointer ();
}
}
+uae_u8 *gfx_lock_picasso (int fullupdate)
+{
+ if (rtg_locked) {
+ write_log (L"rtg already locked!\n");
+ abort ();
+ }
+ EnterCriticalSection (&screen_cs);
+ uae_u8 *p = gfx_lock_picasso2 (fullupdate);
+ if (!p)
+ LeaveCriticalSection (&screen_cs);
+ else
+ rtg_locked = true;
+ return p;
+}
void gfx_unlock_picasso (void)
{
+ if (!rtg_locked)
+ EnterCriticalSection (&screen_cs);
+ rtg_locked = false;
if (currprefs.gfx_api) {
if (p96_double_buffer_needs_flushing) {
D3D_flushtexture (p96_double_buffer_first, p96_double_buffer_last);
p96_double_buffer_needs_flushing = 0;
}
D3D_unlocktexture ();
- if (D3D_renderframe ())
- D3D_showframe ();
+ if (D3D_renderframe ()) {
+ render_ok = true;
+ if (currprefs.gfx_rtg_backbuffers == 0 || isvsync_rtg () >= 0)
+ show_screen ();
+ else
+ SetEvent (flipevent);
+ }
} else {
DirectDraw_SurfaceUnlock ();
if (p96_double_buffer_needs_flushing) {
p96_double_buffer_needs_flushing = 0;
}
}
+ LeaveCriticalSection (&screen_cs);
}
static void close_hwnds (void)
c |= _tcscmp (currprefs.gfx_display_name, changed_prefs.gfx_display_name) ? (2|4|8) : 0;
c |= currprefs.gfx_blackerthanblack != changed_prefs.gfx_blackerthanblack ? (2 | 8) : 0;
c |= currprefs.gfx_backbuffers != changed_prefs.gfx_backbuffers ? (2 | 8) : 0;
+ c |= currprefs.gfx_rtg_backbuffers != changed_prefs.gfx_rtg_backbuffers ? (2 | 8) : 0;
c |= currprefs.win32_alwaysontop != changed_prefs.win32_alwaysontop ? 32 : 0;
c |= currprefs.win32_notaskbarbutton != changed_prefs.win32_notaskbarbutton ? 32 : 0;
_tcscpy (currprefs.gfx_display_name, changed_prefs.gfx_display_name);
currprefs.gfx_blackerthanblack = changed_prefs.gfx_blackerthanblack;
currprefs.gfx_backbuffers = changed_prefs.gfx_backbuffers;
+ currprefs.gfx_rtg_backbuffers = changed_prefs.gfx_rtg_backbuffers;
currprefs.win32_alwaysontop = changed_prefs.win32_alwaysontop;
currprefs.win32_notaskbarbutton = changed_prefs.win32_notaskbarbutton;
} else {
open_screen (); // reopen everything
}
+ if (on && isvsync_rtg () < 0)
+ vblank_calibrate (0, false);
end:
#ifdef RETROPLATFORM
rp_set_hwnd (hAmigaWnd);
int graphics_init (void)
{
- InitializeCriticalSection (&cs_render);
gfxmode_reset ();
return open_windows (1);
}
int graphics_setup (void)
{
+ InitializeCriticalSection (&screen_cs);
#ifdef PICASSO96
InitPicasso96 ();
#endif
return 0;
}
+static bool threaded_vsync = false;
+static volatile frame_time_t vblank_prev_time, thread_vblank_time;
+
+#include <process.h>
-static bool waitvblankstate (bool state, int *maxvpos)
-{
- if (currprefs.gfx_api) {
- return D3D_waitvblankstate (state, maxvpos);
- } else {
- return DirectDraw_waitvblankstate (state, maxvpos);
- }
-}
-static bool getvblankstate (bool *state)
-{
- if (currprefs.gfx_api) {
- if (!D3D_vblank_getstate (state))
- return false;
- return true;
- } else {
- if (!DirectDraw_getvblankstate (state))
- return false;
- return true;
- }
-}
double getcurrentvblankrate (void)
{
if (remembered_vblank)
else
return DirectDraw_CurrentRefreshRate ();
}
-static int getvblankpos (void)
+
+static int maxscanline, prevvblankpos;
+
+static bool getvblankpos (int *vp)
{
- int vpos = -2;
+ int sl;
+ *vp = -2;
if (currprefs.gfx_api) {
- if (!D3D_getvblankpos (&vpos))
- return -2;
- return vpos;
+ if (!D3D_getvblankpos (&sl))
+ return false;
} else {
- bool state;
- if (!DirectDraw_getvblankstate (&state))
- return -2;
- return state ? -1 : 0;
+ if (!DD_getvblankpos (&sl))
+ return false;
}
+ prevvblankpos = sl;
+ if (sl > maxscanline)
+ maxscanline = sl;
+ *vp = sl;
+ return true;
}
-static bool threaded_vsync = false;
-volatile bool thread_vblank_found;
-static volatile frame_time_t vblank_prev_time, thread_vblank_time;
+static bool waitvblankstate (bool state, int *maxvpos)
+{
+ int vp;
+ for (;;) {
+ int omax = maxscanline;
+ if (!getvblankpos (&vp))
+ return false;
+ while (omax != maxscanline) {
+ omax = maxscanline;
+ if (!getvblankpos (&vp))
+ return false;
+ }
+ if (maxvpos)
+ *maxvpos = maxscanline;
+ if (vp < 0) {
+ if (state)
+ return true;
+ } else {
+ if (!state)
+ return true;
+ }
+ }
+}
+
+bool vblank_busywait (void)
+{
+ int vp;
+
+ for (;;) {
+ int opos = prevvblankpos;
+ if (!getvblankpos (&vp))
+ return false;
+ if (opos > maxscanline / 2 && vp < maxscanline / 5)
+ return true;
+ if (vp <= 0)
+ return true;
+ }
+}
+
+bool vblank_getstate (bool *state)
+{
+ int vp, opos;
+
+ opos = prevvblankpos;
+ if (!getvblankpos (&vp))
+ return false;
+ if (opos > maxscanline / 2 && vp < maxscanline / 5) {
+ *state = true;
+ return true;
+ }
+ if (vp <= 0) {
+ *state = true;
+ return true;
+ }
+ *state = false;
+ return true;
+}
-#include <process.h>
-static void _cdecl vblankthread (void *dummy)
+static unsigned int __stdcall flipthread (void *dummy)
+{
+ SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
+ while (flipthread_mode) {
+ WaitForSingleObject (flipevent, INFINITE);
+ if (flipthread_mode == 0)
+ break;
+ show_screen ();
+ }
+ flipthread_mode = -1;
+ return 0;
+}
+
+static unsigned int __stdcall vblankthread (void *dummy)
{
while (vblankthread_mode > VBLANKTH_KILL) {
vblankthread_counter++;
} else if (vblankthread_mode == VBLANKTH_ACTIVE_START) {
// do not start until vblank has been passed
bool vb = false;
- getvblankstate (&vb);
- bool ok = getvblankstate (&vb);
+ vblank_getstate (&vb);
+ bool ok = vblank_getstate (&vb);
if (vb == false)
vblankthread_mode = VBLANKTH_ACTIVE;
else
// busy wait mode
frame_time_t t = read_processor_time ();
bool donotwait = false;
- if (!thread_vblank_found) {
+ if (!vblank_found) {
if (t - thread_vblank_time > vblankbasewait2) {
bool vb = false;
- bool ok = getvblankstate (&vb);
+ bool ok = vblank_getstate (&vb);
if (!ok || vb) {
- thread_vblank_found = true;
- show_screen ();
+ vblank_found = true;
+ if (isvsync_chipset () < 0) {
+ vblank_found_chipset = true;
+ if (!currprefs.gfx_backbuffers)
+ show_screen ();
+ } else if (isvsync_rtg () < 0) {
+ vblank_found_rtg = true;
+ }
//write_log (L"%d\n", t - thread_vblank_time);
thread_vblank_time = t;
vblankthread_mode = VBLANKTH_ACTIVE_WAIT;
}
- if (t - thread_vblank_time > vblankbasewait3 && cpu_number > 2)
+ if (t - thread_vblank_time > vblankbasewait3)
donotwait = true;
}
}
if (t - vblank_prev_time > vblankbasefull * 3)
vblankthread_mode = VBLANKTH_IDLE;
- if (!donotwait)
+ if (!donotwait || currprefs.gfx_backbuffers || picasso_on)
sleep_millis (1);
} else {
break;
}
}
vblankthread_mode = -1;
+ return 0;
}
static int frame_missed, frame_counted, frame_errors;
static int frame_usage, frame_usage_avg, frame_usage_total;
extern int log_vsync;
+bool vsync_busywait_check (void)
+{
+ return vblankthread_mode == VBLANKTH_ACTIVE || vblankthread_mode == VBLANKTH_ACTIVE_WAIT;
+}
+
frame_time_t vsync_busywait_end (void)
{
- while (!thread_vblank_found && vblankthread_mode == VBLANKTH_ACTIVE)
+ while (!vblank_found && vblankthread_mode == VBLANKTH_ACTIVE)
sleep_millis (1);
changevblankthreadmode (VBLANKTH_ACTIVE_WAIT);
for (;;) {
- int vpos = getvblankpos ();
- if (vpos != -1) {
+ int vp;
+ getvblankpos (&vp);
+ if (vp != -1) {
+ //write_log (L"%d ", vpos);
break;
}
}
console_out_f(L"F:%8d M:%8d E:%8d %3d%% (%3d%%) %10d\r", frame_counted, frame_missed, frame_errors, frame_usage, frame_usage_avg, (t - vblank_prev_time) - vblankbasefull);
}
- *freetime = 0;
+ if (freetime)
+ *freetime = 0;
if (currprefs.turbo_emulation) {
frame_missed++;
return true;
else if (frame_usage < 0)
frame_usage = 0;
frame_usage_total += frame_usage;
- *freetime = frame_usage;
+ if (freetime)
+ *freetime = frame_usage;
if (frame_counted)
frame_usage_avg = frame_usage_total / frame_counted;
sleep_millis_main (1);
framelost = false;
- if (currprefs.gfx_api) {
- v = D3D_vblank_busywait ();
- } else {
- v = DirectDraw_vblank_busywait ();
- }
+ vblank_busywait ();
}
if (v) {
return false;
}
+static struct remembered_vsync *vsyncmemory;
+
+struct remembered_vsync
+{
+ struct remembered_vsync *next;
+ int width, height, depth, rate, mode;
+ bool rtg;
+ double remembered_rate;
+};
+
double vblank_calibrate (double approx_vblank, bool waitonly)
{
frame_time_t t1, t2;
int maxcnt, maxtotal, total, cnt, tcnt2;
HANDLE th;
int maxvpos, div;
+ int width, height, depth, rate, mode;
+ struct remembered_vsync *rv;
+ double rval = -1;
+
+ if (picasso_on) {
+ width = picasso96_state.Width;
+ height = picasso96_state.Height;
+ depth = picasso96_state.BytesPerPixel;
+ } else {
+ width = currentmode->native_width;
+ height = currentmode->native_height;
+ depth = (currentmode->native_depth + 7) / 8;
+ }
+ rate = currprefs.gfx_refreshrate;
+ mode = isfullscreen ();
+ rv = vsyncmemory;
+ while (rv) {
+ if (rv->width == width && rv->height == height && rv->depth == depth && rv->rate == rate && rv->mode == mode && rv->rtg == picasso_on) {
+ approx_vblank = rv->remembered_rate;
+ rval = approx_vblank;
+ waitonly = true;
+ write_log (L"VSync calibration: remembered rate %.6fHz\n", rval);
+ break;
+ }
+ rv = rv->next;
+ }
- threaded_vsync = (cpu_number > 1 && currprefs.m68k_speed < 0);
+ threaded_vsync = isvsync () == -2;
- if (remembered_vblank > 0 && (!threaded_vsync || (threaded_vsync && vblankthread_mode > 0)))
- return remembered_vblank;
if (waitonly) {
vblankbasefull = syncbase / approx_vblank;
vblankbasewait = (syncbase / approx_vblank) * 3 / 4;
- vblankbasewait2 = (syncbase / approx_vblank) * 7 / 10;
- vblankbasewait3 = (syncbase / approx_vblank) * 9 / 10;
- remembered_vblank = -1;
- return -1;
+ vblankbasewait2 = (syncbase / approx_vblank) * 70 / 100;
+ vblankbasewait3 = (syncbase / approx_vblank) * 90 / 100;
+ return rval;
}
th = GetCurrentThread ();
int oldpri = GetThreadPriority (th);
SetThreadPriority (th, THREAD_PRIORITY_HIGHEST);
if (vblankthread_mode <= VBLANKTH_KILL) {
+ unsigned th;
vblankthread_mode = VBLANKTH_CALIBRATE;
- _beginthread (&vblankthread, 0, 0);
+ _beginthreadex (NULL, 0, vblankthread, 0, 0, &th);
+ flipthread_mode = 1;
+ flipevent = CreateEvent (NULL, FALSE, FALSE, NULL);
+ _beginthreadex (NULL, 0, flipthread, 0, 0, &th);
} else {
changevblankthreadmode (VBLANKTH_CALIBRATE);
}
write_log (L"VSync calibration: %.6fHz/%d=%.6fHz. MaxV=%d Units=%d Mode=%s\n", tsum, div, tsum2, maxvpos, vblankbasefull, threaded_vsync ? L"threaded" : L"normal");
remembered_vblank = tsum2;
vblank_prev_time = read_processor_time ();
+
+ rv = xcalloc (struct remembered_vsync, 1);
+ rv->width = width;
+ rv->height = height;
+ rv->depth = depth;
+ rv->rate = rate;
+ rv->mode = isfullscreen ();
+ rv->rtg = picasso_on;
+ rv->remembered_rate = tsum2;
+ if (vsyncmemory == NULL) {
+ vsyncmemory = rv;
+ } else {
+ rv->next = vsyncmemory;
+ vsyncmemory = rv;
+ }
+
return tsum;
fail:
write_log (L"VSync calibration failed\n");
return 1;
}
-static void allocsoftbuffer(struct vidbuffer *buf, int flags, int width, int height, int depth)
+static void allocsoftbuffer (struct vidbuffer *buf, int flags, int width, int height, int depth)
{
buf->pixbytes = (depth + 7) / 8;
int tmp_depth;
int ret = 0;
- remembered_vblank = 0;
+ remembered_vblank = -1;
if (wasfullwindow_a == 0)
wasfullwindow_a = currprefs.gfx_afullscreen == GFX_FULLWINDOW ? 1 : -1;
if (wasfullwindow_p == 0)
p->gfx_size = p->gfx_size_win;
}
md = getdisplay (p);
- if (md->disabled) {
- p->gfx_display = 0;
- md = getdisplay (p);
- }
config_changed = 1;
}
extern void close_windows (void);
extern void updatewinfsmode (struct uae_prefs *p);
extern int is3dmode (void);
+extern void gfx_lock (void);
+extern void gfx_unlock (void);
void DX_Fill (int dstx, int dsty, int width, int height, uae_u32 color);
void DX_Blit (int x, int y, int w, int h);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_NATIVE, CB_ADDSTRING, 0, (LPARAM)buffer);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_NATIVE2, CB_ADDSTRING, 0, (LPARAM)L"-");
+#if 0
WIN32GUI_LoadUIString(IDS_SCREEN_VSYNC, buffer, sizeof buffer / sizeof (TCHAR));
SendDlgItemMessage(hDlg, IDC_SCREENMODE_NATIVE2, CB_ADDSTRING, 0, (LPARAM)buffer);
WIN32GUI_LoadUIString(IDS_SCREEN_VSYNC_AUTOSWITCH, buffer, sizeof buffer / sizeof (TCHAR));
SendDlgItemMessage(hDlg, IDC_SCREENMODE_NATIVE2, CB_ADDSTRING, 0, (LPARAM)buffer);
+#endif
WIN32GUI_LoadUIString(IDS_SCREEN_VSYNC2, buffer, sizeof buffer / sizeof (TCHAR));
SendDlgItemMessage(hDlg, IDC_SCREENMODE_NATIVE2, CB_ADDSTRING, 0, (LPARAM)buffer);
WIN32GUI_LoadUIString(IDS_SCREEN_VSYNC2_AUTOSWITCH, buffer, sizeof buffer / sizeof (TCHAR));
SendDlgItemMessage(hDlg, IDC_SCREENMODE_NATIVE, CB_SETCURSEL,
workprefs.gfx_afullscreen, 0);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_NATIVE2, CB_SETCURSEL,
- workprefs.gfx_avsync == 0 ? 0 : workprefs.gfx_avsync + workprefs.gfx_avsyncmode * 2, 0);
+ workprefs.gfx_avsync, 0);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG2, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG, CB_ADDSTRING, 0, (LPARAM)buffer);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG2, CB_ADDSTRING, 0, (LPARAM)L"-");
+#if 0
WIN32GUI_LoadUIString(IDS_SCREEN_VSYNC, buffer, sizeof buffer / sizeof (TCHAR));
SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG2, CB_ADDSTRING, 0, (LPARAM)buffer);
WIN32GUI_LoadUIString(IDS_SCREEN_VSYNC_AUTOSWITCH, buffer, sizeof buffer / sizeof (TCHAR));
SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG2, CB_ADDSTRING, 0, (LPARAM)buffer);
+#endif
+ WIN32GUI_LoadUIString(IDS_SCREEN_VSYNC2, buffer, sizeof buffer / sizeof (TCHAR));
+ SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG2, CB_ADDSTRING, 0, (LPARAM)buffer);
+ WIN32GUI_LoadUIString(IDS_SCREEN_VSYNC2_AUTOSWITCH, buffer, sizeof buffer / sizeof (TCHAR));
+ SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG2, CB_ADDSTRING, 0, (LPARAM)buffer);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG, CB_SETCURSEL,
workprefs.gfx_pfullscreen, 0);
SendDlgItemMessage(hDlg, IDC_SCREENMODE_RTG2, CB_SETCURSEL,
- workprefs.gfx_pvsync == 0 ? 0 : workprefs.gfx_pvsync + workprefs.gfx_pvsyncmode, 0);
+ workprefs.gfx_pvsync, 0);
SendDlgItemMessage(hDlg, IDC_LORES, CB_RESETCONTENT, 0, 0);
WIN32GUI_LoadUIString(IDS_RES_LORES, buffer, sizeof buffer / sizeof (TCHAR));
}
}
}
+
static void init_displays_combo (HWND hDlg)
{
- int i = 0;
+ TCHAR *adapter = L"";
+ struct MultiDisplay *md = Displays;
+ int cnt = 0, cnt2 = 0;
+ int displaynum;
+ int idx = 0;
+
+ displaynum = workprefs.gfx_display - 1;
+ if (displaynum < 0)
+ displaynum = 0;
SendDlgItemMessage (hDlg, IDC_DISPLAYSELECT, CB_RESETCONTENT, 0, 0);
- while (Displays[i].name) {
- SendDlgItemMessage (hDlg, IDC_DISPLAYSELECT, CB_ADDSTRING, 0, (LPARAM)Displays[i].name);
- i++;
+ while (md->monitorname) {
+ if (_tcscmp (md->adapterkey, adapter) != 0) {
+ SendDlgItemMessage (hDlg, IDC_DISPLAYSELECT, CB_ADDSTRING, 0, (LPARAM)md->adaptername);
+ adapter = md->adapterkey;
+ cnt++;
+ }
+ TCHAR buf[MAX_DPATH];
+ _stprintf (buf, L" %s", md->fullname);
+ SendDlgItemMessage (hDlg, IDC_DISPLAYSELECT, CB_ADDSTRING, 0, (LPARAM)buf);
+ if (displaynum == cnt2)
+ idx = cnt;
+ md++;
+ cnt2++;
+ cnt++;
+ }
+ SendDlgItemMessage (hDlg, IDC_DISPLAYSELECT, CB_SETCURSEL, idx, 0);
+}
+
+static void get_displays_combo (HWND hDlg)
+{
+ struct MultiDisplay *md = Displays;
+ LRESULT posn;
+ TCHAR *adapter = L"";
+ int cnt = 0, cnt2 = 0;
+ int displaynum;
+
+ posn = SendDlgItemMessage (hDlg, IDC_DISPLAYSELECT, CB_GETCURSEL, 0, 0);
+ if (posn == CB_ERR)
+ return;
+
+ displaynum = workprefs.gfx_display - 1;
+ if (displaynum < 0)
+ displaynum = 0;
+ while (md->monitorname) {
+ int foundnum = -1;
+ if (_tcscmp (md->adapterkey, adapter) != 0) {
+ adapter = md->adapterkey;
+ if (posn == cnt)
+ foundnum = cnt2;
+ cnt++;
+ }
+ if (posn == cnt)
+ foundnum = cnt2;
+ if (foundnum >= 0) {
+ if (foundnum == displaynum)
+ return;
+ workprefs.gfx_display = foundnum + 1;
+ init_displays_combo (hDlg);
+ init_resolution_combo (hDlg);
+ init_display_mode (hDlg);
+ return;
+ }
+ cnt++;
+ cnt2++;
+ md++;
}
- if (workprefs.gfx_display > i)
- workprefs.gfx_display = 0;
- if (workprefs.gfx_display < 1)
- workprefs.gfx_display = 1;
- SendDlgItemMessage (hDlg, IDC_DISPLAYSELECT, CB_SETCURSEL, workprefs.gfx_display - 1, 0);
}
static void values_from_displaydlg (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
if (i > 0) {
i--;
workprefs.gfx_avsync = (i & 1) + 1;
- workprefs.gfx_avsyncmode = i >= 2 ? 1 : 0;
+ workprefs.gfx_avsyncmode = 1;
}
workprefs.gfx_pfullscreen = SendDlgItemMessage (hDlg, IDC_SCREENMODE_RTG, CB_GETCURSEL, 0, 0);
workprefs.gfx_pvsyncmode = 0;
if (i > 0) {
i--;
- workprefs.gfx_pvsync = 1;
- workprefs.gfx_pvsyncmode = i >= 1 ? 1 : 0;
+ workprefs.gfx_pvsync = (i & 1) + 1;
+ workprefs.gfx_pvsyncmode = 1;
}
bool updaterate = false, updateslider = false;
if (msg == WM_COMMAND && HIWORD (wParam) == CBN_SELCHANGE)
{
if (LOWORD (wParam) == IDC_DISPLAYSELECT) {
- posn = SendDlgItemMessage (hDlg, IDC_DISPLAYSELECT, CB_GETCURSEL, 0, 0);
- if (posn != CB_ERR && posn + 1 != workprefs.gfx_display) {
- if (Displays[posn].disabled)
- posn = 0;
- workprefs.gfx_display = posn + 1;
- init_resolution_combo (hDlg);
- init_display_mode (hDlg);
- }
+ get_displays_combo (hDlg);
return;
} else if (LOWORD (wParam) == IDC_LORES) {
posn = SendDlgItemMessage (hDlg, IDC_LORES, CB_GETCURSEL, 0, 0);
static void update_soundgui (HWND hDlg)
{
- int bufsize, canexc;
+ int bufsize;
TCHAR txt[20];
bufsize = exact_log2 (workprefs.sound_maxbsiz / 1024);
SendDlgItemMessage (hDlg, IDC_SOUNDDRIVEVOLUME, TBM_SETPOS, TRUE, 100 - workprefs.dfxclickvolume);
_stprintf (txt, L"%d%%", 100 - workprefs.dfxclickvolume);
SetDlgItemText (hDlg, IDC_SOUNDDRIVEVOLUME2, txt);
-
- canexc = sound_devices[workprefs.win32_soundcard]->type == SOUND_DEVICE_WASAPI;
- ew (hDlg, IDC_SOUND_EXCLUSIVE, canexc);
- if (!canexc)
- workprefs.win32_soundexclusive = 0;
- CheckDlgButton (hDlg, IDC_SOUND_EXCLUSIVE, workprefs.win32_soundexclusive);
-
}
static int soundfreqs[] = { 11025, 15000, 22050, 32000, 44100, 48000, 0 };
}
workprefs.sound_interpol = SendDlgItemMessage (hDlg, IDC_SOUNDINTERPOLATION, CB_GETCURSEL, 0, 0);
- workprefs.win32_soundexclusive = ischecked (hDlg, IDC_SOUND_EXCLUSIVE);
soundcard = SendDlgItemMessage (hDlg, IDC_SOUNDCARDLIST, CB_GETCURSEL, 0, 0L);
if (soundcard != workprefs.win32_soundcard && soundcard != CB_ERR) {
workprefs.win32_soundcard = soundcard;
TCHAR tmp[MAX_DPATH];
int type = sound_devices[card]->type;
_stprintf (tmp, L"%s: %s",
- type == SOUND_DEVICE_DS ? L"DSOUND" : (type == SOUND_DEVICE_AL ? L"OpenAL" : (type == SOUND_DEVICE_PA ? L"PortAudio" : L"WASAPI")),
+ type == SOUND_DEVICE_DS ? L"DSOUND" : (type == SOUND_DEVICE_AL ? L"OpenAL" : (type == SOUND_DEVICE_PA ? L"PortAudio" : (type == SOUND_DEVICE_WASAPI ? L"WASAPI" : L"WASAPI EX"))),
sound_devices[card]->name);
SendDlgItemMessage (hDlg, IDC_SOUNDCARDLIST, CB_ADDSTRING, 0, (LPARAM)tmp);
}
*pc = v;
SetDlgItemInt (hDlg, IDC_FILTERXLV, v, TRUE);
}
- init_colors ();
- notice_new_xcolors ();
- reset_drawing ();
+ if (!full_property_sheet) {
+ init_colors ();
+ notice_new_xcolors ();
+ reset_drawing ();
+ }
updatedisplayarea ();
WIN32GFX_WindowMove ();
recursive--;
on &= 1;
} else if (led == LED_FPS) {
double fps = (double)gui_data.fps / 10.0;
- extern int p96vblank;
+ extern double p96vblank;
pos = 2;
ptr = drive_text + pos * 16;
if (fps > 999.9)
fps = 999.9;
if (picasso_on)
- _stprintf (ptr, L"%d [%.1f]", p96vblank, fps);
+ _stprintf (ptr, L"%.1f [%.1f]", p96vblank, fps);
else
_stprintf (ptr, L"FPS: %.1f", fps);
if (pause_emulation) {
+Beta 6:
+
+New vsync should finally work in all modes.
+
+- Removed sound exclusive checkbox, WASAPI exclusive modes are now listed in select menu.
+- New RTG vsync using low latency sync method, currently always triple buffered.
+- Display selection GUI changed again, now lists both display adapter(s) and connected monitor(s).
+- Associated ".uae" didn't set correct icon id (right click on .uae shows wrong or missing icon). Reset .uae association again to fix it.
+- Fixed filter panel hang in some situations before emulation was started.
+- Low latency vsync keeps list of modes that have already been calibrated, switching back to remembered mode uses stored calibration value.
+- Unreliable old-style vsync options are gone. Replaced by low latency + double or triple buffered mode.
+- DirectDraw low latency vsync fully implemented.
+- RTG hardware cursor positioning fixed in aspect ratio corrected full window modes.
+
Beta 5:
- Removed obsolete fake (50), (60), (100) and (120) refresh rates.
- Fixed Sound panel crash if sound card id stored in configuration file was larger than available number of sound card drivers.
- Handle situation where PortAudio Pa_IsFormatSupported() returns true but Pa_OpenStream() fails with paInvalidSampleRate.
(Usually seems to happen when requesting 44100Hz but hardware supports only 48000Hz)
-- VSync sound syncronization improved (All types: DirectSound, WASAPI, OpenAL and PortAudio)
+- VSync sound syncronization improved (All types: DirectSound, WASAPI, OpenAL and PortAudio). Note that buffer settings are not same between device types.
- SND% blue/yellow/red flickering fix, previously flickering speed changed depending on buffer size.
- More fastest possible/JIT low latency vsync updates.