mirror of
https://github.com/NovaSquirrel/Mesen-X.git
synced 2024-06-11 16:57:59 -04:00
commit
5c7fd5167c
|
@ -56,7 +56,7 @@ void BaseVideoFilter::SendFrame(uint16_t *ppuOutputBuffer, uint32_t frameNumber)
|
|||
{
|
||||
_frameLock.Acquire();
|
||||
_overscan = _console->GetSettings()->GetOverscanDimensions();
|
||||
_isOddFrame = frameNumber % 2;
|
||||
_isOddFrame = frameNumber & 0x01;
|
||||
UpdateBufferSize();
|
||||
OnBeforeApplyFilter();
|
||||
ApplyFilter(ppuOutputBuffer);
|
||||
|
|
|
@ -23,13 +23,13 @@ protected:
|
|||
|
||||
virtual void ApplyFilter(uint16_t *ppuOutputBuffer) = 0;
|
||||
virtual void OnBeforeApplyFilter();
|
||||
bool IsOddFrame();
|
||||
|
||||
public:
|
||||
BaseVideoFilter(shared_ptr<Console> console);
|
||||
virtual ~BaseVideoFilter();
|
||||
|
||||
uint32_t* GetOutputBuffer();
|
||||
bool IsOddFrame();
|
||||
void SendFrame(uint16_t *ppuOutputBuffer, uint32_t frameNumber);
|
||||
void TakeScreenshot(string romName, VideoFilterType filterType);
|
||||
void TakeScreenshot(VideoFilterType filterType, string filename, std::stringstream *stream = nullptr, bool rawScreenshot = false);
|
||||
|
|
|
@ -50,8 +50,7 @@ BisqwitNtscFilter::BisqwitNtscFilter(shared_ptr<Console> console, int resDivider
|
|||
} else {
|
||||
outputBuffer += GetOverscan().GetScreenWidth() * 64 / _resDivider / _resDivider * (120 - GetOverscan().Top);
|
||||
}
|
||||
|
||||
DecodeFrame(120, 239 - GetOverscan().Bottom, _ppuOutputBuffer, outputBuffer, (IsOddFrame() ? 8 : 0) + 327360);
|
||||
DecodeFrame(120, 239 - GetOverscan().Bottom, _ppuOutputBuffer, outputBuffer, ((_console->GetModel() == NesModel::NTSC ? _console->GetStartingPhase() : 0) * 4) + 327360);
|
||||
|
||||
_workDone = true;
|
||||
}
|
||||
|
@ -71,7 +70,7 @@ void BisqwitNtscFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
|
|||
|
||||
_workDone = false;
|
||||
_waitWork.Signal();
|
||||
DecodeFrame(GetOverscan().Top, 120, ppuOutputBuffer, GetOutputBuffer(), (IsOddFrame() ? 8 : 0) + GetOverscan().Top*341*8);
|
||||
DecodeFrame(GetOverscan().Top, 120, ppuOutputBuffer, GetOutputBuffer(), ((_console->GetModel() == NesModel::NTSC ? _console->GetStartingPhase() : 0) * 4) + GetOverscan().Top * 341 * 8);
|
||||
while(!_workDone) {}
|
||||
}
|
||||
|
||||
|
|
|
@ -568,6 +568,11 @@ uint32_t Console::GetFrameCount()
|
|||
return _ppu ? _ppu->GetFrameCount() : 0;
|
||||
}
|
||||
|
||||
uint8_t Console::GetStartingPhase()
|
||||
{
|
||||
return _ppu ? _ppu->GetStartingPhase() : 0;
|
||||
}
|
||||
|
||||
NesModel Console::GetModel()
|
||||
{
|
||||
return _model;
|
||||
|
|
|
@ -204,6 +204,8 @@ public:
|
|||
VirtualFile GetPatchFile();
|
||||
RomInfo GetRomInfo();
|
||||
uint32_t GetFrameCount();
|
||||
// https://forums.nesdev.org/viewtopic.php?p=30625#p30625
|
||||
uint8_t GetStartingPhase();
|
||||
NesModel GetModel();
|
||||
|
||||
uint32_t GetLagCounter();
|
||||
|
|
|
@ -9,7 +9,7 @@ NtscFilter::NtscFilter(shared_ptr<Console> console) : BaseVideoFilter(console)
|
|||
memset(_palette, 0, sizeof(_palette));
|
||||
memset(&_ntscData, 0, sizeof(_ntscData));
|
||||
_ntscSetup = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
_ntscBuffer = new uint32_t[NES_NTSC_OUT_WIDTH(256) * 240];
|
||||
_ntscBuffer = new uint32_t[NES_NTSC_OUT_WIDTH(256) * 240]();
|
||||
}
|
||||
|
||||
FrameInfo NtscFilter::GetFrameInfo()
|
||||
|
@ -55,14 +55,7 @@ void NtscFilter::OnBeforeApplyFilter()
|
|||
}
|
||||
}
|
||||
|
||||
if (_console->GetModel() == NesModel::NTSC) {
|
||||
// BG color borders on NTSC machines
|
||||
_ntsc_border = _console->GetPpu()->GetCurrentBgColor();
|
||||
}
|
||||
else {
|
||||
// black borders on other machines
|
||||
_ntsc_border = 15;
|
||||
}
|
||||
_ntscBorder = (_console->GetModel() == NesModel::NTSC);
|
||||
|
||||
PictureSettings pictureSettings = _console->GetSettings()->GetPictureSettings();
|
||||
NtscFilterSettings ntscSettings = _console->GetSettings()->GetNtscFilterSettings();
|
||||
|
@ -132,7 +125,22 @@ void NtscFilter::OnBeforeApplyFilter()
|
|||
|
||||
void NtscFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
|
||||
{
|
||||
nes_ntsc_blit(&_ntscData, ppuOutputBuffer, _ntsc_border, PPU::ScreenWidth, IsOddFrame() ? 0 : 1, PPU::ScreenWidth, 240, _ntscBuffer, NES_NTSC_OUT_WIDTH(PPU::ScreenWidth)*4);
|
||||
uint8_t phase = _console->GetModel() == NesModel::NTSC ? _console->GetStartingPhase() : 0;
|
||||
for (int i = 0; i < 240; i++) {
|
||||
nes_ntsc_blit(&_ntscData,
|
||||
// input += in_row_width;
|
||||
ppuOutputBuffer + PPU::ScreenWidth * i,
|
||||
_ntscBorder ? _console->GetPpu()->GetCurrentBgColor() : 0x0F,
|
||||
PPU::ScreenWidth,
|
||||
phase,
|
||||
PPU::ScreenWidth,
|
||||
1,
|
||||
// rgb_out = (char*) rgb_out + out_pitch;
|
||||
reinterpret_cast<char*>(_ntscBuffer) + (NES_NTSC_OUT_WIDTH(PPU::ScreenWidth) * 4 * i),
|
||||
NES_NTSC_OUT_WIDTH(PPU::ScreenWidth) * 4);
|
||||
|
||||
phase = (phase + 1) % 3;
|
||||
}
|
||||
GenerateArgbFrame(_ntscBuffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ private:
|
|||
bool _useExternalPalette = true;
|
||||
uint8_t _palette[512 * 3];
|
||||
uint32_t* _ntscBuffer;
|
||||
uint16_t _ntsc_border;
|
||||
bool _ntscBorder = true;
|
||||
|
||||
void GenerateArgbFrame(uint32_t *outputBuffer);
|
||||
|
||||
|
|
40
Core/PPU.cpp
40
Core/PPU.cpp
|
@ -105,6 +105,8 @@ void PPU::Reset()
|
|||
memset(_oamDecayCycles, 0, sizeof(_oamDecayCycles));
|
||||
_enableOamDecay = _settings->CheckFlag(EmulationFlags::EnableOamDecay);
|
||||
|
||||
_startingPhase = 0;
|
||||
|
||||
UpdateMinimumDrawCycles();
|
||||
}
|
||||
|
||||
|
@ -112,30 +114,37 @@ void PPU::SetNesModel(NesModel model)
|
|||
{
|
||||
_nesModel = model;
|
||||
|
||||
// https://www.nesdev.org/wiki/Cycle_reference_chart
|
||||
switch(_nesModel) {
|
||||
case NesModel::Auto:
|
||||
//Should never be Auto
|
||||
break;
|
||||
|
||||
case NesModel::NTSC:
|
||||
_nmiScanline = 241;
|
||||
_vblankEnd = 260;
|
||||
_standardNmiScanline = 241;
|
||||
_standardVblankEnd = 260;
|
||||
// picture height + postrender blanking lines
|
||||
_nmiScanline = 240 + 1;
|
||||
// picture height + (postrender blanking lines - 1) + vblank length
|
||||
_vblankEnd = 240 + 20;
|
||||
_standardNmiScanline = _nmiScanline;
|
||||
_standardVblankEnd = _vblankEnd;
|
||||
_masterClockDivider = 4;
|
||||
break;
|
||||
case NesModel::PAL:
|
||||
_nmiScanline = 241;
|
||||
_vblankEnd = 310;
|
||||
_standardNmiScanline = 241;
|
||||
_standardVblankEnd = 310;
|
||||
// (picture height + border line) + postrender blanking lines
|
||||
_nmiScanline = 240 + 1;
|
||||
// (picture height + border line) + (postrender blanking lines - 1) + vblank length + 50
|
||||
_vblankEnd = 240 + 20 + 50;
|
||||
_standardNmiScanline = _nmiScanline;
|
||||
_standardVblankEnd = _vblankEnd;
|
||||
_masterClockDivider = 5;
|
||||
break;
|
||||
case NesModel::Dendy:
|
||||
_nmiScanline = 291;
|
||||
_vblankEnd = 310;
|
||||
_standardNmiScanline = 291;
|
||||
_standardVblankEnd = 310;
|
||||
// (picture height + border line) + postrender blanking lines + 50
|
||||
_nmiScanline = 240 + 1 + 50;
|
||||
// (picture height + border line) + (postrender blanking lines - 1) + 50 + vblank length
|
||||
_vblankEnd = 240 + 50 + 20;
|
||||
_standardNmiScanline = _nmiScanline;
|
||||
_standardVblankEnd = _vblankEnd;
|
||||
_masterClockDivider = 5;
|
||||
break;
|
||||
}
|
||||
|
@ -999,10 +1008,9 @@ void PPU::ProcessScanline()
|
|||
LoadTileInfo();
|
||||
}
|
||||
} else if(_cycle == 337 || _cycle == 339) {
|
||||
if(IsRenderingEnabled()) {
|
||||
if (IsRenderingEnabled()) {
|
||||
ReadVram(GetNameTableAddr());
|
||||
|
||||
if(_scanline == -1 && _cycle == 339 && (_frameCount & 0x01) && _nesModel == NesModel::NTSC && _settings->GetPpuModel() == PpuModel::Ppu2C02) {
|
||||
if (_scanline == -1 && _cycle == 339 && (_frameCount & 0x01) && _nesModel == NesModel::NTSC && _settings->GetPpuModel() == PpuModel::Ppu2C02) {
|
||||
//This behavior is NTSC-specific - PAL frames are always the same number of cycles
|
||||
//"With rendering enabled, each odd PPU frame is one PPU clock shorter than normal" (skip from 339 to 0, going over 340)
|
||||
_cycle = 340;
|
||||
|
@ -1347,6 +1355,8 @@ void PPU::Exec()
|
|||
if(_needStateUpdate) {
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
_startingPhase = _cycle % 3;
|
||||
}
|
||||
|
||||
void PPU::UpdateState()
|
||||
|
|
|
@ -109,6 +109,9 @@ class PPU : public IMemoryHandler, public Snapshotable
|
|||
bool _enableOamDecay;
|
||||
bool _corruptOamRow[32];
|
||||
|
||||
// https://forums.nesdev.org/viewtopic.php?p=30625#p30625
|
||||
uint8_t _startingPhase;
|
||||
|
||||
void UpdateStatusFlag();
|
||||
|
||||
void SetControlRegister(uint8_t value);
|
||||
|
@ -217,6 +220,11 @@ class PPU : public IMemoryHandler, public Snapshotable
|
|||
return _frameCount;
|
||||
}
|
||||
|
||||
uint8_t GetStartingPhase()
|
||||
{
|
||||
return _startingPhase;
|
||||
}
|
||||
|
||||
uint32_t GetFrameCycle()
|
||||
{
|
||||
return ((_scanline + 1) * 341) + _cycle;
|
||||
|
|
Loading…
Reference in a new issue