PAL support (PPU & APU)
This commit is contained in:
parent
62d87d6bab
commit
41ae3cdcd2
20 changed files with 236 additions and 26 deletions
24
Core/APU.cpp
24
Core/APU.cpp
|
@ -19,7 +19,6 @@ APU::APU(MemoryManager* memoryManager)
|
|||
_memoryManager = memoryManager;
|
||||
_blipBuffer.reset(new Blip_Buffer());
|
||||
_blipBuffer->sample_rate(APU::SampleRate);
|
||||
_blipBuffer->clock_rate(CPU::ClockRate);
|
||||
|
||||
_outputBuffer = new int16_t[APU::SamplesPerFrame];
|
||||
|
||||
|
@ -45,6 +44,23 @@ APU::~APU()
|
|||
delete[] _outputBuffer;
|
||||
}
|
||||
|
||||
void APU::SetNesModel(NesModel model, bool forceInit)
|
||||
{
|
||||
if(_nesModel != model || forceInit) {
|
||||
//Finish the current apu frame before switching model
|
||||
Run();
|
||||
|
||||
_nesModel = model;
|
||||
_blipBuffer->clock_rate(model == NesModel::NTSC ? CPU::ClockRateNtsc : CPU::ClockRatePal);
|
||||
_squareChannel[0]->SetNesModel(model);
|
||||
_squareChannel[1]->SetNesModel(model);
|
||||
_triangleChannel->SetNesModel(model);
|
||||
_noiseChannel->SetNesModel(model);
|
||||
_deltaModulationChannel->SetNesModel(model);
|
||||
_frameCounter->SetNesModel(model);
|
||||
}
|
||||
}
|
||||
|
||||
void APU::FrameCounterTick(FrameType type)
|
||||
{
|
||||
//Quarter & half frame clock envelope & linear counter
|
||||
|
@ -185,7 +201,6 @@ void APU::StopAudio()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void APU::Reset(bool softReset)
|
||||
{
|
||||
_currentCycle = 0;
|
||||
|
@ -200,6 +215,7 @@ void APU::Reset(bool softReset)
|
|||
|
||||
void APU::StreamState(bool saving)
|
||||
{
|
||||
Stream<NesModel>(_nesModel);
|
||||
Stream<uint32_t>(_currentCycle);
|
||||
Stream<uint32_t>(_previousCycle);
|
||||
Stream(_squareChannel[0].get());
|
||||
|
@ -208,4 +224,8 @@ void APU::StreamState(bool saving)
|
|||
Stream(_noiseChannel.get());
|
||||
Stream(_deltaModulationChannel.get());
|
||||
Stream(_frameCounter.get());
|
||||
|
||||
if(!saving) {
|
||||
SetNesModel(_nesModel, true);
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ class DeltaModulationChannel;
|
|||
class ApuFrameCounter;
|
||||
class Blip_Buffer;
|
||||
enum class FrameType;
|
||||
enum class NesModel;
|
||||
|
||||
class APU : public Snapshotable, public IMemoryHandler
|
||||
{
|
||||
|
@ -34,6 +35,8 @@ class APU : public Snapshotable, public IMemoryHandler
|
|||
int16_t* _outputBuffer;
|
||||
MemoryManager* _memoryManager;
|
||||
|
||||
NesModel _nesModel;
|
||||
|
||||
private:
|
||||
bool NeedToRun(uint32_t currentCycle);
|
||||
void Run();
|
||||
|
@ -59,6 +62,8 @@ class APU : public Snapshotable, public IMemoryHandler
|
|||
APU::AudioDevice = audioDevice;
|
||||
}
|
||||
|
||||
void SetNesModel(NesModel model, bool forceInit = false);
|
||||
|
||||
uint8_t ReadRAM(uint16_t addr);
|
||||
void WriteRAM(uint16_t addr, uint8_t value);
|
||||
void GetMemoryRanges(MemoryRanges &ranges);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "IMemoryHandler.h"
|
||||
#include "CPU.h"
|
||||
#include "EmulationSettings.h"
|
||||
|
||||
enum class FrameType
|
||||
{
|
||||
|
@ -13,11 +14,15 @@ enum class FrameType
|
|||
class ApuFrameCounter : public IMemoryHandler, public Snapshotable
|
||||
{
|
||||
private:
|
||||
const vector<vector<int32_t>> _stepCycles = { { { 7457, 14913, 22371, 29828, 29829, 29830},
|
||||
{ 7457, 14913, 22371, 29829, 37281, 37282} } };
|
||||
const vector<vector<int32_t>> _stepCyclesNtsc = { { { 7457, 14913, 22371, 29828, 29829, 29830},
|
||||
{ 7457, 14913, 22371, 29829, 37281, 37282} } };
|
||||
const vector<vector<int32_t>> _stepCyclesPal = { { { 8313, 16627, 24939, 33252, 33253, 33254},
|
||||
{ 8313, 16627, 24939, 33253, 41565, 41566} } };
|
||||
const vector<vector<FrameType>> _frameType = { { { FrameType::QuarterFrame, FrameType::HalfFrame, FrameType::QuarterFrame, FrameType::None, FrameType::HalfFrame, FrameType::None },
|
||||
{ FrameType::QuarterFrame, FrameType::HalfFrame, FrameType::QuarterFrame, FrameType::None, FrameType::HalfFrame, FrameType::None } } };
|
||||
|
||||
vector<vector<int32_t>> _stepCycles;
|
||||
NesModel _nesModel;
|
||||
int32_t _nextIrqCycle;
|
||||
int32_t _previousCycle;
|
||||
uint32_t _currentStep;
|
||||
|
@ -57,7 +62,22 @@ public:
|
|||
Stream<uint32_t>(_currentStep);
|
||||
Stream<uint32_t>(_stepMode);
|
||||
Stream<bool>(_inhibitIRQ);
|
||||
}
|
||||
Stream<NesModel>(_nesModel);
|
||||
|
||||
if(!saving) {
|
||||
SetNesModel(_nesModel);
|
||||
}
|
||||
}
|
||||
|
||||
void SetNesModel(NesModel model)
|
||||
{
|
||||
if(_nesModel != model || _stepCycles.size() == 0) {
|
||||
_nesModel = model;
|
||||
_stepCycles.clear();
|
||||
_stepCycles.push_back(model == NesModel::NTSC ? _stepCyclesNtsc[0] : _stepCyclesPal[0]);
|
||||
_stepCycles.push_back(model == NesModel::NTSC ? _stepCyclesNtsc[1] : _stepCyclesPal[1]);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Run(int32_t &cyclesToRun)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ private:
|
|||
uint32_t _previousCycle;
|
||||
AudioChannel _channel;
|
||||
double _baseVolume;
|
||||
NesModel _nesModel;
|
||||
|
||||
protected:
|
||||
uint16_t _timer = 0;
|
||||
|
@ -66,12 +67,23 @@ public:
|
|||
Stream<uint32_t>(_previousCycle);
|
||||
Stream<uint16_t>(_timer);
|
||||
Stream<uint16_t>(_period);
|
||||
Stream<NesModel>(_nesModel);
|
||||
|
||||
if(!saving) {
|
||||
_buffer->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void SetNesModel(NesModel model)
|
||||
{
|
||||
_nesModel = model;
|
||||
}
|
||||
|
||||
NesModel GetNesModel()
|
||||
{
|
||||
return _nesModel;
|
||||
}
|
||||
|
||||
virtual void Run(uint32_t targetCycle)
|
||||
{
|
||||
while(_previousCycle < targetCycle) {
|
||||
|
|
|
@ -27,6 +27,7 @@ class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificat
|
|||
|
||||
bool _hasCHRRAM;
|
||||
bool _hasBattery;
|
||||
bool _isPalRom;
|
||||
string _romFilename;
|
||||
|
||||
MirroringType _mirroringType;
|
||||
|
@ -159,6 +160,7 @@ class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificat
|
|||
_prgSize = romLoader.GetPRGSize();
|
||||
_chrSize = romLoader.GetCHRSize();
|
||||
_hasBattery = romLoader.HasBattery();
|
||||
_isPalRom = romLoader.IsPalRom();
|
||||
_romFilename = romLoader.GetFilename();
|
||||
|
||||
_hasExpansionRAM = false;
|
||||
|
@ -252,6 +254,11 @@ class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificat
|
|||
return _hasBattery;
|
||||
}
|
||||
|
||||
bool IsPalRom()
|
||||
{
|
||||
return _isPalRom;
|
||||
}
|
||||
|
||||
MirroringType GetMirroringType()
|
||||
{
|
||||
return _mirroringType;
|
||||
|
|
|
@ -830,7 +830,8 @@ protected:
|
|||
void StreamState(bool saving);
|
||||
|
||||
public:
|
||||
static const uint32_t ClockRate = 1789773;
|
||||
static const uint32_t ClockRateNtsc = 1789773;
|
||||
static const uint32_t ClockRatePal = 1662607;
|
||||
|
||||
CPU(MemoryManager *memoryManager);
|
||||
static int32_t GetCycleCount() { return CPU::Instance->_cycleCount; }
|
||||
|
|
|
@ -153,13 +153,15 @@ void Console::Resume()
|
|||
void Console::Run()
|
||||
{
|
||||
Timer clockTimer;
|
||||
double targetTime;
|
||||
double elapsedTime = 0;
|
||||
double targetTime = 16.63926405550947; //~60.0988fps
|
||||
uint32_t lastFrameNumber = -1;
|
||||
|
||||
_runLock.Acquire();
|
||||
_stopLock.Acquire();
|
||||
|
||||
uint32_t lastFrameNumber = -1;
|
||||
UpdateNesModel(targetTime, true);
|
||||
|
||||
while(true) {
|
||||
_cpu->Exec();
|
||||
uint32_t currentFrameNumber = PPU::GetFrameCount();
|
||||
|
@ -200,6 +202,8 @@ void Console::Run()
|
|||
_runLock.Acquire();
|
||||
MessageManager::SendNotification(ConsoleNotificationType::GameResumed);
|
||||
}
|
||||
|
||||
UpdateNesModel(targetTime, false);
|
||||
clockTimer.Reset();
|
||||
|
||||
if(_stop) {
|
||||
|
@ -213,6 +217,17 @@ void Console::Run()
|
|||
_runLock.Release();
|
||||
}
|
||||
|
||||
void Console::UpdateNesModel(double &frameDelay, bool showMessage)
|
||||
{
|
||||
NesModel model = EmulationSettings::GetNesModel();
|
||||
if(model == NesModel::Auto) {
|
||||
model = _mapper->IsPalRom() ? NesModel::PAL : NesModel::NTSC;
|
||||
}
|
||||
frameDelay = (model == NesModel::NTSC ? 16.63926405550947 : 19.99720920217466); //60.1fps (NTSC), 50.01fps (PAL)
|
||||
_ppu->SetNesModel(model);
|
||||
_apu->SetNesModel(model);
|
||||
}
|
||||
|
||||
void Console::SaveState(ostream &saveStream)
|
||||
{
|
||||
if(Instance->_initialized) {
|
||||
|
|
|
@ -35,6 +35,7 @@ class Console
|
|||
|
||||
void ResetComponents(bool softReset);
|
||||
void Initialize(string filename);
|
||||
void UpdateNesModel(double &frameDelay, bool showMessage);
|
||||
|
||||
public:
|
||||
Console();
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
class DeltaModulationChannel : public BaseApuChannel<127>
|
||||
{
|
||||
private:
|
||||
const vector<uint16_t> _dmcPeriodLookupTable = { { 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54 } };
|
||||
const vector<uint16_t> _dmcPeriodLookupTableNtsc = { { 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54 } };
|
||||
const vector<uint16_t> _dmcPeriodLookupTablePal = { { 398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118, 98, 78, 66, 50 } };
|
||||
|
||||
MemoryManager *_memoryManager = nullptr;
|
||||
|
||||
|
@ -164,7 +165,7 @@ public:
|
|||
|
||||
//"The rate determines for how many CPU cycles happen between changes in the output level during automatic delta-encoded sample playback."
|
||||
//Because BaseApuChannel does not decrement when setting _timer, we need to actually set the value to 1 less than the lookup table
|
||||
_period = _dmcPeriodLookupTable[value & 0x0F] - 1;
|
||||
_period = (GetNesModel() == NesModel::NTSC ? _dmcPeriodLookupTableNtsc : _dmcPeriodLookupTablePal)[value & 0x0F] - 1;
|
||||
|
||||
if(!_irqEnabled) {
|
||||
CPU::ClearIRQSource(IRQSource::DMC);
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
|
||||
uint32_t EmulationSettings::Flags = 0;
|
||||
uint32_t EmulationSettings::AudioLatency = 20000;
|
||||
double EmulationSettings::ChannelVolume[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
|
||||
double EmulationSettings::ChannelVolume[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
|
||||
NesModel EmulationSettings::Model;
|
|
@ -18,12 +18,20 @@ enum class AudioChannel
|
|||
DMC = 4
|
||||
};
|
||||
|
||||
enum class NesModel
|
||||
{
|
||||
Auto = 0,
|
||||
NTSC = 1,
|
||||
PAL = 2,
|
||||
};
|
||||
|
||||
class EmulationSettings
|
||||
{
|
||||
private:
|
||||
static uint32_t Flags;
|
||||
static uint32_t AudioLatency;
|
||||
static double ChannelVolume[5];
|
||||
static NesModel Model;
|
||||
|
||||
public:
|
||||
static void SetFlags(uint32_t flags)
|
||||
|
@ -41,6 +49,16 @@ public:
|
|||
return (Flags & flag) == flag;
|
||||
}
|
||||
|
||||
static void SetNesModel(NesModel model)
|
||||
{
|
||||
Model = model;
|
||||
}
|
||||
|
||||
static NesModel GetNesModel()
|
||||
{
|
||||
return Model;
|
||||
}
|
||||
|
||||
//0: Muted, 0.5: Default, 1.0: Max volume
|
||||
static void SetChannelVolume(AudioChannel channel, double volume)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
class NoiseChannel : public ApuEnvelope
|
||||
{
|
||||
private:
|
||||
const vector<uint16_t> _noisePeriodLookupTable = { { 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068 } };
|
||||
const vector<uint16_t> _noisePeriodLookupTableNtsc = { { 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068 } };
|
||||
const vector<uint16_t> _noisePeriodLookupTablePal = { { 4, 8, 14, 30, 60, 88, 118, 148, 188, 236, 354, 472, 708, 944, 1890, 3778 } };
|
||||
|
||||
//On power-up, the shift register is loaded with the value 1.
|
||||
uint16_t _shiftRegister = 1;
|
||||
|
@ -73,7 +74,7 @@ public:
|
|||
break;
|
||||
|
||||
case 2: //400E
|
||||
_period = _noisePeriodLookupTable[value & 0x0F];
|
||||
_period = (GetNesModel() == NesModel::NTSC ? _noisePeriodLookupTableNtsc : _noisePeriodLookupTablePal)[value & 0x0F];
|
||||
break;
|
||||
|
||||
case 3: //400F
|
||||
|
|
25
Core/PPU.cpp
25
Core/PPU.cpp
|
@ -1,6 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "PPU.h"
|
||||
#include "CPU.h"
|
||||
#include "EmulationSettings.h"
|
||||
|
||||
PPU* PPU::Instance = nullptr;
|
||||
IVideoDevice *PPU::VideoDevice = nullptr;
|
||||
|
@ -50,6 +51,12 @@ void PPU::Reset()
|
|||
memset(_spriteRAM, 0xFF, 0x100);
|
||||
}
|
||||
|
||||
void PPU::SetNesModel(NesModel model)
|
||||
{
|
||||
_nesModel = model;
|
||||
_vblankEnd = (model == NesModel::NTSC ? 260 : 311);
|
||||
}
|
||||
|
||||
PPUDebugState PPU::GetState()
|
||||
{
|
||||
PPUDebugState state;
|
||||
|
@ -473,7 +480,8 @@ void PPU::ProcessPrerenderScanline()
|
|||
//copy vertical scrolling value from t
|
||||
_state.VideoRamAddr = (_state.VideoRamAddr & ~0x7BE0) | (_state.TmpVideoRamAddr & 0x7BE0);
|
||||
}
|
||||
} else if(_cycle == 339 && IsRenderingEnabled() && (_frameCount & 0x01)) {
|
||||
} else if(_nesModel == NesModel::NTSC && _cycle == 339 && IsRenderingEnabled() && (_frameCount & 0x01)) {
|
||||
//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 = -1;
|
||||
_scanline = 0;
|
||||
|
@ -626,15 +634,14 @@ void PPU::Exec()
|
|||
ProcessPrerenderScanline();
|
||||
} else if(_scanline == 241) {
|
||||
BeginVBlank();
|
||||
} else if(_scanline == 260) {
|
||||
} else if(_scanline == _vblankEnd) {
|
||||
EndVBlank();
|
||||
}
|
||||
|
||||
if(_cycle == 340) {
|
||||
_cycle = -1;
|
||||
_scanline++;
|
||||
|
||||
if(_scanline == 261) {
|
||||
if(_scanline++ == _vblankEnd) {
|
||||
_scanline = -1;
|
||||
}
|
||||
}
|
||||
|
@ -646,6 +653,10 @@ void PPU::ExecStatic()
|
|||
PPU::Instance->Exec();
|
||||
PPU::Instance->Exec();
|
||||
PPU::Instance->Exec();
|
||||
if(PPU::Instance->_nesModel == NesModel::PAL && CPU::GetCycleCount() % 5 == 0) {
|
||||
//PAL PPU runs 3.2 clocks for every CPU clock, so we need to run an extra clock every 5 CPU clocks
|
||||
PPU::Instance->Exec();
|
||||
}
|
||||
}
|
||||
|
||||
void PPU::StreamState(bool saving)
|
||||
|
@ -717,4 +728,10 @@ void PPU::StreamState(bool saving)
|
|||
Stream<bool>(_writeOAMData);
|
||||
Stream<uint32_t>(_overflowCounter);
|
||||
Stream<bool>(_sprite0Added);
|
||||
|
||||
Stream<NesModel>(_nesModel);
|
||||
|
||||
if(!saving) {
|
||||
SetNesModel(_nesModel);
|
||||
}
|
||||
}
|
17
Core/PPU.h
17
Core/PPU.h
|
@ -5,6 +5,8 @@
|
|||
#include "MemoryManager.h"
|
||||
#include "IVideoDevice.h"
|
||||
|
||||
enum class NesModel;
|
||||
|
||||
enum PPURegisters
|
||||
{
|
||||
Control = 0x00,
|
||||
|
@ -92,11 +94,11 @@ class PPU : public IMemoryHandler, public Snapshotable
|
|||
MemoryManager *_memoryManager;
|
||||
|
||||
PPUState _state;
|
||||
int32_t _scanline = 0;
|
||||
uint32_t _cycle = 0;
|
||||
uint32_t _frameCount = 0;
|
||||
uint8_t _memoryReadBuffer = 0;
|
||||
|
||||
int32_t _scanline;
|
||||
uint32_t _cycle;
|
||||
uint32_t _frameCount;
|
||||
uint8_t _memoryReadBuffer;
|
||||
|
||||
uint8_t _paletteRAM[0x100];
|
||||
|
||||
uint8_t _spriteRAM[0x100];
|
||||
|
@ -104,6 +106,9 @@ class PPU : public IMemoryHandler, public Snapshotable
|
|||
|
||||
uint32_t *_outputBuffer;
|
||||
|
||||
NesModel _nesModel;
|
||||
uint16_t _vblankEnd;
|
||||
|
||||
PPUControlFlags _flags;
|
||||
PPUStatusFlags _statusFlags;
|
||||
|
||||
|
@ -192,6 +197,8 @@ class PPU : public IMemoryHandler, public Snapshotable
|
|||
uint8_t ReadRAM(uint16_t addr);
|
||||
void WriteRAM(uint16_t addr, uint8_t value);
|
||||
|
||||
void SetNesModel(NesModel model);
|
||||
|
||||
void Exec();
|
||||
static void ExecStatic();
|
||||
|
||||
|
|
|
@ -40,6 +40,11 @@ struct NESHeader
|
|||
return (Flags1 & 0x04) == 0x04;
|
||||
}
|
||||
|
||||
bool IsPalRom()
|
||||
{
|
||||
return (CartType & 0x01) == 0x01;
|
||||
}
|
||||
|
||||
MirroringType GetMirroringType()
|
||||
{
|
||||
if(Flags1 & 0x08) {
|
||||
|
@ -218,6 +223,11 @@ class ROMLoader
|
|||
return _header.HasBattery();
|
||||
}
|
||||
|
||||
bool IsPalRom()
|
||||
{
|
||||
return _header.IsPalRom() || _filename.find("(e)") != string::npos || _filename.find("(E)") != string::npos;
|
||||
}
|
||||
|
||||
string GetFilename()
|
||||
{
|
||||
return _filename;
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace Mesen.GUI.Config
|
|||
public List<CheatInfo> Cheats;
|
||||
public List<ControllerInfo> Controllers;
|
||||
public bool ShowOnlyCheatsForCurrentGame;
|
||||
public NesModel Region;
|
||||
|
||||
public Configuration()
|
||||
{
|
||||
|
@ -33,6 +34,15 @@ namespace Mesen.GUI.Config
|
|||
Controllers = new List<ControllerInfo>();
|
||||
}
|
||||
|
||||
public void ApplyConfig()
|
||||
{
|
||||
ControllerInfo.ApplyConfig();
|
||||
VideoInfo.ApplyConfig();
|
||||
AudioInfo.ApplyConfig();
|
||||
|
||||
InteropEmu.SetNesModel(Region);
|
||||
}
|
||||
|
||||
private void InitializeDefaults()
|
||||
{
|
||||
while(Controllers.Count < 4) {
|
||||
|
|
44
GUI.NET/Forms/frmMain.Designer.cs
generated
44
GUI.NET/Forms/frmMain.Designer.cs
generated
|
@ -78,6 +78,10 @@
|
|||
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.dxViewer = new Mesen.GUI.Controls.DXViewer();
|
||||
this.mnuRegion = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRegionAuto = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRegionNtsc = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRegionPal = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuStrip.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
|
@ -201,9 +205,10 @@
|
|||
this.mnuLimitFPS,
|
||||
this.mnuShowFPS,
|
||||
this.toolStripMenuItem1,
|
||||
this.mnuAudioConfig,
|
||||
this.mnuInput,
|
||||
this.mnuVideoConfig,
|
||||
this.mnuAudioConfig});
|
||||
this.mnuRegion,
|
||||
this.mnuVideoConfig});
|
||||
this.mnuOptions.Name = "mnuOptions";
|
||||
this.mnuOptions.Size = new System.Drawing.Size(61, 20);
|
||||
this.mnuOptions.Text = "Options";
|
||||
|
@ -439,6 +444,37 @@
|
|||
this.dxViewer.Size = new System.Drawing.Size(1024, 896);
|
||||
this.dxViewer.TabIndex = 1;
|
||||
//
|
||||
// mnuRegion
|
||||
//
|
||||
this.mnuRegion.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuRegionAuto,
|
||||
this.mnuRegionNtsc,
|
||||
this.mnuRegionPal});
|
||||
this.mnuRegion.Name = "mnuRegion";
|
||||
this.mnuRegion.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRegion.Text = "Region";
|
||||
//
|
||||
// mnuRegionAuto
|
||||
//
|
||||
this.mnuRegionAuto.Name = "mnuRegionAuto";
|
||||
this.mnuRegionAuto.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRegionAuto.Text = "Auto";
|
||||
this.mnuRegionAuto.Click += new System.EventHandler(this.mnuRegion_Click);
|
||||
//
|
||||
// mnuRegionNtsc
|
||||
//
|
||||
this.mnuRegionNtsc.Name = "mnuRegionNtsc";
|
||||
this.mnuRegionNtsc.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRegionNtsc.Text = "NTSC";
|
||||
this.mnuRegionNtsc.Click += new System.EventHandler(this.mnuRegion_Click);
|
||||
//
|
||||
// mnuRegionPal
|
||||
//
|
||||
this.mnuRegionPal.Name = "mnuRegionPal";
|
||||
this.mnuRegionPal.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRegionPal.Text = "PAL";
|
||||
this.mnuRegionPal.Click += new System.EventHandler(this.mnuRegion_Click);
|
||||
//
|
||||
// frmMain
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
|
@ -504,6 +540,10 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem mnuLoadState;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem7;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuCheats;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuRegion;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuRegionAuto;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuRegionNtsc;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuRegionPal;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,8 +58,7 @@ namespace Mesen.GUI.Forms
|
|||
InteropEmu.AddKnowGameFolder(System.IO.Path.GetDirectoryName(romPath).ToLowerInvariant());
|
||||
}
|
||||
|
||||
ControllerInfo.ApplyConfig();
|
||||
AudioInfo.ApplyConfig();
|
||||
ConfigManager.Config.ApplyConfig();
|
||||
|
||||
UpdateEmulationFlags();
|
||||
}
|
||||
|
@ -135,6 +134,10 @@ namespace Mesen.GUI.Forms
|
|||
mnuDebugger.Enabled = !netPlay && _emuThread != null;
|
||||
|
||||
mnuTakeScreenshot.Enabled = _emuThread != null;
|
||||
|
||||
mnuRegionAuto.Checked = ConfigManager.Config.Region == NesModel.Auto;
|
||||
mnuRegionNtsc.Checked = ConfigManager.Config.Region == NesModel.NTSC;
|
||||
mnuRegionPal.Checked = ConfigManager.Config.Region == NesModel.PAL;
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
|
@ -403,5 +406,17 @@ namespace Mesen.GUI.Forms
|
|||
frmAudioConfig frm = new frmAudioConfig();
|
||||
frm.ShowDialog();
|
||||
}
|
||||
|
||||
private void mnuRegion_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(sender == mnuRegionAuto) {
|
||||
ConfigManager.Config.Region = NesModel.Auto;
|
||||
} else if(sender == mnuRegionNtsc) {
|
||||
ConfigManager.Config.Region = NesModel.NTSC;
|
||||
} else if(sender == mnuRegionPal) {
|
||||
ConfigManager.Config.Region = NesModel.PAL;
|
||||
}
|
||||
ConfigManager.Config.ApplyConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace Mesen.GUI
|
|||
[DllImport(DLLPath)] public static extern void ClearFlags(UInt32 flags);
|
||||
[DllImport(DLLPath)] public static extern void SetChannelVolume(UInt32 channel, double volume);
|
||||
[DllImport(DLLPath)] public static extern void SetAudioLatency(UInt32 msLatency);
|
||||
[DllImport(DLLPath)] public static extern void SetNesModel(NesModel model);
|
||||
|
||||
[DllImport(DLLPath)] public static extern void DebugInitialize();
|
||||
[DllImport(DLLPath)] public static extern void DebugRelease();
|
||||
|
@ -272,6 +273,13 @@ namespace Mesen.GUI
|
|||
Write = 2
|
||||
};
|
||||
|
||||
public enum NesModel
|
||||
{
|
||||
Auto = 0,
|
||||
NTSC = 1,
|
||||
PAL = 2
|
||||
}
|
||||
|
||||
public class MD5Helper
|
||||
{
|
||||
public static string GetMD5Hash(string filename)
|
||||
|
|
|
@ -162,6 +162,7 @@ namespace InteropEmu {
|
|||
DllExport void __stdcall ClearFlags(uint32_t flags) { EmulationSettings::ClearFlags(flags); }
|
||||
DllExport void __stdcall SetChannelVolume(uint32_t channel, double volume) { EmulationSettings::SetChannelVolume((AudioChannel)channel, volume); }
|
||||
DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { EmulationSettings::SetAudioLatency(msLatency); }
|
||||
DllExport void __stdcall SetNesModel(uint32_t model) { EmulationSettings::SetNesModel((NesModel)model); }
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue