BS-X: Improved emulation and support for .bin broadcast files
This commit is contained in:
parent
cf909b56d8
commit
b29fabbb57
21 changed files with 679 additions and 28 deletions
|
@ -5,6 +5,7 @@
|
|||
#include "MemoryMappings.h"
|
||||
#include "BaseCartridge.h"
|
||||
#include "BsxMemoryPack.h"
|
||||
#include "BsxSatellaview.h"
|
||||
#include "RamHandler.h"
|
||||
#include "EmuSettings.h"
|
||||
|
||||
|
@ -18,10 +19,10 @@ BsxCart::BsxCart(Console* console, BsxMemoryPack* memPack)
|
|||
mm->RegisterHandler(0x00, 0x0F, 0x5000, 0x5FFF, this);
|
||||
mm->RegisterHandler(0x10, 0x1F, 0x5000, 0x5FFF, _console->GetCartridge()->GetSaveRamHandlers());
|
||||
|
||||
//Regular B Bus register handler, keep a reference to it, it'll be overwritten below
|
||||
_bBusHandler = mm->GetHandler(0x2000);
|
||||
mm->RegisterHandler(0x00, 0x3F, 0x2000, 0x2FFF, this);
|
||||
mm->RegisterHandler(0x80, 0xBF, 0x2000, 0x2FFF, this);
|
||||
//Override regular B-bus handler
|
||||
_satellaview.reset(new BsxSatellaview(console, mm->GetHandler(0x2000)));
|
||||
mm->RegisterHandler(0x00, 0x3F, 0x2000, 0x2FFF, _satellaview.get());
|
||||
mm->RegisterHandler(0x80, 0xBF, 0x2000, 0x2FFF, _satellaview.get());
|
||||
|
||||
_psRamSize = 512 * 1024;
|
||||
_psRam = new uint8_t[_psRamSize];
|
||||
|
@ -41,17 +42,6 @@ BsxCart::~BsxCart()
|
|||
|
||||
uint8_t BsxCart::Read(uint32_t addr)
|
||||
{
|
||||
if((addr & 0x6000) == 0x2000) {
|
||||
addr &= 0xFFFF;
|
||||
if(addr >= 0x2188 && addr <= 0x219F) {
|
||||
//Handle BS-X $2188-219F registers
|
||||
return 0;
|
||||
} else {
|
||||
//Use regular B-bus handler for everything else
|
||||
return _bBusHandler->Read(addr);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t openBus = _memoryManager->GetOpenBus();
|
||||
if((addr & 0xFFFF) != 0x5000) {
|
||||
return openBus;
|
||||
|
@ -69,16 +59,7 @@ uint8_t BsxCart::Read(uint32_t addr)
|
|||
|
||||
void BsxCart::Write(uint32_t addr, uint8_t value)
|
||||
{
|
||||
if((addr & 0x6000) == 0x2000) {
|
||||
addr &= 0xFFFF;
|
||||
if(addr >= 0x2188 && addr <= 0x219F) {
|
||||
//Handle BS-X register writes
|
||||
} else {
|
||||
//Regular B-bus handler
|
||||
_bBusHandler->Write(addr, value);
|
||||
}
|
||||
return;
|
||||
} else if((addr & 0xFFFF) != 0x5000) {
|
||||
if((addr & 0xFFFF) != 0x5000) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -196,6 +177,8 @@ void BsxCart::Reset()
|
|||
_dirty = false;
|
||||
memcpy(_dirtyRegs, _regs, sizeof(_regs));
|
||||
|
||||
_satellaview->Reset();
|
||||
|
||||
UpdateMemoryMappings();
|
||||
}
|
||||
|
||||
|
@ -205,6 +188,7 @@ void BsxCart::Serialize(Serializer& s)
|
|||
ArrayInfo<uint8_t> regs = { _regs, 0x10 };
|
||||
ArrayInfo<uint8_t> dirtyRegs = { _dirtyRegs, 0x10 };
|
||||
s.Stream(psRam, regs, dirtyRegs, _dirty);
|
||||
s.Stream(_satellaview.get());
|
||||
|
||||
if(!s.IsSaving()) {
|
||||
UpdateMemoryMappings();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
class Console;
|
||||
class MemoryManager;
|
||||
class BsxMemoryPack;
|
||||
class BsxSatellaview;
|
||||
|
||||
class BsxCart : public BaseCoprocessor
|
||||
{
|
||||
|
@ -12,13 +13,12 @@ private:
|
|||
Console* _console;
|
||||
MemoryManager* _memoryManager;
|
||||
BsxMemoryPack* _memPack;
|
||||
unique_ptr<BsxSatellaview> _satellaview;
|
||||
|
||||
uint8_t* _psRam = nullptr;
|
||||
uint32_t _psRamSize = 0;
|
||||
vector<unique_ptr<IMemoryHandler>> _psRamHandlers;
|
||||
|
||||
IMemoryHandler* _bBusHandler = nullptr;
|
||||
|
||||
uint8_t _regs[0x10] = {};
|
||||
uint8_t _dirtyRegs[0x10] = {};
|
||||
bool _dirty = false;
|
||||
|
|
101
Core/BsxSatellaview.cpp
Normal file
101
Core/BsxSatellaview.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
#include "stdafx.h"
|
||||
#include "BsxSatellaview.h"
|
||||
#include "Console.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
BsxSatellaview::BsxSatellaview(Console* console, IMemoryHandler* bBusHandler)
|
||||
{
|
||||
_customDate = console->GetSettings()->GetEmulationConfig().BsxCustomDate;
|
||||
_bBusHandler = bBusHandler;
|
||||
Reset();
|
||||
}
|
||||
|
||||
void BsxSatellaview::Reset()
|
||||
{
|
||||
_streamReg = 0;
|
||||
_extOutput = 0xFF;
|
||||
_stream[0].Reset(_customDate);
|
||||
_stream[1].Reset(_customDate);
|
||||
}
|
||||
|
||||
uint8_t BsxSatellaview::Read(uint32_t addr)
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
if(addr >= 0x2188 && addr <= 0x219F) {
|
||||
//Handle BS-X $2188-219F registers
|
||||
switch(addr) {
|
||||
case 0x2188: return _stream[0].GetChannel() & 0xFF;
|
||||
case 0x2189: return (_stream[0].GetChannel()) >> 8;
|
||||
case 0x218A: return _stream[0].GetPrefixCount();
|
||||
case 0x218B: return _stream[0].GetPrefix();
|
||||
case 0x218C: return _stream[0].GetData();
|
||||
case 0x218D: return _stream[0].GetStatus((_streamReg & 0x01) != 0);
|
||||
|
||||
case 0x218E: return _stream[1].GetChannel() & 0xFF;
|
||||
case 0x218F: return (_stream[1].GetChannel()) >> 8;
|
||||
case 0x2190: return _stream[1].GetPrefixCount();
|
||||
case 0x2191: return _stream[1].GetPrefix();
|
||||
case 0x2192: return _stream[1].GetData();
|
||||
case 0x2193: return _stream[1].GetStatus((_streamReg & 0x01) != 0);
|
||||
|
||||
case 0x2194: return _streamReg; //LED and Stream register
|
||||
case 0x2195: return 0; //Unknown
|
||||
case 0x2196: return 0x10; //Satellaview status
|
||||
case 0x2197: return _extOutput; //Soundlink / EXT output
|
||||
case 0x2198: return 0x80; //Serial IO (Serial number)
|
||||
case 0x2199: return 0x01; //Serial IO (???)
|
||||
case 0x219A: return 0x10; //Unknown
|
||||
}
|
||||
}
|
||||
|
||||
//Use regular B-bus handler for everything else
|
||||
return _bBusHandler->Read(addr);
|
||||
}
|
||||
|
||||
void BsxSatellaview::Write(uint32_t addr, uint8_t value)
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
if(addr >= 0x2188 && addr <= 0x219F) {
|
||||
//Handle BS-X register writes
|
||||
switch(addr) {
|
||||
case 0x2188: _stream[0].SetChannelLow(value); break;
|
||||
case 0x2189: _stream[0].SetChannelHigh(value); break;
|
||||
case 0x218B: _stream[0].SetPrefixLatch(value); break;
|
||||
case 0x218C: _stream[0].SetDataLatch(value); break;
|
||||
|
||||
case 0x218E: _stream[1].SetChannelLow(value); break;
|
||||
case 0x218F: _stream[1].SetChannelHigh(value); break;
|
||||
case 0x2191: _stream[1].SetPrefixLatch(value); break;
|
||||
case 0x2192: _stream[1].SetDataLatch(value); break;
|
||||
|
||||
case 0x2194: _streamReg = value; break;
|
||||
case 0x2197: _extOutput = value; break;
|
||||
}
|
||||
} else {
|
||||
//Regular B-bus handler
|
||||
_bBusHandler->Write(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t BsxSatellaview::Peek(uint32_t addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BsxSatellaview::PeekBlock(uint32_t addr, uint8_t* output)
|
||||
{
|
||||
memset(output, 0, 0x1000);
|
||||
}
|
||||
|
||||
AddressInfo BsxSatellaview::GetAbsoluteAddress(uint32_t address)
|
||||
{
|
||||
return { -1, SnesMemoryType::Register };
|
||||
}
|
||||
|
||||
void BsxSatellaview::Serialize(Serializer& s)
|
||||
{
|
||||
s.Stream(_extOutput, _streamReg);
|
||||
s.Stream(&_stream[0]);
|
||||
s.Stream(&_stream[1]);
|
||||
}
|
31
Core/BsxSatellaview.h
Normal file
31
Core/BsxSatellaview.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "IMemoryHandler.h"
|
||||
#include "BsxStream.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class Console;
|
||||
|
||||
class BsxSatellaview : public IMemoryHandler, public ISerializable
|
||||
{
|
||||
private:
|
||||
IMemoryHandler* _bBusHandler;
|
||||
|
||||
BsxStream _stream[2];
|
||||
uint8_t _streamReg;
|
||||
uint8_t _extOutput;
|
||||
int64_t _customDate;
|
||||
|
||||
public:
|
||||
BsxSatellaview(Console* console, IMemoryHandler *bBusHandler);
|
||||
|
||||
void Reset();
|
||||
|
||||
uint8_t Read(uint32_t addr) override;
|
||||
uint8_t Peek(uint32_t addr) override;
|
||||
void PeekBlock(uint32_t addr, uint8_t* output) override;
|
||||
void Write(uint32_t addr, uint8_t value) override;
|
||||
AddressInfo GetAbsoluteAddress(uint32_t address) override;
|
||||
|
||||
void Serialize(Serializer& s) override;
|
||||
};
|
280
Core/BsxStream.cpp
Normal file
280
Core/BsxStream.cpp
Normal file
|
@ -0,0 +1,280 @@
|
|||
#include "stdafx.h"
|
||||
#include "BsxStream.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
BsxStream::BsxStream()
|
||||
{
|
||||
}
|
||||
|
||||
void BsxStream::Reset(int64_t customDate)
|
||||
{
|
||||
_file.close();
|
||||
|
||||
_channel = 0;
|
||||
_prefix = 0;
|
||||
_data = 0;
|
||||
_status = 0;
|
||||
|
||||
_prefixLatch = false;
|
||||
_dataLatch = false;
|
||||
_firstPacket = false;
|
||||
_fileOffset = 0;
|
||||
_fileIndex = 0;
|
||||
|
||||
_queueLength = 0;
|
||||
_prefixQueueLength = 0;
|
||||
_dataQueueLength = 0;
|
||||
|
||||
_activeChannel = 0;
|
||||
_activeFileIndex = 0;
|
||||
|
||||
_customDate = customDate;
|
||||
time(&_resetTime);
|
||||
_latchedTime = 0;
|
||||
_tm = {};
|
||||
}
|
||||
|
||||
uint16_t BsxStream::GetChannel()
|
||||
{
|
||||
return _channel;
|
||||
}
|
||||
|
||||
void BsxStream::FillQueues()
|
||||
{
|
||||
//TODO: Make this run based on master clock
|
||||
while(_queueLength > 0) {
|
||||
_queueLength--;
|
||||
if(_prefixLatch && _prefixQueueLength < 0x80) {
|
||||
_prefixQueueLength++;
|
||||
}
|
||||
if(_dataLatch && _dataQueueLength < 0x80) {
|
||||
_dataQueueLength++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BsxStream::OpenStreamFile()
|
||||
{
|
||||
_file.close();
|
||||
string filename = "BSX" + HexUtilities::ToHex(_activeChannel) + "-" + std::to_string(_activeFileIndex) + ".bin";
|
||||
string folder = FolderUtilities::CombinePath(FolderUtilities::GetHomeFolder(), "Satellaview");
|
||||
_file.open(FolderUtilities::CombinePath(folder, filename), ios::binary);
|
||||
}
|
||||
|
||||
bool BsxStream::LoadStreamFile()
|
||||
{
|
||||
_activeChannel = _channel;
|
||||
_activeFileIndex = _fileIndex;
|
||||
|
||||
OpenStreamFile();
|
||||
|
||||
if(_file) {
|
||||
_firstPacket = true;
|
||||
_file.seekg(0, ios::end);
|
||||
_queueLength = (uint16_t)std::ceil(_file.tellg() / 22.0);
|
||||
_file.seekg(0, ios::beg);
|
||||
_fileIndex++;
|
||||
FillQueues();
|
||||
return true;
|
||||
} else {
|
||||
if(_fileIndex > 0) {
|
||||
//Go back to file #0 and try again
|
||||
_fileIndex = 0;
|
||||
if(LoadStreamFile()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Couldn't load data for the specified channel
|
||||
_prefix |= 0x0F;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t BsxStream::GetPrefixCount()
|
||||
{
|
||||
if(!_prefixLatch || !_dataLatch) {
|
||||
//Stream is disabled
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(_prefixQueueLength == 0 && _dataQueueLength == 0) {
|
||||
//Queue is empty, try to load in new data
|
||||
_fileOffset = 0;
|
||||
if(_channel == 0) {
|
||||
//Time channel
|
||||
_queueLength = 1;
|
||||
FillQueues();
|
||||
_firstPacket = true;
|
||||
} else {
|
||||
LoadStreamFile();
|
||||
}
|
||||
}
|
||||
|
||||
return _prefixQueueLength;
|
||||
}
|
||||
|
||||
uint8_t BsxStream::GetPrefix()
|
||||
{
|
||||
if(!_prefixLatch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(_prefixQueueLength > 0) {
|
||||
_prefix = 0;
|
||||
if(_firstPacket) {
|
||||
_prefix |= 0x10;
|
||||
_firstPacket = false;
|
||||
}
|
||||
|
||||
_prefixQueueLength--;
|
||||
if(_queueLength == 0 && _prefixQueueLength == 0) {
|
||||
//Last packet
|
||||
_prefix |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
_status |= _prefix;
|
||||
|
||||
return _prefix;
|
||||
}
|
||||
|
||||
uint8_t BsxStream::GetData()
|
||||
{
|
||||
if(!_dataLatch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(_dataQueueLength > 0) {
|
||||
if(_channel == 0) {
|
||||
//Return Time
|
||||
_data = GetTime();
|
||||
} else if(_file) {
|
||||
//Read byte from stream file
|
||||
char byte;
|
||||
_file.get(byte);
|
||||
_data = (uint8_t)byte;
|
||||
}
|
||||
|
||||
_fileOffset++;
|
||||
if(_fileOffset % 22 == 0) {
|
||||
//Finished reading current packet
|
||||
_dataQueueLength--;
|
||||
}
|
||||
}
|
||||
|
||||
return _data;
|
||||
}
|
||||
|
||||
uint8_t BsxStream::GetStatus(bool reset)
|
||||
{
|
||||
uint8_t status = _status;
|
||||
if(reset) {
|
||||
_status = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void BsxStream::SetChannelLow(uint8_t value)
|
||||
{
|
||||
if((_channel & 0xFF) != 0xFF) {
|
||||
_fileIndex = 0;
|
||||
}
|
||||
_channel = (_channel & 0xFF00) | value;
|
||||
if(_channel == 0) {
|
||||
std::cout << "Test";
|
||||
}
|
||||
}
|
||||
|
||||
void BsxStream::SetChannelHigh(uint8_t value)
|
||||
{
|
||||
if((_channel >> 8) != (value & 0x3F)) {
|
||||
_fileIndex = 0;
|
||||
}
|
||||
_channel = (_channel & 0xFF) | ((value & 0x3F) << 8);
|
||||
if(_channel == 0) {
|
||||
std::cout << "Test";
|
||||
}
|
||||
}
|
||||
|
||||
void BsxStream::SetPrefixLatch(uint8_t value)
|
||||
{
|
||||
_prefixLatch = (value != 0);
|
||||
_prefixQueueLength = 0;
|
||||
}
|
||||
|
||||
void BsxStream::SetDataLatch(uint8_t value)
|
||||
{
|
||||
_dataLatch = (value != 0);
|
||||
_dataQueueLength = 0;
|
||||
}
|
||||
|
||||
void BsxStream::InitTimeStruct()
|
||||
{
|
||||
if(_customDate >= 0) {
|
||||
//Use custom date
|
||||
time_t elapsed = _latchedTime - _resetTime;
|
||||
_latchedTime = _customDate + elapsed;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
localtime_s(&_tm, &_latchedTime);
|
||||
#else
|
||||
localtime_r(&_latchedTime, &_tm);
|
||||
#endif
|
||||
|
||||
_tm.tm_wday++;
|
||||
_tm.tm_mon++;
|
||||
_tm.tm_year += 1900;
|
||||
}
|
||||
|
||||
uint8_t BsxStream::GetTime()
|
||||
{
|
||||
if(_fileOffset == 0) {
|
||||
time(&_latchedTime);
|
||||
InitTimeStruct();
|
||||
}
|
||||
|
||||
switch(_fileOffset) {
|
||||
case 0: return 0x00; //Data Group ID / Repetition
|
||||
case 1: return 0x00; //Data Group Link / Continuity
|
||||
case 2: return 0x00; //Data Group Size (24-bit)
|
||||
case 3: return 0x00;
|
||||
case 4: return 0x10;
|
||||
case 5: return 0x01; //Must be 0x01
|
||||
case 6: return 0x01; //Amount of packets (1)
|
||||
case 7: return 0x00; //Offset (24-bit)
|
||||
case 8: return 0x00;
|
||||
case 9: return 0x00;
|
||||
case 10: return _tm.tm_sec;
|
||||
case 11: return _tm.tm_min;
|
||||
case 12: return _tm.tm_hour;
|
||||
case 13: return _tm.tm_wday;
|
||||
case 14: return _tm.tm_mday;
|
||||
case 15: return _tm.tm_mon;
|
||||
case 16: return _tm.tm_year >> 0;
|
||||
case 17: return _tm.tm_year >> 8;
|
||||
default: return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
void BsxStream::Serialize(Serializer& s)
|
||||
{
|
||||
s.Stream(
|
||||
_channel, _prefix, _data, _status, _prefixLatch, _dataLatch, _firstPacket, _fileOffset, _fileIndex,
|
||||
_queueLength, _prefixQueueLength, _dataQueueLength, _latchedTime, _resetTime, _customDate,
|
||||
_activeChannel, _activeFileIndex
|
||||
);
|
||||
|
||||
if(!s.IsSaving()) {
|
||||
InitTimeStruct();
|
||||
OpenStreamFile();
|
||||
|
||||
if(_file) {
|
||||
//Seek back to the previous location
|
||||
_file.seekg(_fileOffset, ios::beg);
|
||||
}
|
||||
}
|
||||
}
|
57
Core/BsxStream.h
Normal file
57
Core/BsxStream.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class BsxStream : public ISerializable
|
||||
{
|
||||
private:
|
||||
ifstream _file;
|
||||
tm _tm = {};
|
||||
|
||||
uint16_t _channel = 0;
|
||||
uint8_t _prefix = 0;
|
||||
uint8_t _data = 0;
|
||||
uint8_t _status = 0;
|
||||
|
||||
bool _prefixLatch = false;
|
||||
bool _dataLatch = false;
|
||||
bool _firstPacket = false;
|
||||
uint32_t _fileOffset = 0;
|
||||
uint8_t _fileIndex = 0;
|
||||
|
||||
uint16_t _queueLength = 0;
|
||||
uint8_t _prefixQueueLength = 0;
|
||||
uint8_t _dataQueueLength = 0;
|
||||
|
||||
uint16_t _activeChannel = 0;
|
||||
uint8_t _activeFileIndex = 0;
|
||||
|
||||
int64_t _customDate = -1;
|
||||
time_t _resetTime = 0;
|
||||
time_t _latchedTime = 0;
|
||||
|
||||
void FillQueues();
|
||||
void OpenStreamFile();
|
||||
bool LoadStreamFile();
|
||||
|
||||
void InitTimeStruct();
|
||||
uint8_t GetTime();
|
||||
|
||||
public:
|
||||
BsxStream();
|
||||
void Reset(int64_t customDate);
|
||||
|
||||
uint16_t GetChannel();
|
||||
|
||||
uint8_t GetPrefixCount();
|
||||
uint8_t GetPrefix();
|
||||
uint8_t GetData();
|
||||
uint8_t GetStatus(bool reset);
|
||||
|
||||
void SetChannelLow(uint8_t value);
|
||||
void SetChannelHigh(uint8_t value);
|
||||
void SetPrefixLatch(uint8_t value);
|
||||
void SetDataLatch(uint8_t value);
|
||||
|
||||
void Serialize(Serializer& s) override;
|
||||
};
|
|
@ -51,6 +51,8 @@
|
|||
<ClInclude Include="BatteryManager.h" />
|
||||
<ClInclude Include="BsxCart.h" />
|
||||
<ClInclude Include="BsxMemoryPack.h" />
|
||||
<ClInclude Include="BsxSatellaview.h" />
|
||||
<ClInclude Include="BsxStream.h" />
|
||||
<ClInclude Include="CheatManager.h" />
|
||||
<ClInclude Include="ClientConnectionData.h" />
|
||||
<ClInclude Include="Cpu.Shared.h" />
|
||||
|
@ -227,6 +229,8 @@
|
|||
<ClCompile Include="BreakpointManager.cpp" />
|
||||
<ClCompile Include="BsxCart.cpp" />
|
||||
<ClCompile Include="BsxMemoryPack.cpp" />
|
||||
<ClCompile Include="BsxSatellaview.cpp" />
|
||||
<ClCompile Include="BsxStream.cpp" />
|
||||
<ClCompile Include="CallstackManager.cpp" />
|
||||
<ClCompile Include="CheatManager.cpp" />
|
||||
<ClCompile Include="CodeDataLogger.cpp" />
|
||||
|
|
|
@ -509,6 +509,12 @@
|
|||
<ClInclude Include="BsxMemoryPack.h">
|
||||
<Filter>SNES\Coprocessors\BSX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BsxSatellaview.h">
|
||||
<Filter>SNES\Coprocessors\BSX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BsxStream.h">
|
||||
<Filter>SNES\Coprocessors\BSX</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
@ -815,6 +821,12 @@
|
|||
<ClCompile Include="BsxMemoryPack.cpp">
|
||||
<Filter>SNES\Coprocessors\BSX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BsxSatellaview.cpp">
|
||||
<Filter>SNES\Coprocessors\BSX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BsxStream.cpp">
|
||||
<Filter>SNES\Coprocessors\BSX</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="SNES">
|
||||
|
|
|
@ -285,6 +285,8 @@ struct EmulationConfig
|
|||
uint32_t GsuClockSpeed = 100;
|
||||
|
||||
RamState RamPowerOnState = RamState::Random;
|
||||
|
||||
int64_t BsxCustomDate = -1;
|
||||
};
|
||||
|
||||
struct PreferencesConfig
|
||||
|
|
|
@ -32,6 +32,8 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \
|
|||
$(CORE_DIR)/BreakpointManager.cpp \
|
||||
$(CORE_DIR)/BsxCart.cpp \
|
||||
$(CORE_DIR)/BsxMemoryPack.cpp \
|
||||
$(CORE_DIR)/BsxSatellaview.cpp \
|
||||
$(CORE_DIR)/BsxStream.cpp \
|
||||
$(CORE_DIR)/CallstackManager.cpp \
|
||||
$(CORE_DIR)/CheatManager.cpp \
|
||||
$(CORE_DIR)/CodeDataLogger.cpp \
|
||||
|
|
|
@ -211,6 +211,7 @@ namespace Mesen.GUI.Config
|
|||
public static string WaveFolder { get { return GetFolder(DefaultWaveFolder, Config.Preferences.WaveFolder, Config.Preferences.OverrideWaveFolder); } }
|
||||
|
||||
public static string CheatFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Cheats"), null, false); } }
|
||||
public static string SatellaviewFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Satellaview"), null, false); } }
|
||||
|
||||
public static string DebuggerFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Debugger"), null, false); } }
|
||||
public static string FirmwareFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Firmware"), null, false); } }
|
||||
|
|
|
@ -26,6 +26,8 @@ namespace Mesen.GUI.Config
|
|||
[MinMax(100, 1000)] public UInt32 GsuClockSpeed = 100;
|
||||
|
||||
public RamState RamPowerOnState = RamState.Random;
|
||||
|
||||
public long BsxCustomDate = -1;
|
||||
|
||||
public void ApplyConfig()
|
||||
{
|
||||
|
|
BIN
UI/Dependencies/Satellaview/BSX0120-0.bin
Normal file
BIN
UI/Dependencies/Satellaview/BSX0120-0.bin
Normal file
Binary file not shown.
BIN
UI/Dependencies/Satellaview/BSX0121-0.bin
Normal file
BIN
UI/Dependencies/Satellaview/BSX0121-0.bin
Normal file
Binary file not shown.
BIN
UI/Dependencies/Satellaview/BSX0122-0.bin
Normal file
BIN
UI/Dependencies/Satellaview/BSX0122-0.bin
Normal file
Binary file not shown.
BIN
UI/Dependencies/Satellaview/BSX0123-0.bin
Normal file
BIN
UI/Dependencies/Satellaview/BSX0123-0.bin
Normal file
Binary file not shown.
BIN
UI/Dependencies/Satellaview/BSX0124-0.bin
Normal file
BIN
UI/Dependencies/Satellaview/BSX0124-0.bin
Normal file
Binary file not shown.
116
UI/Forms/Config/frmEmulationConfig.Designer.cs
generated
116
UI/Forms/Config/frmEmulationConfig.Designer.cs
generated
|
@ -68,6 +68,13 @@
|
|||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.nudGsuClockSpeed = new Mesen.GUI.Controls.MesenNumericUpDown();
|
||||
this.lblGsuClockSpeed = new System.Windows.Forms.Label();
|
||||
this.tpgBsx = new System.Windows.Forms.TabPage();
|
||||
this.grpBsxDateTime = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.dtpBsxCustomDate = new System.Windows.Forms.DateTimePicker();
|
||||
this.radBsxLocalTime = new System.Windows.Forms.RadioButton();
|
||||
this.radBsxCustomTime = new System.Windows.Forms.RadioButton();
|
||||
this.dtpBsxCustomTime = new System.Windows.Forms.DateTimePicker();
|
||||
this.tabMain.SuspendLayout();
|
||||
this.tpgGeneral.SuspendLayout();
|
||||
this.tableLayoutPanel4.SuspendLayout();
|
||||
|
@ -83,6 +90,9 @@
|
|||
this.grpPpuTiming.SuspendLayout();
|
||||
this.tableLayoutPanel5.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.tpgBsx.SuspendLayout();
|
||||
this.grpBsxDateTime.SuspendLayout();
|
||||
this.tableLayoutPanel6.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// baseConfigPanel
|
||||
|
@ -96,6 +106,7 @@
|
|||
this.tabMain.Controls.Add(this.tpgGeneral);
|
||||
this.tabMain.Controls.Add(this.tpgAdvanced);
|
||||
this.tabMain.Controls.Add(this.tpgOverclocking);
|
||||
this.tabMain.Controls.Add(this.tpgBsx);
|
||||
this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tabMain.Location = new System.Drawing.Point(0, 0);
|
||||
this.tabMain.Name = "tabMain";
|
||||
|
@ -709,6 +720,100 @@
|
|||
this.lblGsuClockSpeed.TabIndex = 0;
|
||||
this.lblGsuClockSpeed.Text = "Super FX clock speed (%):";
|
||||
//
|
||||
// tpgBsx
|
||||
//
|
||||
this.tpgBsx.Controls.Add(this.grpBsxDateTime);
|
||||
this.tpgBsx.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpgBsx.Name = "tpgBsx";
|
||||
this.tpgBsx.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tpgBsx.Size = new System.Drawing.Size(437, 264);
|
||||
this.tpgBsx.TabIndex = 5;
|
||||
this.tpgBsx.Text = "BS-X";
|
||||
this.tpgBsx.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// grpBsxDateTime
|
||||
//
|
||||
this.grpBsxDateTime.Controls.Add(this.tableLayoutPanel6);
|
||||
this.grpBsxDateTime.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.grpBsxDateTime.Location = new System.Drawing.Point(3, 3);
|
||||
this.grpBsxDateTime.Name = "grpBsxDateTime";
|
||||
this.grpBsxDateTime.Size = new System.Drawing.Size(431, 258);
|
||||
this.grpBsxDateTime.TabIndex = 1;
|
||||
this.grpBsxDateTime.TabStop = false;
|
||||
this.grpBsxDateTime.Text = "BS-X/Satellaview Date and Time Settings";
|
||||
//
|
||||
// tableLayoutPanel6
|
||||
//
|
||||
this.tableLayoutPanel6.ColumnCount = 3;
|
||||
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel6.Controls.Add(this.dtpBsxCustomDate, 1, 1);
|
||||
this.tableLayoutPanel6.Controls.Add(this.radBsxLocalTime, 0, 0);
|
||||
this.tableLayoutPanel6.Controls.Add(this.radBsxCustomTime, 0, 1);
|
||||
this.tableLayoutPanel6.Controls.Add(this.dtpBsxCustomTime, 2, 1);
|
||||
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel6.Location = new System.Drawing.Point(3, 16);
|
||||
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
|
||||
this.tableLayoutPanel6.RowCount = 3;
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel6.Size = new System.Drawing.Size(425, 239);
|
||||
this.tableLayoutPanel6.TabIndex = 0;
|
||||
//
|
||||
// dtpBsxCustomDate
|
||||
//
|
||||
this.dtpBsxCustomDate.CustomFormat = "";
|
||||
this.dtpBsxCustomDate.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.dtpBsxCustomDate.Format = System.Windows.Forms.DateTimePickerFormat.Short;
|
||||
this.dtpBsxCustomDate.Location = new System.Drawing.Point(160, 26);
|
||||
this.dtpBsxCustomDate.MaxDate = new System.DateTime(2100, 12, 31, 0, 0, 0, 0);
|
||||
this.dtpBsxCustomDate.MinDate = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||
this.dtpBsxCustomDate.Name = "dtpBsxCustomDate";
|
||||
this.dtpBsxCustomDate.Size = new System.Drawing.Size(128, 20);
|
||||
this.dtpBsxCustomDate.TabIndex = 3;
|
||||
this.dtpBsxCustomDate.Value = new System.DateTime(2020, 1, 1, 0, 0, 0, 0);
|
||||
this.dtpBsxCustomDate.Enter += new System.EventHandler(this.dtpBsxCustomDate_Enter);
|
||||
//
|
||||
// radBsxLocalTime
|
||||
//
|
||||
this.radBsxLocalTime.AutoSize = true;
|
||||
this.radBsxLocalTime.Location = new System.Drawing.Point(3, 3);
|
||||
this.radBsxLocalTime.Name = "radBsxLocalTime";
|
||||
this.radBsxLocalTime.Size = new System.Drawing.Size(127, 17);
|
||||
this.radBsxLocalTime.TabIndex = 0;
|
||||
this.radBsxLocalTime.TabStop = true;
|
||||
this.radBsxLocalTime.Text = "Use current local time";
|
||||
this.radBsxLocalTime.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// radBsxCustomTime
|
||||
//
|
||||
this.radBsxCustomTime.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.radBsxCustomTime.AutoSize = true;
|
||||
this.radBsxCustomTime.Location = new System.Drawing.Point(3, 27);
|
||||
this.radBsxCustomTime.Name = "radBsxCustomTime";
|
||||
this.radBsxCustomTime.Size = new System.Drawing.Size(151, 17);
|
||||
this.radBsxCustomTime.TabIndex = 1;
|
||||
this.radBsxCustomTime.TabStop = true;
|
||||
this.radBsxCustomTime.Text = "Use custom date and time:";
|
||||
this.radBsxCustomTime.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// dtpBsxCustomTime
|
||||
//
|
||||
this.dtpBsxCustomTime.CustomFormat = "";
|
||||
this.dtpBsxCustomTime.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.dtpBsxCustomTime.Format = System.Windows.Forms.DateTimePickerFormat.Time;
|
||||
this.dtpBsxCustomTime.Location = new System.Drawing.Point(294, 26);
|
||||
this.dtpBsxCustomTime.MaxDate = new System.DateTime(2000, 1, 2, 0, 0, 0, 0);
|
||||
this.dtpBsxCustomTime.MinDate = new System.DateTime(2000, 1, 1, 0, 0, 0, 0);
|
||||
this.dtpBsxCustomTime.Name = "dtpBsxCustomTime";
|
||||
this.dtpBsxCustomTime.ShowUpDown = true;
|
||||
this.dtpBsxCustomTime.Size = new System.Drawing.Size(128, 20);
|
||||
this.dtpBsxCustomTime.TabIndex = 2;
|
||||
this.dtpBsxCustomTime.Value = new System.DateTime(2000, 1, 1, 0, 0, 0, 0);
|
||||
this.dtpBsxCustomTime.Enter += new System.EventHandler(this.dtpBsxCustomTime_Enter);
|
||||
//
|
||||
// frmEmulationConfig
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
|
@ -748,6 +853,10 @@
|
|||
this.tableLayoutPanel5.PerformLayout();
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.tpgBsx.ResumeLayout(false);
|
||||
this.grpBsxDateTime.ResumeLayout(false);
|
||||
this.tableLayoutPanel6.ResumeLayout(false);
|
||||
this.tableLayoutPanel6.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
|
@ -795,5 +904,12 @@
|
|||
private Controls.MesenNumericUpDown nudRunAheadFrames;
|
||||
private System.Windows.Forms.Label lblRunAheadFrames;
|
||||
private System.Windows.Forms.Label lblRunAhead;
|
||||
private System.Windows.Forms.TabPage tpgBsx;
|
||||
private System.Windows.Forms.GroupBox grpBsxDateTime;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6;
|
||||
private System.Windows.Forms.RadioButton radBsxLocalTime;
|
||||
private System.Windows.Forms.RadioButton radBsxCustomTime;
|
||||
private System.Windows.Forms.DateTimePicker dtpBsxCustomTime;
|
||||
private System.Windows.Forms.DateTimePicker dtpBsxCustomDate;
|
||||
}
|
||||
}
|
|
@ -13,6 +13,8 @@ namespace Mesen.GUI.Forms.Config
|
|||
{
|
||||
public partial class frmEmulationConfig : BaseConfigForm
|
||||
{
|
||||
private DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
public frmEmulationConfig()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
@ -35,10 +37,34 @@ namespace Mesen.GUI.Forms.Config
|
|||
AddBinding(nameof(EmulationConfig.PpuExtraScanlinesBeforeNmi), nudExtraScanlinesBeforeNmi);
|
||||
AddBinding(nameof(EmulationConfig.PpuExtraScanlinesAfterNmi), nudExtraScanlinesAfterNmi);
|
||||
AddBinding(nameof(EmulationConfig.GsuClockSpeed), nudGsuClockSpeed);
|
||||
|
||||
long customDate = ConfigManager.Config.Emulation.BsxCustomDate;
|
||||
if(customDate >= 0) {
|
||||
DateTime stamp;
|
||||
try {
|
||||
stamp = _unixEpoch.AddSeconds(customDate).ToLocalTime();
|
||||
} catch {
|
||||
stamp = DateTime.Now;
|
||||
}
|
||||
radBsxCustomTime.Checked = true;
|
||||
dtpBsxCustomDate.Value = stamp.Date;
|
||||
dtpBsxCustomTime.Value = new DateTime(2000, 01, 01) + stamp.TimeOfDay;
|
||||
} else {
|
||||
radBsxLocalTime.Checked = true;
|
||||
dtpBsxCustomDate.Value = DateTime.Now.Date;
|
||||
dtpBsxCustomTime.Value = new DateTime(2000, 01, 01) + DateTime.Now.TimeOfDay;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApply()
|
||||
{
|
||||
if(radBsxCustomTime.Checked) {
|
||||
DateTime dateTime = dtpBsxCustomDate.Value + dtpBsxCustomTime.Value.TimeOfDay;
|
||||
((EmulationConfig)this.Entity).BsxCustomDate = (long)dateTime.Subtract(_unixEpoch.ToLocalTime()).TotalSeconds;
|
||||
} else {
|
||||
((EmulationConfig)this.Entity).BsxCustomDate = -1;
|
||||
}
|
||||
|
||||
ConfigManager.Config.Emulation = (EmulationConfig)this.Entity;
|
||||
ConfigManager.ApplyChanges();
|
||||
}
|
||||
|
@ -47,5 +73,15 @@ namespace Mesen.GUI.Forms.Config
|
|||
{
|
||||
nudGsuClockSpeed.Value = Math.Ceiling(nudGsuClockSpeed.Value / 100) * 100;
|
||||
}
|
||||
|
||||
private void dtpBsxCustomDate_Enter(object sender, EventArgs e)
|
||||
{
|
||||
radBsxCustomTime.Checked = true;
|
||||
}
|
||||
|
||||
private void dtpBsxCustomTime_Enter(object sender, EventArgs e)
|
||||
{
|
||||
radBsxCustomTime.Checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,14 @@ namespace Mesen.GUI
|
|||
}
|
||||
}
|
||||
|
||||
private static void ExtractFile(ZipArchiveEntry entry, string outputFilename)
|
||||
private static void ExtractFile(ZipArchiveEntry entry, string outputFilename, bool allowOverwrite = true)
|
||||
{
|
||||
if(File.Exists(outputFilename)) {
|
||||
if(!allowOverwrite) {
|
||||
//File already exists, and we don't want to replace it
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] zipFileData = new byte[entry.Length];
|
||||
using(Stream fileStream = entry.Open()) {
|
||||
fileStream.Read(zipFileData, 0, (int)entry.Length);
|
||||
|
@ -100,6 +105,9 @@ namespace Mesen.GUI
|
|||
} else if(entry.Name == "MesenUpdater.exe") {
|
||||
string outputFilename = Path.Combine(ConfigManager.HomeFolder, "Resources", entry.Name);
|
||||
ExtractFile(entry, outputFilename);
|
||||
} else if(entry.Name.StartsWith("BSX")) {
|
||||
string outputFilename = Path.Combine(ConfigManager.SatellaviewFolder, entry.Name);
|
||||
ExtractFile(entry, outputFilename, false);
|
||||
} else if(entry.Name == "Font.24.spritefont" || entry.Name == "Font.64.spritefont" || entry.Name == "LICENSE.txt" || entry.Name == "PixelFont.ttf") {
|
||||
string outputFilename = Path.Combine(ConfigManager.HomeFolder, "Resources", entry.Name);
|
||||
ExtractFile(entry, outputFilename);
|
||||
|
|
15
UI/UI.csproj
15
UI/UI.csproj
|
@ -969,6 +969,21 @@
|
|||
<Compile Include="Utilities\RandomGameHelper.cs" />
|
||||
<Compile Include="Utilities\RomTestHelper.cs" />
|
||||
<Compile Include="Utilities\XmlColor.cs" />
|
||||
<None Include="Dependencies\Satellaview\BSX0120-0.bin">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Dependencies\Satellaview\BSX0121-0.bin">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Dependencies\Satellaview\BSX0122-0.bin">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Dependencies\Satellaview\BSX0123-0.bin">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Dependencies\Satellaview\BSX0124-0.bin">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Resources\CloseWhite.png" />
|
||||
<None Include="Resources\GsuDebugger.png" />
|
||||
<None Include="Resources\Sa1Debugger.png" />
|
||||
|
|
Loading…
Add table
Reference in a new issue