mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
5039 lines
151 KiB
C++
5039 lines
151 KiB
C++
/*
|
||
/*
|
||
* UAE - The Un*x Amiga Emulator
|
||
*
|
||
* Win32 Drawing and DirectX interface
|
||
*
|
||
* Copyright 1997-1998 Mathias Ortmann
|
||
* Copyright 1997-2000 Brian King
|
||
*/
|
||
|
||
#define FORCE16BIT 0
|
||
|
||
#include "sysconfig.h"
|
||
|
||
#include <stdlib.h>
|
||
#include <stdarg.h>
|
||
|
||
#include <windows.h>
|
||
#include <commctrl.h>
|
||
#include <shellapi.h>
|
||
#include <dwmapi.h>
|
||
#include <D3dkmthk.h>
|
||
#include <process.h>
|
||
|
||
#include "sysdeps.h"
|
||
|
||
#include "resource.h"
|
||
|
||
#include "options.h"
|
||
#include "audio.h"
|
||
#include "uae.h"
|
||
#include "memory.h"
|
||
#include "custom.h"
|
||
#include "events.h"
|
||
#include "newcpu.h"
|
||
#include "traps.h"
|
||
#include "xwin.h"
|
||
#include "keyboard.h"
|
||
#include "drawing.h"
|
||
#include "render.h"
|
||
#include "picasso96_win.h"
|
||
#include "registry.h"
|
||
#include "win32.h"
|
||
#include "win32gfx.h"
|
||
#include "win32gui.h"
|
||
#include "sound.h"
|
||
#include "inputdevice.h"
|
||
#include "direct3d.h"
|
||
#include "midi.h"
|
||
#include "gui.h"
|
||
#include "serial.h"
|
||
#include "avioutput.h"
|
||
#include "gfxfilter.h"
|
||
#include "parser.h"
|
||
#include "lcd.h"
|
||
#include "sampler.h"
|
||
#include "gfxboard.h"
|
||
#include "cpuboard.h"
|
||
#include "x86.h"
|
||
#include "keybuf.h"
|
||
#ifdef RETROPLATFORM
|
||
#include "rp.h"
|
||
#endif
|
||
#include "statusline.h"
|
||
#include "devices.h"
|
||
#ifdef WITH_MIDIEMU
|
||
#include "midiemu.h"
|
||
#endif
|
||
|
||
#include "darkmode.h"
|
||
|
||
#define DM_DX_FULLSCREEN 1
|
||
#define DM_W_FULLSCREEN 2
|
||
#define DM_D3D_FULLSCREEN 16
|
||
#define DM_PICASSO96 32
|
||
#define DM_D3D 256
|
||
#define DM_SWSCALE 1024
|
||
|
||
#define SM_WINDOW 0
|
||
#define SM_FULLSCREEN_DX 2
|
||
#define SM_D3D_WINDOW 5
|
||
#define SM_D3D_FULLWINDOW 10
|
||
#define SM_D3D_FULLSCREEN_DX 6
|
||
#define SM_FULLWINDOW 7
|
||
#define SM_NONE 11
|
||
|
||
static int deskhz;
|
||
|
||
struct MultiDisplay Displays[MAX_DISPLAYS + 1];
|
||
|
||
struct AmigaMonitor AMonitors[MAX_AMIGAMONITORS];
|
||
struct AmigaMonitor *amon = NULL;
|
||
|
||
static int display_change_requested;
|
||
int window_led_drives, window_led_drives_end;
|
||
int window_led_hd, window_led_hd_end;
|
||
int window_led_joys, window_led_joys_end, window_led_joy_start;
|
||
int window_led_msg, window_led_msg_end, window_led_msg_start;
|
||
extern int console_logging;
|
||
|
||
static int wasfullwindow_a, wasfullwindow_p;
|
||
|
||
int vsync_modechangetimeout = 10;
|
||
|
||
int vsync_activeheight, vsync_totalheight;
|
||
float vsync_vblank, vsync_hblank;
|
||
bool beamracer_debug;
|
||
bool gfx_hdr;
|
||
|
||
int reopen(struct AmigaMonitor *, int, bool);
|
||
|
||
static CRITICAL_SECTION screen_cs;
|
||
static bool screen_cs_allocated;
|
||
|
||
void gfx_lock (void)
|
||
{
|
||
EnterCriticalSection (&screen_cs);
|
||
}
|
||
void gfx_unlock (void)
|
||
{
|
||
LeaveCriticalSection (&screen_cs);
|
||
}
|
||
|
||
int WIN32GFX_IsPicassoScreen(struct AmigaMonitor *mon)
|
||
{
|
||
return mon->screen_is_picasso ? 1 : 0;
|
||
}
|
||
|
||
static int isscreen(struct AmigaMonitor *mon)
|
||
{
|
||
return mon->hMainWnd ? 1 : 0;
|
||
}
|
||
|
||
static int isfullscreen_2(struct uae_prefs *p)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[0];
|
||
int idx = mon->screen_is_picasso ? 1 : 0;
|
||
return p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLSCREEN ? 1 : (p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLWINDOW ? -1 : 0);
|
||
}
|
||
int isfullscreen(void)
|
||
{
|
||
return isfullscreen_2(&currprefs);
|
||
}
|
||
|
||
int WIN32GFX_GetDepth(struct AmigaMonitor *mon, int real)
|
||
{
|
||
if (!mon->currentmode.native_depth)
|
||
return mon->currentmode.current_depth;
|
||
return real ? mon->currentmode.native_depth : mon->currentmode.current_depth;
|
||
}
|
||
|
||
int WIN32GFX_GetWidth(struct AmigaMonitor *mon)
|
||
{
|
||
return mon->currentmode.current_width;
|
||
}
|
||
|
||
int WIN32GFX_GetHeight(struct AmigaMonitor *mon)
|
||
{
|
||
return mon->currentmode.current_height;
|
||
}
|
||
|
||
static BOOL doInit (struct AmigaMonitor*);
|
||
|
||
int default_freq = 60;
|
||
|
||
static uae_u8 *scrlinebuf;
|
||
|
||
|
||
static struct MultiDisplay *getdisplay2(struct uae_prefs *p, int index)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[0];
|
||
static int max;
|
||
int display = index < 0 ? p->gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display - 1 : index;
|
||
|
||
if (!max || (max > 0 && Displays[max].monitorname != NULL)) {
|
||
max = 0;
|
||
while (Displays[max].monitorname)
|
||
max++;
|
||
if (max == 0) {
|
||
gui_message(_T("no display adapters! Exiting"));
|
||
exit(0);
|
||
}
|
||
}
|
||
if (index >= 0 && display >= max)
|
||
return NULL;
|
||
if (display >= max)
|
||
display = 0;
|
||
if (display < 0)
|
||
display = 0;
|
||
return &Displays[display];
|
||
}
|
||
struct MultiDisplay *getdisplay(struct uae_prefs *p, int monid)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
if (monid > 0 && mon->md)
|
||
return mon->md;
|
||
return getdisplay2(p, -1);
|
||
}
|
||
|
||
void desktop_coords(int monid, int *dw, int *dh, int *ax, int *ay, int *aw, int *ah)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct MultiDisplay *md = getdisplay(&currprefs, monid);
|
||
|
||
*dw = md->rect.right - md->rect.left;
|
||
*dh = md->rect.bottom - md->rect.top;
|
||
*ax = mon->amigawin_rect.left;
|
||
*ay = mon->amigawin_rect.top;
|
||
*aw = mon->amigawin_rect.right - *ax;
|
||
*ah = mon->amigawin_rect.bottom - *ay;
|
||
}
|
||
|
||
static int target_get_display2(const TCHAR *name, int mode)
|
||
{
|
||
int found, found2;
|
||
|
||
found = -1;
|
||
found2 = -1;
|
||
for (int i = 0; Displays[i].monitorname; i++) {
|
||
struct MultiDisplay *md = &Displays[i];
|
||
if (mode == 1 && md->monitorid[0] == '\\')
|
||
continue;
|
||
if (mode == 2 && md->monitorid[0] != '\\')
|
||
continue;
|
||
if (!_tcscmp (md->monitorid, name)) {
|
||
if (found < 0) {
|
||
found = i + 1;
|
||
} else {
|
||
found2 = found;
|
||
found = -1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (found >= 0)
|
||
return found;
|
||
|
||
found = -1;
|
||
for (int i = 0; Displays[i].monitorname; i++) {
|
||
struct MultiDisplay *md = &Displays[i];
|
||
if (mode == 1 && md->adapterid[0] == '\\')
|
||
continue;
|
||
if (mode == 2 && md->adapterid[0] != '\\')
|
||
continue;
|
||
if (!_tcscmp (md->adapterid, name)) {
|
||
if (found < 0) {
|
||
found = i + 1;
|
||
} else {
|
||
if (found2 < 0)
|
||
found2 = found;
|
||
found = -1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (found >= 0)
|
||
return found;
|
||
|
||
for (int i = 0; Displays[i].monitorname; i++) {
|
||
struct MultiDisplay *md = &Displays[i];
|
||
if (mode == 1 && md->adaptername[0] == '\\')
|
||
continue;
|
||
if (mode == 2 && md->adaptername[0] != '\\')
|
||
continue;
|
||
if (!_tcscmp (md->adaptername, name)) {
|
||
if (found < 0) {
|
||
found = i + 1;
|
||
} else {
|
||
if (found2 < 0)
|
||
found2 = found;
|
||
found = -1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (found >= 0)
|
||
return found;
|
||
|
||
for (int i = 0; Displays[i].monitorname; i++) {
|
||
struct MultiDisplay *md = &Displays[i];
|
||
if (mode == 1 && md->monitorname[0] == '\\')
|
||
continue;
|
||
if (mode == 2 && md->monitorname[0] != '\\')
|
||
continue;
|
||
if (!_tcscmp (md->monitorname, name)) {
|
||
if (found < 0) {
|
||
found = i + 1;
|
||
} else {
|
||
if (found2 < 0)
|
||
found2 = found;
|
||
found = -1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (found >= 0)
|
||
return found;
|
||
if (mode == 3) {
|
||
if (found2 >= 0)
|
||
return found2;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int target_get_display(const TCHAR *name)
|
||
{
|
||
int disp;
|
||
|
||
//write_log(_T("target_get_display '%s'\n"), name);
|
||
disp = target_get_display2(name, 0);
|
||
//write_log(_T("Scan 0: %d\n"), disp);
|
||
if (disp >= 0)
|
||
return disp;
|
||
disp = target_get_display2(name, 1);
|
||
//write_log(_T("Scan 1: %d\n"), disp);
|
||
if (disp >= 0)
|
||
return disp;
|
||
disp = target_get_display2(name, 2);
|
||
//write_log(_T("Scan 2: %d\n"), disp);
|
||
if (disp >= 0)
|
||
return disp;
|
||
disp = target_get_display2(name, 3);
|
||
//write_log(_T("Scan 3: %d\n"), disp);
|
||
if (disp >= 0)
|
||
return disp;
|
||
return -1;
|
||
}
|
||
|
||
static volatile int waitvblankthread_mode;
|
||
HANDLE waitvblankevent;
|
||
static frame_time_t wait_vblank_timestamp;
|
||
static MultiDisplay *wait_vblank_display;
|
||
static volatile bool vsync_active;
|
||
static bool scanlinecalibrating;
|
||
|
||
typedef NTSTATUS(CALLBACK* D3DKMTOPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
|
||
static D3DKMTOPENADAPTERFROMHDC pD3DKMTOpenAdapterFromHdc;
|
||
typedef NTSTATUS(CALLBACK* D3DKMTGETSCANLINE)(D3DKMT_GETSCANLINE*);
|
||
static D3DKMTGETSCANLINE pD3DKMTGetScanLine;
|
||
typedef NTSTATUS(CALLBACK* D3DKMTWAITFORVERTICALBLANKEVENT)(const D3DKMT_WAITFORVERTICALBLANKEVENT*);
|
||
static D3DKMTWAITFORVERTICALBLANKEVENT pD3DKMTWaitForVerticalBlankEvent;
|
||
#define STATUS_SUCCESS ((NTSTATUS)0)
|
||
|
||
static int target_get_display_scanline2(int displayindex)
|
||
{
|
||
if (pD3DKMTGetScanLine) {
|
||
D3DKMT_GETSCANLINE sl = { 0 };
|
||
struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs, 0) : &Displays[displayindex];
|
||
if (!md->HasAdapterData)
|
||
return -11;
|
||
sl.VidPnSourceId = md->VidPnSourceId;
|
||
sl.hAdapter = md->AdapterHandle;
|
||
NTSTATUS status = pD3DKMTGetScanLine(&sl);
|
||
if (status == STATUS_SUCCESS) {
|
||
if (sl.InVerticalBlank)
|
||
return -1;
|
||
return sl.ScanLine;
|
||
} else {
|
||
if ((int)status > 0)
|
||
return -(int)status;
|
||
return status;
|
||
}
|
||
return -12;
|
||
} else if (D3D_getscanline) {
|
||
int scanline;
|
||
bool invblank;
|
||
if (D3D_getscanline(&scanline, &invblank)) {
|
||
if (invblank)
|
||
return -1;
|
||
return scanline;
|
||
}
|
||
return -14;
|
||
}
|
||
return -13;
|
||
}
|
||
|
||
extern uae_s64 spincount;
|
||
bool calculated_scanline = true;
|
||
|
||
int target_get_display_scanline(int displayindex)
|
||
{
|
||
if (!scanlinecalibrating && calculated_scanline) {
|
||
static int lastline;
|
||
float diff = (float)(read_processor_time() - wait_vblank_timestamp);
|
||
if (diff < 0)
|
||
return -1;
|
||
int sl = (int)(diff * (vsync_activeheight + (vsync_totalheight - vsync_activeheight) / 10) * vsync_vblank / syncbase);
|
||
if (sl < 0)
|
||
sl = -1;
|
||
return sl;
|
||
} else {
|
||
static uae_s64 lastrdtsc;
|
||
static int lastvpos;
|
||
if (spincount == 0 || currprefs.m68k_speed >= 0) {
|
||
lastrdtsc = 0;
|
||
lastvpos = target_get_display_scanline2(displayindex);
|
||
return lastvpos;
|
||
}
|
||
uae_s64 v = read_processor_time_rdtsc();
|
||
if (lastrdtsc > v)
|
||
return lastvpos;
|
||
lastvpos = target_get_display_scanline2(displayindex);
|
||
lastrdtsc = read_processor_time_rdtsc() + spincount * 4;
|
||
return lastvpos;
|
||
}
|
||
}
|
||
|
||
typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*);
|
||
typedef LONG(CALLBACK* GETDISPLAYCONFIGBUFFERSIZES)(UINT32, UINT32*, UINT32*);
|
||
typedef LONG(CALLBACK* DISPLAYCONFIGGETDEVICEINFO)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);
|
||
|
||
static bool get_display_vblank_params(int displayindex, int *activeheightp, int *totalheightp, float *vblankp, float *hblankp)
|
||
{
|
||
static QUERYDISPLAYCONFIG pQueryDisplayConfig;
|
||
static GETDISPLAYCONFIGBUFFERSIZES pGetDisplayConfigBufferSizes;
|
||
static DISPLAYCONFIGGETDEVICEINFO pDisplayConfigGetDeviceInfo;
|
||
if (!pQueryDisplayConfig)
|
||
pQueryDisplayConfig = (QUERYDISPLAYCONFIG)GetProcAddress(userdll, "QueryDisplayConfig");
|
||
if (!pGetDisplayConfigBufferSizes)
|
||
pGetDisplayConfigBufferSizes = (GETDISPLAYCONFIGBUFFERSIZES)GetProcAddress(userdll, "GetDisplayConfigBufferSizes");
|
||
if (!pDisplayConfigGetDeviceInfo)
|
||
pDisplayConfigGetDeviceInfo = (DISPLAYCONFIGGETDEVICEINFO)GetProcAddress(userdll, "DisplayConfigGetDeviceInfo");
|
||
if (!pQueryDisplayConfig || !pGetDisplayConfigBufferSizes || !pDisplayConfigGetDeviceInfo)
|
||
return false;
|
||
struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs, 0) : &Displays[displayindex];
|
||
UINT32 pathCount, modeCount;
|
||
bool ret = false;
|
||
if (pGetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount) == ERROR_SUCCESS) {
|
||
DISPLAYCONFIG_PATH_INFO *displayPaths;
|
||
DISPLAYCONFIG_MODE_INFO *displayModes;
|
||
displayPaths = xmalloc(DISPLAYCONFIG_PATH_INFO, pathCount);
|
||
displayModes = xmalloc(DISPLAYCONFIG_MODE_INFO, modeCount);
|
||
if (pQueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, displayPaths, &modeCount, displayModes, NULL) == ERROR_SUCCESS) {
|
||
for (int i = 0; i < pathCount; i++) {
|
||
DISPLAYCONFIG_PATH_INFO *path = &displayPaths[i];
|
||
DISPLAYCONFIG_MODE_INFO *target = &displayModes[path->targetInfo.modeInfoIdx];
|
||
DISPLAYCONFIG_MODE_INFO *source = &displayModes[path->sourceInfo.modeInfoIdx];
|
||
DISPLAYCONFIG_SOURCE_DEVICE_NAME dcsdn;
|
||
DISPLAYCONFIG_DEVICE_INFO_HEADER *dcdih = &dcsdn.header;
|
||
dcdih->size = sizeof dcsdn;
|
||
dcdih->adapterId = source->adapterId;
|
||
dcdih->id = source->id;
|
||
dcdih->type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||
if (pDisplayConfigGetDeviceInfo(dcdih) == ERROR_SUCCESS) {
|
||
if (!_tcscmp(md->adapterid, dcsdn.viewGdiDeviceName)) {
|
||
DISPLAYCONFIG_VIDEO_SIGNAL_INFO *si = &target->targetMode.targetVideoSignalInfo;
|
||
if (activeheightp)
|
||
*activeheightp = si->activeSize.cy;
|
||
if (totalheightp)
|
||
*totalheightp = si->totalSize.cy;
|
||
float vblank = (float)si->vSyncFreq.Numerator / si->vSyncFreq.Denominator;
|
||
float hblank = (float)si->hSyncFreq.Numerator / si->hSyncFreq.Denominator;
|
||
if (vblankp)
|
||
*vblankp = vblank;
|
||
if (hblankp)
|
||
*hblankp = hblank;
|
||
write_log(_T("ActiveHeight: %d TotalHeight: %d VFreq=%d/%d=%.2fHz HFreq=%d/%d=%.3fKHz\n"),
|
||
target->targetMode.targetVideoSignalInfo.activeSize.cy,
|
||
target->targetMode.targetVideoSignalInfo.totalSize.cy,
|
||
target->targetMode.targetVideoSignalInfo.vSyncFreq.Numerator,
|
||
target->targetMode.targetVideoSignalInfo.vSyncFreq.Denominator,
|
||
vblank,
|
||
target->targetMode.targetVideoSignalInfo.hSyncFreq.Numerator,
|
||
target->targetMode.targetVideoSignalInfo.hSyncFreq.Denominator,
|
||
hblank / 1000.0);
|
||
ret = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
xfree(displayModes);
|
||
xfree(displayPaths);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
static unsigned int __stdcall waitvblankthread(void *dummy)
|
||
{
|
||
waitvblankthread_mode = 2;
|
||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
|
||
while (waitvblankthread_mode) {
|
||
D3DKMT_WAITFORVERTICALBLANKEVENT e = { 0 };
|
||
e.hAdapter = wait_vblank_display->AdapterHandle;
|
||
e.VidPnSourceId = wait_vblank_display->VidPnSourceId;
|
||
pD3DKMTWaitForVerticalBlankEvent(&e);
|
||
wait_vblank_timestamp = read_processor_time();
|
||
vsync_active = true;
|
||
SetEvent(waitvblankevent);
|
||
}
|
||
waitvblankthread_mode = -1;
|
||
return 0;
|
||
}
|
||
|
||
static void display_vblank_thread_kill(void)
|
||
{
|
||
if (waitvblankthread_mode == 2) {
|
||
waitvblankthread_mode = 0;
|
||
while (waitvblankthread_mode != -1) {
|
||
Sleep(10);
|
||
}
|
||
waitvblankthread_mode = 0;
|
||
CloseHandle(waitvblankevent);
|
||
waitvblankevent = NULL;
|
||
}
|
||
}
|
||
|
||
static void display_vblank_thread(struct AmigaMonitor *mon)
|
||
{
|
||
struct amigadisplay *ad = &adisplays[mon->monitor_id];
|
||
struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
|
||
|
||
if (waitvblankthread_mode > 0)
|
||
return;
|
||
// It seems some Windows 7 drivers stall if D3DKMTWaitForVerticalBlankEvent()
|
||
// and D3DKMTGetScanLine() is used simultaneously.
|
||
if ((calculated_scanline || os_win8) && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display && wait_vblank_display->HasAdapterData) {
|
||
waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||
waitvblankthread_mode = 1;
|
||
unsigned int th;
|
||
_beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th);
|
||
} else {
|
||
calculated_scanline = false;
|
||
}
|
||
}
|
||
|
||
void target_cpu_speed(void)
|
||
{
|
||
display_vblank_thread(&AMonitors[0]);
|
||
}
|
||
|
||
extern void target_calibrate_spin(void);
|
||
static void display_param_init(struct AmigaMonitor *mon)
|
||
{
|
||
struct amigadisplay *ad = &adisplays[mon->monitor_id];
|
||
struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
|
||
|
||
vsync_activeheight = mon->currentmode.current_height;
|
||
vsync_totalheight = vsync_activeheight * 1125 / 1080;
|
||
vsync_vblank = 0;
|
||
vsync_hblank = 0;
|
||
get_display_vblank_params(-1, &vsync_activeheight, &vsync_totalheight, &vsync_vblank, &vsync_hblank);
|
||
if (vsync_vblank <= 0)
|
||
vsync_vblank = (float)mon->currentmode.freq;
|
||
// GPU scaled mode?
|
||
if (vsync_activeheight > mon->currentmode.current_height) {
|
||
float m = (float)vsync_activeheight / mon->currentmode.current_height;
|
||
vsync_hblank = vsync_hblank / m + 0.5f;
|
||
vsync_activeheight = mon->currentmode.current_height;
|
||
}
|
||
|
||
wait_vblank_display = getdisplay(&currprefs, mon->monitor_id);
|
||
if (!wait_vblank_display || !wait_vblank_display->HasAdapterData) {
|
||
write_log(_T("Selected display mode does not have adapter data!\n"));
|
||
}
|
||
scanlinecalibrating = true;
|
||
target_calibrate_spin();
|
||
scanlinecalibrating = false;
|
||
display_vblank_thread(mon);
|
||
}
|
||
|
||
const TCHAR *target_get_display_name (int num, bool friendlyname)
|
||
{
|
||
if (num <= 0)
|
||
return NULL;
|
||
struct MultiDisplay *md = getdisplay2(NULL, num - 1);
|
||
if (!md)
|
||
return NULL;
|
||
if (friendlyname)
|
||
return md->monitorname;
|
||
return md->monitorid;
|
||
}
|
||
|
||
void centerdstrect(struct AmigaMonitor *mon, RECT *dr)
|
||
{
|
||
struct uae_filter *usedfilter = mon->usedfilter;
|
||
if(!(mon->currentmode.flags & (DM_DX_FULLSCREEN | DM_D3D_FULLSCREEN | DM_W_FULLSCREEN)))
|
||
OffsetRect (dr, mon->amigawin_rect.left, mon->amigawin_rect.top);
|
||
if (mon->currentmode.flags & DM_W_FULLSCREEN) {
|
||
if (mon->scalepicasso && mon->screen_is_picasso)
|
||
return;
|
||
if (usedfilter && !mon->screen_is_picasso)
|
||
return;
|
||
if (mon->currentmode.fullfill && (mon->currentmode.current_width > mon->currentmode.native_width || mon->currentmode.current_height > mon->currentmode.native_height))
|
||
return;
|
||
OffsetRect (dr, (mon->currentmode.native_width - mon->currentmode.current_width) / 2,
|
||
(mon->currentmode.native_height - mon->currentmode.current_height) / 2);
|
||
}
|
||
}
|
||
|
||
static int picasso_offset_x, picasso_offset_y;
|
||
static float picasso_offset_mx, picasso_offset_my;
|
||
|
||
void getgfxoffset(int monid, float *dxp, float *dyp, float *mxp, float *myp)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
struct uae_filter *usedfilter = mon->usedfilter;
|
||
float dx, dy, mx, my;
|
||
|
||
getfilteroffset(monid, &dx, &dy, &mx, &my);
|
||
if (ad->picasso_on) {
|
||
dx = picasso_offset_x * picasso_offset_mx;
|
||
dy = picasso_offset_y * picasso_offset_my;
|
||
mx = picasso_offset_mx;
|
||
my = picasso_offset_my;
|
||
}
|
||
|
||
//write_log(_T("%.2fx%.2f %.2fx%.2f\n"), dx, dy, mx, my);
|
||
|
||
if (mon->currentmode.flags & DM_W_FULLSCREEN) {
|
||
for (;;) {
|
||
if (mon->scalepicasso && mon->screen_is_picasso)
|
||
break;
|
||
if (usedfilter && !mon->screen_is_picasso)
|
||
break;
|
||
if (mon->currentmode.fullfill && (mon->currentmode.current_width > mon->currentmode.native_width || mon->currentmode.current_height > mon->currentmode.native_height))
|
||
break;
|
||
dx += (mon->currentmode.native_width - mon->currentmode.current_width) / 2;
|
||
dy += (mon->currentmode.native_height - mon->currentmode.current_height) / 2;
|
||
break;
|
||
}
|
||
}
|
||
|
||
*dxp = dx;
|
||
*dyp = dy;
|
||
*mxp = 1.0f / mx;
|
||
*myp = 1.0f / my;
|
||
}
|
||
|
||
static int rgbformat_bits (RGBFTYPE t)
|
||
{
|
||
unsigned long f = 1 << t;
|
||
return ((f & RGBMASK_8BIT) != 0 ? 8
|
||
: (f & RGBMASK_15BIT) != 0 ? 15
|
||
: (f & RGBMASK_16BIT) != 0 ? 16
|
||
: (f & RGBMASK_24BIT) != 0 ? 24
|
||
: (f & RGBMASK_32BIT) != 0 ? 32
|
||
: 0);
|
||
}
|
||
|
||
int getrefreshrate(int monid, int width, int height)
|
||
{
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[APMODE_RTG] : &currprefs.gfx_apmode[APMODE_NATIVE];
|
||
int freq = 0;
|
||
|
||
if (ap->gfx_refreshrate <= 0)
|
||
return 0;
|
||
|
||
struct MultiDisplay *md = getdisplay(&currprefs, monid);
|
||
for (int i = 0; md->DisplayModes[i].depth >= 0; i++) {
|
||
struct PicassoResolution *pr = &md->DisplayModes[i];
|
||
if (pr->res.width == width && pr->res.height == height) {
|
||
for (int j = 0; pr->refresh[j] > 0; j++) {
|
||
if (pr->refresh[j] == ap->gfx_refreshrate)
|
||
return ap->gfx_refreshrate;
|
||
if (pr->refresh[j] > freq && pr->refresh[j] < ap->gfx_refreshrate)
|
||
freq = pr->refresh[j];
|
||
}
|
||
}
|
||
}
|
||
write_log (_T("Refresh rate %d not supported, using %d\n"), ap->gfx_refreshrate, freq);
|
||
return freq;
|
||
}
|
||
|
||
static void addmode (struct MultiDisplay *md, DEVMODE *dm, int rawmode)
|
||
{
|
||
int ct;
|
||
int i, j;
|
||
int w = dm->dmPelsWidth;
|
||
int h = dm->dmPelsHeight;
|
||
int d = dm->dmBitsPerPel;
|
||
bool lace = false;
|
||
int freq = 0;
|
||
|
||
if (w > max_uae_width || h > max_uae_height) {
|
||
write_log (_T("Ignored mode %d*%d\n"), w, h);
|
||
return;
|
||
}
|
||
|
||
if (dm->dmFields & DM_DISPLAYFREQUENCY) {
|
||
freq = dm->dmDisplayFrequency;
|
||
if (freq < 10)
|
||
freq = 0;
|
||
}
|
||
if (dm->dmFields & DM_DISPLAYFLAGS) {
|
||
lace = (dm->dmDisplayFlags & DM_INTERLACED) != 0;
|
||
}
|
||
|
||
ct = 0;
|
||
if (d == 8)
|
||
ct = RGBMASK_8BIT;
|
||
if (d == 15)
|
||
ct = RGBMASK_15BIT;
|
||
if (d == 16)
|
||
ct = RGBMASK_16BIT;
|
||
if (d == 24)
|
||
ct = RGBMASK_24BIT;
|
||
if (d == 32)
|
||
ct = RGBMASK_32BIT;
|
||
if (ct == 0)
|
||
return;
|
||
d /= 8;
|
||
i = 0;
|
||
while (md->DisplayModes[i].depth >= 0) {
|
||
if (md->DisplayModes[i].depth == d && md->DisplayModes[i].res.width == w && md->DisplayModes[i].res.height == h) {
|
||
for (j = 0; j < MAX_REFRESH_RATES; j++) {
|
||
if (md->DisplayModes[i].refresh[j] == 0 || md->DisplayModes[i].refresh[j] == freq)
|
||
break;
|
||
}
|
||
if (j < MAX_REFRESH_RATES) {
|
||
md->DisplayModes[i].refresh[j] = freq;
|
||
md->DisplayModes[i].refreshtype[j] = (lace ? REFRESH_RATE_LACE : 0) | (rawmode ? REFRESH_RATE_RAW : 0);
|
||
md->DisplayModes[i].refresh[j + 1] = 0;
|
||
if (!lace)
|
||
md->DisplayModes[i].lace = false;
|
||
return;
|
||
}
|
||
}
|
||
i++;
|
||
}
|
||
i = 0;
|
||
while (md->DisplayModes[i].depth >= 0)
|
||
i++;
|
||
if (i >= MAX_PICASSO_MODES - 1)
|
||
return;
|
||
md->DisplayModes[i].rawmode = rawmode;
|
||
md->DisplayModes[i].lace = lace;
|
||
md->DisplayModes[i].res.width = w;
|
||
md->DisplayModes[i].res.height = h;
|
||
md->DisplayModes[i].depth = d;
|
||
md->DisplayModes[i].refresh[0] = freq;
|
||
md->DisplayModes[i].refreshtype[0] = (lace ? REFRESH_RATE_LACE : 0) | (rawmode ? REFRESH_RATE_RAW : 0);
|
||
md->DisplayModes[i].refresh[1] = 0;
|
||
md->DisplayModes[i].colormodes = ct;
|
||
md->DisplayModes[i + 1].depth = -1;
|
||
_stprintf (md->DisplayModes[i].name, _T("%dx%d%s, %d-bit"),
|
||
md->DisplayModes[i].res.width, md->DisplayModes[i].res.height,
|
||
lace ? _T("i") : _T(""),
|
||
md->DisplayModes[i].depth * 8);
|
||
}
|
||
|
||
static int _cdecl resolution_compare (const void *a, const void *b)
|
||
{
|
||
struct PicassoResolution *ma = (struct PicassoResolution *)a;
|
||
struct PicassoResolution *mb = (struct PicassoResolution *)b;
|
||
if (ma->res.width < mb->res.width)
|
||
return -1;
|
||
if (ma->res.width > mb->res.width)
|
||
return 1;
|
||
if (ma->res.height < mb->res.height)
|
||
return -1;
|
||
if (ma->res.height > mb->res.height)
|
||
return 1;
|
||
return ma->depth - mb->depth;
|
||
}
|
||
|
||
static void sortmodes (struct MultiDisplay *md)
|
||
{
|
||
int i, idx = -1;
|
||
int pw = -1, ph = -1;
|
||
|
||
i = 0;
|
||
while (md->DisplayModes[i].depth >= 0)
|
||
i++;
|
||
qsort (md->DisplayModes, i, sizeof (struct PicassoResolution), resolution_compare);
|
||
for (i = 0; md->DisplayModes[i].depth >= 0; i++) {
|
||
int j, k;
|
||
for (j = 0; md->DisplayModes[i].refresh[j]; j++) {
|
||
for (k = j + 1; md->DisplayModes[i].refresh[k]; k++) {
|
||
if (md->DisplayModes[i].refresh[j] > md->DisplayModes[i].refresh[k]) {
|
||
int t = md->DisplayModes[i].refresh[j];
|
||
md->DisplayModes[i].refresh[j] = md->DisplayModes[i].refresh[k];
|
||
md->DisplayModes[i].refresh[k] = t;
|
||
t = md->DisplayModes[i].refreshtype[j];
|
||
md->DisplayModes[i].refreshtype[j] = md->DisplayModes[i].refreshtype[k];
|
||
md->DisplayModes[i].refreshtype[k] = t;
|
||
}
|
||
}
|
||
}
|
||
if (md->DisplayModes[i].res.height != ph || md->DisplayModes[i].res.width != pw) {
|
||
ph = md->DisplayModes[i].res.height;
|
||
pw = md->DisplayModes[i].res.width;
|
||
idx++;
|
||
}
|
||
md->DisplayModes[i].residx = idx;
|
||
}
|
||
}
|
||
|
||
#if 0
|
||
static void sortmonitors (void)
|
||
{
|
||
for (int i = 0; Displays[i].monitorid; i++) {
|
||
for (int j = i + 1; Displays[j].monitorid; j++) {
|
||
int comp = (Displays[j].primary ? 1 : 0) - (Displays[i].primary ? 1 : 0);
|
||
if (!comp)
|
||
comp = _tcsicmp (Displays[i].adapterid, Displays[j].adapterid);
|
||
if (comp > 0) {
|
||
struct MultiDisplay md;
|
||
memcpy (&md, &Displays[i], sizeof MultiDisplay);
|
||
memcpy (&Displays[i], &Displays[j], sizeof MultiDisplay);
|
||
memcpy (&Displays[j], &md, sizeof MultiDisplay);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
static void modesList (struct MultiDisplay *md)
|
||
{
|
||
int i, j;
|
||
|
||
i = 0;
|
||
while (md->DisplayModes[i].depth >= 0) {
|
||
write_log (_T("%d: %s%s ("), i, md->DisplayModes[i].rawmode ? _T("!") : _T(""), md->DisplayModes[i].name);
|
||
j = 0;
|
||
while (md->DisplayModes[i].refresh[j] > 0) {
|
||
if (j > 0)
|
||
write_log (_T(","));
|
||
if (md->DisplayModes[i].refreshtype[j] & REFRESH_RATE_RAW)
|
||
write_log (_T("!"));
|
||
write_log (_T("%d"), md->DisplayModes[i].refresh[j]);
|
||
if (md->DisplayModes[i].refreshtype[j] & REFRESH_RATE_LACE)
|
||
write_log (_T("i"));
|
||
j++;
|
||
}
|
||
write_log (_T(")\n"));
|
||
i++;
|
||
}
|
||
}
|
||
|
||
static void adjustappbar(RECT *monitor, RECT *workrect)
|
||
{
|
||
APPBARDATA abd;
|
||
// Isn't this ugly API?
|
||
for (int i = 0; i < 4; i++) {
|
||
abd.cbSize = sizeof abd;
|
||
abd.rc = *monitor;
|
||
abd.uEdge = i; // ABE_LEFT, TOP, RIGHT, BOTTOM
|
||
HWND hwndAutoHide = (HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAREX, &abd);
|
||
if (hwndAutoHide == NULL)
|
||
continue;
|
||
WINDOWINFO wi;
|
||
wi.cbSize = sizeof wi;
|
||
if (!GetWindowInfo(hwndAutoHide, &wi))
|
||
continue;
|
||
int edge;
|
||
switch (i)
|
||
{
|
||
case ABE_LEFT:
|
||
edge = monitor->left + (wi.rcWindow.right - wi.rcWindow.left);
|
||
if (edge > workrect->left && edge < workrect->right)
|
||
workrect->left = edge;
|
||
break;
|
||
case ABE_RIGHT:
|
||
edge = monitor->right - (wi.rcWindow.right - wi.rcWindow.left);
|
||
if (edge < workrect->right && edge > workrect->left)
|
||
workrect->right = edge;
|
||
break;
|
||
case ABE_TOP:
|
||
edge = monitor->top + (wi.rcWindow.bottom - wi.rcWindow.top);
|
||
if (edge > workrect->top && edge < workrect->bottom)
|
||
workrect->top = edge;
|
||
break;
|
||
case ABE_BOTTOM:
|
||
edge = monitor->bottom - (wi.rcWindow.bottom - wi.rcWindow.top);
|
||
if (edge < workrect->bottom && edge > workrect->top)
|
||
workrect->bottom = edge;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static BOOL CALLBACK monitorEnumProc (HMONITOR h, HDC hdc, LPRECT rect, LPARAM data)
|
||
{
|
||
struct MultiDisplay *md = Displays;
|
||
MONITORINFOEX lpmi;
|
||
lpmi.cbSize = sizeof lpmi;
|
||
GetMonitorInfo(h, (LPMONITORINFO)&lpmi);
|
||
while (md - Displays < MAX_DISPLAYS && md->monitorid) {
|
||
if (!_tcscmp (md->adapterid, lpmi.szDevice)) {
|
||
TCHAR tmp[1000];
|
||
md->monitor = h;
|
||
md->rect = lpmi.rcMonitor;
|
||
md->workrect = lpmi.rcWork;
|
||
adjustappbar(&md->rect, &md->workrect);
|
||
if (md->rect.left == 0 && md->rect.top == 0)
|
||
_stprintf (tmp, _T("%s (%d*%d)"), md->monitorname, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top);
|
||
else
|
||
_stprintf (tmp, _T("%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);
|
||
if (md->primary)
|
||
_tcscat (tmp, _T(" *"));
|
||
xfree (md->fullname);
|
||
md->fullname = my_strdup (tmp);
|
||
return TRUE;
|
||
}
|
||
md++;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
static BOOL CALLBACK monitorEnumProc2(HMONITOR h, HDC hdc, LPRECT rect, LPARAM data)
|
||
{
|
||
MONITORINFOEX lpmi;
|
||
lpmi.cbSize = sizeof lpmi;
|
||
GetMonitorInfo(h, (LPMONITORINFO)&lpmi);
|
||
for (int i = 0; i < MAX_DISPLAYS && Displays[i].monitorid; i++) {
|
||
struct MultiDisplay *md = &Displays[i];
|
||
if (!_tcscmp (md->adapterid, lpmi.szDevice) && !memcmp(&md->rect, &lpmi.rcMonitor, sizeof RECT)) {
|
||
md->workrect = lpmi.rcWork;
|
||
md->monitor = h;
|
||
adjustappbar(&md->rect, &md->workrect);
|
||
return TRUE;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
void reenumeratemonitors(void)
|
||
{
|
||
for (int i = 0; i < MAX_DISPLAYS; i++) {
|
||
struct MultiDisplay *md = &Displays[i];
|
||
memcpy(&md->workrect, &md->rect, sizeof RECT);
|
||
}
|
||
EnumDisplayMonitors (NULL, NULL, monitorEnumProc2, NULL);
|
||
}
|
||
|
||
static void getd3dmonitornames (void)
|
||
{
|
||
// XP does not support hybrid displays, don't load Direct3D
|
||
// Windows 10+ seems to use same names by default
|
||
if (os_win10)
|
||
return;
|
||
IDirect3D9 *d3d = Direct3DCreate9 (D3D_SDK_VERSION);
|
||
if (!d3d)
|
||
return;
|
||
int max = d3d->GetAdapterCount ();
|
||
struct MultiDisplay* md = Displays;
|
||
while (md - Displays < MAX_DISPLAYS && md->monitorid) {
|
||
POINT pt;
|
||
HMONITOR winmon;
|
||
pt.x = (md->rect.right - md->rect.left) / 2 + md->rect.left;
|
||
pt.y = (md->rect.bottom - md->rect.top) / 2 + md->rect.top;
|
||
winmon = MonitorFromPoint (pt, MONITOR_DEFAULTTONEAREST);
|
||
for (int i = 0; i < max; i++) {
|
||
D3DADAPTER_IDENTIFIER9 did;
|
||
HMONITOR d3dmon = d3d->GetAdapterMonitor (i);
|
||
if (d3dmon != winmon)
|
||
continue;
|
||
if (SUCCEEDED (d3d->GetAdapterIdentifier (i, 0, &did))) {
|
||
TCHAR *name = au (did.Description);
|
||
my_trim (name);
|
||
if (_tcsicmp (name, md->adaptername)) {
|
||
write_log (_T("%d: '%s' -> '%s'\n"), i, md->adaptername, name);
|
||
xfree (md->adaptername);
|
||
md->adaptername = name;
|
||
name = NULL;
|
||
}
|
||
xfree (name);
|
||
}
|
||
break;
|
||
}
|
||
md++;
|
||
}
|
||
d3d->Release ();
|
||
}
|
||
|
||
static bool enumeratedisplays2 (bool selectall)
|
||
{
|
||
struct MultiDisplay *md = Displays;
|
||
int adapterindex = 0;
|
||
DISPLAY_DEVICE add;
|
||
add.cb = sizeof add;
|
||
while (EnumDisplayDevices (NULL, adapterindex, &add, 0)) {
|
||
|
||
adapterindex++;
|
||
if (!selectall) {
|
||
if (!(add.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
|
||
continue;
|
||
if (add.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
|
||
continue;
|
||
}
|
||
if (md - Displays >= MAX_DISPLAYS)
|
||
break;
|
||
|
||
int monitorindex = 0;
|
||
DISPLAY_DEVICE mdd;
|
||
mdd.cb = sizeof mdd;
|
||
while (EnumDisplayDevices (add.DeviceName, monitorindex, &mdd, 0)) {
|
||
monitorindex++;
|
||
if (md - Displays >= MAX_DISPLAYS)
|
||
break;
|
||
if (!selectall) {
|
||
if (!(mdd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
|
||
continue;
|
||
if (mdd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
|
||
continue;
|
||
}
|
||
md->adaptername = my_strdup_trim (add.DeviceString);
|
||
md->adapterid = my_strdup (add.DeviceName);
|
||
md->adapterkey = my_strdup (add.DeviceID);
|
||
md->monitorname = my_strdup_trim (mdd.DeviceString);
|
||
md->monitorid = my_strdup (mdd.DeviceKey);
|
||
if (add.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||
md->primary = true;
|
||
if (pD3DKMTOpenAdapterFromHdc) {
|
||
HDC hdc = CreateDC(NULL, add.DeviceName, NULL, NULL);
|
||
if (hdc != NULL) {
|
||
D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = { 0 };
|
||
OpenAdapterData.hDc = hdc;
|
||
NTSTATUS status = pD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
|
||
if (status == STATUS_SUCCESS) {
|
||
md->AdapterLuid = OpenAdapterData.AdapterLuid;
|
||
md->VidPnSourceId = OpenAdapterData.VidPnSourceId;
|
||
md->AdapterHandle = OpenAdapterData.hAdapter;
|
||
md->HasAdapterData = true;
|
||
}
|
||
DeleteDC(hdc);
|
||
}
|
||
}
|
||
|
||
md++;
|
||
}
|
||
if (md - Displays >= MAX_DISPLAYS)
|
||
return true;
|
||
if (monitorindex == 0) {
|
||
md->adaptername = my_strdup_trim (add.DeviceString);
|
||
md->adapterid = my_strdup (add.DeviceName);
|
||
md->adapterkey = my_strdup (add.DeviceID);
|
||
md->monitorname = my_strdup_trim (add.DeviceString);
|
||
md->monitorid = my_strdup (add.DeviceKey);
|
||
md->primary = true;
|
||
md++;
|
||
}
|
||
}
|
||
if (md == Displays)
|
||
return false;
|
||
EnumDisplayMonitors (NULL, NULL, monitorEnumProc, NULL);
|
||
md = Displays;
|
||
while (md->monitorname) {
|
||
if (!md->fullname)
|
||
md->fullname = my_strdup (md->adapterid);
|
||
md++;
|
||
}
|
||
getd3dmonitornames ();
|
||
//sortmonitors ();
|
||
return true;
|
||
}
|
||
void enumeratedisplays (void)
|
||
{
|
||
if (!pD3DKMTWaitForVerticalBlankEvent) {
|
||
pD3DKMTOpenAdapterFromHdc = (D3DKMTOPENADAPTERFROMHDC)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTOpenAdapterFromHdc");
|
||
pD3DKMTGetScanLine = (D3DKMTGETSCANLINE)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTGetScanLine");
|
||
pD3DKMTWaitForVerticalBlankEvent = (D3DKMTWAITFORVERTICALBLANKEVENT)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTWaitForVerticalBlankEvent");
|
||
}
|
||
if (!enumeratedisplays2 (false))
|
||
enumeratedisplays2(true);
|
||
}
|
||
|
||
void sortdisplays (void)
|
||
{
|
||
struct MultiDisplay *md;
|
||
int i, idx;
|
||
|
||
int w = GetSystemMetrics (SM_CXSCREEN);
|
||
int h = GetSystemMetrics (SM_CYSCREEN);
|
||
int wv = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||
int hv = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||
int b = 0;
|
||
|
||
deskhz = 0;
|
||
|
||
HDC hdc = GetDC (NULL);
|
||
if (hdc) {
|
||
b = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
|
||
ReleaseDC (NULL, hdc);
|
||
}
|
||
md = Displays;
|
||
while (md->monitorname) {
|
||
md->DisplayModes = xmalloc (struct PicassoResolution, MAX_PICASSO_MODES);
|
||
md->DisplayModes[0].depth = -1;
|
||
|
||
write_log (_T("%s '%s' [%s]\n"), md->adaptername, md->adapterid, md->adapterkey);
|
||
write_log (_T("-: %s [%s]\n"), md->fullname, md->monitorid);
|
||
for (int mode = 0; mode < 2; mode++) {
|
||
DEVMODE dm;
|
||
dm.dmSize = sizeof dm;
|
||
dm.dmDriverExtra = 0;
|
||
idx = 0;
|
||
while (EnumDisplaySettingsEx (md->adapterid, idx, &dm, mode ? EDS_RAWMODE : 0)) {
|
||
int found = 0;
|
||
int idx2 = 0;
|
||
while (md->DisplayModes[idx2].depth >= 0 && !found) {
|
||
struct PicassoResolution *pr = &md->DisplayModes[idx2];
|
||
if (dm.dmPelsWidth == w && dm.dmPelsHeight == h && dm.dmBitsPerPel == b) {
|
||
if (dm.dmDisplayFrequency > deskhz)
|
||
deskhz = dm.dmDisplayFrequency;
|
||
}
|
||
if (pr->res.width == dm.dmPelsWidth && pr->res.height == dm.dmPelsHeight && pr->depth == dm.dmBitsPerPel / 8) {
|
||
for (i = 0; pr->refresh[i]; i++) {
|
||
if (pr->refresh[i] == dm.dmDisplayFrequency) {
|
||
found = 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
idx2++;
|
||
}
|
||
if (!found && dm.dmBitsPerPel > 8) {
|
||
int freq = 0;
|
||
#if 0
|
||
write_log (_T("EnumDisplaySettings(%dx%dx%d %dHz %08x)\n"),
|
||
dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency, dm.dmFields);
|
||
#endif
|
||
if ((dm.dmFields & DM_PELSWIDTH) && (dm.dmFields & DM_PELSHEIGHT) && (dm.dmFields & DM_BITSPERPEL)) {
|
||
addmode (md, &dm, mode);
|
||
}
|
||
}
|
||
idx++;
|
||
}
|
||
}
|
||
//dhack();
|
||
sortmodes (md);
|
||
modesList (md);
|
||
i = 0;
|
||
while (md->DisplayModes[i].depth > 0)
|
||
i++;
|
||
write_log (_T("%d display modes.\n"), i);
|
||
md++;
|
||
}
|
||
write_log(_T("Desktop: W=%d H=%d B=%d HZ=%d. CXVS=%d CYVS=%d\n"), w, h, b, deskhz, wv, hv);
|
||
|
||
}
|
||
|
||
/* DirectX will fail with "Mode not supported" if we try to switch to a full
|
||
* screen mode that doesn't match one of the dimensions we got during enumeration.
|
||
* So try to find a best match for the given resolution in our list. */
|
||
int WIN32GFX_AdjustScreenmode (struct MultiDisplay *md, int *pwidth, int *pheight, int *ppixbits)
|
||
{
|
||
struct PicassoResolution *best;
|
||
uae_u32 selected_mask = (*ppixbits == 8 ? RGBMASK_8BIT
|
||
: *ppixbits == 15 ? RGBMASK_15BIT
|
||
: *ppixbits == 16 ? RGBMASK_16BIT
|
||
: *ppixbits == 24 ? RGBMASK_24BIT
|
||
: RGBMASK_32BIT);
|
||
int pass, i = 0, index = 0;
|
||
|
||
for (pass = 0; pass < 2; pass++) {
|
||
struct PicassoResolution *dm;
|
||
uae_u32 mask = (pass == 0
|
||
? selected_mask
|
||
: RGBMASK_8BIT | RGBMASK_15BIT | RGBMASK_16BIT | RGBMASK_24BIT | RGBMASK_32BIT); /* %%% - BERND, were you missing 15-bit here??? */
|
||
i = 0;
|
||
index = 0;
|
||
|
||
best = &md->DisplayModes[0];
|
||
dm = &md->DisplayModes[1];
|
||
|
||
while (dm->depth >= 0) {
|
||
|
||
/* do we already have supported resolution? */
|
||
if (dm->res.width == *pwidth && dm->res.height == *pheight && dm->depth == (*ppixbits / 8))
|
||
return i;
|
||
|
||
if ((dm->colormodes & mask) != 0) {
|
||
if (dm->res.width <= best->res.width && dm->res.height <= best->res.height
|
||
&& dm->res.width >= *pwidth && dm->res.height >= *pheight)
|
||
{
|
||
best = dm;
|
||
index = i;
|
||
}
|
||
if (dm->res.width >= best->res.width && dm->res.height >= best->res.height
|
||
&& dm->res.width <= *pwidth && dm->res.height <= *pheight)
|
||
{
|
||
best = dm;
|
||
index = i;
|
||
}
|
||
}
|
||
dm++;
|
||
i++;
|
||
}
|
||
if (best->res.width == *pwidth && best->res.height == *pheight) {
|
||
selected_mask = mask; /* %%% - BERND, I added this - does it make sense? Otherwise, I'd specify a 16-bit display-mode for my
|
||
Workbench (using -H 2, but SHOULD have been -H 1), and end up with an 8-bit mode instead*/
|
||
break;
|
||
}
|
||
}
|
||
*pwidth = best->res.width;
|
||
*pheight = best->res.height;
|
||
if (best->colormodes & selected_mask)
|
||
return index;
|
||
|
||
/* Ordering here is done such that 16-bit is preferred, followed by 15-bit, 8-bit, 32-bit and 24-bit */
|
||
if (best->colormodes & RGBMASK_16BIT)
|
||
*ppixbits = 16;
|
||
else if (best->colormodes & RGBMASK_15BIT) /* %%% - BERND, this possibility was missing? */
|
||
*ppixbits = 15;
|
||
else if (best->colormodes & RGBMASK_8BIT)
|
||
*ppixbits = 8;
|
||
else if (best->colormodes & RGBMASK_32BIT)
|
||
*ppixbits = 32;
|
||
else if (best->colormodes & RGBMASK_24BIT)
|
||
*ppixbits = 24;
|
||
else
|
||
index = -1;
|
||
|
||
return index;
|
||
}
|
||
|
||
#if 0
|
||
static int flushymin, flushymax;
|
||
#define FLUSH_DIFF 50
|
||
|
||
static void flushit (struct vidbuffer *vb, int lineno)
|
||
{
|
||
if (!currprefs.gfx_api)
|
||
return;
|
||
if (mon->currentmode.flags & DM_SWSCALE)
|
||
return;
|
||
if (flushymin > lineno) {
|
||
if (flushymin - lineno > FLUSH_DIFF && flushymax != 0) {
|
||
D3D_flushtexture (flushymin, flushymax);
|
||
flushymin = mon->currentmode.amiga_height;
|
||
flushymax = 0;
|
||
} else {
|
||
flushymin = lineno;
|
||
}
|
||
}
|
||
if (flushymax < lineno) {
|
||
if (lineno - flushymax > FLUSH_DIFF && flushymax != 0) {
|
||
D3D_flushtexture (flushymin, flushymax);
|
||
flushymin = mon->currentmode.amiga_height;
|
||
flushymax = 0;
|
||
} else {
|
||
flushymax = lineno;
|
||
}
|
||
}
|
||
}
|
||
|
||
void flush_line (struct vidbuffer *vb, int lineno)
|
||
{
|
||
flushit (vb, lineno);
|
||
}
|
||
|
||
void flush_block (struct vidbuffer *vb, int first, int last)
|
||
{
|
||
flushit (vb, first);
|
||
flushit (vb, last);
|
||
}
|
||
|
||
void flush_screen (struct vidbuffer *vb, int a, int b)
|
||
{
|
||
}
|
||
#endif
|
||
|
||
bool render_screen(int monid, int mode, bool immediate)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
bool v = false;
|
||
int cnt;
|
||
|
||
mon->render_ok = false;
|
||
if (ad->picasso_on || monitor_off) {
|
||
return mon->render_ok;
|
||
}
|
||
cnt = 0;
|
||
while (mon->wait_render) {
|
||
sleep_millis (1);
|
||
cnt++;
|
||
if (cnt > 500) {
|
||
return mon->render_ok;
|
||
}
|
||
}
|
||
// flushymin = 0;
|
||
// flushymax = mon->currentmode.amiga_height;
|
||
gfx_lock();
|
||
if (mon->currentmode.flags & DM_D3D) {
|
||
v = D3D_renderframe(monid, mode, immediate);
|
||
} else if (mon->currentmode.flags & DM_SWSCALE) {
|
||
S2X_render(monid, -1, -1);
|
||
v = true;
|
||
}
|
||
mon->render_ok = v;
|
||
gfx_unlock();
|
||
return mon->render_ok;
|
||
}
|
||
|
||
bool show_screen_maybe(int monid, bool show)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
|
||
if (!ap->gfx_vflip || ap->gfx_vsyncmode == 0 || ap->gfx_vsync <= 0) {
|
||
if (show)
|
||
show_screen(monid, 0);
|
||
return false;
|
||
}
|
||
#if 0
|
||
if (ap->gfx_vflip < 0) {
|
||
doflipevent ();
|
||
return true;
|
||
}
|
||
#endif
|
||
return false;
|
||
}
|
||
|
||
void show_screen_special (void)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[0];
|
||
if (!mon->screen_is_initialized)
|
||
return;
|
||
if (!D3D_showframe_special)
|
||
return;
|
||
if (mon->currentmode.flags & DM_D3D) {
|
||
gfx_lock();
|
||
D3D_showframe_special(0, 1);
|
||
gfx_unlock();
|
||
}
|
||
}
|
||
static frame_time_t strobo_time;
|
||
static volatile int strobo_active;
|
||
static volatile bool strobo_active2;
|
||
|
||
static void CALLBACK blackinsertion_cb(
|
||
UINT uTimerID,
|
||
UINT uMsg,
|
||
DWORD_PTR dwUser,
|
||
DWORD_PTR dw1,
|
||
DWORD_PTR dw2
|
||
)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[0];
|
||
if (mon->screen_is_initialized) {
|
||
if (strobo_active) {
|
||
}
|
||
|
||
while (strobo_active) {
|
||
frame_time_t ct = read_processor_time();
|
||
frame_time_t diff = strobo_time - ct;
|
||
if (diff < -vsynctimebase / 2) {
|
||
break;
|
||
}
|
||
if (diff <= 0) {
|
||
if (strobo_active) {
|
||
gfx_lock();
|
||
D3D_showframe_special(0, 1);
|
||
gfx_unlock();
|
||
}
|
||
break;
|
||
}
|
||
if (diff > vsynctimebase / 4) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
strobo_active = 0;
|
||
}
|
||
|
||
float target_adjust_vblank_hz(int monid, float hz)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
int maxrate;
|
||
if (!currprefs.lightboost_strobo)
|
||
return hz;
|
||
if (isfullscreen() > 0) {
|
||
maxrate = mon->currentmode.freq;
|
||
} else {
|
||
maxrate = deskhz;
|
||
}
|
||
double nhz = hz * 2.0;
|
||
if (nhz >= maxrate - 1 && nhz < maxrate + 1)
|
||
hz -= 0.5;
|
||
return hz;
|
||
}
|
||
|
||
void show_screen(int monid, int mode)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
strobo_active = false;
|
||
strobo_active2 = false;
|
||
struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
|
||
|
||
gfx_lock();
|
||
if (mode == 2 || mode == 3 || mode == 4) {
|
||
if ((mon->currentmode.flags & DM_D3D) && D3D_showframe_special && ap->gfx_strobo) {
|
||
if (mode == 4) {
|
||
// erase + render
|
||
D3D_showframe_special(0, 2);
|
||
D3D_showframe_special(0, 1);
|
||
} else {
|
||
// erase or render
|
||
D3D_showframe_special(0, mode == 3 ? 2 : 1);
|
||
}
|
||
}
|
||
gfx_unlock();
|
||
return;
|
||
}
|
||
if (mode >= 0 && !mon->render_ok) {
|
||
gfx_unlock();
|
||
return;
|
||
}
|
||
if (mon->currentmode.flags & DM_D3D) {
|
||
if (ap->gfx_strobo && currprefs.gfx_variable_sync) {
|
||
float vblank = vblank_hz;
|
||
int ratio = currprefs.lightboost_strobo_ratio;
|
||
int ms = (int)(1000 / vblank);
|
||
int waitms = ms * ratio / 100 - 1;
|
||
strobo_active = -1;
|
||
strobo_time = read_processor_time() + vsynctimebase * ratio / 100;
|
||
timeSetEvent(waitms, 0, blackinsertion_cb, NULL, TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
|
||
}
|
||
#if 0
|
||
if (ap->gfx_vsync < 0 && ap->gfx_strobo && currprefs.gfx_api < 2) {
|
||
float vblank = vblank_hz;
|
||
if (WIN32GFX_IsPicassoScreen(mon)) {
|
||
if (currprefs.win32_rtgvblankrate > 0)
|
||
vblank = currprefs.win32_rtgvblankrate;
|
||
}
|
||
bool ok = true;
|
||
int ratio = currprefs.lightboost_strobo_ratio;
|
||
int ms = (int)(1000 / vblank);
|
||
int waitms = ms * ratio / 100 - 1;
|
||
int maxrate;
|
||
if (isfullscreen() > 0) {
|
||
maxrate = mon->currentmode.freq;
|
||
} else {
|
||
maxrate = deskhz;
|
||
}
|
||
if (maxrate > 0) {
|
||
double rate = vblank * 2.0;
|
||
rate *= ratio > 50 ? ratio / 50.0 : 50.0 / ratio;
|
||
if (rate > maxrate + 1.0)
|
||
ok = false;
|
||
}
|
||
if (ok) {
|
||
strobo_time = read_processor_time() + vsynctimebase * ratio / 100;
|
||
strobo_active = true;
|
||
timeSetEvent(waitms, 0, blackinsertion_cb, NULL, TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
|
||
}
|
||
}
|
||
#endif
|
||
D3D_showframe(monid);
|
||
if (monid == 0) {
|
||
strobo_active2 = true;
|
||
if (strobo_active < 0) {
|
||
D3D_showframe_special(0, 2);
|
||
}
|
||
}
|
||
}
|
||
gfx_unlock();
|
||
mon->render_ok = false;
|
||
}
|
||
|
||
bool lockscr3d(struct vidbuffer *vb)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
|
||
if (mon->currentmode.flags & DM_D3D) {
|
||
if (!(mon->currentmode.flags & DM_SWSCALE)) {
|
||
vb->bufmem = D3D_locktexture(vb->monitor_id, &vb->rowbytes, NULL, NULL, false);
|
||
if (vb->bufmem)
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void unlockscr3d(struct vidbuffer *vb)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
|
||
if (mon->currentmode.flags & DM_D3D) {
|
||
if (!(mon->currentmode.flags & DM_SWSCALE)) {
|
||
D3D_unlocktexture(vb->monitor_id, -1, -1);
|
||
}
|
||
}
|
||
}
|
||
|
||
int lockscr(struct vidbuffer *vb, bool fullupdate, bool first, bool skip)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
|
||
int ret = 0;
|
||
|
||
if (!isscreen(mon))
|
||
return ret;
|
||
#if 0
|
||
flushymin = mon->currentmode.amiga_height;
|
||
flushymax = 0;
|
||
#endif
|
||
gfx_lock();
|
||
ret = 1;
|
||
if (mon->currentmode.flags & DM_D3D) {
|
||
#ifdef D3D
|
||
if (mon->currentmode.flags & DM_SWSCALE) {
|
||
ret = 1;
|
||
} else {
|
||
ret = 0;
|
||
vb->bufmem = D3D_locktexture(vb->monitor_id, &vb->rowbytes, NULL, NULL, skip ? -1 : (fullupdate ? 1 : 0));
|
||
if (vb->bufmem) {
|
||
if (first)
|
||
init_row_map();
|
||
ret = 1;
|
||
}
|
||
}
|
||
#endif
|
||
} else if (mon->currentmode.flags & DM_SWSCALE) {
|
||
ret = 1;
|
||
}
|
||
gfx_unlock();
|
||
return ret;
|
||
}
|
||
|
||
void unlockscr(struct vidbuffer *vb, int y_start, int y_end)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
|
||
gfx_lock();
|
||
if (mon->currentmode.flags & DM_D3D) {
|
||
if (mon->currentmode.flags & DM_SWSCALE) {
|
||
S2X_render(vb->monitor_id, y_start, y_end);
|
||
} else {
|
||
vb->bufmem = NULL;
|
||
}
|
||
D3D_unlocktexture(vb->monitor_id, y_start, y_end);
|
||
}
|
||
gfx_unlock();
|
||
}
|
||
|
||
void flush_clear_screen (struct vidbuffer *vb)
|
||
{
|
||
if (!vb)
|
||
return;
|
||
if (lockscr(vb, true, true, false)) {
|
||
int y;
|
||
for (y = 0; y < vb->height_allocated; y++) {
|
||
memset(vb->bufmem + y * vb->rowbytes, 0, vb->width_allocated * vb->pixbytes);
|
||
}
|
||
unlockscr(vb, -1, -1);
|
||
}
|
||
}
|
||
|
||
float filterrectmult(int v1, float v2, int dmode)
|
||
{
|
||
float v = v1 / v2;
|
||
int vv = (int)(v + 0.5f);
|
||
if (v > 1.5f && vv * v2 <= v1 && vv * (v2 + vv - 1) >= v1) {
|
||
return (float)vv;
|
||
}
|
||
if (!dmode) {
|
||
return v;
|
||
}
|
||
if (v > 0.2f && v < 0.3f) {
|
||
return 0.25f;
|
||
}
|
||
if (v > 0.4f && v < 0.6f) {
|
||
return 0.5f;
|
||
}
|
||
return (float)(int)(v + 0.5f);
|
||
}
|
||
|
||
void getrtgfilterrect2(int monid, RECT *sr, RECT *dr, RECT *zr, int *mode, int dst_width, int dst_height)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
struct picasso96_state_struct *state = &picasso96_state[monid];
|
||
|
||
SetRect (sr, 0, 0, mon->currentmode.native_width, mon->currentmode.native_height);
|
||
SetRect (dr, 0, 0, state->Width, state->Height);
|
||
SetRect (zr, 0, 0, 0, 0);
|
||
|
||
picasso_offset_x = 0;
|
||
picasso_offset_y = 0;
|
||
picasso_offset_mx = 1.0;
|
||
picasso_offset_my = 1.0;
|
||
|
||
*mode = 0;
|
||
|
||
if (!ad->picasso_on)
|
||
return;
|
||
|
||
if (currprefs.gf[GF_RTG].gfx_filter_horiz_zoom_mult > 0) {
|
||
picasso_offset_mx *= currprefs.gf[GF_RTG].gfx_filter_horiz_zoom_mult;
|
||
}
|
||
if (currprefs.gf[GF_RTG].gfx_filter_vert_zoom_mult > 0) {
|
||
picasso_offset_my *= currprefs.gf[GF_RTG].gfx_filter_vert_zoom_mult;
|
||
}
|
||
|
||
if (!mon->scalepicasso)
|
||
return;
|
||
|
||
int srcratio, dstratio;
|
||
int srcwidth, srcheight;
|
||
srcwidth = state->Width;
|
||
srcheight = state->Height;
|
||
if (!srcwidth || !srcheight)
|
||
return;
|
||
|
||
float mx = (float)mon->currentmode.native_width / srcwidth;
|
||
float my = (float)mon->currentmode.native_height / srcheight;
|
||
int outwidth;
|
||
int outheight;
|
||
|
||
if (mon->scalepicasso == RTG_MODE_INTEGER_SCALE) {
|
||
int divx = mon->currentmode.native_width / srcwidth;
|
||
int divy = mon->currentmode.native_height / srcheight;
|
||
float mul = (float)(!divx || !divy ? 1 : (divx > divy ? divy : divx));
|
||
if (!divx || !divy) {
|
||
if ((float)mon->currentmode.native_width / srcwidth <= 0.95f || ((float)mon->currentmode.native_height / srcheight <= 0.95f)) {
|
||
mul = 0.5f;
|
||
}
|
||
if ((float)mon->currentmode.native_width / srcwidth <= 0.45f || ((float)mon->currentmode.native_height / srcheight <= 0.45f)) {
|
||
mul = 0.25f;
|
||
}
|
||
}
|
||
SetRect(dr, 0, 0, (int)(mon->currentmode.native_width / mul), (int)(mon->currentmode.native_height / mul));
|
||
int xx = (int)((mon->currentmode.native_width / mul - srcwidth) / 2);
|
||
int yy = (int)((mon->currentmode.native_height / mul - srcheight) / 2);
|
||
picasso_offset_x = -xx;
|
||
picasso_offset_y = -yy;
|
||
mx = mul;
|
||
my = mul;
|
||
outwidth = srcwidth;
|
||
outheight = srcheight;
|
||
*mode = 1;
|
||
} else if (mon->scalepicasso == RTG_MODE_CENTER) {
|
||
int xx = (mon->currentmode.native_width - srcwidth) / 2;
|
||
int yy = (mon->currentmode.native_height - srcheight) / 2;
|
||
picasso_offset_x = -xx;
|
||
picasso_offset_y = -yy;
|
||
SetRect (sr, 0, 0, mon->currentmode.native_width, mon->currentmode.native_height);
|
||
SetRect (dr, 0, 0, mon->currentmode.native_width, mon->currentmode.native_height);
|
||
outwidth = dr->right - dr->left;
|
||
outheight = dr->bottom - dr->top;
|
||
mx = my = 1.0;
|
||
} else {
|
||
if (currprefs.win32_rtgscaleaspectratio < 0) {
|
||
// automatic
|
||
srcratio = srcwidth * ASPECTMULT / srcheight;
|
||
dstratio = mon->currentmode.native_width * ASPECTMULT / mon->currentmode.native_height;
|
||
} else if (currprefs.win32_rtgscaleaspectratio == 0) {
|
||
// none
|
||
srcratio = dstratio = 0;
|
||
} else {
|
||
// manual
|
||
dstratio = (currprefs.win32_rtgscaleaspectratio / ASPECTMULT) * ASPECTMULT / (currprefs.win32_rtgscaleaspectratio & (ASPECTMULT - 1));
|
||
srcratio = srcwidth * ASPECTMULT / srcheight;
|
||
}
|
||
|
||
if (srcratio == dstratio) {
|
||
SetRect (dr, 0, 0, srcwidth, srcheight);
|
||
} else if (srcratio > dstratio) {
|
||
int yy = srcheight * srcratio / dstratio;
|
||
SetRect (dr, 0, 0, srcwidth, yy);
|
||
picasso_offset_y = (state->Height - yy) / 2;
|
||
} else {
|
||
int xx = srcwidth * dstratio / srcratio;
|
||
SetRect (dr, 0, 0, xx, srcheight);
|
||
picasso_offset_x = (state->Width - xx) / 2;
|
||
}
|
||
outwidth = dr->right - dr->left;
|
||
outheight = dr->bottom - dr->top;
|
||
}
|
||
|
||
OffsetRect (zr, picasso_offset_x, picasso_offset_y);
|
||
|
||
picasso_offset_x /= state->HLineDBL;
|
||
picasso_offset_y /= state->VLineDBL;
|
||
|
||
picasso_offset_mx = (float)(srcwidth * mx * state->HLineDBL) / outwidth;
|
||
picasso_offset_my = (float)(srcheight * my * state->VLineDBL) / outheight;
|
||
}
|
||
|
||
static uae_u8 *gfx_lock_picasso2(int monid, bool fullupdate)
|
||
{
|
||
struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
|
||
uae_u8 *p = D3D_locktexture(monid, &vidinfo->rowbytes, &vidinfo->maxwidth, &vidinfo->maxheight, fullupdate);
|
||
return p;
|
||
}
|
||
uae_u8 *gfx_lock_picasso(int monid, bool fullupdate)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
|
||
static uae_u8 *p;
|
||
if (mon->rtg_locked) {
|
||
return p;
|
||
}
|
||
gfx_lock();
|
||
p = gfx_lock_picasso2(monid, fullupdate);
|
||
if (!p) {
|
||
gfx_unlock();
|
||
} else {
|
||
mon->rtg_locked = true;
|
||
}
|
||
return p;
|
||
}
|
||
|
||
void gfx_unlock_picasso(int monid, bool dorender)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
if (!mon->rtg_locked)
|
||
gfx_lock();
|
||
mon->rtg_locked = false;
|
||
if (dorender) {
|
||
if (mon->p96_double_buffer_needs_flushing) {
|
||
D3D_flushtexture(monid, mon->p96_double_buffer_first, mon->p96_double_buffer_last);
|
||
mon->p96_double_buffer_needs_flushing = 0;
|
||
}
|
||
}
|
||
D3D_unlocktexture(monid, -1, -1);
|
||
if (dorender) {
|
||
if (D3D_renderframe(monid, true, false)) {
|
||
gfx_unlock();
|
||
mon->render_ok = true;
|
||
show_screen_maybe(monid, true);
|
||
} else {
|
||
gfx_unlock();
|
||
}
|
||
} else {
|
||
gfx_unlock();
|
||
}
|
||
}
|
||
|
||
static HWND blankwindows[MAX_DISPLAYS];
|
||
static void closeblankwindows (void)
|
||
{
|
||
for (int i = 0; i < MAX_DISPLAYS; i++) {
|
||
HWND h = blankwindows[i];
|
||
if (h) {
|
||
ShowWindow (h, SW_HIDE);
|
||
DestroyWindow (h);
|
||
blankwindows[i] = NULL;
|
||
}
|
||
}
|
||
}
|
||
static void createblankwindows (void)
|
||
{
|
||
struct MultiDisplay *mdx = getdisplay(&currprefs, 0);
|
||
int i;
|
||
|
||
if (!currprefs.win32_blankmonitors)
|
||
return;
|
||
|
||
for (i = 0; Displays[i].monitorname; i++) {
|
||
struct MultiDisplay *md = &Displays[i];
|
||
TCHAR name[100];
|
||
if (mdx == md)
|
||
continue;
|
||
_stprintf (name, _T("WinUAE_Blank_%d"), i);
|
||
blankwindows[i] = CreateWindowEx (
|
||
WS_EX_TOPMOST,
|
||
_T("Blank"), name,
|
||
WS_POPUP | WS_VISIBLE,
|
||
md->rect.left, md->rect.top, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top,
|
||
NULL,
|
||
NULL, hInst, NULL);
|
||
}
|
||
}
|
||
|
||
static void close_hwnds(struct AmigaMonitor *mon)
|
||
{
|
||
if (mon->screen_is_initialized)
|
||
releasecapture(mon);
|
||
mon->screen_is_initialized = 0;
|
||
if (!mon->monitor_id) {
|
||
display_vblank_thread_kill();
|
||
#ifdef AVIOUTPUT
|
||
AVIOutput_Restart(true);
|
||
#endif
|
||
#ifdef RETROPLATFORM
|
||
rp_set_hwnd(NULL);
|
||
#endif
|
||
closeblankwindows();
|
||
rawinput_release();
|
||
}
|
||
if (mon->monitor_id > 0 && mon->hMainWnd)
|
||
setmouseactive(mon->monitor_id, 0);
|
||
deletestatusline(mon->monitor_id);
|
||
if (mon->hStatusWnd) {
|
||
ShowWindow(mon->hStatusWnd, SW_HIDE);
|
||
DestroyWindow(mon->hStatusWnd);
|
||
mon->hStatusWnd = 0;
|
||
if (mon->hStatusBkgB)
|
||
DeleteObject(mon->hStatusBkgB);
|
||
mon->hStatusBkgB = NULL;
|
||
}
|
||
if (mon->hAmigaWnd) {
|
||
addnotifications (mon->hAmigaWnd, TRUE, FALSE);
|
||
#ifdef D3D
|
||
D3D_free(mon->monitor_id, true);
|
||
#endif
|
||
ShowWindow (mon->hAmigaWnd, SW_HIDE);
|
||
DestroyWindow (mon->hAmigaWnd);
|
||
if (mon->hAmigaWnd == mon->hMainWnd)
|
||
mon->hMainWnd = 0;
|
||
mon->hAmigaWnd = 0;
|
||
}
|
||
if (mon->hMainWnd) {
|
||
ShowWindow(mon->hMainWnd, SW_HIDE);
|
||
DestroyWindow(mon->hMainWnd);
|
||
mon->hMainWnd = 0;
|
||
}
|
||
gfx_hdr = false;
|
||
}
|
||
|
||
static bool canmatchdepth(void)
|
||
{
|
||
if (!currprefs.win32_rtgmatchdepth)
|
||
return false;
|
||
if (currprefs.gfx_api >= 2)
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
static void updatemodes(struct AmigaMonitor *mon)
|
||
{
|
||
struct uae_filter *usedfilter = mon->usedfilter;
|
||
DWORD flags = 0;
|
||
|
||
mon->currentmode.fullfill = 0;
|
||
if (isfullscreen () > 0)
|
||
flags |= DM_DX_FULLSCREEN;
|
||
else if (isfullscreen () < 0)
|
||
flags |= DM_W_FULLSCREEN;
|
||
#if defined (GFXFILTER)
|
||
if (usedfilter) {
|
||
flags |= DM_SWSCALE;
|
||
if (mon->currentmode.current_depth < 15)
|
||
mon->currentmode.current_depth = 16;
|
||
}
|
||
#endif
|
||
flags |= DM_D3D;
|
||
if (flags & DM_DX_FULLSCREEN) {
|
||
flags &= ~DM_DX_FULLSCREEN;
|
||
flags |= DM_D3D_FULLSCREEN;
|
||
}
|
||
mon->currentmode.flags = flags;
|
||
if (flags & DM_SWSCALE)
|
||
mon->currentmode.fullfill = 1;
|
||
if (flags & DM_W_FULLSCREEN) {
|
||
RECT rc = getdisplay(&currprefs, mon->monitor_id)->rect;
|
||
mon->currentmode.native_width = rc.right - rc.left;
|
||
mon->currentmode.native_height = rc.bottom - rc.top;
|
||
mon->currentmode.current_width = mon->currentmode.native_width;
|
||
mon->currentmode.current_height = mon->currentmode.native_height;
|
||
} else {
|
||
mon->currentmode.native_width = mon->currentmode.current_width;
|
||
mon->currentmode.native_height = mon->currentmode.current_height;
|
||
}
|
||
}
|
||
|
||
static void update_gfxparams(struct AmigaMonitor *mon)
|
||
{
|
||
struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
|
||
|
||
updatewinfsmode(mon->monitor_id, &currprefs);
|
||
#ifdef PICASSO96
|
||
mon->currentmode.vsync = 0;
|
||
if (mon->screen_is_picasso) {
|
||
float mx = 1.0;
|
||
float my = 1.0;
|
||
if (currprefs.gf[GF_RTG].gfx_filter_horiz_zoom_mult > 0) {
|
||
mx *= currprefs.gf[GF_RTG].gfx_filter_horiz_zoom_mult;
|
||
}
|
||
if (currprefs.gf[GF_RTG].gfx_filter_vert_zoom_mult > 0) {
|
||
my *= currprefs.gf[GF_RTG].gfx_filter_vert_zoom_mult;
|
||
}
|
||
mon->currentmode.current_width = (int)(state->Width * currprefs.rtg_horiz_zoom_mult * mx);
|
||
mon->currentmode.current_height = (int)(state->Height * currprefs.rtg_vert_zoom_mult * my);
|
||
currprefs.gfx_apmode[1].gfx_interlaced = false;
|
||
if (currprefs.win32_rtgvblankrate == 0) {
|
||
currprefs.gfx_apmode[1].gfx_refreshrate = currprefs.gfx_apmode[0].gfx_refreshrate;
|
||
if (currprefs.gfx_apmode[0].gfx_interlaced) {
|
||
currprefs.gfx_apmode[1].gfx_refreshrate *= 2;
|
||
}
|
||
} else if (currprefs.win32_rtgvblankrate < 0) {
|
||
currprefs.gfx_apmode[1].gfx_refreshrate = 0;
|
||
} else {
|
||
currprefs.gfx_apmode[1].gfx_refreshrate = currprefs.win32_rtgvblankrate;
|
||
}
|
||
if (currprefs.gfx_apmode[1].gfx_vsync)
|
||
mon->currentmode.vsync = 1 + currprefs.gfx_apmode[1].gfx_vsyncmode;
|
||
} else {
|
||
#endif
|
||
mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
|
||
mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
|
||
if (currprefs.gfx_apmode[0].gfx_vsync)
|
||
mon->currentmode.vsync = 1 + currprefs.gfx_apmode[0].gfx_vsyncmode;
|
||
#ifdef PICASSO96
|
||
}
|
||
#endif
|
||
#if FORCE16BIT
|
||
mon->currentmode.current_depth = 16;
|
||
#else
|
||
mon->currentmode.current_depth = currprefs.color_mode < 5 ? 16 : 32;
|
||
#endif
|
||
if (mon->screen_is_picasso && canmatchdepth() && isfullscreen () > 0) {
|
||
int pbits = state->BytesPerPixel * 8;
|
||
if (pbits <= 8) {
|
||
if (mon->currentmode.current_depth == 32)
|
||
pbits = 32;
|
||
else
|
||
pbits = 16;
|
||
}
|
||
if (pbits == 24)
|
||
pbits = 32;
|
||
mon->currentmode.current_depth = pbits;
|
||
}
|
||
mon->currentmode.amiga_width = mon->currentmode.current_width;
|
||
mon->currentmode.amiga_height = mon->currentmode.current_height;
|
||
|
||
mon->scalepicasso = 0;
|
||
if (mon->screen_is_picasso) {
|
||
bool diff = state->Width != mon->currentmode.native_width || state->Height != mon->currentmode.native_height;
|
||
if (isfullscreen () < 0) {
|
||
if ((currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_CENTER || currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_SCALE || currprefs.win32_rtgallowscaling) && diff) {
|
||
mon->scalepicasso = RTG_MODE_SCALE;
|
||
}
|
||
if (currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_INTEGER_SCALE && diff) {
|
||
mon->scalepicasso = RTG_MODE_INTEGER_SCALE;
|
||
}
|
||
if (currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_CENTER && diff) {
|
||
mon->scalepicasso = currprefs.gf[GF_RTG].gfx_filter_autoscale;
|
||
}
|
||
if (!mon->scalepicasso && currprefs.win32_rtgscaleaspectratio) {
|
||
mon->scalepicasso = -1;
|
||
}
|
||
} else if (isfullscreen () > 0) {
|
||
if (!canmatchdepth()) { // can't scale to different color depth
|
||
if (mon->currentmode.native_width > state->Width && mon->currentmode.native_height > state->Height) {
|
||
if (currprefs.gf[GF_RTG].gfx_filter_autoscale)
|
||
mon->scalepicasso = RTG_MODE_SCALE;
|
||
if (currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_INTEGER_SCALE) {
|
||
mon->scalepicasso = RTG_MODE_INTEGER_SCALE;
|
||
}
|
||
}
|
||
if (currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_CENTER)
|
||
mon->scalepicasso = currprefs.gf[GF_RTG].gfx_filter_autoscale;
|
||
if (!mon->scalepicasso && currprefs.win32_rtgscaleaspectratio)
|
||
mon->scalepicasso = -1;
|
||
}
|
||
} else if (isfullscreen () == 0) {
|
||
if (currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_INTEGER_SCALE) {
|
||
mon->scalepicasso = RTG_MODE_INTEGER_SCALE;
|
||
mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
|
||
mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
|
||
} else if (currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_CENTER) {
|
||
if (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width < state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height < state->Height) {
|
||
if (!currprefs.win32_rtgallowscaling) {
|
||
;
|
||
} else if (currprefs.win32_rtgscaleaspectratio) {
|
||
mon->scalepicasso = -1;
|
||
mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
|
||
mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
|
||
}
|
||
} else {
|
||
mon->scalepicasso = RTG_MODE_CENTER;
|
||
mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
|
||
mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
|
||
}
|
||
} else if (currprefs.gf[GF_RTG].gfx_filter_autoscale == RTG_MODE_SCALE) {
|
||
if (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width > state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height > state->Height)
|
||
mon->scalepicasso = RTG_MODE_SCALE;
|
||
if ((currprefs.gfx_monitor[mon->monitor_id].gfx_size.width != state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height != state->Height) && currprefs.win32_rtgallowscaling) {
|
||
mon->scalepicasso = RTG_MODE_SCALE;
|
||
} else if (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width < state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height < state->Height) {
|
||
// no always scaling and smaller? Back to normal size and set new configured max size
|
||
mon->currentmode.current_width = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.width = state->Width;
|
||
mon->currentmode.current_height = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.height = state->Height;
|
||
} else if (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width == state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height == state->Height) {
|
||
;
|
||
} else if (!mon->scalepicasso && currprefs.win32_rtgscaleaspectratio) {
|
||
mon->scalepicasso = -1;
|
||
}
|
||
} else {
|
||
if ((currprefs.gfx_monitor[mon->monitor_id].gfx_size.width != state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height != state->Height) && currprefs.win32_rtgallowscaling)
|
||
mon->scalepicasso = RTG_MODE_SCALE;
|
||
if (!mon->scalepicasso && currprefs.win32_rtgscaleaspectratio)
|
||
mon->scalepicasso = -1;
|
||
}
|
||
}
|
||
|
||
if (mon->scalepicasso > 0 && (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width != state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height != state->Height)) {
|
||
mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
|
||
mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
static int open_windows(struct AmigaMonitor *mon, bool mousecapture, bool started)
|
||
{
|
||
bool recapture = false;
|
||
int ret;
|
||
|
||
mon->screen_is_initialized = 0;
|
||
|
||
if (mon->monitor_id && mouseactive)
|
||
recapture = true;
|
||
|
||
inputdevice_unacquire();
|
||
reset_sound();
|
||
if (mon->hAmigaWnd == NULL)
|
||
wait_keyrelease();
|
||
|
||
mon->in_sizemove = 0;
|
||
|
||
updatewinfsmode(mon->monitor_id, &currprefs);
|
||
|
||
int init_round = 0;
|
||
ret = -2;
|
||
do {
|
||
if (ret < -1) {
|
||
updatemodes(mon);
|
||
update_gfxparams(mon);
|
||
}
|
||
ret = doInit(mon);
|
||
init_round++;
|
||
if (ret < -9) {
|
||
return 0;
|
||
}
|
||
} while (ret < 0);
|
||
|
||
if (!ret) {
|
||
return ret;
|
||
}
|
||
|
||
bool startactive = (started && mouseactive) || (!started && !currprefs.win32_start_uncaptured && !currprefs.win32_start_minimized);
|
||
bool startpaused = !started && ((currprefs.win32_start_minimized && currprefs.win32_iconified_pause) || (currprefs.win32_start_uncaptured && currprefs.win32_inactive_pause && isfullscreen() <= 0));
|
||
bool startminimized = !started && currprefs.win32_start_minimized && isfullscreen() <= 0;
|
||
int input = 0;
|
||
|
||
if ((mousecapture && startactive) || recapture)
|
||
setmouseactive(mon->monitor_id, -1);
|
||
|
||
int upd = 0;
|
||
if (startactive) {
|
||
setpriority(&priorities[currprefs.win32_active_capture_priority]);
|
||
upd = 2;
|
||
} else if (startminimized) {
|
||
setpriority(&priorities[currprefs.win32_iconified_priority]);
|
||
setminimized(mon->monitor_id);
|
||
input = currprefs.win32_inactive_input;
|
||
upd = 1;
|
||
} else {
|
||
setpriority(&priorities[currprefs.win32_inactive_priority]);
|
||
input = currprefs.win32_inactive_input;
|
||
upd = 2;
|
||
}
|
||
if (upd > 1) {
|
||
for (int i = 0; i < NUM_LEDS; i++)
|
||
gui_flicker_led(i, -1, -1);
|
||
gui_led(LED_POWER, gui_data.powerled, gui_data.powerled_brightness);
|
||
gui_fps(0, 0, 0);
|
||
if (gui_data.md >= 0)
|
||
gui_led(LED_MD, 0, -1);
|
||
for (int i = 0; i < 4; i++) {
|
||
if (currprefs.floppyslots[i].dfxtype >= 0)
|
||
gui_led(LED_DF0 + i, 0, -1);
|
||
}
|
||
}
|
||
if (upd > 0) {
|
||
inputdevice_acquire(TRUE);
|
||
if (!isfocus())
|
||
inputdevice_unacquire(input);
|
||
}
|
||
|
||
if (startpaused)
|
||
setpaused(1);
|
||
|
||
statusline_updated(mon->monitor_id);
|
||
refreshtitle();
|
||
|
||
return ret;
|
||
}
|
||
|
||
static void reopen_gfx(struct AmigaMonitor *mon)
|
||
{
|
||
open_windows(mon, false, true);
|
||
render_screen(mon->monitor_id, 1, true);
|
||
}
|
||
|
||
static int getstatuswindowheight(int monid, HWND hwnd)
|
||
{
|
||
if (monid > 0)
|
||
return 0;
|
||
int def = GetSystemMetrics (SM_CYMENU) + 3;
|
||
WINDOWINFO wi;
|
||
HWND h = CreateWindowEx (
|
||
0, STATUSCLASSNAME, (LPCTSTR) NULL, SBARS_TOOLTIPS | WS_CHILD,
|
||
0, 0, 0, 0, hwnd ? hwnd : hHiddenWnd, (HMENU) 1, hInst, NULL);
|
||
if (!h)
|
||
return def;
|
||
wi.cbSize = sizeof wi;
|
||
if (GetWindowInfo(h, &wi)) {
|
||
def = wi.rcWindow.bottom - wi.rcWindow.top;
|
||
}
|
||
DestroyWindow(h);
|
||
return def;
|
||
}
|
||
|
||
void graphics_reset(bool forced)
|
||
{
|
||
if (forced) {
|
||
display_change_requested = 2;
|
||
} else {
|
||
// full reset if display size can't changed.
|
||
if (currprefs.gfx_api) {
|
||
display_change_requested = 3;
|
||
} else {
|
||
display_change_requested = 2;
|
||
}
|
||
}
|
||
}
|
||
|
||
void WIN32GFX_DisplayChangeRequested(int mode)
|
||
{
|
||
display_change_requested = mode;
|
||
}
|
||
|
||
int check_prefs_changed_gfx(void)
|
||
{
|
||
int c = 0;
|
||
bool monitors[MAX_AMIGAMONITORS];
|
||
|
||
if (!config_changed && !display_change_requested)
|
||
return 0;
|
||
|
||
c |= config_changed_flags;
|
||
config_changed_flags = 0;
|
||
|
||
c |= currprefs.win32_statusbar != changed_prefs.win32_statusbar ? 512 : 0;
|
||
|
||
for (int i = 0; i < MAX_AMIGADISPLAYS; i++) {
|
||
monitors[i] = false;
|
||
int c2 = 0;
|
||
c2 |= currprefs.gfx_monitor[i].gfx_size_fs.width != changed_prefs.gfx_monitor[i].gfx_size_fs.width ? 16 : 0;
|
||
c2 |= currprefs.gfx_monitor[i].gfx_size_fs.height != changed_prefs.gfx_monitor[i].gfx_size_fs.height ? 16 : 0;
|
||
c2 |= ((currprefs.gfx_monitor[i].gfx_size_win.width + 7) & ~7) != ((changed_prefs.gfx_monitor[i].gfx_size_win.width + 7) & ~7) ? 16 : 0;
|
||
c2 |= currprefs.gfx_monitor[i].gfx_size_win.height != changed_prefs.gfx_monitor[i].gfx_size_win.height ? 16 : 0;
|
||
if (c2) {
|
||
if (i > 0) {
|
||
for (int j = 0; j < MAX_AMIGAMONITORS; j++) {
|
||
struct rtgboardconfig *rbc = &changed_prefs.rtgboards[j];
|
||
if (rbc->monitor_id == i) {
|
||
c |= c2;
|
||
monitors[i] = true;
|
||
}
|
||
}
|
||
if (!monitors[i]) {
|
||
currprefs.gfx_monitor[i].gfx_size_fs.width = changed_prefs.gfx_monitor[i].gfx_size_fs.width;
|
||
currprefs.gfx_monitor[i].gfx_size_fs.height = changed_prefs.gfx_monitor[i].gfx_size_fs.height;
|
||
currprefs.gfx_monitor[i].gfx_size_win.width = changed_prefs.gfx_monitor[i].gfx_size_win.width;
|
||
currprefs.gfx_monitor[i].gfx_size_win.height = changed_prefs.gfx_monitor[i].gfx_size_win.height;
|
||
}
|
||
} else {
|
||
c |= c2;
|
||
monitors[i] = true;
|
||
}
|
||
}
|
||
if (WIN32GFX_IsPicassoScreen(&AMonitors[i])) {
|
||
struct gfx_filterdata *gfc = &changed_prefs.gf[1];
|
||
if (gfc->changed) {
|
||
gfc->changed = false;
|
||
c |= 16;
|
||
}
|
||
} else {
|
||
struct gfx_filterdata *gfc1 = &changed_prefs.gf[0];
|
||
struct gfx_filterdata *gfc2 = &changed_prefs.gf[2];
|
||
if (gfc1->changed || gfc2->changed) {
|
||
gfc1->changed = false;
|
||
gfc2->changed = false;
|
||
c |= 16;
|
||
}
|
||
}
|
||
}
|
||
if (currprefs.gf[2].enable != changed_prefs.gf[2].enable) {
|
||
currprefs.gf[2].enable = changed_prefs.gf[2].enable;
|
||
c |= 512;
|
||
}
|
||
|
||
monitors[0] = true;
|
||
|
||
#if 0
|
||
c |= currprefs.gfx_size_win.x != changed_prefs.gfx_size_win.x ? 16 : 0;
|
||
c |= currprefs.gfx_size_win.y != changed_prefs.gfx_size_win.y ? 16 : 0;
|
||
#endif
|
||
c |= currprefs.color_mode != changed_prefs.color_mode ? 2 | 16 : 0;
|
||
c |= currprefs.gfx_apmode[0].gfx_fullscreen != changed_prefs.gfx_apmode[0].gfx_fullscreen ? 16 : 0;
|
||
c |= currprefs.gfx_apmode[1].gfx_fullscreen != changed_prefs.gfx_apmode[1].gfx_fullscreen ? 16 : 0;
|
||
c |= currprefs.gfx_apmode[0].gfx_vsync != changed_prefs.gfx_apmode[0].gfx_vsync ? 2 | 16 : 0;
|
||
c |= currprefs.gfx_apmode[1].gfx_vsync != changed_prefs.gfx_apmode[1].gfx_vsync ? 2 | 16 : 0;
|
||
c |= currprefs.gfx_apmode[0].gfx_vsyncmode != changed_prefs.gfx_apmode[0].gfx_vsyncmode ? 2 | 16 : 0;
|
||
c |= currprefs.gfx_apmode[1].gfx_vsyncmode != changed_prefs.gfx_apmode[1].gfx_vsyncmode ? 2 | 16 : 0;
|
||
c |= currprefs.gfx_apmode[0].gfx_refreshrate != changed_prefs.gfx_apmode[0].gfx_refreshrate ? 2 | 16 : 0;
|
||
#if 0
|
||
c |= currprefs.gfx_apmode[1].gfx_refreshrate != changed_prefs.gfx_apmode[1].gfx_refreshrate ? 2 | 16 : 0;
|
||
#endif
|
||
c |= currprefs.gfx_autoresolution != changed_prefs.gfx_autoresolution ? (2|8|16) : 0;
|
||
c |= currprefs.gfx_autoresolution_vga != changed_prefs.gfx_autoresolution_vga ? (2|8|16) : 0;
|
||
c |= currprefs.gfx_api != changed_prefs.gfx_api ? (1 | 8 | 32) : 0;
|
||
c |= currprefs.gfx_api_options != changed_prefs.gfx_api_options ? (1 | 8 | 32) : 0;
|
||
c |= currprefs.lightboost_strobo != changed_prefs.lightboost_strobo ? (2|16) : 0;
|
||
|
||
for (int j = 0; j < MAX_FILTERDATA; j++) {
|
||
struct gfx_filterdata *gf = &currprefs.gf[j];
|
||
struct gfx_filterdata *gfc = &changed_prefs.gf[j];
|
||
|
||
c |= gf->gfx_filter != gfc->gfx_filter ? (2 | 8) : 0;
|
||
c |= gf->gfx_filter != gfc->gfx_filter ? (2 | 8) : 0;
|
||
|
||
for (int i = 0; i <= 2 * MAX_FILTERSHADERS; i++) {
|
||
c |= _tcscmp (gf->gfx_filtershader[i], gfc->gfx_filtershader[i]) ? (2|8) : 0;
|
||
c |= _tcscmp (gf->gfx_filtermask[i], gfc->gfx_filtermask[i]) ? (2|8) : 0;
|
||
}
|
||
c |= _tcscmp (gf->gfx_filteroverlay, gfc->gfx_filteroverlay) ? (2|8) : 0;
|
||
|
||
c |= gf->gfx_filter_scanlines != gfc->gfx_filter_scanlines ? (1|8) : 0;
|
||
c |= gf->gfx_filter_scanlinelevel != gfc->gfx_filter_scanlinelevel ? (1|8) : 0;
|
||
c |= gf->gfx_filter_scanlineratio != gfc->gfx_filter_scanlineratio ? (1 | 8) : 0;
|
||
c |= gf->gfx_filter_scanlineoffset != gfc->gfx_filter_scanlineoffset ? (1 | 8) : 0;
|
||
|
||
c |= gf->gfx_filter_horiz_zoom_mult != gfc->gfx_filter_horiz_zoom_mult ? (1) : 0;
|
||
c |= gf->gfx_filter_vert_zoom_mult != gfc->gfx_filter_vert_zoom_mult ? (1) : 0;
|
||
|
||
c |= gf->gfx_filter_filtermodeh != gfc->gfx_filter_filtermodeh ? (2 | 8) : 0;
|
||
c |= gf->gfx_filter_filtermodev != gfc->gfx_filter_filtermodev ? (2 | 8) : 0;
|
||
c |= gf->gfx_filter_bilinear != gfc->gfx_filter_bilinear ? (2|8|16) : 0;
|
||
c |= gf->gfx_filter_noise != gfc->gfx_filter_noise ? (1) : 0;
|
||
c |= gf->gfx_filter_blur != gfc->gfx_filter_blur ? (1) : 0;
|
||
|
||
c |= gf->gfx_filter_aspect != gfc->gfx_filter_aspect ? (1) : 0;
|
||
c |= gf->gfx_filter_rotation != gfc->gfx_filter_rotation ? (1) : 0;
|
||
c |= gf->gfx_filter_keep_aspect != gfc->gfx_filter_keep_aspect ? (1) : 0;
|
||
c |= gf->gfx_filter_keep_autoscale_aspect != gfc->gfx_filter_keep_autoscale_aspect ? (1) : 0;
|
||
c |= gf->gfx_filter_luminance != gfc->gfx_filter_luminance ? (1) : 0;
|
||
c |= gf->gfx_filter_contrast != gfc->gfx_filter_contrast ? (1) : 0;
|
||
c |= gf->gfx_filter_saturation != gfc->gfx_filter_saturation ? (1) : 0;
|
||
c |= gf->gfx_filter_gamma != gfc->gfx_filter_gamma ? (1) : 0;
|
||
c |= gf->gfx_filter_integerscalelimit != gfc->gfx_filter_integerscalelimit ? (1) : 0;
|
||
if (j && gf->gfx_filter_autoscale != gfc->gfx_filter_autoscale)
|
||
c |= 8 | 64;
|
||
//c |= gf->gfx_filter_ != gfc->gfx_filter_ ? (1|8) : 0;
|
||
}
|
||
|
||
c |= currprefs.rtg_horiz_zoom_mult != changed_prefs.rtg_horiz_zoom_mult ? 16 : 0;
|
||
c |= currprefs.rtg_vert_zoom_mult != changed_prefs.rtg_vert_zoom_mult ? 16 : 0;
|
||
|
||
c |= currprefs.gfx_luminance != changed_prefs.gfx_luminance ? (1 | 256) : 0;
|
||
c |= currprefs.gfx_contrast != changed_prefs.gfx_contrast ? (1 | 256) : 0;
|
||
c |= currprefs.gfx_gamma != changed_prefs.gfx_gamma ? (1 | 256) : 0;
|
||
|
||
c |= currprefs.gfx_resolution != changed_prefs.gfx_resolution ? (128) : 0;
|
||
c |= currprefs.gfx_vresolution != changed_prefs.gfx_vresolution ? (128) : 0;
|
||
c |= currprefs.gfx_autoresolution_minh != changed_prefs.gfx_autoresolution_minh ? (128) : 0;
|
||
c |= currprefs.gfx_autoresolution_minv != changed_prefs.gfx_autoresolution_minv ? (128) : 0;
|
||
c |= currprefs.gfx_iscanlines != changed_prefs.gfx_iscanlines ? (2 | 8) : 0;
|
||
c |= currprefs.gfx_pscanlines != changed_prefs.gfx_pscanlines ? (2 | 8) : 0;
|
||
|
||
c |= currprefs.monitoremu != changed_prefs.monitoremu ? (2 | 8) : 0;
|
||
c |= currprefs.genlock_image != changed_prefs.genlock_image ? (2 | 8) : 0;
|
||
c |= currprefs.genlock != changed_prefs.genlock ? (2 | 8) : 0;
|
||
c |= currprefs.genlock_alpha != changed_prefs.genlock_alpha ? (1 | 8) : 0;
|
||
c |= currprefs.genlock_mix != changed_prefs.genlock_mix ? (1 | 256) : 0;
|
||
c |= currprefs.genlock_aspect != changed_prefs.genlock_aspect ? (1 | 256) : 0;
|
||
c |= currprefs.genlock_scale != changed_prefs.genlock_scale ? (1 | 256) : 0;
|
||
c |= _tcsicmp(currprefs.genlock_image_file, changed_prefs.genlock_image_file) ? (2 | 8) : 0;
|
||
c |= _tcsicmp(currprefs.genlock_video_file, changed_prefs.genlock_video_file) ? (2 | 8) : 0;
|
||
|
||
c |= currprefs.gfx_lores_mode != changed_prefs.gfx_lores_mode ? (2 | 8) : 0;
|
||
c |= currprefs.gfx_overscanmode != changed_prefs.gfx_overscanmode ? (2 | 8) : 0;
|
||
c |= currprefs.gfx_scandoubler != changed_prefs.gfx_scandoubler ? (2 | 8) : 0;
|
||
c |= currprefs.gfx_threebitcolors != changed_prefs.gfx_threebitcolors ? (256) : 0;
|
||
c |= currprefs.gfx_grayscale != changed_prefs.gfx_grayscale ? (512) : 0;
|
||
c |= currprefs.gfx_monitorblankdelay != changed_prefs.gfx_monitorblankdelay ? (512) : 0;
|
||
|
||
c |= currprefs.gfx_display_sections != changed_prefs.gfx_display_sections ? (512) : 0;
|
||
c |= currprefs.gfx_variable_sync != changed_prefs.gfx_variable_sync ? 1 : 0;
|
||
c |= currprefs.gfx_windowed_resize != changed_prefs.gfx_windowed_resize ? 1 : 0;
|
||
|
||
c |= currprefs.gfx_apmode[APMODE_NATIVE].gfx_display != changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_display ? (2|4|8) : 0;
|
||
c |= currprefs.gfx_apmode[APMODE_RTG].gfx_display != changed_prefs.gfx_apmode[APMODE_RTG].gfx_display ? (2|4|8) : 0;
|
||
c |= currprefs.gfx_blackerthanblack != changed_prefs.gfx_blackerthanblack ? (2 | 8) : 0;
|
||
c |= currprefs.gfx_apmode[APMODE_NATIVE].gfx_backbuffers != changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_backbuffers ? (2 | 16) : 0;
|
||
c |= currprefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced != changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced ? (2 | 8) : 0;
|
||
c |= currprefs.gfx_apmode[APMODE_RTG].gfx_backbuffers != changed_prefs.gfx_apmode[APMODE_RTG].gfx_backbuffers ? (2 | 16) : 0;
|
||
|
||
c |= currprefs.win32_main_alwaysontop != changed_prefs.win32_main_alwaysontop ? 32 : 0;
|
||
c |= currprefs.win32_gui_alwaysontop != changed_prefs.win32_gui_alwaysontop ? 2 : 0;
|
||
c |= currprefs.win32_notaskbarbutton != changed_prefs.win32_notaskbarbutton ? 32 : 0;
|
||
c |= currprefs.win32_nonotificationicon != changed_prefs.win32_nonotificationicon ? 32 : 0;
|
||
c |= currprefs.win32_borderless != changed_prefs.win32_borderless ? 32 : 0;
|
||
c |= currprefs.win32_blankmonitors != changed_prefs.win32_blankmonitors ? 32 : 0;
|
||
c |= currprefs.win32_rtgmatchdepth != changed_prefs.win32_rtgmatchdepth ? 2 : 0;
|
||
// c |= currprefs.win32_rtgscalemode != changed_prefs.win32_rtgscalemode ? (2 | 8 | 64) : 0;
|
||
c |= currprefs.win32_rtgallowscaling != changed_prefs.win32_rtgallowscaling ? (2 | 8 | 64) : 0;
|
||
c |= currprefs.win32_rtgscaleaspectratio != changed_prefs.win32_rtgscaleaspectratio ? (8 | 64) : 0;
|
||
c |= currprefs.win32_rtgvblankrate != changed_prefs.win32_rtgvblankrate ? 8 : 0;
|
||
|
||
|
||
if (display_change_requested || c)
|
||
{
|
||
bool setpause = false;
|
||
bool dontcapture = false;
|
||
int keepfsmode =
|
||
currprefs.gfx_apmode[0].gfx_fullscreen == changed_prefs.gfx_apmode[0].gfx_fullscreen &&
|
||
currprefs.gfx_apmode[1].gfx_fullscreen == changed_prefs.gfx_apmode[1].gfx_fullscreen;
|
||
|
||
currprefs.gfx_autoresolution = changed_prefs.gfx_autoresolution;
|
||
currprefs.gfx_autoresolution_vga = changed_prefs.gfx_autoresolution_vga;
|
||
currprefs.color_mode = changed_prefs.color_mode;
|
||
currprefs.lightboost_strobo = changed_prefs.lightboost_strobo;
|
||
|
||
if (currprefs.gfx_api != changed_prefs.gfx_api) {
|
||
display_change_requested = 1;
|
||
}
|
||
|
||
if (c & 128) {
|
||
// hres/vres change
|
||
rp_screenmode_changed();
|
||
}
|
||
|
||
if (display_change_requested) {
|
||
if (display_change_requested == 3) {
|
||
c = 1024;
|
||
} else if (display_change_requested == 2) {
|
||
c = 512;
|
||
} else if (display_change_requested == 4) {
|
||
c = 32;
|
||
} else {
|
||
c = 2;
|
||
keepfsmode = 0;
|
||
if (display_change_requested <= -1) {
|
||
dontcapture = true;
|
||
if (display_change_requested == -2)
|
||
setpause = true;
|
||
if (pause_emulation)
|
||
setpause = true;
|
||
}
|
||
}
|
||
display_change_requested = 0;
|
||
}
|
||
|
||
for (int j = 0; j < MAX_FILTERDATA; j++) {
|
||
struct gfx_filterdata *gf = &currprefs.gf[j];
|
||
struct gfx_filterdata *gfc = &changed_prefs.gf[j];
|
||
memcpy(gf, gfc, sizeof(struct gfx_filterdata));
|
||
}
|
||
|
||
currprefs.rtg_horiz_zoom_mult = changed_prefs.rtg_horiz_zoom_mult;
|
||
currprefs.rtg_vert_zoom_mult = changed_prefs.rtg_vert_zoom_mult;
|
||
|
||
currprefs.gfx_luminance = changed_prefs.gfx_luminance;
|
||
currprefs.gfx_contrast = changed_prefs.gfx_contrast;
|
||
currprefs.gfx_gamma = changed_prefs.gfx_gamma;
|
||
|
||
currprefs.gfx_resolution = changed_prefs.gfx_resolution;
|
||
currprefs.gfx_vresolution = changed_prefs.gfx_vresolution;
|
||
currprefs.gfx_autoresolution_minh = changed_prefs.gfx_autoresolution_minh;
|
||
currprefs.gfx_autoresolution_minv = changed_prefs.gfx_autoresolution_minv;
|
||
currprefs.gfx_iscanlines = changed_prefs.gfx_iscanlines;
|
||
currprefs.gfx_pscanlines = changed_prefs.gfx_pscanlines;
|
||
currprefs.monitoremu = changed_prefs.monitoremu;
|
||
|
||
currprefs.genlock_image = changed_prefs.genlock_image;
|
||
currprefs.genlock = changed_prefs.genlock;
|
||
currprefs.genlock_mix = changed_prefs.genlock_mix;
|
||
currprefs.genlock_alpha = changed_prefs.genlock_alpha;
|
||
currprefs.genlock_aspect = changed_prefs.genlock_aspect;
|
||
currprefs.genlock_scale = changed_prefs.genlock_scale;
|
||
_tcscpy(currprefs.genlock_image_file, changed_prefs.genlock_image_file);
|
||
_tcscpy(currprefs.genlock_video_file, changed_prefs.genlock_video_file);
|
||
|
||
currprefs.gfx_lores_mode = changed_prefs.gfx_lores_mode;
|
||
currprefs.gfx_overscanmode = changed_prefs.gfx_overscanmode;
|
||
currprefs.gfx_scandoubler = changed_prefs.gfx_scandoubler;
|
||
currprefs.gfx_threebitcolors = changed_prefs.gfx_threebitcolors;
|
||
currprefs.gfx_grayscale = changed_prefs.gfx_grayscale;
|
||
currprefs.gfx_monitorblankdelay = changed_prefs.gfx_monitorblankdelay;
|
||
|
||
currprefs.gfx_display_sections = changed_prefs.gfx_display_sections;
|
||
currprefs.gfx_variable_sync = changed_prefs.gfx_variable_sync;
|
||
currprefs.gfx_windowed_resize = changed_prefs.gfx_windowed_resize;
|
||
|
||
currprefs.gfx_apmode[APMODE_NATIVE].gfx_display = changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_display;
|
||
currprefs.gfx_apmode[APMODE_RTG].gfx_display = changed_prefs.gfx_apmode[APMODE_RTG].gfx_display;
|
||
currprefs.gfx_blackerthanblack = changed_prefs.gfx_blackerthanblack;
|
||
currprefs.gfx_apmode[APMODE_NATIVE].gfx_backbuffers = changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_backbuffers;
|
||
currprefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced = changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced;
|
||
currprefs.gfx_apmode[APMODE_RTG].gfx_backbuffers = changed_prefs.gfx_apmode[APMODE_RTG].gfx_backbuffers;
|
||
|
||
currprefs.win32_main_alwaysontop = changed_prefs.win32_main_alwaysontop;
|
||
currprefs.win32_gui_alwaysontop = changed_prefs.win32_gui_alwaysontop;
|
||
currprefs.win32_nonotificationicon = changed_prefs.win32_nonotificationicon;
|
||
currprefs.win32_notaskbarbutton = changed_prefs.win32_notaskbarbutton;
|
||
currprefs.win32_borderless = changed_prefs.win32_borderless;
|
||
currprefs.win32_blankmonitors = changed_prefs.win32_blankmonitors;
|
||
currprefs.win32_statusbar = changed_prefs.win32_statusbar;
|
||
currprefs.win32_rtgmatchdepth = changed_prefs.win32_rtgmatchdepth;
|
||
// currprefs.win32_rtgscalemode = changed_prefs.win32_rtgscalemode;
|
||
currprefs.win32_rtgallowscaling = changed_prefs.win32_rtgallowscaling;
|
||
currprefs.win32_rtgscaleaspectratio = changed_prefs.win32_rtgscaleaspectratio;
|
||
currprefs.win32_rtgvblankrate = changed_prefs.win32_rtgvblankrate;
|
||
|
||
bool unacquired = false;
|
||
for (int monid = MAX_AMIGAMONITORS - 1; monid >= 0; monid--) {
|
||
if (!monitors[monid])
|
||
continue;
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
|
||
if (c & 64) {
|
||
if (!unacquired) {
|
||
inputdevice_unacquire();
|
||
unacquired = true;
|
||
}
|
||
}
|
||
if (c & 256) {
|
||
init_colors(mon->monitor_id);
|
||
reset_drawing();
|
||
}
|
||
if (c & 128) {
|
||
if (currprefs.gfx_autoresolution) {
|
||
c |= 2 | 8;
|
||
} else {
|
||
c |= 16;
|
||
reset_drawing();
|
||
S2X_reset(mon->monitor_id);
|
||
}
|
||
}
|
||
if (c & 1024) {
|
||
target_graphics_buffer_update(mon->monitor_id);
|
||
}
|
||
if (c & 512) {
|
||
reopen_gfx(mon);
|
||
}
|
||
if ((c & 16) || ((c & 8) && keepfsmode)) {
|
||
if (reopen(mon, c & 2, unacquired == false)) {
|
||
c |= 2;
|
||
} else {
|
||
unacquired = true;
|
||
}
|
||
}
|
||
if ((c & 32) || ((c & 2) && !keepfsmode)) {
|
||
if (!unacquired) {
|
||
inputdevice_unacquire();
|
||
unacquired = true;
|
||
}
|
||
close_windows(mon);
|
||
if (currprefs.gfx_api != changed_prefs.gfx_api || currprefs.gfx_api_options != changed_prefs.gfx_api_options) {
|
||
currprefs.gfx_api = changed_prefs.gfx_api;
|
||
currprefs.gfx_api_options = changed_prefs.gfx_api_options;
|
||
d3d_select(&currprefs);
|
||
}
|
||
graphics_init(dontcapture ? false : true);
|
||
}
|
||
}
|
||
|
||
init_custom();
|
||
if (c & 4) {
|
||
pause_sound();
|
||
reset_sound();
|
||
resume_sound();
|
||
}
|
||
|
||
if (setpause || dontcapture) {
|
||
if (!unacquired)
|
||
inputdevice_unacquire();
|
||
unacquired = false;
|
||
}
|
||
|
||
if (unacquired)
|
||
inputdevice_acquire(TRUE);
|
||
|
||
if (setpause)
|
||
setpaused(1);
|
||
|
||
return 1;
|
||
}
|
||
|
||
bool changed = false;
|
||
for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) {
|
||
if (currprefs.cr[i].rate != changed_prefs.cr[i].rate ||
|
||
currprefs.cr[i].locked != changed_prefs.cr[i].locked) {
|
||
memcpy (&currprefs.cr[i], &changed_prefs.cr[i], sizeof (struct chipset_refresh));
|
||
changed = true;
|
||
}
|
||
}
|
||
if (changed) {
|
||
init_hz_normal();
|
||
}
|
||
if (currprefs.chipset_refreshrate != changed_prefs.chipset_refreshrate) {
|
||
currprefs.chipset_refreshrate = changed_prefs.chipset_refreshrate;
|
||
init_hz_normal();
|
||
return 1;
|
||
}
|
||
|
||
if (
|
||
currprefs.gf[0].gfx_filter_autoscale != changed_prefs.gf[0].gfx_filter_autoscale ||
|
||
currprefs.gf[2].gfx_filter_autoscale != changed_prefs.gf[2].gfx_filter_autoscale ||
|
||
currprefs.gfx_xcenter_pos != changed_prefs.gfx_xcenter_pos ||
|
||
currprefs.gfx_ycenter_pos != changed_prefs.gfx_ycenter_pos ||
|
||
currprefs.gfx_xcenter_size != changed_prefs.gfx_xcenter_size ||
|
||
currprefs.gfx_ycenter_size != changed_prefs.gfx_ycenter_size ||
|
||
currprefs.gfx_xcenter != changed_prefs.gfx_xcenter ||
|
||
currprefs.gfx_ycenter != changed_prefs.gfx_ycenter)
|
||
{
|
||
currprefs.gfx_xcenter_pos = changed_prefs.gfx_xcenter_pos;
|
||
currprefs.gfx_ycenter_pos = changed_prefs.gfx_ycenter_pos;
|
||
currprefs.gfx_xcenter_size = changed_prefs.gfx_xcenter_size;
|
||
currprefs.gfx_ycenter_size = changed_prefs.gfx_ycenter_size;
|
||
currprefs.gfx_xcenter = changed_prefs.gfx_xcenter;
|
||
currprefs.gfx_ycenter = changed_prefs.gfx_ycenter;
|
||
currprefs.gf[0].gfx_filter_autoscale = changed_prefs.gf[0].gfx_filter_autoscale;
|
||
currprefs.gf[2].gfx_filter_autoscale = changed_prefs.gf[2].gfx_filter_autoscale;
|
||
|
||
get_custom_limits (NULL, NULL, NULL, NULL, NULL);
|
||
fixup_prefs_dimensions (&changed_prefs);
|
||
|
||
return 1;
|
||
}
|
||
|
||
currprefs.win32_norecyclebin = changed_prefs.win32_norecyclebin;
|
||
currprefs.filesys_limit = changed_prefs.filesys_limit;
|
||
currprefs.harddrive_read_only = changed_prefs.harddrive_read_only;
|
||
|
||
if (currprefs.win32_logfile != changed_prefs.win32_logfile) {
|
||
currprefs.win32_logfile = changed_prefs.win32_logfile;
|
||
if (currprefs.win32_logfile)
|
||
logging_open (0, 1);
|
||
else
|
||
logging_cleanup ();
|
||
}
|
||
|
||
if (currprefs.leds_on_screen != changed_prefs.leds_on_screen ||
|
||
currprefs.keyboard_leds[0] != changed_prefs.keyboard_leds[0] ||
|
||
currprefs.keyboard_leds[1] != changed_prefs.keyboard_leds[1] ||
|
||
currprefs.keyboard_leds[2] != changed_prefs.keyboard_leds[2] ||
|
||
currprefs.input_mouse_untrap != changed_prefs.input_mouse_untrap ||
|
||
currprefs.win32_minimize_inactive != changed_prefs.win32_minimize_inactive ||
|
||
currprefs.win32_active_capture_priority != changed_prefs.win32_active_capture_priority ||
|
||
currprefs.win32_inactive_priority != changed_prefs.win32_inactive_priority ||
|
||
currprefs.win32_iconified_priority != changed_prefs.win32_iconified_priority ||
|
||
currprefs.win32_active_nocapture_nosound != changed_prefs.win32_active_nocapture_nosound ||
|
||
currprefs.win32_active_nocapture_pause != changed_prefs.win32_active_nocapture_pause ||
|
||
currprefs.win32_active_input != changed_prefs.win32_active_input ||
|
||
currprefs.win32_inactive_nosound != changed_prefs.win32_inactive_nosound ||
|
||
currprefs.win32_inactive_pause != changed_prefs.win32_inactive_pause ||
|
||
currprefs.win32_inactive_input != changed_prefs.win32_inactive_input ||
|
||
currprefs.win32_iconified_nosound != changed_prefs.win32_iconified_nosound ||
|
||
currprefs.win32_iconified_pause != changed_prefs.win32_iconified_pause ||
|
||
currprefs.win32_iconified_input != changed_prefs.win32_iconified_input ||
|
||
currprefs.win32_capture_always != changed_prefs.win32_capture_always ||
|
||
currprefs.win32_ctrl_F11_is_quit != changed_prefs.win32_ctrl_F11_is_quit ||
|
||
currprefs.win32_shutdown_notification != changed_prefs.win32_shutdown_notification ||
|
||
currprefs.win32_warn_exit != changed_prefs.win32_warn_exit ||
|
||
currprefs.win32_gui_control != changed_prefs.win32_gui_control ||
|
||
currprefs.turbo_boot != changed_prefs.turbo_boot ||
|
||
currprefs.right_control_is_right_win_key != changed_prefs.right_control_is_right_win_key)
|
||
{
|
||
currprefs.win32_minimize_inactive = changed_prefs.win32_minimize_inactive;
|
||
currprefs.leds_on_screen = changed_prefs.leds_on_screen;
|
||
currprefs.keyboard_leds[0] = changed_prefs.keyboard_leds[0];
|
||
currprefs.keyboard_leds[1] = changed_prefs.keyboard_leds[1];
|
||
currprefs.keyboard_leds[2] = changed_prefs.keyboard_leds[2];
|
||
currprefs.input_mouse_untrap = changed_prefs.input_mouse_untrap;
|
||
currprefs.win32_active_capture_priority = changed_prefs.win32_active_capture_priority;
|
||
currprefs.win32_inactive_priority = changed_prefs.win32_inactive_priority;
|
||
currprefs.win32_iconified_priority = changed_prefs.win32_iconified_priority;
|
||
currprefs.win32_active_nocapture_nosound = changed_prefs.win32_active_nocapture_nosound;
|
||
currprefs.win32_active_input = changed_prefs.win32_active_input;
|
||
currprefs.win32_active_nocapture_pause = changed_prefs.win32_active_nocapture_pause;
|
||
currprefs.win32_inactive_nosound = changed_prefs.win32_inactive_nosound;
|
||
currprefs.win32_inactive_pause = changed_prefs.win32_inactive_pause;
|
||
currprefs.win32_inactive_input = changed_prefs.win32_inactive_input;
|
||
currprefs.win32_iconified_nosound = changed_prefs.win32_iconified_nosound;
|
||
currprefs.win32_iconified_pause = changed_prefs.win32_iconified_pause;
|
||
currprefs.win32_iconified_input = changed_prefs.win32_iconified_input;
|
||
currprefs.win32_capture_always = changed_prefs.win32_capture_always;
|
||
currprefs.win32_ctrl_F11_is_quit = changed_prefs.win32_ctrl_F11_is_quit;
|
||
currprefs.win32_shutdown_notification = changed_prefs.win32_shutdown_notification;
|
||
currprefs.win32_warn_exit = changed_prefs.win32_warn_exit;
|
||
currprefs.win32_gui_control = changed_prefs.win32_gui_control;
|
||
currprefs.turbo_boot = changed_prefs.turbo_boot;
|
||
currprefs.right_control_is_right_win_key = changed_prefs.right_control_is_right_win_key;
|
||
inputdevice_unacquire ();
|
||
currprefs.keyboard_leds_in_use = changed_prefs.keyboard_leds_in_use = (currprefs.keyboard_leds[0] | currprefs.keyboard_leds[1] | currprefs.keyboard_leds[2]) != 0;
|
||
pause_sound ();
|
||
resume_sound ();
|
||
refreshtitle();
|
||
inputdevice_acquire (TRUE);
|
||
#ifndef _DEBUG
|
||
setpriority (&priorities[currprefs.win32_active_capture_priority]);
|
||
#endif
|
||
return 1;
|
||
}
|
||
|
||
if (currprefs.win32_samplersoundcard != changed_prefs.win32_samplersoundcard ||
|
||
currprefs.sampler_stereo != changed_prefs.sampler_stereo) {
|
||
currprefs.win32_samplersoundcard = changed_prefs.win32_samplersoundcard;
|
||
currprefs.sampler_stereo = changed_prefs.sampler_stereo;
|
||
sampler_free ();
|
||
}
|
||
|
||
if (_tcscmp (currprefs.prtname, changed_prefs.prtname) ||
|
||
currprefs.parallel_autoflush_time != changed_prefs.parallel_autoflush_time ||
|
||
currprefs.parallel_matrix_emulation != changed_prefs.parallel_matrix_emulation ||
|
||
currprefs.parallel_postscript_emulation != changed_prefs.parallel_postscript_emulation ||
|
||
currprefs.parallel_postscript_detection != changed_prefs.parallel_postscript_detection ||
|
||
_tcscmp (currprefs.ghostscript_parameters, changed_prefs.ghostscript_parameters)) {
|
||
_tcscpy (currprefs.prtname, changed_prefs.prtname);
|
||
currprefs.parallel_autoflush_time = changed_prefs.parallel_autoflush_time;
|
||
currprefs.parallel_matrix_emulation = changed_prefs.parallel_matrix_emulation;
|
||
currprefs.parallel_postscript_emulation = changed_prefs.parallel_postscript_emulation;
|
||
currprefs.parallel_postscript_detection = changed_prefs.parallel_postscript_detection;
|
||
_tcscpy (currprefs.ghostscript_parameters, changed_prefs.ghostscript_parameters);
|
||
#ifdef PARALLEL_PORT
|
||
closeprinter ();
|
||
#endif
|
||
}
|
||
if (_tcscmp (currprefs.sername, changed_prefs.sername) ||
|
||
currprefs.serial_hwctsrts != changed_prefs.serial_hwctsrts ||
|
||
currprefs.serial_direct != changed_prefs.serial_direct ||
|
||
currprefs.serial_demand != changed_prefs.serial_demand) {
|
||
_tcscpy (currprefs.sername, changed_prefs.sername);
|
||
currprefs.serial_hwctsrts = changed_prefs.serial_hwctsrts;
|
||
currprefs.serial_demand = changed_prefs.serial_demand;
|
||
currprefs.serial_direct = changed_prefs.serial_direct;
|
||
#ifdef SERIAL_PORT
|
||
serial_exit ();
|
||
serial_init ();
|
||
#endif
|
||
}
|
||
if (currprefs.win32_midiindev != changed_prefs.win32_midiindev ||
|
||
currprefs.win32_midioutdev != changed_prefs.win32_midioutdev ||
|
||
currprefs.win32_midirouter != changed_prefs.win32_midirouter)
|
||
{
|
||
currprefs.win32_midiindev = changed_prefs.win32_midiindev;
|
||
currprefs.win32_midioutdev = changed_prefs.win32_midioutdev;
|
||
currprefs.win32_midirouter = changed_prefs.win32_midirouter;
|
||
|
||
#ifdef SERIAL_PORT
|
||
serial_exit();
|
||
serial_init();
|
||
Midi_Reopen();
|
||
#endif
|
||
#ifdef WITH_MIDIEMU
|
||
midi_emu_reopen();
|
||
#endif
|
||
}
|
||
|
||
if (currprefs.win32_powersavedisabled != changed_prefs.win32_powersavedisabled) {
|
||
|
||
currprefs.win32_powersavedisabled = changed_prefs.win32_powersavedisabled;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/* Color management */
|
||
|
||
static xcolnr xcol8[4096];
|
||
|
||
static int red_bits, green_bits, blue_bits, alpha_bits;
|
||
static int red_shift, green_shift, blue_shift, alpha_shift;
|
||
static int alpha;
|
||
|
||
void init_colors(int monid)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
/* init colors */
|
||
D3D_getpixelformat (mon->currentmode.current_depth,
|
||
&red_bits, &green_bits, &blue_bits, &red_shift, &green_shift, &blue_shift, &alpha_bits, &alpha_shift, &alpha);
|
||
|
||
if (!(mon->currentmode.flags & (DM_D3D))) {
|
||
if (mon->currentmode.current_depth != mon->currentmode.native_depth) {
|
||
if (mon->currentmode.current_depth == 16) {
|
||
red_bits = 5; green_bits = 6; blue_bits = 5;
|
||
red_shift = 11; green_shift = 5; blue_shift = 0;
|
||
} else {
|
||
red_bits = green_bits = blue_bits = 8;
|
||
red_shift = 16; green_shift = 8; blue_shift = 0;
|
||
}
|
||
}
|
||
}
|
||
alloc_colors64k(monid, red_bits, green_bits, blue_bits, red_shift,green_shift, blue_shift, alpha_bits, alpha_shift, alpha, 0, mon->usedfilter && mon->usedfilter->yuv);
|
||
notice_new_xcolors ();
|
||
#ifdef GFXFILTER
|
||
S2X_configure(monid, red_bits, green_bits, blue_bits, red_shift,green_shift, blue_shift);
|
||
#endif
|
||
#ifdef AVIOUTPUT
|
||
AVIOutput_RGBinfo (red_bits, green_bits, blue_bits, alpha_bits, red_shift, green_shift, blue_shift, alpha_shift);
|
||
#endif
|
||
Screenshot_RGBinfo (red_bits, green_bits, blue_bits, alpha_bits, red_shift, green_shift, blue_shift, alpha_shift);
|
||
}
|
||
|
||
#ifdef PICASSO96
|
||
|
||
int picasso_palette(struct MyCLUTEntry *CLUT, uae_u32 *clut)
|
||
{
|
||
int changed = 0;
|
||
|
||
for (int i = 0; i < 256 * 2; i++) {
|
||
int r = CLUT[i].Red;
|
||
int g = CLUT[i].Green;
|
||
int b = CLUT[i].Blue;
|
||
uae_u32 v = (doMask256 (r, red_bits, red_shift)
|
||
| doMask256 (g, green_bits, green_shift)
|
||
| doMask256 (b, blue_bits, blue_shift))
|
||
| doMask256 ((1 << alpha_bits) - 1, alpha_bits, alpha_shift);
|
||
if (v != clut[i]) {
|
||
//write_log (_T("%d:%08x\n"), i, v);
|
||
clut[i] = v;
|
||
changed = 1;
|
||
}
|
||
}
|
||
return changed;
|
||
}
|
||
|
||
void DX_Invalidate(struct AmigaMonitor *mon, int x, int y, int width, int height)
|
||
{
|
||
struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[mon->monitor_id];
|
||
int last, lastx;
|
||
|
||
if (width == 0 || height == 0)
|
||
return;
|
||
if (y < 0 || height < 0) {
|
||
y = 0;
|
||
height = vidinfo->height;
|
||
}
|
||
if (x < 0 || width < 0) {
|
||
x = 0;
|
||
width = vidinfo->width;
|
||
}
|
||
last = y + height - 1;
|
||
lastx = x + width - 1;
|
||
mon->p96_double_buffer_first = y;
|
||
mon->p96_double_buffer_last = last;
|
||
mon->p96_double_buffer_firstx = x;
|
||
mon->p96_double_buffer_lastx = lastx;
|
||
mon->p96_double_buffer_needs_flushing = 1;
|
||
}
|
||
|
||
#endif
|
||
|
||
static void open_screen(struct AmigaMonitor *mon)
|
||
{
|
||
close_windows(mon);
|
||
open_windows(mon, true, true);
|
||
}
|
||
|
||
static int ifs(struct AmigaMonitor *mon, struct uae_prefs *p)
|
||
{
|
||
int idx = mon->screen_is_picasso ? 1 : 0;
|
||
return p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLSCREEN ? 1 : (p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLWINDOW ? -1 : 0);
|
||
}
|
||
|
||
static int reopen(struct AmigaMonitor *mon, int full, bool unacquire)
|
||
{
|
||
struct amigadisplay *ad = &adisplays[mon->monitor_id];
|
||
int quick = 0;
|
||
int idx = mon->screen_is_picasso ? 1 : 0;
|
||
struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
|
||
|
||
updatewinfsmode(mon->monitor_id, &changed_prefs);
|
||
|
||
if (changed_prefs.gfx_apmode[0].gfx_fullscreen != currprefs.gfx_apmode[0].gfx_fullscreen && !mon->screen_is_picasso)
|
||
full = 1;
|
||
if (changed_prefs.gfx_apmode[1].gfx_fullscreen != currprefs.gfx_apmode[1].gfx_fullscreen && mon->screen_is_picasso)
|
||
full = 1;
|
||
|
||
/* fullscreen to fullscreen? */
|
||
if (isfullscreen () > 0 && currprefs.gfx_apmode[0].gfx_fullscreen == changed_prefs.gfx_apmode[0].gfx_fullscreen &&
|
||
currprefs.gfx_apmode[1].gfx_fullscreen == changed_prefs.gfx_apmode[1].gfx_fullscreen && currprefs.gfx_apmode[0].gfx_fullscreen == GFX_FULLSCREEN) {
|
||
quick = 1;
|
||
}
|
||
/* windowed to windowed */
|
||
if (isfullscreen () <= 0 && currprefs.gfx_apmode[0].gfx_fullscreen == changed_prefs.gfx_apmode[0].gfx_fullscreen &&
|
||
currprefs.gfx_apmode[1].gfx_fullscreen == changed_prefs.gfx_apmode[1].gfx_fullscreen) {
|
||
quick = 1;
|
||
}
|
||
|
||
currprefs.gfx_monitor[mon->monitor_id].gfx_size_fs.width = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_fs.width;
|
||
currprefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height;
|
||
currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.width = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.width;
|
||
currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.height = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.height;
|
||
currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.x = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.x;
|
||
currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.y = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.y;
|
||
|
||
currprefs.gfx_apmode[0].gfx_fullscreen = changed_prefs.gfx_apmode[0].gfx_fullscreen;
|
||
currprefs.gfx_apmode[1].gfx_fullscreen = changed_prefs.gfx_apmode[1].gfx_fullscreen;
|
||
currprefs.gfx_apmode[0].gfx_vsync = changed_prefs.gfx_apmode[0].gfx_vsync;
|
||
currprefs.gfx_apmode[1].gfx_vsync = changed_prefs.gfx_apmode[1].gfx_vsync;
|
||
currprefs.gfx_apmode[0].gfx_vsyncmode = changed_prefs.gfx_apmode[0].gfx_vsyncmode;
|
||
currprefs.gfx_apmode[1].gfx_vsyncmode = changed_prefs.gfx_apmode[1].gfx_vsyncmode;
|
||
currprefs.gfx_apmode[0].gfx_refreshrate = changed_prefs.gfx_apmode[0].gfx_refreshrate;
|
||
|
||
currprefs.rtg_horiz_zoom_mult = changed_prefs.rtg_horiz_zoom_mult;
|
||
currprefs.rtg_vert_zoom_mult = changed_prefs.rtg_vert_zoom_mult;
|
||
|
||
#if 0
|
||
currprefs.gfx_apmode[1].gfx_refreshrate = changed_prefs.gfx_apmode[1].gfx_refreshrate;
|
||
#endif
|
||
set_config_changed ();
|
||
|
||
if (!quick)
|
||
return 1;
|
||
|
||
if (unacquire) {
|
||
inputdevice_unacquire ();
|
||
}
|
||
|
||
reopen_gfx(mon);
|
||
|
||
return 0;
|
||
}
|
||
|
||
bool vsync_switchmode(int monid, int hz)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
static struct PicassoResolution *oldmode;
|
||
static int oldhz;
|
||
int w = mon->currentmode.native_width;
|
||
int h = mon->currentmode.native_height;
|
||
int d = mon->currentmode.native_depth / 8;
|
||
struct MultiDisplay *md = getdisplay(&currprefs, monid);
|
||
struct PicassoResolution *found;
|
||
int newh, i, cnt;
|
||
bool preferdouble = 0, preferlace = 0;
|
||
bool lace = false;
|
||
|
||
if (currprefs.gfx_apmode[APMODE_NATIVE].gfx_refreshrate > 85) {
|
||
preferdouble = 1;
|
||
} else if (currprefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced) {
|
||
preferlace = 1;
|
||
}
|
||
|
||
if (hz >= 55)
|
||
hz = 60;
|
||
else
|
||
hz = 50;
|
||
|
||
newh = h * (currprefs.ntscmode ? 60 : 50) / hz;
|
||
|
||
found = NULL;
|
||
for (cnt = 0; cnt <= abs (newh - h) + 1 && !found; cnt++) {
|
||
for (int dbl = 0; dbl < 2 && !found; dbl++) {
|
||
bool doublecheck = false;
|
||
bool lacecheck = false;
|
||
if (preferdouble && dbl == 0)
|
||
doublecheck = true;
|
||
else if (preferlace && dbl == 0)
|
||
lacecheck = true;
|
||
|
||
for (int extra = 1; extra >= -1 && !found; extra--) {
|
||
for (i = 0; md->DisplayModes[i].depth >= 0 && !found; i++) {
|
||
struct PicassoResolution *r = &md->DisplayModes[i];
|
||
if (r->res.width == w && (r->res.height == newh + cnt || r->res.height == newh - cnt) && r->depth == d) {
|
||
int j;
|
||
for (j = 0; r->refresh[j] > 0; j++) {
|
||
if (doublecheck) {
|
||
if (r->refreshtype[j] & REFRESH_RATE_LACE)
|
||
continue;
|
||
if (r->refresh[j] == hz * 2 + extra) {
|
||
found = r;
|
||
hz = r->refresh[j];
|
||
break;
|
||
}
|
||
} else if (lacecheck) {
|
||
if (!(r->refreshtype[j] & REFRESH_RATE_LACE))
|
||
continue;
|
||
if (r->refresh[j] * 2 == hz + extra) {
|
||
found = r;
|
||
lace = true;
|
||
hz = r->refresh[j];
|
||
break;
|
||
}
|
||
} else {
|
||
if (r->refresh[j] == hz + extra) {
|
||
found = r;
|
||
hz = r->refresh[j];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (found == oldmode && hz == oldhz)
|
||
return true;
|
||
oldmode = found;
|
||
oldhz = hz;
|
||
if (!found) {
|
||
changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_vsync = 0;
|
||
if (currprefs.gfx_apmode[APMODE_NATIVE].gfx_vsync != changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_vsync) {
|
||
set_config_changed ();
|
||
}
|
||
write_log (_T("refresh rate changed to %d%s but no matching screenmode found, vsync disabled\n"), hz, lace ? _T("i") : _T("p"));
|
||
return false;
|
||
} else {
|
||
newh = found->res.height;
|
||
changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height = newh;
|
||
changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_refreshrate = hz;
|
||
changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced = lace;
|
||
if (changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height != currprefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height ||
|
||
changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_refreshrate != currprefs.gfx_apmode[APMODE_NATIVE].gfx_refreshrate) {
|
||
write_log (_T("refresh rate changed to %d%s, new screenmode %dx%d\n"), hz, lace ? _T("i") : _T("p"), w, newh);
|
||
set_config_changed ();
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
|
||
void vsync_clear(void)
|
||
{
|
||
vsync_active = false;
|
||
if (waitvblankevent)
|
||
ResetEvent(waitvblankevent);
|
||
}
|
||
|
||
int vsync_isdone(frame_time_t *dt)
|
||
{
|
||
if (isvsync() == 0)
|
||
return -1;
|
||
if (waitvblankthread_mode <= 0)
|
||
return -2;
|
||
if (dt)
|
||
*dt = wait_vblank_timestamp;
|
||
return vsync_active ? 1 : 0;
|
||
}
|
||
|
||
#ifdef PICASSO96
|
||
|
||
static int modeswitchneeded(struct AmigaMonitor *mon, struct winuae_currentmode *wc)
|
||
{
|
||
struct vidbuf_description *avidinfo = &adisplays[mon->monitor_id].gfxvidinfo;
|
||
struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
|
||
|
||
if (isfullscreen () > 0) {
|
||
/* fullscreen to fullscreen */
|
||
if (mon->screen_is_picasso) {
|
||
if (state->BytesPerPixel > 1 && state->BytesPerPixel * 8 != wc->current_depth && canmatchdepth())
|
||
return -1;
|
||
if (state->Width < wc->current_width && state->Height < wc->current_height) {
|
||
if ((currprefs.gf[GF_RTG].gfx_filter_autoscale == 1 || (currprefs.gf[GF_RTG].gfx_filter_autoscale == 2 && currprefs.win32_rtgallowscaling)) && !canmatchdepth())
|
||
return 0;
|
||
}
|
||
if (state->Width != wc->current_width ||
|
||
state->Height != wc->current_height)
|
||
return 1;
|
||
if (state->Width == wc->current_width &&
|
||
state->Height == wc->current_height) {
|
||
if (state->BytesPerPixel * 8 == wc->current_depth || state->BytesPerPixel == 1)
|
||
return 0;
|
||
if (!canmatchdepth())
|
||
return 0;
|
||
}
|
||
return 1;
|
||
} else {
|
||
if (mon->currentmode.current_width != wc->current_width ||
|
||
mon->currentmode.current_height != wc->current_height ||
|
||
mon->currentmode.current_depth != wc->current_depth)
|
||
return -1;
|
||
if (!avidinfo->outbuffer->bufmem_lockable)
|
||
return -1;
|
||
}
|
||
} else if (isfullscreen () == 0) {
|
||
/* windowed to windowed */
|
||
return -2;
|
||
} else {
|
||
/* fullwindow to fullwindow */
|
||
if (mon->screen_is_picasso) {
|
||
if (currprefs.gf[GF_RTG].gfx_filter_autoscale && ((wc->native_width > state->Width && wc->native_height >= state->Height) || (wc->native_height > state->Height && wc->native_width >= state->Width)))
|
||
return -1;
|
||
if (currprefs.win32_rtgallowscaling && (state->Width != wc->native_width || state->Height != wc->native_height))
|
||
return -1;
|
||
#if 0
|
||
if (wc->native_width < state->Width || wc->native_height < state->Height)
|
||
return 1;
|
||
#endif
|
||
}
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void gfx_set_picasso_state(int monid, int on)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct winuae_currentmode wc;
|
||
struct apmode *newmode, *oldmode;
|
||
struct gfx_filterdata *newf, *oldf;
|
||
int mode;
|
||
|
||
if (mon->screen_is_picasso == on)
|
||
return;
|
||
mon->screen_is_picasso = on;
|
||
rp_rtg_switch ();
|
||
memcpy (&wc, &mon->currentmode, sizeof (wc));
|
||
|
||
newmode = &currprefs.gfx_apmode[on ? 1 : 0];
|
||
oldmode = &currprefs.gfx_apmode[on ? 0 : 1];
|
||
|
||
newf = &currprefs.gf[on ? 1 : 0];
|
||
oldf = &currprefs.gf[on ? 0 : 1];
|
||
|
||
updatemodes(mon);
|
||
update_gfxparams(mon);
|
||
|
||
// if filter changes, need to reset
|
||
mode = 0;
|
||
if (newf->gfx_filter != oldf->gfx_filter)
|
||
mode = -1;
|
||
for (int i = 0; i <= 2 * MAX_FILTERSHADERS; i++) {
|
||
if (_tcscmp(newf->gfx_filtershader[i], oldf->gfx_filtershader[i]))
|
||
mode = -1;
|
||
if (_tcscmp(newf->gfx_filtermask[i], oldf->gfx_filtermask[i]))
|
||
mode = -1;
|
||
}
|
||
bool differentmonitor = getdisplay(&currprefs, newmode->gfx_display) != getdisplay(&currprefs, oldmode->gfx_display);
|
||
// if screen parameter changes, need to reopen window
|
||
if (newmode->gfx_fullscreen != oldmode->gfx_fullscreen ||
|
||
(newmode->gfx_fullscreen && (
|
||
newmode->gfx_backbuffers != oldmode->gfx_backbuffers ||
|
||
differentmonitor ||
|
||
newmode->gfx_refreshrate != oldmode->gfx_refreshrate ||
|
||
newmode->gfx_strobo != oldmode->gfx_strobo ||
|
||
newmode->gfx_vflip != oldmode->gfx_vflip ||
|
||
newmode->gfx_vsync != oldmode->gfx_vsync))) {
|
||
mode = 1;
|
||
}
|
||
if (mode <= 0) {
|
||
int m = modeswitchneeded(mon, &wc);
|
||
if (m > 0)
|
||
mode = m;
|
||
if (m < 0 && !mode)
|
||
mode = m;
|
||
if (!mode)
|
||
goto end;
|
||
}
|
||
if (mode < 0) {
|
||
open_windows(mon, true, true);
|
||
} else {
|
||
open_screen(mon); // reopen everything
|
||
}
|
||
end:
|
||
#ifdef RETROPLATFORM
|
||
rp_set_hwnd (mon->hAmigaWnd);
|
||
#endif
|
||
}
|
||
|
||
static void updatepicasso96(struct AmigaMonitor *mon)
|
||
{
|
||
#ifdef PICASSO96
|
||
struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[mon->monitor_id];
|
||
vidinfo->rowbytes = 0;
|
||
vidinfo->pixbytes = mon->currentmode.current_depth / 8;
|
||
vidinfo->rgbformat = 0;
|
||
vidinfo->extra_mem = 1;
|
||
vidinfo->height = mon->currentmode.current_height;
|
||
vidinfo->width = mon->currentmode.current_width;
|
||
vidinfo->depth = mon->currentmode.current_depth;
|
||
vidinfo->offset = 0;
|
||
vidinfo->splitypos = -1;
|
||
#endif
|
||
}
|
||
|
||
void gfx_set_picasso_modeinfo(int monid, RGBFTYPE rgbfmt)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
|
||
int need;
|
||
if (!mon->screen_is_picasso)
|
||
return;
|
||
gfx_set_picasso_colors(monid, rgbfmt);
|
||
update_gfxparams(mon);
|
||
updatemodes(mon);
|
||
need = modeswitchneeded(mon, &mon->currentmode);
|
||
if (need > 0) {
|
||
open_screen(mon);
|
||
} else if (need < 0) {
|
||
open_windows(mon, true, true);
|
||
}
|
||
state->ModeChanged = false;
|
||
#ifdef RETROPLATFORM
|
||
rp_set_hwnd(mon->hAmigaWnd);
|
||
#endif
|
||
target_graphics_buffer_update(monid);
|
||
}
|
||
#endif
|
||
|
||
void gfx_set_picasso_colors(int monid, RGBFTYPE rgbfmt)
|
||
{
|
||
alloc_colors_picasso(red_bits, green_bits, blue_bits, red_shift, green_shift, blue_shift, rgbfmt, p96_rgbx16);
|
||
}
|
||
|
||
static void gfxmode_reset(int monid)
|
||
{
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
struct uae_filter **usedfilter = &AMonitors[monid].usedfilter;
|
||
|
||
#ifdef GFXFILTER
|
||
*usedfilter = NULL;
|
||
if (currprefs.gf[ad->gf_index].gfx_filter > 0) {
|
||
int i = 0;
|
||
while (uaefilters[i].name) {
|
||
if (uaefilters[i].type == currprefs.gf[ad->gf_index].gfx_filter) {
|
||
*usedfilter = &uaefilters[i];
|
||
break;
|
||
}
|
||
i++;
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
int machdep_init(void)
|
||
{
|
||
for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
|
||
struct AmigaMonitor *mon = &AMonitors[i];
|
||
struct amigadisplay *ad = &adisplays[i];
|
||
mon->monitor_id = i;
|
||
ad->picasso_requested_on = 0;
|
||
ad->picasso_on = 0;
|
||
mon->screen_is_picasso = 0;
|
||
memset(&mon->currentmode, 0, sizeof(*&mon->currentmode));
|
||
}
|
||
#ifdef LOGITECHLCD
|
||
lcd_open ();
|
||
#endif
|
||
systray (hHiddenWnd, FALSE);
|
||
return 1;
|
||
}
|
||
|
||
void machdep_free(void)
|
||
{
|
||
#ifdef LOGITECHLCD
|
||
lcd_close ();
|
||
#endif
|
||
}
|
||
|
||
int graphics_init(bool mousecapture)
|
||
{
|
||
InitializeDarkMode();
|
||
systray (hHiddenWnd, TRUE);
|
||
systray (hHiddenWnd, FALSE);
|
||
d3d_select(&currprefs);
|
||
gfxmode_reset(0);
|
||
if (open_windows(&AMonitors[0], mousecapture, false)) {
|
||
if (currprefs.monitoremu_mon > 0 && currprefs.monitoremu) {
|
||
gfxmode_reset(currprefs.monitoremu_mon);
|
||
open_windows(&AMonitors[currprefs.monitoremu_mon], mousecapture, false);
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
int graphics_setup(void)
|
||
{
|
||
if (!screen_cs_allocated) {
|
||
InitializeCriticalSection(&screen_cs);
|
||
screen_cs_allocated = true;
|
||
}
|
||
#ifdef PICASSO96
|
||
InitPicasso96(0);
|
||
#endif
|
||
return 1;
|
||
}
|
||
|
||
void graphics_leave(void)
|
||
{
|
||
for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
|
||
close_windows(&AMonitors[i]);
|
||
}
|
||
}
|
||
|
||
uae_u32 OSDEP_minimize_uae (void)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[0];
|
||
return ShowWindow(mon->hAmigaWnd, SW_MINIMIZE);
|
||
}
|
||
|
||
typedef HRESULT (CALLBACK* DWMENABLEMMCSS)(BOOL);
|
||
static void setDwmEnableMMCSS (bool state)
|
||
{
|
||
HMODULE hm = GetModuleHandle(_T("dwmapi.dll"));
|
||
if (hm) {
|
||
DWMENABLEMMCSS pDwmEnableMMCSS;
|
||
pDwmEnableMMCSS = (DWMENABLEMMCSS)GetProcAddress(hm, "DwmEnableMMCSS");
|
||
if (pDwmEnableMMCSS)
|
||
pDwmEnableMMCSS(state);
|
||
}
|
||
}
|
||
|
||
void close_windows(struct AmigaMonitor *mon)
|
||
{
|
||
struct vidbuf_description *avidinfo = &adisplays[mon->monitor_id].gfxvidinfo;
|
||
|
||
setDwmEnableMMCSS (FALSE);
|
||
reset_sound ();
|
||
#if defined (GFXFILTER)
|
||
S2X_free(mon->monitor_id);
|
||
#endif
|
||
freevidbuffer(mon->monitor_id, &avidinfo->drawbuffer);
|
||
freevidbuffer(mon->monitor_id, &avidinfo->tempbuffer);
|
||
close_hwnds(mon);
|
||
}
|
||
|
||
static void createstatuswindow(struct AmigaMonitor *mon)
|
||
{
|
||
RECT rc;
|
||
HLOCAL hloc;
|
||
LPINT lpParts;
|
||
int drive_width, hd_width, cd_width, power_width;
|
||
int fps_width, idle_width, snd_width, joy_width, net_width;
|
||
int joys = currprefs.win32_statusbar > 1 ? 2 : 0;
|
||
int num_parts = 12 + joys + 1;
|
||
float scale = 1.0;
|
||
WINDOWINFO wi;
|
||
int extra;
|
||
|
||
if (mon->hStatusWnd) {
|
||
ShowWindow(mon->hStatusWnd, SW_HIDE);
|
||
DestroyWindow(mon->hStatusWnd);
|
||
mon->hStatusWnd = NULL;
|
||
}
|
||
if (currprefs.win32_statusbar == 0 || mon->monitor_id > 0)
|
||
return;
|
||
if (isfullscreen () != 0)
|
||
return;
|
||
if (currprefs.win32_borderless)
|
||
return;
|
||
|
||
mon->hStatusWnd = CreateWindowEx (
|
||
WS_EX_COMPOSITED, STATUSCLASSNAME, (LPCTSTR) NULL, SBARS_TOOLTIPS | WS_CHILD | WS_VISIBLE,
|
||
0, 0, 0, 0, mon->hMainWnd, (HMENU) 1, hInst, NULL);
|
||
if (!mon->hStatusWnd)
|
||
return;
|
||
if (g_darkModeSupported) {
|
||
BOOL value = g_darkModeEnabled;
|
||
DwmSetWindowAttribute(mon->hStatusWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
|
||
if (g_darkModeEnabled) {
|
||
SubClassStatusBar(mon->hStatusWnd);
|
||
}
|
||
}
|
||
wi.cbSize = sizeof wi;
|
||
GetWindowInfo(mon->hMainWnd, &wi);
|
||
extra = wi.rcClient.top - wi.rcWindow.top;
|
||
scale = getdpiforwindow(mon->hStatusWnd) / 96.0f;
|
||
drive_width = (int)(24 * scale);
|
||
hd_width = (int)(24 * scale);
|
||
cd_width = (int)(24 * scale);
|
||
power_width = (int)(42 * scale);
|
||
fps_width = (int)(64 * scale);
|
||
idle_width = (int)(64 * scale);
|
||
net_width = (int)(24 * scale);
|
||
if (is_ppc_cpu(&currprefs))
|
||
idle_width += (int)(68 * scale);
|
||
if (is_x86_cpu(&currprefs))
|
||
idle_width += (int)(68 * scale);
|
||
snd_width = (int)(72 * scale);
|
||
joy_width = (int)(24 * scale);
|
||
GetClientRect(mon->hMainWnd, &rc);
|
||
/* Allocate an array for holding the right edge coordinates. */
|
||
hloc = LocalAlloc (LHND, sizeof (int) * (num_parts + 1));
|
||
if (hloc) {
|
||
lpParts = (LPINT)LocalLock(hloc);
|
||
if (lpParts) {
|
||
int i = 0, i1;
|
||
// left side, msg area
|
||
lpParts[i] = rc.left;
|
||
i++;
|
||
window_led_msg_start = i;
|
||
/* Calculate the right edge coordinate for each part, and copy the coords to the array. */
|
||
int startx = rc.right - (drive_width * 4) - power_width - idle_width - fps_width - cd_width - hd_width - snd_width - net_width - joys * joy_width - extra;
|
||
for (int j = 0; j < joys; j++) {
|
||
lpParts[i] = startx;
|
||
i++;
|
||
startx += joy_width;
|
||
}
|
||
window_led_joy_start = i;
|
||
if (lpParts[0] >= startx)
|
||
lpParts[0] = startx - 1;
|
||
// snd
|
||
lpParts[i] = startx;
|
||
i++;
|
||
// cpu
|
||
lpParts[i] = lpParts[i - 1] + snd_width;
|
||
i++;
|
||
// fps
|
||
lpParts[i] = lpParts[i - 1] + idle_width;
|
||
i++;
|
||
// power
|
||
lpParts[i] = lpParts[i - 1] + fps_width;
|
||
i++;
|
||
i1 = i;
|
||
// hd
|
||
lpParts[i] = lpParts[i - 1] + power_width;
|
||
i++;
|
||
// cd
|
||
lpParts[i] = lpParts[i - 1] + hd_width;
|
||
i++;
|
||
// net
|
||
lpParts[i] = lpParts[i - 1] + cd_width;
|
||
i++;
|
||
// df0
|
||
lpParts[i] = lpParts[i - 1] + net_width;
|
||
i++;
|
||
// df1
|
||
lpParts[i] = lpParts[i - 1] + drive_width;
|
||
i++;
|
||
// df2
|
||
lpParts[i] = lpParts[i - 1] + drive_width;
|
||
i++;
|
||
// df3
|
||
lpParts[i] = lpParts[i - 1] + drive_width;
|
||
i++;
|
||
// edge
|
||
lpParts[i] = lpParts[i - 1] + drive_width;
|
||
|
||
window_led_msg = lpParts[window_led_msg_start - 1];
|
||
window_led_msg_end = lpParts[window_led_msg_start - 1 + 1];
|
||
window_led_joys = lpParts[window_led_joy_start - joys];
|
||
window_led_joys_end = lpParts[window_led_joy_start - joys + 1];
|
||
window_led_hd = lpParts[i1];
|
||
window_led_hd_end = lpParts[i1 + 1];
|
||
window_led_drives = lpParts[i1 + 3];
|
||
window_led_drives_end = lpParts[i1 + 3 + 4];
|
||
|
||
/* Create the parts */
|
||
SendMessage(mon->hStatusWnd, SB_SETPARTS, (WPARAM)num_parts, (LPARAM)lpParts);
|
||
LocalUnlock(hloc);
|
||
LocalFree(hloc);
|
||
}
|
||
}
|
||
registertouch(mon->hStatusWnd);
|
||
}
|
||
|
||
#if 0
|
||
#include <dbt.h>
|
||
|
||
static int createnotification (HWND hwnd)
|
||
{
|
||
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
|
||
HDEVNOTIFY hDevNotify;
|
||
|
||
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
|
||
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
||
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||
|
||
hDevNotify = RegisterDeviceNotification(hMainWnd,
|
||
&NotificationFilter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
|
||
|
||
if(!hDevNotify)
|
||
{
|
||
write_log (_T("RegisterDeviceNotification failed: %d\n"), GetLastError());
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
#endif
|
||
|
||
static int getbestmode(struct AmigaMonitor *mon, int nextbest)
|
||
{
|
||
int i, startidx;
|
||
struct MultiDisplay *md;
|
||
int ratio;
|
||
int index = -1;
|
||
|
||
for(;;) {
|
||
md = getdisplay2(&currprefs, index);
|
||
if (!md)
|
||
return 0;
|
||
ratio = mon->currentmode.native_width > mon->currentmode.native_height ? 1 : 0;
|
||
for (i = 0; md->DisplayModes[i].depth >= 0; i++) {
|
||
struct PicassoResolution *pr = &md->DisplayModes[i];
|
||
if (pr->res.width == mon->currentmode.native_width && pr->res.height == mon->currentmode.native_height)
|
||
break;
|
||
}
|
||
if (md->DisplayModes[i].depth >= 0) {
|
||
if (!nextbest)
|
||
break;
|
||
while (md->DisplayModes[i].res.width == mon->currentmode.native_width && md->DisplayModes[i].res.height == mon->currentmode.native_height)
|
||
i++;
|
||
} else {
|
||
i = 0;
|
||
}
|
||
// first iterate only modes that have similar aspect ratio
|
||
startidx = i;
|
||
for (; md->DisplayModes[i].depth >= 0; i++) {
|
||
struct PicassoResolution *pr = &md->DisplayModes[i];
|
||
int r = pr->res.width > pr->res.height ? 1 : 0;
|
||
if (pr->res.width >= mon->currentmode.native_width && pr->res.height >= mon->currentmode.native_height && r == ratio) {
|
||
write_log (_T("FS: %dx%d -> %dx%d %d %d\n"), mon->currentmode.native_width, mon->currentmode.native_height,
|
||
pr->res.width, pr->res.height, ratio, index);
|
||
mon->currentmode.native_width = pr->res.width;
|
||
mon->currentmode.native_height = pr->res.height;
|
||
mon->currentmode.current_width = mon->currentmode.native_width;
|
||
mon->currentmode.current_height = mon->currentmode.native_height;
|
||
goto end;
|
||
}
|
||
}
|
||
// still not match? check all modes
|
||
i = startidx;
|
||
for (; md->DisplayModes[i].depth >= 0; i++) {
|
||
struct PicassoResolution *pr = &md->DisplayModes[i];
|
||
int r = pr->res.width > pr->res.height ? 1 : 0;
|
||
if (pr->res.width >= mon->currentmode.native_width && pr->res.height >= mon->currentmode.native_height) {
|
||
write_log (_T("FS: %dx%d -> %dx%d\n"), mon->currentmode.native_width, mon->currentmode.native_height,
|
||
pr->res.width, pr->res.height);
|
||
mon->currentmode.native_width = pr->res.width;
|
||
mon->currentmode.native_height = pr->res.height;
|
||
mon->currentmode.current_width = mon->currentmode.native_width;
|
||
mon->currentmode.current_height = mon->currentmode.native_height;
|
||
goto end;
|
||
}
|
||
}
|
||
index++;
|
||
}
|
||
end:
|
||
if (index >= 0) {
|
||
currprefs.gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display =
|
||
changed_prefs.gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display = index;
|
||
write_log (L"Can't find mode %dx%d ->\n", mon->currentmode.native_width, mon->currentmode.native_height);
|
||
write_log (L"Monitor switched to '%s'\n", md->adaptername);
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
float target_getcurrentvblankrate(int monid)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
float vb;
|
||
if (currprefs.gfx_variable_sync)
|
||
return (float)mon->currentmode.freq;
|
||
if (get_display_vblank_params(-1, NULL, NULL, &vb, NULL)) {
|
||
return vb;
|
||
} else {
|
||
return D3D_getrefreshrate(0);
|
||
}
|
||
}
|
||
|
||
static void movecursor (int x, int y)
|
||
{
|
||
write_log (_T("SetCursorPos %dx%d\n"), x, y);
|
||
SetCursorPos (x, y);
|
||
}
|
||
|
||
static void getextramonitorpos(struct AmigaMonitor *mon, RECT *r)
|
||
{
|
||
TCHAR buf[100];
|
||
RECT r1, r2;
|
||
int x, y;
|
||
bool got = true;
|
||
|
||
_stprintf(buf, _T("MainPosX_%d"), mon->monitor_id);
|
||
if (!regqueryint(NULL, buf, &x)) {
|
||
got = false;
|
||
}
|
||
_stprintf(buf, _T("MainPosY_%d"), mon->monitor_id);
|
||
if (!regqueryint(NULL, buf, &y)) {
|
||
got = false;
|
||
}
|
||
if (got) {
|
||
POINT pt;
|
||
pt.x = x;
|
||
pt.y = y;
|
||
if (!MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
||
got = false;
|
||
}
|
||
}
|
||
// find rightmost window edge
|
||
int monid = MAX_AMIGAMONITORS - 1;
|
||
int rightmon = -1;
|
||
int rightedge = 0;
|
||
HWND hwnd = NULL;
|
||
for (;;) {
|
||
if (monid < 1)
|
||
break;
|
||
monid--;
|
||
hwnd = AMonitors[monid].hMainWnd;
|
||
if (!hwnd)
|
||
continue;
|
||
GetWindowRect(hwnd, &r1);
|
||
if (r1.right > rightedge) {
|
||
rightedge = r1.right;
|
||
rightmon = monid;
|
||
}
|
||
}
|
||
if (rightmon < 0 && !got)
|
||
return;
|
||
hwnd = AMonitors[rightmon].hMainWnd;
|
||
GetWindowRect(hwnd, &r1);
|
||
r2 = r1;
|
||
|
||
getextendedframebounds(hwnd, &r2);
|
||
int width = r->right - r->left;
|
||
int height = r->bottom - r->top;
|
||
|
||
if (got) {
|
||
r->left = x;
|
||
r->top = y;
|
||
} else {
|
||
r->left = r1.right - ((r2.left - r1.left) + (r1.right - r2.right));
|
||
r->top = r1.top;
|
||
}
|
||
r->bottom = r->top + height;
|
||
r->right = r->left + width;
|
||
}
|
||
|
||
static int create_windows(struct AmigaMonitor *mon)
|
||
{
|
||
static bool firstwindow = true;
|
||
int dxfs = mon->currentmode.flags & (DM_DX_FULLSCREEN);
|
||
int d3dfs = mon->currentmode.flags & (DM_D3D_FULLSCREEN);
|
||
int fsw = mon->currentmode.flags & (DM_W_FULLSCREEN);
|
||
DWORD exstyle = (currprefs.win32_notaskbarbutton ? WS_EX_TOOLWINDOW : WS_EX_APPWINDOW) | 0;
|
||
DWORD flags = 0;
|
||
int borderless = currprefs.win32_borderless;
|
||
DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||
int cyborder = GetSystemMetrics (SM_CYFRAME);
|
||
int gap = 0;
|
||
int x, y, w, h;
|
||
struct MultiDisplay *md;
|
||
|
||
md = getdisplay(&currprefs, mon->monitor_id);
|
||
if (mon->monitor_id && fsw) {
|
||
struct MultiDisplay *md2 = NULL;
|
||
int idx = 0;
|
||
for (;;) {
|
||
md2 = getdisplay2(&currprefs, idx);
|
||
if (md2 == md)
|
||
break;
|
||
if (!md2)
|
||
break;
|
||
idx++;
|
||
}
|
||
for (int i = 0; i <= mon->monitor_id; i++) {
|
||
md2 = getdisplay2(&currprefs, idx);
|
||
if (!md2)
|
||
idx = 0;
|
||
else
|
||
idx++;
|
||
}
|
||
if (md2)
|
||
md = md2;
|
||
}
|
||
mon->md = md;
|
||
|
||
if (mon->hAmigaWnd) {
|
||
RECT r;
|
||
int w, h, x, y;
|
||
int nw, nh, nx, ny;
|
||
|
||
if (minimized) {
|
||
minimized = -1;
|
||
return 1;
|
||
}
|
||
#if 0
|
||
if (minimized && hMainWnd) {
|
||
unsetminimized ();
|
||
ShowWindow (hMainWnd, SW_SHOW);
|
||
ShowWindow (hMainWnd, SW_RESTORE);
|
||
}
|
||
#endif
|
||
GetWindowRect (mon->hAmigaWnd, &r);
|
||
|
||
int sbheight = currprefs.win32_statusbar && !currprefs.win32_borderless ? getstatuswindowheight(mon->monitor_id, mon->hAmigaWnd) : 0;
|
||
int dpi = getdpiforwindow(mon->hAmigaWnd);
|
||
|
||
x = r.left;
|
||
y = r.top;
|
||
w = r.right - r.left;
|
||
h = r.bottom - r.top;
|
||
nx = x;
|
||
ny = y;
|
||
|
||
if (mon->screen_is_picasso) {
|
||
nw = mon->currentmode.current_width;
|
||
nh = mon->currentmode.current_height;
|
||
} else {
|
||
nw = currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.width;
|
||
nh = currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.height;
|
||
}
|
||
|
||
if (fsw || dxfs) {
|
||
RECT rc = md->rect;
|
||
nx = rc.left;
|
||
ny = rc.top;
|
||
nw = rc.right - rc.left;
|
||
nh = rc.bottom - rc.top;
|
||
} else if (d3dfs) {
|
||
RECT rc = md->rect;
|
||
nw = mon->currentmode.native_width;
|
||
nh = mon->currentmode.native_height;
|
||
if (rc.left >= 0)
|
||
nx = rc.left;
|
||
else
|
||
nx = rc.left + (rc.right - rc.left - nw);
|
||
if (rc.top >= 0)
|
||
ny = rc.top;
|
||
else
|
||
ny = rc.top + (rc.bottom - rc.top - nh);
|
||
}
|
||
|
||
if (w != nw || h != nh || x != nx || y != ny || sbheight != mon->window_extra_height_bar || dpi != mon->dpi) {
|
||
w = nw;
|
||
h = nh;
|
||
x = nx;
|
||
y = ny;
|
||
mon->in_sizemove++;
|
||
if (mon->hMainWnd && !fsw && !dxfs && !d3dfs && !rp_isactive()) {
|
||
if (dpi != mon->dpi) {
|
||
mon->window_extra_height -= mon->window_extra_height_bar;
|
||
mon->window_extra_height += sbheight;
|
||
} else {
|
||
mon->window_extra_height += (sbheight - mon->window_extra_height_bar);
|
||
}
|
||
|
||
GetWindowRect(mon->hMainWnd, &r);
|
||
#if 0
|
||
RECT r2;
|
||
GetClientRect(mon->hMainWnd, &r2);
|
||
if (pAdjustWindowRectExForDpi) {
|
||
HMONITOR mon = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST);
|
||
pAdjustWindowRectExForDpi(&r, borderless ? WS_POPUP : style, FALSE, exstyle, getdpiformonitor(mon));
|
||
} else {
|
||
AdjustWindowRectEx(&r, borderless ? WS_POPUP : style, FALSE, exstyle);
|
||
}
|
||
#endif
|
||
x = r.left;
|
||
y = r.top;
|
||
SetWindowPos(mon->hMainWnd, HWND_TOP, x, y, w + mon->window_extra_width, h + mon->window_extra_height,
|
||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER);
|
||
x = gap;
|
||
y = gap;
|
||
}
|
||
SetWindowPos(mon->hAmigaWnd, HWND_TOP, x, y, w, h,
|
||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER);
|
||
mon->in_sizemove--;
|
||
mon->dpi = dpi;
|
||
} else {
|
||
w = nw;
|
||
h = nh;
|
||
x = nx;
|
||
y = ny;
|
||
}
|
||
createstatuswindow(mon);
|
||
createstatusline(mon->hAmigaWnd, mon->monitor_id);
|
||
updatewinrect(mon, false);
|
||
GetWindowRect (mon->hMainWnd, &mon->mainwin_rect);
|
||
if (d3dfs || dxfs)
|
||
movecursor (x + w / 2, y + h / 2);
|
||
write_log (_T("window already open (%dx%d %dx%d)\n"),
|
||
mon->amigawin_rect.left, mon->amigawin_rect.top, mon->amigawin_rect.right - mon->amigawin_rect.left, mon->amigawin_rect.bottom - mon->amigawin_rect.top);
|
||
updatemouseclip(mon);
|
||
rp_screenmode_changed ();
|
||
mon->window_extra_height_bar = sbheight;
|
||
return 1;
|
||
}
|
||
|
||
gfx_lock();
|
||
D3D_free(mon->monitor_id, false);
|
||
gfx_unlock();
|
||
|
||
if (fsw && !borderless)
|
||
borderless = 1;
|
||
window_led_drives = 0;
|
||
window_led_drives_end = 0;
|
||
mon->hMainWnd = NULL;
|
||
x = 0; y = 0;
|
||
|
||
int sbheight = currprefs.win32_statusbar && !currprefs.win32_borderless ? getstatuswindowheight(mon->monitor_id, NULL) : 0;
|
||
|
||
if (borderless)
|
||
sbheight = cyborder = 0;
|
||
|
||
if (!dxfs && !d3dfs) {
|
||
RECT rc;
|
||
int stored_x = 1, stored_y = sbheight + cyborder;
|
||
int oldx, oldy;
|
||
int first = 2;
|
||
|
||
regqueryint (NULL, _T("MainPosX"), &stored_x);
|
||
regqueryint (NULL, _T("MainPosY"), &stored_y);
|
||
|
||
if (borderless) {
|
||
stored_x = currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.x;
|
||
stored_y = currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.y;
|
||
}
|
||
|
||
while (first) {
|
||
first--;
|
||
if (stored_x < GetSystemMetrics (SM_XVIRTUALSCREEN))
|
||
stored_x = GetSystemMetrics (SM_XVIRTUALSCREEN);
|
||
if (stored_y < GetSystemMetrics (SM_YVIRTUALSCREEN) + sbheight + cyborder)
|
||
stored_y = GetSystemMetrics (SM_YVIRTUALSCREEN) + sbheight + cyborder;
|
||
|
||
if (stored_x > GetSystemMetrics (SM_CXVIRTUALSCREEN))
|
||
rc.left = 1;
|
||
else
|
||
rc.left = stored_x;
|
||
|
||
if (stored_y > GetSystemMetrics (SM_CYVIRTUALSCREEN))
|
||
rc.top = 1;
|
||
else
|
||
rc.top = stored_y;
|
||
|
||
rc.right = rc.left + gap + mon->currentmode.current_width + gap;
|
||
rc.bottom = rc.top + gap + mon->currentmode.current_height + gap + sbheight;
|
||
|
||
oldx = rc.left;
|
||
oldy = rc.top;
|
||
if (pAdjustWindowRectExForDpi) {
|
||
HMONITOR mon = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
|
||
pAdjustWindowRectExForDpi(&rc, borderless ? WS_POPUP : style, FALSE, exstyle, getdpiformonitor(mon));
|
||
} else {
|
||
AdjustWindowRectEx(&rc, borderless ? WS_POPUP : style, FALSE, exstyle);
|
||
}
|
||
mon->win_x_diff = rc.left - oldx;
|
||
mon->win_y_diff = rc.top - oldy;
|
||
|
||
if (MonitorFromRect (&rc, MONITOR_DEFAULTTONULL) == NULL) {
|
||
write_log (_T("window coordinates are not visible on any monitor, reseting..\n"));
|
||
stored_x = stored_y = 0;
|
||
continue;
|
||
}
|
||
|
||
if (mon->monitor_id > 0) {
|
||
getextramonitorpos(mon, &rc);
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (fsw) {
|
||
rc = md->rect;
|
||
flags |= WS_EX_TOPMOST;
|
||
style = WS_POPUP;
|
||
mon->currentmode.native_width = rc.right - rc.left;
|
||
mon->currentmode.native_height = rc.bottom - rc.top;
|
||
}
|
||
if (currprefs.gfx_api < 2) {
|
||
flags |= currprefs.win32_main_alwaysontop ? WS_EX_TOPMOST : 0;
|
||
}
|
||
|
||
if (!borderless) {
|
||
RECT rc2;
|
||
int sbheight2 = -1;
|
||
for (;;) {
|
||
mon->hMainWnd = CreateWindowEx(WS_EX_ACCEPTFILES | exstyle | flags,
|
||
_T("PCsuxRox"), _T("WinUAE"),
|
||
style,
|
||
rc.left, rc.top,
|
||
rc.right - rc.left, rc.bottom - rc.top,
|
||
NULL, NULL, hInst, NULL);
|
||
if (!mon->hMainWnd) {
|
||
write_log(_T("main window creation failed\n"));
|
||
return 0;
|
||
}
|
||
if (sbheight && sbheight2 < 0 && !fsw) {
|
||
// recheck, system could have multiple monitors with different DPI
|
||
sbheight2 = getstatuswindowheight(mon->monitor_id, mon->hMainWnd);
|
||
if (sbheight2 != sbheight) {
|
||
rc.bottom -= sbheight;
|
||
rc.bottom += sbheight2;
|
||
sbheight = sbheight2;
|
||
DestroyWindow(mon->hMainWnd);
|
||
mon->hMainWnd = NULL;
|
||
continue;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
if (g_darkModeSupported) {
|
||
BOOL value = g_darkModeEnabled;
|
||
DwmSetWindowAttribute(mon->hMainWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
|
||
}
|
||
GetWindowRect(mon->hMainWnd, &rc2);
|
||
mon->window_extra_width = rc2.right - rc2.left - mon->currentmode.current_width;
|
||
mon->window_extra_height = rc2.bottom - rc2.top - mon->currentmode.current_height;
|
||
createstatuswindow(mon);
|
||
createstatusline(mon->hMainWnd, mon->monitor_id);
|
||
} else {
|
||
x = rc.left;
|
||
y = rc.top;
|
||
}
|
||
w = mon->currentmode.native_width;
|
||
h = mon->currentmode.native_height;
|
||
|
||
} else {
|
||
|
||
RECT rc;
|
||
getbestmode(mon, 0);
|
||
w = mon->currentmode.native_width;
|
||
h = mon->currentmode.native_height;
|
||
rc = md->rect;
|
||
if (rc.left >= 0)
|
||
x = rc.left;
|
||
else
|
||
x = rc.left + (rc.right - rc.left - w);
|
||
if (rc.top >= 0)
|
||
y = rc.top;
|
||
else
|
||
y = rc.top + (rc.bottom - rc.top - h);
|
||
}
|
||
|
||
if (rp_isactive () && !dxfs && !d3dfs && !fsw) {
|
||
HWND parent = rp_getparent ();
|
||
mon->hAmigaWnd = CreateWindowEx (dxfs || d3dfs ? WS_EX_ACCEPTFILES | WS_EX_TOPMOST : WS_EX_ACCEPTFILES | WS_EX_TOOLWINDOW | (currprefs.win32_main_alwaysontop ? WS_EX_TOPMOST : 0),
|
||
_T("AmigaPowah"), _T("WinUAE"),
|
||
WS_POPUP,
|
||
0, 0, w, h,
|
||
parent, NULL, hInst, NULL);
|
||
} else {
|
||
mon->hAmigaWnd = CreateWindowEx (
|
||
((dxfs || d3dfs || currprefs.win32_main_alwaysontop) ? WS_EX_TOPMOST : WS_EX_ACCEPTFILES) | exstyle,
|
||
_T("AmigaPowah"), _T("WinUAE"),
|
||
((dxfs || d3dfs || currprefs.headless) ? WS_POPUP : (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | (mon->hMainWnd ? WS_VISIBLE | WS_CHILD : WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX))),
|
||
x, y, w, h,
|
||
borderless ? NULL : (mon->hMainWnd ? mon->hMainWnd : NULL),
|
||
NULL, hInst, NULL);
|
||
}
|
||
if (!mon->hAmigaWnd) {
|
||
write_log (_T("creation of amiga window failed\n"));
|
||
close_hwnds(mon);
|
||
return 0;
|
||
}
|
||
if (g_darkModeSupported) {
|
||
BOOL value = g_darkModeEnabled;
|
||
DwmSetWindowAttribute(mon->hAmigaWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
|
||
}
|
||
if (mon->hMainWnd == NULL) {
|
||
mon->hMainWnd = mon->hAmigaWnd;
|
||
registertouch(mon->hAmigaWnd);
|
||
} else {
|
||
registertouch(mon->hMainWnd);
|
||
registertouch(mon->hAmigaWnd);
|
||
}
|
||
|
||
updatewinrect(mon, true);
|
||
GetWindowRect(mon->hMainWnd, &mon->mainwin_rect);
|
||
if (dxfs || d3dfs)
|
||
movecursor (x + w / 2, y + h / 2);
|
||
addnotifications (mon->hAmigaWnd, FALSE, FALSE);
|
||
mon->window_extra_height_bar = sbheight;
|
||
mon->dpi = getdpiforwindow(mon->hAmigaWnd);
|
||
|
||
if (mon->monitor_id) {
|
||
ShowWindow(mon->hMainWnd, SW_SHOWNOACTIVATE);
|
||
UpdateWindow(mon->hMainWnd);
|
||
ShowWindow(mon->hAmigaWnd, SW_SHOWNOACTIVATE);
|
||
UpdateWindow(mon->hAmigaWnd);
|
||
} else {
|
||
createblankwindows();
|
||
if (mon->hMainWnd != mon->hAmigaWnd) {
|
||
if (!currprefs.headless && !rp_isactive())
|
||
ShowWindow(mon->hMainWnd, firstwindow ? (currprefs.win32_start_minimized ? SW_SHOWMINIMIZED : SW_SHOWDEFAULT) : SW_SHOWNORMAL);
|
||
UpdateWindow(mon->hMainWnd);
|
||
}
|
||
if (!currprefs.headless && !rp_isactive())
|
||
ShowWindow(mon->hAmigaWnd, SW_SHOWNORMAL);
|
||
UpdateWindow(mon->hAmigaWnd);
|
||
firstwindow = false;
|
||
setDwmEnableMMCSS(true);
|
||
rawinput_alloc();
|
||
|
||
if (currprefs.win32_shutdown_notification && !rp_isactive()) {
|
||
typedef BOOL(WINAPI *SHUTDOWNBLOCKREASONCREATE)(HWND, LPCWSTR);
|
||
SHUTDOWNBLOCKREASONCREATE pShutdownBlockReasonCreate;
|
||
pShutdownBlockReasonCreate = (SHUTDOWNBLOCKREASONCREATE)GetProcAddress(userdll, "ShutdownBlockReasonCreate");
|
||
if (pShutdownBlockReasonCreate) {
|
||
TCHAR tmp[MAX_DPATH];
|
||
WIN32GUI_LoadUIString(IDS_SHUTDOWN_NOTIFICATION, tmp, MAX_DPATH);
|
||
if (!pShutdownBlockReasonCreate(mon->hMainWnd, tmp)) {
|
||
write_log(_T("ShutdownBlockReasonCreate %08x\n"), GetLastError());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
static void allocsoftbuffer(int monid, const TCHAR *name, struct vidbuffer *buf, int flags, int width, int height, int depth)
|
||
{
|
||
struct vidbuf_description *vidinfo = &adisplays[monid].gfxvidinfo;
|
||
|
||
buf->monitor_id = monid;
|
||
buf->pixbytes = (depth + 7) / 8;
|
||
buf->width_allocated = (width + 7) & ~7;
|
||
buf->height_allocated = height;
|
||
|
||
if (!(flags & DM_SWSCALE)) {
|
||
|
||
if (buf != &vidinfo->drawbuffer)
|
||
return;
|
||
|
||
buf->bufmem = NULL;
|
||
buf->bufmemend = NULL;
|
||
buf->realbufmem = NULL;
|
||
buf->bufmem_allocated = NULL;
|
||
buf->bufmem_lockable = true;
|
||
|
||
write_log (_T("Mon %d reserved %s temp buffer (%d*%d*%d)\n"), monid, name, width, height, depth);
|
||
|
||
} else if (flags & DM_SWSCALE) {
|
||
|
||
int w = buf->width_allocated;
|
||
int h = buf->height_allocated;
|
||
int size = (w * 2) * (h * 2) * buf->pixbytes;
|
||
buf->rowbytes = w * 2 * buf->pixbytes;
|
||
buf->realbufmem = xcalloc(uae_u8, size);
|
||
buf->bufmem_allocated = buf->bufmem = buf->realbufmem + (h / 2) * buf->rowbytes + (w / 2) * buf->pixbytes;
|
||
buf->bufmemend = buf->realbufmem + size - buf->rowbytes;
|
||
buf->bufmem_lockable = true;
|
||
|
||
write_log (_T("Mon %d allocated %s temp buffer (%d*%d*%d) = %p\n"), monid, name, width, height, depth, buf->realbufmem);
|
||
}
|
||
}
|
||
|
||
static int oldtex_w[MAX_AMIGAMONITORS], oldtex_h[MAX_AMIGAMONITORS], oldtex_rtg[MAX_AMIGAMONITORS];
|
||
|
||
static BOOL doInit(struct AmigaMonitor *mon)
|
||
{
|
||
int tmp_depth;
|
||
int ret = 0;
|
||
bool modechanged;
|
||
|
||
retry:
|
||
struct vidbuf_description *avidinfo = &adisplays[mon->monitor_id].gfxvidinfo;
|
||
struct amigadisplay *ad = &adisplays[mon->monitor_id];
|
||
|
||
modechanged = true;
|
||
if (wasfullwindow_a == 0)
|
||
wasfullwindow_a = currprefs.gfx_apmode[0].gfx_fullscreen == GFX_FULLWINDOW ? 1 : -1;
|
||
if (wasfullwindow_p == 0)
|
||
wasfullwindow_p = currprefs.gfx_apmode[1].gfx_fullscreen == GFX_FULLWINDOW ? 1 : -1;
|
||
gfxmode_reset(mon->monitor_id);
|
||
freevidbuffer(mon->monitor_id, &avidinfo->drawbuffer);
|
||
freevidbuffer(mon->monitor_id, &avidinfo->tempbuffer);
|
||
|
||
for (;;) {
|
||
updatemodes(mon);
|
||
mon->currentmode.native_depth = 0;
|
||
tmp_depth = mon->currentmode.current_depth;
|
||
|
||
if (mon->currentmode.flags & DM_W_FULLSCREEN) {
|
||
RECT rc = getdisplay(&currprefs, mon->monitor_id)->rect;
|
||
mon->currentmode.native_width = rc.right - rc.left;
|
||
mon->currentmode.native_height = rc.bottom - rc.top;
|
||
}
|
||
if (!create_windows(mon))
|
||
goto oops;
|
||
#ifdef PICASSO96
|
||
if (mon->screen_is_picasso) {
|
||
break;
|
||
} else {
|
||
#endif
|
||
struct uae_filter *usedfilter = mon->usedfilter;
|
||
mon->currentmode.native_depth = mon->currentmode.current_depth;
|
||
|
||
if (currprefs.gfx_resolution > avidinfo->gfx_resolution_reserved)
|
||
avidinfo->gfx_resolution_reserved = currprefs.gfx_resolution;
|
||
if (currprefs.gfx_vresolution > avidinfo->gfx_vresolution_reserved)
|
||
avidinfo->gfx_vresolution_reserved = currprefs.gfx_vresolution;
|
||
|
||
//gfxvidinfo.drawbuffer.gfx_resolution_reserved = RES_SUPERHIRES;
|
||
|
||
#if defined (GFXFILTER)
|
||
if (mon->currentmode.flags & (DM_D3D | DM_SWSCALE)) {
|
||
if (!currprefs.gfx_autoresolution) {
|
||
mon->currentmode.amiga_width = AMIGA_WIDTH_MAX << currprefs.gfx_resolution;
|
||
mon->currentmode.amiga_height = AMIGA_HEIGHT_MAX << currprefs.gfx_vresolution;
|
||
} else {
|
||
mon->currentmode.amiga_width = AMIGA_WIDTH_MAX << avidinfo->gfx_resolution_reserved;
|
||
mon->currentmode.amiga_height = AMIGA_HEIGHT_MAX << avidinfo->gfx_vresolution_reserved;
|
||
}
|
||
if (avidinfo->gfx_resolution_reserved == RES_SUPERHIRES)
|
||
mon->currentmode.amiga_height *= 2;
|
||
if (mon->currentmode.amiga_height > 1280)
|
||
mon->currentmode.amiga_height = 1280;
|
||
|
||
avidinfo->drawbuffer.inwidth = avidinfo->drawbuffer.outwidth = mon->currentmode.amiga_width;
|
||
avidinfo->drawbuffer.inheight = avidinfo->drawbuffer.outheight = mon->currentmode.amiga_height;
|
||
|
||
if (usedfilter) {
|
||
if ((usedfilter->flags & (UAE_FILTER_MODE_16 | UAE_FILTER_MODE_32)) == (UAE_FILTER_MODE_16 | UAE_FILTER_MODE_32)) {
|
||
mon->currentmode.current_depth = mon->currentmode.native_depth;
|
||
} else {
|
||
mon->currentmode.current_depth = (usedfilter->flags & UAE_FILTER_MODE_32) ? 32 : 16;
|
||
}
|
||
}
|
||
mon->currentmode.pitch = mon->currentmode.amiga_width * mon->currentmode.current_depth >> 3;
|
||
}
|
||
else
|
||
#endif
|
||
{
|
||
mon->currentmode.amiga_width = mon->currentmode.current_width;
|
||
mon->currentmode.amiga_height = mon->currentmode.current_height;
|
||
}
|
||
avidinfo->drawbuffer.pixbytes = mon->currentmode.current_depth >> 3;
|
||
avidinfo->drawbuffer.bufmem = NULL;
|
||
avidinfo->drawbuffer.linemem = NULL;
|
||
avidinfo->drawbuffer.rowbytes = mon->currentmode.pitch;
|
||
break;
|
||
#ifdef PICASSO96
|
||
}
|
||
#endif
|
||
}
|
||
|
||
updatepicasso96(mon);
|
||
|
||
if (!scrlinebuf)
|
||
scrlinebuf = xmalloc (uae_u8, max_uae_width * 4);
|
||
|
||
avidinfo->drawbuffer.emergmem = scrlinebuf; // memcpy from system-memory to video-memory
|
||
|
||
avidinfo->drawbuffer.realbufmem = NULL;
|
||
avidinfo->drawbuffer.bufmem = NULL;
|
||
avidinfo->drawbuffer.bufmem_allocated = NULL;
|
||
avidinfo->drawbuffer.bufmem_lockable = false;
|
||
|
||
avidinfo->outbuffer = &avidinfo->drawbuffer;
|
||
avidinfo->inbuffer = &avidinfo->drawbuffer;
|
||
|
||
if (!mon->screen_is_picasso) {
|
||
|
||
allocsoftbuffer(mon->monitor_id, _T("draw"), &avidinfo->drawbuffer, mon->currentmode.flags,
|
||
1920, 1280, mon->currentmode.current_depth);
|
||
if (currprefs.monitoremu || currprefs.cs_cd32fmv || ((currprefs.genlock || currprefs.genlock_effects) && currprefs.genlock_image) || currprefs.cs_color_burst || currprefs.gfx_grayscale) {
|
||
allocsoftbuffer(mon->monitor_id, _T("monemu"), &avidinfo->tempbuffer, mon->currentmode.flags,
|
||
mon->currentmode.amiga_width > 1024 ? mon->currentmode.amiga_width : 1024,
|
||
mon->currentmode.amiga_height > 1024 ? mon->currentmode.amiga_height : 1024,
|
||
mon->currentmode.current_depth);
|
||
}
|
||
|
||
init_row_map ();
|
||
}
|
||
|
||
S2X_free(mon->monitor_id);
|
||
if (!D3D_isenabled(mon->monitor_id)) {
|
||
for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
|
||
oldtex_w[i] = oldtex_h[i] = -1;
|
||
}
|
||
}
|
||
if (mon->currentmode.flags & DM_D3D) {
|
||
int fmh = mon->screen_is_picasso ? 1 : currprefs.gf[ad->gf_index].gfx_filter_filtermodeh + 1;
|
||
int fmv = mon->screen_is_picasso ? 1 : currprefs.gf[ad->gf_index].gfx_filter_filtermodev + 1 - 1;
|
||
if (currprefs.gf[ad->gf_index].gfx_filter_filtermodev == 0) {
|
||
fmv = fmh;
|
||
}
|
||
int errv = 0;
|
||
const TCHAR *err = D3D_init(mon->hAmigaWnd, mon->monitor_id, mon->currentmode.native_width, mon->currentmode.native_height,
|
||
mon->currentmode.current_depth, &mon->currentmode.freq, fmh, fmv, &errv);
|
||
if (errv > 0) {
|
||
if (errv == 2 && currprefs.gfx_api == 0) {
|
||
write_log("Retrying D3D %s\n", err);
|
||
changed_prefs.gfx_api = currprefs.gfx_api = 2;
|
||
changed_prefs.color_mode = currprefs.color_mode = 5;
|
||
update_gfxparams(mon);
|
||
goto retry;
|
||
}
|
||
gfx_hdr = false;
|
||
if (currprefs.gfx_api >= 2) {
|
||
D3D_free(0, true);
|
||
if (err[0] == 0 && currprefs.color_mode != 5) {
|
||
changed_prefs.color_mode = currprefs.color_mode = 5;
|
||
update_gfxparams(mon);
|
||
goto retry;
|
||
}
|
||
changed_prefs.gfx_api = currprefs.gfx_api = 1;
|
||
d3d_select(&currprefs);
|
||
error_log(_T("Direct3D11 failed to initialize ('%s'), falling back to Direct3D9."), err);
|
||
errv = 0;
|
||
err = D3D_init(mon->hAmigaWnd, mon->monitor_id, mon->currentmode.native_width, mon->currentmode.native_height,
|
||
mon->currentmode.current_depth, &mon->currentmode.freq, fmh, fmv, &errv);
|
||
}
|
||
if (errv > 0) {
|
||
D3D_free(0, true);
|
||
if (isfullscreen() > 0) {
|
||
int idx = mon->screen_is_picasso ? 1 : 0;
|
||
changed_prefs.gfx_apmode[idx].gfx_fullscreen = currprefs.gfx_apmode[idx].gfx_fullscreen = GFX_FULLWINDOW;
|
||
goto retry;
|
||
} else if (currprefs.gfx_api > 0) {
|
||
changed_prefs.gfx_api = currprefs.gfx_api = 0;
|
||
changed_prefs.color_mode = currprefs.color_mode = 5;
|
||
changed_prefs.gf[ad->gf_index].gfx_filter = currprefs.gf[ad->gf_index].gfx_filter = 1;
|
||
update_gfxparams(mon);
|
||
d3d_select(&currprefs);
|
||
error_log(_T("Direct3D9/11 failed to initialize ('%s'), falling back to GDI."), err);
|
||
errv = 0;
|
||
err = D3D_init(mon->hAmigaWnd, mon->monitor_id, mon->currentmode.native_width, mon->currentmode.native_height,
|
||
mon->currentmode.current_depth, &mon->currentmode.freq, fmh, fmv, &errv);
|
||
if (errv) {
|
||
error_log(_T("Failed to initialize any rendering modes."));
|
||
}
|
||
}
|
||
mon->currentmode.current_depth = mon->currentmode.native_depth;
|
||
gfxmode_reset(mon->monitor_id);
|
||
ret = -1;
|
||
goto oops;
|
||
}
|
||
} else if (errv < 0) {
|
||
modechanged = false;
|
||
}
|
||
target_graphics_buffer_update(mon->monitor_id);
|
||
updatewinrect(mon, true);
|
||
}
|
||
|
||
mon->screen_is_initialized = 1;
|
||
|
||
if (modechanged) {
|
||
init_colors(mon->monitor_id);
|
||
display_param_init(mon);
|
||
createstatusline(mon->hAmigaWnd, mon->monitor_id);
|
||
}
|
||
|
||
|
||
picasso_refresh(mon->monitor_id);
|
||
#ifdef RETROPLATFORM
|
||
rp_set_hwnd_delayed();
|
||
#endif
|
||
|
||
if (isfullscreen () != 0) {
|
||
setmouseactive(mon->monitor_id, -1);
|
||
}
|
||
|
||
osk_setup(mon->monitor_id, -2);
|
||
|
||
return 1;
|
||
|
||
oops:
|
||
osk_setup(mon->monitor_id, 0);
|
||
close_hwnds(mon);
|
||
return ret;
|
||
}
|
||
|
||
bool target_graphics_buffer_update(int monid)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
|
||
struct vidbuf_description *avidinfo = &adisplays[monid].gfxvidinfo;
|
||
struct picasso96_state_struct *state = &picasso96_state[monid];
|
||
|
||
static bool graphicsbuffer_retry;
|
||
int w, h;
|
||
|
||
graphicsbuffer_retry = false;
|
||
if (mon->screen_is_picasso) {
|
||
w = state->Width;
|
||
h = state->Height;
|
||
} else {
|
||
struct vidbuffer *vb = avidinfo->drawbuffer.tempbufferinuse ? &avidinfo->tempbuffer : &avidinfo->drawbuffer;
|
||
avidinfo->outbuffer = vb;
|
||
w = vb->outwidth;
|
||
h = vb->outheight;
|
||
}
|
||
|
||
if (oldtex_w[monid] == w && oldtex_h[monid] == h && oldtex_rtg[monid] == mon->screen_is_picasso && D3D_alloctexture(mon->monitor_id, -w, -h)) {
|
||
osk_setup(monid, -2);
|
||
return false;
|
||
}
|
||
|
||
if (!w || !h) {
|
||
oldtex_w[monid] = w;
|
||
oldtex_h[monid] = h;
|
||
oldtex_rtg[monid] = mon->screen_is_picasso;
|
||
return false;
|
||
}
|
||
|
||
S2X_free(mon->monitor_id);
|
||
if (!D3D_alloctexture(mon->monitor_id, w, h)) {
|
||
graphicsbuffer_retry = true;
|
||
return false;
|
||
}
|
||
|
||
oldtex_w[monid] = w;
|
||
oldtex_h[monid] = h;
|
||
oldtex_rtg[monid] = mon->screen_is_picasso;
|
||
osk_setup(monid, -2);
|
||
|
||
write_log (_T("Buffer %d size (%d*%d) %s\n"), monid, w, h, mon->screen_is_picasso ? _T("RTG") : _T("Native"));
|
||
|
||
if ((mon->currentmode.flags & DM_SWSCALE) && !mon->screen_is_picasso) {
|
||
if (!S2X_init(mon->monitor_id, mon->currentmode.native_width, mon->currentmode.native_height, mon->currentmode.native_depth))
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
static void updatedisplayarea2(int monid)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
if (!mon->screen_is_initialized)
|
||
return;
|
||
D3D_refresh(monid);
|
||
}
|
||
|
||
void updatedisplayarea(int monid)
|
||
{
|
||
set_custom_limits(-1, -1, -1, -1, false);
|
||
if (monid >= 0) {
|
||
updatedisplayarea2(monid);
|
||
} else {
|
||
for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
|
||
updatedisplayarea2(i);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
void updatewinfsmode(int monid, struct uae_prefs *p)
|
||
{
|
||
struct MultiDisplay *md;
|
||
|
||
fixup_prefs_dimensions (p);
|
||
if (isfullscreen_2 (p) != 0) {
|
||
p->gfx_monitor[monid].gfx_size = p->gfx_monitor[monid].gfx_size_fs;
|
||
} else {
|
||
p->gfx_monitor[monid].gfx_size = p->gfx_monitor[monid].gfx_size_win;
|
||
}
|
||
md = getdisplay(p, monid);
|
||
set_config_changed ();
|
||
}
|
||
|
||
bool toggle_3d_debug(void)
|
||
{
|
||
if (isvsync_chipset() < 0) {
|
||
beamracer_debug = !beamracer_debug;
|
||
if (D3D_debug) {
|
||
D3D_debug(0, beamracer_debug);
|
||
}
|
||
reset_drawing();
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
|
||
int rtg_index = -1;
|
||
|
||
// -2 = default
|
||
// -1 = prev
|
||
// 0 = chipset
|
||
// 1..4 = rtg
|
||
// 5 = next
|
||
bool toggle_rtg (int monid, int mode)
|
||
{
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
|
||
int old_index = rtg_index;
|
||
|
||
if (monid > 0) {
|
||
return true;
|
||
}
|
||
|
||
if (mode < -1 && rtg_index >= 0)
|
||
return true;
|
||
|
||
for (;;) {
|
||
if (mode == -1) {
|
||
rtg_index--;
|
||
} else if (mode >= 0 && mode <= MAX_RTG_BOARDS) {
|
||
rtg_index = mode - 1;
|
||
} else {
|
||
rtg_index++;
|
||
}
|
||
if (rtg_index >= MAX_RTG_BOARDS) {
|
||
rtg_index = -1;
|
||
} else if (rtg_index < -1) {
|
||
rtg_index = MAX_RTG_BOARDS - 1;
|
||
}
|
||
if (rtg_index < 0) {
|
||
if (ad->picasso_on) {
|
||
gfxboard_rtg_disable(monid, old_index);
|
||
ad->picasso_requested_on = false;
|
||
statusline_add_message(STATUSTYPE_DISPLAY, _T("Chipset display"));
|
||
set_config_changed();
|
||
return false;
|
||
}
|
||
return false;
|
||
}
|
||
struct rtgboardconfig *r = &currprefs.rtgboards[rtg_index];
|
||
if (r->rtgmem_size > 0 && r->monitor_id == monid) {
|
||
if (r->rtgmem_type >= GFXBOARD_HARDWARE) {
|
||
int idx = gfxboard_toggle(r->monitor_id, rtg_index, mode >= -1);
|
||
if (idx >= 0) {
|
||
rtg_index = idx;
|
||
return true;
|
||
}
|
||
if (idx < -1) {
|
||
rtg_index = -1;
|
||
return false;
|
||
}
|
||
} else {
|
||
gfxboard_toggle(r->monitor_id, -1, -1);
|
||
if (mode < -1)
|
||
return true;
|
||
devices_unsafeperiod();
|
||
gfxboard_rtg_disable(monid, old_index);
|
||
// can always switch from RTG to custom
|
||
if (ad->picasso_requested_on && ad->picasso_on) {
|
||
ad->picasso_requested_on = false;
|
||
rtg_index = -1;
|
||
set_config_changed();
|
||
return true;
|
||
}
|
||
if (ad->picasso_on)
|
||
return false;
|
||
// can only switch from custom to RTG if there is some mode active
|
||
if (picasso_is_active(r->monitor_id)) {
|
||
picasso_enablescreen(r->monitor_id, 1);
|
||
ad->picasso_requested_on = true;
|
||
statusline_add_message(STATUSTYPE_DISPLAY, _T("RTG %d: %s"), rtg_index + 1, _T("UAEGFX"));
|
||
set_config_changed();
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
if (mode >= 0 && mode <= MAX_RTG_BOARDS) {
|
||
rtg_index = old_index;
|
||
return false;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void close_rtg(int monid, bool reset)
|
||
{
|
||
struct AmigaMonitor *mon = &AMonitors[monid];
|
||
close_windows(mon);
|
||
if (reset) {
|
||
mon->screen_is_picasso = false;
|
||
}
|
||
}
|
||
|
||
void toggle_fullscreen(int monid, int mode)
|
||
{
|
||
struct amigadisplay *ad = &adisplays[monid];
|
||
int *p = ad->picasso_on ? &changed_prefs.gfx_apmode[1].gfx_fullscreen : &changed_prefs.gfx_apmode[0].gfx_fullscreen;
|
||
int wfw = ad->picasso_on ? wasfullwindow_p : wasfullwindow_a;
|
||
int v = *p;
|
||
static int prevmode = -1;
|
||
|
||
if (mode < 0) {
|
||
// fullwindow->window->fullwindow.
|
||
// fullscreen->window->fullscreen.
|
||
// window->fullscreen->window.
|
||
if (v == GFX_FULLWINDOW) {
|
||
prevmode = v;
|
||
v = GFX_WINDOW;
|
||
} else if (v == GFX_WINDOW) {
|
||
if (prevmode < 0) {
|
||
v = GFX_FULLSCREEN;
|
||
prevmode = v;
|
||
} else {
|
||
v = prevmode;
|
||
}
|
||
} else if (v == GFX_FULLSCREEN) {
|
||
if (wfw > 0)
|
||
v = GFX_FULLWINDOW;
|
||
else
|
||
v = GFX_WINDOW;
|
||
}
|
||
} else if (mode == 0) {
|
||
prevmode = v;
|
||
// fullscreen <> window
|
||
if (v == GFX_FULLSCREEN)
|
||
v = GFX_WINDOW;
|
||
else
|
||
v = GFX_FULLSCREEN;
|
||
} else if (mode == 1) {
|
||
prevmode = v;
|
||
// fullscreen <> fullwindow
|
||
if (v == GFX_FULLSCREEN)
|
||
v = GFX_FULLWINDOW;
|
||
else
|
||
v = GFX_FULLSCREEN;
|
||
} else if (mode == 2) {
|
||
prevmode = v;
|
||
// window <> fullwindow
|
||
if (v == GFX_FULLWINDOW)
|
||
v = GFX_WINDOW;
|
||
else
|
||
v = GFX_FULLWINDOW;
|
||
} else if (mode == 10) {
|
||
v = GFX_WINDOW;
|
||
}
|
||
*p = v;
|
||
devices_unsafeperiod();
|
||
updatewinfsmode(monid, &changed_prefs);
|
||
}
|
||
|
||
HDC gethdc(int monid)
|
||
{
|
||
HDC hdc = 0;
|
||
|
||
if (D3D_isenabled(0))
|
||
return D3D_getDC(monid, 0);
|
||
return hdc;
|
||
}
|
||
|
||
void releasehdc(int monid, HDC hdc)
|
||
{
|
||
if (D3D_isenabled(0)) {
|
||
D3D_getDC(monid, hdc);
|
||
return;
|
||
}
|
||
}
|
||
|
||
TCHAR *outGUID(const GUID *guid)
|
||
{
|
||
static TCHAR gb[64];
|
||
if (guid == NULL)
|
||
return _T("NULL");
|
||
_stprintf(gb, _T("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
|
||
guid->Data1, guid->Data2, guid->Data3,
|
||
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
||
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
|
||
return gb;
|
||
}
|
||
|
||
const TCHAR *DXError(HRESULT ddrval)
|
||
{
|
||
static TCHAR dderr[1000];
|
||
_stprintf(dderr, _T("%08X S=%d F=%04X C=%04X (%d)"),
|
||
ddrval, (ddrval & 0x80000000) ? 1 : 0,
|
||
HRESULT_FACILITY(ddrval),
|
||
HRESULT_CODE(ddrval),
|
||
HRESULT_CODE(ddrval));
|
||
return dderr;
|
||
}
|
||
|
||
struct osd_kb
|
||
{
|
||
uae_s16 x, y;
|
||
uae_s16 w, h;
|
||
uae_u16 code;
|
||
uae_s8 pressed;
|
||
uae_s8 inverted;
|
||
};
|
||
|
||
static struct osd_kb *osd_kb_data;
|
||
static int osd_kb_selected = 11, osd_kb_x, osd_kb_y;
|
||
struct extoverlay osd_kb_eo = { 0 };
|
||
|
||
#define OSD_KB_TRANSPARENCY 0xaa
|
||
#define OSD_KB_ACTIVE_TRANSPARENCY 0xaa
|
||
#define OSD_KB_PRESSED_TRANSPARENCY 0xff
|
||
#define OSD_KB_COLOR 0xeeeeee
|
||
#define OSD_KB_ACTIVE_COLOR 0x44cc44
|
||
#define OSD_KB_PRESSED_COLOR 0x222222
|
||
#define OSD_KB_PRESSED_COLOR2 0x444444
|
||
|
||
static void drawpixel(uae_u8 *p, uae_u32 c, uae_u8 trans)
|
||
{
|
||
((uae_u32*)p)[0] = (c & 0x00ffffff) | (trans << 24);
|
||
}
|
||
|
||
static void drawline(struct extoverlay *eo, int x1, int y1, int x2, int y2)
|
||
{
|
||
uae_u8 *p = eo->data + y1 * eo->width * 4 + x1 * 4;
|
||
if (x1 != x2) {
|
||
x2++;
|
||
}
|
||
if (y1 != y2) {
|
||
y2++;
|
||
}
|
||
while (x1 != x2) {
|
||
drawpixel(p, OSD_KB_COLOR, OSD_KB_TRANSPARENCY);
|
||
if (x1 < x2) {
|
||
x1++;
|
||
p += 4;
|
||
} else {
|
||
x1--;
|
||
p -= 4;
|
||
}
|
||
}
|
||
while (y1 != y2) {
|
||
drawpixel(p, OSD_KB_COLOR, OSD_KB_TRANSPARENCY);
|
||
if (y1 < y2) {
|
||
y1++;
|
||
p += eo->width * 4;
|
||
} else {
|
||
y1--;
|
||
p -= eo->width * 4;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void highlight(struct extoverlay *eo, struct osd_kb *kb, bool mode)
|
||
{
|
||
if (kb->inverted) {
|
||
kb->inverted = false;
|
||
highlight(eo, kb, true);
|
||
kb->inverted = false;
|
||
}
|
||
int x1 = kb->x;
|
||
int x2 = kb->x + kb->w;
|
||
int y1 = kb->y;
|
||
int y2 = kb->y + kb->h;
|
||
uae_u8 *p = eo->data + y1 * eo->width * 4;
|
||
uae_u32 color = 0;
|
||
uae_u8 tr = 0;
|
||
if (mode) {
|
||
kb->inverted = true;
|
||
color = OSD_KB_COLOR;
|
||
tr = OSD_KB_TRANSPARENCY;
|
||
} else {
|
||
color = !mode ? OSD_KB_COLOR : OSD_KB_ACTIVE_COLOR;
|
||
tr = !mode ? OSD_KB_TRANSPARENCY : OSD_KB_ACTIVE_TRANSPARENCY;
|
||
if (kb->pressed) {
|
||
color = OSD_KB_PRESSED_COLOR;
|
||
tr = OSD_KB_PRESSED_TRANSPARENCY;
|
||
}
|
||
}
|
||
while (y1 <= y2) {
|
||
uae_u8 *pp = p + x1 * 4;
|
||
for (int x = x1; x <= x2; x++) {
|
||
if (kb->inverted) {
|
||
uae_u32 *p32 = (uae_u32*)pp;
|
||
*p32 ^= 0xffffff;
|
||
} else {
|
||
if (pp[0] || pp[1] || pp[2]) {
|
||
drawpixel(pp, color, tr);
|
||
} else {
|
||
pp[3] = tr;
|
||
}
|
||
}
|
||
pp += 4;
|
||
}
|
||
p += eo->width * 4;
|
||
y1++;
|
||
}
|
||
if (mode) {
|
||
if (osd_kb_x < kb->x || osd_kb_x > kb->x + kb->w) {
|
||
osd_kb_x = kb->x + kb->w / 2;
|
||
}
|
||
if (osd_kb_y < kb->y || osd_kb_y > kb->y + kb->h) {
|
||
osd_kb_y = kb->y + kb->h / 2;
|
||
}
|
||
}
|
||
}
|
||
|
||
static const uae_s16 layout[] = {
|
||
10,-5,13,13,13,13,13,-5,13,13,13,13,13,-5,13,13,13,13,0,
|
||
15,10,10,10,10,10,10,10,10,10,10,10,10,10,10,-5,15,15,-5,10,10,10,10,0,
|
||
23,10,10,10,10,10,10,10,10,10,10,10,10,12 + 256,-40,10,10,10,10,0,
|
||
13,10,10,10,10,10,10,10,10,10,10,10,10,10,-27,10,-15,10,10,10,10,0,
|
||
18,10,10,10,10,10,10,10,10,10,10,10,27,-5,10,10,10,-5,10,10,10,10 + 256,0,
|
||
-8,13,13,90,13,13,-45,20,10,0,
|
||
0
|
||
};
|
||
static const TCHAR *key_labels[] = {
|
||
L"Esc",L"F1",L"F2",L"F3",L"F4",L"F5",L"F6",L"F7",L"F8",L"F9",L"F10",L"GUI",L"J<>M",L"↑↓",L"X",
|
||
L"~|´",L"!|1",L"@|2",L"#|3",L"$|4",L"%|5",L"^|6",L"&|7",L"*|8",L"(|9",L")|0",L"_|-",L"+|=",L"\\||\\\\",L"←",L"Del",L"Help",L"(",L")",L"/",L"*",
|
||
L"←|→",L"Q",L"W",L"E",L"R",L"T",L"Y",L"U",L"I",L"O",L"P",L"{|[",L"}|]",L"Ret",L"7",L"8",L"9",L"-",
|
||
L"Ctrl",L"Caps|Lock",L"A",L"S",L"D",L"F",L"G",L"H",L"J",L"K",L"L",L":|;",L"*|'",L"",L"↑",L"4",L"5",L"6",L"+",
|
||
L"Shift",L"",L"Z",L"X",L"C",L"V",L"B",L"N",L"M",L"<|,",L">|.",L"?|/",L"Shift",L"←",L"↓",L"→",L"1",L"2",L"3",L"E|n|t|e|r",
|
||
L"Alt",L"\\iA",L"",L"\\iA",L"Alt",L"0",L".",
|
||
0,0
|
||
};
|
||
static const uae_u16 key_codes[] = {
|
||
0x45, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, AKS_ENTERGUI | 0x8000, AKS_SWAPJOYPORTS | 0x8000, 0xf001, AKS_OSK | 0x8000,
|
||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x41, 0x46, 0x5f, 0x5a, 0x5b, 0x5c, 0x5d,
|
||
0x42, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x44, 0x3d, 0x3e, 0x3f, 0x4a,
|
||
0x63, 0x62, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x4c, 0x2d, 0x2e, 0x2f, 0x5e,
|
||
0x60, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x61, 0x4f, 0x4d, 0x4e, 0x1d, 0x1e, 0x1f, 0x43,
|
||
0x64, 0x66, 0x40, 0x67, 0x64, 0x0f, 0x3c,
|
||
0
|
||
};
|
||
|
||
static void draw_key(HDC hdc, void *bm, int bmw, int bmh, struct extoverlay *eo, float sx, float sy, const TCHAR *key, int len, int fw, int fh)
|
||
{
|
||
SetBkMode(hdc, OPAQUE);
|
||
BitBlt(hdc, 0, 0, bmw, bmh, NULL, 0, 0, BLACKNESS);
|
||
TextOut(hdc, 10, 10, key, len);
|
||
int offsetx = 10;
|
||
int offsety = 10 - 1;
|
||
for (int y = 0; y < fh + 2; y++) {
|
||
uae_u8 *src = (uae_u8 *)bm + (y + offsety) * bmw + offsetx;
|
||
uae_u8 *dst = eo->data + (int)(sx + 0.5f) * 4 + ((int)(sy + 0.5f) + y) * eo->width * 4;
|
||
for (int x = 0; x < bmw; x++) {
|
||
uae_u8 b = *src++;
|
||
if (b == 2) {
|
||
drawpixel(dst, OSD_KB_COLOR, OSD_KB_TRANSPARENCY);
|
||
}
|
||
dst += 4;
|
||
}
|
||
}
|
||
}
|
||
|
||
static bool draw_keyboard(HDC hdc, HFONT *fonts, void *bm, int bmw, int bmh, struct extoverlay *eo, int fw, int fh)
|
||
{
|
||
int num = 0, knum = 0;
|
||
int maxcols = 240;
|
||
|
||
float space = (float)eo->width / maxcols;
|
||
float colwidth = (float)eo->width / maxcols;
|
||
float rowheight = colwidth * 7.5f;
|
||
|
||
int theight = (int)((rowheight + space) * 6 + 2 * space);
|
||
if (eo->height < theight) {
|
||
eo->height = theight;
|
||
}
|
||
eo->data = xcalloc(uae_u8, eo->width * eo->height * 4);
|
||
if (!eo->data) {
|
||
return false;
|
||
}
|
||
|
||
for (int y = 0; y < eo->height; y++) {
|
||
uae_u8 *p = eo->data + y * eo->width * 4;
|
||
for (int x = 0; x < eo->width; x++) {
|
||
p[3] = OSD_KB_TRANSPARENCY;
|
||
p += 4;
|
||
}
|
||
}
|
||
|
||
float y = 2.0f * space;
|
||
float x = 2.0f * space;
|
||
const uae_s16 *lp = layout;
|
||
const TCHAR **ll = key_labels;
|
||
while (*lp) {
|
||
uae_s16 v = *lp++;
|
||
float w = (abs(v) & 255) * colwidth - space;
|
||
float h = rowheight;
|
||
if ((abs(v) >> 8) > 0) {
|
||
h += rowheight;
|
||
h += space;
|
||
}
|
||
if (v > 0) {
|
||
const TCHAR *lab = key_labels[knum];
|
||
if (lab) {
|
||
float kx = x;
|
||
float ky = y;
|
||
int i = 0;
|
||
bool esc = false;
|
||
TCHAR out[10];
|
||
TCHAR *outp = out;
|
||
bool italic = false;
|
||
for (;;) {
|
||
bool skip = false;
|
||
TCHAR c = lab[i];
|
||
TCHAR cn = lab[i + 1];
|
||
if (c == '\\' && cn != '\\' && !esc) {
|
||
esc = true;
|
||
} else if (c == 'i' && esc) {
|
||
italic = true;
|
||
esc = false;
|
||
} else if (c == '|' && esc) {
|
||
*outp++ = c;
|
||
esc = false;
|
||
skip = true;
|
||
} else if (c != '|' && c) {
|
||
*outp++ = c;
|
||
esc = false;
|
||
}
|
||
if ((c == '|' && !esc && !skip) || c == 0) {
|
||
SelectObject(hdc, italic ? fonts[1] : fonts[0]);
|
||
draw_key(hdc, bm, bmw, bmh, eo, kx + space, ky + space, out, addrdiff(outp, out), fw, fh);
|
||
ky += fh + 2;
|
||
outp = out;
|
||
italic = false;
|
||
}
|
||
if (!c) {
|
||
break;
|
||
}
|
||
i++;
|
||
}
|
||
}
|
||
if (key_labels[knum] != NULL || key_labels[knum + 1] != NULL) {
|
||
knum++;
|
||
}
|
||
|
||
struct osd_kb *kb = &osd_kb_data[num];
|
||
kb->x = (int)(x + 0.5f);
|
||
kb->y = (int)(y + 0.5f);
|
||
kb->w = (int)(w + 0.5f);
|
||
kb->h = (int)(h + 0.5f);
|
||
kb->code = key_codes[num];
|
||
|
||
drawline(eo, kb->x, kb->y, kb->x + kb->w, kb->y);
|
||
drawline(eo, kb->x, kb->y + 1, kb->x + kb->w, kb->y + 1);
|
||
|
||
drawline(eo, kb->x, kb->y + kb->h, kb->x + kb->w, kb->y + kb->h);
|
||
drawline(eo, kb->x, kb->y + kb->h - 1, kb->x + kb->w, kb->y + kb->h - 1);
|
||
|
||
drawline(eo, kb->x, kb->y, kb->x, kb->y + kb->h);
|
||
drawline(eo, kb->x + 1, kb->y, kb->x + 1, kb->y + kb->h);
|
||
|
||
drawline(eo, kb->x + kb->w, kb->y, kb->x + kb->w, kb->y + kb->h);
|
||
drawline(eo, kb->x + kb->w - 1, kb->y, kb->x + kb->w - 1, kb->y + kb->h);
|
||
|
||
if (num == osd_kb_selected) {
|
||
highlight(eo, kb, true);
|
||
}
|
||
num++;
|
||
}
|
||
x += w + space;
|
||
|
||
if (*lp == 0) {
|
||
y += rowheight + space;
|
||
x = 2 * space;
|
||
lp++;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
static const TCHAR *ab = _T("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
|
||
|
||
static bool drawkeys(HWND parent, struct extoverlay *eo)
|
||
{
|
||
bool ret = false;
|
||
HDC hdc;
|
||
LPLOGPALETTE lp;
|
||
HPALETTE hpal;
|
||
BITMAPINFO *bi;
|
||
BITMAPINFOHEADER *bih;
|
||
HBITMAP bitmap = NULL;
|
||
int width = 128;
|
||
int height = 128;
|
||
void *bm;
|
||
int fsize = eo->height / 30;
|
||
|
||
if (fsize < 4) {
|
||
return false;
|
||
}
|
||
|
||
hdc = CreateCompatibleDC(NULL);
|
||
if (hdc) {
|
||
int y = getdpiforwindow(parent);
|
||
int fontsize = -MulDiv(fsize, y, 72);
|
||
fontsize = fontsize * statusline_get_multiplier(0) / 100;
|
||
lp = (LOGPALETTE *)xcalloc(uae_u8, sizeof(LOGPALETTE) + 3 * sizeof(PALETTEENTRY));
|
||
if (lp) {
|
||
lp->palNumEntries = 4;
|
||
lp->palVersion = 0x300;
|
||
lp->palPalEntry[1].peBlue = lp->palPalEntry[1].peGreen = lp->palPalEntry[0].peRed = 0x10;
|
||
lp->palPalEntry[2].peBlue = lp->palPalEntry[2].peGreen = lp->palPalEntry[2].peRed = 0xff;
|
||
lp->palPalEntry[3].peBlue = lp->palPalEntry[3].peGreen = lp->palPalEntry[3].peRed = 0x7f;
|
||
hpal = CreatePalette(lp);
|
||
if (hpal) {
|
||
SelectPalette(hdc, hpal, FALSE);
|
||
bi = (BITMAPINFO *)xcalloc(uae_u8, sizeof(BITMAPINFOHEADER) + 4 * sizeof(RGBQUAD));
|
||
if (bi) {
|
||
bih = &bi->bmiHeader;
|
||
bih->biSize = sizeof(BITMAPINFOHEADER);
|
||
bih->biWidth = width;
|
||
bih->biHeight = -height;
|
||
bih->biPlanes = 1;
|
||
bih->biBitCount = 8;
|
||
bih->biCompression = BI_RGB;
|
||
bih->biClrUsed = 4;
|
||
bih->biClrImportant = 4;
|
||
bi->bmiColors[1].rgbBlue = bi->bmiColors[1].rgbGreen = bi->bmiColors[1].rgbRed = 0x10;
|
||
bi->bmiColors[2].rgbBlue = bi->bmiColors[2].rgbGreen = bi->bmiColors[2].rgbRed = 0xff;
|
||
bi->bmiColors[3].rgbBlue = bi->bmiColors[3].rgbGreen = bi->bmiColors[3].rgbRed = 0x7f;
|
||
bitmap = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bm, NULL, 0);
|
||
if (bitmap) {
|
||
SelectObject(hdc, bitmap);
|
||
RealizePalette(hdc);
|
||
HFONT fonts[3] = { 0, 0, 0 };
|
||
fonts[0] = CreateFont(fontsize, 0,
|
||
0, 0,
|
||
FW_BOLD,
|
||
FALSE,
|
||
FALSE,
|
||
FALSE,
|
||
DEFAULT_CHARSET,
|
||
OUT_TT_PRECIS,
|
||
CLIP_DEFAULT_PRECIS,
|
||
PROOF_QUALITY,
|
||
FIXED_PITCH | FF_DONTCARE,
|
||
_T("Lucida Console"));
|
||
fonts[1] = CreateFont(fontsize, 0,
|
||
0, 0,
|
||
FW_BOLD,
|
||
TRUE,
|
||
FALSE,
|
||
FALSE,
|
||
DEFAULT_CHARSET,
|
||
OUT_TT_PRECIS,
|
||
CLIP_DEFAULT_PRECIS,
|
||
PROOF_QUALITY,
|
||
FIXED_PITCH | FF_DONTCARE,
|
||
_T("Lucida Console"));
|
||
if (fonts[0] && fonts[1]) {
|
||
SelectObject(hdc, fonts[0]);
|
||
SetTextColor(hdc, PALETTEINDEX(2));
|
||
SetBkColor(hdc, PALETTEINDEX(1));
|
||
|
||
TEXTMETRIC tm;
|
||
GetTextMetrics(hdc, &tm);
|
||
int w = 0;
|
||
int h = tm.tmAscent + 2;
|
||
for (int i = 0; i < ab[i]; i++) {
|
||
SIZE sz;
|
||
if (GetTextExtentPoint32(hdc, &ab[i], 1, &sz)) {
|
||
if (sz.cx > w)
|
||
w = sz.cx;
|
||
}
|
||
}
|
||
w += 1;
|
||
|
||
if (draw_keyboard(hdc, fonts, bm, width, height, eo, w, h)) {
|
||
ret = true;
|
||
}
|
||
}
|
||
if (fonts[0]) {
|
||
DeleteObject(fonts[0]);
|
||
}
|
||
if (fonts[1]) {
|
||
DeleteObject(fonts[1]);
|
||
}
|
||
DeleteObject(bitmap);
|
||
}
|
||
xfree(bi);
|
||
}
|
||
DeleteObject(hpal);
|
||
}
|
||
xfree(lp);
|
||
}
|
||
ReleaseDC(NULL, hdc);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
void target_osk_control(int x, int y, int button, int buttonstate)
|
||
{
|
||
if (button == 2) {
|
||
if (buttonstate) {
|
||
struct osd_kb *kb = &osd_kb_data[osd_kb_selected];
|
||
kb->pressed = kb->pressed ? 0 : 1;
|
||
highlight(&osd_kb_eo, kb, false);
|
||
D3D_extoverlay(&osd_kb_eo, 0);
|
||
if ((kb->code & 0xf000) != 0xf000) {
|
||
if (kb->pressed) {
|
||
record_key((kb->code << 1) | 0, true);
|
||
} else {
|
||
record_key((kb->code << 1) | 1, true);
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
if (button == 1) {
|
||
struct osd_kb *kb = &osd_kb_data[osd_kb_selected];
|
||
if (kb->pressed) {
|
||
kb->pressed = 0;
|
||
highlight(&osd_kb_eo, kb, true);
|
||
D3D_extoverlay(&osd_kb_eo, 0);
|
||
if (kb->code != 0x62) {
|
||
record_key((kb->code << 1) | 1, true);
|
||
}
|
||
}
|
||
if (buttonstate) {
|
||
kb->pressed = -1;
|
||
highlight(&osd_kb_eo, kb, false);
|
||
D3D_extoverlay(&osd_kb_eo, 0);
|
||
}
|
||
|
||
if (kb->code & 0x8000) {
|
||
if ((kb->code & 0xf000) != 0xf000) {
|
||
inputdevice_add_inputcode(kb->code & 0x7fff, buttonstate, NULL);
|
||
} else {
|
||
int c = kb->code & 0xfff;
|
||
if (c == 1) {
|
||
if (buttonstate) {
|
||
struct AmigaMonitor *amon = &AMonitors[0];
|
||
if (osd_kb_eo.ypos == 0) {
|
||
osd_kb_eo.ypos = (amon->amigawin_rect.bottom - amon->amigawin_rect.top) - osd_kb_eo.height;
|
||
} else {
|
||
osd_kb_eo.ypos = 0;
|
||
}
|
||
D3D_extoverlay(&osd_kb_eo, 0);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
// capslock?
|
||
if (kb->code == 0x62) {
|
||
if (buttonstate) {
|
||
int capsstate = getcapslockstate();
|
||
capsstate = capsstate ? 0 : 1;
|
||
record_key((kb->code << 1) | capsstate, true);
|
||
setcapslockstate(capsstate);
|
||
}
|
||
} else {
|
||
if (buttonstate) {
|
||
record_key((kb->code << 1) | 0, true);
|
||
} else {
|
||
record_key((kb->code << 1) | 1, true);
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (x > 1) {
|
||
x = 1;
|
||
}
|
||
if (x < -1) {
|
||
x = -1;
|
||
}
|
||
if (y > 1) {
|
||
y = 1;
|
||
}
|
||
if (y < -1) {
|
||
y = -1;
|
||
}
|
||
|
||
if (x || y) {
|
||
for (int i = 0; osd_kb_data[i].w; i++) {
|
||
struct osd_kb *kb = &osd_kb_data[i];
|
||
if (kb->pressed < 0) {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
int max = 1000;
|
||
while (x || y) {
|
||
osd_kb_x += x * 5;
|
||
osd_kb_y += y * 5;
|
||
if (osd_kb_x < 0) {
|
||
for (int i = 0; osd_kb_data[i].w; i++) {
|
||
struct osd_kb *kb = &osd_kb_data[i];
|
||
if (kb->x + kb->w > osd_kb_x) {
|
||
osd_kb_x = kb->x + kb->w;
|
||
}
|
||
}
|
||
}
|
||
if (osd_kb_y < 0) {
|
||
for (int i = 0; osd_kb_data[i].w; i++) {
|
||
struct osd_kb *kb = &osd_kb_data[i];
|
||
if (kb->y + kb->h > osd_kb_y) {
|
||
osd_kb_y = kb->y + kb->h;
|
||
}
|
||
}
|
||
}
|
||
int xmax = 0, ymax = 0;
|
||
int i;
|
||
for (i = 0; osd_kb_data[i].w; i++) {
|
||
struct osd_kb *kb = &osd_kb_data[i];
|
||
if (osd_kb_x > kb->x + kb->w) {
|
||
xmax++;
|
||
}
|
||
if (osd_kb_y > kb->y + kb->h) {
|
||
ymax++;
|
||
}
|
||
if (i != osd_kb_selected) {
|
||
if (kb->x <= osd_kb_x && kb->x + kb->w >= osd_kb_x && kb->y <= osd_kb_y && kb->y + kb->h >= osd_kb_y) {
|
||
highlight(&osd_kb_eo, &osd_kb_data[osd_kb_selected], false);
|
||
highlight(&osd_kb_eo, kb, true);
|
||
osd_kb_selected = i;
|
||
D3D_extoverlay(&osd_kb_eo, 0);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
if (xmax >= i) {
|
||
osd_kb_x = 0;
|
||
}
|
||
if (ymax >= i) {
|
||
osd_kb_y = 0;
|
||
}
|
||
max--;
|
||
if (max < 0) {
|
||
highlight(&osd_kb_eo, &osd_kb_data[osd_kb_selected], false);
|
||
osd_kb_selected = 0;
|
||
highlight(&osd_kb_eo, &osd_kb_data[osd_kb_selected], true);
|
||
D3D_extoverlay(&osd_kb_eo, 0);
|
||
return;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
int on_screen_keyboard;
|
||
|
||
bool target_osd_keyboard(int show)
|
||
{
|
||
struct AmigaMonitor *amon = &AMonitors[0];
|
||
static bool first;
|
||
|
||
#ifdef RETROPLATFORM
|
||
if (rp_isactive() && !on_screen_keyboard) {
|
||
return false;
|
||
}
|
||
#endif
|
||
|
||
xfree(osd_kb_data);
|
||
osd_kb_data = NULL;
|
||
osd_kb_eo.idx = 0x7f7f0000;
|
||
if (!show) {
|
||
osd_kb_eo.width = -1;
|
||
osd_kb_eo.height = -1;
|
||
D3D_extoverlay(&osd_kb_eo, 0);
|
||
return true;
|
||
}
|
||
|
||
int w = amon->amigawin_rect.right - amon->amigawinclip_rect.left;
|
||
int h = amon->amigawin_rect.bottom - amon->amigawinclip_rect.top;
|
||
|
||
if (w > h * 4 / 3) {
|
||
w = h * 4 / 3;
|
||
}
|
||
osd_kb_eo.width = w;
|
||
osd_kb_eo.height = w * 10 / 44;
|
||
osd_kb_data = xcalloc(struct osd_kb, 120);
|
||
if (osd_kb_data) {
|
||
if (!drawkeys(amon->hAmigaWnd, &osd_kb_eo)) {
|
||
return false;
|
||
}
|
||
}
|
||
if (!first) {
|
||
osd_kb_eo.ypos = (amon->amigawin_rect.bottom - amon->amigawin_rect.top) - osd_kb_eo.height;
|
||
}
|
||
if (osd_kb_eo.ypos) {
|
||
osd_kb_eo.ypos = (amon->amigawin_rect.bottom - amon->amigawin_rect.top) - osd_kb_eo.height;
|
||
}
|
||
osd_kb_eo.xpos = ((amon->amigawin_rect.right - amon->amigawinclip_rect.left) - w) / 2;
|
||
if (!osd_kb_eo.data) {
|
||
return false;
|
||
}
|
||
if (!D3D_extoverlay(&osd_kb_eo, 0)) {
|
||
return false;
|
||
}
|
||
|
||
first = true;
|
||
return true;
|
||
}
|