Michael Maltese d10d09ccc1 VideoCommon: rework anamorphic widescreen heuristic
Some widescreen hacks (see below) properly force anamorphic output, but
don't make the last projection in a frame 16:9, so Dolphin doesn't
display it correctly.

This changes the heuristic code to assume a frame is anamorphic based on
the total number of vertex flushes in 4:3 and 16:9 projections that
frame. It also adds a bit of "aspect ratio inertia" by making it harder
to switch aspect ratios, which takes care of aspect ratio flickering
that some games / widescreen hacks would be susceptible with the new
logic.

I've tested this on SSX Tricky's native anamorphic support, Tom Clancy's
Splinter Cell (it stayed in 4:3 the whole time), and on the following
widescreen hacks for which the heuristic doesn't currently work:

Paper Mario: The Thousand-Year Door (Gecko widescreen code from Nintendont)
C202F310 00000003
3DC08042 3DE03FD8
91EEF6D8 4E800020
60000000 00000000
04199598 4E800020
C200F500 00000004
3DE08082 3DC0402B
61CE12A2 91CFA1BC
60000000 387D015C
60000000 00000000
C200F508 00000004
3DE08082 3DC04063
61CEE8D3 91CFA1BC
60000000 7FC3F378
60000000 00000000

The Simpsons: Hit & Run (AR widescreen code from the wiki)
04004600 C002A604
04004604 C09F0014
04004608 FC002040
0400460C 4082000C
04004610 C002A608
04004614 EC630032
04004618 48220508
04041A5C 38600001
04224344 C002A60C
04224B1C 4BDDFAE4
044786B0 3FAAAAAB
04479F28 3FA33333
2017-04-05 17:23:16 -07:00

104 lines
3.3 KiB
C++

// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
// Core
// The external interface to the emulator core. Plus some extras.
// This is another part of the emu that needs cleaning - Core.cpp really has
// too much random junk inside.
#pragma once
#include <functional>
#include <string>
#include <vector>
#include "Common/CommonTypes.h"
namespace Core
{
bool GetIsThrottlerTempDisabled();
void SetIsThrottlerTempDisabled(bool disable);
void Callback_VideoCopiedToXFB(bool video_update);
enum class State
{
Uninitialized,
Paused,
Running,
Stopping
};
bool Init();
void Stop();
void Shutdown();
void DeclareAsCPUThread();
void UndeclareAsCPUThread();
std::string StopMessage(bool, const std::string&);
bool IsRunning();
bool IsRunningAndStarted(); // is running and the CPU loop has been entered
bool IsRunningInCurrentThread(); // this tells us whether we are running in the CPU thread.
bool IsCPUThread(); // this tells us whether we are the CPU thread.
bool IsGPUThread();
bool WantsDeterminism();
// [NOT THREADSAFE] For use by Host only
void SetState(State state);
State GetState();
void SaveScreenShot(bool wait_for_completion = false);
void SaveScreenShot(const std::string& name, bool wait_for_completion = false);
void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size);
// This displays messages in a user-visible way.
void DisplayMessage(const std::string& message, int time_in_ms);
std::string GetStateFileName();
void SetStateFileName(const std::string& val);
void FrameUpdateOnCPUThread();
bool ShouldSkipFrame(int skipped);
void VideoThrottle();
void RequestRefreshInfo();
void UpdateTitle();
// waits until all systems are paused and fully idle, and acquires a lock on that state.
// or, if doLock is false, releases a lock on that state and optionally unpauses.
// calls must be balanced (once with doLock true, then once with doLock false) but may be recursive.
// the return value of the first call should be passed in as the second argument of the second call.
// [NOT THREADSAFE] Host only
bool PauseAndLock(bool doLock, bool unpauseOnUnlock = true);
// for calling back into UI code without introducing a dependency on it in core
using StoppedCallbackFunc = std::function<void()>;
void SetOnStoppedCallback(StoppedCallbackFunc callback);
// Run on the Host thread when the factors change. [NOT THREADSAFE]
void UpdateWantDeterminism(bool initial = false);
// Queue an arbitrary function to asynchronously run once on the Host thread later.
// Threadsafe. Can be called by any thread, including the Host itself.
// Jobs will be executed in RELATIVE order. If you queue 2 jobs from the same thread
// then they will be executed in the order they were queued; however, there is no
// global order guarantee across threads - jobs from other threads may execute in
// between.
// NOTE: Make sure the jobs check the global state instead of assuming everything is
// still the same as when the job was queued.
// NOTE: Jobs that are not set to run during stop will be discarded instead.
void QueueHostJob(std::function<void()> job, bool run_during_stop = false);
// Should be called periodically by the Host to run pending jobs.
// WM_USER_JOB_DISPATCH will be sent when something is added to the queue.
void HostDispatchJobs();
} // namespace