_tcscat (s, L",vsync");
else if (cr->vsync == 0)
_tcscat (s, L",nvsync");
+ if (cr->rtg)
+ _tcscat (s, L",rtg");
if (cr->commands[0]) {
_tcscat (s, L",");
_tcscat (s, cr->commands);
tmpbuf[sizeof tmpbuf / sizeof (TCHAR) - 1] = '\0';
int vert = -1, horiz = -1, lace = -1, ntsc = -1, framelength = -1, vsync = -1;
- int locked = 0;
+ bool locked = false;
+ bool rtg = false;
double rate = -1;
TCHAR cmd[MAX_DPATH], label[16] = { 0 };
TCHAR *tmpp = tmpbuf;
}
}
if (!_tcsnicmp (tmpp, L"locked", 4))
- locked = 1;
+ locked = true;
if (!_tcsnicmp (tmpp, L"nlace", 5))
lace = 0;
if (!_tcsnicmp (tmpp, L"lace", 4))
framelength = 1;
if (!_tcsnicmp (tmpp, L"shf", 3))
framelength = 0;
+ if (!_tcsnicmp (tmpp, L"rtg", 3))
+ rtg = true;
tmpp = next;
if (tmpp >= end)
break;
p->cr[i].lace = lace;
p->cr[i].ntsc = ntsc;
p->cr[i].vsync = vsync;
- p->cr[i].locked = locked != 0;
+ p->cr[i].locked = locked;
+ p->cr[i].rtg = rtg;
p->cr[i].framelength = framelength;
p->cr[i].rate = rate;
_tcscpy (p->cr[i].commands, cmd);
reset_drawing ();
}
- if (!picasso_on) {
- for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) {
- struct chipset_refresh *cr = &currprefs.cr[i];
- if ((cr->horiz < 0 || cr->horiz == maxhpos) &&
- (cr->vert < 0 || cr->vert == maxvpos_nom) &&
- (cr->ntsc < 0 || (cr->ntsc > 0 && isntsc) || (cr->ntsc == 0 && !isntsc)) &&
- (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->vsync < 0 || (cr->vsync > 0 && isvsync ()) || (cr->vsync == 0 && !isvsync ()))) {
- double v = -1;
-
+ for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) {
+ struct chipset_refresh *cr = &currprefs.cr[i];
+ if ((cr->horiz < 0 || cr->horiz == maxhpos) &&
+ (cr->vert < 0 || cr->vert == maxvpos_nom) &&
+ (cr->ntsc < 0 || (cr->ntsc > 0 && isntsc) || (cr->ntsc == 0 && !isntsc)) &&
+ (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->rtg && picasso_on) || (!cr->rtg && !picasso_on)) &&
+ (cr->vsync < 0 || (cr->vsync > 0 && isvsync ()) || (cr->vsync == 0 && !isvsync ()))) {
+ double v = -1;
+
+ if (!picasso_on) {
if (isvsync ()) {
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) {
if (v < 0)
v = cr->rate;
if (v > 0) {
- changed_prefs.chipset_refreshrate = v;
+ changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = v;
cfgfile_parse_lines (&changed_prefs, cr->commands, -1);
}
- break;
- }
+ } else {
+ if (cr->locked == false)
+ v = vblank_hz;
+ else
+ v = cr->rate;
+ changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = v;
+ cfgfile_parse_lines (&changed_prefs, cr->commands, -1);
+ }
+ break;
}
}
if (vs > 0) {
vsyncmintime = vsynctime;
- update_screen ();
+ render_screen ();
+ show_screen ();
return;
} else if (vs < 0) {
vsyncmintime = vsynctime;
+ render_screen ();
vsync_busywait ();
- update_screen ();
+ show_screen ();
return;
}
+ render_screen ();
for (;;) {
double v = rpt_vsync () / (syncbase / 1000.0);
if (v >= -4)
break;
sleep_millis (2);
}
- update_screen ();
curr_time = start = read_processor_time ();
while (rpt_vsync () < 0);
curr_time = read_processor_time ();
vsyncmintime = curr_time + vsynctime;
idletime += read_processor_time() - start;
+ show_screen ();
}
static frame_time_t frametime2;
if ((long int)(curr_time - vsyncmintime) > 0 || rpt_did_reset)
vsyncmintime = curr_time + vsynctime;
rpt_did_reset = 0;
- update_screen ();
+ render_screen ();
+ show_screen ();
} else if (rpt_available) {
framewait ();
}
if (rpt_available && currprefs.m68k_speed == 0) {
framewait ();
} else {
- update_screen ();
+ render_screen ();
+ show_screen ();
}
}
#endif
} else if (currprefs.m68k_speed == 0) {
framewait ();
} else {
- update_screen ();
+ render_screen ();
+ show_screen ();
}
#if CUSTOM_DEBUG > 1
struct chipset_refresh
{
bool locked;
+ bool rtg;
int horiz;
int vert;
int lace;
extern void flush_block (int, int);
extern void flush_screen (int, int);
extern void flush_clear_screen (void);
-extern void update_screen (void);
+extern bool render_screen (void);
+extern void show_screen (void);
extern int lockscr (int);
extern void unlockscr (void);
static int melast_x, melast_y;
static int isnonzero;
- if (currprefs.input_magic_mouse == 0 || currprefs.input_tablet > 0)
+ if (currprefs.input_magic_mouse == 0 || currprefs.input_tablet > 0 || isfullscreen ())
return 0;
if (magicmouse_ibase == 0xffffffff)
return 0;
: License version 2 as published by the Free Software Foundation.
Authors : os, mcb
Created : 2007-08-27 13:55:49
- Updated : 2011-02-02 12:20:00
+ Updated : 2011-07-07 00:04:00
Comment : RP Player interprocess communication include file
*****************************************************************************/
#include <windows.h>
-#define RPLATFORM_API_VER "1.4"
+#define RPLATFORM_API_VER "1.5"
#define RPLATFORM_API_VER_MAJOR 1
-#define RPLATFORM_API_VER_MINOR 4
+#define RPLATFORM_API_VER_MINOR 5
#define RPIPC_HostWndClass "RetroPlatformHost%s"
#define RPIPC_GuestWndClass "RetroPlatformGuest%d"
#define RP_FEATURE_STATE 0x00000400 // loading and saving of emulation state is supported (see RPIPCHM_SAVESTATE/RPIPCHM_LOADSTATE message)
#define RP_FEATURE_SCANLINES 0x00000800 // scan lines video effect is available
#define RP_FEATURE_DEVICEREADWRITE 0x00001000 // device read/write can be set at runtime on floppy and hard disks
+#define RP_FEATURE_RESIZE_SUBPIXEL 0x00002000 // supports sub-pixel scaling of windowed and full-screen modes (i.e. not just integer multipliers like 1X, 2X, etc., but stretch to fill any desired pixel size)
+#define RP_FEATURE_RESIZE_STRETCH 0x00004000 // supports "stretch to fill" (without preserving original ratio) in full-screen mode or with lTargetWidth and lTargetHeight set
// Screen Modes
#define RP_SCREENMODE_1X 0x00000000 // 1x window or full-screen mode ("CGA mode")
#define RP_SCREENMODE_2X 0x00000001 // 2x window or full-screen mode ("VGA mode")
#define RP_SCREENMODE_3X 0x00000002 // 3x window or full-screen mode ("triple CGA mode")
#define RP_SCREENMODE_4X 0x00000003 // 4x window or full-screen mode ("double VGA mode")
-#define RP_SCREENMODE_XX 0x000000FF // autoset maximum nX (integer n, preserve ratio)
+#define RP_SCREENMODE_WW 0x000000FE // scale WindoW to lTargetWidth/lTargetHeight (default: maximum possible integer multiplication, no subpixel stretching, preserve ratio)
+#define RP_SCREENMODE_XX 0x000000FF // autoset maximum nX (default: maximum possible integer multiplication, no subpixel stretching, preserve ratio)
#define RP_SCREENMODE_MODEMASK 0x000000FF
#define RP_SCREENMODE_FULLSCREEN_1 0x00000100 // full screen on primary (default) display
#define RP_SCREENMODE_FULLSCREEN_2 0x00000200 // full screen on secondary display (fallback to 1 if unavailable)
#define RP_SCREENMODE_DISPLAYMASK 0x0000FF00
-#define RP_SCREENMODE_FULLWINDOW 0x00010000 // use "full window" when in fullscreen (no gfx card full screen)
+#define RP_SCREENMODE_FULLWINDOW 0x00010000 // use "full window" (desktop size) when in full screen (no gfx card full screen)
#define RP_SCREENMODE_USETVM_NEVER 0x00000000 // never use TV modes
#define RP_SCREENMODE_USETVM_ALWAYS 0x00020000 // always use TV modes
#define RP_SCREENMODE_USETVM_AUTO 0x00040000 // use all available modes
#define RP_SCREENMODE_USETVMMASK 0x00060000
#define RP_SCREENMODE_SCANLINES 0x00080000 // show video scan lines
+#define RP_SCREENMODE_SUBPIXEL 0x00100000 // use sub-pixel (non-integer) scaling in full-screen = "XX" mode, or with lTargetWidth and lTargetHeight set (if not set may add black bars)
+#define RP_SCREENMODE_STRETCH 0x00200000 // "stretch to fill" (do not preserve original ratio) in full-screen = "XX" mode, or with lTargetWidth and lTargetHeight set (if not set may add black bars)
#define RP_SCREENMODE_DISPLAY(m) (((m) & RP_SCREENMODE_DISPLAYMASK) >> 8) // given a mode 'm' returns the display number (1-255) or 0 if full screen is not active
#define RP_SCREENMODE_USETVM(m) ((m) & RP_SCREENMODE_USETVMMASK) // given a mode 'm' returns the RP_SCREENMODE_USETVM_* value in it (automatic display mode selection in full screen modes)
#define RP_SCREENMODE_MODE(m) ((m) & RP_SCREENMODE_MODEMASK) // given a mode 'm' returns the #X mode
#define RP_CLIPFLAGS_AUTOCLIP 0x00000001 // ignore all 4 Clip values (same as all values = -1) and use "smart" offset and size
#define RP_CLIPFLAGS_NOCLIP 0x00000002 // ignore all 4 Clip values (same as all values = -1) and use 0:0 offset and maximum possible size (probably ugly, but good for adjusting clip area manually)
-// Clip/Scale Examples
//
-// An Amiga game with known clip offset/size will have lClipLeft/Top/Width/Height set, and no RP_CLIPFLAGS.
+// Integer vs. subpixel scaling, and stretching with or without original ratio
+//
+// By default, the guest is only expected to be able to scale (resize) the window by an integer number of times, e.g. 1X, 2X, 3X, etc., as indicated in RP_FEATURE_SCREEN...
+// This means that when going to full-screen or full-window mode or a window mode with lTargetWidth and lTargetHeight set, the content will be an integer number of times the original, and surrounded by black bars if necessary.
+//
+// In a known-size target (e.g. full-screen), unless RP_SCREENMODE_SUBPIXEL or RP_SCREENMODE_STRETCH are set, there may be up to four black bars to fill any unused space.
+//
+// RP_SCREENMODE_SUBPIXEL (used only if RP_FEATURE_RESIZE_SUBPIXEL was set) allows for subpixel resize scenarios beyond integer 1X, 2X, etc. This is both in full-screen/window and in window mode.
+//
+// In a known-size target (e.g. full-screen), RP_SCREENMODE_SUBPIXEL allows for "stretch to fill" with black areas only on two sides out of four (e.g. 4:3 displayed on 16:9 will fill to the top and bottom, and have bars only on the left and right).
+//
+// RP_SCREENMODE_STRETCH (used only if RP_FEATURE_RESIZE_STRETCH was set) allows to break (not respect) the original screen ratio.
+//
+// In theory RP_SCREENMODE_STRETCH could be used alone (without RP_SCREENMODE_SUBPIXEL), but it probably doesn'd make practical sense. In any case, the theoretical result would be scaling with different integer values for X and Y.
+//
+// RP_SCREENMODE_SUBPIXEL combined with RP_SCREENMODE_STRETCH allows for maximum "stretch to fill" with no black areas.
+//
+//
+// Typical scenarios:
+//
+// - Window mode without lTargetWidth and lTargetHeight set (user clicks 1X, 2X, etc. to resize)
+// - Window mode with lTargetWidth and lTargetHeight set (user resizes via window resize corner)
+// - Full-screen mode
+// - Real-time clip changes (users clicks a control and uses cursor keys to visually adjust clip)
+//
+//
+// Full-window Examples
+//
+// Example 1: No RP_SCREENMODE_SUBPIXEL, no RP_SCREENMODE_STRETCH: maximum integer scaling (can have black bars on up to four sides)
+//
+// Example 2: RP_SCREENMODE_SUBPIXEL, no RP_SCREENMODE_STRETCH: maximum "soft" scaling keeping ratio (can have black bars on two sides)
+//
+// Example 3: RP_SCREENMODE_SUBPIXEL combined with RP_SCREENMODE_STRETCH: maximum "stretch to fill" with no black areas
+//
+// There is a (theoretical) fourth case (RP_SCREENMODE_STRETCH without RP_SCREENMODE_SUBPIXEL), which could result in different integer multiplications along each axis. The player will not request such a mode.
+//
+//
+// Clipping Examples
+//
+// In the following examples it is assumed that RP_SCREENMODE_SUBPIXEL and RP_SCREENMODE_STRETCH are cleared unless specified otherwise.
+//
+// Example 1: An Amiga game with known clip offset/size will have lClipLeft/Top/Width/Height set, and no RP_CLIPFLAGS.
// In windowed mode, the guest (e.g. WinUAE) will take the net clipped region and apply RP_SCREENMODE_xX scaling to that.
-// In RP_SCREENMODE_FULLWINDOW mode, the net clipped region will be "soft-scaled" to the maximum possible (not necessarily an integer scaling factor), centered and padded by a black border.
+// In RP_SCREENMODE_FULLWINDOW mode, the net clipped region will be scaled to the maximum possible (not necessarily an integer scaling factor, if RP_SCREENMODE_SUBPIXEL and RP_SCREENMODE_STRETCH are set), centered and padded by black bars if necessary (unless RP_SCREENMODE_SUBPIXEL and RP_SCREENMODE_STRETCH are set).
// In one of the RP_SCREENMODE_FULLSCREEN modes, the net clipped region will be centered in the smallest possible compatible hardware mode (in consideration of RP_SCREENMODE_USETVM) and padded by a black border.
-// If an Amiga application sets a different Amiga chipset screen mode, the "container" window size will remain unchanged.
+// If an Amiga application sets a different Amiga chipset screen mode, the "container" window size will remain unchanged (because it is still constrained by the clipping values).
// If an Amiga application sets a different RTG screen mode, the "container" window size will reflect the new RTG size (instead of the Amiga clip size) and apply RP_SCREENMODE_xX.
//
-// An unknown Amiga application or one that has no known clip offset/size will start with RP_CLIPFLAGS_AUTOCLIP.
+// Example 2: An unknown Amiga application or one that has no known clip offset/size will start with RP_CLIPFLAGS_AUTOCLIP.
// The guest (e.g. WinUAE) will apply whatever logic it can to minimize the visible overscan region.
// The guest will send to the host the actual RPScreenMode data with the offset/size details that were applied.
// In windowed mode, RP_SCREENMODE_xX scaling is applied like in the previous example.
// RP_SCREENMODE_FULLWINDOW and RP_SCREENMODE_FULLSCREEN modes behave like in the previous example (scaling, etc.)
-// If an Amiga application sets a different Amiga or RTG chipset screen mode, the "container" window size may change.
+// If an Amiga application sets a different Amiga or RTG chipset screen mode, the "container" window size may change (because it is not constrained by any host-set clipping values), in consideration of RP_SCREENMODE_xX.
+//
+//
+// Notes
+//
+// If the user wants to adjust clipping, or for automated grabs and calculations, it is possible to set RP_CLIPFLAGS_NOCLIP, which will widen the window to the maximum (within lTargetWidth+lTargetHeight/full-screen constraints).
+//
+// Whenever the guest sets or changes the "container" window size or scaling factor (initially, or due to a command it receives, or due to Amiga-sourced changes), it sends an RPScreenMode update to the host.
+//
+// In window mode, if no lTargetWidth and lTargetHeight are set, when the host asks for a change in clipping (net content size), the host window size will be adjusted taking into account the current integer multiplication factor.
//
-// If the user wants to adjust clipping, or for automated grabs and calculations, it is possible to set RP_CLIPFLAGS_NOCLIP, which will widen the window to the maximum.
+// In window mode, after a change of clipping or size, the player may have to reset the visual hilight of the 1X, 2X etc. buttons according to new RPIPCGM_SCREENMODE data (setting a hilight if the correct scaling button is present in the user interface, or removing all hilights if the corresponding button is missing).
//
-// Whenever the guest sets or changes the "container" window size (initially, or due to a command it receives, or due to Amiga-sourced changes), it sends a RPScreenMode update to the host.
typedef struct RPScreenMode
{
DWORD dwScreenMode; // RP_SCREENMODE_* values and flags
- LONG lClipLeft; // -1 = ignore (0 is a valid value)
- LONG lClipTop; // -1 = ignore (0 is a valid value)
- LONG lClipWidth; // -1 = ignore
- LONG lClipHeight; // -1 = ignore
+ LONG lClipLeft; // in guest pixel units; -1 = ignore (0 is a valid value)
+ LONG lClipTop; // in guest pixel units; -1 = ignore (0 is a valid value)
+ LONG lClipWidth; // in guest pixel units; -1 = ignore
+ LONG lClipHeight; // in guest pixel units; -1 = ignore
HWND hGuestWindow; // only valid for RPIPCGM_SCREENMODE
- DWORD dwClipFlags;
+ DWORD dwClipFlags; // clip flags (or 0)
+ LONG lTargetWidth; // in exact host pixels; if set, must also set lTargetHeight; ignored unless RP_SCREENMODE_WW is set (resulting size is result of clipping and scaling); RP_SCREENMODE_SUBPIXEL and RP_SCREENMODE_STRETCH are taken into account
+ LONG lTargetHeight; // in exact host pixels, used with lTargetWidth
} RPSCREENMODE;
// Device Categories
#define RP_JOYSTICK_BUTTON2 0x00000020 // button 2 - Fire 2 - CD32 Blue
#define RP_JOYSTICK_BUTTON3 0x00000040 // button 3 - Fire 3 - CD32 Yellow
#define RP_JOYSTICK_BUTTON4 0x00000080 // button 4 - Fire 4 - CD32 Green
-#define RP_JOYSTICK_BUTTON5 0x00000100 // button 5 - CD32 Play
-#define RP_JOYSTICK_BUTTON6 0x00000200 // button 6 - CD32 Reverse
-#define RP_JOYSTICK_BUTTON7 0x00000400 // button 7 - CD32 Forward
+#define RP_JOYSTICK_BUTTON5 0x00000100 // button 5 - CDTV/CD32 Play/Pause
+#define RP_JOYSTICK_BUTTON6 0x00000200 // button 6 - CDTV/CD32 Reverse
+#define RP_JOYSTICK_BUTTON7 0x00000400 // button 7 - CDTV/CD32 Forward
+// To clarify: Where is the CDTV Stop button? Does the CD32 joypad have Stop?
// Device Read/Write status
#define RP_DEVICE_READONLY 0 // the medium is write-protected
static IDirect3DDevice9Ex *d3ddevex;
static D3DSURFACE_DESC dsdbb;
static LPDIRECT3DTEXTURE9 texture, sltexture, ledtexture, masktexture, mask2texture, blanktexture;
+static IDirect3DQuery9 *query;
static int masktexture_w, masktexture_h;
static float mask2texture_w, mask2texture_h, mask2texture_ww, mask2texture_wh;
static float mask2texture_multx, mask2texture_multy, mask2texture_offsetw;
static void invalidatedeviceobjects (void)
{
+ if (query) {
+ query->Release();
+ query = NULL;
+ }
if (texture) {
texture->Release ();
texture = NULL;
HINSTANCE d3dDLL, d3dx;
typedef HRESULT (WINAPI *LPDIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**);
LPDIRECT3DCREATE9EX d3dexp = NULL;
+ bool newvsync = currprefs.gfx_avsync && currprefs.gfx_avsyncmode && !picasso_on;
D3D_free2 ();
if (!currprefs.gfx_api) {
memset (&dpp, 0, sizeof (dpp));
dpp.Windowed = isfullscreen () <= 0;
dpp.BackBufferFormat = mode.Format;
- dpp.BackBufferCount = dpp.Windowed || !currprefs.gfx_avsync ? 1 : currprefs.gfx_backbuffers;
+ dpp.BackBufferCount = newvsync ? 0 : (dpp.Windowed || !currprefs.gfx_avsync ? 1 : currprefs.gfx_backbuffers);
dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
dpp.BackBufferWidth = w_w;
dpp.BackBufferHeight = w_h;
- dpp.PresentationInterval = dpp.Windowed || currprefs.gfx_backbuffers == 0 ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;
+ dpp.PresentationInterval = dpp.Windowed || currprefs.gfx_backbuffers == 0 || newvsync ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;
modeex.Width = w_w;
modeex.Height = w_h;
modeex.Format = mode.Format;
vsync2 = 0;
- if (isfullscreen() > 0) {
+ 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) {
maxscanline = 0;
d3d_enabled = 1;
+ if (newvsync) {
+ d3ddev->CreateQuery(D3DQUERYTYPE_EVENT, &query);
+ }
+ if (d3ddevex)
+ d3ddevex->SetMaximumFrameLatency (1);
+
return 0;
}
}
}
-static void D3D_render22 (void)
+static void D3D_render2 (void)
{
HRESULT hr;
LPDIRECT3DTEXTURE9 srctex = texture;
hr = d3ddev->EndScene ();
if (FAILED (hr))
write_log (L"%s: EndScene() %s\n", D3DHEAD, D3D_ErrorString (hr));
- hr = d3ddev->Present (NULL, NULL, NULL, NULL);
- if (FAILED (hr)) {
- write_log (L"%s: Present() %s\n", D3DHEAD, D3D_ErrorString (hr));
- if (hr == D3DERR_DEVICELOST) {
- devicelost = 1;
- }
- }
-}
-
-static void D3D_render2 (void)
-{
- D3D_render22 ();
}
void D3D_setcursor (int x, int y, int visible)
return (uae_u8*)lock.pBits;
}
-void D3D_flip (void)
+bool D3D_renderframe (void)
{
static int frameskip;
+
if (!isd3d ())
- return;
+ return false;
if (currprefs.turbo_emulation && isfullscreen () > 0 && frameskip-- > 0)
- return;
+ return false;
frameskip = 50;
+
D3D_render2 ();
- if (vsync2 && !currprefs.turbo_emulation)
+ if (vsync2 && !currprefs.turbo_emulation) {
D3D_render2 ();
+ }
+
+ if (query) {
+ if (SUCCEEDED (query->Issue (D3DISSUE_END))) {
+ while (query->GetData (NULL, 0, D3DGETDATA_FLUSH) == S_FALSE);
+ }
+ }
+ return true;
+}
+
+void D3D_showframe (void)
+{
+ HRESULT hr;
+
+ if (!isd3d ())
+ return;
+ hr = d3ddev->Present (NULL, NULL, NULL, NULL);
+ if (FAILED (hr)) {
+ write_log (L"%s: Present() %s\n", D3DHEAD, D3D_ErrorString (hr));
+ if (hr == D3DERR_DEVICELOST) {
+ devicelost = 1;
+ }
+ }
}
void D3D_refresh (void)
if (!isd3d ())
return;
D3D_render2 ();
+ D3D_showframe ();
D3D_render2 ();
+ D3D_showframe ();
createscanlines (0);
}
extern const TCHAR *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth, int mult);
extern void D3D_getpixelformat (int depth,int *rb, int *bb, int *gb, int *rs, int *bs, int *gs, int *ab, int *ar, int *a);
extern void D3D_refresh (void);
-extern void D3D_flip (void);
+extern bool D3D_renderframe (void);
+extern void D3D_showframe (void);
extern uae_u8 *D3D_locktexture(int*,int);
extern void D3D_unlocktexture(void);
extern void D3D_flushtexture (int miny, int maxy);
static int recursive_device, recursive;
static int currentpausemode;
static int gameportmask[MAX_JPORTS];
+static DWORD storeflags;
static int cando (void)
{
sm->lClipHeight = shift (p->gfx_size_win.height, -(VRES_MAX - vres));
}
- if (full && p->gfx_filter && p->gfx_filter_horiz_zoom_mult == 0)
- m = RP_SCREENMODE_XX;
if (p->gfx_filter_scanlines || p->gfx_scanlines)
m |= RP_SCREENMODE_SCANLINES;
cf |= RP_CLIPFLAGS_AUTOCLIP;
}
if (full) {
- m &= ~0x0000ff00;
+ m &= ~RP_SCREENMODE_DISPLAYMASK;
m |= p->gfx_display << 8;
}
if (full > 1)
m |= RP_SCREENMODE_FULLWINDOW;
- sm->dwScreenMode = m;
+ sm->dwScreenMode = m | (storeflags & (RP_SCREENMODE_STRETCH | RP_SCREENMODE_SUBPIXEL));
+ if ((storeflags & RP_SCREENMODE_MODEMASK) == RP_SCREENMODE_XX) {
+ sm->dwScreenMode |= RP_SCREENMODE_XX;
+ } else if ((storeflags & RP_SCREENMODE_MODEMASK) == RP_SCREENMODE_WW) {
+ sm->dwScreenMode |= RP_SCREENMODE_WW;
+ sm->lTargetWidth = p->gfx_size_win.width;
+ sm->lTargetHeight = p->gfx_size_win.height;
+ }
sm->dwClipFlags = cf;
if (log_rp)
int hres, vres;
int hmult = 1, vmult = 1;
struct MultiDisplay *disp;
+ bool keepaspect = (sm->dwScreenMode & RP_SCREENMODE_SUBPIXEL) && !(sm->dwScreenMode & RP_SCREENMODE_STRETCH);
+ bool stretch = (sm->dwScreenMode & RP_SCREENMODE_STRETCH) != 0;
+ bool forcesize = smm == RP_SCREENMODE_WW && sm->lTargetWidth > 0 && sm->lTargetHeight > 0;
+ storeflags = sm->dwScreenMode;
minimized = 0;
if (display) {
p->gfx_display = display;
p->gfx_size_win.height = sm->lClipHeight >> (VRES_MAX - vdbl);
}
+ if (forcesize) {
+ p->gfx_size_win.width = sm->lTargetWidth;
+ p->gfx_size_win.height = sm->lTargetHeight;
+ }
+
if (fs == 1) {
p->gfx_size_fs.width = p->gfx_size_win.width;
p->gfx_size_fs.height = p->gfx_size_win.height;
p->gfx_size_fs.height = disp->rect.bottom - disp->rect.top;
}
- if (fs) {
- if (smm == RP_SCREENMODE_XX) {
- p->gfx_filter = rp_filter;
- } else {
- int mult;
- int prevmult = 1;
- int xmult = uaefilters[p->gfx_filter].intmul;
- int ymult = uaefilters[p->gfx_filter].intmul ;
- for (mult = 2; mult <= 4; mult += 2) {
- int w = p->gfx_size_win.width;
- int h = p->gfx_size_win.height;
- if (p->gfx_size_fs.width * xmult < w * mult || p->gfx_size_fs.height * ymult < h * mult) {
- mult = prevmult;
- break;
- }
- prevmult = mult;
- }
- if (mult > 1 || fs == 2) {
- p->gfx_filter = rp_filter;
- hmult = vmult = mult;
+ if (smm == RP_SCREENMODE_XX) {
+ int mult;
+ int prevmult = 1;
+ int xmult = uaefilters[p->gfx_filter].intmul;
+ int ymult = uaefilters[p->gfx_filter].intmul;
+ for (mult = 2; mult <= 8; mult++) {
+ int w = p->gfx_size_win.width;
+ int h = p->gfx_size_win.height;
+ if (p->gfx_size_fs.width * xmult < w * mult || p->gfx_size_fs.height * ymult < h * mult) {
+ mult = prevmult;
+ break;
}
+ prevmult = mult;
+ }
+ if (mult > 1) {
+ hmult = vmult = mult;
}
}
p->gfx_pfullscreen = fs;
p->gfx_afullscreen = fs;
p->win32_rtgscaleifsmall = fs == 2;
-#if 1
- if (fs) {
+ if (stretch) {
+ hmult = vmult = 0;
+ }
+ if (keepaspect) {
p->gfx_filter_aspect = -1;
p->gfx_filter_keep_aspect = 1;
} else {
p->gfx_filter_aspect = 0;
p->gfx_filter_keep_aspect = 0;
}
-#endif
- write_log(L"%dx%d %dx%d %08x\n", sm->lClipLeft, sm->lClipTop, sm->lClipWidth, sm->lClipHeight, sm->dwClipFlags);
+ write_log(L"%dx%d %dx%d %dx%d %08x\n",
+ sm->lClipLeft, sm->lClipTop, sm->lClipWidth, sm->lClipHeight, sm->lTargetWidth, sm->lTargetHeight, sm->dwClipFlags);
p->gfx_xcenter_pos = sm->lClipLeft;
p->gfx_ycenter_pos = sm->lClipTop;
p->gfx_ycenter_size = sm->lClipHeight;
if (sm->dwClipFlags & RP_CLIPFLAGS_AUTOCLIP) {
- if (!fs)
+ if (!forcesize)
p->gfx_filter_autoscale = AUTOSCALE_RESIZE;
else
p->gfx_filter_autoscale = AUTOSCALE_NORMAL;
p->gfx_xcenter_size = -1;
p->gfx_ycenter_size = -1;
} else if (sm->dwClipFlags & RP_CLIPFLAGS_NOCLIP) {
- if (!fs)
- p->gfx_filter_autoscale = AUTOSCALE_RESIZE;
- else
- p->gfx_filter_autoscale = AUTOSCALE_NORMAL;
- p->gfx_xcenter_pos = 0;
- p->gfx_ycenter_pos = 0;
- p->gfx_xcenter_size = 1408;
- p->gfx_ycenter_size = 568;
+ p->gfx_filter_autoscale = AUTOSCALE_STATIC_MAX;
+ p->gfx_xcenter_pos = -1;
+ p->gfx_ycenter_pos = -1;
+ p->gfx_xcenter_size = -1;
+ p->gfx_ycenter_size = -1;
+ if (!forcesize) {
+ p->gfx_size_win.width = AMIGA_WIDTH_MAX << currprefs.gfx_resolution;
+ p->gfx_size_win.height = AMIGA_HEIGHT_MAX << currprefs.gfx_vresolution;;
+ }
} else if (p->gfx_xcenter_pos >= 0 || p->gfx_ycenter_pos >= 0) {
p->gfx_filter_autoscale = AUTOSCALE_MANUAL;
} else {
p->gfx_filter_autoscale = AUTOSCALE_STATIC_NOMINAL;
}
- //p->gfx_filter = rp_filter_default;
- p->gfx_filter_horiz_zoom_mult = 1000 / hmult;
- p->gfx_filter_vert_zoom_mult = 1000 / vmult;
+ p->gfx_filter_horiz_zoom_mult = hmult ? 1000 / hmult : 0;
+ p->gfx_filter_vert_zoom_mult = vmult ? 1000 / vmult : 0;
p->gfx_filter_scanlines = 0;
p->gfx_scanlines = 0;
}
if (log_rp)
- write_log (L"WW=%d WH=%d FW=%d FH=%d HM=%d VM=%d XP=%d YP=%d XS=%d YS=%d AS=%d\n",
+ write_log (L"WW=%d WH=%d FW=%d FH=%d HM=%d VM=%d XP=%d YP=%d XS=%d YS=%d AS=%d AR=%d,%d\n",
p->gfx_size_win.width, p->gfx_size_win.height,
p->gfx_size_fs.width, p->gfx_size_fs.height,
p->gfx_filter_horiz_zoom_mult, p->gfx_filter_vert_zoom_mult,
p->gfx_xcenter_pos, p->gfx_ycenter_pos,
p->gfx_xcenter_size, p->gfx_ycenter_size,
- p->gfx_filter_autoscale);
+ p->gfx_filter_autoscale, p->gfx_filter_aspect, p->gfx_filter_keep_aspect);
updatewinfsmode (p);
feat = RP_FEATURE_POWERLED | RP_FEATURE_SCREEN1X | RP_FEATURE_FULLSCREEN;
feat |= RP_FEATURE_PAUSE | RP_FEATURE_TURBO | RP_FEATURE_VOLUME | RP_FEATURE_SCREENCAPTURE;
feat |= RP_FEATURE_STATE | RP_FEATURE_SCANLINES | RP_FEATURE_DEVICEREADWRITE;
+ feat |= RP_FEATURE_RESIZE_SUBPIXEL | RP_FEATURE_RESIZE_STRETCH;
if (!WIN32GFX_IsPicassoScreen ())
feat |= RP_FEATURE_SCREEN2X | RP_FEATURE_SCREEN4X;
RPSendMessagex (RPIPCGM_FEATURES, feat, 0, NULL, 0, &guestinfo, NULL);
#define WINUAEPUBLICBETA 1
#define LANG_DLL 1
-#define WINUAEBETA L"Beta 2"
-#define WINUAEDATE MAKEBD(2011, 7, 5)
+#define WINUAEBETA L"Beta 3"
+#define WINUAEDATE MAKEBD(2011, 7, 10)
#define WINUAEEXTRA L""
#define WINUAEREV L""
static struct winuae_currentmode *currentmode = ¤tmodestruct;
static int wasfullwindow_a, wasfullwindow_p;
-static int vblankbase;
+static int vblankbasewait, vblankbasefull;
int screen_is_picasso = 0;
{
}
-void update_screen (void)
+static bool render_ok;
+
+bool render_screen (void)
{
+ bool v = false;
+
+ render_ok = false;
if (dx_islost ())
- return;
+ return render_ok;
flushymin = 0;
flushymax = currentmode->amiga_height;
if (currentmode->flags & DM_D3D) {
- D3D_flip ();
+ v = D3D_renderframe ();
#ifdef GFXFILTER
} else if (currentmode->flags & DM_SWSCALE) {
S2X_render ();
+ v = true;
+#endif
+ } else if (currentmode->flags & DM_DDRAW) {
+ v = true;
+ }
+ render_ok = v;
+ return render_ok;
+}
+
+void show_screen (void)
+{
+ if (dx_islost ())
+ return;
+ if (!render_ok)
+ return;
+ if (currentmode->flags & DM_D3D) {
+ D3D_showframe ();
+#ifdef GFXFILTER
+ } else if (currentmode->flags & DM_SWSCALE) {
DirectDraw_Flip (1);
#endif
} else if (currentmode->flags & DM_DDRAW) {
p96_double_buffer_needs_flushing = 0;
}
D3D_unlocktexture ();
- D3D_flip ();
+ if (D3D_renderframe ())
+ D3D_showframe ();
} else {
DirectDraw_SurfaceUnlock ();
if (p96_double_buffer_needs_flushing) {
if (remembered_vblank > 0)
return remembered_vblank;
if (waitonly) {
- vblankbase = (syncbase / approx_vblank) * 3 / 4;
+ vblankbasefull = syncbase / approx_vblank;
+ vblankbasewait = (syncbase / approx_vblank) * 3 / 4;
remembered_vblank = -1;
return -1;
}
}
if (tsum >= 85)
tsum /= 2;
- vblankbase = (syncbase / tsum) * 3 / 4;
+ vblankbasefull = (syncbase / tsum);
+ vblankbasewait = (syncbase / tsum) * 3 / 4;
write_log (L"VSync calibration: %.6fHz\n", tsum);
remembered_vblank = tsum;
return tsum;
{
bool v;
static frame_time_t prevtime;
+ static bool framelost;
if (currprefs.turbo_emulation)
return true;
- while (read_processor_time () - prevtime < vblankbase)
+ if (!framelost && read_processor_time () - prevtime > vblankbasefull) {
+ framelost = true;
+ prevtime = read_processor_time ();
+ return true;
+ }
+ if (framelost) {
+ framelost = false;
+ prevtime = read_processor_time ();
+ return true;
+ }
+
+ while (read_processor_time () - prevtime < vblankbasewait)
sleep_millis (1);
v = false;
if (currprefs.gfx_api) {
extern void close_windows (void);
extern void updatewinfsmode (struct uae_prefs *p);
extern int is3dmode (void);
-extern int vblankbase;
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);
TCHAR tmp[200];
workprefs.gfx_afullscreen = SendDlgItemMessage (hDlg, IDC_SCREENMODE_NATIVE, CB_GETCURSEL, 0, 0);
+ workprefs.gfx_lores_mode = ischecked (hDlg, IDC_LORES_SMOOTHED);
+ workprefs.gfx_scandoubler = ischecked (hDlg, IDC_FLICKERFIXER);
+ workprefs.gfx_blackerthanblack = ischecked (hDlg, IDC_BLACKER_THAN_BLACK);
+ workprefs.gfx_vresolution = (ischecked (hDlg, IDC_LM_DOUBLED) || ischecked (hDlg, IDC_LM_SCANLINES)) ? VRES_DOUBLE : VRES_NONDOUBLE;
+ workprefs.gfx_scanlines = ischecked (hDlg, IDC_LM_SCANLINES);
+ workprefs.gfx_backbuffers = SendDlgItemMessage (hDlg, IDC_DISPLAY_BUFFERCNT, CB_GETCURSEL, 0, 0);
+ workprefs.gfx_framerate = SendDlgItemMessage (hDlg, IDC_FRAMERATE, TBM_GETPOS, 0, 0);
+
i = SendDlgItemMessage (hDlg, IDC_SCREENMODE_NATIVE2, CB_GETCURSEL, 0, 0);
+ int oldmode = workprefs.gfx_avsyncmode;
workprefs.gfx_avsync = 0;
workprefs.gfx_avsyncmode = 0;
if (i > 0) {
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);
workprefs.gfx_pvsyncmode = i >= 1 ? 1 : 0;
}
- workprefs.gfx_lores_mode = ischecked (hDlg, IDC_LORES_SMOOTHED);
- workprefs.gfx_scandoubler = ischecked (hDlg, IDC_FLICKERFIXER);
- workprefs.gfx_blackerthanblack = ischecked (hDlg, IDC_BLACKER_THAN_BLACK);
- workprefs.gfx_vresolution = (ischecked (hDlg, IDC_LM_DOUBLED) || ischecked (hDlg, IDC_LM_SCANLINES)) ? VRES_DOUBLE : VRES_NONDOUBLE;
- workprefs.gfx_scanlines = ischecked (hDlg, IDC_LM_SCANLINES);
- workprefs.gfx_backbuffers = SendDlgItemMessage (hDlg, IDC_DISPLAY_BUFFERCNT, CB_GETCURSEL, 0, 0);
- workprefs.gfx_framerate = SendDlgItemMessage (hDlg, IDC_FRAMERATE, TBM_GETPOS, 0, 0);
-
bool updaterate = false, updateslider = false;
TCHAR label[16];
label[0] = 0;
+Beta 3:
+
+- tearing in new vsync modes should be completely gone, without introducing any extra latency
+- Display panel buffering option now does nothing in new vsync modes
+
Beta 2:
- experimental joystick raw input support, enable using -rawhid command line parameter.