/* too fast cpu fixes */
uaecptr ptx;
bool ptx_written;
+ bool ptx_tofetch;
};
static int samplecnt;
{
struct audio_channel_data *cdp = audio_channel + nr;
#if DEBUG_AUDIO > 0
- write_log (L"%d: ZEROSTATE\n", nr);
+ if (debugchannel (nr))
+ write_log (L"%d: ZEROSTATE\n", nr);
#endif
cdp->state = 0;
cdp->evtime = MAX_EV;
if (!debugchannel (nr))
sample = 0;
#endif
-#if DEBUG_AUDIO > 1
+#if DEBUG_AUDIO > 2
if (debugchannel (nr))
write_log (L"SAMPLE%d: %02x\n", nr, sample & 0xff);
#endif
cdp->hisample = cdp->losample = true;
cdp->have_dat = false;
#endif
-#if DEBUG_AUDIO > 1
+#if DEBUG_AUDIO > 2
if (debugchannel (nr))
write_log (L"LOAD%dDAT: New:%04x, Old:%04x\n", nr, cdp->dat, cdp->dat2);
#endif
// DMA switched off, state=2/3 and "too fast CPU": kill DMA instantly
// or CPU timed DMA wait routines in common tracker players will lose notes
#if DEBUG_AUDIO > 0
- write_log (L"%d: INSTADMAOFF\n", nr, M68K_GETPC);
+ if (debugchannel (nr))
+ write_log (L"%d: INSTADMAOFF\n", nr, M68K_GETPC);
#endif
newsample (nr, (cdp->dat2 >> 0) & 0xff);
if (napnav)
cdp->drhpos = hpos;
cdp->wlen = cdp->len;
cdp->ptx_written = false;
+ cdp->ptx_tofetch = true;
cdp->dsr = true;
#if TEST_AUDIO > 0
cdp->have_dat = false;
cdp->pt += 2;
if (reset)
cdp->pt = cdp->lc;
+ cdp->ptx_tofetch = false;
return p;
}
// someone wants to update PT but DSR has not yet been processed.
// too fast CPU and some tracker players: enable DMA, CPU delay, update AUDxPT with loop position
- if (usehacks1 () && ((cdp->dsr && cdp->state == 1) || cdp->ptx_written)) {
+ if (usehacks1 () && ((cdp->ptx_tofetch && cdp->state == 1) || cdp->ptx_written)) {
cdp->ptx = cdp->lc;
cdp->ptx_written = true;
} else {
}
#if DEBUG_AUDIO > 0
if (debugchannel (nr))
- write_log (L"AUD%dLCH: %04X %08X\n", nr, v, M68K_GETPC);
+ write_log (L"AUD%dLCH: %04X %08X (%d) (%d %d %08x)\n", nr, v, M68K_GETPC, cdp->state, cdp->dsr, cdp->ptx_written, cdp->ptx);
#endif
}
struct audio_channel_data *cdp = audio_channel + nr;
audio_activate ();
update_audio ();
- if (usehacks1 () && ((cdp->dsr && cdp->state == 1) || cdp->ptx_written)) {
+ if (usehacks1 () && ((cdp->ptx_tofetch && cdp->state == 1) || cdp->ptx_written)) {
cdp->ptx = cdp->lc;
cdp->ptx_written = true;
} else {
}
#if DEBUG_AUDIO > 0
if (debugchannel (nr))
- write_log (L"AUD%dLCL: %04X %08X\n", nr, v, M68K_GETPC);
+ write_log (L"AUD%dLCL: %04X %08X (%d) (%d %d %08x)\n", nr, v, M68K_GETPC, cdp->state, cdp->dsr, cdp->ptx_written, cdp->ptx);
#endif
}
return 0;
if (!dmaen (DMA_BLITTER))
return 0;
+ if (blitter_cycle_exact) {
+ blitter_force_finish ();
+ return -1;
+ }
if (blit_last_cycle >= blit_diag[0] && blit_dmacount == blit_diag[0])
return 0;
cycles = (get_cycles () - blit_first_cycle) / CYCLE_UNIT;
static enum nln_how nextline_how;
static int lof_changed = 0;
static int scandoubled_line;
+static bool vsync_rendered;
/* Stupid genlock-detection prevention hack.
* We should stop calling vsync_handler() and
if (vs == -2) {
- show_screen ();
vsync_busywait_end ();
vsync_busywait_do (&freetime);
curr_time = read_processor_time ();
vsyncmintime = curr_time + vsynctime;
- render_screen ();
vsync_busywait_start ();
} else {
// vsync functions that are not hardware timing related
static void vsync_handler_pre (void)
{
+ vsync_rendered = false;
+
if (bogusframe > 0)
bogusframe--;
#ifdef JIT
}
#endif
+ if (is_lastline && isvsync () == -2 && !vsync_rendered) {
+ vsync_rendered = true;
+ render_screen ();
+ }
if (!nocustom ()) {
int lineno = vpos;
while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) {
int c = blitnasty ();
- if (c > 0) {
+ if (c < 0) {
+ break;
+ } else if (c > 0) {
cycles -= c * CYCLE_UNIT * 2;
if (cycles < CYCLE_UNIT)
cycles = 0;
- } else
+ } else {
c = 4;
+ }
x_do_cycles (c * CYCLE_UNIT);
if (regs.spcflags & SPCFLAG_COPPER)
do_copper ();
memset (&dpp, 0, sizeof (dpp));
dpp.Windowed = isfullscreen () <= 0;
dpp.BackBufferFormat = mode.Format;
- dpp.BackBufferCount = vsync == -1 ? 0 : (vsync == -2 ? 2 : currprefs.gfx_backbuffers);
+ dpp.BackBufferCount = currprefs.gfx_backbuffers;
dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
dpp.BackBufferWidth = w_w;
dpp.BackBufferHeight = w_h;
- dpp.PresentationInterval = (dpp.Windowed || dpp.BackBufferCount == 0 || vsync == -1) ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;
+ dpp.PresentationInterval = dpp.BackBufferCount <= 1 || dpp.Windowed ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;
modeex.Width = w_w;
modeex.Height = w_h;
if (isfullscreen () > 0) {
dpp.FullScreen_RefreshRateInHz = currprefs.gfx_refreshrate > 0 ? currprefs.gfx_refreshrate : 0;
modeex.RefreshRate = dpp.FullScreen_RefreshRateInHz;
- if (currprefs.gfx_avsync && currprefs.gfx_avsyncmode == 0) {
+ if (vsync > 0) {
dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
if (getvsyncrate (dpp.FullScreen_RefreshRateInHz) != dpp.FullScreen_RefreshRateInHz) {
if (d3dCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
write_log (L"DYNAMIC ");
write_log (L"\n");
- write_log (L"%s: PS=%d.%d VS=%d.%d %d*%d*%d%s%s %d-bit %d\n",
+ write_log (L"%s: PS=%d.%d VS=%d.%d %d*%d*%d%s VS=%d B=%d%s%s %d-bit %d\n",
D3DHEAD,
(d3dCaps.PixelShaderVersion >> 8) & 0xff, d3dCaps.PixelShaderVersion & 0xff,
(d3dCaps.VertexShaderVersion >> 8) & 0xff, d3dCaps.VertexShaderVersion & 0xff,
max_texture_w, max_texture_h,
dpp.Windowed ? 0 : dpp.FullScreen_RefreshRateInHz,
dpp.Windowed ? L"" : L" FS",
- currprefs.gfx_avsync ? L" VSYNC" : L"",
+ vsync, dpp.BackBufferCount,
+ dpp.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE ? L"I" : L"F",
+ currprefs.gfx_backbuffers == 0 ? L"E" : L"",
t_depth, adapter
);
maxscanline = 0;
d3d_enabled = 1;
- if (vsync == -1) {
- 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) {
+ 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 (d3ddevex) {
- hr = d3ddevex->SetMaximumFrameLatency (1);
+ hr = d3ddevex->SetMaximumFrameLatency (vsync < 0 ? 1 : 0);
if (FAILED (hr))
write_log (L"%s: SetMaximumFrameLatency() failed: %s\n", D3DHEAD, D3D_ErrorString (hr));
}
#include "dxwrap.h"
#include "win32gfx.h"
#include "statusline.h"
+#include "xwin.h"
#include <d3d9.h>
#include <dxerr.h>
DWORD oldflags = desc.dwFlags;
desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP;
- desc.dwBackBufferCount = currprefs.gfx_backbuffers;
+ desc.dwBackBufferCount = currprefs.gfx_backbuffers == 0 ? 1 : currprefs.gfx_backbuffers;
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;
+ int vsync = isvsync ();
- if (currprefs.turbo_emulation)
+ if (currprefs.turbo_emulation || (vsync && currprefs.gfx_backbuffers <= 1))
flags |= DDFLIP_NOVSYNC;
if (dxdata.backbuffers == 2) {
DirectDraw_Blit (dxdata.flipping[1], dxdata.flipping[0]);
- if (currprefs.gfx_avsync) {
+ if (vsync) {
if (vblank_skip >= 0 || currprefs.turbo_emulation) {
ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags);
} else {
ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags| DDFLIP_NOVSYNC);
}
} else if(dxdata.backbuffers == 1) {
- if (currprefs.gfx_avsync) {
- ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags);
- } else {
- ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags | DDFLIP_NOVSYNC);
- }
+ ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags | DDFLIP_NOVSYNC);
DirectDraw_Blit (dxdata.flipping[0], dxdata.primary);
}
if (ddrval == DDERR_SURFACELOST) {
#define LANG_DLL 1
//#define WINUAEBETA L""
-#define WINUAEBETA L"Beta 2"
-#define WINUAEDATE MAKEBD(2011, 12, 11)
+#define WINUAEBETA L"Beta 4"
+#define WINUAEDATE MAKEBD(2011, 12, 12)
#define WINUAEEXTRA L""
#define WINUAEREV L""
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;
return render_ok;
flushymin = 0;
flushymax = currentmode->amiga_height;
+ EnterCriticalSection (&cs_render);
if (currentmode->flags & DM_D3D) {
v = D3D_renderframe ();
#ifdef GFXFILTER
} else if (currentmode->flags & DM_DDRAW) {
v = true;
}
+ LeaveCriticalSection (&cs_render);
render_ok = v;
return render_ok;
}
return;
if (!render_ok)
return;
+ EnterCriticalSection (&cs_render);
if (currentmode->flags & DM_D3D) {
D3D_showframe ();
#ifdef GFXFILTER
} else if (currentmode->flags & DM_DDRAW) {
DirectDraw_Flip (1);
}
+ LeaveCriticalSection (&cs_render);
}
static uae_u8 *ddraw_dolock (void)
int graphics_init (void)
{
+ InitializeCriticalSection (&cs_render);
gfxmode_reset ();
return open_windows (1);
}
bool ok = getvblankstate (&vb);
if (!ok || vb) {
thread_vblank_found = true;
+ show_screen ();
//write_log (L"%d\n", t - thread_vblank_time);
thread_vblank_time = t;
}
if (waitonly) {
vblankbasefull = syncbase / approx_vblank;
vblankbasewait = (syncbase / approx_vblank) * 3 / 4;
- vblankbasewait2 = (syncbase / approx_vblank) * 5 / 10;
+ vblankbasewait2 = (syncbase / approx_vblank) * 7 / 10;
remembered_vblank = -1;
return -1;
}
if (cnt >= total)
break;
}
- changevblankthreadmode (VBLANKTH_IDLE);
+ changevblankthreadmode (threaded_vsync ? VBLANKTH_IDLE : VBLANKTH_KILL);
SetThreadPriority (th, oldpri);
if (maxcnt >= maxtotal) {
tsum = tsum2 / tcnt2;
i--;
workprefs.gfx_avsync = (i & 1) + 1;
workprefs.gfx_avsyncmode = i >= 2 ? 1 : 0;
- if (workprefs.gfx_avsyncmode != oldmode && workprefs.gfx_avsyncmode) {
- workprefs.gfx_backbuffers = 0;
- SendDlgItemMessage (hDlg, IDC_DISPLAY_BUFFERCNT, CB_SETCURSEL, workprefs.gfx_backbuffers, 0);
- }
}
workprefs.gfx_pfullscreen = SendDlgItemMessage (hDlg, IDC_SCREENMODE_RTG, CB_GETCURSEL, 0, 0);
+Beta 4:
+
+- Another switching from CE mode to non-CE hang fix. (Blitter nasty related)
+- Another too fast CPU audio hack update, fixes random glitches (Uridium II, Moonstone, probably many others)
+- Low latency vsync buffering change, selected buffering mode can be modified now.
+ - No buffering is same as previously
+ - Double and triple buffering can be enabled, increases latency but can reduce random jumps.
+- Fastest possible CPU low latency vsync update:
+ - Works now without buffering
+ - Flips buffers in vblank thread (Flipping timing is correct now, tearing gone)
+
+Normal vsync may still be broken.
+
Beta 3:
- Fixed DirectDraw mode crash (b1)